1 | /* |
2 | * TCC - Tiny C Compiler |
3 | * |
4 | * Copyright (c) 2001-2004 Fabrice Bellard |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Lesser General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2 of the License, or (at your option) any later version. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Lesser General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Lesser General Public |
17 | * License along with this library; if not, write to the Free Software |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ |
20 | |
21 | #define USING_GLOBALS |
22 | #include "tcc.h" |
23 | |
24 | /********************************************************/ |
25 | /* global variables */ |
26 | |
27 | /* loc : local variable index |
28 | ind : output code index |
29 | rsym: return symbol |
30 | anon_sym: anonymous symbol index |
31 | */ |
32 | ST_DATA int rsym, anon_sym, ind, loc; |
33 | |
34 | ST_DATA Sym *global_stack; |
35 | ST_DATA Sym *local_stack; |
36 | ST_DATA Sym *define_stack; |
37 | ST_DATA Sym *global_label_stack; |
38 | ST_DATA Sym *local_label_stack; |
39 | |
40 | static Sym *sym_free_first; |
41 | static void **sym_pools; |
42 | static int nb_sym_pools; |
43 | |
44 | static Sym *all_cleanups, *pending_gotos; |
45 | static int local_scope; |
46 | static int in_sizeof; |
47 | static int in_generic; |
48 | static int section_sym; |
49 | |
50 | ST_DATA SValue *vtop; |
51 | static SValue _vstack[1 + VSTACK_SIZE]; |
52 | #define vstack (_vstack + 1) |
53 | |
54 | ST_DATA int const_wanted; /* true if constant wanted */ |
55 | ST_DATA int nocode_wanted; /* no code generation wanted */ |
56 | #define unevalmask 0xffff /* unevaluated subexpression */ |
57 | #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */ |
58 | #define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data output */ |
59 | |
60 | /* Automagical code suppression ----> */ |
61 | #define CODE_OFF() (nocode_wanted |= 0x20000000) |
62 | #define CODE_ON() (nocode_wanted &= ~0x20000000) |
63 | |
64 | /* Clear 'nocode_wanted' at label if it was used */ |
65 | ST_FUNC void gsym(int t) { if (t) { gsym_addr(t, ind); CODE_ON(); }} |
66 | static int gind(void) { CODE_ON(); return ind; } |
67 | |
68 | /* Set 'nocode_wanted' after unconditional jumps */ |
69 | static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); } |
70 | static int gjmp_acs(int t) { t = gjmp(t); CODE_OFF(); return t; } |
71 | |
72 | /* These are #undef'd at the end of this file */ |
73 | #define gjmp_addr gjmp_addr_acs |
74 | #define gjmp gjmp_acs |
75 | /* <---- */ |
76 | |
77 | ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ |
78 | ST_DATA CType func_vt; /* current function return type (used by return instruction) */ |
79 | ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */ |
80 | ST_DATA int func_vc; |
81 | static int last_line_num, new_file, func_ind; /* debug info control */ |
82 | ST_DATA const char *funcname; |
83 | ST_DATA CType int_type, func_old_type, char_type, char_pointer_type; |
84 | static CString initstr; |
85 | |
86 | #if PTR_SIZE == 4 |
87 | #define VT_SIZE_T (VT_INT | VT_UNSIGNED) |
88 | #define VT_PTRDIFF_T VT_INT |
89 | #elif LONG_SIZE == 4 |
90 | #define VT_SIZE_T (VT_LLONG | VT_UNSIGNED) |
91 | #define VT_PTRDIFF_T VT_LLONG |
92 | #else |
93 | #define VT_SIZE_T (VT_LONG | VT_LLONG | VT_UNSIGNED) |
94 | #define VT_PTRDIFF_T (VT_LONG | VT_LLONG) |
95 | #endif |
96 | |
97 | ST_DATA struct switch_t { |
98 | struct case_t { |
99 | int64_t v1, v2; |
100 | int sym; |
101 | } **p; int n; /* list of case ranges */ |
102 | int def_sym; /* default symbol */ |
103 | int *bsym; |
104 | struct scope *scope; |
105 | struct switch_t *prev; |
106 | SValue sv; |
107 | } *cur_switch; /* current switch */ |
108 | |
109 | #define MAX_TEMP_LOCAL_VARIABLE_NUMBER 8 |
110 | /*list of temporary local variables on the stack in current function. */ |
111 | ST_DATA struct temp_local_variable { |
112 | int location; //offset on stack. Svalue.c.i |
113 | short size; |
114 | short align; |
115 | } arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER]; |
116 | short nb_temp_local_vars; |
117 | |
118 | static struct scope { |
119 | struct scope *prev; |
120 | struct { int loc, num; } vla; |
121 | struct { Sym *s; int n; } cl; |
122 | int *bsym, *csym; |
123 | Sym *lstk, *llstk; |
124 | } *cur_scope, *loop_scope, *root_scope; |
125 | |
126 | typedef struct { |
127 | Section *sec; |
128 | int local_offset; |
129 | Sym *flex_array_ref; |
130 | } init_params; |
131 | |
132 | /********************************************************/ |
133 | /* stab debug support */ |
134 | |
135 | static const struct { |
136 | int type; |
137 | const char *name; |
138 | } default_debug[] = { |
139 | { VT_INT, "int:t1=r1;-2147483648;2147483647;" }, |
140 | { VT_BYTE, "char:t2=r2;0;127;" }, |
141 | #if LONG_SIZE == 4 |
142 | { VT_LONG | VT_INT, "long int:t3=r3;-2147483648;2147483647;" }, |
143 | #else |
144 | { VT_LLONG | VT_LONG, "long int:t3=r3;-9223372036854775808;9223372036854775807;" }, |
145 | #endif |
146 | { VT_INT | VT_UNSIGNED, "unsigned int:t4=r4;0;037777777777;" }, |
147 | #if LONG_SIZE == 4 |
148 | { VT_LONG | VT_INT | VT_UNSIGNED, "long unsigned int:t5=r5;0;037777777777;" }, |
149 | #else |
150 | /* use octal instead of -1 so size_t works (-gstabs+ in gcc) */ |
151 | { VT_LLONG | VT_LONG | VT_UNSIGNED, "long unsigned int:t5=r5;0;01777777777777777777777;" }, |
152 | #endif |
153 | { VT_QLONG, "__int128:t6=r6;0;-1;" }, |
154 | { VT_QLONG | VT_UNSIGNED, "__int128 unsigned:t7=r7;0;-1;" }, |
155 | { VT_LLONG, "long long int:t8=r8;-9223372036854775808;9223372036854775807;" }, |
156 | { VT_LLONG | VT_UNSIGNED, "long long unsigned int:t9=r9;0;01777777777777777777777;" }, |
157 | { VT_SHORT, "short int:t10=r10;-32768;32767;" }, |
158 | { VT_SHORT | VT_UNSIGNED, "short unsigned int:t11=r11;0;65535;" }, |
159 | { VT_BYTE | VT_DEFSIGN, "signed char:t12=r12;-128;127;" }, |
160 | { VT_BYTE | VT_DEFSIGN | VT_UNSIGNED, "unsigned char:t13=r13;0;255;" }, |
161 | { VT_FLOAT, "float:t14=r1;4;0;" }, |
162 | { VT_DOUBLE, "double:t15=r1;8;0;" }, |
163 | { VT_LDOUBLE, "long double:t16=r1;16;0;" }, |
164 | { -1, "_Float32:t17=r1;4;0;" }, |
165 | { -1, "_Float64:t18=r1;8;0;" }, |
166 | { -1, "_Float128:t19=r1;16;0;" }, |
167 | { -1, "_Float32x:t20=r1;8;0;" }, |
168 | { -1, "_Float64x:t21=r1;16;0;" }, |
169 | { -1, "_Decimal32:t22=r1;4;0;" }, |
170 | { -1, "_Decimal64:t23=r1;8;0;" }, |
171 | { -1, "_Decimal128:t24=r1;16;0;" }, |
172 | /* if default char is unsigned */ |
173 | { VT_BYTE | VT_UNSIGNED, "unsigned char:t25=r25;0;255;" }, |
174 | /* boolean type */ |
175 | { VT_BOOL, "bool:t26=r26;0;255;" }, |
176 | { VT_VOID, "void:t27=27" }, |
177 | }; |
178 | |
179 | static int debug_next_type; |
180 | |
181 | static struct debug_hash { |
182 | int debug_type; |
183 | Sym *type; |
184 | } *debug_hash; |
185 | |
186 | static int n_debug_hash; |
187 | |
188 | static struct debug_info { |
189 | int start; |
190 | int end; |
191 | int n_sym; |
192 | struct debug_sym { |
193 | int type; |
194 | unsigned long value; |
195 | char *str; |
196 | Section *sec; |
197 | int sym_index; |
198 | } *sym; |
199 | struct debug_info *child, *next, *last, *parent; |
200 | } *debug_info, *debug_info_root; |
201 | |
202 | /********************************************************/ |
203 | #if 1 |
204 | #define precedence_parser |
205 | static void init_prec(void); |
206 | #endif |
207 | /********************************************************/ |
208 | #ifndef CONFIG_TCC_ASM |
209 | ST_FUNC void asm_instr(void) |
210 | { |
211 | tcc_error("inline asm() not supported" ); |
212 | } |
213 | ST_FUNC void asm_global_instr(void) |
214 | { |
215 | tcc_error("inline asm() not supported" ); |
216 | } |
217 | #endif |
218 | |
219 | /* ------------------------------------------------------------------------- */ |
220 | static void gen_cast(CType *type); |
221 | static void gen_cast_s(int t); |
222 | static inline CType *pointed_type(CType *type); |
223 | static int is_compatible_types(CType *type1, CType *type2); |
224 | static int parse_btype(CType *type, AttributeDef *ad); |
225 | static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td); |
226 | static void parse_expr_type(CType *type); |
227 | static void init_putv(init_params *p, CType *type, unsigned long c); |
228 | static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags); |
229 | static void block(int is_expr); |
230 | static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope); |
231 | static void decl(int l); |
232 | static int decl0(int l, int is_for_loop_init, Sym *); |
233 | static void expr_eq(void); |
234 | static void vla_runtime_type_size(CType *type, int *a); |
235 | static int is_compatible_unqualified_types(CType *type1, CType *type2); |
236 | static inline int64_t expr_const64(void); |
237 | static void vpush64(int ty, unsigned long long v); |
238 | static void vpush(CType *type); |
239 | static int gvtst(int inv, int t); |
240 | static void gen_inline_functions(TCCState *s); |
241 | static void free_inline_functions(TCCState *s); |
242 | static void skip_or_save_block(TokenString **str); |
243 | static void gv_dup(void); |
244 | static int get_temp_local_var(int size,int align); |
245 | static void clear_temp_local_var_list(); |
246 | static void cast_error(CType *st, CType *dt); |
247 | |
248 | ST_INLN int is_float(int t) |
249 | { |
250 | int bt = t & VT_BTYPE; |
251 | return bt == VT_LDOUBLE |
252 | || bt == VT_DOUBLE |
253 | || bt == VT_FLOAT |
254 | || bt == VT_QFLOAT; |
255 | } |
256 | |
257 | static inline int is_integer_btype(int bt) |
258 | { |
259 | return bt == VT_BYTE |
260 | || bt == VT_BOOL |
261 | || bt == VT_SHORT |
262 | || bt == VT_INT |
263 | || bt == VT_LLONG; |
264 | } |
265 | |
266 | static int btype_size(int bt) |
267 | { |
268 | return bt == VT_BYTE || bt == VT_BOOL ? 1 : |
269 | bt == VT_SHORT ? 2 : |
270 | bt == VT_INT ? 4 : |
271 | bt == VT_LLONG ? 8 : |
272 | bt == VT_PTR ? PTR_SIZE : 0; |
273 | } |
274 | |
275 | /* returns function return register from type */ |
276 | static int R_RET(int t) |
277 | { |
278 | if (!is_float(t)) |
279 | return REG_IRET; |
280 | #ifdef TCC_TARGET_X86_64 |
281 | if ((t & VT_BTYPE) == VT_LDOUBLE) |
282 | return TREG_ST0; |
283 | #elif defined TCC_TARGET_RISCV64 |
284 | if ((t & VT_BTYPE) == VT_LDOUBLE) |
285 | return REG_IRET; |
286 | #endif |
287 | return REG_FRET; |
288 | } |
289 | |
290 | /* returns 2nd function return register, if any */ |
291 | static int R2_RET(int t) |
292 | { |
293 | t &= VT_BTYPE; |
294 | #if PTR_SIZE == 4 |
295 | if (t == VT_LLONG) |
296 | return REG_IRE2; |
297 | #elif defined TCC_TARGET_X86_64 |
298 | if (t == VT_QLONG) |
299 | return REG_IRE2; |
300 | if (t == VT_QFLOAT) |
301 | return REG_FRE2; |
302 | #elif defined TCC_TARGET_RISCV64 |
303 | if (t == VT_LDOUBLE) |
304 | return REG_IRE2; |
305 | #endif |
306 | return VT_CONST; |
307 | } |
308 | |
309 | /* returns true for two-word types */ |
310 | #define USING_TWO_WORDS(t) (R2_RET(t) != VT_CONST) |
311 | |
312 | /* put function return registers to stack value */ |
313 | static void PUT_R_RET(SValue *sv, int t) |
314 | { |
315 | sv->r = R_RET(t), sv->r2 = R2_RET(t); |
316 | } |
317 | |
318 | /* returns function return register class for type t */ |
319 | static int RC_RET(int t) |
320 | { |
321 | return reg_classes[R_RET(t)] & ~(RC_FLOAT | RC_INT); |
322 | } |
323 | |
324 | /* returns generic register class for type t */ |
325 | static int RC_TYPE(int t) |
326 | { |
327 | if (!is_float(t)) |
328 | return RC_INT; |
329 | #ifdef TCC_TARGET_X86_64 |
330 | if ((t & VT_BTYPE) == VT_LDOUBLE) |
331 | return RC_ST0; |
332 | if ((t & VT_BTYPE) == VT_QFLOAT) |
333 | return RC_FRET; |
334 | #elif defined TCC_TARGET_RISCV64 |
335 | if ((t & VT_BTYPE) == VT_LDOUBLE) |
336 | return RC_INT; |
337 | #endif |
338 | return RC_FLOAT; |
339 | } |
340 | |
341 | /* returns 2nd register class corresponding to t and rc */ |
342 | static int RC2_TYPE(int t, int rc) |
343 | { |
344 | if (!USING_TWO_WORDS(t)) |
345 | return 0; |
346 | #ifdef RC_IRE2 |
347 | if (rc == RC_IRET) |
348 | return RC_IRE2; |
349 | #endif |
350 | #ifdef RC_FRE2 |
351 | if (rc == RC_FRET) |
352 | return RC_FRE2; |
353 | #endif |
354 | if (rc & RC_FLOAT) |
355 | return RC_FLOAT; |
356 | return RC_INT; |
357 | } |
358 | |
359 | /* we use our own 'finite' function to avoid potential problems with |
360 | non standard math libs */ |
361 | /* XXX: endianness dependent */ |
362 | ST_FUNC int ieee_finite(double d) |
363 | { |
364 | int p[4]; |
365 | memcpy(p, &d, sizeof(double)); |
366 | return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31; |
367 | } |
368 | |
369 | /* compiling intel long double natively */ |
370 | #if (defined __i386__ || defined __x86_64__) \ |
371 | && (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64) |
372 | # define TCC_IS_NATIVE_387 |
373 | #endif |
374 | |
375 | ST_FUNC void test_lvalue(void) |
376 | { |
377 | if (!(vtop->r & VT_LVAL)) |
378 | expect("lvalue" ); |
379 | } |
380 | |
381 | ST_FUNC void check_vstack(void) |
382 | { |
383 | if (vtop != vstack - 1) |
384 | tcc_error("internal compiler error: vstack leak (%d)" , |
385 | (int)(vtop - vstack + 1)); |
386 | } |
387 | |
388 | /* ------------------------------------------------------------------------- */ |
389 | /* vstack debugging aid */ |
390 | |
391 | #if 0 |
392 | void pv (const char *lbl, int a, int b) |
393 | { |
394 | int i; |
395 | for (i = a; i < a + b; ++i) { |
396 | SValue *p = &vtop[-i]; |
397 | printf("%s vtop[-%d] : type.t:%04x r:%04x r2:%04x c.i:%d\n" , |
398 | lbl, i, p->type.t, p->r, p->r2, (int)p->c.i); |
399 | } |
400 | } |
401 | #endif |
402 | |
403 | /* ------------------------------------------------------------------------- */ |
404 | /* start of translation unit info */ |
405 | ST_FUNC void tcc_debug_start(TCCState *s1) |
406 | { |
407 | if (s1->do_debug) { |
408 | int i; |
409 | char buf[512]; |
410 | |
411 | /* file info: full path + filename */ |
412 | section_sym = put_elf_sym(symtab_section, 0, 0, |
413 | ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0, |
414 | text_section->sh_num, NULL); |
415 | getcwd(buf, sizeof(buf)); |
416 | #ifdef _WIN32 |
417 | normalize_slashes(buf); |
418 | #endif |
419 | pstrcat(buf, sizeof(buf), "/" ); |
420 | put_stabs_r(s1, buf, N_SO, 0, 0, |
421 | text_section->data_offset, text_section, section_sym); |
422 | put_stabs_r(s1, file->prev ? file->prev->filename : file->filename, |
423 | N_SO, 0, 0, |
424 | text_section->data_offset, text_section, section_sym); |
425 | for (i = 0; i < sizeof (default_debug) / sizeof (default_debug[0]); i++) |
426 | put_stabs(s1, default_debug[i].name, N_LSYM, 0, 0, 0); |
427 | |
428 | new_file = last_line_num = 0; |
429 | func_ind = -1; |
430 | debug_next_type = sizeof(default_debug) / sizeof(default_debug[0]); |
431 | debug_hash = NULL; |
432 | n_debug_hash = 0; |
433 | |
434 | /* we're currently 'including' the <command line> */ |
435 | tcc_debug_bincl(s1); |
436 | } |
437 | |
438 | /* an elf symbol of type STT_FILE must be put so that STB_LOCAL |
439 | symbols can be safely used */ |
440 | put_elf_sym(symtab_section, 0, 0, |
441 | ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, |
442 | SHN_ABS, file->filename); |
443 | } |
444 | |
445 | static void tcc_debug_stabs (TCCState *s1, const char *str, int type, unsigned long value, |
446 | Section *sec, int sym_index) |
447 | { |
448 | struct debug_sym *s; |
449 | |
450 | if (debug_info) { |
451 | debug_info->sym = |
452 | (struct debug_sym *)tcc_realloc (debug_info->sym, |
453 | sizeof(struct debug_sym) * |
454 | (debug_info->n_sym + 1)); |
455 | s = debug_info->sym + debug_info->n_sym++; |
456 | s->type = type; |
457 | s->value = value; |
458 | s->str = tcc_strdup(str); |
459 | s->sec = sec; |
460 | s->sym_index = sym_index; |
461 | } |
462 | else if (sec) |
463 | put_stabs_r (s1, str, type, 0, 0, value, sec, sym_index); |
464 | else |
465 | put_stabs (s1, str, type, 0, 0, value); |
466 | } |
467 | |
468 | static void tcc_debug_stabn(int type, int value) |
469 | { |
470 | if (type == N_LBRAC) { |
471 | struct debug_info *info = |
472 | (struct debug_info *) tcc_mallocz(sizeof (*info)); |
473 | |
474 | info->start = value; |
475 | info->parent = debug_info; |
476 | if (debug_info) { |
477 | if (debug_info->child) { |
478 | if (debug_info->child->last) |
479 | debug_info->child->last->next = info; |
480 | else |
481 | debug_info->child->next = info; |
482 | debug_info->child->last = info; |
483 | } |
484 | else |
485 | debug_info->child = info; |
486 | } |
487 | else |
488 | debug_info_root = info; |
489 | debug_info = info; |
490 | } |
491 | else { |
492 | debug_info->end = value; |
493 | debug_info = debug_info->parent; |
494 | } |
495 | } |
496 | |
497 | static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result) |
498 | { |
499 | int type; |
500 | int n = 0; |
501 | int debug_type = -1; |
502 | Sym *t = s; |
503 | CString str; |
504 | |
505 | for (;;) { |
506 | type = t->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE); |
507 | if ((type & VT_BTYPE) != VT_BYTE) |
508 | type &= ~VT_DEFSIGN; |
509 | if (type == VT_PTR || type == (VT_PTR | VT_ARRAY)) |
510 | n++, t = t->type.ref; |
511 | else |
512 | break; |
513 | } |
514 | if ((type & VT_BTYPE) == VT_STRUCT) { |
515 | int i; |
516 | |
517 | t = t->type.ref; |
518 | for (i = 0; i < n_debug_hash; i++) { |
519 | if (t == debug_hash[i].type) { |
520 | debug_type = debug_hash[i].debug_type; |
521 | break; |
522 | } |
523 | } |
524 | if (debug_type == -1) { |
525 | debug_type = ++debug_next_type; |
526 | debug_hash = (struct debug_hash *) |
527 | tcc_realloc (debug_hash, |
528 | (n_debug_hash + 1) * sizeof(*debug_hash)); |
529 | debug_hash[n_debug_hash].debug_type = debug_type; |
530 | debug_hash[n_debug_hash++].type = t; |
531 | cstr_new (&str); |
532 | cstr_printf (&str, "%s:T%d=%c%d" , |
533 | (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM |
534 | ? "" : get_tok_str(t->v & ~SYM_STRUCT, NULL), |
535 | debug_type, |
536 | IS_UNION (t->type.t) ? 'u' : 's', |
537 | t->c); |
538 | while (t->next) { |
539 | int pos, size, align; |
540 | |
541 | t = t->next; |
542 | cstr_printf (&str, "%s:" , |
543 | (t->v & ~SYM_FIELD) >= SYM_FIRST_ANOM |
544 | ? "" : get_tok_str(t->v & ~SYM_FIELD, NULL)); |
545 | tcc_get_debug_info (s1, t, &str); |
546 | if (t->type.t & VT_BITFIELD) { |
547 | pos = t->c * 8 + BIT_POS(t->type.t); |
548 | size = BIT_SIZE(t->type.t); |
549 | } |
550 | else { |
551 | pos = t->c * 8; |
552 | size = type_size(&t->type, &align) * 8; |
553 | } |
554 | cstr_printf (&str, ",%d,%d;" , pos, size); |
555 | } |
556 | cstr_printf (&str, ";" ); |
557 | tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0); |
558 | cstr_free (&str); |
559 | } |
560 | } |
561 | else if (IS_ENUM(type)) { |
562 | Sym *e = t = t->type.ref; |
563 | |
564 | debug_type = ++debug_next_type; |
565 | cstr_new (&str); |
566 | cstr_printf (&str, "%s:T%d=e" , |
567 | (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM |
568 | ? "" : get_tok_str(t->v & ~SYM_STRUCT, NULL), |
569 | debug_type); |
570 | while (t->next) { |
571 | t = t->next; |
572 | cstr_printf (&str, "%s:" , |
573 | (t->v & ~SYM_FIELD) >= SYM_FIRST_ANOM |
574 | ? "" : get_tok_str(t->v & ~SYM_FIELD, NULL)); |
575 | cstr_printf (&str, e->type.t & VT_UNSIGNED ? "%u," : "%d," , |
576 | (int)t->enum_val); |
577 | } |
578 | cstr_printf (&str, ";" ); |
579 | tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0); |
580 | cstr_free (&str); |
581 | } |
582 | else if ((type & VT_BTYPE) != VT_FUNC) { |
583 | type &= ~VT_STRUCT_MASK; |
584 | for (debug_type = 1; |
585 | debug_type <= sizeof(default_debug) / sizeof(default_debug[0]); |
586 | debug_type++) |
587 | if (default_debug[debug_type - 1].type == type) |
588 | break; |
589 | if (debug_type > sizeof(default_debug) / sizeof(default_debug[0])) |
590 | return; |
591 | } |
592 | if (n > 0) |
593 | cstr_printf (result, "%d=" , ++debug_next_type); |
594 | t = s; |
595 | for (;;) { |
596 | type = t->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE); |
597 | if ((type & VT_BTYPE) != VT_BYTE) |
598 | type &= ~VT_DEFSIGN; |
599 | if (type == VT_PTR) |
600 | cstr_printf (result, "%d=*" , ++debug_next_type); |
601 | else if (type == (VT_PTR | VT_ARRAY)) |
602 | cstr_printf (result, "%d=ar1;0;%d;" , |
603 | ++debug_next_type, t->type.ref->c - 1); |
604 | else if (type == VT_FUNC) { |
605 | cstr_printf (result, "%d=f" , ++debug_next_type); |
606 | tcc_get_debug_info (s1, t->type.ref, result); |
607 | return; |
608 | } |
609 | else |
610 | break; |
611 | t = t->type.ref; |
612 | } |
613 | cstr_printf (result, "%d" , debug_type); |
614 | } |
615 | |
616 | static void tcc_debug_finish (TCCState *s1, struct debug_info *cur) |
617 | { |
618 | while (cur) { |
619 | int i; |
620 | struct debug_info *next = cur->next; |
621 | |
622 | for (i = 0; i < cur->n_sym; i++) { |
623 | struct debug_sym *s = &cur->sym[i]; |
624 | |
625 | if (s->sec) |
626 | put_stabs_r(s1, s->str, s->type, 0, 0, s->value, |
627 | s->sec, s->sym_index); |
628 | else |
629 | put_stabs(s1, s->str, s->type, 0, 0, s->value); |
630 | tcc_free (s->str); |
631 | } |
632 | tcc_free (cur->sym); |
633 | put_stabn(s1, N_LBRAC, 0, 0, cur->start); |
634 | tcc_debug_finish (s1, cur->child); |
635 | put_stabn(s1, N_RBRAC, 0, 0, cur->end); |
636 | tcc_free (cur); |
637 | cur = next; |
638 | } |
639 | } |
640 | |
641 | static void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e) |
642 | { |
643 | CString debug_str; |
644 | cstr_new (&debug_str); |
645 | for (; s != e; s = s->prev) { |
646 | if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL) |
647 | continue; |
648 | cstr_reset (&debug_str); |
649 | cstr_printf (&debug_str, "%s:%s" , get_tok_str(s->v, NULL), param ? "p" : "" ); |
650 | tcc_get_debug_info(s1, s, &debug_str); |
651 | tcc_debug_stabs(s1, debug_str.data, param ? N_PSYM : N_LSYM, s->c, NULL, 0); |
652 | } |
653 | cstr_free (&debug_str); |
654 | } |
655 | |
656 | static void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bind) |
657 | { |
658 | Section *s = s1->sections[sh_num]; |
659 | CString str; |
660 | |
661 | cstr_new (&str); |
662 | cstr_printf (&str, "%s:%c" , |
663 | get_tok_str(sym->v, NULL), |
664 | sym_bind == STB_GLOBAL ? 'G' : local_scope ? 'V' : 'S' |
665 | ); |
666 | tcc_get_debug_info(s1, sym, &str); |
667 | if (sym_bind == STB_GLOBAL) |
668 | tcc_debug_stabs(s1, str.data, N_GSYM, 0, NULL, 0); |
669 | else |
670 | tcc_debug_stabs(s1, str.data, |
671 | (sym->type.t & VT_STATIC) && data_section == s |
672 | ? N_STSYM : N_LCSYM, 0, s, sym->c); |
673 | cstr_free (&str); |
674 | } |
675 | |
676 | static void tcc_debug_typedef(TCCState *s1, Sym *sym) |
677 | { |
678 | CString str; |
679 | |
680 | cstr_new (&str); |
681 | cstr_printf (&str, "%s:t" , |
682 | (sym->v & ~SYM_FIELD) >= SYM_FIRST_ANOM |
683 | ? "" : get_tok_str(sym->v & ~SYM_FIELD, NULL)); |
684 | tcc_get_debug_info(s1, sym, &str); |
685 | tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0); |
686 | cstr_free (&str); |
687 | } |
688 | |
689 | /* put end of translation unit info */ |
690 | ST_FUNC void tcc_debug_end(TCCState *s1) |
691 | { |
692 | if (!s1->do_debug) |
693 | return; |
694 | put_stabs_r(s1, NULL, N_SO, 0, 0, |
695 | text_section->data_offset, text_section, section_sym); |
696 | tcc_free(debug_hash); |
697 | } |
698 | |
699 | static BufferedFile* put_new_file(TCCState *s1) |
700 | { |
701 | BufferedFile *f = file; |
702 | /* use upper file if from inline ":asm:" */ |
703 | if (f->filename[0] == ':') |
704 | f = f->prev; |
705 | if (f && new_file) { |
706 | put_stabs_r(s1, f->filename, N_SOL, 0, 0, ind, text_section, section_sym); |
707 | new_file = last_line_num = 0; |
708 | } |
709 | return f; |
710 | } |
711 | |
712 | /* generate line number info */ |
713 | ST_FUNC void tcc_debug_line(TCCState *s1) |
714 | { |
715 | BufferedFile *f; |
716 | if (!s1->do_debug |
717 | || cur_text_section != text_section |
718 | || !(f = put_new_file(s1)) |
719 | || last_line_num == f->line_num) |
720 | return; |
721 | if (func_ind != -1) { |
722 | put_stabn(s1, N_SLINE, 0, f->line_num, ind - func_ind); |
723 | } else { |
724 | /* from tcc_assemble */ |
725 | put_stabs_r(s1, NULL, N_SLINE, 0, f->line_num, ind, text_section, section_sym); |
726 | } |
727 | last_line_num = f->line_num; |
728 | } |
729 | |
730 | /* put function symbol */ |
731 | ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym) |
732 | { |
733 | CString debug_str; |
734 | BufferedFile *f; |
735 | if (!s1->do_debug) |
736 | return; |
737 | debug_info_root = NULL; |
738 | debug_info = NULL; |
739 | tcc_debug_stabn(N_LBRAC, ind - func_ind); |
740 | if (!(f = put_new_file(s1))) |
741 | return; |
742 | cstr_new (&debug_str); |
743 | cstr_printf(&debug_str, "%s:%c" , funcname, sym->type.t & VT_STATIC ? 'f' : 'F'); |
744 | tcc_get_debug_info(s1, sym->type.ref, &debug_str); |
745 | put_stabs_r(s1, debug_str.data, N_FUN, 0, f->line_num, 0, cur_text_section, sym->c); |
746 | cstr_free (&debug_str); |
747 | |
748 | tcc_debug_line(s1); |
749 | } |
750 | |
751 | /* put function size */ |
752 | ST_FUNC void tcc_debug_funcend(TCCState *s1, int size) |
753 | { |
754 | if (!s1->do_debug) |
755 | return; |
756 | tcc_debug_stabn(N_RBRAC, size); |
757 | tcc_debug_finish (s1, debug_info_root); |
758 | } |
759 | |
760 | /* put alternative filename */ |
761 | ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename) |
762 | { |
763 | if (0 == strcmp(file->filename, filename)) |
764 | return; |
765 | pstrcpy(file->filename, sizeof(file->filename), filename); |
766 | new_file = 1; |
767 | } |
768 | |
769 | /* begin of #include */ |
770 | ST_FUNC void tcc_debug_bincl(TCCState *s1) |
771 | { |
772 | if (!s1->do_debug) |
773 | return; |
774 | put_stabs(s1, file->filename, N_BINCL, 0, 0, 0); |
775 | new_file = 1; |
776 | } |
777 | |
778 | /* end of #include */ |
779 | ST_FUNC void tcc_debug_eincl(TCCState *s1) |
780 | { |
781 | if (!s1->do_debug) |
782 | return; |
783 | put_stabn(s1, N_EINCL, 0, 0, 0); |
784 | new_file = 1; |
785 | } |
786 | |
787 | /* ------------------------------------------------------------------------- */ |
788 | /* initialize vstack and types. This must be done also for tcc -E */ |
789 | ST_FUNC void tccgen_init(TCCState *s1) |
790 | { |
791 | vtop = vstack - 1; |
792 | memset(vtop, 0, sizeof *vtop); |
793 | |
794 | /* define some often used types */ |
795 | int_type.t = VT_INT; |
796 | |
797 | char_type.t = VT_BYTE; |
798 | if (s1->char_is_unsigned) |
799 | char_type.t |= VT_UNSIGNED; |
800 | char_pointer_type = char_type; |
801 | mk_pointer(&char_pointer_type); |
802 | |
803 | func_old_type.t = VT_FUNC; |
804 | func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0); |
805 | func_old_type.ref->f.func_call = FUNC_CDECL; |
806 | func_old_type.ref->f.func_type = FUNC_OLD; |
807 | #ifdef precedence_parser |
808 | init_prec(); |
809 | #endif |
810 | cstr_new(&initstr); |
811 | } |
812 | |
813 | ST_FUNC int tccgen_compile(TCCState *s1) |
814 | { |
815 | cur_text_section = NULL; |
816 | funcname = "" ; |
817 | anon_sym = SYM_FIRST_ANOM; |
818 | section_sym = 0; |
819 | const_wanted = 0; |
820 | nocode_wanted = 0x80000000; |
821 | local_scope = 0; |
822 | |
823 | tcc_debug_start(s1); |
824 | #ifdef TCC_TARGET_ARM |
825 | arm_init(s1); |
826 | #endif |
827 | #ifdef INC_DEBUG |
828 | printf("%s: **** new file\n" , file->filename); |
829 | #endif |
830 | parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_TOK_STR; |
831 | next(); |
832 | decl(VT_CONST); |
833 | gen_inline_functions(s1); |
834 | check_vstack(); |
835 | /* end of translation unit info */ |
836 | tcc_debug_end(s1); |
837 | return 0; |
838 | } |
839 | |
840 | ST_FUNC void tccgen_finish(TCCState *s1) |
841 | { |
842 | cstr_free(&initstr); |
843 | free_inline_functions(s1); |
844 | sym_pop(&global_stack, NULL, 0); |
845 | sym_pop(&local_stack, NULL, 0); |
846 | /* free preprocessor macros */ |
847 | free_defines(NULL); |
848 | /* free sym_pools */ |
849 | dynarray_reset(&sym_pools, &nb_sym_pools); |
850 | sym_free_first = NULL; |
851 | } |
852 | |
853 | /* ------------------------------------------------------------------------- */ |
854 | ST_FUNC ElfSym *elfsym(Sym *s) |
855 | { |
856 | if (!s || !s->c) |
857 | return NULL; |
858 | return &((ElfSym *)symtab_section->data)[s->c]; |
859 | } |
860 | |
861 | /* apply storage attributes to Elf symbol */ |
862 | ST_FUNC void update_storage(Sym *sym) |
863 | { |
864 | ElfSym *esym; |
865 | int sym_bind, old_sym_bind; |
866 | |
867 | esym = elfsym(sym); |
868 | if (!esym) |
869 | return; |
870 | |
871 | if (sym->a.visibility) |
872 | esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1)) |
873 | | sym->a.visibility; |
874 | |
875 | if (sym->type.t & (VT_STATIC | VT_INLINE)) |
876 | sym_bind = STB_LOCAL; |
877 | else if (sym->a.weak) |
878 | sym_bind = STB_WEAK; |
879 | else |
880 | sym_bind = STB_GLOBAL; |
881 | old_sym_bind = ELFW(ST_BIND)(esym->st_info); |
882 | if (sym_bind != old_sym_bind) { |
883 | esym->st_info = ELFW(ST_INFO)(sym_bind, ELFW(ST_TYPE)(esym->st_info)); |
884 | } |
885 | |
886 | #ifdef TCC_TARGET_PE |
887 | if (sym->a.dllimport) |
888 | esym->st_other |= ST_PE_IMPORT; |
889 | if (sym->a.dllexport) |
890 | esym->st_other |= ST_PE_EXPORT; |
891 | #endif |
892 | |
893 | #if 0 |
894 | printf("storage %s: bind=%c vis=%d exp=%d imp=%d\n" , |
895 | get_tok_str(sym->v, NULL), |
896 | sym_bind == STB_WEAK ? 'w' : sym_bind == STB_LOCAL ? 'l' : 'g', |
897 | sym->a.visibility, |
898 | sym->a.dllexport, |
899 | sym->a.dllimport |
900 | ); |
901 | #endif |
902 | } |
903 | |
904 | /* ------------------------------------------------------------------------- */ |
905 | /* update sym->c so that it points to an external symbol in section |
906 | 'section' with value 'value' */ |
907 | |
908 | ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, |
909 | addr_t value, unsigned long size, |
910 | int can_add_underscore) |
911 | { |
912 | int sym_type, sym_bind, info, other, t; |
913 | ElfSym *esym; |
914 | const char *name; |
915 | char buf1[256]; |
916 | |
917 | if (!sym->c) { |
918 | name = get_tok_str(sym->v, NULL); |
919 | t = sym->type.t; |
920 | if ((t & VT_BTYPE) == VT_FUNC) { |
921 | sym_type = STT_FUNC; |
922 | } else if ((t & VT_BTYPE) == VT_VOID) { |
923 | sym_type = STT_NOTYPE; |
924 | } else { |
925 | sym_type = STT_OBJECT; |
926 | } |
927 | if (t & (VT_STATIC | VT_INLINE)) |
928 | sym_bind = STB_LOCAL; |
929 | else |
930 | sym_bind = STB_GLOBAL; |
931 | other = 0; |
932 | |
933 | #ifdef TCC_TARGET_PE |
934 | if (sym_type == STT_FUNC && sym->type.ref) { |
935 | Sym *ref = sym->type.ref; |
936 | if (ref->a.nodecorate) { |
937 | can_add_underscore = 0; |
938 | } |
939 | if (ref->f.func_call == FUNC_STDCALL && can_add_underscore) { |
940 | sprintf(buf1, "_%s@%d" , name, ref->f.func_args * PTR_SIZE); |
941 | name = buf1; |
942 | other |= ST_PE_STDCALL; |
943 | can_add_underscore = 0; |
944 | } |
945 | } |
946 | #endif |
947 | |
948 | if (sym->asm_label) { |
949 | name = get_tok_str(sym->asm_label, NULL); |
950 | can_add_underscore = 0; |
951 | } |
952 | |
953 | if (tcc_state->leading_underscore && can_add_underscore) { |
954 | buf1[0] = '_'; |
955 | pstrcpy(buf1 + 1, sizeof(buf1) - 1, name); |
956 | name = buf1; |
957 | } |
958 | |
959 | info = ELFW(ST_INFO)(sym_bind, sym_type); |
960 | sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name); |
961 | |
962 | if (tcc_state->do_debug |
963 | && sym_type != STT_FUNC |
964 | && sym->v < SYM_FIRST_ANOM) |
965 | tcc_debug_extern_sym(tcc_state, sym, sh_num, sym_bind); |
966 | |
967 | } else { |
968 | esym = elfsym(sym); |
969 | esym->st_value = value; |
970 | esym->st_size = size; |
971 | esym->st_shndx = sh_num; |
972 | } |
973 | update_storage(sym); |
974 | } |
975 | |
976 | ST_FUNC void put_extern_sym(Sym *sym, Section *section, |
977 | addr_t value, unsigned long size) |
978 | { |
979 | int sh_num = section ? section->sh_num : SHN_UNDEF; |
980 | put_extern_sym2(sym, sh_num, value, size, 1); |
981 | } |
982 | |
983 | /* add a new relocation entry to symbol 'sym' in section 's' */ |
984 | ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, |
985 | addr_t addend) |
986 | { |
987 | int c = 0; |
988 | |
989 | if (nocode_wanted && s == cur_text_section) |
990 | return; |
991 | |
992 | if (sym) { |
993 | if (0 == sym->c) |
994 | put_extern_sym(sym, NULL, 0, 0); |
995 | c = sym->c; |
996 | } |
997 | |
998 | /* now we can add ELF relocation info */ |
999 | put_elf_reloca(symtab_section, s, offset, type, c, addend); |
1000 | } |
1001 | |
1002 | #if PTR_SIZE == 4 |
1003 | ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type) |
1004 | { |
1005 | greloca(s, sym, offset, type, 0); |
1006 | } |
1007 | #endif |
1008 | |
1009 | /* ------------------------------------------------------------------------- */ |
1010 | /* symbol allocator */ |
1011 | static Sym *__sym_malloc(void) |
1012 | { |
1013 | Sym *sym_pool, *sym, *last_sym; |
1014 | int i; |
1015 | |
1016 | sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym)); |
1017 | dynarray_add(&sym_pools, &nb_sym_pools, sym_pool); |
1018 | |
1019 | last_sym = sym_free_first; |
1020 | sym = sym_pool; |
1021 | for(i = 0; i < SYM_POOL_NB; i++) { |
1022 | sym->next = last_sym; |
1023 | last_sym = sym; |
1024 | sym++; |
1025 | } |
1026 | sym_free_first = last_sym; |
1027 | return last_sym; |
1028 | } |
1029 | |
1030 | static inline Sym *sym_malloc(void) |
1031 | { |
1032 | Sym *sym; |
1033 | #ifndef SYM_DEBUG |
1034 | sym = sym_free_first; |
1035 | if (!sym) |
1036 | sym = __sym_malloc(); |
1037 | sym_free_first = sym->next; |
1038 | return sym; |
1039 | #else |
1040 | sym = tcc_malloc(sizeof(Sym)); |
1041 | return sym; |
1042 | #endif |
1043 | } |
1044 | |
1045 | ST_INLN void sym_free(Sym *sym) |
1046 | { |
1047 | #ifndef SYM_DEBUG |
1048 | sym->next = sym_free_first; |
1049 | sym_free_first = sym; |
1050 | #else |
1051 | tcc_free(sym); |
1052 | #endif |
1053 | } |
1054 | |
1055 | /* push, without hashing */ |
1056 | ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c) |
1057 | { |
1058 | Sym *s; |
1059 | |
1060 | s = sym_malloc(); |
1061 | memset(s, 0, sizeof *s); |
1062 | s->v = v; |
1063 | s->type.t = t; |
1064 | s->c = c; |
1065 | /* add in stack */ |
1066 | s->prev = *ps; |
1067 | *ps = s; |
1068 | return s; |
1069 | } |
1070 | |
1071 | /* find a symbol and return its associated structure. 's' is the top |
1072 | of the symbol stack */ |
1073 | ST_FUNC Sym *sym_find2(Sym *s, int v) |
1074 | { |
1075 | while (s) { |
1076 | if (s->v == v) |
1077 | return s; |
1078 | else if (s->v == -1) |
1079 | return NULL; |
1080 | s = s->prev; |
1081 | } |
1082 | return NULL; |
1083 | } |
1084 | |
1085 | /* structure lookup */ |
1086 | ST_INLN Sym *struct_find(int v) |
1087 | { |
1088 | v -= TOK_IDENT; |
1089 | if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) |
1090 | return NULL; |
1091 | return table_ident[v]->sym_struct; |
1092 | } |
1093 | |
1094 | /* find an identifier */ |
1095 | ST_INLN Sym *sym_find(int v) |
1096 | { |
1097 | v -= TOK_IDENT; |
1098 | if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) |
1099 | return NULL; |
1100 | return table_ident[v]->sym_identifier; |
1101 | } |
1102 | |
1103 | static int sym_scope(Sym *s) |
1104 | { |
1105 | if (IS_ENUM_VAL (s->type.t)) |
1106 | return s->type.ref->sym_scope; |
1107 | else |
1108 | return s->sym_scope; |
1109 | } |
1110 | |
1111 | /* push a given symbol on the symbol stack */ |
1112 | ST_FUNC Sym *sym_push(int v, CType *type, int r, int c) |
1113 | { |
1114 | Sym *s, **ps; |
1115 | TokenSym *ts; |
1116 | |
1117 | if (local_stack) |
1118 | ps = &local_stack; |
1119 | else |
1120 | ps = &global_stack; |
1121 | s = sym_push2(ps, v, type->t, c); |
1122 | s->type.ref = type->ref; |
1123 | s->r = r; |
1124 | /* don't record fields or anonymous symbols */ |
1125 | /* XXX: simplify */ |
1126 | if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) { |
1127 | /* record symbol in token array */ |
1128 | ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT]; |
1129 | if (v & SYM_STRUCT) |
1130 | ps = &ts->sym_struct; |
1131 | else |
1132 | ps = &ts->sym_identifier; |
1133 | s->prev_tok = *ps; |
1134 | *ps = s; |
1135 | s->sym_scope = local_scope; |
1136 | if (s->prev_tok && sym_scope(s->prev_tok) == s->sym_scope) |
1137 | tcc_error("redeclaration of '%s'" , |
1138 | get_tok_str(v & ~SYM_STRUCT, NULL)); |
1139 | } |
1140 | return s; |
1141 | } |
1142 | |
1143 | /* push a global identifier */ |
1144 | ST_FUNC Sym *global_identifier_push(int v, int t, int c) |
1145 | { |
1146 | Sym *s, **ps; |
1147 | s = sym_push2(&global_stack, v, t, c); |
1148 | s->r = VT_CONST | VT_SYM; |
1149 | /* don't record anonymous symbol */ |
1150 | if (v < SYM_FIRST_ANOM) { |
1151 | ps = &table_ident[v - TOK_IDENT]->sym_identifier; |
1152 | /* modify the top most local identifier, so that sym_identifier will |
1153 | point to 's' when popped; happens when called from inline asm */ |
1154 | while (*ps != NULL && (*ps)->sym_scope) |
1155 | ps = &(*ps)->prev_tok; |
1156 | s->prev_tok = *ps; |
1157 | *ps = s; |
1158 | } |
1159 | return s; |
1160 | } |
1161 | |
1162 | /* pop symbols until top reaches 'b'. If KEEP is non-zero don't really |
1163 | pop them yet from the list, but do remove them from the token array. */ |
1164 | ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep) |
1165 | { |
1166 | Sym *s, *ss, **ps; |
1167 | TokenSym *ts; |
1168 | int v; |
1169 | |
1170 | s = *ptop; |
1171 | while(s != b) { |
1172 | ss = s->prev; |
1173 | v = s->v; |
1174 | /* remove symbol in token array */ |
1175 | /* XXX: simplify */ |
1176 | if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) { |
1177 | ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT]; |
1178 | if (v & SYM_STRUCT) |
1179 | ps = &ts->sym_struct; |
1180 | else |
1181 | ps = &ts->sym_identifier; |
1182 | *ps = s->prev_tok; |
1183 | } |
1184 | if (!keep) |
1185 | sym_free(s); |
1186 | s = ss; |
1187 | } |
1188 | if (!keep) |
1189 | *ptop = b; |
1190 | } |
1191 | |
1192 | /* ------------------------------------------------------------------------- */ |
1193 | static void vcheck_cmp(void) |
1194 | { |
1195 | /* cannot let cpu flags if other instruction are generated. Also |
1196 | avoid leaving VT_JMP anywhere except on the top of the stack |
1197 | because it would complicate the code generator. |
1198 | |
1199 | Don't do this when nocode_wanted. vtop might come from |
1200 | !nocode_wanted regions (see 88_codeopt.c) and transforming |
1201 | it to a register without actually generating code is wrong |
1202 | as their value might still be used for real. All values |
1203 | we push under nocode_wanted will eventually be popped |
1204 | again, so that the VT_CMP/VT_JMP value will be in vtop |
1205 | when code is unsuppressed again. */ |
1206 | |
1207 | if (vtop->r == VT_CMP && !nocode_wanted) |
1208 | gv(RC_INT); |
1209 | } |
1210 | |
1211 | static void vsetc(CType *type, int r, CValue *vc) |
1212 | { |
1213 | if (vtop >= vstack + (VSTACK_SIZE - 1)) |
1214 | tcc_error("memory full (vstack)" ); |
1215 | vcheck_cmp(); |
1216 | vtop++; |
1217 | vtop->type = *type; |
1218 | vtop->r = r; |
1219 | vtop->r2 = VT_CONST; |
1220 | vtop->c = *vc; |
1221 | vtop->sym = NULL; |
1222 | } |
1223 | |
1224 | ST_FUNC void vswap(void) |
1225 | { |
1226 | SValue tmp; |
1227 | |
1228 | vcheck_cmp(); |
1229 | tmp = vtop[0]; |
1230 | vtop[0] = vtop[-1]; |
1231 | vtop[-1] = tmp; |
1232 | } |
1233 | |
1234 | /* pop stack value */ |
1235 | ST_FUNC void vpop(void) |
1236 | { |
1237 | int v; |
1238 | v = vtop->r & VT_VALMASK; |
1239 | #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) |
1240 | /* for x86, we need to pop the FP stack */ |
1241 | if (v == TREG_ST0) { |
1242 | o(0xd8dd); /* fstp %st(0) */ |
1243 | } else |
1244 | #endif |
1245 | if (v == VT_CMP) { |
1246 | /* need to put correct jump if && or || without test */ |
1247 | gsym(vtop->jtrue); |
1248 | gsym(vtop->jfalse); |
1249 | } |
1250 | vtop--; |
1251 | } |
1252 | |
1253 | /* push constant of type "type" with useless value */ |
1254 | static void vpush(CType *type) |
1255 | { |
1256 | vset(type, VT_CONST, 0); |
1257 | } |
1258 | |
1259 | /* push arbitrary 64bit constant */ |
1260 | static void vpush64(int ty, unsigned long long v) |
1261 | { |
1262 | CValue cval; |
1263 | CType ctype; |
1264 | ctype.t = ty; |
1265 | ctype.ref = NULL; |
1266 | cval.i = v; |
1267 | vsetc(&ctype, VT_CONST, &cval); |
1268 | } |
1269 | |
1270 | /* push integer constant */ |
1271 | ST_FUNC void vpushi(int v) |
1272 | { |
1273 | vpush64(VT_INT, v); |
1274 | } |
1275 | |
1276 | /* push a pointer sized constant */ |
1277 | static void vpushs(addr_t v) |
1278 | { |
1279 | vpush64(VT_SIZE_T, v); |
1280 | } |
1281 | |
1282 | /* push long long constant */ |
1283 | static inline void vpushll(long long v) |
1284 | { |
1285 | vpush64(VT_LLONG, v); |
1286 | } |
1287 | |
1288 | ST_FUNC void vset(CType *type, int r, int v) |
1289 | { |
1290 | CValue cval; |
1291 | cval.i = v; |
1292 | vsetc(type, r, &cval); |
1293 | } |
1294 | |
1295 | static void vseti(int r, int v) |
1296 | { |
1297 | CType type; |
1298 | type.t = VT_INT; |
1299 | type.ref = NULL; |
1300 | vset(&type, r, v); |
1301 | } |
1302 | |
1303 | ST_FUNC void vpushv(SValue *v) |
1304 | { |
1305 | if (vtop >= vstack + (VSTACK_SIZE - 1)) |
1306 | tcc_error("memory full (vstack)" ); |
1307 | vtop++; |
1308 | *vtop = *v; |
1309 | } |
1310 | |
1311 | static void vdup(void) |
1312 | { |
1313 | vpushv(vtop); |
1314 | } |
1315 | |
1316 | /* rotate n first stack elements to the bottom |
1317 | I1 ... In -> I2 ... In I1 [top is right] |
1318 | */ |
1319 | ST_FUNC void vrotb(int n) |
1320 | { |
1321 | int i; |
1322 | SValue tmp; |
1323 | |
1324 | vcheck_cmp(); |
1325 | tmp = vtop[-n + 1]; |
1326 | for(i=-n+1;i!=0;i++) |
1327 | vtop[i] = vtop[i+1]; |
1328 | vtop[0] = tmp; |
1329 | } |
1330 | |
1331 | /* rotate the n elements before entry e towards the top |
1332 | I1 ... In ... -> In I1 ... I(n-1) ... [top is right] |
1333 | */ |
1334 | ST_FUNC void vrote(SValue *e, int n) |
1335 | { |
1336 | int i; |
1337 | SValue tmp; |
1338 | |
1339 | vcheck_cmp(); |
1340 | tmp = *e; |
1341 | for(i = 0;i < n - 1; i++) |
1342 | e[-i] = e[-i - 1]; |
1343 | e[-n + 1] = tmp; |
1344 | } |
1345 | |
1346 | /* rotate n first stack elements to the top |
1347 | I1 ... In -> In I1 ... I(n-1) [top is right] |
1348 | */ |
1349 | ST_FUNC void vrott(int n) |
1350 | { |
1351 | vrote(vtop, n); |
1352 | } |
1353 | |
1354 | /* ------------------------------------------------------------------------- */ |
1355 | /* vtop->r = VT_CMP means CPU-flags have been set from comparison or test. */ |
1356 | |
1357 | /* called from generators to set the result from relational ops */ |
1358 | ST_FUNC void vset_VT_CMP(int op) |
1359 | { |
1360 | vtop->r = VT_CMP; |
1361 | vtop->cmp_op = op; |
1362 | vtop->jfalse = 0; |
1363 | vtop->jtrue = 0; |
1364 | } |
1365 | |
1366 | /* called once before asking generators to load VT_CMP to a register */ |
1367 | static void vset_VT_JMP(void) |
1368 | { |
1369 | int op = vtop->cmp_op; |
1370 | |
1371 | if (vtop->jtrue || vtop->jfalse) { |
1372 | /* we need to jump to 'mov $0,%R' or 'mov $1,%R' */ |
1373 | int inv = op & (op < 2); /* small optimization */ |
1374 | vseti(VT_JMP+inv, gvtst(inv, 0)); |
1375 | } else { |
1376 | /* otherwise convert flags (rsp. 0/1) to register */ |
1377 | vtop->c.i = op; |
1378 | if (op < 2) /* doesn't seem to happen */ |
1379 | vtop->r = VT_CONST; |
1380 | } |
1381 | } |
1382 | |
1383 | /* Set CPU Flags, doesn't yet jump */ |
1384 | static void gvtst_set(int inv, int t) |
1385 | { |
1386 | int *p; |
1387 | |
1388 | if (vtop->r != VT_CMP) { |
1389 | vpushi(0); |
1390 | gen_op(TOK_NE); |
1391 | if (vtop->r != VT_CMP) /* must be VT_CONST then */ |
1392 | vset_VT_CMP(vtop->c.i != 0); |
1393 | } |
1394 | |
1395 | p = inv ? &vtop->jfalse : &vtop->jtrue; |
1396 | *p = gjmp_append(*p, t); |
1397 | } |
1398 | |
1399 | /* Generate value test |
1400 | * |
1401 | * Generate a test for any value (jump, comparison and integers) */ |
1402 | static int gvtst(int inv, int t) |
1403 | { |
1404 | int op, x, u; |
1405 | |
1406 | gvtst_set(inv, t); |
1407 | t = vtop->jtrue, u = vtop->jfalse; |
1408 | if (inv) |
1409 | x = u, u = t, t = x; |
1410 | op = vtop->cmp_op; |
1411 | |
1412 | /* jump to the wanted target */ |
1413 | if (op > 1) |
1414 | t = gjmp_cond(op ^ inv, t); |
1415 | else if (op != inv) |
1416 | t = gjmp(t); |
1417 | /* resolve complementary jumps to here */ |
1418 | gsym(u); |
1419 | |
1420 | vtop--; |
1421 | return t; |
1422 | } |
1423 | |
1424 | /* generate a zero or nozero test */ |
1425 | static void gen_test_zero(int op) |
1426 | { |
1427 | if (vtop->r == VT_CMP) { |
1428 | int j; |
1429 | if (op == TOK_EQ) { |
1430 | j = vtop->jfalse; |
1431 | vtop->jfalse = vtop->jtrue; |
1432 | vtop->jtrue = j; |
1433 | vtop->cmp_op ^= 1; |
1434 | } |
1435 | } else { |
1436 | vpushi(0); |
1437 | gen_op(op); |
1438 | } |
1439 | } |
1440 | |
1441 | /* ------------------------------------------------------------------------- */ |
1442 | /* push a symbol value of TYPE */ |
1443 | static inline void vpushsym(CType *type, Sym *sym) |
1444 | { |
1445 | CValue cval; |
1446 | cval.i = 0; |
1447 | vsetc(type, VT_CONST | VT_SYM, &cval); |
1448 | vtop->sym = sym; |
1449 | } |
1450 | |
1451 | /* Return a static symbol pointing to a section */ |
1452 | ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size) |
1453 | { |
1454 | int v; |
1455 | Sym *sym; |
1456 | |
1457 | v = anon_sym++; |
1458 | sym = sym_push(v, type, VT_CONST | VT_SYM, 0); |
1459 | sym->type.t |= VT_STATIC; |
1460 | put_extern_sym(sym, sec, offset, size); |
1461 | return sym; |
1462 | } |
1463 | |
1464 | /* push a reference to a section offset by adding a dummy symbol */ |
1465 | static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size) |
1466 | { |
1467 | vpushsym(type, get_sym_ref(type, sec, offset, size)); |
1468 | } |
1469 | |
1470 | /* define a new external reference to a symbol 'v' of type 'u' */ |
1471 | ST_FUNC Sym *external_global_sym(int v, CType *type) |
1472 | { |
1473 | Sym *s; |
1474 | |
1475 | s = sym_find(v); |
1476 | if (!s) { |
1477 | /* push forward reference */ |
1478 | s = global_identifier_push(v, type->t | VT_EXTERN, 0); |
1479 | s->type.ref = type->ref; |
1480 | } else if (IS_ASM_SYM(s)) { |
1481 | s->type.t = type->t | (s->type.t & VT_EXTERN); |
1482 | s->type.ref = type->ref; |
1483 | update_storage(s); |
1484 | } |
1485 | return s; |
1486 | } |
1487 | |
1488 | /* Merge symbol attributes. */ |
1489 | static void merge_symattr(struct SymAttr *sa, struct SymAttr *sa1) |
1490 | { |
1491 | if (sa1->aligned && !sa->aligned) |
1492 | sa->aligned = sa1->aligned; |
1493 | sa->packed |= sa1->packed; |
1494 | sa->weak |= sa1->weak; |
1495 | if (sa1->visibility != STV_DEFAULT) { |
1496 | int vis = sa->visibility; |
1497 | if (vis == STV_DEFAULT |
1498 | || vis > sa1->visibility) |
1499 | vis = sa1->visibility; |
1500 | sa->visibility = vis; |
1501 | } |
1502 | sa->dllexport |= sa1->dllexport; |
1503 | sa->nodecorate |= sa1->nodecorate; |
1504 | sa->dllimport |= sa1->dllimport; |
1505 | } |
1506 | |
1507 | /* Merge function attributes. */ |
1508 | static void merge_funcattr(struct FuncAttr *fa, struct FuncAttr *fa1) |
1509 | { |
1510 | if (fa1->func_call && !fa->func_call) |
1511 | fa->func_call = fa1->func_call; |
1512 | if (fa1->func_type && !fa->func_type) |
1513 | fa->func_type = fa1->func_type; |
1514 | if (fa1->func_args && !fa->func_args) |
1515 | fa->func_args = fa1->func_args; |
1516 | if (fa1->func_noreturn) |
1517 | fa->func_noreturn = 1; |
1518 | if (fa1->func_ctor) |
1519 | fa->func_ctor = 1; |
1520 | if (fa1->func_dtor) |
1521 | fa->func_dtor = 1; |
1522 | } |
1523 | |
1524 | /* Merge attributes. */ |
1525 | static void merge_attr(AttributeDef *ad, AttributeDef *ad1) |
1526 | { |
1527 | merge_symattr(&ad->a, &ad1->a); |
1528 | merge_funcattr(&ad->f, &ad1->f); |
1529 | |
1530 | if (ad1->section) |
1531 | ad->section = ad1->section; |
1532 | if (ad1->alias_target) |
1533 | ad->alias_target = ad1->alias_target; |
1534 | if (ad1->asm_label) |
1535 | ad->asm_label = ad1->asm_label; |
1536 | if (ad1->attr_mode) |
1537 | ad->attr_mode = ad1->attr_mode; |
1538 | } |
1539 | |
1540 | /* Merge some type attributes. */ |
1541 | static void patch_type(Sym *sym, CType *type) |
1542 | { |
1543 | if (!(type->t & VT_EXTERN) || IS_ENUM_VAL(sym->type.t)) { |
1544 | if (!(sym->type.t & VT_EXTERN)) |
1545 | tcc_error("redefinition of '%s'" , get_tok_str(sym->v, NULL)); |
1546 | sym->type.t &= ~VT_EXTERN; |
1547 | } |
1548 | |
1549 | if (IS_ASM_SYM(sym)) { |
1550 | /* stay static if both are static */ |
1551 | sym->type.t = type->t & (sym->type.t | ~VT_STATIC); |
1552 | sym->type.ref = type->ref; |
1553 | } |
1554 | |
1555 | if (!is_compatible_types(&sym->type, type)) { |
1556 | tcc_error("incompatible types for redefinition of '%s'" , |
1557 | get_tok_str(sym->v, NULL)); |
1558 | |
1559 | } else if ((sym->type.t & VT_BTYPE) == VT_FUNC) { |
1560 | int static_proto = sym->type.t & VT_STATIC; |
1561 | /* warn if static follows non-static function declaration */ |
1562 | if ((type->t & VT_STATIC) && !static_proto |
1563 | /* XXX this test for inline shouldn't be here. Until we |
1564 | implement gnu-inline mode again it silences a warning for |
1565 | mingw caused by our workarounds. */ |
1566 | && !((type->t | sym->type.t) & VT_INLINE)) |
1567 | tcc_warning("static storage ignored for redefinition of '%s'" , |
1568 | get_tok_str(sym->v, NULL)); |
1569 | |
1570 | /* set 'inline' if both agree or if one has static */ |
1571 | if ((type->t | sym->type.t) & VT_INLINE) { |
1572 | if (!((type->t ^ sym->type.t) & VT_INLINE) |
1573 | || ((type->t | sym->type.t) & VT_STATIC)) |
1574 | static_proto |= VT_INLINE; |
1575 | } |
1576 | |
1577 | if (0 == (type->t & VT_EXTERN)) { |
1578 | struct FuncAttr f = sym->type.ref->f; |
1579 | /* put complete type, use static from prototype */ |
1580 | sym->type.t = (type->t & ~(VT_STATIC|VT_INLINE)) | static_proto; |
1581 | sym->type.ref = type->ref; |
1582 | merge_funcattr(&sym->type.ref->f, &f); |
1583 | } else { |
1584 | sym->type.t &= ~VT_INLINE | static_proto; |
1585 | } |
1586 | |
1587 | if (sym->type.ref->f.func_type == FUNC_OLD |
1588 | && type->ref->f.func_type != FUNC_OLD) { |
1589 | sym->type.ref = type->ref; |
1590 | } |
1591 | |
1592 | } else { |
1593 | if ((sym->type.t & VT_ARRAY) && type->ref->c >= 0) { |
1594 | /* set array size if it was omitted in extern declaration */ |
1595 | sym->type.ref->c = type->ref->c; |
1596 | } |
1597 | if ((type->t ^ sym->type.t) & VT_STATIC) |
1598 | tcc_warning("storage mismatch for redefinition of '%s'" , |
1599 | get_tok_str(sym->v, NULL)); |
1600 | } |
1601 | } |
1602 | |
1603 | /* Merge some storage attributes. */ |
1604 | static void patch_storage(Sym *sym, AttributeDef *ad, CType *type) |
1605 | { |
1606 | if (type) |
1607 | patch_type(sym, type); |
1608 | |
1609 | #ifdef TCC_TARGET_PE |
1610 | if (sym->a.dllimport != ad->a.dllimport) |
1611 | tcc_error("incompatible dll linkage for redefinition of '%s'" , |
1612 | get_tok_str(sym->v, NULL)); |
1613 | #endif |
1614 | merge_symattr(&sym->a, &ad->a); |
1615 | if (ad->asm_label) |
1616 | sym->asm_label = ad->asm_label; |
1617 | update_storage(sym); |
1618 | } |
1619 | |
1620 | /* copy sym to other stack */ |
1621 | static Sym *sym_copy(Sym *s0, Sym **ps) |
1622 | { |
1623 | Sym *s; |
1624 | s = sym_malloc(), *s = *s0; |
1625 | s->prev = *ps, *ps = s; |
1626 | if (s->v < SYM_FIRST_ANOM) { |
1627 | ps = &table_ident[s->v - TOK_IDENT]->sym_identifier; |
1628 | s->prev_tok = *ps, *ps = s; |
1629 | } |
1630 | return s; |
1631 | } |
1632 | |
1633 | /* copy s->type.ref to stack 'ps' for VT_FUNC and VT_PTR */ |
1634 | static void sym_copy_ref(Sym *s, Sym **ps) |
1635 | { |
1636 | int bt = s->type.t & VT_BTYPE; |
1637 | if (bt == VT_FUNC || bt == VT_PTR) { |
1638 | Sym **sp = &s->type.ref; |
1639 | for (s = *sp, *sp = NULL; s; s = s->next) { |
1640 | Sym *s2 = sym_copy(s, ps); |
1641 | sp = &(*sp = s2)->next; |
1642 | sym_copy_ref(s2, ps); |
1643 | } |
1644 | } |
1645 | } |
1646 | |
1647 | /* define a new external reference to a symbol 'v' */ |
1648 | static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad) |
1649 | { |
1650 | Sym *s; |
1651 | |
1652 | /* look for global symbol */ |
1653 | s = sym_find(v); |
1654 | while (s && s->sym_scope) |
1655 | s = s->prev_tok; |
1656 | |
1657 | if (!s) { |
1658 | /* push forward reference */ |
1659 | s = global_identifier_push(v, type->t, 0); |
1660 | s->r |= r; |
1661 | s->a = ad->a; |
1662 | s->asm_label = ad->asm_label; |
1663 | s->type.ref = type->ref; |
1664 | /* copy type to the global stack */ |
1665 | if (local_stack) |
1666 | sym_copy_ref(s, &global_stack); |
1667 | } else { |
1668 | patch_storage(s, ad, type); |
1669 | } |
1670 | /* push variables on local_stack if any */ |
1671 | if (local_stack && (s->type.t & VT_BTYPE) != VT_FUNC) |
1672 | s = sym_copy(s, &local_stack); |
1673 | return s; |
1674 | } |
1675 | |
1676 | /* push a reference to global symbol v */ |
1677 | ST_FUNC void vpush_global_sym(CType *type, int v) |
1678 | { |
1679 | vpushsym(type, external_global_sym(v, type)); |
1680 | } |
1681 | |
1682 | /* save registers up to (vtop - n) stack entry */ |
1683 | ST_FUNC void save_regs(int n) |
1684 | { |
1685 | SValue *p, *p1; |
1686 | for(p = vstack, p1 = vtop - n; p <= p1; p++) |
1687 | save_reg(p->r); |
1688 | } |
1689 | |
1690 | /* save r to the memory stack, and mark it as being free */ |
1691 | ST_FUNC void save_reg(int r) |
1692 | { |
1693 | save_reg_upstack(r, 0); |
1694 | } |
1695 | |
1696 | /* save r to the memory stack, and mark it as being free, |
1697 | if seen up to (vtop - n) stack entry */ |
1698 | ST_FUNC void save_reg_upstack(int r, int n) |
1699 | { |
1700 | int l, size, align, bt; |
1701 | SValue *p, *p1, sv; |
1702 | |
1703 | if ((r &= VT_VALMASK) >= VT_CONST) |
1704 | return; |
1705 | if (nocode_wanted) |
1706 | return; |
1707 | l = 0; |
1708 | for(p = vstack, p1 = vtop - n; p <= p1; p++) { |
1709 | if ((p->r & VT_VALMASK) == r || p->r2 == r) { |
1710 | /* must save value on stack if not already done */ |
1711 | if (!l) { |
1712 | bt = p->type.t & VT_BTYPE; |
1713 | if (bt == VT_VOID) |
1714 | continue; |
1715 | if ((p->r & VT_LVAL) || bt == VT_FUNC) |
1716 | bt = VT_PTR; |
1717 | sv.type.t = bt; |
1718 | size = type_size(&sv.type, &align); |
1719 | l = get_temp_local_var(size,align); |
1720 | sv.r = VT_LOCAL | VT_LVAL; |
1721 | sv.c.i = l; |
1722 | store(p->r & VT_VALMASK, &sv); |
1723 | #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) |
1724 | /* x86 specific: need to pop fp register ST0 if saved */ |
1725 | if (r == TREG_ST0) { |
1726 | o(0xd8dd); /* fstp %st(0) */ |
1727 | } |
1728 | #endif |
1729 | /* special long long case */ |
1730 | if (p->r2 < VT_CONST && USING_TWO_WORDS(bt)) { |
1731 | sv.c.i += PTR_SIZE; |
1732 | store(p->r2, &sv); |
1733 | } |
1734 | } |
1735 | /* mark that stack entry as being saved on the stack */ |
1736 | if (p->r & VT_LVAL) { |
1737 | /* also clear the bounded flag because the |
1738 | relocation address of the function was stored in |
1739 | p->c.i */ |
1740 | p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL; |
1741 | } else { |
1742 | p->r = VT_LVAL | VT_LOCAL; |
1743 | } |
1744 | p->r2 = VT_CONST; |
1745 | p->c.i = l; |
1746 | } |
1747 | } |
1748 | } |
1749 | |
1750 | #ifdef TCC_TARGET_ARM |
1751 | /* find a register of class 'rc2' with at most one reference on stack. |
1752 | * If none, call get_reg(rc) */ |
1753 | ST_FUNC int get_reg_ex(int rc, int rc2) |
1754 | { |
1755 | int r; |
1756 | SValue *p; |
1757 | |
1758 | for(r=0;r<NB_REGS;r++) { |
1759 | if (reg_classes[r] & rc2) { |
1760 | int n; |
1761 | n=0; |
1762 | for(p = vstack; p <= vtop; p++) { |
1763 | if ((p->r & VT_VALMASK) == r || |
1764 | p->r2 == r) |
1765 | n++; |
1766 | } |
1767 | if (n <= 1) |
1768 | return r; |
1769 | } |
1770 | } |
1771 | return get_reg(rc); |
1772 | } |
1773 | #endif |
1774 | |
1775 | /* find a free register of class 'rc'. If none, save one register */ |
1776 | ST_FUNC int get_reg(int rc) |
1777 | { |
1778 | int r; |
1779 | SValue *p; |
1780 | |
1781 | /* find a free register */ |
1782 | for(r=0;r<NB_REGS;r++) { |
1783 | if (reg_classes[r] & rc) { |
1784 | if (nocode_wanted) |
1785 | return r; |
1786 | for(p=vstack;p<=vtop;p++) { |
1787 | if ((p->r & VT_VALMASK) == r || |
1788 | p->r2 == r) |
1789 | goto notfound; |
1790 | } |
1791 | return r; |
1792 | } |
1793 | notfound: ; |
1794 | } |
1795 | |
1796 | /* no register left : free the first one on the stack (VERY |
1797 | IMPORTANT to start from the bottom to ensure that we don't |
1798 | spill registers used in gen_opi()) */ |
1799 | for(p=vstack;p<=vtop;p++) { |
1800 | /* look at second register (if long long) */ |
1801 | r = p->r2; |
1802 | if (r < VT_CONST && (reg_classes[r] & rc)) |
1803 | goto save_found; |
1804 | r = p->r & VT_VALMASK; |
1805 | if (r < VT_CONST && (reg_classes[r] & rc)) { |
1806 | save_found: |
1807 | save_reg(r); |
1808 | return r; |
1809 | } |
1810 | } |
1811 | /* Should never comes here */ |
1812 | return -1; |
1813 | } |
1814 | |
1815 | /* find a free temporary local variable (return the offset on stack) match the size and align. If none, add new temporary stack variable*/ |
1816 | static int get_temp_local_var(int size,int align){ |
1817 | int i; |
1818 | struct temp_local_variable *temp_var; |
1819 | int found_var; |
1820 | SValue *p; |
1821 | int r; |
1822 | char free; |
1823 | char found; |
1824 | found=0; |
1825 | for(i=0;i<nb_temp_local_vars;i++){ |
1826 | temp_var=&arr_temp_local_vars[i]; |
1827 | if(temp_var->size<size||align!=temp_var->align){ |
1828 | continue; |
1829 | } |
1830 | /*check if temp_var is free*/ |
1831 | free=1; |
1832 | for(p=vstack;p<=vtop;p++) { |
1833 | r=p->r&VT_VALMASK; |
1834 | if(r==VT_LOCAL||r==VT_LLOCAL){ |
1835 | if(p->c.i==temp_var->location){ |
1836 | free=0; |
1837 | break; |
1838 | } |
1839 | } |
1840 | } |
1841 | if(free){ |
1842 | found_var=temp_var->location; |
1843 | found=1; |
1844 | break; |
1845 | } |
1846 | } |
1847 | if(!found){ |
1848 | loc = (loc - size) & -align; |
1849 | if(nb_temp_local_vars<MAX_TEMP_LOCAL_VARIABLE_NUMBER){ |
1850 | temp_var=&arr_temp_local_vars[i]; |
1851 | temp_var->location=loc; |
1852 | temp_var->size=size; |
1853 | temp_var->align=align; |
1854 | nb_temp_local_vars++; |
1855 | } |
1856 | found_var=loc; |
1857 | } |
1858 | return found_var; |
1859 | } |
1860 | |
1861 | static void clear_temp_local_var_list(){ |
1862 | nb_temp_local_vars=0; |
1863 | } |
1864 | |
1865 | /* move register 's' (of type 't') to 'r', and flush previous value of r to memory |
1866 | if needed */ |
1867 | static void move_reg(int r, int s, int t) |
1868 | { |
1869 | SValue sv; |
1870 | |
1871 | if (r != s) { |
1872 | save_reg(r); |
1873 | sv.type.t = t; |
1874 | sv.type.ref = NULL; |
1875 | sv.r = s; |
1876 | sv.c.i = 0; |
1877 | load(r, &sv); |
1878 | } |
1879 | } |
1880 | |
1881 | /* get address of vtop (vtop MUST BE an lvalue) */ |
1882 | ST_FUNC void gaddrof(void) |
1883 | { |
1884 | vtop->r &= ~VT_LVAL; |
1885 | /* tricky: if saved lvalue, then we can go back to lvalue */ |
1886 | if ((vtop->r & VT_VALMASK) == VT_LLOCAL) |
1887 | vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL; |
1888 | } |
1889 | |
1890 | #ifdef CONFIG_TCC_BCHECK |
1891 | /* generate a bounded pointer addition */ |
1892 | static void gen_bounded_ptr_add(void) |
1893 | { |
1894 | int save = (vtop[-1].r & VT_VALMASK) == VT_LOCAL; |
1895 | if (save) { |
1896 | vpushv(&vtop[-1]); |
1897 | vrott(3); |
1898 | } |
1899 | vpush_global_sym(&func_old_type, TOK___bound_ptr_add); |
1900 | vrott(3); |
1901 | gfunc_call(2); |
1902 | vtop -= save; |
1903 | vpushi(0); |
1904 | /* returned pointer is in REG_IRET */ |
1905 | vtop->r = REG_IRET | VT_BOUNDED; |
1906 | if (nocode_wanted) |
1907 | return; |
1908 | /* relocation offset of the bounding function call point */ |
1909 | vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(ElfW_Rel)); |
1910 | } |
1911 | |
1912 | /* patch pointer addition in vtop so that pointer dereferencing is |
1913 | also tested */ |
1914 | static void gen_bounded_ptr_deref(void) |
1915 | { |
1916 | addr_t func; |
1917 | int size, align; |
1918 | ElfW_Rel *rel; |
1919 | Sym *sym; |
1920 | |
1921 | if (nocode_wanted) |
1922 | return; |
1923 | |
1924 | size = type_size(&vtop->type, &align); |
1925 | switch(size) { |
1926 | case 1: func = TOK___bound_ptr_indir1; break; |
1927 | case 2: func = TOK___bound_ptr_indir2; break; |
1928 | case 4: func = TOK___bound_ptr_indir4; break; |
1929 | case 8: func = TOK___bound_ptr_indir8; break; |
1930 | case 12: func = TOK___bound_ptr_indir12; break; |
1931 | case 16: func = TOK___bound_ptr_indir16; break; |
1932 | default: |
1933 | /* may happen with struct member access */ |
1934 | return; |
1935 | } |
1936 | sym = external_global_sym(func, &func_old_type); |
1937 | if (!sym->c) |
1938 | put_extern_sym(sym, NULL, 0, 0); |
1939 | /* patch relocation */ |
1940 | /* XXX: find a better solution ? */ |
1941 | rel = (ElfW_Rel *)(cur_text_section->reloc->data + vtop->c.i); |
1942 | rel->r_info = ELFW(R_INFO)(sym->c, ELFW(R_TYPE)(rel->r_info)); |
1943 | } |
1944 | |
1945 | /* generate lvalue bound code */ |
1946 | static void gbound(void) |
1947 | { |
1948 | CType type1; |
1949 | |
1950 | vtop->r &= ~VT_MUSTBOUND; |
1951 | /* if lvalue, then use checking code before dereferencing */ |
1952 | if (vtop->r & VT_LVAL) { |
1953 | /* if not VT_BOUNDED value, then make one */ |
1954 | if (!(vtop->r & VT_BOUNDED)) { |
1955 | /* must save type because we must set it to int to get pointer */ |
1956 | type1 = vtop->type; |
1957 | vtop->type.t = VT_PTR; |
1958 | gaddrof(); |
1959 | vpushi(0); |
1960 | gen_bounded_ptr_add(); |
1961 | vtop->r |= VT_LVAL; |
1962 | vtop->type = type1; |
1963 | } |
1964 | /* then check for dereferencing */ |
1965 | gen_bounded_ptr_deref(); |
1966 | } |
1967 | } |
1968 | |
1969 | /* we need to call __bound_ptr_add before we start to load function |
1970 | args into registers */ |
1971 | ST_FUNC void gbound_args(int nb_args) |
1972 | { |
1973 | int i, v; |
1974 | SValue *sv; |
1975 | |
1976 | for (i = 1; i <= nb_args; ++i) |
1977 | if (vtop[1 - i].r & VT_MUSTBOUND) { |
1978 | vrotb(i); |
1979 | gbound(); |
1980 | vrott(i); |
1981 | } |
1982 | |
1983 | sv = vtop - nb_args; |
1984 | if (sv->r & VT_SYM) { |
1985 | v = sv->sym->v; |
1986 | if (v == TOK_setjmp |
1987 | || v == TOK__setjmp |
1988 | #ifndef TCC_TARGET_PE |
1989 | || v == TOK_sigsetjmp |
1990 | || v == TOK___sigsetjmp |
1991 | #endif |
1992 | ) { |
1993 | vpush_global_sym(&func_old_type, TOK___bound_setjmp); |
1994 | vpushv(sv + 1); |
1995 | gfunc_call(1); |
1996 | func_bound_add_epilog = 1; |
1997 | } |
1998 | #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 |
1999 | if (v == TOK_alloca) |
2000 | func_bound_add_epilog = 1; |
2001 | #endif |
2002 | } |
2003 | } |
2004 | |
2005 | /* Add bounds for local symbols from S to E (via ->prev) */ |
2006 | static void add_local_bounds(Sym *s, Sym *e) |
2007 | { |
2008 | for (; s != e; s = s->prev) { |
2009 | if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL) |
2010 | continue; |
2011 | /* Add arrays/structs/unions because we always take address */ |
2012 | if ((s->type.t & VT_ARRAY) |
2013 | || (s->type.t & VT_BTYPE) == VT_STRUCT |
2014 | || s->a.addrtaken) { |
2015 | /* add local bound info */ |
2016 | int align, size = type_size(&s->type, &align); |
2017 | addr_t *bounds_ptr = section_ptr_add(lbounds_section, |
2018 | 2 * sizeof(addr_t)); |
2019 | bounds_ptr[0] = s->c; |
2020 | bounds_ptr[1] = size; |
2021 | } |
2022 | } |
2023 | } |
2024 | #endif |
2025 | |
2026 | /* Wrapper around sym_pop, that potentially also registers local bounds. */ |
2027 | static void pop_local_syms(Sym **ptop, Sym *b, int keep, int ellipsis) |
2028 | { |
2029 | #ifdef CONFIG_TCC_BCHECK |
2030 | if (tcc_state->do_bounds_check && !ellipsis && !keep) |
2031 | add_local_bounds(*ptop, b); |
2032 | #endif |
2033 | if (tcc_state->do_debug) |
2034 | tcc_add_debug_info (tcc_state, !local_scope, *ptop, b); |
2035 | sym_pop(ptop, b, keep); |
2036 | } |
2037 | |
2038 | static void incr_bf_adr(int o) |
2039 | { |
2040 | vtop->type = char_pointer_type; |
2041 | gaddrof(); |
2042 | vpushs(o); |
2043 | gen_op('+'); |
2044 | vtop->type.t = VT_BYTE | VT_UNSIGNED; |
2045 | vtop->r |= VT_LVAL; |
2046 | } |
2047 | |
2048 | /* single-byte load mode for packed or otherwise unaligned bitfields */ |
2049 | static void load_packed_bf(CType *type, int bit_pos, int bit_size) |
2050 | { |
2051 | int n, o, bits; |
2052 | save_reg_upstack(vtop->r, 1); |
2053 | vpush64(type->t & VT_BTYPE, 0); // B X |
2054 | bits = 0, o = bit_pos >> 3, bit_pos &= 7; |
2055 | do { |
2056 | vswap(); // X B |
2057 | incr_bf_adr(o); |
2058 | vdup(); // X B B |
2059 | n = 8 - bit_pos; |
2060 | if (n > bit_size) |
2061 | n = bit_size; |
2062 | if (bit_pos) |
2063 | vpushi(bit_pos), gen_op(TOK_SHR), bit_pos = 0; // X B Y |
2064 | if (n < 8) |
2065 | vpushi((1 << n) - 1), gen_op('&'); |
2066 | gen_cast(type); |
2067 | if (bits) |
2068 | vpushi(bits), gen_op(TOK_SHL); |
2069 | vrotb(3); // B Y X |
2070 | gen_op('|'); // B X |
2071 | bits += n, bit_size -= n, o = 1; |
2072 | } while (bit_size); |
2073 | vswap(), vpop(); |
2074 | if (!(type->t & VT_UNSIGNED)) { |
2075 | n = ((type->t & VT_BTYPE) == VT_LLONG ? 64 : 32) - bits; |
2076 | vpushi(n), gen_op(TOK_SHL); |
2077 | vpushi(n), gen_op(TOK_SAR); |
2078 | } |
2079 | } |
2080 | |
2081 | /* single-byte store mode for packed or otherwise unaligned bitfields */ |
2082 | static void store_packed_bf(int bit_pos, int bit_size) |
2083 | { |
2084 | int bits, n, o, m, c; |
2085 | |
2086 | c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; |
2087 | vswap(); // X B |
2088 | save_reg_upstack(vtop->r, 1); |
2089 | bits = 0, o = bit_pos >> 3, bit_pos &= 7; |
2090 | do { |
2091 | incr_bf_adr(o); // X B |
2092 | vswap(); //B X |
2093 | c ? vdup() : gv_dup(); // B V X |
2094 | vrott(3); // X B V |
2095 | if (bits) |
2096 | vpushi(bits), gen_op(TOK_SHR); |
2097 | if (bit_pos) |
2098 | vpushi(bit_pos), gen_op(TOK_SHL); |
2099 | n = 8 - bit_pos; |
2100 | if (n > bit_size) |
2101 | n = bit_size; |
2102 | if (n < 8) { |
2103 | m = ((1 << n) - 1) << bit_pos; |
2104 | vpushi(m), gen_op('&'); // X B V1 |
2105 | vpushv(vtop-1); // X B V1 B |
2106 | vpushi(m & 0x80 ? ~m & 0x7f : ~m); |
2107 | gen_op('&'); // X B V1 B1 |
2108 | gen_op('|'); // X B V2 |
2109 | } |
2110 | vdup(), vtop[-1] = vtop[-2]; // X B B V2 |
2111 | vstore(), vpop(); // X B |
2112 | bits += n, bit_size -= n, bit_pos = 0, o = 1; |
2113 | } while (bit_size); |
2114 | vpop(), vpop(); |
2115 | } |
2116 | |
2117 | static int adjust_bf(SValue *sv, int bit_pos, int bit_size) |
2118 | { |
2119 | int t; |
2120 | if (0 == sv->type.ref) |
2121 | return 0; |
2122 | t = sv->type.ref->auxtype; |
2123 | if (t != -1 && t != VT_STRUCT) { |
2124 | sv->type.t = (sv->type.t & ~(VT_BTYPE | VT_LONG)) | t; |
2125 | sv->r |= VT_LVAL; |
2126 | } |
2127 | return t; |
2128 | } |
2129 | |
2130 | /* store vtop a register belonging to class 'rc'. lvalues are |
2131 | converted to values. Cannot be used if cannot be converted to |
2132 | register value (such as structures). */ |
2133 | ST_FUNC int gv(int rc) |
2134 | { |
2135 | int r, r2, r_ok, r2_ok, rc2, bt; |
2136 | int bit_pos, bit_size, size, align; |
2137 | |
2138 | /* NOTE: get_reg can modify vstack[] */ |
2139 | if (vtop->type.t & VT_BITFIELD) { |
2140 | CType type; |
2141 | |
2142 | bit_pos = BIT_POS(vtop->type.t); |
2143 | bit_size = BIT_SIZE(vtop->type.t); |
2144 | /* remove bit field info to avoid loops */ |
2145 | vtop->type.t &= ~VT_STRUCT_MASK; |
2146 | |
2147 | type.ref = NULL; |
2148 | type.t = vtop->type.t & VT_UNSIGNED; |
2149 | if ((vtop->type.t & VT_BTYPE) == VT_BOOL) |
2150 | type.t |= VT_UNSIGNED; |
2151 | |
2152 | r = adjust_bf(vtop, bit_pos, bit_size); |
2153 | |
2154 | if ((vtop->type.t & VT_BTYPE) == VT_LLONG) |
2155 | type.t |= VT_LLONG; |
2156 | else |
2157 | type.t |= VT_INT; |
2158 | |
2159 | if (r == VT_STRUCT) { |
2160 | load_packed_bf(&type, bit_pos, bit_size); |
2161 | } else { |
2162 | int bits = (type.t & VT_BTYPE) == VT_LLONG ? 64 : 32; |
2163 | /* cast to int to propagate signedness in following ops */ |
2164 | gen_cast(&type); |
2165 | /* generate shifts */ |
2166 | vpushi(bits - (bit_pos + bit_size)); |
2167 | gen_op(TOK_SHL); |
2168 | vpushi(bits - bit_size); |
2169 | /* NOTE: transformed to SHR if unsigned */ |
2170 | gen_op(TOK_SAR); |
2171 | } |
2172 | r = gv(rc); |
2173 | } else { |
2174 | if (is_float(vtop->type.t) && |
2175 | (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { |
2176 | /* CPUs usually cannot use float constants, so we store them |
2177 | generically in data segment */ |
2178 | init_params p = { data_section }; |
2179 | unsigned long offset; |
2180 | size = type_size(&vtop->type, &align); |
2181 | if (NODATA_WANTED) |
2182 | size = 0, align = 1; |
2183 | offset = section_add(p.sec, size, align); |
2184 | vpush_ref(&vtop->type, p.sec, offset, size); |
2185 | vswap(); |
2186 | init_putv(&p, &vtop->type, offset); |
2187 | vtop->r |= VT_LVAL; |
2188 | } |
2189 | #ifdef CONFIG_TCC_BCHECK |
2190 | if (vtop->r & VT_MUSTBOUND) |
2191 | gbound(); |
2192 | #endif |
2193 | |
2194 | bt = vtop->type.t & VT_BTYPE; |
2195 | |
2196 | #ifdef TCC_TARGET_RISCV64 |
2197 | /* XXX mega hack */ |
2198 | if (bt == VT_LDOUBLE && rc == RC_FLOAT) |
2199 | rc = RC_INT; |
2200 | #endif |
2201 | rc2 = RC2_TYPE(bt, rc); |
2202 | |
2203 | /* need to reload if: |
2204 | - constant |
2205 | - lvalue (need to dereference pointer) |
2206 | - already a register, but not in the right class */ |
2207 | r = vtop->r & VT_VALMASK; |
2208 | r_ok = !(vtop->r & VT_LVAL) && (r < VT_CONST) && (reg_classes[r] & rc); |
2209 | r2_ok = !rc2 || ((vtop->r2 < VT_CONST) && (reg_classes[vtop->r2] & rc2)); |
2210 | |
2211 | if (!r_ok || !r2_ok) { |
2212 | if (!r_ok) |
2213 | r = get_reg(rc); |
2214 | if (rc2) { |
2215 | int load_type = (bt == VT_QFLOAT) ? VT_DOUBLE : VT_PTRDIFF_T; |
2216 | int original_type = vtop->type.t; |
2217 | |
2218 | /* two register type load : |
2219 | expand to two words temporarily */ |
2220 | if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { |
2221 | /* load constant */ |
2222 | unsigned long long ll = vtop->c.i; |
2223 | vtop->c.i = ll; /* first word */ |
2224 | load(r, vtop); |
2225 | vtop->r = r; /* save register value */ |
2226 | vpushi(ll >> 32); /* second word */ |
2227 | } else if (vtop->r & VT_LVAL) { |
2228 | /* We do not want to modifier the long long pointer here. |
2229 | So we save any other instances down the stack */ |
2230 | save_reg_upstack(vtop->r, 1); |
2231 | /* load from memory */ |
2232 | vtop->type.t = load_type; |
2233 | load(r, vtop); |
2234 | vdup(); |
2235 | vtop[-1].r = r; /* save register value */ |
2236 | /* increment pointer to get second word */ |
2237 | vtop->type.t = VT_PTRDIFF_T; |
2238 | gaddrof(); |
2239 | vpushs(PTR_SIZE); |
2240 | gen_op('+'); |
2241 | vtop->r |= VT_LVAL; |
2242 | vtop->type.t = load_type; |
2243 | } else { |
2244 | /* move registers */ |
2245 | if (!r_ok) |
2246 | load(r, vtop); |
2247 | if (r2_ok && vtop->r2 < VT_CONST) |
2248 | goto done; |
2249 | vdup(); |
2250 | vtop[-1].r = r; /* save register value */ |
2251 | vtop->r = vtop[-1].r2; |
2252 | } |
2253 | /* Allocate second register. Here we rely on the fact that |
2254 | get_reg() tries first to free r2 of an SValue. */ |
2255 | r2 = get_reg(rc2); |
2256 | load(r2, vtop); |
2257 | vpop(); |
2258 | /* write second register */ |
2259 | vtop->r2 = r2; |
2260 | done: |
2261 | vtop->type.t = original_type; |
2262 | } else { |
2263 | if (vtop->r == VT_CMP) |
2264 | vset_VT_JMP(); |
2265 | /* one register type load */ |
2266 | load(r, vtop); |
2267 | } |
2268 | } |
2269 | vtop->r = r; |
2270 | #ifdef TCC_TARGET_C67 |
2271 | /* uses register pairs for doubles */ |
2272 | if (bt == VT_DOUBLE) |
2273 | vtop->r2 = r+1; |
2274 | #endif |
2275 | } |
2276 | return r; |
2277 | } |
2278 | |
2279 | /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */ |
2280 | ST_FUNC void gv2(int rc1, int rc2) |
2281 | { |
2282 | /* generate more generic register first. But VT_JMP or VT_CMP |
2283 | values must be generated first in all cases to avoid possible |
2284 | reload errors */ |
2285 | if (vtop->r != VT_CMP && rc1 <= rc2) { |
2286 | vswap(); |
2287 | gv(rc1); |
2288 | vswap(); |
2289 | gv(rc2); |
2290 | /* test if reload is needed for first register */ |
2291 | if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { |
2292 | vswap(); |
2293 | gv(rc1); |
2294 | vswap(); |
2295 | } |
2296 | } else { |
2297 | gv(rc2); |
2298 | vswap(); |
2299 | gv(rc1); |
2300 | vswap(); |
2301 | /* test if reload is needed for first register */ |
2302 | if ((vtop[0].r & VT_VALMASK) >= VT_CONST) { |
2303 | gv(rc2); |
2304 | } |
2305 | } |
2306 | } |
2307 | |
2308 | #if PTR_SIZE == 4 |
2309 | /* expand 64bit on stack in two ints */ |
2310 | ST_FUNC void lexpand(void) |
2311 | { |
2312 | int u, v; |
2313 | u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED); |
2314 | v = vtop->r & (VT_VALMASK | VT_LVAL); |
2315 | if (v == VT_CONST) { |
2316 | vdup(); |
2317 | vtop[0].c.i >>= 32; |
2318 | } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) { |
2319 | vdup(); |
2320 | vtop[0].c.i += 4; |
2321 | } else { |
2322 | gv(RC_INT); |
2323 | vdup(); |
2324 | vtop[0].r = vtop[-1].r2; |
2325 | vtop[0].r2 = vtop[-1].r2 = VT_CONST; |
2326 | } |
2327 | vtop[0].type.t = vtop[-1].type.t = VT_INT | u; |
2328 | } |
2329 | #endif |
2330 | |
2331 | #if PTR_SIZE == 4 |
2332 | /* build a long long from two ints */ |
2333 | static void lbuild(int t) |
2334 | { |
2335 | gv2(RC_INT, RC_INT); |
2336 | vtop[-1].r2 = vtop[0].r; |
2337 | vtop[-1].type.t = t; |
2338 | vpop(); |
2339 | } |
2340 | #endif |
2341 | |
2342 | /* convert stack entry to register and duplicate its value in another |
2343 | register */ |
2344 | static void gv_dup(void) |
2345 | { |
2346 | int t, rc, r; |
2347 | |
2348 | t = vtop->type.t; |
2349 | #if PTR_SIZE == 4 |
2350 | if ((t & VT_BTYPE) == VT_LLONG) { |
2351 | if (t & VT_BITFIELD) { |
2352 | gv(RC_INT); |
2353 | t = vtop->type.t; |
2354 | } |
2355 | lexpand(); |
2356 | gv_dup(); |
2357 | vswap(); |
2358 | vrotb(3); |
2359 | gv_dup(); |
2360 | vrotb(4); |
2361 | /* stack: H L L1 H1 */ |
2362 | lbuild(t); |
2363 | vrotb(3); |
2364 | vrotb(3); |
2365 | vswap(); |
2366 | lbuild(t); |
2367 | vswap(); |
2368 | return; |
2369 | } |
2370 | #endif |
2371 | /* duplicate value */ |
2372 | rc = RC_TYPE(t); |
2373 | gv(rc); |
2374 | r = get_reg(rc); |
2375 | vdup(); |
2376 | load(r, vtop); |
2377 | vtop->r = r; |
2378 | } |
2379 | |
2380 | #if PTR_SIZE == 4 |
2381 | /* generate CPU independent (unsigned) long long operations */ |
2382 | static void gen_opl(int op) |
2383 | { |
2384 | int t, a, b, op1, c, i; |
2385 | int func; |
2386 | unsigned short reg_iret = REG_IRET; |
2387 | unsigned short reg_lret = REG_IRE2; |
2388 | SValue tmp; |
2389 | |
2390 | switch(op) { |
2391 | case '/': |
2392 | case TOK_PDIV: |
2393 | func = TOK___divdi3; |
2394 | goto gen_func; |
2395 | case TOK_UDIV: |
2396 | func = TOK___udivdi3; |
2397 | goto gen_func; |
2398 | case '%': |
2399 | func = TOK___moddi3; |
2400 | goto gen_mod_func; |
2401 | case TOK_UMOD: |
2402 | func = TOK___umoddi3; |
2403 | gen_mod_func: |
2404 | #ifdef TCC_ARM_EABI |
2405 | reg_iret = TREG_R2; |
2406 | reg_lret = TREG_R3; |
2407 | #endif |
2408 | gen_func: |
2409 | /* call generic long long function */ |
2410 | vpush_global_sym(&func_old_type, func); |
2411 | vrott(3); |
2412 | gfunc_call(2); |
2413 | vpushi(0); |
2414 | vtop->r = reg_iret; |
2415 | vtop->r2 = reg_lret; |
2416 | break; |
2417 | case '^': |
2418 | case '&': |
2419 | case '|': |
2420 | case '*': |
2421 | case '+': |
2422 | case '-': |
2423 | //pv("gen_opl A",0,2); |
2424 | t = vtop->type.t; |
2425 | vswap(); |
2426 | lexpand(); |
2427 | vrotb(3); |
2428 | lexpand(); |
2429 | /* stack: L1 H1 L2 H2 */ |
2430 | tmp = vtop[0]; |
2431 | vtop[0] = vtop[-3]; |
2432 | vtop[-3] = tmp; |
2433 | tmp = vtop[-2]; |
2434 | vtop[-2] = vtop[-3]; |
2435 | vtop[-3] = tmp; |
2436 | vswap(); |
2437 | /* stack: H1 H2 L1 L2 */ |
2438 | //pv("gen_opl B",0,4); |
2439 | if (op == '*') { |
2440 | vpushv(vtop - 1); |
2441 | vpushv(vtop - 1); |
2442 | gen_op(TOK_UMULL); |
2443 | lexpand(); |
2444 | /* stack: H1 H2 L1 L2 ML MH */ |
2445 | for(i=0;i<4;i++) |
2446 | vrotb(6); |
2447 | /* stack: ML MH H1 H2 L1 L2 */ |
2448 | tmp = vtop[0]; |
2449 | vtop[0] = vtop[-2]; |
2450 | vtop[-2] = tmp; |
2451 | /* stack: ML MH H1 L2 H2 L1 */ |
2452 | gen_op('*'); |
2453 | vrotb(3); |
2454 | vrotb(3); |
2455 | gen_op('*'); |
2456 | /* stack: ML MH M1 M2 */ |
2457 | gen_op('+'); |
2458 | gen_op('+'); |
2459 | } else if (op == '+' || op == '-') { |
2460 | /* XXX: add non carry method too (for MIPS or alpha) */ |
2461 | if (op == '+') |
2462 | op1 = TOK_ADDC1; |
2463 | else |
2464 | op1 = TOK_SUBC1; |
2465 | gen_op(op1); |
2466 | /* stack: H1 H2 (L1 op L2) */ |
2467 | vrotb(3); |
2468 | vrotb(3); |
2469 | gen_op(op1 + 1); /* TOK_xxxC2 */ |
2470 | } else { |
2471 | gen_op(op); |
2472 | /* stack: H1 H2 (L1 op L2) */ |
2473 | vrotb(3); |
2474 | vrotb(3); |
2475 | /* stack: (L1 op L2) H1 H2 */ |
2476 | gen_op(op); |
2477 | /* stack: (L1 op L2) (H1 op H2) */ |
2478 | } |
2479 | /* stack: L H */ |
2480 | lbuild(t); |
2481 | break; |
2482 | case TOK_SAR: |
2483 | case TOK_SHR: |
2484 | case TOK_SHL: |
2485 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
2486 | t = vtop[-1].type.t; |
2487 | vswap(); |
2488 | lexpand(); |
2489 | vrotb(3); |
2490 | /* stack: L H shift */ |
2491 | c = (int)vtop->c.i; |
2492 | /* constant: simpler */ |
2493 | /* NOTE: all comments are for SHL. the other cases are |
2494 | done by swapping words */ |
2495 | vpop(); |
2496 | if (op != TOK_SHL) |
2497 | vswap(); |
2498 | if (c >= 32) { |
2499 | /* stack: L H */ |
2500 | vpop(); |
2501 | if (c > 32) { |
2502 | vpushi(c - 32); |
2503 | gen_op(op); |
2504 | } |
2505 | if (op != TOK_SAR) { |
2506 | vpushi(0); |
2507 | } else { |
2508 | gv_dup(); |
2509 | vpushi(31); |
2510 | gen_op(TOK_SAR); |
2511 | } |
2512 | vswap(); |
2513 | } else { |
2514 | vswap(); |
2515 | gv_dup(); |
2516 | /* stack: H L L */ |
2517 | vpushi(c); |
2518 | gen_op(op); |
2519 | vswap(); |
2520 | vpushi(32 - c); |
2521 | if (op == TOK_SHL) |
2522 | gen_op(TOK_SHR); |
2523 | else |
2524 | gen_op(TOK_SHL); |
2525 | vrotb(3); |
2526 | /* stack: L L H */ |
2527 | vpushi(c); |
2528 | if (op == TOK_SHL) |
2529 | gen_op(TOK_SHL); |
2530 | else |
2531 | gen_op(TOK_SHR); |
2532 | gen_op('|'); |
2533 | } |
2534 | if (op != TOK_SHL) |
2535 | vswap(); |
2536 | lbuild(t); |
2537 | } else { |
2538 | /* XXX: should provide a faster fallback on x86 ? */ |
2539 | switch(op) { |
2540 | case TOK_SAR: |
2541 | func = TOK___ashrdi3; |
2542 | goto gen_func; |
2543 | case TOK_SHR: |
2544 | func = TOK___lshrdi3; |
2545 | goto gen_func; |
2546 | case TOK_SHL: |
2547 | func = TOK___ashldi3; |
2548 | goto gen_func; |
2549 | } |
2550 | } |
2551 | break; |
2552 | default: |
2553 | /* compare operations */ |
2554 | t = vtop->type.t; |
2555 | vswap(); |
2556 | lexpand(); |
2557 | vrotb(3); |
2558 | lexpand(); |
2559 | /* stack: L1 H1 L2 H2 */ |
2560 | tmp = vtop[-1]; |
2561 | vtop[-1] = vtop[-2]; |
2562 | vtop[-2] = tmp; |
2563 | /* stack: L1 L2 H1 H2 */ |
2564 | save_regs(4); |
2565 | /* compare high */ |
2566 | op1 = op; |
2567 | /* when values are equal, we need to compare low words. since |
2568 | the jump is inverted, we invert the test too. */ |
2569 | if (op1 == TOK_LT) |
2570 | op1 = TOK_LE; |
2571 | else if (op1 == TOK_GT) |
2572 | op1 = TOK_GE; |
2573 | else if (op1 == TOK_ULT) |
2574 | op1 = TOK_ULE; |
2575 | else if (op1 == TOK_UGT) |
2576 | op1 = TOK_UGE; |
2577 | a = 0; |
2578 | b = 0; |
2579 | gen_op(op1); |
2580 | if (op == TOK_NE) { |
2581 | b = gvtst(0, 0); |
2582 | } else { |
2583 | a = gvtst(1, 0); |
2584 | if (op != TOK_EQ) { |
2585 | /* generate non equal test */ |
2586 | vpushi(0); |
2587 | vset_VT_CMP(TOK_NE); |
2588 | b = gvtst(0, 0); |
2589 | } |
2590 | } |
2591 | /* compare low. Always unsigned */ |
2592 | op1 = op; |
2593 | if (op1 == TOK_LT) |
2594 | op1 = TOK_ULT; |
2595 | else if (op1 == TOK_LE) |
2596 | op1 = TOK_ULE; |
2597 | else if (op1 == TOK_GT) |
2598 | op1 = TOK_UGT; |
2599 | else if (op1 == TOK_GE) |
2600 | op1 = TOK_UGE; |
2601 | gen_op(op1); |
2602 | #if 0//def TCC_TARGET_I386 |
2603 | if (op == TOK_NE) { gsym(b); break; } |
2604 | if (op == TOK_EQ) { gsym(a); break; } |
2605 | #endif |
2606 | gvtst_set(1, a); |
2607 | gvtst_set(0, b); |
2608 | break; |
2609 | } |
2610 | } |
2611 | #endif |
2612 | |
2613 | static uint64_t gen_opic_sdiv(uint64_t a, uint64_t b) |
2614 | { |
2615 | uint64_t x = (a >> 63 ? -a : a) / (b >> 63 ? -b : b); |
2616 | return (a ^ b) >> 63 ? -x : x; |
2617 | } |
2618 | |
2619 | static int gen_opic_lt(uint64_t a, uint64_t b) |
2620 | { |
2621 | return (a ^ (uint64_t)1 << 63) < (b ^ (uint64_t)1 << 63); |
2622 | } |
2623 | |
2624 | /* handle integer constant optimizations and various machine |
2625 | independent opt */ |
2626 | static void gen_opic(int op) |
2627 | { |
2628 | SValue *v1 = vtop - 1; |
2629 | SValue *v2 = vtop; |
2630 | int t1 = v1->type.t & VT_BTYPE; |
2631 | int t2 = v2->type.t & VT_BTYPE; |
2632 | int c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; |
2633 | int c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; |
2634 | uint64_t l1 = c1 ? v1->c.i : 0; |
2635 | uint64_t l2 = c2 ? v2->c.i : 0; |
2636 | int shm = (t1 == VT_LLONG) ? 63 : 31; |
2637 | |
2638 | if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR)) |
2639 | l1 = ((uint32_t)l1 | |
2640 | (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000))); |
2641 | if (t2 != VT_LLONG && (PTR_SIZE != 8 || t2 != VT_PTR)) |
2642 | l2 = ((uint32_t)l2 | |
2643 | (v2->type.t & VT_UNSIGNED ? 0 : -(l2 & 0x80000000))); |
2644 | |
2645 | if (c1 && c2) { |
2646 | switch(op) { |
2647 | case '+': l1 += l2; break; |
2648 | case '-': l1 -= l2; break; |
2649 | case '&': l1 &= l2; break; |
2650 | case '^': l1 ^= l2; break; |
2651 | case '|': l1 |= l2; break; |
2652 | case '*': l1 *= l2; break; |
2653 | |
2654 | case TOK_PDIV: |
2655 | case '/': |
2656 | case '%': |
2657 | case TOK_UDIV: |
2658 | case TOK_UMOD: |
2659 | /* if division by zero, generate explicit division */ |
2660 | if (l2 == 0) { |
2661 | if (const_wanted && !(nocode_wanted & unevalmask)) |
2662 | tcc_error("division by zero in constant" ); |
2663 | goto general_case; |
2664 | } |
2665 | switch(op) { |
2666 | default: l1 = gen_opic_sdiv(l1, l2); break; |
2667 | case '%': l1 = l1 - l2 * gen_opic_sdiv(l1, l2); break; |
2668 | case TOK_UDIV: l1 = l1 / l2; break; |
2669 | case TOK_UMOD: l1 = l1 % l2; break; |
2670 | } |
2671 | break; |
2672 | case TOK_SHL: l1 <<= (l2 & shm); break; |
2673 | case TOK_SHR: l1 >>= (l2 & shm); break; |
2674 | case TOK_SAR: |
2675 | l1 = (l1 >> 63) ? ~(~l1 >> (l2 & shm)) : l1 >> (l2 & shm); |
2676 | break; |
2677 | /* tests */ |
2678 | case TOK_ULT: l1 = l1 < l2; break; |
2679 | case TOK_UGE: l1 = l1 >= l2; break; |
2680 | case TOK_EQ: l1 = l1 == l2; break; |
2681 | case TOK_NE: l1 = l1 != l2; break; |
2682 | case TOK_ULE: l1 = l1 <= l2; break; |
2683 | case TOK_UGT: l1 = l1 > l2; break; |
2684 | case TOK_LT: l1 = gen_opic_lt(l1, l2); break; |
2685 | case TOK_GE: l1 = !gen_opic_lt(l1, l2); break; |
2686 | case TOK_LE: l1 = !gen_opic_lt(l2, l1); break; |
2687 | case TOK_GT: l1 = gen_opic_lt(l2, l1); break; |
2688 | /* logical */ |
2689 | case TOK_LAND: l1 = l1 && l2; break; |
2690 | case TOK_LOR: l1 = l1 || l2; break; |
2691 | default: |
2692 | goto general_case; |
2693 | } |
2694 | if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR)) |
2695 | l1 = ((uint32_t)l1 | |
2696 | (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000))); |
2697 | v1->c.i = l1; |
2698 | vtop--; |
2699 | } else { |
2700 | /* if commutative ops, put c2 as constant */ |
2701 | if (c1 && (op == '+' || op == '&' || op == '^' || |
2702 | op == '|' || op == '*' || op == TOK_EQ || op == TOK_NE)) { |
2703 | vswap(); |
2704 | c2 = c1; //c = c1, c1 = c2, c2 = c; |
2705 | l2 = l1; //l = l1, l1 = l2, l2 = l; |
2706 | } |
2707 | if (!const_wanted && |
2708 | c1 && ((l1 == 0 && |
2709 | (op == TOK_SHL || op == TOK_SHR || op == TOK_SAR)) || |
2710 | (l1 == -1 && op == TOK_SAR))) { |
2711 | /* treat (0 << x), (0 >> x) and (-1 >> x) as constant */ |
2712 | vtop--; |
2713 | } else if (!const_wanted && |
2714 | c2 && ((l2 == 0 && (op == '&' || op == '*')) || |
2715 | (op == '|' && |
2716 | (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))) || |
2717 | (l2 == 1 && (op == '%' || op == TOK_UMOD)))) { |
2718 | /* treat (x & 0), (x * 0), (x | -1) and (x % 1) as constant */ |
2719 | if (l2 == 1) |
2720 | vtop->c.i = 0; |
2721 | vswap(); |
2722 | vtop--; |
2723 | } else if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV || |
2724 | op == TOK_PDIV) && |
2725 | l2 == 1) || |
2726 | ((op == '+' || op == '-' || op == '|' || op == '^' || |
2727 | op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) && |
2728 | l2 == 0) || |
2729 | (op == '&' && |
2730 | (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))))) { |
2731 | /* filter out NOP operations like x*1, x-0, x&-1... */ |
2732 | vtop--; |
2733 | } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) { |
2734 | /* try to use shifts instead of muls or divs */ |
2735 | if (l2 > 0 && (l2 & (l2 - 1)) == 0) { |
2736 | int n = -1; |
2737 | while (l2) { |
2738 | l2 >>= 1; |
2739 | n++; |
2740 | } |
2741 | vtop->c.i = n; |
2742 | if (op == '*') |
2743 | op = TOK_SHL; |
2744 | else if (op == TOK_PDIV) |
2745 | op = TOK_SAR; |
2746 | else |
2747 | op = TOK_SHR; |
2748 | } |
2749 | goto general_case; |
2750 | } else if (c2 && (op == '+' || op == '-') && |
2751 | (((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM)) |
2752 | || (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) { |
2753 | /* symbol + constant case */ |
2754 | if (op == '-') |
2755 | l2 = -l2; |
2756 | l2 += vtop[-1].c.i; |
2757 | /* The backends can't always deal with addends to symbols |
2758 | larger than +-1<<31. Don't construct such. */ |
2759 | if ((int)l2 != l2) |
2760 | goto general_case; |
2761 | vtop--; |
2762 | vtop->c.i = l2; |
2763 | } else { |
2764 | general_case: |
2765 | /* call low level op generator */ |
2766 | if (t1 == VT_LLONG || t2 == VT_LLONG || |
2767 | (PTR_SIZE == 8 && (t1 == VT_PTR || t2 == VT_PTR))) |
2768 | gen_opl(op); |
2769 | else |
2770 | gen_opi(op); |
2771 | } |
2772 | } |
2773 | } |
2774 | |
2775 | /* generate a floating point operation with constant propagation */ |
2776 | static void gen_opif(int op) |
2777 | { |
2778 | int c1, c2; |
2779 | SValue *v1, *v2; |
2780 | #if defined _MSC_VER && defined __x86_64__ |
2781 | /* avoid bad optimization with f1 -= f2 for f1:-0.0, f2:0.0 */ |
2782 | volatile |
2783 | #endif |
2784 | long double f1, f2; |
2785 | |
2786 | v1 = vtop - 1; |
2787 | v2 = vtop; |
2788 | /* currently, we cannot do computations with forward symbols */ |
2789 | c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; |
2790 | c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; |
2791 | if (c1 && c2) { |
2792 | if (v1->type.t == VT_FLOAT) { |
2793 | f1 = v1->c.f; |
2794 | f2 = v2->c.f; |
2795 | } else if (v1->type.t == VT_DOUBLE) { |
2796 | f1 = v1->c.d; |
2797 | f2 = v2->c.d; |
2798 | } else { |
2799 | f1 = v1->c.ld; |
2800 | f2 = v2->c.ld; |
2801 | } |
2802 | |
2803 | /* NOTE: we only do constant propagation if finite number (not |
2804 | NaN or infinity) (ANSI spec) */ |
2805 | if (!ieee_finite(f1) || !ieee_finite(f2)) |
2806 | goto general_case; |
2807 | |
2808 | switch(op) { |
2809 | case '+': f1 += f2; break; |
2810 | case '-': f1 -= f2; break; |
2811 | case '*': f1 *= f2; break; |
2812 | case '/': |
2813 | if (f2 == 0.0) { |
2814 | /* If not in initializer we need to potentially generate |
2815 | FP exceptions at runtime, otherwise we want to fold. */ |
2816 | if (!const_wanted) |
2817 | goto general_case; |
2818 | } |
2819 | f1 /= f2; |
2820 | break; |
2821 | /* XXX: also handles tests ? */ |
2822 | default: |
2823 | goto general_case; |
2824 | } |
2825 | /* XXX: overflow test ? */ |
2826 | if (v1->type.t == VT_FLOAT) { |
2827 | v1->c.f = f1; |
2828 | } else if (v1->type.t == VT_DOUBLE) { |
2829 | v1->c.d = f1; |
2830 | } else { |
2831 | v1->c.ld = f1; |
2832 | } |
2833 | vtop--; |
2834 | } else { |
2835 | general_case: |
2836 | gen_opf(op); |
2837 | } |
2838 | } |
2839 | |
2840 | /* print a type. If 'varstr' is not NULL, then the variable is also |
2841 | printed in the type */ |
2842 | /* XXX: union */ |
2843 | /* XXX: add array and function pointers */ |
2844 | static void type_to_str(char *buf, int buf_size, |
2845 | CType *type, const char *varstr) |
2846 | { |
2847 | int bt, v, t; |
2848 | Sym *s, *sa; |
2849 | char buf1[256]; |
2850 | const char *tstr; |
2851 | |
2852 | t = type->t; |
2853 | bt = t & VT_BTYPE; |
2854 | buf[0] = '\0'; |
2855 | |
2856 | if (t & VT_EXTERN) |
2857 | pstrcat(buf, buf_size, "extern " ); |
2858 | if (t & VT_STATIC) |
2859 | pstrcat(buf, buf_size, "static " ); |
2860 | if (t & VT_TYPEDEF) |
2861 | pstrcat(buf, buf_size, "typedef " ); |
2862 | if (t & VT_INLINE) |
2863 | pstrcat(buf, buf_size, "inline " ); |
2864 | if (t & VT_VOLATILE) |
2865 | pstrcat(buf, buf_size, "volatile " ); |
2866 | if (t & VT_CONSTANT) |
2867 | pstrcat(buf, buf_size, "const " ); |
2868 | |
2869 | if (((t & VT_DEFSIGN) && bt == VT_BYTE) |
2870 | || ((t & VT_UNSIGNED) |
2871 | && (bt == VT_SHORT || bt == VT_INT || bt == VT_LLONG) |
2872 | && !IS_ENUM(t) |
2873 | )) |
2874 | pstrcat(buf, buf_size, (t & VT_UNSIGNED) ? "unsigned " : "signed " ); |
2875 | |
2876 | buf_size -= strlen(buf); |
2877 | buf += strlen(buf); |
2878 | |
2879 | switch(bt) { |
2880 | case VT_VOID: |
2881 | tstr = "void" ; |
2882 | goto add_tstr; |
2883 | case VT_BOOL: |
2884 | tstr = "_Bool" ; |
2885 | goto add_tstr; |
2886 | case VT_BYTE: |
2887 | tstr = "char" ; |
2888 | goto add_tstr; |
2889 | case VT_SHORT: |
2890 | tstr = "short" ; |
2891 | goto add_tstr; |
2892 | case VT_INT: |
2893 | tstr = "int" ; |
2894 | goto maybe_long; |
2895 | case VT_LLONG: |
2896 | tstr = "long long" ; |
2897 | maybe_long: |
2898 | if (t & VT_LONG) |
2899 | tstr = "long" ; |
2900 | if (!IS_ENUM(t)) |
2901 | goto add_tstr; |
2902 | tstr = "enum " ; |
2903 | goto tstruct; |
2904 | case VT_FLOAT: |
2905 | tstr = "float" ; |
2906 | goto add_tstr; |
2907 | case VT_DOUBLE: |
2908 | tstr = "double" ; |
2909 | if (!(t & VT_LONG)) |
2910 | goto add_tstr; |
2911 | case VT_LDOUBLE: |
2912 | tstr = "long double" ; |
2913 | add_tstr: |
2914 | pstrcat(buf, buf_size, tstr); |
2915 | break; |
2916 | case VT_STRUCT: |
2917 | tstr = "struct " ; |
2918 | if (IS_UNION(t)) |
2919 | tstr = "union " ; |
2920 | tstruct: |
2921 | pstrcat(buf, buf_size, tstr); |
2922 | v = type->ref->v & ~SYM_STRUCT; |
2923 | if (v >= SYM_FIRST_ANOM) |
2924 | pstrcat(buf, buf_size, "<anonymous>" ); |
2925 | else |
2926 | pstrcat(buf, buf_size, get_tok_str(v, NULL)); |
2927 | break; |
2928 | case VT_FUNC: |
2929 | s = type->ref; |
2930 | buf1[0]=0; |
2931 | if (varstr && '*' == *varstr) { |
2932 | pstrcat(buf1, sizeof(buf1), "(" ); |
2933 | pstrcat(buf1, sizeof(buf1), varstr); |
2934 | pstrcat(buf1, sizeof(buf1), ")" ); |
2935 | } |
2936 | pstrcat(buf1, buf_size, "(" ); |
2937 | sa = s->next; |
2938 | while (sa != NULL) { |
2939 | char buf2[256]; |
2940 | type_to_str(buf2, sizeof(buf2), &sa->type, NULL); |
2941 | pstrcat(buf1, sizeof(buf1), buf2); |
2942 | sa = sa->next; |
2943 | if (sa) |
2944 | pstrcat(buf1, sizeof(buf1), ", " ); |
2945 | } |
2946 | if (s->f.func_type == FUNC_ELLIPSIS) |
2947 | pstrcat(buf1, sizeof(buf1), ", ..." ); |
2948 | pstrcat(buf1, sizeof(buf1), ")" ); |
2949 | type_to_str(buf, buf_size, &s->type, buf1); |
2950 | goto no_var; |
2951 | case VT_PTR: |
2952 | s = type->ref; |
2953 | if (t & VT_ARRAY) { |
2954 | if (varstr && '*' == *varstr) |
2955 | snprintf(buf1, sizeof(buf1), "(%s)[%d]" , varstr, s->c); |
2956 | else |
2957 | snprintf(buf1, sizeof(buf1), "%s[%d]" , varstr ? varstr : "" , s->c); |
2958 | type_to_str(buf, buf_size, &s->type, buf1); |
2959 | goto no_var; |
2960 | } |
2961 | pstrcpy(buf1, sizeof(buf1), "*" ); |
2962 | if (t & VT_CONSTANT) |
2963 | pstrcat(buf1, buf_size, "const " ); |
2964 | if (t & VT_VOLATILE) |
2965 | pstrcat(buf1, buf_size, "volatile " ); |
2966 | if (varstr) |
2967 | pstrcat(buf1, sizeof(buf1), varstr); |
2968 | type_to_str(buf, buf_size, &s->type, buf1); |
2969 | goto no_var; |
2970 | } |
2971 | if (varstr) { |
2972 | pstrcat(buf, buf_size, " " ); |
2973 | pstrcat(buf, buf_size, varstr); |
2974 | } |
2975 | no_var: ; |
2976 | } |
2977 | |
2978 | static void type_incompatibility_error(CType* st, CType* dt, const char* fmt) |
2979 | { |
2980 | char buf1[256], buf2[256]; |
2981 | type_to_str(buf1, sizeof(buf1), st, NULL); |
2982 | type_to_str(buf2, sizeof(buf2), dt, NULL); |
2983 | tcc_error(fmt, buf1, buf2); |
2984 | } |
2985 | |
2986 | static void type_incompatibility_warning(CType* st, CType* dt, const char* fmt) |
2987 | { |
2988 | char buf1[256], buf2[256]; |
2989 | type_to_str(buf1, sizeof(buf1), st, NULL); |
2990 | type_to_str(buf2, sizeof(buf2), dt, NULL); |
2991 | tcc_warning(fmt, buf1, buf2); |
2992 | } |
2993 | |
2994 | static int pointed_size(CType *type) |
2995 | { |
2996 | int align; |
2997 | return type_size(pointed_type(type), &align); |
2998 | } |
2999 | |
3000 | static void vla_runtime_pointed_size(CType *type) |
3001 | { |
3002 | int align; |
3003 | vla_runtime_type_size(pointed_type(type), &align); |
3004 | } |
3005 | |
3006 | static inline int is_null_pointer(SValue *p) |
3007 | { |
3008 | if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) |
3009 | return 0; |
3010 | return ((p->type.t & VT_BTYPE) == VT_INT && (uint32_t)p->c.i == 0) || |
3011 | ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.i == 0) || |
3012 | ((p->type.t & VT_BTYPE) == VT_PTR && |
3013 | (PTR_SIZE == 4 ? (uint32_t)p->c.i == 0 : p->c.i == 0) && |
3014 | ((pointed_type(&p->type)->t & VT_BTYPE) == VT_VOID) && |
3015 | 0 == (pointed_type(&p->type)->t & (VT_CONSTANT | VT_VOLATILE)) |
3016 | ); |
3017 | } |
3018 | |
3019 | /* compare function types. OLD functions match any new functions */ |
3020 | static int is_compatible_func(CType *type1, CType *type2) |
3021 | { |
3022 | Sym *s1, *s2; |
3023 | |
3024 | s1 = type1->ref; |
3025 | s2 = type2->ref; |
3026 | if (s1->f.func_call != s2->f.func_call) |
3027 | return 0; |
3028 | if (s1->f.func_type != s2->f.func_type |
3029 | && s1->f.func_type != FUNC_OLD |
3030 | && s2->f.func_type != FUNC_OLD) |
3031 | return 0; |
3032 | /* we should check the function return type for FUNC_OLD too |
3033 | but that causes problems with the internally used support |
3034 | functions such as TOK_memmove */ |
3035 | if (s1->f.func_type == FUNC_OLD && !s1->next) |
3036 | return 1; |
3037 | if (s2->f.func_type == FUNC_OLD && !s2->next) |
3038 | return 1; |
3039 | for (;;) { |
3040 | if (!is_compatible_unqualified_types(&s1->type, &s2->type)) |
3041 | return 0; |
3042 | s1 = s1->next; |
3043 | s2 = s2->next; |
3044 | if (!s1) |
3045 | return !s2; |
3046 | if (!s2) |
3047 | return 0; |
3048 | } |
3049 | } |
3050 | |
3051 | /* return true if type1 and type2 are the same. If unqualified is |
3052 | true, qualifiers on the types are ignored. |
3053 | */ |
3054 | static int compare_types(CType *type1, CType *type2, int unqualified) |
3055 | { |
3056 | int bt1, t1, t2; |
3057 | |
3058 | t1 = type1->t & VT_TYPE; |
3059 | t2 = type2->t & VT_TYPE; |
3060 | if (unqualified) { |
3061 | /* strip qualifiers before comparing */ |
3062 | t1 &= ~(VT_CONSTANT | VT_VOLATILE); |
3063 | t2 &= ~(VT_CONSTANT | VT_VOLATILE); |
3064 | } |
3065 | |
3066 | /* Default Vs explicit signedness only matters for char */ |
3067 | if ((t1 & VT_BTYPE) != VT_BYTE) { |
3068 | t1 &= ~VT_DEFSIGN; |
3069 | t2 &= ~VT_DEFSIGN; |
3070 | } |
3071 | /* XXX: bitfields ? */ |
3072 | if (t1 != t2) |
3073 | return 0; |
3074 | |
3075 | if ((t1 & VT_ARRAY) |
3076 | && !(type1->ref->c < 0 |
3077 | || type2->ref->c < 0 |
3078 | || type1->ref->c == type2->ref->c)) |
3079 | return 0; |
3080 | |
3081 | /* test more complicated cases */ |
3082 | bt1 = t1 & VT_BTYPE; |
3083 | if (bt1 == VT_PTR) { |
3084 | type1 = pointed_type(type1); |
3085 | type2 = pointed_type(type2); |
3086 | return is_compatible_types(type1, type2); |
3087 | } else if (bt1 == VT_STRUCT) { |
3088 | return (type1->ref == type2->ref); |
3089 | } else if (bt1 == VT_FUNC) { |
3090 | return is_compatible_func(type1, type2); |
3091 | } else if (IS_ENUM(type1->t) && IS_ENUM(type2->t)) { |
3092 | /* If both are enums then they must be the same, if only one is then |
3093 | t1 and t2 must be equal, which was checked above already. */ |
3094 | return type1->ref == type2->ref; |
3095 | } else { |
3096 | return 1; |
3097 | } |
3098 | } |
3099 | |
3100 | /* Check if OP1 and OP2 can be "combined" with operation OP, the combined |
3101 | type is stored in DEST if non-null (except for pointer plus/minus) . */ |
3102 | static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) |
3103 | { |
3104 | CType *type1 = &op1->type, *type2 = &op2->type, type; |
3105 | int t1 = type1->t, t2 = type2->t, bt1 = t1 & VT_BTYPE, bt2 = t2 & VT_BTYPE; |
3106 | int ret = 1; |
3107 | |
3108 | type.t = VT_VOID; |
3109 | type.ref = NULL; |
3110 | |
3111 | if (bt1 == VT_VOID || bt2 == VT_VOID) { |
3112 | ret = op == '?' ? 1 : 0; |
3113 | /* NOTE: as an extension, we accept void on only one side */ |
3114 | type.t = VT_VOID; |
3115 | } else if (bt1 == VT_PTR || bt2 == VT_PTR) { |
3116 | if (op == '+') ; /* Handled in caller */ |
3117 | /* http://port70.net/~nsz/c/c99/n1256.html#6.5.15p6 */ |
3118 | /* If one is a null ptr constant the result type is the other. */ |
3119 | else if (is_null_pointer (op2)) type = *type1; |
3120 | else if (is_null_pointer (op1)) type = *type2; |
3121 | else if (bt1 != bt2) { |
3122 | /* accept comparison or cond-expr between pointer and integer |
3123 | with a warning */ |
3124 | if ((op == '?' || TOK_ISCOND(op)) |
3125 | && (is_integer_btype(bt1) || is_integer_btype(bt2))) |
3126 | tcc_warning("pointer/integer mismatch in %s" , |
3127 | op == '?' ? "conditional expression" : "comparison" ); |
3128 | else if (op != '-' || !is_integer_btype(bt2)) |
3129 | ret = 0; |
3130 | type = *(bt1 == VT_PTR ? type1 : type2); |
3131 | } else { |
3132 | CType *pt1 = pointed_type(type1); |
3133 | CType *pt2 = pointed_type(type2); |
3134 | int pbt1 = pt1->t & VT_BTYPE; |
3135 | int pbt2 = pt2->t & VT_BTYPE; |
3136 | int newquals, copied = 0; |
3137 | if (pbt1 != VT_VOID && pbt2 != VT_VOID |
3138 | && !compare_types(pt1, pt2, 1/*unqualif*/)) { |
3139 | if (op != '?' && !TOK_ISCOND(op)) |
3140 | ret = 0; |
3141 | else |
3142 | type_incompatibility_warning(type1, type2, |
3143 | op == '?' |
3144 | ? "pointer type mismatch in conditional expression ('%s' and '%s')" |
3145 | : "pointer type mismatch in comparison('%s' and '%s')" ); |
3146 | } |
3147 | if (op == '?') { |
3148 | /* pointers to void get preferred, otherwise the |
3149 | pointed to types minus qualifs should be compatible */ |
3150 | type = *((pbt1 == VT_VOID) ? type1 : type2); |
3151 | /* combine qualifs */ |
3152 | newquals = ((pt1->t | pt2->t) & (VT_CONSTANT | VT_VOLATILE)); |
3153 | if ((~pointed_type(&type)->t & (VT_CONSTANT | VT_VOLATILE)) |
3154 | & newquals) |
3155 | { |
3156 | /* copy the pointer target symbol */ |
3157 | type.ref = sym_push(SYM_FIELD, &type.ref->type, |
3158 | 0, type.ref->c); |
3159 | copied = 1; |
3160 | pointed_type(&type)->t |= newquals; |
3161 | } |
3162 | /* pointers to incomplete arrays get converted to |
3163 | pointers to completed ones if possible */ |
3164 | if (pt1->t & VT_ARRAY |
3165 | && pt2->t & VT_ARRAY |
3166 | && pointed_type(&type)->ref->c < 0 |
3167 | && (pt1->ref->c > 0 || pt2->ref->c > 0)) |
3168 | { |
3169 | if (!copied) |
3170 | type.ref = sym_push(SYM_FIELD, &type.ref->type, |
3171 | 0, type.ref->c); |
3172 | pointed_type(&type)->ref = |
3173 | sym_push(SYM_FIELD, &pointed_type(&type)->ref->type, |
3174 | 0, pointed_type(&type)->ref->c); |
3175 | pointed_type(&type)->ref->c = |
3176 | 0 < pt1->ref->c ? pt1->ref->c : pt2->ref->c; |
3177 | } |
3178 | } |
3179 | } |
3180 | if (TOK_ISCOND(op)) |
3181 | type.t = VT_SIZE_T; |
3182 | } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) { |
3183 | if (op != '?' || !compare_types(type1, type2, 1)) |
3184 | ret = 0; |
3185 | type = *type1; |
3186 | } else if (is_float(bt1) || is_float(bt2)) { |
3187 | if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) { |
3188 | type.t = VT_LDOUBLE; |
3189 | } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) { |
3190 | type.t = VT_DOUBLE; |
3191 | } else { |
3192 | type.t = VT_FLOAT; |
3193 | } |
3194 | } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) { |
3195 | /* cast to biggest op */ |
3196 | type.t = VT_LLONG | VT_LONG; |
3197 | if (bt1 == VT_LLONG) |
3198 | type.t &= t1; |
3199 | if (bt2 == VT_LLONG) |
3200 | type.t &= t2; |
3201 | /* convert to unsigned if it does not fit in a long long */ |
3202 | if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED) || |
3203 | (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED)) |
3204 | type.t |= VT_UNSIGNED; |
3205 | } else { |
3206 | /* integer operations */ |
3207 | type.t = VT_INT | (VT_LONG & (t1 | t2)); |
3208 | /* convert to unsigned if it does not fit in an integer */ |
3209 | if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED) || |
3210 | (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED)) |
3211 | type.t |= VT_UNSIGNED; |
3212 | } |
3213 | if (dest) |
3214 | *dest = type; |
3215 | return ret; |
3216 | } |
3217 | |
3218 | /* generic gen_op: handles types problems */ |
3219 | ST_FUNC void gen_op(int op) |
3220 | { |
3221 | int u, t1, t2, bt1, bt2, t; |
3222 | CType type1, combtype; |
3223 | |
3224 | redo: |
3225 | t1 = vtop[-1].type.t; |
3226 | t2 = vtop[0].type.t; |
3227 | bt1 = t1 & VT_BTYPE; |
3228 | bt2 = t2 & VT_BTYPE; |
3229 | |
3230 | if (bt1 == VT_FUNC || bt2 == VT_FUNC) { |
3231 | if (bt2 == VT_FUNC) { |
3232 | mk_pointer(&vtop->type); |
3233 | gaddrof(); |
3234 | } |
3235 | if (bt1 == VT_FUNC) { |
3236 | vswap(); |
3237 | mk_pointer(&vtop->type); |
3238 | gaddrof(); |
3239 | vswap(); |
3240 | } |
3241 | goto redo; |
3242 | } else if (!combine_types(&combtype, vtop - 1, vtop, op)) { |
3243 | tcc_error_noabort("invalid operand types for binary operation" ); |
3244 | vpop(); |
3245 | } else if (bt1 == VT_PTR || bt2 == VT_PTR) { |
3246 | /* at least one operand is a pointer */ |
3247 | /* relational op: must be both pointers */ |
3248 | if (TOK_ISCOND(op)) |
3249 | goto std_op; |
3250 | /* if both pointers, then it must be the '-' op */ |
3251 | if (bt1 == VT_PTR && bt2 == VT_PTR) { |
3252 | if (op != '-') |
3253 | tcc_error("cannot use pointers here" ); |
3254 | if (vtop[-1].type.t & VT_VLA) { |
3255 | vla_runtime_pointed_size(&vtop[-1].type); |
3256 | } else { |
3257 | vpushi(pointed_size(&vtop[-1].type)); |
3258 | } |
3259 | vrott(3); |
3260 | gen_opic(op); |
3261 | vtop->type.t = VT_PTRDIFF_T; |
3262 | vswap(); |
3263 | gen_op(TOK_PDIV); |
3264 | } else { |
3265 | /* exactly one pointer : must be '+' or '-'. */ |
3266 | if (op != '-' && op != '+') |
3267 | tcc_error("cannot use pointers here" ); |
3268 | /* Put pointer as first operand */ |
3269 | if (bt2 == VT_PTR) { |
3270 | vswap(); |
3271 | t = t1, t1 = t2, t2 = t; |
3272 | } |
3273 | #if PTR_SIZE == 4 |
3274 | if ((vtop[0].type.t & VT_BTYPE) == VT_LLONG) |
3275 | /* XXX: truncate here because gen_opl can't handle ptr + long long */ |
3276 | gen_cast_s(VT_INT); |
3277 | #endif |
3278 | type1 = vtop[-1].type; |
3279 | if (vtop[-1].type.t & VT_VLA) |
3280 | vla_runtime_pointed_size(&vtop[-1].type); |
3281 | else { |
3282 | u = pointed_size(&vtop[-1].type); |
3283 | if (u < 0) |
3284 | tcc_error("unknown array element size" ); |
3285 | #if PTR_SIZE == 8 |
3286 | vpushll(u); |
3287 | #else |
3288 | /* XXX: cast to int ? (long long case) */ |
3289 | vpushi(u); |
3290 | #endif |
3291 | } |
3292 | gen_op('*'); |
3293 | #ifdef CONFIG_TCC_BCHECK |
3294 | if (tcc_state->do_bounds_check && !const_wanted) { |
3295 | /* if bounded pointers, we generate a special code to |
3296 | test bounds */ |
3297 | if (op == '-') { |
3298 | vpushi(0); |
3299 | vswap(); |
3300 | gen_op('-'); |
3301 | } |
3302 | gen_bounded_ptr_add(); |
3303 | } else |
3304 | #endif |
3305 | { |
3306 | gen_opic(op); |
3307 | } |
3308 | type1.t &= ~VT_ARRAY; |
3309 | /* put again type if gen_opic() swaped operands */ |
3310 | vtop->type = type1; |
3311 | } |
3312 | } else { |
3313 | /* floats can only be used for a few operations */ |
3314 | if (is_float(combtype.t) |
3315 | && op != '+' && op != '-' && op != '*' && op != '/' |
3316 | && !TOK_ISCOND(op)) |
3317 | tcc_error("invalid operands for binary operation" ); |
3318 | else if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL) { |
3319 | t = bt1 == VT_LLONG ? VT_LLONG : VT_INT; |
3320 | if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (t | VT_UNSIGNED)) |
3321 | t |= VT_UNSIGNED; |
3322 | t |= (VT_LONG & t1); |
3323 | combtype.t = t; |
3324 | } |
3325 | std_op: |
3326 | t = t2 = combtype.t; |
3327 | /* XXX: currently, some unsigned operations are explicit, so |
3328 | we modify them here */ |
3329 | if (t & VT_UNSIGNED) { |
3330 | if (op == TOK_SAR) |
3331 | op = TOK_SHR; |
3332 | else if (op == '/') |
3333 | op = TOK_UDIV; |
3334 | else if (op == '%') |
3335 | op = TOK_UMOD; |
3336 | else if (op == TOK_LT) |
3337 | op = TOK_ULT; |
3338 | else if (op == TOK_GT) |
3339 | op = TOK_UGT; |
3340 | else if (op == TOK_LE) |
3341 | op = TOK_ULE; |
3342 | else if (op == TOK_GE) |
3343 | op = TOK_UGE; |
3344 | } |
3345 | vswap(); |
3346 | gen_cast_s(t); |
3347 | vswap(); |
3348 | /* special case for shifts and long long: we keep the shift as |
3349 | an integer */ |
3350 | if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL) |
3351 | t2 = VT_INT; |
3352 | gen_cast_s(t2); |
3353 | if (is_float(t)) |
3354 | gen_opif(op); |
3355 | else |
3356 | gen_opic(op); |
3357 | if (TOK_ISCOND(op)) { |
3358 | /* relational op: the result is an int */ |
3359 | vtop->type.t = VT_INT; |
3360 | } else { |
3361 | vtop->type.t = t; |
3362 | } |
3363 | } |
3364 | // Make sure that we have converted to an rvalue: |
3365 | if (vtop->r & VT_LVAL) |
3366 | gv(is_float(vtop->type.t & VT_BTYPE) ? RC_FLOAT : RC_INT); |
3367 | } |
3368 | |
3369 | #if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64 || defined TCC_TARGET_ARM |
3370 | #define gen_cvt_itof1 gen_cvt_itof |
3371 | #else |
3372 | /* generic itof for unsigned long long case */ |
3373 | static void gen_cvt_itof1(int t) |
3374 | { |
3375 | if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == |
3376 | (VT_LLONG | VT_UNSIGNED)) { |
3377 | |
3378 | if (t == VT_FLOAT) |
3379 | vpush_global_sym(&func_old_type, TOK___floatundisf); |
3380 | #if LDOUBLE_SIZE != 8 |
3381 | else if (t == VT_LDOUBLE) |
3382 | vpush_global_sym(&func_old_type, TOK___floatundixf); |
3383 | #endif |
3384 | else |
3385 | vpush_global_sym(&func_old_type, TOK___floatundidf); |
3386 | vrott(2); |
3387 | gfunc_call(1); |
3388 | vpushi(0); |
3389 | PUT_R_RET(vtop, t); |
3390 | } else { |
3391 | gen_cvt_itof(t); |
3392 | } |
3393 | } |
3394 | #endif |
3395 | |
3396 | #if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64 |
3397 | #define gen_cvt_ftoi1 gen_cvt_ftoi |
3398 | #else |
3399 | /* generic ftoi for unsigned long long case */ |
3400 | static void gen_cvt_ftoi1(int t) |
3401 | { |
3402 | int st; |
3403 | if (t == (VT_LLONG | VT_UNSIGNED)) { |
3404 | /* not handled natively */ |
3405 | st = vtop->type.t & VT_BTYPE; |
3406 | if (st == VT_FLOAT) |
3407 | vpush_global_sym(&func_old_type, TOK___fixunssfdi); |
3408 | #if LDOUBLE_SIZE != 8 |
3409 | else if (st == VT_LDOUBLE) |
3410 | vpush_global_sym(&func_old_type, TOK___fixunsxfdi); |
3411 | #endif |
3412 | else |
3413 | vpush_global_sym(&func_old_type, TOK___fixunsdfdi); |
3414 | vrott(2); |
3415 | gfunc_call(1); |
3416 | vpushi(0); |
3417 | PUT_R_RET(vtop, t); |
3418 | } else { |
3419 | gen_cvt_ftoi(t); |
3420 | } |
3421 | } |
3422 | #endif |
3423 | |
3424 | /* special delayed cast for char/short */ |
3425 | static void force_charshort_cast(void) |
3426 | { |
3427 | int sbt = BFGET(vtop->r, VT_MUSTCAST) == 2 ? VT_LLONG : VT_INT; |
3428 | int dbt = vtop->type.t; |
3429 | vtop->r &= ~VT_MUSTCAST; |
3430 | vtop->type.t = sbt; |
3431 | gen_cast_s(dbt == VT_BOOL ? VT_BYTE|VT_UNSIGNED : dbt); |
3432 | vtop->type.t = dbt; |
3433 | } |
3434 | |
3435 | static void gen_cast_s(int t) |
3436 | { |
3437 | CType type; |
3438 | type.t = t; |
3439 | type.ref = NULL; |
3440 | gen_cast(&type); |
3441 | } |
3442 | |
3443 | /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */ |
3444 | static void gen_cast(CType *type) |
3445 | { |
3446 | int sbt, dbt, sf, df, c; |
3447 | int dbt_bt, sbt_bt, ds, ss, bits, trunc; |
3448 | |
3449 | /* special delayed cast for char/short */ |
3450 | if (vtop->r & VT_MUSTCAST) |
3451 | force_charshort_cast(); |
3452 | |
3453 | /* bitfields first get cast to ints */ |
3454 | if (vtop->type.t & VT_BITFIELD) |
3455 | gv(RC_INT); |
3456 | |
3457 | dbt = type->t & (VT_BTYPE | VT_UNSIGNED); |
3458 | sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); |
3459 | if (sbt == VT_FUNC) |
3460 | sbt = VT_PTR; |
3461 | |
3462 | again: |
3463 | if (sbt != dbt) { |
3464 | sf = is_float(sbt); |
3465 | df = is_float(dbt); |
3466 | dbt_bt = dbt & VT_BTYPE; |
3467 | sbt_bt = sbt & VT_BTYPE; |
3468 | |
3469 | c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; |
3470 | #if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_387 |
3471 | c &= (dbt != VT_LDOUBLE) | !!nocode_wanted; |
3472 | #endif |
3473 | if (c) { |
3474 | /* constant case: we can do it now */ |
3475 | /* XXX: in ISOC, cannot do it if error in convert */ |
3476 | if (sbt == VT_FLOAT) |
3477 | vtop->c.ld = vtop->c.f; |
3478 | else if (sbt == VT_DOUBLE) |
3479 | vtop->c.ld = vtop->c.d; |
3480 | |
3481 | if (df) { |
3482 | if (sbt_bt == VT_LLONG) { |
3483 | if ((sbt & VT_UNSIGNED) || !(vtop->c.i >> 63)) |
3484 | vtop->c.ld = vtop->c.i; |
3485 | else |
3486 | vtop->c.ld = -(long double)-vtop->c.i; |
3487 | } else if(!sf) { |
3488 | if ((sbt & VT_UNSIGNED) || !(vtop->c.i >> 31)) |
3489 | vtop->c.ld = (uint32_t)vtop->c.i; |
3490 | else |
3491 | vtop->c.ld = -(long double)-(uint32_t)vtop->c.i; |
3492 | } |
3493 | |
3494 | if (dbt == VT_FLOAT) |
3495 | vtop->c.f = (float)vtop->c.ld; |
3496 | else if (dbt == VT_DOUBLE) |
3497 | vtop->c.d = (double)vtop->c.ld; |
3498 | } else if (sf && dbt == VT_BOOL) { |
3499 | vtop->c.i = (vtop->c.ld != 0); |
3500 | } else { |
3501 | if(sf) |
3502 | vtop->c.i = vtop->c.ld; |
3503 | else if (sbt_bt == VT_LLONG || (PTR_SIZE == 8 && sbt == VT_PTR)) |
3504 | ; |
3505 | else if (sbt & VT_UNSIGNED) |
3506 | vtop->c.i = (uint32_t)vtop->c.i; |
3507 | else |
3508 | vtop->c.i = ((uint32_t)vtop->c.i | -(vtop->c.i & 0x80000000)); |
3509 | |
3510 | if (dbt_bt == VT_LLONG || (PTR_SIZE == 8 && dbt == VT_PTR)) |
3511 | ; |
3512 | else if (dbt == VT_BOOL) |
3513 | vtop->c.i = (vtop->c.i != 0); |
3514 | else { |
3515 | uint32_t m = dbt_bt == VT_BYTE ? 0xff : |
3516 | dbt_bt == VT_SHORT ? 0xffff : |
3517 | 0xffffffff; |
3518 | vtop->c.i &= m; |
3519 | if (!(dbt & VT_UNSIGNED)) |
3520 | vtop->c.i |= -(vtop->c.i & ((m >> 1) + 1)); |
3521 | } |
3522 | } |
3523 | goto done; |
3524 | |
3525 | } else if (dbt == VT_BOOL |
3526 | && (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) |
3527 | == (VT_CONST | VT_SYM)) { |
3528 | /* addresses are considered non-zero (see tcctest.c:sinit23) */ |
3529 | vtop->r = VT_CONST; |
3530 | vtop->c.i = 1; |
3531 | goto done; |
3532 | } |
3533 | |
3534 | /* cannot generate code for global or static initializers */ |
3535 | if (STATIC_DATA_WANTED) |
3536 | goto done; |
3537 | |
3538 | /* non constant case: generate code */ |
3539 | if (dbt == VT_BOOL) { |
3540 | gen_test_zero(TOK_NE); |
3541 | goto done; |
3542 | } |
3543 | |
3544 | if (sf || df) { |
3545 | if (sf && df) { |
3546 | /* convert from fp to fp */ |
3547 | gen_cvt_ftof(dbt); |
3548 | } else if (df) { |
3549 | /* convert int to fp */ |
3550 | gen_cvt_itof1(dbt); |
3551 | } else { |
3552 | /* convert fp to int */ |
3553 | sbt = dbt; |
3554 | if (dbt_bt != VT_LLONG && dbt_bt != VT_INT) |
3555 | sbt = VT_INT; |
3556 | gen_cvt_ftoi1(sbt); |
3557 | goto again; /* may need char/short cast */ |
3558 | } |
3559 | goto done; |
3560 | } |
3561 | |
3562 | ds = btype_size(dbt_bt); |
3563 | ss = btype_size(sbt_bt); |
3564 | if (ds == 0 || ss == 0) { |
3565 | if (dbt_bt == VT_VOID) |
3566 | goto done; |
3567 | cast_error(&vtop->type, type); |
3568 | } |
3569 | if (IS_ENUM(type->t) && type->ref->c < 0) |
3570 | tcc_error("cast to incomplete type" ); |
3571 | |
3572 | /* same size and no sign conversion needed */ |
3573 | if (ds == ss && ds >= 4) |
3574 | goto done; |
3575 | if (dbt_bt == VT_PTR || sbt_bt == VT_PTR) { |
3576 | tcc_warning("cast between pointer and integer of different size" ); |
3577 | if (sbt_bt == VT_PTR) { |
3578 | /* put integer type to allow logical operations below */ |
3579 | vtop->type.t = (PTR_SIZE == 8 ? VT_LLONG : VT_INT); |
3580 | } |
3581 | } |
3582 | |
3583 | /* processor allows { int a = 0, b = *(char*)&a; } |
3584 | That means that if we cast to less width, we can just |
3585 | change the type and read it still later. */ |
3586 | #define ALLOW_SUBTYPE_ACCESS 1 |
3587 | |
3588 | if (ALLOW_SUBTYPE_ACCESS && (vtop->r & VT_LVAL)) { |
3589 | /* value still in memory */ |
3590 | if (ds <= ss) |
3591 | goto done; |
3592 | /* ss <= 4 here */ |
3593 | if (ds <= 4 && !(dbt == (VT_SHORT | VT_UNSIGNED) && sbt == VT_BYTE)) { |
3594 | gv(RC_INT); |
3595 | goto done; /* no 64bit envolved */ |
3596 | } |
3597 | } |
3598 | gv(RC_INT); |
3599 | |
3600 | trunc = 0; |
3601 | #if PTR_SIZE == 4 |
3602 | if (ds == 8) { |
3603 | /* generate high word */ |
3604 | if (sbt & VT_UNSIGNED) { |
3605 | vpushi(0); |
3606 | gv(RC_INT); |
3607 | } else { |
3608 | gv_dup(); |
3609 | vpushi(31); |
3610 | gen_op(TOK_SAR); |
3611 | } |
3612 | lbuild(dbt); |
3613 | } else if (ss == 8) { |
3614 | /* from long long: just take low order word */ |
3615 | lexpand(); |
3616 | vpop(); |
3617 | } |
3618 | ss = 4; |
3619 | |
3620 | #elif PTR_SIZE == 8 |
3621 | if (ds == 8) { |
3622 | /* need to convert from 32bit to 64bit */ |
3623 | if (sbt & VT_UNSIGNED) { |
3624 | #if defined(TCC_TARGET_RISCV64) |
3625 | /* RISC-V keeps 32bit vals in registers sign-extended. |
3626 | So here we need a zero-extension. */ |
3627 | trunc = 32; |
3628 | #else |
3629 | goto done; |
3630 | #endif |
3631 | } else { |
3632 | gen_cvt_sxtw(); |
3633 | goto done; |
3634 | } |
3635 | ss = ds, ds = 4, dbt = sbt; |
3636 | } else if (ss == 8) { |
3637 | /* RISC-V keeps 32bit vals in registers sign-extended. |
3638 | So here we need a sign-extension for signed types and |
3639 | zero-extension. for unsigned types. */ |
3640 | #if !defined(TCC_TARGET_RISCV64) |
3641 | trunc = 32; /* zero upper 32 bits for non RISC-V targets */ |
3642 | #endif |
3643 | } else { |
3644 | ss = 4; |
3645 | } |
3646 | #endif |
3647 | |
3648 | if (ds >= ss) |
3649 | goto done; |
3650 | #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64 |
3651 | if (ss == 4) { |
3652 | gen_cvt_csti(dbt); |
3653 | goto done; |
3654 | } |
3655 | #endif |
3656 | bits = (ss - ds) * 8; |
3657 | /* for unsigned, gen_op will convert SAR to SHR */ |
3658 | vtop->type.t = (ss == 8 ? VT_LLONG : VT_INT) | (dbt & VT_UNSIGNED); |
3659 | vpushi(bits); |
3660 | gen_op(TOK_SHL); |
3661 | vpushi(bits - trunc); |
3662 | gen_op(TOK_SAR); |
3663 | vpushi(trunc); |
3664 | gen_op(TOK_SHR); |
3665 | } |
3666 | done: |
3667 | vtop->type = *type; |
3668 | vtop->type.t &= ~ ( VT_CONSTANT | VT_VOLATILE | VT_ARRAY ); |
3669 | } |
3670 | |
3671 | /* return type size as known at compile time. Put alignment at 'a' */ |
3672 | ST_FUNC int type_size(CType *type, int *a) |
3673 | { |
3674 | Sym *s; |
3675 | int bt; |
3676 | |
3677 | bt = type->t & VT_BTYPE; |
3678 | if (bt == VT_STRUCT) { |
3679 | /* struct/union */ |
3680 | s = type->ref; |
3681 | *a = s->r; |
3682 | return s->c; |
3683 | } else if (bt == VT_PTR) { |
3684 | if (type->t & VT_ARRAY) { |
3685 | int ts; |
3686 | |
3687 | s = type->ref; |
3688 | ts = type_size(&s->type, a); |
3689 | |
3690 | if (ts < 0 && s->c < 0) |
3691 | ts = -ts; |
3692 | |
3693 | return ts * s->c; |
3694 | } else { |
3695 | *a = PTR_SIZE; |
3696 | return PTR_SIZE; |
3697 | } |
3698 | } else if (IS_ENUM(type->t) && type->ref->c < 0) { |
3699 | return -1; /* incomplete enum */ |
3700 | } else if (bt == VT_LDOUBLE) { |
3701 | *a = LDOUBLE_ALIGN; |
3702 | return LDOUBLE_SIZE; |
3703 | } else if (bt == VT_DOUBLE || bt == VT_LLONG) { |
3704 | #ifdef TCC_TARGET_I386 |
3705 | #ifdef TCC_TARGET_PE |
3706 | *a = 8; |
3707 | #else |
3708 | *a = 4; |
3709 | #endif |
3710 | #elif defined(TCC_TARGET_ARM) |
3711 | #ifdef TCC_ARM_EABI |
3712 | *a = 8; |
3713 | #else |
3714 | *a = 4; |
3715 | #endif |
3716 | #else |
3717 | *a = 8; |
3718 | #endif |
3719 | return 8; |
3720 | } else if (bt == VT_INT || bt == VT_FLOAT) { |
3721 | *a = 4; |
3722 | return 4; |
3723 | } else if (bt == VT_SHORT) { |
3724 | *a = 2; |
3725 | return 2; |
3726 | } else if (bt == VT_QLONG || bt == VT_QFLOAT) { |
3727 | *a = 8; |
3728 | return 16; |
3729 | } else { |
3730 | /* char, void, function, _Bool */ |
3731 | *a = 1; |
3732 | return 1; |
3733 | } |
3734 | } |
3735 | |
3736 | /* push type size as known at runtime time on top of value stack. Put |
3737 | alignment at 'a' */ |
3738 | ST_FUNC void vla_runtime_type_size(CType *type, int *a) |
3739 | { |
3740 | if (type->t & VT_VLA) { |
3741 | type_size(&type->ref->type, a); |
3742 | vset(&int_type, VT_LOCAL|VT_LVAL, type->ref->c); |
3743 | } else { |
3744 | vpushi(type_size(type, a)); |
3745 | } |
3746 | } |
3747 | |
3748 | /* return the pointed type of t */ |
3749 | static inline CType *pointed_type(CType *type) |
3750 | { |
3751 | return &type->ref->type; |
3752 | } |
3753 | |
3754 | /* modify type so that its it is a pointer to type. */ |
3755 | ST_FUNC void mk_pointer(CType *type) |
3756 | { |
3757 | Sym *s; |
3758 | s = sym_push(SYM_FIELD, type, 0, -1); |
3759 | type->t = VT_PTR | (type->t & VT_STORAGE); |
3760 | type->ref = s; |
3761 | } |
3762 | |
3763 | /* return true if type1 and type2 are exactly the same (including |
3764 | qualifiers). |
3765 | */ |
3766 | static int is_compatible_types(CType *type1, CType *type2) |
3767 | { |
3768 | return compare_types(type1,type2,0); |
3769 | } |
3770 | |
3771 | /* return true if type1 and type2 are the same (ignoring qualifiers). |
3772 | */ |
3773 | static int is_compatible_unqualified_types(CType *type1, CType *type2) |
3774 | { |
3775 | return compare_types(type1,type2,1); |
3776 | } |
3777 | |
3778 | static void cast_error(CType *st, CType *dt) |
3779 | { |
3780 | type_incompatibility_error(st, dt, "cannot convert '%s' to '%s'" ); |
3781 | } |
3782 | |
3783 | /* verify type compatibility to store vtop in 'dt' type */ |
3784 | static void verify_assign_cast(CType *dt) |
3785 | { |
3786 | CType *st, *type1, *type2; |
3787 | int dbt, sbt, qualwarn, lvl; |
3788 | |
3789 | st = &vtop->type; /* source type */ |
3790 | dbt = dt->t & VT_BTYPE; |
3791 | sbt = st->t & VT_BTYPE; |
3792 | if (dt->t & VT_CONSTANT) |
3793 | tcc_warning("assignment of read-only location" ); |
3794 | switch(dbt) { |
3795 | case VT_VOID: |
3796 | if (sbt != dbt) |
3797 | tcc_error("assignment to void expression" ); |
3798 | break; |
3799 | case VT_PTR: |
3800 | /* special cases for pointers */ |
3801 | /* '0' can also be a pointer */ |
3802 | if (is_null_pointer(vtop)) |
3803 | break; |
3804 | /* accept implicit pointer to integer cast with warning */ |
3805 | if (is_integer_btype(sbt)) { |
3806 | tcc_warning("assignment makes pointer from integer without a cast" ); |
3807 | break; |
3808 | } |
3809 | type1 = pointed_type(dt); |
3810 | if (sbt == VT_PTR) |
3811 | type2 = pointed_type(st); |
3812 | else if (sbt == VT_FUNC) |
3813 | type2 = st; /* a function is implicitly a function pointer */ |
3814 | else |
3815 | goto error; |
3816 | if (is_compatible_types(type1, type2)) |
3817 | break; |
3818 | for (qualwarn = lvl = 0;; ++lvl) { |
3819 | if (((type2->t & VT_CONSTANT) && !(type1->t & VT_CONSTANT)) || |
3820 | ((type2->t & VT_VOLATILE) && !(type1->t & VT_VOLATILE))) |
3821 | qualwarn = 1; |
3822 | dbt = type1->t & (VT_BTYPE|VT_LONG); |
3823 | sbt = type2->t & (VT_BTYPE|VT_LONG); |
3824 | if (dbt != VT_PTR || sbt != VT_PTR) |
3825 | break; |
3826 | type1 = pointed_type(type1); |
3827 | type2 = pointed_type(type2); |
3828 | } |
3829 | if (!is_compatible_unqualified_types(type1, type2)) { |
3830 | if ((dbt == VT_VOID || sbt == VT_VOID) && lvl == 0) { |
3831 | /* void * can match anything */ |
3832 | } else if (dbt == sbt |
3833 | && is_integer_btype(sbt & VT_BTYPE) |
3834 | && IS_ENUM(type1->t) + IS_ENUM(type2->t) |
3835 | + !!((type1->t ^ type2->t) & VT_UNSIGNED) < 2) { |
3836 | /* Like GCC don't warn by default for merely changes |
3837 | in pointer target signedness. Do warn for different |
3838 | base types, though, in particular for unsigned enums |
3839 | and signed int targets. */ |
3840 | } else { |
3841 | tcc_warning("assignment from incompatible pointer type" ); |
3842 | break; |
3843 | } |
3844 | } |
3845 | if (qualwarn) |
3846 | tcc_warning("assignment discards qualifiers from pointer target type" ); |
3847 | break; |
3848 | case VT_BYTE: |
3849 | case VT_SHORT: |
3850 | case VT_INT: |
3851 | case VT_LLONG: |
3852 | if (sbt == VT_PTR || sbt == VT_FUNC) { |
3853 | tcc_warning("assignment makes integer from pointer without a cast" ); |
3854 | } else if (sbt == VT_STRUCT) { |
3855 | goto case_VT_STRUCT; |
3856 | } |
3857 | /* XXX: more tests */ |
3858 | break; |
3859 | case VT_STRUCT: |
3860 | case_VT_STRUCT: |
3861 | if (!is_compatible_unqualified_types(dt, st)) { |
3862 | error: |
3863 | cast_error(st, dt); |
3864 | } |
3865 | break; |
3866 | } |
3867 | } |
3868 | |
3869 | static void gen_assign_cast(CType *dt) |
3870 | { |
3871 | verify_assign_cast(dt); |
3872 | gen_cast(dt); |
3873 | } |
3874 | |
3875 | /* store vtop in lvalue pushed on stack */ |
3876 | ST_FUNC void vstore(void) |
3877 | { |
3878 | int sbt, dbt, ft, r, size, align, bit_size, bit_pos, delayed_cast; |
3879 | |
3880 | ft = vtop[-1].type.t; |
3881 | sbt = vtop->type.t & VT_BTYPE; |
3882 | dbt = ft & VT_BTYPE; |
3883 | |
3884 | verify_assign_cast(&vtop[-1].type); |
3885 | |
3886 | if (sbt == VT_STRUCT) { |
3887 | /* if structure, only generate pointer */ |
3888 | /* structure assignment : generate memcpy */ |
3889 | /* XXX: optimize if small size */ |
3890 | size = type_size(&vtop->type, &align); |
3891 | |
3892 | /* destination */ |
3893 | vswap(); |
3894 | #ifdef CONFIG_TCC_BCHECK |
3895 | if (vtop->r & VT_MUSTBOUND) |
3896 | gbound(); /* check would be wrong after gaddrof() */ |
3897 | #endif |
3898 | vtop->type.t = VT_PTR; |
3899 | gaddrof(); |
3900 | |
3901 | /* address of memcpy() */ |
3902 | #ifdef TCC_ARM_EABI |
3903 | if(!(align & 7)) |
3904 | vpush_global_sym(&func_old_type, TOK_memmove8); |
3905 | else if(!(align & 3)) |
3906 | vpush_global_sym(&func_old_type, TOK_memmove4); |
3907 | else |
3908 | #endif |
3909 | /* Use memmove, rather than memcpy, as dest and src may be same: */ |
3910 | vpush_global_sym(&func_old_type, TOK_memmove); |
3911 | |
3912 | vswap(); |
3913 | /* source */ |
3914 | vpushv(vtop - 2); |
3915 | #ifdef CONFIG_TCC_BCHECK |
3916 | if (vtop->r & VT_MUSTBOUND) |
3917 | gbound(); |
3918 | #endif |
3919 | vtop->type.t = VT_PTR; |
3920 | gaddrof(); |
3921 | /* type size */ |
3922 | vpushi(size); |
3923 | gfunc_call(3); |
3924 | /* leave source on stack */ |
3925 | |
3926 | } else if (ft & VT_BITFIELD) { |
3927 | /* bitfield store handling */ |
3928 | |
3929 | /* save lvalue as expression result (example: s.b = s.a = n;) */ |
3930 | vdup(), vtop[-1] = vtop[-2]; |
3931 | |
3932 | bit_pos = BIT_POS(ft); |
3933 | bit_size = BIT_SIZE(ft); |
3934 | /* remove bit field info to avoid loops */ |
3935 | vtop[-1].type.t = ft & ~VT_STRUCT_MASK; |
3936 | |
3937 | if (dbt == VT_BOOL) { |
3938 | gen_cast(&vtop[-1].type); |
3939 | vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED); |
3940 | } |
3941 | r = adjust_bf(vtop - 1, bit_pos, bit_size); |
3942 | if (dbt != VT_BOOL) { |
3943 | gen_cast(&vtop[-1].type); |
3944 | dbt = vtop[-1].type.t & VT_BTYPE; |
3945 | } |
3946 | if (r == VT_STRUCT) { |
3947 | store_packed_bf(bit_pos, bit_size); |
3948 | } else { |
3949 | unsigned long long mask = (1ULL << bit_size) - 1; |
3950 | if (dbt != VT_BOOL) { |
3951 | /* mask source */ |
3952 | if (dbt == VT_LLONG) |
3953 | vpushll(mask); |
3954 | else |
3955 | vpushi((unsigned)mask); |
3956 | gen_op('&'); |
3957 | } |
3958 | /* shift source */ |
3959 | vpushi(bit_pos); |
3960 | gen_op(TOK_SHL); |
3961 | vswap(); |
3962 | /* duplicate destination */ |
3963 | vdup(); |
3964 | vrott(3); |
3965 | /* load destination, mask and or with source */ |
3966 | if (dbt == VT_LLONG) |
3967 | vpushll(~(mask << bit_pos)); |
3968 | else |
3969 | vpushi(~((unsigned)mask << bit_pos)); |
3970 | gen_op('&'); |
3971 | gen_op('|'); |
3972 | /* store result */ |
3973 | vstore(); |
3974 | /* ... and discard */ |
3975 | vpop(); |
3976 | } |
3977 | } else if (dbt == VT_VOID) { |
3978 | --vtop; |
3979 | } else { |
3980 | /* optimize char/short casts */ |
3981 | delayed_cast = 0; |
3982 | if ((dbt == VT_BYTE || dbt == VT_SHORT) |
3983 | && is_integer_btype(sbt) |
3984 | ) { |
3985 | if ((vtop->r & VT_MUSTCAST) |
3986 | && btype_size(dbt) > btype_size(sbt) |
3987 | ) |
3988 | force_charshort_cast(); |
3989 | delayed_cast = 1; |
3990 | } else { |
3991 | gen_cast(&vtop[-1].type); |
3992 | } |
3993 | |
3994 | #ifdef CONFIG_TCC_BCHECK |
3995 | /* bound check case */ |
3996 | if (vtop[-1].r & VT_MUSTBOUND) { |
3997 | vswap(); |
3998 | gbound(); |
3999 | vswap(); |
4000 | } |
4001 | #endif |
4002 | gv(RC_TYPE(dbt)); /* generate value */ |
4003 | |
4004 | if (delayed_cast) { |
4005 | vtop->r |= BFVAL(VT_MUSTCAST, (sbt == VT_LLONG) + 1); |
4006 | //tcc_warning("deley cast %x -> %x", sbt, dbt); |
4007 | vtop->type.t = ft & VT_TYPE; |
4008 | } |
4009 | |
4010 | /* if lvalue was saved on stack, must read it */ |
4011 | if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) { |
4012 | SValue sv; |
4013 | r = get_reg(RC_INT); |
4014 | sv.type.t = VT_PTRDIFF_T; |
4015 | sv.r = VT_LOCAL | VT_LVAL; |
4016 | sv.c.i = vtop[-1].c.i; |
4017 | load(r, &sv); |
4018 | vtop[-1].r = r | VT_LVAL; |
4019 | } |
4020 | |
4021 | r = vtop->r & VT_VALMASK; |
4022 | /* two word case handling : |
4023 | store second register at word + 4 (or +8 for x86-64) */ |
4024 | if (USING_TWO_WORDS(dbt)) { |
4025 | int load_type = (dbt == VT_QFLOAT) ? VT_DOUBLE : VT_PTRDIFF_T; |
4026 | vtop[-1].type.t = load_type; |
4027 | store(r, vtop - 1); |
4028 | vswap(); |
4029 | /* convert to int to increment easily */ |
4030 | vtop->type.t = VT_PTRDIFF_T; |
4031 | gaddrof(); |
4032 | vpushs(PTR_SIZE); |
4033 | gen_op('+'); |
4034 | vtop->r |= VT_LVAL; |
4035 | vswap(); |
4036 | vtop[-1].type.t = load_type; |
4037 | /* XXX: it works because r2 is spilled last ! */ |
4038 | store(vtop->r2, vtop - 1); |
4039 | } else { |
4040 | /* single word */ |
4041 | store(r, vtop - 1); |
4042 | } |
4043 | vswap(); |
4044 | vtop--; /* NOT vpop() because on x86 it would flush the fp stack */ |
4045 | } |
4046 | } |
4047 | |
4048 | /* post defines POST/PRE add. c is the token ++ or -- */ |
4049 | ST_FUNC void inc(int post, int c) |
4050 | { |
4051 | test_lvalue(); |
4052 | vdup(); /* save lvalue */ |
4053 | if (post) { |
4054 | gv_dup(); /* duplicate value */ |
4055 | vrotb(3); |
4056 | vrotb(3); |
4057 | } |
4058 | /* add constant */ |
4059 | vpushi(c - TOK_MID); |
4060 | gen_op('+'); |
4061 | vstore(); /* store value */ |
4062 | if (post) |
4063 | vpop(); /* if post op, return saved value */ |
4064 | } |
4065 | |
4066 | ST_FUNC void parse_mult_str (CString *astr, const char *msg) |
4067 | { |
4068 | /* read the string */ |
4069 | if (tok != TOK_STR) |
4070 | expect(msg); |
4071 | cstr_new(astr); |
4072 | while (tok == TOK_STR) { |
4073 | /* XXX: add \0 handling too ? */ |
4074 | cstr_cat(astr, tokc.str.data, -1); |
4075 | next(); |
4076 | } |
4077 | cstr_ccat(astr, '\0'); |
4078 | } |
4079 | |
4080 | /* If I is >= 1 and a power of two, returns log2(i)+1. |
4081 | If I is 0 returns 0. */ |
4082 | ST_FUNC int exact_log2p1(int i) |
4083 | { |
4084 | int ret; |
4085 | if (!i) |
4086 | return 0; |
4087 | for (ret = 1; i >= 1 << 8; ret += 8) |
4088 | i >>= 8; |
4089 | if (i >= 1 << 4) |
4090 | ret += 4, i >>= 4; |
4091 | if (i >= 1 << 2) |
4092 | ret += 2, i >>= 2; |
4093 | if (i >= 1 << 1) |
4094 | ret++; |
4095 | return ret; |
4096 | } |
4097 | |
4098 | /* Parse __attribute__((...)) GNUC extension. */ |
4099 | static void parse_attribute(AttributeDef *ad) |
4100 | { |
4101 | int t, n; |
4102 | CString astr; |
4103 | |
4104 | redo: |
4105 | if (tok != TOK_ATTRIBUTE1 && tok != TOK_ATTRIBUTE2) |
4106 | return; |
4107 | next(); |
4108 | skip('('); |
4109 | skip('('); |
4110 | while (tok != ')') { |
4111 | if (tok < TOK_IDENT) |
4112 | expect("attribute name" ); |
4113 | t = tok; |
4114 | next(); |
4115 | switch(t) { |
4116 | case TOK_CLEANUP1: |
4117 | case TOK_CLEANUP2: |
4118 | { |
4119 | Sym *s; |
4120 | |
4121 | skip('('); |
4122 | s = sym_find(tok); |
4123 | if (!s) { |
4124 | tcc_warning("implicit declaration of function '%s'" , |
4125 | get_tok_str(tok, &tokc)); |
4126 | s = external_global_sym(tok, &func_old_type); |
4127 | } else if ((s->type.t & VT_BTYPE) != VT_FUNC) |
4128 | tcc_error("'%s' is not declared as function" , get_tok_str(tok, &tokc)); |
4129 | ad->cleanup_func = s; |
4130 | next(); |
4131 | skip(')'); |
4132 | break; |
4133 | } |
4134 | case TOK_CONSTRUCTOR1: |
4135 | case TOK_CONSTRUCTOR2: |
4136 | ad->f.func_ctor = 1; |
4137 | break; |
4138 | case TOK_DESTRUCTOR1: |
4139 | case TOK_DESTRUCTOR2: |
4140 | ad->f.func_dtor = 1; |
4141 | break; |
4142 | case TOK_ALWAYS_INLINE1: |
4143 | case TOK_ALWAYS_INLINE2: |
4144 | ad->f.func_alwinl = 1; |
4145 | break; |
4146 | case TOK_SECTION1: |
4147 | case TOK_SECTION2: |
4148 | skip('('); |
4149 | parse_mult_str(&astr, "section name" ); |
4150 | ad->section = find_section(tcc_state, (char *)astr.data); |
4151 | skip(')'); |
4152 | cstr_free(&astr); |
4153 | break; |
4154 | case TOK_ALIAS1: |
4155 | case TOK_ALIAS2: |
4156 | skip('('); |
4157 | parse_mult_str(&astr, "alias(\"target\")" ); |
4158 | ad->alias_target = /* save string as token, for later */ |
4159 | tok_alloc((char*)astr.data, astr.size-1)->tok; |
4160 | skip(')'); |
4161 | cstr_free(&astr); |
4162 | break; |
4163 | case TOK_VISIBILITY1: |
4164 | case TOK_VISIBILITY2: |
4165 | skip('('); |
4166 | parse_mult_str(&astr, |
4167 | "visibility(\"default|hidden|internal|protected\")" ); |
4168 | if (!strcmp (astr.data, "default" )) |
4169 | ad->a.visibility = STV_DEFAULT; |
4170 | else if (!strcmp (astr.data, "hidden" )) |
4171 | ad->a.visibility = STV_HIDDEN; |
4172 | else if (!strcmp (astr.data, "internal" )) |
4173 | ad->a.visibility = STV_INTERNAL; |
4174 | else if (!strcmp (astr.data, "protected" )) |
4175 | ad->a.visibility = STV_PROTECTED; |
4176 | else |
4177 | expect("visibility(\"default|hidden|internal|protected\")" ); |
4178 | skip(')'); |
4179 | cstr_free(&astr); |
4180 | break; |
4181 | case TOK_ALIGNED1: |
4182 | case TOK_ALIGNED2: |
4183 | if (tok == '(') { |
4184 | next(); |
4185 | n = expr_const(); |
4186 | if (n <= 0 || (n & (n - 1)) != 0) |
4187 | tcc_error("alignment must be a positive power of two" ); |
4188 | skip(')'); |
4189 | } else { |
4190 | n = MAX_ALIGN; |
4191 | } |
4192 | ad->a.aligned = exact_log2p1(n); |
4193 | if (n != 1 << (ad->a.aligned - 1)) |
4194 | tcc_error("alignment of %d is larger than implemented" , n); |
4195 | break; |
4196 | case TOK_PACKED1: |
4197 | case TOK_PACKED2: |
4198 | ad->a.packed = 1; |
4199 | break; |
4200 | case TOK_WEAK1: |
4201 | case TOK_WEAK2: |
4202 | ad->a.weak = 1; |
4203 | break; |
4204 | case TOK_UNUSED1: |
4205 | case TOK_UNUSED2: |
4206 | /* currently, no need to handle it because tcc does not |
4207 | track unused objects */ |
4208 | break; |
4209 | case TOK_NORETURN1: |
4210 | case TOK_NORETURN2: |
4211 | ad->f.func_noreturn = 1; |
4212 | break; |
4213 | case TOK_CDECL1: |
4214 | case TOK_CDECL2: |
4215 | case TOK_CDECL3: |
4216 | ad->f.func_call = FUNC_CDECL; |
4217 | break; |
4218 | case TOK_STDCALL1: |
4219 | case TOK_STDCALL2: |
4220 | case TOK_STDCALL3: |
4221 | ad->f.func_call = FUNC_STDCALL; |
4222 | break; |
4223 | #ifdef TCC_TARGET_I386 |
4224 | case TOK_REGPARM1: |
4225 | case TOK_REGPARM2: |
4226 | skip('('); |
4227 | n = expr_const(); |
4228 | if (n > 3) |
4229 | n = 3; |
4230 | else if (n < 0) |
4231 | n = 0; |
4232 | if (n > 0) |
4233 | ad->f.func_call = FUNC_FASTCALL1 + n - 1; |
4234 | skip(')'); |
4235 | break; |
4236 | case TOK_FASTCALL1: |
4237 | case TOK_FASTCALL2: |
4238 | case TOK_FASTCALL3: |
4239 | ad->f.func_call = FUNC_FASTCALLW; |
4240 | break; |
4241 | #endif |
4242 | case TOK_MODE: |
4243 | skip('('); |
4244 | switch(tok) { |
4245 | case TOK_MODE_DI: |
4246 | ad->attr_mode = VT_LLONG + 1; |
4247 | break; |
4248 | case TOK_MODE_QI: |
4249 | ad->attr_mode = VT_BYTE + 1; |
4250 | break; |
4251 | case TOK_MODE_HI: |
4252 | ad->attr_mode = VT_SHORT + 1; |
4253 | break; |
4254 | case TOK_MODE_SI: |
4255 | case TOK_MODE_word: |
4256 | ad->attr_mode = VT_INT + 1; |
4257 | break; |
4258 | default: |
4259 | tcc_warning("__mode__(%s) not supported\n" , get_tok_str(tok, NULL)); |
4260 | break; |
4261 | } |
4262 | next(); |
4263 | skip(')'); |
4264 | break; |
4265 | case TOK_DLLEXPORT: |
4266 | ad->a.dllexport = 1; |
4267 | break; |
4268 | case TOK_NODECORATE: |
4269 | ad->a.nodecorate = 1; |
4270 | break; |
4271 | case TOK_DLLIMPORT: |
4272 | ad->a.dllimport = 1; |
4273 | break; |
4274 | default: |
4275 | if (tcc_state->warn_unsupported) |
4276 | tcc_warning("'%s' attribute ignored" , get_tok_str(t, NULL)); |
4277 | /* skip parameters */ |
4278 | if (tok == '(') { |
4279 | int parenthesis = 0; |
4280 | do { |
4281 | if (tok == '(') |
4282 | parenthesis++; |
4283 | else if (tok == ')') |
4284 | parenthesis--; |
4285 | next(); |
4286 | } while (parenthesis && tok != -1); |
4287 | } |
4288 | break; |
4289 | } |
4290 | if (tok != ',') |
4291 | break; |
4292 | next(); |
4293 | } |
4294 | skip(')'); |
4295 | skip(')'); |
4296 | goto redo; |
4297 | } |
4298 | |
4299 | static Sym * find_field (CType *type, int v, int *cumofs) |
4300 | { |
4301 | Sym *s = type->ref; |
4302 | v |= SYM_FIELD; |
4303 | while ((s = s->next) != NULL) { |
4304 | if ((s->v & SYM_FIELD) && |
4305 | (s->type.t & VT_BTYPE) == VT_STRUCT && |
4306 | (s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) { |
4307 | Sym *ret = find_field (&s->type, v, cumofs); |
4308 | if (ret) { |
4309 | *cumofs += s->c; |
4310 | return ret; |
4311 | } |
4312 | } |
4313 | if (s->v == v) |
4314 | break; |
4315 | } |
4316 | return s; |
4317 | } |
4318 | |
4319 | static void struct_layout(CType *type, AttributeDef *ad) |
4320 | { |
4321 | int size, align, maxalign, offset, c, bit_pos, bit_size; |
4322 | int packed, a, bt, prevbt, prev_bit_size; |
4323 | int pcc = !tcc_state->ms_bitfields; |
4324 | int pragma_pack = *tcc_state->pack_stack_ptr; |
4325 | Sym *f; |
4326 | |
4327 | maxalign = 1; |
4328 | offset = 0; |
4329 | c = 0; |
4330 | bit_pos = 0; |
4331 | prevbt = VT_STRUCT; /* make it never match */ |
4332 | prev_bit_size = 0; |
4333 | |
4334 | //#define BF_DEBUG |
4335 | |
4336 | for (f = type->ref->next; f; f = f->next) { |
4337 | if (f->type.t & VT_BITFIELD) |
4338 | bit_size = BIT_SIZE(f->type.t); |
4339 | else |
4340 | bit_size = -1; |
4341 | size = type_size(&f->type, &align); |
4342 | a = f->a.aligned ? 1 << (f->a.aligned - 1) : 0; |
4343 | packed = 0; |
4344 | |
4345 | if (pcc && bit_size == 0) { |
4346 | /* in pcc mode, packing does not affect zero-width bitfields */ |
4347 | |
4348 | } else { |
4349 | /* in pcc mode, attribute packed overrides if set. */ |
4350 | if (pcc && (f->a.packed || ad->a.packed)) |
4351 | align = packed = 1; |
4352 | |
4353 | /* pragma pack overrides align if lesser and packs bitfields always */ |
4354 | if (pragma_pack) { |
4355 | packed = 1; |
4356 | if (pragma_pack < align) |
4357 | align = pragma_pack; |
4358 | /* in pcc mode pragma pack also overrides individual align */ |
4359 | if (pcc && pragma_pack < a) |
4360 | a = 0; |
4361 | } |
4362 | } |
4363 | /* some individual align was specified */ |
4364 | if (a) |
4365 | align = a; |
4366 | |
4367 | if (type->ref->type.t == VT_UNION) { |
4368 | if (pcc && bit_size >= 0) |
4369 | size = (bit_size + 7) >> 3; |
4370 | offset = 0; |
4371 | if (size > c) |
4372 | c = size; |
4373 | |
4374 | } else if (bit_size < 0) { |
4375 | if (pcc) |
4376 | c += (bit_pos + 7) >> 3; |
4377 | c = (c + align - 1) & -align; |
4378 | offset = c; |
4379 | if (size > 0) |
4380 | c += size; |
4381 | bit_pos = 0; |
4382 | prevbt = VT_STRUCT; |
4383 | prev_bit_size = 0; |
4384 | |
4385 | } else { |
4386 | /* A bit-field. Layout is more complicated. There are two |
4387 | options: PCC (GCC) compatible and MS compatible */ |
4388 | if (pcc) { |
4389 | /* In PCC layout a bit-field is placed adjacent to the |
4390 | preceding bit-fields, except if: |
4391 | - it has zero-width |
4392 | - an individual alignment was given |
4393 | - it would overflow its base type container and |
4394 | there is no packing */ |
4395 | if (bit_size == 0) { |
4396 | new_field: |
4397 | c = (c + ((bit_pos + 7) >> 3) + align - 1) & -align; |
4398 | bit_pos = 0; |
4399 | } else if (f->a.aligned) { |
4400 | goto new_field; |
4401 | } else if (!packed) { |
4402 | int a8 = align * 8; |
4403 | int ofs = ((c * 8 + bit_pos) % a8 + bit_size + a8 - 1) / a8; |
4404 | if (ofs > size / align) |
4405 | goto new_field; |
4406 | } |
4407 | |
4408 | /* in pcc mode, long long bitfields have type int if they fit */ |
4409 | if (size == 8 && bit_size <= 32) |
4410 | f->type.t = (f->type.t & ~VT_BTYPE) | VT_INT, size = 4; |
4411 | |
4412 | while (bit_pos >= align * 8) |
4413 | c += align, bit_pos -= align * 8; |
4414 | offset = c; |
4415 | |
4416 | /* In PCC layout named bit-fields influence the alignment |
4417 | of the containing struct using the base types alignment, |
4418 | except for packed fields (which here have correct align). */ |
4419 | if (f->v & SYM_FIRST_ANOM |
4420 | // && bit_size // ??? gcc on ARM/rpi does that |
4421 | ) |
4422 | align = 1; |
4423 | |
4424 | } else { |
4425 | bt = f->type.t & VT_BTYPE; |
4426 | if ((bit_pos + bit_size > size * 8) |
4427 | || (bit_size > 0) == (bt != prevbt) |
4428 | ) { |
4429 | c = (c + align - 1) & -align; |
4430 | offset = c; |
4431 | bit_pos = 0; |
4432 | /* In MS bitfield mode a bit-field run always uses |
4433 | at least as many bits as the underlying type. |
4434 | To start a new run it's also required that this |
4435 | or the last bit-field had non-zero width. */ |
4436 | if (bit_size || prev_bit_size) |
4437 | c += size; |
4438 | } |
4439 | /* In MS layout the records alignment is normally |
4440 | influenced by the field, except for a zero-width |
4441 | field at the start of a run (but by further zero-width |
4442 | fields it is again). */ |
4443 | if (bit_size == 0 && prevbt != bt) |
4444 | align = 1; |
4445 | prevbt = bt; |
4446 | prev_bit_size = bit_size; |
4447 | } |
4448 | |
4449 | f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT)) |
4450 | | (bit_pos << VT_STRUCT_SHIFT); |
4451 | bit_pos += bit_size; |
4452 | } |
4453 | if (align > maxalign) |
4454 | maxalign = align; |
4455 | |
4456 | #ifdef BF_DEBUG |
4457 | printf("set field %s offset %-2d size %-2d align %-2d" , |
4458 | get_tok_str(f->v & ~SYM_FIELD, NULL), offset, size, align); |
4459 | if (f->type.t & VT_BITFIELD) { |
4460 | printf(" pos %-2d bits %-2d" , |
4461 | BIT_POS(f->type.t), |
4462 | BIT_SIZE(f->type.t) |
4463 | ); |
4464 | } |
4465 | printf("\n" ); |
4466 | #endif |
4467 | |
4468 | f->c = offset; |
4469 | f->r = 0; |
4470 | } |
4471 | |
4472 | if (pcc) |
4473 | c += (bit_pos + 7) >> 3; |
4474 | |
4475 | /* store size and alignment */ |
4476 | a = bt = ad->a.aligned ? 1 << (ad->a.aligned - 1) : 1; |
4477 | if (a < maxalign) |
4478 | a = maxalign; |
4479 | type->ref->r = a; |
4480 | if (pragma_pack && pragma_pack < maxalign && 0 == pcc) { |
4481 | /* can happen if individual align for some member was given. In |
4482 | this case MSVC ignores maxalign when aligning the size */ |
4483 | a = pragma_pack; |
4484 | if (a < bt) |
4485 | a = bt; |
4486 | } |
4487 | c = (c + a - 1) & -a; |
4488 | type->ref->c = c; |
4489 | |
4490 | #ifdef BF_DEBUG |
4491 | printf("struct size %-2d align %-2d\n\n" , c, a), fflush(stdout); |
4492 | #endif |
4493 | |
4494 | /* check whether we can access bitfields by their type */ |
4495 | for (f = type->ref->next; f; f = f->next) { |
4496 | int s, px, cx, c0; |
4497 | CType t; |
4498 | |
4499 | if (0 == (f->type.t & VT_BITFIELD)) |
4500 | continue; |
4501 | f->type.ref = f; |
4502 | f->auxtype = -1; |
4503 | bit_size = BIT_SIZE(f->type.t); |
4504 | if (bit_size == 0) |
4505 | continue; |
4506 | bit_pos = BIT_POS(f->type.t); |
4507 | size = type_size(&f->type, &align); |
4508 | if (bit_pos + bit_size <= size * 8 && f->c + size <= c) |
4509 | continue; |
4510 | |
4511 | /* try to access the field using a different type */ |
4512 | c0 = -1, s = align = 1; |
4513 | t.t = VT_BYTE; |
4514 | for (;;) { |
4515 | px = f->c * 8 + bit_pos; |
4516 | cx = (px >> 3) & -align; |
4517 | px = px - (cx << 3); |
4518 | if (c0 == cx) |
4519 | break; |
4520 | s = (px + bit_size + 7) >> 3; |
4521 | if (s > 4) { |
4522 | t.t = VT_LLONG; |
4523 | } else if (s > 2) { |
4524 | t.t = VT_INT; |
4525 | } else if (s > 1) { |
4526 | t.t = VT_SHORT; |
4527 | } else { |
4528 | t.t = VT_BYTE; |
4529 | } |
4530 | s = type_size(&t, &align); |
4531 | c0 = cx; |
4532 | } |
4533 | |
4534 | if (px + bit_size <= s * 8 && cx + s <= c) { |
4535 | /* update offset and bit position */ |
4536 | f->c = cx; |
4537 | bit_pos = px; |
4538 | f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT)) |
4539 | | (bit_pos << VT_STRUCT_SHIFT); |
4540 | if (s != size) |
4541 | f->auxtype = t.t; |
4542 | #ifdef BF_DEBUG |
4543 | printf("FIX field %s offset %-2d size %-2d align %-2d " |
4544 | "pos %-2d bits %-2d\n" , |
4545 | get_tok_str(f->v & ~SYM_FIELD, NULL), |
4546 | cx, s, align, px, bit_size); |
4547 | #endif |
4548 | } else { |
4549 | /* fall back to load/store single-byte wise */ |
4550 | f->auxtype = VT_STRUCT; |
4551 | #ifdef BF_DEBUG |
4552 | printf("FIX field %s : load byte-wise\n" , |
4553 | get_tok_str(f->v & ~SYM_FIELD, NULL)); |
4554 | #endif |
4555 | } |
4556 | } |
4557 | } |
4558 | |
4559 | /* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */ |
4560 | static void struct_decl(CType *type, int u) |
4561 | { |
4562 | int v, c, size, align, flexible; |
4563 | int bit_size, bsize, bt; |
4564 | Sym *s, *ss, **ps; |
4565 | AttributeDef ad, ad1; |
4566 | CType type1, btype; |
4567 | |
4568 | memset(&ad, 0, sizeof ad); |
4569 | next(); |
4570 | parse_attribute(&ad); |
4571 | if (tok != '{') { |
4572 | v = tok; |
4573 | next(); |
4574 | /* struct already defined ? return it */ |
4575 | if (v < TOK_IDENT) |
4576 | expect("struct/union/enum name" ); |
4577 | s = struct_find(v); |
4578 | if (s && (s->sym_scope == local_scope || tok != '{')) { |
4579 | if (u == s->type.t) |
4580 | goto do_decl; |
4581 | if (u == VT_ENUM && IS_ENUM(s->type.t)) |
4582 | goto do_decl; |
4583 | tcc_error("redefinition of '%s'" , get_tok_str(v, NULL)); |
4584 | } |
4585 | } else { |
4586 | v = anon_sym++; |
4587 | } |
4588 | /* Record the original enum/struct/union token. */ |
4589 | type1.t = u == VT_ENUM ? u | VT_INT | VT_UNSIGNED : u; |
4590 | type1.ref = NULL; |
4591 | /* we put an undefined size for struct/union */ |
4592 | s = sym_push(v | SYM_STRUCT, &type1, 0, -1); |
4593 | s->r = 0; /* default alignment is zero as gcc */ |
4594 | do_decl: |
4595 | type->t = s->type.t; |
4596 | type->ref = s; |
4597 | |
4598 | if (tok == '{') { |
4599 | next(); |
4600 | if (s->c != -1) |
4601 | tcc_error("struct/union/enum already defined" ); |
4602 | s->c = -2; |
4603 | /* cannot be empty */ |
4604 | /* non empty enums are not allowed */ |
4605 | ps = &s->next; |
4606 | if (u == VT_ENUM) { |
4607 | long long ll = 0, pl = 0, nl = 0; |
4608 | CType t; |
4609 | t.ref = s; |
4610 | /* enum symbols have static storage */ |
4611 | t.t = VT_INT|VT_STATIC|VT_ENUM_VAL; |
4612 | for(;;) { |
4613 | v = tok; |
4614 | if (v < TOK_UIDENT) |
4615 | expect("identifier" ); |
4616 | ss = sym_find(v); |
4617 | if (ss && !local_stack) |
4618 | tcc_error("redefinition of enumerator '%s'" , |
4619 | get_tok_str(v, NULL)); |
4620 | next(); |
4621 | if (tok == '=') { |
4622 | next(); |
4623 | ll = expr_const64(); |
4624 | } |
4625 | ss = sym_push(v, &t, VT_CONST, 0); |
4626 | ss->enum_val = ll; |
4627 | *ps = ss, ps = &ss->next; |
4628 | if (ll < nl) |
4629 | nl = ll; |
4630 | if (ll > pl) |
4631 | pl = ll; |
4632 | if (tok != ',') |
4633 | break; |
4634 | next(); |
4635 | ll++; |
4636 | /* NOTE: we accept a trailing comma */ |
4637 | if (tok == '}') |
4638 | break; |
4639 | } |
4640 | skip('}'); |
4641 | /* set integral type of the enum */ |
4642 | t.t = VT_INT; |
4643 | if (nl >= 0) { |
4644 | if (pl != (unsigned)pl) |
4645 | t.t = (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG); |
4646 | t.t |= VT_UNSIGNED; |
4647 | } else if (pl != (int)pl || nl != (int)nl) |
4648 | t.t = (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG); |
4649 | s->type.t = type->t = t.t | VT_ENUM; |
4650 | s->c = 0; |
4651 | /* set type for enum members */ |
4652 | for (ss = s->next; ss; ss = ss->next) { |
4653 | ll = ss->enum_val; |
4654 | if (ll == (int)ll) /* default is int if it fits */ |
4655 | continue; |
4656 | if (t.t & VT_UNSIGNED) { |
4657 | ss->type.t |= VT_UNSIGNED; |
4658 | if (ll == (unsigned)ll) |
4659 | continue; |
4660 | } |
4661 | ss->type.t = (ss->type.t & ~VT_BTYPE) |
4662 | | (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG); |
4663 | } |
4664 | } else { |
4665 | c = 0; |
4666 | flexible = 0; |
4667 | while (tok != '}') { |
4668 | if (!parse_btype(&btype, &ad1)) { |
4669 | skip(';'); |
4670 | continue; |
4671 | } |
4672 | while (1) { |
4673 | if (flexible) |
4674 | tcc_error("flexible array member '%s' not at the end of struct" , |
4675 | get_tok_str(v, NULL)); |
4676 | bit_size = -1; |
4677 | v = 0; |
4678 | type1 = btype; |
4679 | if (tok != ':') { |
4680 | if (tok != ';') |
4681 | type_decl(&type1, &ad1, &v, TYPE_DIRECT); |
4682 | if (v == 0) { |
4683 | if ((type1.t & VT_BTYPE) != VT_STRUCT) |
4684 | expect("identifier" ); |
4685 | else { |
4686 | int v = btype.ref->v; |
4687 | if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) { |
4688 | if (tcc_state->ms_extensions == 0) |
4689 | expect("identifier" ); |
4690 | } |
4691 | } |
4692 | } |
4693 | if (type_size(&type1, &align) < 0) { |
4694 | if ((u == VT_STRUCT) && (type1.t & VT_ARRAY) && c) |
4695 | flexible = 1; |
4696 | else |
4697 | tcc_error("field '%s' has incomplete type" , |
4698 | get_tok_str(v, NULL)); |
4699 | } |
4700 | if ((type1.t & VT_BTYPE) == VT_FUNC || |
4701 | (type1.t & VT_BTYPE) == VT_VOID || |
4702 | (type1.t & VT_STORAGE)) |
4703 | tcc_error("invalid type for '%s'" , |
4704 | get_tok_str(v, NULL)); |
4705 | } |
4706 | if (tok == ':') { |
4707 | next(); |
4708 | bit_size = expr_const(); |
4709 | /* XXX: handle v = 0 case for messages */ |
4710 | if (bit_size < 0) |
4711 | tcc_error("negative width in bit-field '%s'" , |
4712 | get_tok_str(v, NULL)); |
4713 | if (v && bit_size == 0) |
4714 | tcc_error("zero width for bit-field '%s'" , |
4715 | get_tok_str(v, NULL)); |
4716 | parse_attribute(&ad1); |
4717 | } |
4718 | size = type_size(&type1, &align); |
4719 | if (bit_size >= 0) { |
4720 | bt = type1.t & VT_BTYPE; |
4721 | if (bt != VT_INT && |
4722 | bt != VT_BYTE && |
4723 | bt != VT_SHORT && |
4724 | bt != VT_BOOL && |
4725 | bt != VT_LLONG) |
4726 | tcc_error("bitfields must have scalar type" ); |
4727 | bsize = size * 8; |
4728 | if (bit_size > bsize) { |
4729 | tcc_error("width of '%s' exceeds its type" , |
4730 | get_tok_str(v, NULL)); |
4731 | } else if (bit_size == bsize |
4732 | && !ad.a.packed && !ad1.a.packed) { |
4733 | /* no need for bit fields */ |
4734 | ; |
4735 | } else if (bit_size == 64) { |
4736 | tcc_error("field width 64 not implemented" ); |
4737 | } else { |
4738 | type1.t = (type1.t & ~VT_STRUCT_MASK) |
4739 | | VT_BITFIELD |
4740 | | (bit_size << (VT_STRUCT_SHIFT + 6)); |
4741 | } |
4742 | } |
4743 | if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) { |
4744 | /* Remember we've seen a real field to check |
4745 | for placement of flexible array member. */ |
4746 | c = 1; |
4747 | } |
4748 | /* If member is a struct or bit-field, enforce |
4749 | placing into the struct (as anonymous). */ |
4750 | if (v == 0 && |
4751 | ((type1.t & VT_BTYPE) == VT_STRUCT || |
4752 | bit_size >= 0)) { |
4753 | v = anon_sym++; |
4754 | } |
4755 | if (v) { |
4756 | ss = sym_push(v | SYM_FIELD, &type1, 0, 0); |
4757 | ss->a = ad1.a; |
4758 | *ps = ss; |
4759 | ps = &ss->next; |
4760 | } |
4761 | if (tok == ';' || tok == TOK_EOF) |
4762 | break; |
4763 | skip(','); |
4764 | } |
4765 | skip(';'); |
4766 | } |
4767 | skip('}'); |
4768 | parse_attribute(&ad); |
4769 | if (ad.cleanup_func) { |
4770 | tcc_warning("attribute '__cleanup__' ignored on type" ); |
4771 | } |
4772 | struct_layout(type, &ad); |
4773 | } |
4774 | } |
4775 | } |
4776 | |
4777 | static void sym_to_attr(AttributeDef *ad, Sym *s) |
4778 | { |
4779 | merge_symattr(&ad->a, &s->a); |
4780 | merge_funcattr(&ad->f, &s->f); |
4781 | } |
4782 | |
4783 | /* Add type qualifiers to a type. If the type is an array then the qualifiers |
4784 | are added to the element type, copied because it could be a typedef. */ |
4785 | static void parse_btype_qualify(CType *type, int qualifiers) |
4786 | { |
4787 | while (type->t & VT_ARRAY) { |
4788 | type->ref = sym_push(SYM_FIELD, &type->ref->type, 0, type->ref->c); |
4789 | type = &type->ref->type; |
4790 | } |
4791 | type->t |= qualifiers; |
4792 | } |
4793 | |
4794 | /* return 0 if no type declaration. otherwise, return the basic type |
4795 | and skip it. |
4796 | */ |
4797 | static int parse_btype(CType *type, AttributeDef *ad) |
4798 | { |
4799 | int t, u, bt, st, type_found, typespec_found, g, n; |
4800 | Sym *s; |
4801 | CType type1; |
4802 | |
4803 | memset(ad, 0, sizeof(AttributeDef)); |
4804 | type_found = 0; |
4805 | typespec_found = 0; |
4806 | t = VT_INT; |
4807 | bt = st = -1; |
4808 | type->ref = NULL; |
4809 | |
4810 | while(1) { |
4811 | switch(tok) { |
4812 | case TOK_EXTENSION: |
4813 | /* currently, we really ignore extension */ |
4814 | next(); |
4815 | continue; |
4816 | |
4817 | /* basic types */ |
4818 | case TOK_CHAR: |
4819 | u = VT_BYTE; |
4820 | basic_type: |
4821 | next(); |
4822 | basic_type1: |
4823 | if (u == VT_SHORT || u == VT_LONG) { |
4824 | if (st != -1 || (bt != -1 && bt != VT_INT)) |
4825 | tmbt: tcc_error("too many basic types" ); |
4826 | st = u; |
4827 | } else { |
4828 | if (bt != -1 || (st != -1 && u != VT_INT)) |
4829 | goto tmbt; |
4830 | bt = u; |
4831 | } |
4832 | if (u != VT_INT) |
4833 | t = (t & ~(VT_BTYPE|VT_LONG)) | u; |
4834 | typespec_found = 1; |
4835 | break; |
4836 | case TOK_VOID: |
4837 | u = VT_VOID; |
4838 | goto basic_type; |
4839 | case TOK_SHORT: |
4840 | u = VT_SHORT; |
4841 | goto basic_type; |
4842 | case TOK_INT: |
4843 | u = VT_INT; |
4844 | goto basic_type; |
4845 | case TOK_ALIGNAS: |
4846 | { int n; |
4847 | AttributeDef ad1; |
4848 | next(); |
4849 | skip('('); |
4850 | memset(&ad1, 0, sizeof(AttributeDef)); |
4851 | if (parse_btype(&type1, &ad1)) { |
4852 | type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); |
4853 | if (ad1.a.aligned) |
4854 | n = 1 << (ad1.a.aligned - 1); |
4855 | else |
4856 | type_size(&type1, &n); |
4857 | } else { |
4858 | n = expr_const(); |
4859 | if (n <= 0 || (n & (n - 1)) != 0) |
4860 | tcc_error("alignment must be a positive power of two" ); |
4861 | } |
4862 | skip(')'); |
4863 | ad->a.aligned = exact_log2p1(n); |
4864 | } |
4865 | continue; |
4866 | case TOK_LONG: |
4867 | if ((t & VT_BTYPE) == VT_DOUBLE) { |
4868 | t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LDOUBLE; |
4869 | } else if ((t & (VT_BTYPE|VT_LONG)) == VT_LONG) { |
4870 | t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LLONG; |
4871 | } else { |
4872 | u = VT_LONG; |
4873 | goto basic_type; |
4874 | } |
4875 | next(); |
4876 | break; |
4877 | #ifdef TCC_TARGET_ARM64 |
4878 | case TOK_UINT128: |
4879 | /* GCC's __uint128_t appears in some Linux header files. Make it a |
4880 | synonym for long double to get the size and alignment right. */ |
4881 | u = VT_LDOUBLE; |
4882 | goto basic_type; |
4883 | #endif |
4884 | case TOK_BOOL: |
4885 | u = VT_BOOL; |
4886 | goto basic_type; |
4887 | case TOK_FLOAT: |
4888 | u = VT_FLOAT; |
4889 | goto basic_type; |
4890 | case TOK_DOUBLE: |
4891 | if ((t & (VT_BTYPE|VT_LONG)) == VT_LONG) { |
4892 | t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LDOUBLE; |
4893 | } else { |
4894 | u = VT_DOUBLE; |
4895 | goto basic_type; |
4896 | } |
4897 | next(); |
4898 | break; |
4899 | case TOK_ENUM: |
4900 | struct_decl(&type1, VT_ENUM); |
4901 | basic_type2: |
4902 | u = type1.t; |
4903 | type->ref = type1.ref; |
4904 | goto basic_type1; |
4905 | case TOK_STRUCT: |
4906 | struct_decl(&type1, VT_STRUCT); |
4907 | goto basic_type2; |
4908 | case TOK_UNION: |
4909 | struct_decl(&type1, VT_UNION); |
4910 | goto basic_type2; |
4911 | |
4912 | /* type modifiers */ |
4913 | case TOK_CONST1: |
4914 | case TOK_CONST2: |
4915 | case TOK_CONST3: |
4916 | type->t = t; |
4917 | parse_btype_qualify(type, VT_CONSTANT); |
4918 | t = type->t; |
4919 | next(); |
4920 | break; |
4921 | case TOK_VOLATILE1: |
4922 | case TOK_VOLATILE2: |
4923 | case TOK_VOLATILE3: |
4924 | type->t = t; |
4925 | parse_btype_qualify(type, VT_VOLATILE); |
4926 | t = type->t; |
4927 | next(); |
4928 | break; |
4929 | case TOK_SIGNED1: |
4930 | case TOK_SIGNED2: |
4931 | case TOK_SIGNED3: |
4932 | if ((t & (VT_DEFSIGN|VT_UNSIGNED)) == (VT_DEFSIGN|VT_UNSIGNED)) |
4933 | tcc_error("signed and unsigned modifier" ); |
4934 | t |= VT_DEFSIGN; |
4935 | next(); |
4936 | typespec_found = 1; |
4937 | break; |
4938 | case TOK_REGISTER: |
4939 | case TOK_AUTO: |
4940 | case TOK_RESTRICT1: |
4941 | case TOK_RESTRICT2: |
4942 | case TOK_RESTRICT3: |
4943 | next(); |
4944 | break; |
4945 | case TOK_UNSIGNED: |
4946 | if ((t & (VT_DEFSIGN|VT_UNSIGNED)) == VT_DEFSIGN) |
4947 | tcc_error("signed and unsigned modifier" ); |
4948 | t |= VT_DEFSIGN | VT_UNSIGNED; |
4949 | next(); |
4950 | typespec_found = 1; |
4951 | break; |
4952 | |
4953 | /* storage */ |
4954 | case TOK_EXTERN: |
4955 | g = VT_EXTERN; |
4956 | goto storage; |
4957 | case TOK_STATIC: |
4958 | g = VT_STATIC; |
4959 | goto storage; |
4960 | case TOK_TYPEDEF: |
4961 | g = VT_TYPEDEF; |
4962 | goto storage; |
4963 | storage: |
4964 | if (t & (VT_EXTERN|VT_STATIC|VT_TYPEDEF) & ~g) |
4965 | tcc_error("multiple storage classes" ); |
4966 | t |= g; |
4967 | next(); |
4968 | break; |
4969 | case TOK_INLINE1: |
4970 | case TOK_INLINE2: |
4971 | case TOK_INLINE3: |
4972 | t |= VT_INLINE; |
4973 | next(); |
4974 | break; |
4975 | case TOK_NORETURN3: |
4976 | next(); |
4977 | ad->f.func_noreturn = 1; |
4978 | break; |
4979 | /* GNUC attribute */ |
4980 | case TOK_ATTRIBUTE1: |
4981 | case TOK_ATTRIBUTE2: |
4982 | parse_attribute(ad); |
4983 | if (ad->attr_mode) { |
4984 | u = ad->attr_mode -1; |
4985 | t = (t & ~(VT_BTYPE|VT_LONG)) | u; |
4986 | } |
4987 | continue; |
4988 | /* GNUC typeof */ |
4989 | case TOK_TYPEOF1: |
4990 | case TOK_TYPEOF2: |
4991 | case TOK_TYPEOF3: |
4992 | next(); |
4993 | parse_expr_type(&type1); |
4994 | /* remove all storage modifiers except typedef */ |
4995 | type1.t &= ~(VT_STORAGE&~VT_TYPEDEF); |
4996 | if (type1.ref) |
4997 | sym_to_attr(ad, type1.ref); |
4998 | goto basic_type2; |
4999 | default: |
5000 | if (typespec_found) |
5001 | goto the_end; |
5002 | s = sym_find(tok); |
5003 | if (!s || !(s->type.t & VT_TYPEDEF)) |
5004 | goto the_end; |
5005 | |
5006 | n = tok, next(); |
5007 | if (tok == ':' && !in_generic) { |
5008 | /* ignore if it's a label */ |
5009 | unget_tok(n); |
5010 | goto the_end; |
5011 | } |
5012 | |
5013 | t &= ~(VT_BTYPE|VT_LONG); |
5014 | u = t & ~(VT_CONSTANT | VT_VOLATILE), t ^= u; |
5015 | type->t = (s->type.t & ~VT_TYPEDEF) | u; |
5016 | type->ref = s->type.ref; |
5017 | if (t) |
5018 | parse_btype_qualify(type, t); |
5019 | t = type->t; |
5020 | /* get attributes from typedef */ |
5021 | sym_to_attr(ad, s); |
5022 | typespec_found = 1; |
5023 | st = bt = -2; |
5024 | break; |
5025 | } |
5026 | type_found = 1; |
5027 | } |
5028 | the_end: |
5029 | if (tcc_state->char_is_unsigned) { |
5030 | if ((t & (VT_DEFSIGN|VT_BTYPE)) == VT_BYTE) |
5031 | t |= VT_UNSIGNED; |
5032 | } |
5033 | /* VT_LONG is used just as a modifier for VT_INT / VT_LLONG */ |
5034 | bt = t & (VT_BTYPE|VT_LONG); |
5035 | if (bt == VT_LONG) |
5036 | t |= LONG_SIZE == 8 ? VT_LLONG : VT_INT; |
5037 | #if defined TCC_TARGET_PE || (defined _WIN32 && defined _MSC_VER) |
5038 | if (bt == VT_LDOUBLE) |
5039 | t = (t & ~(VT_BTYPE|VT_LONG)) | (VT_DOUBLE|VT_LONG); |
5040 | #endif |
5041 | type->t = t; |
5042 | return type_found; |
5043 | } |
5044 | |
5045 | /* convert a function parameter type (array to pointer and function to |
5046 | function pointer) */ |
5047 | static inline void convert_parameter_type(CType *pt) |
5048 | { |
5049 | /* remove const and volatile qualifiers (XXX: const could be used |
5050 | to indicate a const function parameter */ |
5051 | pt->t &= ~(VT_CONSTANT | VT_VOLATILE); |
5052 | /* array must be transformed to pointer according to ANSI C */ |
5053 | pt->t &= ~VT_ARRAY; |
5054 | if ((pt->t & VT_BTYPE) == VT_FUNC) { |
5055 | mk_pointer(pt); |
5056 | } |
5057 | } |
5058 | |
5059 | ST_FUNC void parse_asm_str(CString *astr) |
5060 | { |
5061 | skip('('); |
5062 | parse_mult_str(astr, "string constant" ); |
5063 | } |
5064 | |
5065 | /* Parse an asm label and return the token */ |
5066 | static int asm_label_instr(void) |
5067 | { |
5068 | int v; |
5069 | CString astr; |
5070 | |
5071 | next(); |
5072 | parse_asm_str(&astr); |
5073 | skip(')'); |
5074 | #ifdef ASM_DEBUG |
5075 | printf("asm_alias: \"%s\"\n" , (char *)astr.data); |
5076 | #endif |
5077 | v = tok_alloc(astr.data, astr.size - 1)->tok; |
5078 | cstr_free(&astr); |
5079 | return v; |
5080 | } |
5081 | |
5082 | static int post_type(CType *type, AttributeDef *ad, int storage, int td) |
5083 | { |
5084 | int n, l, t1, arg_size, align, unused_align; |
5085 | Sym **plast, *s, *first; |
5086 | AttributeDef ad1; |
5087 | CType pt; |
5088 | |
5089 | if (tok == '(') { |
5090 | /* function type, or recursive declarator (return if so) */ |
5091 | next(); |
5092 | if (td && !(td & TYPE_ABSTRACT)) |
5093 | return 0; |
5094 | if (tok == ')') |
5095 | l = 0; |
5096 | else if (parse_btype(&pt, &ad1)) |
5097 | l = FUNC_NEW; |
5098 | else if (td) { |
5099 | merge_attr (ad, &ad1); |
5100 | return 0; |
5101 | } else |
5102 | l = FUNC_OLD; |
5103 | first = NULL; |
5104 | plast = &first; |
5105 | arg_size = 0; |
5106 | if (l) { |
5107 | for(;;) { |
5108 | /* read param name and compute offset */ |
5109 | if (l != FUNC_OLD) { |
5110 | if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')') |
5111 | break; |
5112 | type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT); |
5113 | if ((pt.t & VT_BTYPE) == VT_VOID) |
5114 | tcc_error("parameter declared as void" ); |
5115 | } else { |
5116 | n = tok; |
5117 | if (n < TOK_UIDENT) |
5118 | expect("identifier" ); |
5119 | pt.t = VT_VOID; /* invalid type */ |
5120 | pt.ref = NULL; |
5121 | next(); |
5122 | } |
5123 | convert_parameter_type(&pt); |
5124 | arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE; |
5125 | s = sym_push(n | SYM_FIELD, &pt, 0, 0); |
5126 | *plast = s; |
5127 | plast = &s->next; |
5128 | if (tok == ')') |
5129 | break; |
5130 | skip(','); |
5131 | if (l == FUNC_NEW && tok == TOK_DOTS) { |
5132 | l = FUNC_ELLIPSIS; |
5133 | next(); |
5134 | break; |
5135 | } |
5136 | if (l == FUNC_NEW && !parse_btype(&pt, &ad1)) |
5137 | tcc_error("invalid type" ); |
5138 | } |
5139 | } else |
5140 | /* if no parameters, then old type prototype */ |
5141 | l = FUNC_OLD; |
5142 | skip(')'); |
5143 | /* NOTE: const is ignored in returned type as it has a special |
5144 | meaning in gcc / C++ */ |
5145 | type->t &= ~VT_CONSTANT; |
5146 | /* some ancient pre-K&R C allows a function to return an array |
5147 | and the array brackets to be put after the arguments, such |
5148 | that "int c()[]" means something like "int[] c()" */ |
5149 | if (tok == '[') { |
5150 | next(); |
5151 | skip(']'); /* only handle simple "[]" */ |
5152 | mk_pointer(type); |
5153 | } |
5154 | /* we push a anonymous symbol which will contain the function prototype */ |
5155 | ad->f.func_args = arg_size; |
5156 | ad->f.func_type = l; |
5157 | s = sym_push(SYM_FIELD, type, 0, 0); |
5158 | s->a = ad->a; |
5159 | s->f = ad->f; |
5160 | s->next = first; |
5161 | type->t = VT_FUNC; |
5162 | type->ref = s; |
5163 | } else if (tok == '[') { |
5164 | int saved_nocode_wanted = nocode_wanted; |
5165 | /* array definition */ |
5166 | next(); |
5167 | while (1) { |
5168 | /* XXX The optional type-quals and static should only be accepted |
5169 | in parameter decls. The '*' as well, and then even only |
5170 | in prototypes (not function defs). */ |
5171 | switch (tok) { |
5172 | case TOK_RESTRICT1: case TOK_RESTRICT2: case TOK_RESTRICT3: |
5173 | case TOK_CONST1: |
5174 | case TOK_VOLATILE1: |
5175 | case TOK_STATIC: |
5176 | case '*': |
5177 | next(); |
5178 | continue; |
5179 | default: |
5180 | break; |
5181 | } |
5182 | break; |
5183 | } |
5184 | n = -1; |
5185 | t1 = 0; |
5186 | if (tok != ']') { |
5187 | if (!local_stack || (storage & VT_STATIC)) |
5188 | vpushi(expr_const()); |
5189 | else { |
5190 | /* VLAs (which can only happen with local_stack && !VT_STATIC) |
5191 | length must always be evaluated, even under nocode_wanted, |
5192 | so that its size slot is initialized (e.g. under sizeof |
5193 | or typeof). */ |
5194 | nocode_wanted = 0; |
5195 | gexpr(); |
5196 | } |
5197 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
5198 | n = vtop->c.i; |
5199 | if (n < 0) |
5200 | tcc_error("invalid array size" ); |
5201 | } else { |
5202 | if (!is_integer_btype(vtop->type.t & VT_BTYPE)) |
5203 | tcc_error("size of variable length array should be an integer" ); |
5204 | n = 0; |
5205 | t1 = VT_VLA; |
5206 | } |
5207 | } |
5208 | skip(']'); |
5209 | /* parse next post type */ |
5210 | post_type(type, ad, storage, 0); |
5211 | |
5212 | if ((type->t & VT_BTYPE) == VT_FUNC) |
5213 | tcc_error("declaration of an array of functions" ); |
5214 | if ((type->t & VT_BTYPE) == VT_VOID |
5215 | || type_size(type, &unused_align) < 0) |
5216 | tcc_error("declaration of an array of incomplete type elements" ); |
5217 | |
5218 | t1 |= type->t & VT_VLA; |
5219 | |
5220 | if (t1 & VT_VLA) { |
5221 | if (n < 0) |
5222 | tcc_error("need explicit inner array size in VLAs" ); |
5223 | loc -= type_size(&int_type, &align); |
5224 | loc &= -align; |
5225 | n = loc; |
5226 | |
5227 | vla_runtime_type_size(type, &align); |
5228 | gen_op('*'); |
5229 | vset(&int_type, VT_LOCAL|VT_LVAL, n); |
5230 | vswap(); |
5231 | vstore(); |
5232 | } |
5233 | if (n != -1) |
5234 | vpop(); |
5235 | nocode_wanted = saved_nocode_wanted; |
5236 | |
5237 | /* we push an anonymous symbol which will contain the array |
5238 | element type */ |
5239 | s = sym_push(SYM_FIELD, type, 0, n); |
5240 | type->t = (t1 ? VT_VLA : VT_ARRAY) | VT_PTR; |
5241 | type->ref = s; |
5242 | } |
5243 | return 1; |
5244 | } |
5245 | |
5246 | /* Parse a type declarator (except basic type), and return the type |
5247 | in 'type'. 'td' is a bitmask indicating which kind of type decl is |
5248 | expected. 'type' should contain the basic type. 'ad' is the |
5249 | attribute definition of the basic type. It can be modified by |
5250 | type_decl(). If this (possibly abstract) declarator is a pointer chain |
5251 | it returns the innermost pointed to type (equals *type, but is a different |
5252 | pointer), otherwise returns type itself, that's used for recursive calls. */ |
5253 | static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td) |
5254 | { |
5255 | CType *post, *ret; |
5256 | int qualifiers, storage; |
5257 | |
5258 | /* recursive type, remove storage bits first, apply them later again */ |
5259 | storage = type->t & VT_STORAGE; |
5260 | type->t &= ~VT_STORAGE; |
5261 | post = ret = type; |
5262 | |
5263 | while (tok == '*') { |
5264 | qualifiers = 0; |
5265 | redo: |
5266 | next(); |
5267 | switch(tok) { |
5268 | case TOK_CONST1: |
5269 | case TOK_CONST2: |
5270 | case TOK_CONST3: |
5271 | qualifiers |= VT_CONSTANT; |
5272 | goto redo; |
5273 | case TOK_VOLATILE1: |
5274 | case TOK_VOLATILE2: |
5275 | case TOK_VOLATILE3: |
5276 | qualifiers |= VT_VOLATILE; |
5277 | goto redo; |
5278 | case TOK_RESTRICT1: |
5279 | case TOK_RESTRICT2: |
5280 | case TOK_RESTRICT3: |
5281 | goto redo; |
5282 | /* XXX: clarify attribute handling */ |
5283 | case TOK_ATTRIBUTE1: |
5284 | case TOK_ATTRIBUTE2: |
5285 | parse_attribute(ad); |
5286 | break; |
5287 | } |
5288 | mk_pointer(type); |
5289 | type->t |= qualifiers; |
5290 | if (ret == type) |
5291 | /* innermost pointed to type is the one for the first derivation */ |
5292 | ret = pointed_type(type); |
5293 | } |
5294 | |
5295 | if (tok == '(') { |
5296 | /* This is possibly a parameter type list for abstract declarators |
5297 | ('int ()'), use post_type for testing this. */ |
5298 | if (!post_type(type, ad, 0, td)) { |
5299 | /* It's not, so it's a nested declarator, and the post operations |
5300 | apply to the innermost pointed to type (if any). */ |
5301 | /* XXX: this is not correct to modify 'ad' at this point, but |
5302 | the syntax is not clear */ |
5303 | parse_attribute(ad); |
5304 | post = type_decl(type, ad, v, td); |
5305 | skip(')'); |
5306 | } else |
5307 | goto abstract; |
5308 | } else if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) { |
5309 | /* type identifier */ |
5310 | *v = tok; |
5311 | next(); |
5312 | } else { |
5313 | abstract: |
5314 | if (!(td & TYPE_ABSTRACT)) |
5315 | expect("identifier" ); |
5316 | *v = 0; |
5317 | } |
5318 | post_type(post, ad, storage, 0); |
5319 | parse_attribute(ad); |
5320 | type->t |= storage; |
5321 | return ret; |
5322 | } |
5323 | |
5324 | /* indirection with full error checking and bound check */ |
5325 | ST_FUNC void indir(void) |
5326 | { |
5327 | if ((vtop->type.t & VT_BTYPE) != VT_PTR) { |
5328 | if ((vtop->type.t & VT_BTYPE) == VT_FUNC) |
5329 | return; |
5330 | expect("pointer" ); |
5331 | } |
5332 | if (vtop->r & VT_LVAL) |
5333 | gv(RC_INT); |
5334 | vtop->type = *pointed_type(&vtop->type); |
5335 | /* Arrays and functions are never lvalues */ |
5336 | if (!(vtop->type.t & (VT_ARRAY | VT_VLA)) |
5337 | && (vtop->type.t & VT_BTYPE) != VT_FUNC) { |
5338 | vtop->r |= VT_LVAL; |
5339 | /* if bound checking, the referenced pointer must be checked */ |
5340 | #ifdef CONFIG_TCC_BCHECK |
5341 | if (tcc_state->do_bounds_check) |
5342 | vtop->r |= VT_MUSTBOUND; |
5343 | #endif |
5344 | } |
5345 | } |
5346 | |
5347 | /* pass a parameter to a function and do type checking and casting */ |
5348 | static void gfunc_param_typed(Sym *func, Sym *arg) |
5349 | { |
5350 | int func_type; |
5351 | CType type; |
5352 | |
5353 | func_type = func->f.func_type; |
5354 | if (func_type == FUNC_OLD || |
5355 | (func_type == FUNC_ELLIPSIS && arg == NULL)) { |
5356 | /* default casting : only need to convert float to double */ |
5357 | if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) { |
5358 | gen_cast_s(VT_DOUBLE); |
5359 | } else if (vtop->type.t & VT_BITFIELD) { |
5360 | type.t = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); |
5361 | type.ref = vtop->type.ref; |
5362 | gen_cast(&type); |
5363 | } else if (vtop->r & VT_MUSTCAST) { |
5364 | force_charshort_cast(); |
5365 | } |
5366 | } else if (arg == NULL) { |
5367 | tcc_error("too many arguments to function" ); |
5368 | } else { |
5369 | type = arg->type; |
5370 | type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */ |
5371 | gen_assign_cast(&type); |
5372 | } |
5373 | } |
5374 | |
5375 | /* parse an expression and return its type without any side effect. */ |
5376 | static void expr_type(CType *type, void (*expr_fn)(void)) |
5377 | { |
5378 | nocode_wanted++; |
5379 | expr_fn(); |
5380 | *type = vtop->type; |
5381 | vpop(); |
5382 | nocode_wanted--; |
5383 | } |
5384 | |
5385 | /* parse an expression of the form '(type)' or '(expr)' and return its |
5386 | type */ |
5387 | static void parse_expr_type(CType *type) |
5388 | { |
5389 | int n; |
5390 | AttributeDef ad; |
5391 | |
5392 | skip('('); |
5393 | if (parse_btype(type, &ad)) { |
5394 | type_decl(type, &ad, &n, TYPE_ABSTRACT); |
5395 | } else { |
5396 | expr_type(type, gexpr); |
5397 | } |
5398 | skip(')'); |
5399 | } |
5400 | |
5401 | static void parse_type(CType *type) |
5402 | { |
5403 | AttributeDef ad; |
5404 | int n; |
5405 | |
5406 | if (!parse_btype(type, &ad)) { |
5407 | expect("type" ); |
5408 | } |
5409 | type_decl(type, &ad, &n, TYPE_ABSTRACT); |
5410 | } |
5411 | |
5412 | static void parse_builtin_params(int nc, const char *args) |
5413 | { |
5414 | char c, sep = '('; |
5415 | CType type; |
5416 | if (nc) |
5417 | nocode_wanted++; |
5418 | next(); |
5419 | if (*args == 0) |
5420 | skip(sep); |
5421 | while ((c = *args++)) { |
5422 | skip(sep); |
5423 | sep = ','; |
5424 | if (c == 't') { |
5425 | parse_type(&type); |
5426 | vpush(&type); |
5427 | continue; |
5428 | } |
5429 | expr_eq(); |
5430 | type.ref = NULL; |
5431 | type.t = 0; |
5432 | switch (c) { |
5433 | case 'e': |
5434 | continue; |
5435 | case 'V': |
5436 | type.t = VT_CONSTANT; |
5437 | case 'v': |
5438 | type.t |= VT_VOID; |
5439 | mk_pointer (&type); |
5440 | break; |
5441 | case 'S': |
5442 | type.t = VT_CONSTANT; |
5443 | case 's': |
5444 | type.t |= char_type.t; |
5445 | mk_pointer (&type); |
5446 | break; |
5447 | case 'i': |
5448 | type.t = VT_INT; |
5449 | break; |
5450 | case 'l': |
5451 | type.t = VT_SIZE_T; |
5452 | break; |
5453 | default: |
5454 | break; |
5455 | } |
5456 | gen_assign_cast(&type); |
5457 | } |
5458 | skip(')'); |
5459 | if (nc) |
5460 | nocode_wanted--; |
5461 | } |
5462 | |
5463 | ST_FUNC void unary(void) |
5464 | { |
5465 | int n, t, align, size, r, sizeof_caller; |
5466 | CType type; |
5467 | Sym *s; |
5468 | AttributeDef ad; |
5469 | |
5470 | /* generate line number info */ |
5471 | if (tcc_state->do_debug) |
5472 | tcc_debug_line(tcc_state); |
5473 | |
5474 | sizeof_caller = in_sizeof; |
5475 | in_sizeof = 0; |
5476 | type.ref = NULL; |
5477 | /* XXX: GCC 2.95.3 does not generate a table although it should be |
5478 | better here */ |
5479 | tok_next: |
5480 | switch(tok) { |
5481 | case TOK_EXTENSION: |
5482 | next(); |
5483 | goto tok_next; |
5484 | case TOK_LCHAR: |
5485 | #ifdef TCC_TARGET_PE |
5486 | t = VT_SHORT|VT_UNSIGNED; |
5487 | goto push_tokc; |
5488 | #endif |
5489 | case TOK_CINT: |
5490 | case TOK_CCHAR: |
5491 | t = VT_INT; |
5492 | push_tokc: |
5493 | type.t = t; |
5494 | vsetc(&type, VT_CONST, &tokc); |
5495 | next(); |
5496 | break; |
5497 | case TOK_CUINT: |
5498 | t = VT_INT | VT_UNSIGNED; |
5499 | goto push_tokc; |
5500 | case TOK_CLLONG: |
5501 | t = VT_LLONG; |
5502 | goto push_tokc; |
5503 | case TOK_CULLONG: |
5504 | t = VT_LLONG | VT_UNSIGNED; |
5505 | goto push_tokc; |
5506 | case TOK_CFLOAT: |
5507 | t = VT_FLOAT; |
5508 | goto push_tokc; |
5509 | case TOK_CDOUBLE: |
5510 | t = VT_DOUBLE; |
5511 | goto push_tokc; |
5512 | case TOK_CLDOUBLE: |
5513 | t = VT_LDOUBLE; |
5514 | goto push_tokc; |
5515 | case TOK_CLONG: |
5516 | t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG; |
5517 | goto push_tokc; |
5518 | case TOK_CULONG: |
5519 | t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG | VT_UNSIGNED; |
5520 | goto push_tokc; |
5521 | case TOK___FUNCTION__: |
5522 | if (!gnu_ext) |
5523 | goto tok_identifier; |
5524 | /* fall thru */ |
5525 | case TOK___FUNC__: |
5526 | { |
5527 | void *ptr; |
5528 | int len; |
5529 | /* special function name identifier */ |
5530 | len = strlen(funcname) + 1; |
5531 | /* generate char[len] type */ |
5532 | type.t = VT_BYTE; |
5533 | mk_pointer(&type); |
5534 | type.t |= VT_ARRAY; |
5535 | type.ref->c = len; |
5536 | vpush_ref(&type, data_section, data_section->data_offset, len); |
5537 | if (!NODATA_WANTED) { |
5538 | ptr = section_ptr_add(data_section, len); |
5539 | memcpy(ptr, funcname, len); |
5540 | } |
5541 | next(); |
5542 | } |
5543 | break; |
5544 | case TOK_LSTR: |
5545 | #ifdef TCC_TARGET_PE |
5546 | t = VT_SHORT | VT_UNSIGNED; |
5547 | #else |
5548 | t = VT_INT; |
5549 | #endif |
5550 | goto str_init; |
5551 | case TOK_STR: |
5552 | /* string parsing */ |
5553 | t = VT_BYTE; |
5554 | if (tcc_state->char_is_unsigned) |
5555 | t = VT_BYTE | VT_UNSIGNED; |
5556 | str_init: |
5557 | if (tcc_state->warn_write_strings) |
5558 | t |= VT_CONSTANT; |
5559 | type.t = t; |
5560 | mk_pointer(&type); |
5561 | type.t |= VT_ARRAY; |
5562 | memset(&ad, 0, sizeof(AttributeDef)); |
5563 | decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0); |
5564 | break; |
5565 | case '(': |
5566 | next(); |
5567 | /* cast ? */ |
5568 | if (parse_btype(&type, &ad)) { |
5569 | type_decl(&type, &ad, &n, TYPE_ABSTRACT); |
5570 | skip(')'); |
5571 | /* check ISOC99 compound literal */ |
5572 | if (tok == '{') { |
5573 | /* data is allocated locally by default */ |
5574 | if (global_expr) |
5575 | r = VT_CONST; |
5576 | else |
5577 | r = VT_LOCAL; |
5578 | /* all except arrays are lvalues */ |
5579 | if (!(type.t & VT_ARRAY)) |
5580 | r |= VT_LVAL; |
5581 | memset(&ad, 0, sizeof(AttributeDef)); |
5582 | decl_initializer_alloc(&type, &ad, r, 1, 0, 0); |
5583 | } else { |
5584 | if (sizeof_caller) { |
5585 | vpush(&type); |
5586 | return; |
5587 | } |
5588 | unary(); |
5589 | gen_cast(&type); |
5590 | } |
5591 | } else if (tok == '{') { |
5592 | int saved_nocode_wanted = nocode_wanted; |
5593 | if (const_wanted && !(nocode_wanted & unevalmask)) |
5594 | tcc_error("expected constant" ); |
5595 | /* save all registers */ |
5596 | save_regs(0); |
5597 | /* statement expression : we do not accept break/continue |
5598 | inside as GCC does. We do retain the nocode_wanted state, |
5599 | as statement expressions can't ever be entered from the |
5600 | outside, so any reactivation of code emission (from labels |
5601 | or loop heads) can be disabled again after the end of it. */ |
5602 | block(1); |
5603 | nocode_wanted = saved_nocode_wanted; |
5604 | skip(')'); |
5605 | } else { |
5606 | gexpr(); |
5607 | skip(')'); |
5608 | } |
5609 | break; |
5610 | case '*': |
5611 | next(); |
5612 | unary(); |
5613 | indir(); |
5614 | break; |
5615 | case '&': |
5616 | next(); |
5617 | unary(); |
5618 | /* functions names must be treated as function pointers, |
5619 | except for unary '&' and sizeof. Since we consider that |
5620 | functions are not lvalues, we only have to handle it |
5621 | there and in function calls. */ |
5622 | /* arrays can also be used although they are not lvalues */ |
5623 | if ((vtop->type.t & VT_BTYPE) != VT_FUNC && |
5624 | !(vtop->type.t & VT_ARRAY)) |
5625 | test_lvalue(); |
5626 | if (vtop->sym) |
5627 | vtop->sym->a.addrtaken = 1; |
5628 | mk_pointer(&vtop->type); |
5629 | gaddrof(); |
5630 | break; |
5631 | case '!': |
5632 | next(); |
5633 | unary(); |
5634 | gen_test_zero(TOK_EQ); |
5635 | break; |
5636 | case '~': |
5637 | next(); |
5638 | unary(); |
5639 | vpushi(-1); |
5640 | gen_op('^'); |
5641 | break; |
5642 | case '+': |
5643 | next(); |
5644 | unary(); |
5645 | if ((vtop->type.t & VT_BTYPE) == VT_PTR) |
5646 | tcc_error("pointer not accepted for unary plus" ); |
5647 | /* In order to force cast, we add zero, except for floating point |
5648 | where we really need an noop (otherwise -0.0 will be transformed |
5649 | into +0.0). */ |
5650 | if (!is_float(vtop->type.t)) { |
5651 | vpushi(0); |
5652 | gen_op('+'); |
5653 | } |
5654 | break; |
5655 | case TOK_SIZEOF: |
5656 | case TOK_ALIGNOF1: |
5657 | case TOK_ALIGNOF2: |
5658 | case TOK_ALIGNOF3: |
5659 | t = tok; |
5660 | next(); |
5661 | in_sizeof++; |
5662 | expr_type(&type, unary); /* Perform a in_sizeof = 0; */ |
5663 | s = NULL; |
5664 | if (vtop[1].r & VT_SYM) |
5665 | s = vtop[1].sym; /* hack: accessing previous vtop */ |
5666 | size = type_size(&type, &align); |
5667 | if (s && s->a.aligned) |
5668 | align = 1 << (s->a.aligned - 1); |
5669 | if (t == TOK_SIZEOF) { |
5670 | if (!(type.t & VT_VLA)) { |
5671 | if (size < 0) |
5672 | tcc_error("sizeof applied to an incomplete type" ); |
5673 | vpushs(size); |
5674 | } else { |
5675 | vla_runtime_type_size(&type, &align); |
5676 | } |
5677 | } else { |
5678 | vpushs(align); |
5679 | } |
5680 | vtop->type.t |= VT_UNSIGNED; |
5681 | break; |
5682 | |
5683 | case TOK_builtin_expect: |
5684 | /* __builtin_expect is a no-op for now */ |
5685 | parse_builtin_params(0, "ee" ); |
5686 | vpop(); |
5687 | break; |
5688 | case TOK_builtin_types_compatible_p: |
5689 | parse_builtin_params(0, "tt" ); |
5690 | vtop[-1].type.t &= ~(VT_CONSTANT | VT_VOLATILE); |
5691 | vtop[0].type.t &= ~(VT_CONSTANT | VT_VOLATILE); |
5692 | n = is_compatible_types(&vtop[-1].type, &vtop[0].type); |
5693 | vtop -= 2; |
5694 | vpushi(n); |
5695 | break; |
5696 | case TOK_builtin_choose_expr: |
5697 | { |
5698 | int64_t c; |
5699 | next(); |
5700 | skip('('); |
5701 | c = expr_const64(); |
5702 | skip(','); |
5703 | if (!c) { |
5704 | nocode_wanted++; |
5705 | } |
5706 | expr_eq(); |
5707 | if (!c) { |
5708 | vpop(); |
5709 | nocode_wanted--; |
5710 | } |
5711 | skip(','); |
5712 | if (c) { |
5713 | nocode_wanted++; |
5714 | } |
5715 | expr_eq(); |
5716 | if (c) { |
5717 | vpop(); |
5718 | nocode_wanted--; |
5719 | } |
5720 | skip(')'); |
5721 | } |
5722 | break; |
5723 | case TOK_builtin_constant_p: |
5724 | parse_builtin_params(1, "e" ); |
5725 | n = (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && |
5726 | !((vtop->r & VT_SYM) && vtop->sym->a.addrtaken); |
5727 | vtop--; |
5728 | vpushi(n); |
5729 | break; |
5730 | case TOK_builtin_frame_address: |
5731 | case TOK_builtin_return_address: |
5732 | { |
5733 | int tok1 = tok; |
5734 | int level; |
5735 | next(); |
5736 | skip('('); |
5737 | if (tok != TOK_CINT) { |
5738 | tcc_error("%s only takes positive integers" , |
5739 | tok1 == TOK_builtin_return_address ? |
5740 | "__builtin_return_address" : |
5741 | "__builtin_frame_address" ); |
5742 | } |
5743 | level = (uint32_t)tokc.i; |
5744 | next(); |
5745 | skip(')'); |
5746 | type.t = VT_VOID; |
5747 | mk_pointer(&type); |
5748 | vset(&type, VT_LOCAL, 0); /* local frame */ |
5749 | while (level--) { |
5750 | #ifdef TCC_TARGET_RISCV64 |
5751 | vpushi(2*PTR_SIZE); |
5752 | gen_op('-'); |
5753 | #endif |
5754 | mk_pointer(&vtop->type); |
5755 | indir(); /* -> parent frame */ |
5756 | } |
5757 | if (tok1 == TOK_builtin_return_address) { |
5758 | // assume return address is just above frame pointer on stack |
5759 | #ifdef TCC_TARGET_ARM |
5760 | vpushi(2*PTR_SIZE); |
5761 | gen_op('+'); |
5762 | #elif defined TCC_TARGET_RISCV64 |
5763 | vpushi(PTR_SIZE); |
5764 | gen_op('-'); |
5765 | #else |
5766 | vpushi(PTR_SIZE); |
5767 | gen_op('+'); |
5768 | #endif |
5769 | mk_pointer(&vtop->type); |
5770 | indir(); |
5771 | } |
5772 | } |
5773 | break; |
5774 | #ifdef TCC_TARGET_RISCV64 |
5775 | case TOK_builtin_va_start: |
5776 | parse_builtin_params(0, "ee" ); |
5777 | r = vtop->r & VT_VALMASK; |
5778 | if (r == VT_LLOCAL) |
5779 | r = VT_LOCAL; |
5780 | if (r != VT_LOCAL) |
5781 | tcc_error("__builtin_va_start expects a local variable" ); |
5782 | gen_va_start(); |
5783 | vstore(); |
5784 | break; |
5785 | #endif |
5786 | #ifdef TCC_TARGET_X86_64 |
5787 | #ifdef TCC_TARGET_PE |
5788 | case TOK_builtin_va_start: |
5789 | parse_builtin_params(0, "ee" ); |
5790 | r = vtop->r & VT_VALMASK; |
5791 | if (r == VT_LLOCAL) |
5792 | r = VT_LOCAL; |
5793 | if (r != VT_LOCAL) |
5794 | tcc_error("__builtin_va_start expects a local variable" ); |
5795 | vtop->r = r; |
5796 | vtop->type = char_pointer_type; |
5797 | vtop->c.i += 8; |
5798 | vstore(); |
5799 | break; |
5800 | #else |
5801 | case TOK_builtin_va_arg_types: |
5802 | parse_builtin_params(0, "t" ); |
5803 | vpushi(classify_x86_64_va_arg(&vtop->type)); |
5804 | vswap(); |
5805 | vpop(); |
5806 | break; |
5807 | #endif |
5808 | #endif |
5809 | |
5810 | #ifdef TCC_TARGET_ARM64 |
5811 | case TOK_builtin_va_start: { |
5812 | parse_builtin_params(0, "ee" ); |
5813 | //xx check types |
5814 | gen_va_start(); |
5815 | vpushi(0); |
5816 | vtop->type.t = VT_VOID; |
5817 | break; |
5818 | } |
5819 | case TOK_builtin_va_arg: { |
5820 | parse_builtin_params(0, "et" ); |
5821 | type = vtop->type; |
5822 | vpop(); |
5823 | //xx check types |
5824 | gen_va_arg(&type); |
5825 | vtop->type = type; |
5826 | break; |
5827 | } |
5828 | case TOK___arm64_clear_cache: { |
5829 | parse_builtin_params(0, "ee" ); |
5830 | gen_clear_cache(); |
5831 | vpushi(0); |
5832 | vtop->type.t = VT_VOID; |
5833 | break; |
5834 | } |
5835 | #endif |
5836 | |
5837 | /* pre operations */ |
5838 | case TOK_INC: |
5839 | case TOK_DEC: |
5840 | t = tok; |
5841 | next(); |
5842 | unary(); |
5843 | inc(0, t); |
5844 | break; |
5845 | case '-': |
5846 | next(); |
5847 | unary(); |
5848 | t = vtop->type.t & VT_BTYPE; |
5849 | if (is_float(t)) { |
5850 | /* In IEEE negate(x) isn't subtract(0,x), but rather |
5851 | subtract(-0, x). */ |
5852 | vpush(&vtop->type); |
5853 | if (t == VT_FLOAT) |
5854 | vtop->c.f = -1.0 * 0.0; |
5855 | else if (t == VT_DOUBLE) |
5856 | vtop->c.d = -1.0 * 0.0; |
5857 | else |
5858 | vtop->c.ld = -1.0 * 0.0; |
5859 | } else |
5860 | vpushi(0); |
5861 | vswap(); |
5862 | gen_op('-'); |
5863 | break; |
5864 | case TOK_LAND: |
5865 | if (!gnu_ext) |
5866 | goto tok_identifier; |
5867 | next(); |
5868 | /* allow to take the address of a label */ |
5869 | if (tok < TOK_UIDENT) |
5870 | expect("label identifier" ); |
5871 | s = label_find(tok); |
5872 | if (!s) { |
5873 | s = label_push(&global_label_stack, tok, LABEL_FORWARD); |
5874 | } else { |
5875 | if (s->r == LABEL_DECLARED) |
5876 | s->r = LABEL_FORWARD; |
5877 | } |
5878 | if (!s->type.t) { |
5879 | s->type.t = VT_VOID; |
5880 | mk_pointer(&s->type); |
5881 | s->type.t |= VT_STATIC; |
5882 | } |
5883 | vpushsym(&s->type, s); |
5884 | next(); |
5885 | break; |
5886 | |
5887 | case TOK_GENERIC: |
5888 | { |
5889 | CType controlling_type; |
5890 | int has_default = 0; |
5891 | int has_match = 0; |
5892 | int learn = 0; |
5893 | TokenString *str = NULL; |
5894 | int saved_const_wanted = const_wanted; |
5895 | |
5896 | next(); |
5897 | skip('('); |
5898 | const_wanted = 0; |
5899 | expr_type(&controlling_type, expr_eq); |
5900 | controlling_type.t &= ~(VT_CONSTANT | VT_VOLATILE | VT_ARRAY); |
5901 | if ((controlling_type.t & VT_BTYPE) == VT_FUNC) |
5902 | mk_pointer(&controlling_type); |
5903 | const_wanted = saved_const_wanted; |
5904 | for (;;) { |
5905 | learn = 0; |
5906 | skip(','); |
5907 | if (tok == TOK_DEFAULT) { |
5908 | if (has_default) |
5909 | tcc_error("too many 'default'" ); |
5910 | has_default = 1; |
5911 | if (!has_match) |
5912 | learn = 1; |
5913 | next(); |
5914 | } else { |
5915 | AttributeDef ad_tmp; |
5916 | int itmp; |
5917 | CType cur_type; |
5918 | |
5919 | in_generic++; |
5920 | parse_btype(&cur_type, &ad_tmp); |
5921 | in_generic--; |
5922 | |
5923 | type_decl(&cur_type, &ad_tmp, &itmp, TYPE_ABSTRACT); |
5924 | if (compare_types(&controlling_type, &cur_type, 0)) { |
5925 | if (has_match) { |
5926 | tcc_error("type match twice" ); |
5927 | } |
5928 | has_match = 1; |
5929 | learn = 1; |
5930 | } |
5931 | } |
5932 | skip(':'); |
5933 | if (learn) { |
5934 | if (str) |
5935 | tok_str_free(str); |
5936 | skip_or_save_block(&str); |
5937 | } else { |
5938 | skip_or_save_block(NULL); |
5939 | } |
5940 | if (tok == ')') |
5941 | break; |
5942 | } |
5943 | if (!str) { |
5944 | char buf[60]; |
5945 | type_to_str(buf, sizeof buf, &controlling_type, NULL); |
5946 | tcc_error("type '%s' does not match any association" , buf); |
5947 | } |
5948 | begin_macro(str, 1); |
5949 | next(); |
5950 | expr_eq(); |
5951 | if (tok != TOK_EOF) |
5952 | expect("," ); |
5953 | end_macro(); |
5954 | next(); |
5955 | break; |
5956 | } |
5957 | // special qnan , snan and infinity values |
5958 | case TOK___NAN__: |
5959 | n = 0x7fc00000; |
5960 | special_math_val: |
5961 | vpushi(n); |
5962 | vtop->type.t = VT_FLOAT; |
5963 | next(); |
5964 | break; |
5965 | case TOK___SNAN__: |
5966 | n = 0x7f800001; |
5967 | goto special_math_val; |
5968 | case TOK___INF__: |
5969 | n = 0x7f800000; |
5970 | goto special_math_val; |
5971 | |
5972 | default: |
5973 | tok_identifier: |
5974 | t = tok; |
5975 | next(); |
5976 | if (t < TOK_UIDENT) |
5977 | expect("identifier" ); |
5978 | s = sym_find(t); |
5979 | if (!s || IS_ASM_SYM(s)) { |
5980 | const char *name = get_tok_str(t, NULL); |
5981 | if (tok != '(') |
5982 | tcc_error("'%s' undeclared" , name); |
5983 | /* for simple function calls, we tolerate undeclared |
5984 | external reference to int() function */ |
5985 | if (tcc_state->warn_implicit_function_declaration |
5986 | #ifdef TCC_TARGET_PE |
5987 | /* people must be warned about using undeclared WINAPI functions |
5988 | (which usually start with uppercase letter) */ |
5989 | || (name[0] >= 'A' && name[0] <= 'Z') |
5990 | #endif |
5991 | ) |
5992 | tcc_warning("implicit declaration of function '%s'" , name); |
5993 | s = external_global_sym(t, &func_old_type); |
5994 | } |
5995 | |
5996 | r = s->r; |
5997 | /* A symbol that has a register is a local register variable, |
5998 | which starts out as VT_LOCAL value. */ |
5999 | if ((r & VT_VALMASK) < VT_CONST) |
6000 | r = (r & ~VT_VALMASK) | VT_LOCAL; |
6001 | |
6002 | vset(&s->type, r, s->c); |
6003 | /* Point to s as backpointer (even without r&VT_SYM). |
6004 | Will be used by at least the x86 inline asm parser for |
6005 | regvars. */ |
6006 | vtop->sym = s; |
6007 | |
6008 | if (r & VT_SYM) { |
6009 | vtop->c.i = 0; |
6010 | } else if (r == VT_CONST && IS_ENUM_VAL(s->type.t)) { |
6011 | vtop->c.i = s->enum_val; |
6012 | } |
6013 | break; |
6014 | } |
6015 | |
6016 | /* post operations */ |
6017 | while (1) { |
6018 | if (tok == TOK_INC || tok == TOK_DEC) { |
6019 | inc(1, tok); |
6020 | next(); |
6021 | } else if (tok == '.' || tok == TOK_ARROW || tok == TOK_CDOUBLE) { |
6022 | int qualifiers, cumofs = 0; |
6023 | /* field */ |
6024 | if (tok == TOK_ARROW) |
6025 | indir(); |
6026 | qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE); |
6027 | test_lvalue(); |
6028 | gaddrof(); |
6029 | /* expect pointer on structure */ |
6030 | if ((vtop->type.t & VT_BTYPE) != VT_STRUCT) |
6031 | expect("struct or union" ); |
6032 | if (tok == TOK_CDOUBLE) |
6033 | expect("field name" ); |
6034 | next(); |
6035 | if (tok == TOK_CINT || tok == TOK_CUINT) |
6036 | expect("field name" ); |
6037 | s = find_field(&vtop->type, tok, &cumofs); |
6038 | if (!s) |
6039 | tcc_error("field not found: %s" , get_tok_str(tok & ~SYM_FIELD, &tokc)); |
6040 | /* add field offset to pointer */ |
6041 | vtop->type = char_pointer_type; /* change type to 'char *' */ |
6042 | vpushi(cumofs + s->c); |
6043 | gen_op('+'); |
6044 | /* change type to field type, and set to lvalue */ |
6045 | vtop->type = s->type; |
6046 | vtop->type.t |= qualifiers; |
6047 | /* an array is never an lvalue */ |
6048 | if (!(vtop->type.t & VT_ARRAY)) { |
6049 | vtop->r |= VT_LVAL; |
6050 | #ifdef CONFIG_TCC_BCHECK |
6051 | /* if bound checking, the referenced pointer must be checked */ |
6052 | if (tcc_state->do_bounds_check) |
6053 | vtop->r |= VT_MUSTBOUND; |
6054 | #endif |
6055 | } |
6056 | next(); |
6057 | } else if (tok == '[') { |
6058 | next(); |
6059 | gexpr(); |
6060 | gen_op('+'); |
6061 | indir(); |
6062 | skip(']'); |
6063 | } else if (tok == '(') { |
6064 | SValue ret; |
6065 | Sym *sa; |
6066 | int nb_args, ret_nregs, ret_align, regsize, variadic; |
6067 | |
6068 | /* function call */ |
6069 | if ((vtop->type.t & VT_BTYPE) != VT_FUNC) { |
6070 | /* pointer test (no array accepted) */ |
6071 | if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) { |
6072 | vtop->type = *pointed_type(&vtop->type); |
6073 | if ((vtop->type.t & VT_BTYPE) != VT_FUNC) |
6074 | goto error_func; |
6075 | } else { |
6076 | error_func: |
6077 | expect("function pointer" ); |
6078 | } |
6079 | } else { |
6080 | vtop->r &= ~VT_LVAL; /* no lvalue */ |
6081 | } |
6082 | /* get return type */ |
6083 | s = vtop->type.ref; |
6084 | next(); |
6085 | sa = s->next; /* first parameter */ |
6086 | nb_args = regsize = 0; |
6087 | ret.r2 = VT_CONST; |
6088 | /* compute first implicit argument if a structure is returned */ |
6089 | if ((s->type.t & VT_BTYPE) == VT_STRUCT) { |
6090 | variadic = (s->f.func_type == FUNC_ELLIPSIS); |
6091 | ret_nregs = gfunc_sret(&s->type, variadic, &ret.type, |
6092 | &ret_align, ®size); |
6093 | if (ret_nregs <= 0) { |
6094 | /* get some space for the returned structure */ |
6095 | size = type_size(&s->type, &align); |
6096 | #ifdef TCC_TARGET_ARM64 |
6097 | /* On arm64, a small struct is return in registers. |
6098 | It is much easier to write it to memory if we know |
6099 | that we are allowed to write some extra bytes, so |
6100 | round the allocated space up to a power of 2: */ |
6101 | if (size < 16) |
6102 | while (size & (size - 1)) |
6103 | size = (size | (size - 1)) + 1; |
6104 | #endif |
6105 | loc = (loc - size) & -align; |
6106 | ret.type = s->type; |
6107 | ret.r = VT_LOCAL | VT_LVAL; |
6108 | /* pass it as 'int' to avoid structure arg passing |
6109 | problems */ |
6110 | vseti(VT_LOCAL, loc); |
6111 | #ifdef CONFIG_TCC_BCHECK |
6112 | if (tcc_state->do_bounds_check) |
6113 | --loc; |
6114 | #endif |
6115 | ret.c = vtop->c; |
6116 | if (ret_nregs < 0) |
6117 | vtop--; |
6118 | else |
6119 | nb_args++; |
6120 | } |
6121 | } else { |
6122 | ret_nregs = 1; |
6123 | ret.type = s->type; |
6124 | } |
6125 | |
6126 | if (ret_nregs > 0) { |
6127 | /* return in register */ |
6128 | ret.c.i = 0; |
6129 | PUT_R_RET(&ret, ret.type.t); |
6130 | } |
6131 | if (tok != ')') { |
6132 | for(;;) { |
6133 | expr_eq(); |
6134 | gfunc_param_typed(s, sa); |
6135 | nb_args++; |
6136 | if (sa) |
6137 | sa = sa->next; |
6138 | if (tok == ')') |
6139 | break; |
6140 | skip(','); |
6141 | } |
6142 | } |
6143 | if (sa) |
6144 | tcc_error("too few arguments to function" ); |
6145 | skip(')'); |
6146 | gfunc_call(nb_args); |
6147 | |
6148 | if (ret_nregs < 0) { |
6149 | vsetc(&ret.type, ret.r, &ret.c); |
6150 | #ifdef TCC_TARGET_RISCV64 |
6151 | arch_transfer_ret_regs(1); |
6152 | #endif |
6153 | } else { |
6154 | /* return value */ |
6155 | for (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) { |
6156 | vsetc(&ret.type, r, &ret.c); |
6157 | vtop->r2 = ret.r2; /* Loop only happens when r2 is VT_CONST */ |
6158 | } |
6159 | |
6160 | /* handle packed struct return */ |
6161 | if (((s->type.t & VT_BTYPE) == VT_STRUCT) && ret_nregs) { |
6162 | int addr, offset; |
6163 | |
6164 | size = type_size(&s->type, &align); |
6165 | /* We're writing whole regs often, make sure there's enough |
6166 | space. Assume register size is power of 2. */ |
6167 | if (regsize > align) |
6168 | align = regsize; |
6169 | loc = (loc - size) & -align; |
6170 | addr = loc; |
6171 | offset = 0; |
6172 | for (;;) { |
6173 | vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset); |
6174 | vswap(); |
6175 | vstore(); |
6176 | vtop--; |
6177 | if (--ret_nregs == 0) |
6178 | break; |
6179 | offset += regsize; |
6180 | } |
6181 | vset(&s->type, VT_LOCAL | VT_LVAL, addr); |
6182 | } |
6183 | |
6184 | /* Promote char/short return values. This is matters only |
6185 | for calling function that were not compiled by TCC and |
6186 | only on some architectures. For those where it doesn't |
6187 | matter we expect things to be already promoted to int, |
6188 | but not larger. */ |
6189 | t = s->type.t & VT_BTYPE; |
6190 | if (t == VT_BYTE || t == VT_SHORT || t == VT_BOOL) { |
6191 | #ifdef PROMOTE_RET |
6192 | vtop->r |= BFVAL(VT_MUSTCAST, 1); |
6193 | #else |
6194 | vtop->type.t = VT_INT; |
6195 | #endif |
6196 | } |
6197 | } |
6198 | if (s->f.func_noreturn) |
6199 | CODE_OFF(); |
6200 | } else { |
6201 | break; |
6202 | } |
6203 | } |
6204 | } |
6205 | |
6206 | #ifndef precedence_parser /* original top-down parser */ |
6207 | |
6208 | static void expr_prod(void) |
6209 | { |
6210 | int t; |
6211 | |
6212 | unary(); |
6213 | while ((t = tok) == '*' || t == '/' || t == '%') { |
6214 | next(); |
6215 | unary(); |
6216 | gen_op(t); |
6217 | } |
6218 | } |
6219 | |
6220 | static void expr_sum(void) |
6221 | { |
6222 | int t; |
6223 | |
6224 | expr_prod(); |
6225 | while ((t = tok) == '+' || t == '-') { |
6226 | next(); |
6227 | expr_prod(); |
6228 | gen_op(t); |
6229 | } |
6230 | } |
6231 | |
6232 | static void expr_shift(void) |
6233 | { |
6234 | int t; |
6235 | |
6236 | expr_sum(); |
6237 | while ((t = tok) == TOK_SHL || t == TOK_SAR) { |
6238 | next(); |
6239 | expr_sum(); |
6240 | gen_op(t); |
6241 | } |
6242 | } |
6243 | |
6244 | static void expr_cmp(void) |
6245 | { |
6246 | int t; |
6247 | |
6248 | expr_shift(); |
6249 | while (((t = tok) >= TOK_ULE && t <= TOK_GT) || |
6250 | t == TOK_ULT || t == TOK_UGE) { |
6251 | next(); |
6252 | expr_shift(); |
6253 | gen_op(t); |
6254 | } |
6255 | } |
6256 | |
6257 | static void expr_cmpeq(void) |
6258 | { |
6259 | int t; |
6260 | |
6261 | expr_cmp(); |
6262 | while ((t = tok) == TOK_EQ || t == TOK_NE) { |
6263 | next(); |
6264 | expr_cmp(); |
6265 | gen_op(t); |
6266 | } |
6267 | } |
6268 | |
6269 | static void expr_and(void) |
6270 | { |
6271 | expr_cmpeq(); |
6272 | while (tok == '&') { |
6273 | next(); |
6274 | expr_cmpeq(); |
6275 | gen_op('&'); |
6276 | } |
6277 | } |
6278 | |
6279 | static void expr_xor(void) |
6280 | { |
6281 | expr_and(); |
6282 | while (tok == '^') { |
6283 | next(); |
6284 | expr_and(); |
6285 | gen_op('^'); |
6286 | } |
6287 | } |
6288 | |
6289 | static void expr_or(void) |
6290 | { |
6291 | expr_xor(); |
6292 | while (tok == '|') { |
6293 | next(); |
6294 | expr_xor(); |
6295 | gen_op('|'); |
6296 | } |
6297 | } |
6298 | |
6299 | static void expr_landor(int op); |
6300 | |
6301 | static void expr_land(void) |
6302 | { |
6303 | expr_or(); |
6304 | if (tok == TOK_LAND) |
6305 | expr_landor(tok); |
6306 | } |
6307 | |
6308 | static void expr_lor(void) |
6309 | { |
6310 | expr_land(); |
6311 | if (tok == TOK_LOR) |
6312 | expr_landor(tok); |
6313 | } |
6314 | |
6315 | # define expr_landor_next(op) op == TOK_LAND ? expr_or() : expr_land() |
6316 | #else /* defined precedence_parser */ |
6317 | # define expr_landor_next(op) unary(), expr_infix(precedence(op) + 1) |
6318 | # define expr_lor() unary(), expr_infix(1) |
6319 | |
6320 | static int precedence(int tok) |
6321 | { |
6322 | switch (tok) { |
6323 | case TOK_LOR: return 1; |
6324 | case TOK_LAND: return 2; |
6325 | case '|': return 3; |
6326 | case '^': return 4; |
6327 | case '&': return 5; |
6328 | case TOK_EQ: case TOK_NE: return 6; |
6329 | relat: case TOK_ULT: case TOK_UGE: return 7; |
6330 | case TOK_SHL: case TOK_SAR: return 8; |
6331 | case '+': case '-': return 9; |
6332 | case '*': case '/': case '%': return 10; |
6333 | default: |
6334 | if (tok >= TOK_ULE && tok <= TOK_GT) |
6335 | goto relat; |
6336 | return 0; |
6337 | } |
6338 | } |
6339 | static unsigned char prec[256]; |
6340 | static void init_prec(void) |
6341 | { |
6342 | int i; |
6343 | for (i = 0; i < 256; i++) |
6344 | prec[i] = precedence(i); |
6345 | } |
6346 | #define precedence(i) ((unsigned)i < 256 ? prec[i] : 0) |
6347 | |
6348 | static void expr_landor(int op); |
6349 | |
6350 | static void expr_infix(int p) |
6351 | { |
6352 | int t = tok, p2; |
6353 | while ((p2 = precedence(t)) >= p) { |
6354 | if (t == TOK_LOR || t == TOK_LAND) { |
6355 | expr_landor(t); |
6356 | } else { |
6357 | next(); |
6358 | unary(); |
6359 | if (precedence(tok) > p2) |
6360 | expr_infix(p2 + 1); |
6361 | gen_op(t); |
6362 | } |
6363 | t = tok; |
6364 | } |
6365 | } |
6366 | #endif |
6367 | |
6368 | /* Assuming vtop is a value used in a conditional context |
6369 | (i.e. compared with zero) return 0 if it's false, 1 if |
6370 | true and -1 if it can't be statically determined. */ |
6371 | static int condition_3way(void) |
6372 | { |
6373 | int c = -1; |
6374 | if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && |
6375 | (!(vtop->r & VT_SYM) || !vtop->sym->a.weak)) { |
6376 | vdup(); |
6377 | gen_cast_s(VT_BOOL); |
6378 | c = vtop->c.i; |
6379 | vpop(); |
6380 | } |
6381 | return c; |
6382 | } |
6383 | |
6384 | static void expr_landor(int op) |
6385 | { |
6386 | int t = 0, cc = 1, f = 0, i = op == TOK_LAND, c; |
6387 | for(;;) { |
6388 | c = f ? i : condition_3way(); |
6389 | if (c < 0) |
6390 | save_regs(1), cc = 0; |
6391 | else if (c != i) |
6392 | nocode_wanted++, f = 1; |
6393 | if (tok != op) |
6394 | break; |
6395 | if (c < 0) |
6396 | t = gvtst(i, t); |
6397 | else |
6398 | vpop(); |
6399 | next(); |
6400 | expr_landor_next(op); |
6401 | } |
6402 | if (cc || f) { |
6403 | vpop(); |
6404 | vpushi(i ^ f); |
6405 | gsym(t); |
6406 | nocode_wanted -= f; |
6407 | } else { |
6408 | gvtst_set(i, t); |
6409 | } |
6410 | } |
6411 | |
6412 | static int is_cond_bool(SValue *sv) |
6413 | { |
6414 | if ((sv->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST |
6415 | && (sv->type.t & VT_BTYPE) == VT_INT) |
6416 | return (unsigned)sv->c.i < 2; |
6417 | if (sv->r == VT_CMP) |
6418 | return 1; |
6419 | return 0; |
6420 | } |
6421 | |
6422 | static void expr_cond(void) |
6423 | { |
6424 | int tt, u, r1, r2, rc, t1, t2, islv, c, g; |
6425 | SValue sv; |
6426 | CType type; |
6427 | int ncw_prev; |
6428 | |
6429 | expr_lor(); |
6430 | if (tok == '?') { |
6431 | next(); |
6432 | c = condition_3way(); |
6433 | g = (tok == ':' && gnu_ext); |
6434 | tt = 0; |
6435 | if (!g) { |
6436 | if (c < 0) { |
6437 | save_regs(1); |
6438 | tt = gvtst(1, 0); |
6439 | } else { |
6440 | vpop(); |
6441 | } |
6442 | } else if (c < 0) { |
6443 | /* needed to avoid having different registers saved in |
6444 | each branch */ |
6445 | save_regs(1); |
6446 | gv_dup(); |
6447 | tt = gvtst(0, 0); |
6448 | } |
6449 | |
6450 | ncw_prev = nocode_wanted; |
6451 | if (c == 0) |
6452 | nocode_wanted++; |
6453 | if (!g) |
6454 | gexpr(); |
6455 | |
6456 | if (c < 0 && vtop->r == VT_CMP) { |
6457 | t1 = gvtst(0, 0); |
6458 | vpushi(0); |
6459 | gvtst_set(0, t1); |
6460 | gv(RC_INT); |
6461 | } |
6462 | |
6463 | if ((vtop->type.t & VT_BTYPE) == VT_FUNC) |
6464 | mk_pointer(&vtop->type); |
6465 | sv = *vtop; /* save value to handle it later */ |
6466 | vtop--; /* no vpop so that FP stack is not flushed */ |
6467 | |
6468 | if (g) { |
6469 | u = tt; |
6470 | } else if (c < 0) { |
6471 | u = gjmp(0); |
6472 | gsym(tt); |
6473 | } else |
6474 | u = 0; |
6475 | |
6476 | nocode_wanted = ncw_prev; |
6477 | if (c == 1) |
6478 | nocode_wanted++; |
6479 | skip(':'); |
6480 | expr_cond(); |
6481 | |
6482 | if (c < 0 && is_cond_bool(vtop) && is_cond_bool(&sv)) { |
6483 | if (sv.r == VT_CMP) { |
6484 | t1 = sv.jtrue; |
6485 | t2 = u; |
6486 | } else { |
6487 | t1 = gvtst(0, 0); |
6488 | t2 = gjmp(0); |
6489 | gsym(u); |
6490 | vpushv(&sv); |
6491 | } |
6492 | gvtst_set(0, t1); |
6493 | gvtst_set(1, t2); |
6494 | nocode_wanted = ncw_prev; |
6495 | // tcc_warning("two conditions expr_cond"); |
6496 | return; |
6497 | } |
6498 | |
6499 | if ((vtop->type.t & VT_BTYPE) == VT_FUNC) |
6500 | mk_pointer(&vtop->type); |
6501 | |
6502 | /* cast operands to correct type according to ISOC rules */ |
6503 | if (!combine_types(&type, &sv, vtop, '?')) |
6504 | type_incompatibility_error(&sv.type, &vtop->type, |
6505 | "type mismatch in conditional expression (have '%s' and '%s')" ); |
6506 | /* keep structs lvalue by transforming `(expr ? a : b)` to `*(expr ? &a : &b)` so |
6507 | that `(expr ? a : b).mem` does not error with "lvalue expected" */ |
6508 | islv = (vtop->r & VT_LVAL) && (sv.r & VT_LVAL) && VT_STRUCT == (type.t & VT_BTYPE); |
6509 | |
6510 | /* now we convert second operand */ |
6511 | if (c != 1) { |
6512 | gen_cast(&type); |
6513 | if (islv) { |
6514 | mk_pointer(&vtop->type); |
6515 | gaddrof(); |
6516 | } else if (VT_STRUCT == (vtop->type.t & VT_BTYPE)) |
6517 | gaddrof(); |
6518 | } |
6519 | |
6520 | rc = RC_TYPE(type.t); |
6521 | /* for long longs, we use fixed registers to avoid having |
6522 | to handle a complicated move */ |
6523 | if (USING_TWO_WORDS(type.t)) |
6524 | rc = RC_RET(type.t); |
6525 | |
6526 | tt = r2 = 0; |
6527 | if (c < 0) { |
6528 | r2 = gv(rc); |
6529 | tt = gjmp(0); |
6530 | } |
6531 | gsym(u); |
6532 | nocode_wanted = ncw_prev; |
6533 | |
6534 | /* this is horrible, but we must also convert first |
6535 | operand */ |
6536 | if (c != 0) { |
6537 | *vtop = sv; |
6538 | gen_cast(&type); |
6539 | if (islv) { |
6540 | mk_pointer(&vtop->type); |
6541 | gaddrof(); |
6542 | } else if (VT_STRUCT == (vtop->type.t & VT_BTYPE)) |
6543 | gaddrof(); |
6544 | } |
6545 | |
6546 | if (c < 0) { |
6547 | r1 = gv(rc); |
6548 | move_reg(r2, r1, islv ? VT_PTR : type.t); |
6549 | vtop->r = r2; |
6550 | gsym(tt); |
6551 | } |
6552 | |
6553 | if (islv) |
6554 | indir(); |
6555 | } |
6556 | } |
6557 | |
6558 | static void expr_eq(void) |
6559 | { |
6560 | int t; |
6561 | |
6562 | expr_cond(); |
6563 | if ((t = tok) == '=' || TOK_ASSIGN(t)) { |
6564 | test_lvalue(); |
6565 | next(); |
6566 | if (t == '=') { |
6567 | expr_eq(); |
6568 | } else { |
6569 | vdup(); |
6570 | expr_eq(); |
6571 | gen_op(TOK_ASSIGN_OP(t)); |
6572 | } |
6573 | vstore(); |
6574 | } |
6575 | } |
6576 | |
6577 | ST_FUNC void gexpr(void) |
6578 | { |
6579 | while (1) { |
6580 | expr_eq(); |
6581 | if (tok != ',') |
6582 | break; |
6583 | vpop(); |
6584 | next(); |
6585 | } |
6586 | } |
6587 | |
6588 | /* parse a constant expression and return value in vtop. */ |
6589 | static void expr_const1(void) |
6590 | { |
6591 | const_wanted++; |
6592 | nocode_wanted += unevalmask + 1; |
6593 | expr_cond(); |
6594 | nocode_wanted -= unevalmask + 1; |
6595 | const_wanted--; |
6596 | } |
6597 | |
6598 | /* parse an integer constant and return its value. */ |
6599 | static inline int64_t expr_const64(void) |
6600 | { |
6601 | int64_t c; |
6602 | expr_const1(); |
6603 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) |
6604 | expect("constant expression" ); |
6605 | c = vtop->c.i; |
6606 | vpop(); |
6607 | return c; |
6608 | } |
6609 | |
6610 | /* parse an integer constant and return its value. |
6611 | Complain if it doesn't fit 32bit (signed or unsigned). */ |
6612 | ST_FUNC int expr_const(void) |
6613 | { |
6614 | int c; |
6615 | int64_t wc = expr_const64(); |
6616 | c = wc; |
6617 | if (c != wc && (unsigned)c != wc) |
6618 | tcc_error("constant exceeds 32 bit" ); |
6619 | return c; |
6620 | } |
6621 | |
6622 | /* ------------------------------------------------------------------------- */ |
6623 | /* return from function */ |
6624 | |
6625 | #ifndef TCC_TARGET_ARM64 |
6626 | static void gfunc_return(CType *func_type) |
6627 | { |
6628 | if ((func_type->t & VT_BTYPE) == VT_STRUCT) { |
6629 | CType type, ret_type; |
6630 | int ret_align, ret_nregs, regsize; |
6631 | ret_nregs = gfunc_sret(func_type, func_var, &ret_type, |
6632 | &ret_align, ®size); |
6633 | if (ret_nregs < 0) { |
6634 | #ifdef TCC_TARGET_RISCV64 |
6635 | arch_transfer_ret_regs(0); |
6636 | #endif |
6637 | } else if (0 == ret_nregs) { |
6638 | /* if returning structure, must copy it to implicit |
6639 | first pointer arg location */ |
6640 | type = *func_type; |
6641 | mk_pointer(&type); |
6642 | vset(&type, VT_LOCAL | VT_LVAL, func_vc); |
6643 | indir(); |
6644 | vswap(); |
6645 | /* copy structure value to pointer */ |
6646 | vstore(); |
6647 | } else { |
6648 | /* returning structure packed into registers */ |
6649 | int size, addr, align, rc; |
6650 | size = type_size(func_type,&align); |
6651 | if ((vtop->r != (VT_LOCAL | VT_LVAL) || |
6652 | (vtop->c.i & (ret_align-1))) |
6653 | && (align & (ret_align-1))) { |
6654 | loc = (loc - size) & -ret_align; |
6655 | addr = loc; |
6656 | type = *func_type; |
6657 | vset(&type, VT_LOCAL | VT_LVAL, addr); |
6658 | vswap(); |
6659 | vstore(); |
6660 | vpop(); |
6661 | vset(&ret_type, VT_LOCAL | VT_LVAL, addr); |
6662 | } |
6663 | vtop->type = ret_type; |
6664 | rc = RC_RET(ret_type.t); |
6665 | if (ret_nregs == 1) |
6666 | gv(rc); |
6667 | else { |
6668 | for (;;) { |
6669 | vdup(); |
6670 | gv(rc); |
6671 | vpop(); |
6672 | if (--ret_nregs == 0) |
6673 | break; |
6674 | /* We assume that when a structure is returned in multiple |
6675 | registers, their classes are consecutive values of the |
6676 | suite s(n) = 2^n */ |
6677 | rc <<= 1; |
6678 | vtop->c.i += regsize; |
6679 | } |
6680 | } |
6681 | } |
6682 | } else { |
6683 | gv(RC_RET(func_type->t)); |
6684 | } |
6685 | vtop--; /* NOT vpop() because on x86 it would flush the fp stack */ |
6686 | } |
6687 | #endif |
6688 | |
6689 | static void check_func_return(void) |
6690 | { |
6691 | if ((func_vt.t & VT_BTYPE) == VT_VOID) |
6692 | return; |
6693 | if (!strcmp (funcname, "main" ) |
6694 | && (func_vt.t & VT_BTYPE) == VT_INT) { |
6695 | /* main returns 0 by default */ |
6696 | vpushi(0); |
6697 | gen_assign_cast(&func_vt); |
6698 | gfunc_return(&func_vt); |
6699 | } else { |
6700 | tcc_warning("function might return no value: '%s'" , funcname); |
6701 | } |
6702 | } |
6703 | |
6704 | /* ------------------------------------------------------------------------- */ |
6705 | /* switch/case */ |
6706 | |
6707 | static int case_cmpi(const void *pa, const void *pb) |
6708 | { |
6709 | int64_t a = (*(struct case_t**) pa)->v1; |
6710 | int64_t b = (*(struct case_t**) pb)->v1; |
6711 | return a < b ? -1 : a > b; |
6712 | } |
6713 | |
6714 | static int case_cmpu(const void *pa, const void *pb) |
6715 | { |
6716 | uint64_t a = (uint64_t)(*(struct case_t**) pa)->v1; |
6717 | uint64_t b = (uint64_t)(*(struct case_t**) pb)->v1; |
6718 | return a < b ? -1 : a > b; |
6719 | } |
6720 | |
6721 | static void gtst_addr(int t, int a) |
6722 | { |
6723 | gsym_addr(gvtst(0, t), a); |
6724 | } |
6725 | |
6726 | static void gcase(struct case_t **base, int len, int *bsym) |
6727 | { |
6728 | struct case_t *p; |
6729 | int e; |
6730 | int ll = (vtop->type.t & VT_BTYPE) == VT_LLONG; |
6731 | while (len > 8) { |
6732 | /* binary search */ |
6733 | p = base[len/2]; |
6734 | vdup(); |
6735 | if (ll) |
6736 | vpushll(p->v2); |
6737 | else |
6738 | vpushi(p->v2); |
6739 | gen_op(TOK_LE); |
6740 | e = gvtst(1, 0); |
6741 | vdup(); |
6742 | if (ll) |
6743 | vpushll(p->v1); |
6744 | else |
6745 | vpushi(p->v1); |
6746 | gen_op(TOK_GE); |
6747 | gtst_addr(0, p->sym); /* v1 <= x <= v2 */ |
6748 | /* x < v1 */ |
6749 | gcase(base, len/2, bsym); |
6750 | /* x > v2 */ |
6751 | gsym(e); |
6752 | e = len/2 + 1; |
6753 | base += e; len -= e; |
6754 | } |
6755 | /* linear scan */ |
6756 | while (len--) { |
6757 | p = *base++; |
6758 | vdup(); |
6759 | if (ll) |
6760 | vpushll(p->v2); |
6761 | else |
6762 | vpushi(p->v2); |
6763 | if (p->v1 == p->v2) { |
6764 | gen_op(TOK_EQ); |
6765 | gtst_addr(0, p->sym); |
6766 | } else { |
6767 | gen_op(TOK_LE); |
6768 | e = gvtst(1, 0); |
6769 | vdup(); |
6770 | if (ll) |
6771 | vpushll(p->v1); |
6772 | else |
6773 | vpushi(p->v1); |
6774 | gen_op(TOK_GE); |
6775 | gtst_addr(0, p->sym); |
6776 | gsym(e); |
6777 | } |
6778 | } |
6779 | *bsym = gjmp(*bsym); |
6780 | } |
6781 | |
6782 | /* ------------------------------------------------------------------------- */ |
6783 | /* __attribute__((cleanup(fn))) */ |
6784 | |
6785 | static void try_call_scope_cleanup(Sym *stop) |
6786 | { |
6787 | Sym *cls = cur_scope->cl.s; |
6788 | |
6789 | for (; cls != stop; cls = cls->ncl) { |
6790 | Sym *fs = cls->next; |
6791 | Sym *vs = cls->prev_tok; |
6792 | |
6793 | vpushsym(&fs->type, fs); |
6794 | vset(&vs->type, vs->r, vs->c); |
6795 | vtop->sym = vs; |
6796 | mk_pointer(&vtop->type); |
6797 | gaddrof(); |
6798 | gfunc_call(1); |
6799 | } |
6800 | } |
6801 | |
6802 | static void try_call_cleanup_goto(Sym *cleanupstate) |
6803 | { |
6804 | Sym *oc, *cc; |
6805 | int ocd, ccd; |
6806 | |
6807 | if (!cur_scope->cl.s) |
6808 | return; |
6809 | |
6810 | /* search NCA of both cleanup chains given parents and initial depth */ |
6811 | ocd = cleanupstate ? cleanupstate->v & ~SYM_FIELD : 0; |
6812 | for (ccd = cur_scope->cl.n, oc = cleanupstate; ocd > ccd; --ocd, oc = oc->ncl) |
6813 | ; |
6814 | for (cc = cur_scope->cl.s; ccd > ocd; --ccd, cc = cc->ncl) |
6815 | ; |
6816 | for (; cc != oc; cc = cc->ncl, oc = oc->ncl, --ccd) |
6817 | ; |
6818 | |
6819 | try_call_scope_cleanup(cc); |
6820 | } |
6821 | |
6822 | /* call 'func' for each __attribute__((cleanup(func))) */ |
6823 | static void block_cleanup(struct scope *o) |
6824 | { |
6825 | int jmp = 0; |
6826 | Sym *g, **pg; |
6827 | for (pg = &pending_gotos; (g = *pg) && g->c > o->cl.n;) { |
6828 | if (g->prev_tok->r & LABEL_FORWARD) { |
6829 | Sym *pcl = g->next; |
6830 | if (!jmp) |
6831 | jmp = gjmp(0); |
6832 | gsym(pcl->jnext); |
6833 | try_call_scope_cleanup(o->cl.s); |
6834 | pcl->jnext = gjmp(0); |
6835 | if (!o->cl.n) |
6836 | goto remove_pending; |
6837 | g->c = o->cl.n; |
6838 | pg = &g->prev; |
6839 | } else { |
6840 | remove_pending: |
6841 | *pg = g->prev; |
6842 | sym_free(g); |
6843 | } |
6844 | } |
6845 | gsym(jmp); |
6846 | try_call_scope_cleanup(o->cl.s); |
6847 | } |
6848 | |
6849 | /* ------------------------------------------------------------------------- */ |
6850 | /* VLA */ |
6851 | |
6852 | static void vla_restore(int loc) |
6853 | { |
6854 | if (loc) |
6855 | gen_vla_sp_restore(loc); |
6856 | } |
6857 | |
6858 | static void vla_leave(struct scope *o) |
6859 | { |
6860 | if (o->vla.num < cur_scope->vla.num) |
6861 | vla_restore(o->vla.loc); |
6862 | } |
6863 | |
6864 | /* ------------------------------------------------------------------------- */ |
6865 | /* local scopes */ |
6866 | |
6867 | void new_scope(struct scope *o) |
6868 | { |
6869 | /* copy and link previous scope */ |
6870 | *o = *cur_scope; |
6871 | o->prev = cur_scope; |
6872 | cur_scope = o; |
6873 | |
6874 | /* record local declaration stack position */ |
6875 | o->lstk = local_stack; |
6876 | o->llstk = local_label_stack; |
6877 | |
6878 | ++local_scope; |
6879 | |
6880 | if (tcc_state->do_debug) |
6881 | tcc_debug_stabn(N_LBRAC, ind - func_ind); |
6882 | } |
6883 | |
6884 | void prev_scope(struct scope *o, int is_expr) |
6885 | { |
6886 | vla_leave(o->prev); |
6887 | |
6888 | if (o->cl.s != o->prev->cl.s) |
6889 | block_cleanup(o->prev); |
6890 | |
6891 | /* pop locally defined labels */ |
6892 | label_pop(&local_label_stack, o->llstk, is_expr); |
6893 | |
6894 | /* In the is_expr case (a statement expression is finished here), |
6895 | vtop might refer to symbols on the local_stack. Either via the |
6896 | type or via vtop->sym. We can't pop those nor any that in turn |
6897 | might be referred to. To make it easier we don't roll back |
6898 | any symbols in that case; some upper level call to block() will |
6899 | do that. We do have to remove such symbols from the lookup |
6900 | tables, though. sym_pop will do that. */ |
6901 | |
6902 | /* pop locally defined symbols */ |
6903 | pop_local_syms(&local_stack, o->lstk, is_expr, 0); |
6904 | cur_scope = o->prev; |
6905 | --local_scope; |
6906 | |
6907 | if (tcc_state->do_debug) |
6908 | tcc_debug_stabn(N_RBRAC, ind - func_ind); |
6909 | } |
6910 | |
6911 | /* leave a scope via break/continue(/goto) */ |
6912 | void leave_scope(struct scope *o) |
6913 | { |
6914 | if (!o) |
6915 | return; |
6916 | try_call_scope_cleanup(o->cl.s); |
6917 | vla_leave(o); |
6918 | } |
6919 | |
6920 | /* ------------------------------------------------------------------------- */ |
6921 | /* call block from 'for do while' loops */ |
6922 | |
6923 | static void lblock(int *bsym, int *csym) |
6924 | { |
6925 | struct scope *lo = loop_scope, *co = cur_scope; |
6926 | int *b = co->bsym, *c = co->csym; |
6927 | if (csym) { |
6928 | co->csym = csym; |
6929 | loop_scope = co; |
6930 | } |
6931 | co->bsym = bsym; |
6932 | block(0); |
6933 | co->bsym = b; |
6934 | if (csym) { |
6935 | co->csym = c; |
6936 | loop_scope = lo; |
6937 | } |
6938 | } |
6939 | |
6940 | static void block(int is_expr) |
6941 | { |
6942 | int a, b, c, d, e, t; |
6943 | struct scope o; |
6944 | Sym *s; |
6945 | |
6946 | if (is_expr) { |
6947 | /* default return value is (void) */ |
6948 | vpushi(0); |
6949 | vtop->type.t = VT_VOID; |
6950 | } |
6951 | |
6952 | again: |
6953 | t = tok, next(); |
6954 | |
6955 | if (t == TOK_IF) { |
6956 | skip('('); |
6957 | gexpr(); |
6958 | skip(')'); |
6959 | a = gvtst(1, 0); |
6960 | block(0); |
6961 | if (tok == TOK_ELSE) { |
6962 | d = gjmp(0); |
6963 | gsym(a); |
6964 | next(); |
6965 | block(0); |
6966 | gsym(d); /* patch else jmp */ |
6967 | } else { |
6968 | gsym(a); |
6969 | } |
6970 | |
6971 | } else if (t == TOK_WHILE) { |
6972 | d = gind(); |
6973 | skip('('); |
6974 | gexpr(); |
6975 | skip(')'); |
6976 | a = gvtst(1, 0); |
6977 | b = 0; |
6978 | lblock(&a, &b); |
6979 | gjmp_addr(d); |
6980 | gsym_addr(b, d); |
6981 | gsym(a); |
6982 | |
6983 | } else if (t == '{') { |
6984 | new_scope(&o); |
6985 | |
6986 | /* handle local labels declarations */ |
6987 | while (tok == TOK_LABEL) { |
6988 | do { |
6989 | next(); |
6990 | if (tok < TOK_UIDENT) |
6991 | expect("label identifier" ); |
6992 | label_push(&local_label_stack, tok, LABEL_DECLARED); |
6993 | next(); |
6994 | } while (tok == ','); |
6995 | skip(';'); |
6996 | } |
6997 | |
6998 | while (tok != '}') { |
6999 | decl(VT_LOCAL); |
7000 | if (tok != '}') { |
7001 | if (is_expr) |
7002 | vpop(); |
7003 | block(is_expr); |
7004 | } |
7005 | } |
7006 | |
7007 | prev_scope(&o, is_expr); |
7008 | if (local_scope) |
7009 | next(); |
7010 | else if (!nocode_wanted) |
7011 | check_func_return(); |
7012 | |
7013 | } else if (t == TOK_RETURN) { |
7014 | b = (func_vt.t & VT_BTYPE) != VT_VOID; |
7015 | if (tok != ';') { |
7016 | gexpr(); |
7017 | if (b) { |
7018 | gen_assign_cast(&func_vt); |
7019 | } else { |
7020 | if (vtop->type.t != VT_VOID) |
7021 | tcc_warning("void function returns a value" ); |
7022 | vtop--; |
7023 | } |
7024 | } else if (b) { |
7025 | tcc_warning("'return' with no value" ); |
7026 | b = 0; |
7027 | } |
7028 | leave_scope(root_scope); |
7029 | if (b) |
7030 | gfunc_return(&func_vt); |
7031 | skip(';'); |
7032 | /* jump unless last stmt in top-level block */ |
7033 | if (tok != '}' || local_scope != 1) |
7034 | rsym = gjmp(rsym); |
7035 | CODE_OFF(); |
7036 | |
7037 | } else if (t == TOK_BREAK) { |
7038 | /* compute jump */ |
7039 | if (!cur_scope->bsym) |
7040 | tcc_error("cannot break" ); |
7041 | if (cur_switch && cur_scope->bsym == cur_switch->bsym) |
7042 | leave_scope(cur_switch->scope); |
7043 | else |
7044 | leave_scope(loop_scope); |
7045 | *cur_scope->bsym = gjmp(*cur_scope->bsym); |
7046 | skip(';'); |
7047 | |
7048 | } else if (t == TOK_CONTINUE) { |
7049 | /* compute jump */ |
7050 | if (!cur_scope->csym) |
7051 | tcc_error("cannot continue" ); |
7052 | leave_scope(loop_scope); |
7053 | *cur_scope->csym = gjmp(*cur_scope->csym); |
7054 | skip(';'); |
7055 | |
7056 | } else if (t == TOK_FOR) { |
7057 | new_scope(&o); |
7058 | |
7059 | skip('('); |
7060 | if (tok != ';') { |
7061 | /* c99 for-loop init decl? */ |
7062 | if (!decl0(VT_LOCAL, 1, NULL)) { |
7063 | /* no, regular for-loop init expr */ |
7064 | gexpr(); |
7065 | vpop(); |
7066 | } |
7067 | } |
7068 | skip(';'); |
7069 | a = b = 0; |
7070 | c = d = gind(); |
7071 | if (tok != ';') { |
7072 | gexpr(); |
7073 | a = gvtst(1, 0); |
7074 | } |
7075 | skip(';'); |
7076 | if (tok != ')') { |
7077 | e = gjmp(0); |
7078 | d = gind(); |
7079 | gexpr(); |
7080 | vpop(); |
7081 | gjmp_addr(c); |
7082 | gsym(e); |
7083 | } |
7084 | skip(')'); |
7085 | lblock(&a, &b); |
7086 | gjmp_addr(d); |
7087 | gsym_addr(b, d); |
7088 | gsym(a); |
7089 | prev_scope(&o, 0); |
7090 | |
7091 | } else if (t == TOK_DO) { |
7092 | a = b = 0; |
7093 | d = gind(); |
7094 | lblock(&a, &b); |
7095 | gsym(b); |
7096 | skip(TOK_WHILE); |
7097 | skip('('); |
7098 | gexpr(); |
7099 | skip(')'); |
7100 | skip(';'); |
7101 | c = gvtst(0, 0); |
7102 | gsym_addr(c, d); |
7103 | gsym(a); |
7104 | |
7105 | } else if (t == TOK_SWITCH) { |
7106 | struct switch_t *sw; |
7107 | |
7108 | sw = tcc_mallocz(sizeof *sw); |
7109 | sw->bsym = &a; |
7110 | sw->scope = cur_scope; |
7111 | sw->prev = cur_switch; |
7112 | cur_switch = sw; |
7113 | |
7114 | skip('('); |
7115 | gexpr(); |
7116 | skip(')'); |
7117 | sw->sv = *vtop--; /* save switch value */ |
7118 | |
7119 | a = 0; |
7120 | b = gjmp(0); /* jump to first case */ |
7121 | lblock(&a, NULL); |
7122 | a = gjmp(a); /* add implicit break */ |
7123 | /* case lookup */ |
7124 | gsym(b); |
7125 | |
7126 | if (sw->sv.type.t & VT_UNSIGNED) |
7127 | qsort(sw->p, sw->n, sizeof(void*), case_cmpu); |
7128 | else |
7129 | qsort(sw->p, sw->n, sizeof(void*), case_cmpi); |
7130 | |
7131 | for (b = 1; b < sw->n; b++) |
7132 | if (sw->sv.type.t & VT_UNSIGNED |
7133 | ? (uint64_t)sw->p[b - 1]->v2 >= (uint64_t)sw->p[b]->v1 |
7134 | : sw->p[b - 1]->v2 >= sw->p[b]->v1) |
7135 | tcc_error("duplicate case value" ); |
7136 | |
7137 | vpushv(&sw->sv); |
7138 | gv(RC_INT); |
7139 | d = 0, gcase(sw->p, sw->n, &d); |
7140 | vpop(); |
7141 | if (sw->def_sym) |
7142 | gsym_addr(d, sw->def_sym); |
7143 | else |
7144 | gsym(d); |
7145 | /* break label */ |
7146 | gsym(a); |
7147 | |
7148 | dynarray_reset(&sw->p, &sw->n); |
7149 | cur_switch = sw->prev; |
7150 | tcc_free(sw); |
7151 | |
7152 | } else if (t == TOK_CASE) { |
7153 | struct case_t *cr = tcc_malloc(sizeof(struct case_t)); |
7154 | if (!cur_switch) |
7155 | expect("switch" ); |
7156 | cr->v1 = cr->v2 = expr_const64(); |
7157 | if (gnu_ext && tok == TOK_DOTS) { |
7158 | next(); |
7159 | cr->v2 = expr_const64(); |
7160 | if ((!(cur_switch->sv.type.t & VT_UNSIGNED) && cr->v2 < cr->v1) |
7161 | || (cur_switch->sv.type.t & VT_UNSIGNED && (uint64_t)cr->v2 < (uint64_t)cr->v1)) |
7162 | tcc_warning("empty case range" ); |
7163 | } |
7164 | cr->sym = gind(); |
7165 | dynarray_add(&cur_switch->p, &cur_switch->n, cr); |
7166 | skip(':'); |
7167 | is_expr = 0; |
7168 | goto block_after_label; |
7169 | |
7170 | } else if (t == TOK_DEFAULT) { |
7171 | if (!cur_switch) |
7172 | expect("switch" ); |
7173 | if (cur_switch->def_sym) |
7174 | tcc_error("too many 'default'" ); |
7175 | cur_switch->def_sym = gind(); |
7176 | skip(':'); |
7177 | is_expr = 0; |
7178 | goto block_after_label; |
7179 | |
7180 | } else if (t == TOK_GOTO) { |
7181 | vla_restore(root_scope->vla.loc); |
7182 | if (tok == '*' && gnu_ext) { |
7183 | /* computed goto */ |
7184 | next(); |
7185 | gexpr(); |
7186 | if ((vtop->type.t & VT_BTYPE) != VT_PTR) |
7187 | expect("pointer" ); |
7188 | ggoto(); |
7189 | |
7190 | } else if (tok >= TOK_UIDENT) { |
7191 | s = label_find(tok); |
7192 | /* put forward definition if needed */ |
7193 | if (!s) |
7194 | s = label_push(&global_label_stack, tok, LABEL_FORWARD); |
7195 | else if (s->r == LABEL_DECLARED) |
7196 | s->r = LABEL_FORWARD; |
7197 | |
7198 | if (s->r & LABEL_FORWARD) { |
7199 | /* start new goto chain for cleanups, linked via label->next */ |
7200 | if (cur_scope->cl.s && !nocode_wanted) { |
7201 | sym_push2(&pending_gotos, SYM_FIELD, 0, cur_scope->cl.n); |
7202 | pending_gotos->prev_tok = s; |
7203 | s = sym_push2(&s->next, SYM_FIELD, 0, 0); |
7204 | pending_gotos->next = s; |
7205 | } |
7206 | s->jnext = gjmp(s->jnext); |
7207 | } else { |
7208 | try_call_cleanup_goto(s->cleanupstate); |
7209 | gjmp_addr(s->jnext); |
7210 | } |
7211 | next(); |
7212 | |
7213 | } else { |
7214 | expect("label identifier" ); |
7215 | } |
7216 | skip(';'); |
7217 | |
7218 | } else if (t == TOK_ASM1 || t == TOK_ASM2 || t == TOK_ASM3) { |
7219 | asm_instr(); |
7220 | |
7221 | } else { |
7222 | if (tok == ':' && t >= TOK_UIDENT) { |
7223 | /* label case */ |
7224 | next(); |
7225 | s = label_find(t); |
7226 | if (s) { |
7227 | if (s->r == LABEL_DEFINED) |
7228 | tcc_error("duplicate label '%s'" , get_tok_str(s->v, NULL)); |
7229 | s->r = LABEL_DEFINED; |
7230 | if (s->next) { |
7231 | Sym *pcl; /* pending cleanup goto */ |
7232 | for (pcl = s->next; pcl; pcl = pcl->prev) |
7233 | gsym(pcl->jnext); |
7234 | sym_pop(&s->next, NULL, 0); |
7235 | } else |
7236 | gsym(s->jnext); |
7237 | } else { |
7238 | s = label_push(&global_label_stack, t, LABEL_DEFINED); |
7239 | } |
7240 | s->jnext = gind(); |
7241 | s->cleanupstate = cur_scope->cl.s; |
7242 | |
7243 | block_after_label: |
7244 | vla_restore(cur_scope->vla.loc); |
7245 | /* we accept this, but it is a mistake */ |
7246 | if (tok == '}') { |
7247 | tcc_warning("deprecated use of label at end of compound statement" ); |
7248 | } else { |
7249 | goto again; |
7250 | } |
7251 | |
7252 | } else { |
7253 | /* expression case */ |
7254 | if (t != ';') { |
7255 | unget_tok(t); |
7256 | if (is_expr) { |
7257 | vpop(); |
7258 | gexpr(); |
7259 | } else { |
7260 | gexpr(); |
7261 | vpop(); |
7262 | } |
7263 | skip(';'); |
7264 | } |
7265 | } |
7266 | } |
7267 | } |
7268 | |
7269 | /* This skips over a stream of tokens containing balanced {} and () |
7270 | pairs, stopping at outer ',' ';' and '}' (or matching '}' if we started |
7271 | with a '{'). If STR then allocates and stores the skipped tokens |
7272 | in *STR. This doesn't check if () and {} are nested correctly, |
7273 | i.e. "({)}" is accepted. */ |
7274 | static void skip_or_save_block(TokenString **str) |
7275 | { |
7276 | int braces = tok == '{'; |
7277 | int level = 0; |
7278 | if (str) |
7279 | *str = tok_str_alloc(); |
7280 | |
7281 | while ((level > 0 || (tok != '}' && tok != ',' && tok != ';' && tok != ')'))) { |
7282 | int t; |
7283 | if (tok == TOK_EOF) { |
7284 | if (str || level > 0) |
7285 | tcc_error("unexpected end of file" ); |
7286 | else |
7287 | break; |
7288 | } |
7289 | if (str) |
7290 | tok_str_add_tok(*str); |
7291 | t = tok; |
7292 | next(); |
7293 | if (t == '{' || t == '(') { |
7294 | level++; |
7295 | } else if (t == '}' || t == ')') { |
7296 | level--; |
7297 | if (level == 0 && braces && t == '}') |
7298 | break; |
7299 | } |
7300 | } |
7301 | if (str) { |
7302 | tok_str_add(*str, -1); |
7303 | tok_str_add(*str, 0); |
7304 | } |
7305 | } |
7306 | |
7307 | #define EXPR_CONST 1 |
7308 | #define EXPR_ANY 2 |
7309 | |
7310 | static void parse_init_elem(int expr_type) |
7311 | { |
7312 | int saved_global_expr; |
7313 | switch(expr_type) { |
7314 | case EXPR_CONST: |
7315 | /* compound literals must be allocated globally in this case */ |
7316 | saved_global_expr = global_expr; |
7317 | global_expr = 1; |
7318 | expr_const1(); |
7319 | global_expr = saved_global_expr; |
7320 | /* NOTE: symbols are accepted, as well as lvalue for anon symbols |
7321 | (compound literals). */ |
7322 | if (((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST |
7323 | && ((vtop->r & (VT_SYM|VT_LVAL)) != (VT_SYM|VT_LVAL) |
7324 | || vtop->sym->v < SYM_FIRST_ANOM)) |
7325 | #ifdef TCC_TARGET_PE |
7326 | || ((vtop->r & VT_SYM) && vtop->sym->a.dllimport) |
7327 | #endif |
7328 | ) |
7329 | tcc_error("initializer element is not constant" ); |
7330 | break; |
7331 | case EXPR_ANY: |
7332 | expr_eq(); |
7333 | break; |
7334 | } |
7335 | } |
7336 | |
7337 | #if 1 |
7338 | static void init_assert(init_params *p, int offset) |
7339 | { |
7340 | if (p->sec ? !NODATA_WANTED && offset > p->sec->data_offset |
7341 | : !nocode_wanted && offset > p->local_offset) |
7342 | tcc_internal_error("initializer overflow" ); |
7343 | } |
7344 | #else |
7345 | #define init_assert(sec, offset) |
7346 | #endif |
7347 | |
7348 | /* put zeros for variable based init */ |
7349 | static void init_putz(init_params *p, unsigned long c, int size) |
7350 | { |
7351 | init_assert(p, c + size); |
7352 | if (p->sec) { |
7353 | /* nothing to do because globals are already set to zero */ |
7354 | } else { |
7355 | vpush_global_sym(&func_old_type, TOK_memset); |
7356 | vseti(VT_LOCAL, c); |
7357 | #ifdef TCC_TARGET_ARM |
7358 | vpushs(size); |
7359 | vpushi(0); |
7360 | #else |
7361 | vpushi(0); |
7362 | vpushs(size); |
7363 | #endif |
7364 | gfunc_call(3); |
7365 | } |
7366 | } |
7367 | |
7368 | #define DIF_FIRST 1 |
7369 | #define DIF_SIZE_ONLY 2 |
7370 | #define DIF_HAVE_ELEM 4 |
7371 | #define DIF_CLEAR 8 |
7372 | |
7373 | /* delete relocations for specified range c ... c + size. Unfortunatly |
7374 | in very special cases, relocations may occur unordered */ |
7375 | static void decl_design_delrels(Section *sec, int c, int size) |
7376 | { |
7377 | ElfW_Rel *rel, *rel2, *rel_end; |
7378 | if (!sec || !sec->reloc) |
7379 | return; |
7380 | rel = rel2 = (ElfW_Rel*)sec->reloc->data; |
7381 | rel_end = (ElfW_Rel*)(sec->reloc->data + sec->reloc->data_offset); |
7382 | while (rel < rel_end) { |
7383 | if (rel->r_offset >= c && rel->r_offset < c + size) { |
7384 | sec->reloc->data_offset -= sizeof *rel; |
7385 | } else { |
7386 | if (rel2 != rel) |
7387 | memcpy(rel2, rel, sizeof *rel); |
7388 | ++rel2; |
7389 | } |
7390 | ++rel; |
7391 | } |
7392 | } |
7393 | |
7394 | static void decl_design_flex(init_params *p, Sym *ref, int index) |
7395 | { |
7396 | if (ref == p->flex_array_ref) { |
7397 | if (index >= ref->c) |
7398 | ref->c = index + 1; |
7399 | } else if (ref->c < 0) |
7400 | tcc_error("flexible array has zero size in this context" ); |
7401 | } |
7402 | |
7403 | /* t is the array or struct type. c is the array or struct |
7404 | address. cur_field is the pointer to the current |
7405 | field, for arrays the 'c' member contains the current start |
7406 | index. 'flags' is as in decl_initializer. |
7407 | 'al' contains the already initialized length of the |
7408 | current container (starting at c). This returns the new length of that. */ |
7409 | static int decl_designator(init_params *p, CType *type, unsigned long c, |
7410 | Sym **cur_field, int flags, int al) |
7411 | { |
7412 | Sym *s, *f; |
7413 | int index, index_last, align, l, nb_elems, elem_size; |
7414 | unsigned long corig = c; |
7415 | |
7416 | elem_size = 0; |
7417 | nb_elems = 1; |
7418 | |
7419 | if (flags & DIF_HAVE_ELEM) |
7420 | goto no_designator; |
7421 | |
7422 | if (gnu_ext && tok >= TOK_UIDENT) { |
7423 | l = tok, next(); |
7424 | if (tok == ':') |
7425 | goto struct_field; |
7426 | unget_tok(l); |
7427 | } |
7428 | |
7429 | /* NOTE: we only support ranges for last designator */ |
7430 | while (nb_elems == 1 && (tok == '[' || tok == '.')) { |
7431 | if (tok == '[') { |
7432 | if (!(type->t & VT_ARRAY)) |
7433 | expect("array type" ); |
7434 | next(); |
7435 | index = index_last = expr_const(); |
7436 | if (tok == TOK_DOTS && gnu_ext) { |
7437 | next(); |
7438 | index_last = expr_const(); |
7439 | } |
7440 | skip(']'); |
7441 | s = type->ref; |
7442 | decl_design_flex(p, s, index_last); |
7443 | if (index < 0 || index_last >= s->c || index_last < index) |
7444 | tcc_error("index exceeds array bounds or range is empty" ); |
7445 | if (cur_field) |
7446 | (*cur_field)->c = index_last; |
7447 | type = pointed_type(type); |
7448 | elem_size = type_size(type, &align); |
7449 | c += index * elem_size; |
7450 | nb_elems = index_last - index + 1; |
7451 | } else { |
7452 | int cumofs; |
7453 | next(); |
7454 | l = tok; |
7455 | struct_field: |
7456 | next(); |
7457 | if ((type->t & VT_BTYPE) != VT_STRUCT) |
7458 | expect("struct/union type" ); |
7459 | cumofs = 0; |
7460 | f = find_field(type, l, &cumofs); |
7461 | if (!f) |
7462 | expect("field" ); |
7463 | if (cur_field) |
7464 | *cur_field = f; |
7465 | type = &f->type; |
7466 | c += cumofs + f->c; |
7467 | } |
7468 | cur_field = NULL; |
7469 | } |
7470 | if (!cur_field) { |
7471 | if (tok == '=') { |
7472 | next(); |
7473 | } else if (!gnu_ext) { |
7474 | expect("=" ); |
7475 | } |
7476 | } else { |
7477 | no_designator: |
7478 | if (type->t & VT_ARRAY) { |
7479 | index = (*cur_field)->c; |
7480 | s = type->ref; |
7481 | decl_design_flex(p, s, index); |
7482 | if (index >= s->c) |
7483 | tcc_error("too many initializers" ); |
7484 | type = pointed_type(type); |
7485 | elem_size = type_size(type, &align); |
7486 | c += index * elem_size; |
7487 | } else { |
7488 | f = *cur_field; |
7489 | while (f && (f->v & SYM_FIRST_ANOM) && (f->type.t & VT_BITFIELD)) |
7490 | *cur_field = f = f->next; |
7491 | if (!f) |
7492 | tcc_error("too many initializers" ); |
7493 | type = &f->type; |
7494 | c += f->c; |
7495 | } |
7496 | } |
7497 | |
7498 | if (!elem_size) /* for structs */ |
7499 | elem_size = type_size(type, &align); |
7500 | |
7501 | /* Using designators the same element can be initialized more |
7502 | than once. In that case we need to delete possibly already |
7503 | existing relocations. */ |
7504 | if (!(flags & DIF_SIZE_ONLY) && c - corig < al) { |
7505 | decl_design_delrels(p->sec, c, elem_size * nb_elems); |
7506 | flags &= ~DIF_CLEAR; /* mark stack dirty too */ |
7507 | } |
7508 | |
7509 | decl_initializer(p, type, c, flags & ~DIF_FIRST); |
7510 | |
7511 | if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) { |
7512 | Sym aref = {0}; |
7513 | CType t1; |
7514 | int i; |
7515 | if (p->sec || (type->t & VT_ARRAY)) { |
7516 | /* make init_putv/vstore believe it were a struct */ |
7517 | aref.c = elem_size; |
7518 | t1.t = VT_STRUCT, t1.ref = &aref; |
7519 | type = &t1; |
7520 | } |
7521 | if (p->sec) |
7522 | vpush_ref(type, p->sec, c, elem_size); |
7523 | else |
7524 | vset(type, VT_LOCAL|VT_LVAL, c); |
7525 | for (i = 1; i < nb_elems; i++) { |
7526 | vdup(); |
7527 | init_putv(p, type, c + elem_size * i); |
7528 | } |
7529 | vpop(); |
7530 | } |
7531 | |
7532 | c += nb_elems * elem_size; |
7533 | if (c - corig > al) |
7534 | al = c - corig; |
7535 | return al; |
7536 | } |
7537 | |
7538 | /* store a value or an expression directly in global data or in local array */ |
7539 | static void init_putv(init_params *p, CType *type, unsigned long c) |
7540 | { |
7541 | int bt; |
7542 | void *ptr; |
7543 | CType dtype; |
7544 | int size, align; |
7545 | Section *sec = p->sec; |
7546 | |
7547 | dtype = *type; |
7548 | dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */ |
7549 | |
7550 | size = type_size(type, &align); |
7551 | if (type->t & VT_BITFIELD) |
7552 | size = (BIT_POS(type->t) + BIT_SIZE(type->t) + 7) / 8; |
7553 | init_assert(p, c + size); |
7554 | |
7555 | if (sec) { |
7556 | /* XXX: not portable */ |
7557 | /* XXX: generate error if incorrect relocation */ |
7558 | gen_assign_cast(&dtype); |
7559 | bt = type->t & VT_BTYPE; |
7560 | |
7561 | if ((vtop->r & VT_SYM) |
7562 | && bt != VT_PTR |
7563 | && bt != VT_FUNC |
7564 | && (bt != (PTR_SIZE == 8 ? VT_LLONG : VT_INT) |
7565 | || (type->t & VT_BITFIELD)) |
7566 | && !((vtop->r & VT_CONST) && vtop->sym->v >= SYM_FIRST_ANOM) |
7567 | ) |
7568 | tcc_error("initializer element is not computable at load time" ); |
7569 | |
7570 | if (NODATA_WANTED) { |
7571 | vtop--; |
7572 | return; |
7573 | } |
7574 | |
7575 | ptr = sec->data + c; |
7576 | |
7577 | /* XXX: make code faster ? */ |
7578 | if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) && |
7579 | vtop->sym->v >= SYM_FIRST_ANOM && |
7580 | /* XXX This rejects compound literals like |
7581 | '(void *){ptr}'. The problem is that '&sym' is |
7582 | represented the same way, which would be ruled out |
7583 | by the SYM_FIRST_ANOM check above, but also '"string"' |
7584 | in 'char *p = "string"' is represented the same |
7585 | with the type being VT_PTR and the symbol being an |
7586 | anonymous one. That is, there's no difference in vtop |
7587 | between '(void *){x}' and '&(void *){x}'. Ignore |
7588 | pointer typed entities here. Hopefully no real code |
7589 | will ever use compound literals with scalar type. */ |
7590 | (vtop->type.t & VT_BTYPE) != VT_PTR) { |
7591 | /* These come from compound literals, memcpy stuff over. */ |
7592 | Section *ssec; |
7593 | ElfSym *esym; |
7594 | ElfW_Rel *rel; |
7595 | esym = elfsym(vtop->sym); |
7596 | ssec = tcc_state->sections[esym->st_shndx]; |
7597 | memmove (ptr, ssec->data + esym->st_value + (int)vtop->c.i, size); |
7598 | if (ssec->reloc) { |
7599 | /* We need to copy over all memory contents, and that |
7600 | includes relocations. Use the fact that relocs are |
7601 | created it order, so look from the end of relocs |
7602 | until we hit one before the copied region. */ |
7603 | int num_relocs = ssec->reloc->data_offset / sizeof(*rel); |
7604 | rel = (ElfW_Rel*)(ssec->reloc->data + ssec->reloc->data_offset); |
7605 | while (num_relocs--) { |
7606 | rel--; |
7607 | if (rel->r_offset >= esym->st_value + size) |
7608 | continue; |
7609 | if (rel->r_offset < esym->st_value) |
7610 | break; |
7611 | put_elf_reloca(symtab_section, sec, |
7612 | c + rel->r_offset - esym->st_value, |
7613 | ELFW(R_TYPE)(rel->r_info), |
7614 | ELFW(R_SYM)(rel->r_info), |
7615 | #if PTR_SIZE == 8 |
7616 | rel->r_addend |
7617 | #else |
7618 | 0 |
7619 | #endif |
7620 | ); |
7621 | } |
7622 | } |
7623 | } else { |
7624 | if (type->t & VT_BITFIELD) { |
7625 | int bit_pos, bit_size, bits, n; |
7626 | unsigned char *p, v, m; |
7627 | bit_pos = BIT_POS(vtop->type.t); |
7628 | bit_size = BIT_SIZE(vtop->type.t); |
7629 | p = (unsigned char*)ptr + (bit_pos >> 3); |
7630 | bit_pos &= 7, bits = 0; |
7631 | while (bit_size) { |
7632 | n = 8 - bit_pos; |
7633 | if (n > bit_size) |
7634 | n = bit_size; |
7635 | v = vtop->c.i >> bits << bit_pos; |
7636 | m = ((1 << n) - 1) << bit_pos; |
7637 | *p = (*p & ~m) | (v & m); |
7638 | bits += n, bit_size -= n, bit_pos = 0, ++p; |
7639 | } |
7640 | } else |
7641 | switch(bt) { |
7642 | /* XXX: when cross-compiling we assume that each type has the |
7643 | same representation on host and target, which is likely to |
7644 | be wrong in the case of long double */ |
7645 | case VT_BOOL: |
7646 | vtop->c.i = vtop->c.i != 0; |
7647 | case VT_BYTE: |
7648 | *(char *)ptr = vtop->c.i; |
7649 | break; |
7650 | case VT_SHORT: |
7651 | *(short *)ptr = vtop->c.i; |
7652 | break; |
7653 | case VT_FLOAT: |
7654 | *(float*)ptr = vtop->c.f; |
7655 | break; |
7656 | case VT_DOUBLE: |
7657 | *(double *)ptr = vtop->c.d; |
7658 | break; |
7659 | case VT_LDOUBLE: |
7660 | #if defined TCC_IS_NATIVE_387 |
7661 | if (sizeof (long double) >= 10) /* zero pad ten-byte LD */ |
7662 | memcpy(ptr, &vtop->c.ld, 10); |
7663 | #ifdef __TINYC__ |
7664 | else if (sizeof (long double) == sizeof (double)) |
7665 | __asm__("fldl %1\nfstpt %0\n" : "=m" (*ptr) : "m" (vtop->c.ld)); |
7666 | #endif |
7667 | else if (vtop->c.ld == 0.0) |
7668 | ; |
7669 | else |
7670 | #endif |
7671 | if (sizeof(long double) == LDOUBLE_SIZE) |
7672 | *(long double*)ptr = vtop->c.ld; |
7673 | else if (sizeof(double) == LDOUBLE_SIZE) |
7674 | *(double *)ptr = (double)vtop->c.ld; |
7675 | else |
7676 | tcc_error("can't cross compile long double constants" ); |
7677 | break; |
7678 | #if PTR_SIZE != 8 |
7679 | case VT_LLONG: |
7680 | *(long long *)ptr = vtop->c.i; |
7681 | break; |
7682 | #else |
7683 | case VT_LLONG: |
7684 | #endif |
7685 | case VT_PTR: |
7686 | { |
7687 | addr_t val = vtop->c.i; |
7688 | #if PTR_SIZE == 8 |
7689 | if (vtop->r & VT_SYM) |
7690 | greloca(sec, vtop->sym, c, R_DATA_PTR, val); |
7691 | else |
7692 | *(addr_t *)ptr = val; |
7693 | #else |
7694 | if (vtop->r & VT_SYM) |
7695 | greloc(sec, vtop->sym, c, R_DATA_PTR); |
7696 | *(addr_t *)ptr = val; |
7697 | #endif |
7698 | break; |
7699 | } |
7700 | default: |
7701 | { |
7702 | int val = vtop->c.i; |
7703 | #if PTR_SIZE == 8 |
7704 | if (vtop->r & VT_SYM) |
7705 | greloca(sec, vtop->sym, c, R_DATA_PTR, val); |
7706 | else |
7707 | *(int *)ptr = val; |
7708 | #else |
7709 | if (vtop->r & VT_SYM) |
7710 | greloc(sec, vtop->sym, c, R_DATA_PTR); |
7711 | *(int *)ptr = val; |
7712 | #endif |
7713 | break; |
7714 | } |
7715 | } |
7716 | } |
7717 | vtop--; |
7718 | } else { |
7719 | vset(&dtype, VT_LOCAL|VT_LVAL, c); |
7720 | vswap(); |
7721 | vstore(); |
7722 | vpop(); |
7723 | } |
7724 | } |
7725 | |
7726 | /* 't' contains the type and storage info. 'c' is the offset of the |
7727 | object in section 'sec'. If 'sec' is NULL, it means stack based |
7728 | allocation. 'flags & DIF_FIRST' is true if array '{' must be read (multi |
7729 | dimension implicit array init handling). 'flags & DIF_SIZE_ONLY' is true if |
7730 | size only evaluation is wanted (only for arrays). */ |
7731 | static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags) |
7732 | { |
7733 | int len, n, no_oblock, i; |
7734 | int size1, align1; |
7735 | Sym *s, *f; |
7736 | Sym indexsym; |
7737 | CType *t1; |
7738 | |
7739 | /* generate line number info */ |
7740 | if (!p->sec && tcc_state->do_debug) |
7741 | tcc_debug_line(tcc_state); |
7742 | |
7743 | if (!(flags & DIF_HAVE_ELEM) && tok != '{' && |
7744 | /* In case of strings we have special handling for arrays, so |
7745 | don't consume them as initializer value (which would commit them |
7746 | to some anonymous symbol). */ |
7747 | tok != TOK_LSTR && tok != TOK_STR && |
7748 | !(flags & DIF_SIZE_ONLY)) { |
7749 | parse_init_elem(!p->sec ? EXPR_ANY : EXPR_CONST); |
7750 | flags |= DIF_HAVE_ELEM; |
7751 | } |
7752 | |
7753 | if ((flags & DIF_HAVE_ELEM) && |
7754 | !(type->t & VT_ARRAY) && |
7755 | /* Use i_c_parameter_t, to strip toplevel qualifiers. |
7756 | The source type might have VT_CONSTANT set, which is |
7757 | of course assignable to non-const elements. */ |
7758 | is_compatible_unqualified_types(type, &vtop->type)) { |
7759 | goto init_putv; |
7760 | |
7761 | } else if (type->t & VT_ARRAY) { |
7762 | no_oblock = 1; |
7763 | if (((flags & DIF_FIRST) && tok != TOK_LSTR && tok != TOK_STR) || |
7764 | tok == '{') { |
7765 | skip('{'); |
7766 | no_oblock = 0; |
7767 | } |
7768 | |
7769 | s = type->ref; |
7770 | n = s->c; |
7771 | t1 = pointed_type(type); |
7772 | size1 = type_size(t1, &align1); |
7773 | |
7774 | /* only parse strings here if correct type (otherwise: handle |
7775 | them as ((w)char *) expressions */ |
7776 | if ((tok == TOK_LSTR && |
7777 | #ifdef TCC_TARGET_PE |
7778 | (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED) |
7779 | #else |
7780 | (t1->t & VT_BTYPE) == VT_INT |
7781 | #endif |
7782 | ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) { |
7783 | len = 0; |
7784 | cstr_reset(&initstr); |
7785 | if (size1 != (tok == TOK_STR ? 1 : sizeof(nwchar_t))) |
7786 | tcc_error("unhandled string literal merging" ); |
7787 | while (tok == TOK_STR || tok == TOK_LSTR) { |
7788 | if (initstr.size) |
7789 | initstr.size -= size1; |
7790 | if (tok == TOK_STR) |
7791 | len += tokc.str.size; |
7792 | else |
7793 | len += tokc.str.size / sizeof(nwchar_t); |
7794 | len--; |
7795 | cstr_cat(&initstr, tokc.str.data, tokc.str.size); |
7796 | next(); |
7797 | } |
7798 | if (tok != ')' && tok != '}' && tok != ',' && tok != ';' |
7799 | && tok != TOK_EOF) { |
7800 | /* Not a lone literal but part of a bigger expression. */ |
7801 | unget_tok(size1 == 1 ? TOK_STR : TOK_LSTR); |
7802 | tokc.str.size = initstr.size; |
7803 | tokc.str.data = initstr.data; |
7804 | goto do_init_array; |
7805 | } |
7806 | |
7807 | if (!(flags & DIF_SIZE_ONLY)) { |
7808 | int nb = n; |
7809 | if (len < nb) |
7810 | nb = len; |
7811 | if (len > nb) |
7812 | tcc_warning("initializer-string for array is too long" ); |
7813 | /* in order to go faster for common case (char |
7814 | string in global variable, we handle it |
7815 | specifically */ |
7816 | if (p->sec && size1 == 1) { |
7817 | init_assert(p, c + nb); |
7818 | if (!NODATA_WANTED) |
7819 | memcpy(p->sec->data + c, initstr.data, nb); |
7820 | } else { |
7821 | for(i=0;i<n;i++) { |
7822 | if (i >= nb) { |
7823 | /* only add trailing zero if enough storage (no |
7824 | warning in this case since it is standard) */ |
7825 | if (flags & DIF_CLEAR) |
7826 | break; |
7827 | if (n - i >= 4) { |
7828 | init_putz(p, c + i * size1, (n - i) * size1); |
7829 | break; |
7830 | } |
7831 | ch = 0; |
7832 | } else if (size1 == 1) |
7833 | ch = ((unsigned char *)initstr.data)[i]; |
7834 | else |
7835 | ch = ((nwchar_t *)initstr.data)[i]; |
7836 | vpushi(ch); |
7837 | init_putv(p, t1, c + i * size1); |
7838 | } |
7839 | } |
7840 | } else { |
7841 | decl_design_flex(p, s, len); |
7842 | } |
7843 | } else { |
7844 | |
7845 | do_init_array: |
7846 | indexsym.c = 0; |
7847 | f = &indexsym; |
7848 | |
7849 | do_init_list: |
7850 | /* zero memory once in advance */ |
7851 | if (!(flags & (DIF_CLEAR | DIF_SIZE_ONLY))) { |
7852 | init_putz(p, c, n*size1); |
7853 | flags |= DIF_CLEAR; |
7854 | } |
7855 | |
7856 | len = 0; |
7857 | while (tok != '}' || (flags & DIF_HAVE_ELEM)) { |
7858 | len = decl_designator(p, type, c, &f, flags, len); |
7859 | flags &= ~DIF_HAVE_ELEM; |
7860 | if (type->t & VT_ARRAY) { |
7861 | ++indexsym.c; |
7862 | /* special test for multi dimensional arrays (may not |
7863 | be strictly correct if designators are used at the |
7864 | same time) */ |
7865 | if (no_oblock && len >= n*size1) |
7866 | break; |
7867 | } else { |
7868 | if (s->type.t == VT_UNION) |
7869 | f = NULL; |
7870 | else |
7871 | f = f->next; |
7872 | if (no_oblock && f == NULL) |
7873 | break; |
7874 | } |
7875 | |
7876 | if (tok == '}') |
7877 | break; |
7878 | skip(','); |
7879 | } |
7880 | } |
7881 | if (!no_oblock) |
7882 | skip('}'); |
7883 | } else if ((type->t & VT_BTYPE) == VT_STRUCT) { |
7884 | no_oblock = 1; |
7885 | if ((flags & DIF_FIRST) || tok == '{') { |
7886 | skip('{'); |
7887 | no_oblock = 0; |
7888 | } |
7889 | s = type->ref; |
7890 | f = s->next; |
7891 | n = s->c; |
7892 | size1 = 1; |
7893 | goto do_init_list; |
7894 | } else if (tok == '{') { |
7895 | if (flags & DIF_HAVE_ELEM) |
7896 | skip(';'); |
7897 | next(); |
7898 | decl_initializer(p, type, c, flags & ~DIF_HAVE_ELEM); |
7899 | skip('}'); |
7900 | } else if ((flags & DIF_SIZE_ONLY)) { |
7901 | /* If we supported only ISO C we wouldn't have to accept calling |
7902 | this on anything than an array if DIF_SIZE_ONLY (and even then |
7903 | only on the outermost level, so no recursion would be needed), |
7904 | because initializing a flex array member isn't supported. |
7905 | But GNU C supports it, so we need to recurse even into |
7906 | subfields of structs and arrays when DIF_SIZE_ONLY is set. */ |
7907 | /* just skip expression */ |
7908 | skip_or_save_block(NULL); |
7909 | } else { |
7910 | if (!(flags & DIF_HAVE_ELEM)) { |
7911 | /* This should happen only when we haven't parsed |
7912 | the init element above for fear of committing a |
7913 | string constant to memory too early. */ |
7914 | if (tok != TOK_STR && tok != TOK_LSTR) |
7915 | expect("string constant" ); |
7916 | parse_init_elem(!p->sec ? EXPR_ANY : EXPR_CONST); |
7917 | } |
7918 | init_putv: |
7919 | if (!p->sec && (flags & DIF_CLEAR) /* container was already zero'd */ |
7920 | && (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST |
7921 | && vtop->c.i == 0 |
7922 | && btype_size(type->t & VT_BTYPE) /* not for fp constants */ |
7923 | ) |
7924 | vpop(); |
7925 | else |
7926 | init_putv(p, type, c); |
7927 | } |
7928 | } |
7929 | |
7930 | /* parse an initializer for type 't' if 'has_init' is non zero, and |
7931 | allocate space in local or global data space ('r' is either |
7932 | VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated |
7933 | variable 'v' of scope 'scope' is declared before initializers |
7934 | are parsed. If 'v' is zero, then a reference to the new object |
7935 | is put in the value stack. If 'has_init' is 2, a special parsing |
7936 | is done to handle string constants. */ |
7937 | static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, |
7938 | int has_init, int v, int scope) |
7939 | { |
7940 | int size, align, addr; |
7941 | TokenString *init_str = NULL; |
7942 | |
7943 | Section *sec; |
7944 | Sym *flexible_array; |
7945 | Sym *sym = NULL; |
7946 | int saved_nocode_wanted = nocode_wanted; |
7947 | #ifdef CONFIG_TCC_BCHECK |
7948 | int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED; |
7949 | #endif |
7950 | init_params p = {0}; |
7951 | |
7952 | /* Always allocate static or global variables */ |
7953 | if (v && (r & VT_VALMASK) == VT_CONST) |
7954 | nocode_wanted |= 0x80000000; |
7955 | |
7956 | flexible_array = NULL; |
7957 | size = type_size(type, &align); |
7958 | |
7959 | /* exactly one flexible array may be initialized, either the |
7960 | toplevel array or the last member of the toplevel struct */ |
7961 | |
7962 | if (size < 0) { |
7963 | /* If the base type itself was an array type of unspecified size |
7964 | (like in 'typedef int arr[]; arr x = {1};') then we will |
7965 | overwrite the unknown size by the real one for this decl. |
7966 | We need to unshare the ref symbol holding that size. */ |
7967 | type->ref = sym_push(SYM_FIELD, &type->ref->type, 0, type->ref->c); |
7968 | p.flex_array_ref = type->ref; |
7969 | |
7970 | } else if (has_init && (type->t & VT_BTYPE) == VT_STRUCT) { |
7971 | Sym *field = type->ref->next; |
7972 | if (field) { |
7973 | while (field->next) |
7974 | field = field->next; |
7975 | if (field->type.t & VT_ARRAY && field->type.ref->c < 0) { |
7976 | flexible_array = field; |
7977 | p.flex_array_ref = field->type.ref; |
7978 | size = -1; |
7979 | } |
7980 | } |
7981 | } |
7982 | |
7983 | if (size < 0) { |
7984 | /* If unknown size, do a dry-run 1st pass */ |
7985 | if (!has_init) |
7986 | tcc_error("unknown type size" ); |
7987 | if (has_init == 2) { |
7988 | /* only get strings */ |
7989 | init_str = tok_str_alloc(); |
7990 | while (tok == TOK_STR || tok == TOK_LSTR) { |
7991 | tok_str_add_tok(init_str); |
7992 | next(); |
7993 | } |
7994 | tok_str_add(init_str, -1); |
7995 | tok_str_add(init_str, 0); |
7996 | } else |
7997 | skip_or_save_block(&init_str); |
7998 | unget_tok(0); |
7999 | |
8000 | /* compute size */ |
8001 | begin_macro(init_str, 1); |
8002 | next(); |
8003 | decl_initializer(&p, type, 0, DIF_FIRST | DIF_SIZE_ONLY); |
8004 | /* prepare second initializer parsing */ |
8005 | macro_ptr = init_str->str; |
8006 | next(); |
8007 | |
8008 | /* if still unknown size, error */ |
8009 | size = type_size(type, &align); |
8010 | if (size < 0) |
8011 | tcc_error("unknown type size" ); |
8012 | |
8013 | /* If there's a flex member and it was used in the initializer |
8014 | adjust size. */ |
8015 | if (flexible_array && flexible_array->type.ref->c > 0) |
8016 | size += flexible_array->type.ref->c |
8017 | * pointed_size(&flexible_array->type); |
8018 | } |
8019 | |
8020 | /* take into account specified alignment if bigger */ |
8021 | if (ad->a.aligned) { |
8022 | int speca = 1 << (ad->a.aligned - 1); |
8023 | if (speca > align) |
8024 | align = speca; |
8025 | } else if (ad->a.packed) { |
8026 | align = 1; |
8027 | } |
8028 | |
8029 | if (!v && NODATA_WANTED) |
8030 | size = 0, align = 1; |
8031 | |
8032 | if ((r & VT_VALMASK) == VT_LOCAL) { |
8033 | sec = NULL; |
8034 | #ifdef CONFIG_TCC_BCHECK |
8035 | if (bcheck && v) { |
8036 | /* add padding between stack variables for bound checking */ |
8037 | loc--; |
8038 | } |
8039 | #endif |
8040 | loc = (loc - size) & -align; |
8041 | addr = loc; |
8042 | p.local_offset = addr + size; |
8043 | #ifdef CONFIG_TCC_BCHECK |
8044 | if (bcheck && v) { |
8045 | /* add padding between stack variables for bound checking */ |
8046 | loc--; |
8047 | } |
8048 | #endif |
8049 | if (v) { |
8050 | /* local variable */ |
8051 | #ifdef CONFIG_TCC_ASM |
8052 | if (ad->asm_label) { |
8053 | int reg = asm_parse_regvar(ad->asm_label); |
8054 | if (reg >= 0) |
8055 | r = (r & ~VT_VALMASK) | reg; |
8056 | } |
8057 | #endif |
8058 | sym = sym_push(v, type, r, addr); |
8059 | if (ad->cleanup_func) { |
8060 | Sym *cls = sym_push2(&all_cleanups, |
8061 | SYM_FIELD | ++cur_scope->cl.n, 0, 0); |
8062 | cls->prev_tok = sym; |
8063 | cls->next = ad->cleanup_func; |
8064 | cls->ncl = cur_scope->cl.s; |
8065 | cur_scope->cl.s = cls; |
8066 | } |
8067 | |
8068 | sym->a = ad->a; |
8069 | } else { |
8070 | /* push local reference */ |
8071 | vset(type, r, addr); |
8072 | } |
8073 | } else { |
8074 | if (v && scope == VT_CONST) { |
8075 | /* see if the symbol was already defined */ |
8076 | sym = sym_find(v); |
8077 | if (sym) { |
8078 | patch_storage(sym, ad, type); |
8079 | /* we accept several definitions of the same global variable. */ |
8080 | if (!has_init && sym->c && elfsym(sym)->st_shndx != SHN_UNDEF) |
8081 | goto no_alloc; |
8082 | } |
8083 | } |
8084 | |
8085 | /* allocate symbol in corresponding section */ |
8086 | sec = ad->section; |
8087 | if (!sec) { |
8088 | if (has_init) |
8089 | sec = data_section; |
8090 | else if (tcc_state->nocommon) |
8091 | sec = bss_section; |
8092 | } |
8093 | |
8094 | if (sec) { |
8095 | addr = section_add(sec, size, align); |
8096 | #ifdef CONFIG_TCC_BCHECK |
8097 | /* add padding if bound check */ |
8098 | if (bcheck) |
8099 | section_add(sec, 1, 1); |
8100 | #endif |
8101 | } else { |
8102 | addr = align; /* SHN_COMMON is special, symbol value is align */ |
8103 | sec = common_section; |
8104 | } |
8105 | |
8106 | if (v) { |
8107 | if (!sym) { |
8108 | sym = sym_push(v, type, r | VT_SYM, 0); |
8109 | patch_storage(sym, ad, NULL); |
8110 | } |
8111 | /* update symbol definition */ |
8112 | put_extern_sym(sym, sec, addr, size); |
8113 | } else { |
8114 | /* push global reference */ |
8115 | vpush_ref(type, sec, addr, size); |
8116 | sym = vtop->sym; |
8117 | vtop->r |= r; |
8118 | } |
8119 | |
8120 | #ifdef CONFIG_TCC_BCHECK |
8121 | /* handles bounds now because the symbol must be defined |
8122 | before for the relocation */ |
8123 | if (bcheck) { |
8124 | addr_t *bounds_ptr; |
8125 | |
8126 | greloca(bounds_section, sym, bounds_section->data_offset, R_DATA_PTR, 0); |
8127 | /* then add global bound info */ |
8128 | bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(addr_t)); |
8129 | bounds_ptr[0] = 0; /* relocated */ |
8130 | bounds_ptr[1] = size; |
8131 | } |
8132 | #endif |
8133 | } |
8134 | |
8135 | if (type->t & VT_VLA) { |
8136 | int a; |
8137 | |
8138 | if (NODATA_WANTED) |
8139 | goto no_alloc; |
8140 | |
8141 | /* save current stack pointer */ |
8142 | if (root_scope->vla.loc == 0) { |
8143 | struct scope *v = cur_scope; |
8144 | gen_vla_sp_save(loc -= PTR_SIZE); |
8145 | do v->vla.loc = loc; while ((v = v->prev)); |
8146 | } |
8147 | |
8148 | vla_runtime_type_size(type, &a); |
8149 | gen_vla_alloc(type, a); |
8150 | #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64 |
8151 | /* on _WIN64, because of the function args scratch area, the |
8152 | result of alloca differs from RSP and is returned in RAX. */ |
8153 | gen_vla_result(addr), addr = (loc -= PTR_SIZE); |
8154 | #endif |
8155 | gen_vla_sp_save(addr); |
8156 | cur_scope->vla.loc = addr; |
8157 | cur_scope->vla.num++; |
8158 | } else if (has_init) { |
8159 | p.sec = sec; |
8160 | decl_initializer(&p, type, addr, DIF_FIRST); |
8161 | /* patch flexible array member size back to -1, */ |
8162 | /* for possible subsequent similar declarations */ |
8163 | if (flexible_array) |
8164 | flexible_array->type.ref->c = -1; |
8165 | } |
8166 | |
8167 | no_alloc: |
8168 | /* restore parse state if needed */ |
8169 | if (init_str) { |
8170 | end_macro(); |
8171 | next(); |
8172 | } |
8173 | |
8174 | nocode_wanted = saved_nocode_wanted; |
8175 | } |
8176 | |
8177 | /* parse a function defined by symbol 'sym' and generate its code in |
8178 | 'cur_text_section' */ |
8179 | static void gen_function(Sym *sym) |
8180 | { |
8181 | struct scope f = { 0 }; |
8182 | cur_scope = root_scope = &f; |
8183 | nocode_wanted = 0; |
8184 | ind = cur_text_section->data_offset; |
8185 | if (sym->a.aligned) { |
8186 | size_t newoff = section_add(cur_text_section, 0, |
8187 | 1 << (sym->a.aligned - 1)); |
8188 | gen_fill_nops(newoff - ind); |
8189 | } |
8190 | /* NOTE: we patch the symbol size later */ |
8191 | put_extern_sym(sym, cur_text_section, ind, 0); |
8192 | if (sym->type.ref->f.func_ctor) |
8193 | add_array (tcc_state, ".init_array" , sym->c); |
8194 | if (sym->type.ref->f.func_dtor) |
8195 | add_array (tcc_state, ".fini_array" , sym->c); |
8196 | |
8197 | funcname = get_tok_str(sym->v, NULL); |
8198 | func_ind = ind; |
8199 | func_vt = sym->type.ref->type; |
8200 | func_var = sym->type.ref->f.func_type == FUNC_ELLIPSIS; |
8201 | |
8202 | /* put debug symbol */ |
8203 | tcc_debug_funcstart(tcc_state, sym); |
8204 | /* push a dummy symbol to enable local sym storage */ |
8205 | sym_push2(&local_stack, SYM_FIELD, 0, 0); |
8206 | local_scope = 1; /* for function parameters */ |
8207 | gfunc_prolog(sym); |
8208 | local_scope = 0; |
8209 | rsym = 0; |
8210 | clear_temp_local_var_list(); |
8211 | block(0); |
8212 | gsym(rsym); |
8213 | nocode_wanted = 0; |
8214 | /* reset local stack */ |
8215 | pop_local_syms(&local_stack, NULL, 0, func_var); |
8216 | gfunc_epilog(); |
8217 | cur_text_section->data_offset = ind; |
8218 | local_scope = 0; |
8219 | label_pop(&global_label_stack, NULL, 0); |
8220 | sym_pop(&all_cleanups, NULL, 0); |
8221 | /* patch symbol size */ |
8222 | elfsym(sym)->st_size = ind - func_ind; |
8223 | /* end of function */ |
8224 | tcc_debug_funcend(tcc_state, ind - func_ind); |
8225 | /* It's better to crash than to generate wrong code */ |
8226 | cur_text_section = NULL; |
8227 | funcname = "" ; /* for safety */ |
8228 | func_vt.t = VT_VOID; /* for safety */ |
8229 | func_var = 0; /* for safety */ |
8230 | ind = 0; /* for safety */ |
8231 | nocode_wanted = 0x80000000; |
8232 | check_vstack(); |
8233 | /* do this after funcend debug info */ |
8234 | next(); |
8235 | } |
8236 | |
8237 | static void gen_inline_functions(TCCState *s) |
8238 | { |
8239 | Sym *sym; |
8240 | int inline_generated, i; |
8241 | struct InlineFunc *fn; |
8242 | |
8243 | tcc_open_bf(s, ":inline:" , 0); |
8244 | /* iterate while inline function are referenced */ |
8245 | do { |
8246 | inline_generated = 0; |
8247 | for (i = 0; i < s->nb_inline_fns; ++i) { |
8248 | fn = s->inline_fns[i]; |
8249 | sym = fn->sym; |
8250 | if (sym && (sym->c || !(sym->type.t & VT_INLINE))) { |
8251 | /* the function was used or forced (and then not internal): |
8252 | generate its code and convert it to a normal function */ |
8253 | fn->sym = NULL; |
8254 | tcc_debug_putfile(s, fn->filename); |
8255 | begin_macro(fn->func_str, 1); |
8256 | next(); |
8257 | cur_text_section = text_section; |
8258 | gen_function(sym); |
8259 | end_macro(); |
8260 | |
8261 | inline_generated = 1; |
8262 | } |
8263 | } |
8264 | } while (inline_generated); |
8265 | tcc_close(); |
8266 | } |
8267 | |
8268 | static void free_inline_functions(TCCState *s) |
8269 | { |
8270 | int i; |
8271 | /* free tokens of unused inline functions */ |
8272 | for (i = 0; i < s->nb_inline_fns; ++i) { |
8273 | struct InlineFunc *fn = s->inline_fns[i]; |
8274 | if (fn->sym) |
8275 | tok_str_free(fn->func_str); |
8276 | } |
8277 | dynarray_reset(&s->inline_fns, &s->nb_inline_fns); |
8278 | } |
8279 | |
8280 | /* 'l' is VT_LOCAL or VT_CONST to define default storage type, or VT_CMP |
8281 | if parsing old style parameter decl list (and FUNC_SYM is set then) */ |
8282 | static int decl0(int l, int is_for_loop_init, Sym *func_sym) |
8283 | { |
8284 | int v, has_init, r; |
8285 | CType type, btype; |
8286 | Sym *sym; |
8287 | AttributeDef ad, adbase; |
8288 | |
8289 | while (1) { |
8290 | if (tok == TOK_STATIC_ASSERT) { |
8291 | CString error_str; |
8292 | int c; |
8293 | |
8294 | next(); |
8295 | skip('('); |
8296 | c = expr_const(); |
8297 | |
8298 | if (tok == ')') { |
8299 | if (!c) |
8300 | tcc_error("_Static_assert fail" ); |
8301 | next(); |
8302 | goto static_assert_out; |
8303 | } |
8304 | |
8305 | skip(','); |
8306 | parse_mult_str(&error_str, "string constant" ); |
8307 | if (c == 0) |
8308 | tcc_error("%s" , (char *)error_str.data); |
8309 | cstr_free(&error_str); |
8310 | skip(')'); |
8311 | static_assert_out: |
8312 | skip(';'); |
8313 | continue; |
8314 | } |
8315 | if (!parse_btype(&btype, &adbase)) { |
8316 | if (is_for_loop_init) |
8317 | return 0; |
8318 | /* skip redundant ';' if not in old parameter decl scope */ |
8319 | if (tok == ';' && l != VT_CMP) { |
8320 | next(); |
8321 | continue; |
8322 | } |
8323 | if (l != VT_CONST) |
8324 | break; |
8325 | if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) { |
8326 | /* global asm block */ |
8327 | asm_global_instr(); |
8328 | continue; |
8329 | } |
8330 | if (tok >= TOK_UIDENT) { |
8331 | /* special test for old K&R protos without explicit int |
8332 | type. Only accepted when defining global data */ |
8333 | btype.t = VT_INT; |
8334 | } else { |
8335 | if (tok != TOK_EOF) |
8336 | expect("declaration" ); |
8337 | break; |
8338 | } |
8339 | } |
8340 | if (tok == ';') { |
8341 | if ((btype.t & VT_BTYPE) == VT_STRUCT) { |
8342 | int v = btype.ref->v; |
8343 | if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM) |
8344 | tcc_warning("unnamed struct/union that defines no instances" ); |
8345 | next(); |
8346 | continue; |
8347 | } |
8348 | if (IS_ENUM(btype.t)) { |
8349 | next(); |
8350 | continue; |
8351 | } |
8352 | } |
8353 | while (1) { /* iterate thru each declaration */ |
8354 | type = btype; |
8355 | ad = adbase; |
8356 | type_decl(&type, &ad, &v, TYPE_DIRECT); |
8357 | #if 0 |
8358 | { |
8359 | char buf[500]; |
8360 | type_to_str(buf, sizeof(buf), &type, get_tok_str(v, NULL)); |
8361 | printf("type = '%s'\n" , buf); |
8362 | } |
8363 | #endif |
8364 | if ((type.t & VT_BTYPE) == VT_FUNC) { |
8365 | if ((type.t & VT_STATIC) && (l == VT_LOCAL)) |
8366 | tcc_error("function without file scope cannot be static" ); |
8367 | /* if old style function prototype, we accept a |
8368 | declaration list */ |
8369 | sym = type.ref; |
8370 | if (sym->f.func_type == FUNC_OLD && l == VT_CONST) |
8371 | decl0(VT_CMP, 0, sym); |
8372 | #ifdef TCC_TARGET_MACHO |
8373 | if (sym->f.func_alwinl |
8374 | && ((type.t & (VT_EXTERN | VT_INLINE)) |
8375 | == (VT_EXTERN | VT_INLINE))) { |
8376 | /* always_inline functions must be handled as if they |
8377 | don't generate multiple global defs, even if extern |
8378 | inline, i.e. GNU inline semantics for those. Rewrite |
8379 | them into static inline. */ |
8380 | type.t &= ~VT_EXTERN; |
8381 | type.t |= VT_STATIC; |
8382 | } |
8383 | #endif |
8384 | /* always compile 'extern inline' */ |
8385 | if (type.t & VT_EXTERN) |
8386 | type.t &= ~VT_INLINE; |
8387 | } |
8388 | |
8389 | if (gnu_ext && (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) { |
8390 | ad.asm_label = asm_label_instr(); |
8391 | /* parse one last attribute list, after asm label */ |
8392 | parse_attribute(&ad); |
8393 | #if 0 |
8394 | /* gcc does not allow __asm__("label") with function definition, |
8395 | but why not ... */ |
8396 | if (tok == '{') |
8397 | expect(";" ); |
8398 | #endif |
8399 | } |
8400 | |
8401 | #ifdef TCC_TARGET_PE |
8402 | if (ad.a.dllimport || ad.a.dllexport) { |
8403 | if (type.t & VT_STATIC) |
8404 | tcc_error("cannot have dll linkage with static" ); |
8405 | if (type.t & VT_TYPEDEF) { |
8406 | tcc_warning("'%s' attribute ignored for typedef" , |
8407 | ad.a.dllimport ? (ad.a.dllimport = 0, "dllimport" ) : |
8408 | (ad.a.dllexport = 0, "dllexport" )); |
8409 | } else if (ad.a.dllimport) { |
8410 | if ((type.t & VT_BTYPE) == VT_FUNC) |
8411 | ad.a.dllimport = 0; |
8412 | else |
8413 | type.t |= VT_EXTERN; |
8414 | } |
8415 | } |
8416 | #endif |
8417 | if (tok == '{') { |
8418 | if (l != VT_CONST) |
8419 | tcc_error("cannot use local functions" ); |
8420 | if ((type.t & VT_BTYPE) != VT_FUNC) |
8421 | expect("function definition" ); |
8422 | |
8423 | /* reject abstract declarators in function definition |
8424 | make old style params without decl have int type */ |
8425 | sym = type.ref; |
8426 | while ((sym = sym->next) != NULL) { |
8427 | if (!(sym->v & ~SYM_FIELD)) |
8428 | expect("identifier" ); |
8429 | if (sym->type.t == VT_VOID) |
8430 | sym->type = int_type; |
8431 | } |
8432 | |
8433 | /* apply post-declaraton attributes */ |
8434 | merge_funcattr(&type.ref->f, &ad.f); |
8435 | |
8436 | /* put function symbol */ |
8437 | type.t &= ~VT_EXTERN; |
8438 | sym = external_sym(v, &type, 0, &ad); |
8439 | |
8440 | /* static inline functions are just recorded as a kind |
8441 | of macro. Their code will be emitted at the end of |
8442 | the compilation unit only if they are used */ |
8443 | if (sym->type.t & VT_INLINE) { |
8444 | struct InlineFunc *fn; |
8445 | fn = tcc_malloc(sizeof *fn + strlen(file->filename)); |
8446 | strcpy(fn->filename, file->filename); |
8447 | fn->sym = sym; |
8448 | skip_or_save_block(&fn->func_str); |
8449 | dynarray_add(&tcc_state->inline_fns, |
8450 | &tcc_state->nb_inline_fns, fn); |
8451 | } else { |
8452 | /* compute text section */ |
8453 | cur_text_section = ad.section; |
8454 | if (!cur_text_section) |
8455 | cur_text_section = text_section; |
8456 | gen_function(sym); |
8457 | } |
8458 | break; |
8459 | } else { |
8460 | if (l == VT_CMP) { |
8461 | /* find parameter in function parameter list */ |
8462 | for (sym = func_sym->next; sym; sym = sym->next) |
8463 | if ((sym->v & ~SYM_FIELD) == v) |
8464 | goto found; |
8465 | tcc_error("declaration for parameter '%s' but no such parameter" , |
8466 | get_tok_str(v, NULL)); |
8467 | found: |
8468 | if (type.t & VT_STORAGE) /* 'register' is okay */ |
8469 | tcc_error("storage class specified for '%s'" , |
8470 | get_tok_str(v, NULL)); |
8471 | if (sym->type.t != VT_VOID) |
8472 | tcc_error("redefinition of parameter '%s'" , |
8473 | get_tok_str(v, NULL)); |
8474 | convert_parameter_type(&type); |
8475 | sym->type = type; |
8476 | } else if (type.t & VT_TYPEDEF) { |
8477 | /* save typedefed type */ |
8478 | /* XXX: test storage specifiers ? */ |
8479 | sym = sym_find(v); |
8480 | if (sym && sym->sym_scope == local_scope) { |
8481 | if (!is_compatible_types(&sym->type, &type) |
8482 | || !(sym->type.t & VT_TYPEDEF)) |
8483 | tcc_error("incompatible redefinition of '%s'" , |
8484 | get_tok_str(v, NULL)); |
8485 | sym->type = type; |
8486 | } else { |
8487 | sym = sym_push(v, &type, 0, 0); |
8488 | } |
8489 | sym->a = ad.a; |
8490 | sym->f = ad.f; |
8491 | if (tcc_state->do_debug) |
8492 | tcc_debug_typedef (tcc_state, sym); |
8493 | } else if ((type.t & VT_BTYPE) == VT_VOID |
8494 | && !(type.t & VT_EXTERN)) { |
8495 | tcc_error("declaration of void object" ); |
8496 | } else { |
8497 | r = 0; |
8498 | if ((type.t & VT_BTYPE) == VT_FUNC) { |
8499 | /* external function definition */ |
8500 | /* specific case for func_call attribute */ |
8501 | type.ref->f = ad.f; |
8502 | } else if (!(type.t & VT_ARRAY)) { |
8503 | /* not lvalue if array */ |
8504 | r |= VT_LVAL; |
8505 | } |
8506 | has_init = (tok == '='); |
8507 | if (has_init && (type.t & VT_VLA)) |
8508 | tcc_error("variable length array cannot be initialized" ); |
8509 | if (((type.t & VT_EXTERN) && (!has_init || l != VT_CONST)) |
8510 | || (type.t & VT_BTYPE) == VT_FUNC |
8511 | /* as with GCC, uninitialized global arrays with no size |
8512 | are considered extern: */ |
8513 | || ((type.t & VT_ARRAY) && !has_init |
8514 | && l == VT_CONST && type.ref->c < 0) |
8515 | ) { |
8516 | /* external variable or function */ |
8517 | type.t |= VT_EXTERN; |
8518 | sym = external_sym(v, &type, r, &ad); |
8519 | if (ad.alias_target) { |
8520 | /* Aliases need to be emitted when their target |
8521 | symbol is emitted, even if perhaps unreferenced. |
8522 | We only support the case where the base is |
8523 | already defined, otherwise we would need |
8524 | deferring to emit the aliases until the end of |
8525 | the compile unit. */ |
8526 | Sym *alias_target = sym_find(ad.alias_target); |
8527 | ElfSym *esym = elfsym(alias_target); |
8528 | if (!esym) |
8529 | tcc_error("unsupported forward __alias__ attribute" ); |
8530 | put_extern_sym2(sym, esym->st_shndx, |
8531 | esym->st_value, esym->st_size, 1); |
8532 | } |
8533 | } else { |
8534 | if (type.t & VT_STATIC) |
8535 | r |= VT_CONST; |
8536 | else |
8537 | r |= l; |
8538 | if (has_init) |
8539 | next(); |
8540 | else if (l == VT_CONST) |
8541 | /* uninitialized global variables may be overridden */ |
8542 | type.t |= VT_EXTERN; |
8543 | decl_initializer_alloc(&type, &ad, r, has_init, v, l); |
8544 | } |
8545 | } |
8546 | if (tok != ',') { |
8547 | if (is_for_loop_init) |
8548 | return 1; |
8549 | skip(';'); |
8550 | break; |
8551 | } |
8552 | next(); |
8553 | } |
8554 | } |
8555 | } |
8556 | return 0; |
8557 | } |
8558 | |
8559 | static void decl(int l) |
8560 | { |
8561 | decl0(l, 0, NULL); |
8562 | } |
8563 | |
8564 | /* ------------------------------------------------------------------------- */ |
8565 | #undef gjmp_addr |
8566 | #undef gjmp |
8567 | /* ------------------------------------------------------------------------- */ |
8568 | |