fix-mixed-struct (patch by Pip Cet)
[tinycc.git] / tccgen.c
Commit [+]AuthorDateLineData
a93bcdff grischka2009-05-05 20:17:11 +02001/*
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
88a3ccab grischka2009-12-20 01:53:49 +010021#include "tcc.h"
22
23/********************************************************/
24/* global variables */
25
26/* loc : local variable index
27 ind : output code index
28 rsym: return symbol
29 anon_sym: anonymous symbol index
30*/
31ST_DATA int rsym, anon_sym, ind, loc;
32
33ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */
34ST_DATA Section *cur_text_section; /* current section where function code is generated */
35#ifdef CONFIG_TCC_ASM
36ST_DATA Section *last_text_section; /* to handle .previous asm directive */
37#endif
38#ifdef CONFIG_TCC_BCHECK
39/* bound check related sections */
40ST_DATA Section *bounds_section; /* contains global data bound description */
41ST_DATA Section *lbounds_section; /* contains local data bound description */
42#endif
43/* symbol sections */
44ST_DATA Section *symtab_section, *strtab_section;
45/* debug sections */
46ST_DATA Section *stab_section, *stabstr_section;
47ST_DATA Sym *sym_free_first;
48ST_DATA void **sym_pools;
49ST_DATA int nb_sym_pools;
50
51ST_DATA Sym *global_stack;
52ST_DATA Sym *local_stack;
cf95ac39 Thomas Preud'homme2012-10-25 19:40:04 +020053ST_DATA Sym *scope_stack_bottom;
88a3ccab grischka2009-12-20 01:53:49 +010054ST_DATA Sym *define_stack;
55ST_DATA Sym *global_label_stack;
56ST_DATA Sym *local_label_stack;
57
999274ca seyko2015-05-04 04:09:05 +030058ST_DATA int vlas_in_scope; /* number of VLAs that are currently in scope */
41b3c7a5 James Lyon2013-04-27 20:39:34 +010059ST_DATA int vla_sp_root_loc; /* vla_sp_loc for SP before any VLAs were pushed */
999274ca seyko2015-05-04 04:09:05 +030060ST_DATA int vla_sp_loc; /* Pointer to variable holding location to store stack pointer on the stack when modifying stack pointer */
41b3c7a5 James Lyon2013-04-27 20:39:34 +010061
30df3189 grischka2015-05-09 14:29:39 +020062ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop, *pvtop;
88a3ccab grischka2009-12-20 01:53:49 +010063
64ST_DATA int const_wanted; /* true if constant wanted */
65ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */
66ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
67ST_DATA CType func_vt; /* current function return type (used by return instruction) */
8efaa711 Thomas Preud'homme2014-01-06 22:27:39 +080068ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */
88a3ccab grischka2009-12-20 01:53:49 +010069ST_DATA int func_vc;
70ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
30df3189 grischka2015-05-09 14:29:39 +020071ST_DATA const char *funcname;
88a3ccab grischka2009-12-20 01:53:49 +010072
718fd591 Michael Matz2012-04-16 01:13:25 +020073ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
88a3ccab grischka2009-12-20 01:53:49 +010074
75/* ------------------------------------------------------------------------- */
76static void gen_cast(CType *type);
77static inline CType *pointed_type(CType *type);
78static int is_compatible_types(CType *type1, CType *type2);
79static int parse_btype(CType *type, AttributeDef *ad);
80static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
81static void parse_expr_type(CType *type);
367bb6f4 seyko2015-03-23 07:40:41 +030082static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only);
88a3ccab grischka2009-12-20 01:53:49 +010083static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg, int is_expr);
11b2d335 Thomas Preud'homme2011-02-07 23:43:18 +010084static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, char *asm_label, int scope);
5eb82755 Joe Soroka2011-03-08 13:36:04 -080085static int decl0(int l, int is_for_loop_init);
88a3ccab grischka2009-12-20 01:53:49 +010086static void expr_eq(void);
87static void unary_type(CType *type);
ace0f7f2 Joe Soroka2011-04-06 09:17:03 -070088static void vla_runtime_type_size(CType *type, int *a);
999274ca seyko2015-05-04 04:09:05 +030089static void vla_sp_restore(void);
90static void vla_sp_restore_root(void);
88a3ccab grischka2009-12-20 01:53:49 +010091static int is_compatible_parameter_types(CType *type1, CType *type2);
92static void expr_type(CType *type);
822f4630
UJ
Urs Janssen2014-04-10 11:53:54 +020093ST_FUNC void vpush64(int ty, unsigned long long v);
94ST_FUNC void vpush(CType *type);
95ST_FUNC int gvtst(int inv, int t);
96ST_FUNC int is_btype_size(int bt);
88a3ccab grischka2009-12-20 01:53:49 +010097
98ST_INLN int is_float(int t)
99{
100 int bt;
101 bt = t & VT_BTYPE;
0e17671f James Lyon2013-04-19 15:33:16 +0100102 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT || bt == VT_QFLOAT;
88a3ccab grischka2009-12-20 01:53:49 +0100103}
104
df9cce24 grischka2011-08-01 01:10:36 +0200105/* we use our own 'finite' function to avoid potential problems with
106 non standard math libs */
107/* XXX: endianness dependent */
108ST_FUNC int ieee_finite(double d)
109{
3fe2a95d grischka2014-01-07 14:57:07 +0100110 int p[4];
111 memcpy(p, &d, sizeof(double));
df9cce24 grischka2011-08-01 01:10:36 +0200112 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
113}
114
88a3ccab grischka2009-12-20 01:53:49 +0100115ST_FUNC void test_lvalue(void)
116{
117 if (!(vtop->r & VT_LVAL))
118 expect("lvalue");
119}
120
30df3189 grischka2015-05-09 14:29:39 +0200121ST_FUNC void check_vstack(void)
122{
123 if (pvtop != vtop)
124 tcc_error("internal compiler error: vstack leak (%d)", vtop - pvtop);
125}
126
88a3ccab grischka2009-12-20 01:53:49 +0100127/* ------------------------------------------------------------------------- */
128/* symbol allocator */
129static Sym *__sym_malloc(void)
130{
131 Sym *sym_pool, *sym, *last_sym;
132 int i;
133
134 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
135 dynarray_add(&sym_pools, &nb_sym_pools, sym_pool);
136
137 last_sym = sym_free_first;
138 sym = sym_pool;
139 for(i = 0; i < SYM_POOL_NB; i++) {
140 sym->next = last_sym;
141 last_sym = sym;
142 sym++;
143 }
144 sym_free_first = last_sym;
145 return last_sym;
146}
147
148static inline Sym *sym_malloc(void)
149{
150 Sym *sym;
151 sym = sym_free_first;
152 if (!sym)
153 sym = __sym_malloc();
154 sym_free_first = sym->next;
155 return sym;
156}
157
158ST_INLN void sym_free(Sym *sym)
159{
160 sym->next = sym_free_first;
7c27186a grischka2015-04-23 23:26:46 +0200161 tcc_free(sym->asm_label);
88a3ccab grischka2009-12-20 01:53:49 +0100162 sym_free_first = sym;
163}
164
165/* push, without hashing */
166ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c)
167{
168 Sym *s;
cf95ac39
TP
Thomas Preud'homme2012-10-25 19:40:04 +0200169 if (ps == &local_stack) {
170 for (s = *ps; s && s != scope_stack_bottom; s = s->prev)
171 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM && s->v == v)
172 tcc_error("incompatible types for redefinition of '%s'",
173 get_tok_str(v, NULL));
174 }
88a3ccab grischka2009-12-20 01:53:49 +0100175 s = sym_malloc();
32a682b8 Thomas Preud'homme2011-02-07 22:42:38 +0100176 s->asm_label = NULL;
88a3ccab grischka2009-12-20 01:53:49 +0100177 s->v = v;
178 s->type.t = t;
179 s->type.ref = NULL;
180#ifdef _WIN64
181 s->d = NULL;
182#endif
183 s->c = c;
184 s->next = NULL;
185 /* add in stack */
186 s->prev = *ps;
187 *ps = s;
188 return s;
189}
190
191/* find a symbol and return its associated structure. 's' is the top
192 of the symbol stack */
193ST_FUNC Sym *sym_find2(Sym *s, int v)
194{
195 while (s) {
196 if (s->v == v)
197 return s;
c2422ba8
TP
Thomas Preud'homme2014-04-07 21:12:08 +0800198 else if (s->v == -1)
199 return NULL;
88a3ccab grischka2009-12-20 01:53:49 +0100200 s = s->prev;
201 }
202 return NULL;
203}
204
205/* structure lookup */
206ST_INLN Sym *struct_find(int v)
207{
208 v -= TOK_IDENT;
209 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
210 return NULL;
211 return table_ident[v]->sym_struct;
212}
213
214/* find an identifier */
215ST_INLN Sym *sym_find(int v)
216{
217 v -= TOK_IDENT;
218 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
219 return NULL;
220 return table_ident[v]->sym_identifier;
221}
222
223/* push a given symbol on the symbol stack */
224ST_FUNC Sym *sym_push(int v, CType *type, int r, int c)
225{
226 Sym *s, **ps;
227 TokenSym *ts;
228
229 if (local_stack)
230 ps = &local_stack;
231 else
232 ps = &global_stack;
233 s = sym_push2(ps, v, type->t, c);
234 s->type.ref = type->ref;
235 s->r = r;
236 /* don't record fields or anonymous symbols */
237 /* XXX: simplify */
238 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
239 /* record symbol in token array */
240 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
241 if (v & SYM_STRUCT)
242 ps = &ts->sym_struct;
243 else
244 ps = &ts->sym_identifier;
245 s->prev_tok = *ps;
246 *ps = s;
247 }
248 return s;
249}
250
251/* push a global identifier */
252ST_FUNC Sym *global_identifier_push(int v, int t, int c)
253{
254 Sym *s, **ps;
255 s = sym_push2(&global_stack, v, t, c);
256 /* don't record anonymous symbol */
257 if (v < SYM_FIRST_ANOM) {
258 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
259 /* modify the top most local identifier, so that
260 sym_identifier will point to 's' when popped */
261 while (*ps != NULL)
262 ps = &(*ps)->prev_tok;
263 s->prev_tok = NULL;
264 *ps = s;
265 }
266 return s;
267}
268
269/* pop symbols until top reaches 'b' */
270ST_FUNC void sym_pop(Sym **ptop, Sym *b)
271{
272 Sym *s, *ss, **ps;
273 TokenSym *ts;
274 int v;
275
276 s = *ptop;
277 while(s != b) {
278 ss = s->prev;
279 v = s->v;
280 /* remove symbol in token array */
281 /* XXX: simplify */
282 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
283 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
284 if (v & SYM_STRUCT)
285 ps = &ts->sym_struct;
286 else
287 ps = &ts->sym_identifier;
288 *ps = s->prev_tok;
289 }
290 sym_free(s);
291 s = ss;
292 }
293 *ptop = b;
294}
295
8bcb2ae1
JS
Joe Soroka2011-03-07 01:02:23 -0800296static void weaken_symbol(Sym *sym)
297{
298 sym->type.t |= VT_WEAK;
299 if (sym->c > 0) {
300 int esym_type;
301 ElfW(Sym) *esym;
302
303 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
304 esym_type = ELFW(ST_TYPE)(esym->st_info);
305 esym->st_info = ELFW(ST_INFO)(STB_WEAK, esym_type);
306 }
307}
308
fbda78ae
MM
Michael Matz2014-04-14 02:53:11 +0200309static void apply_visibility(Sym *sym, CType *type)
310{
311 int vis = sym->type.t & VT_VIS_MASK;
312 int vis2 = type->t & VT_VIS_MASK;
313 if (vis == (STV_DEFAULT << VT_VIS_SHIFT))
314 vis = vis2;
315 else if (vis2 == (STV_DEFAULT << VT_VIS_SHIFT))
316 ;
317 else
318 vis = (vis < vis2) ? vis : vis2;
319 sym->type.t &= ~VT_VIS_MASK;
320 sym->type.t |= vis;
321
322 if (sym->c > 0) {
fbda78ae
MM
Michael Matz2014-04-14 02:53:11 +0200323 ElfW(Sym) *esym;
324
325 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
326 vis >>= VT_VIS_SHIFT;
327 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1)) | vis;
328 }
329}
330
88a3ccab grischka2009-12-20 01:53:49 +0100331/* ------------------------------------------------------------------------- */
332
333ST_FUNC void swap(int *p, int *q)
0d1ed741 grischka2009-05-05 20:18:10 +0200334{
335 int t;
336 t = *p;
337 *p = *q;
338 *q = t;
339}
340
88a3ccab grischka2009-12-20 01:53:49 +0100341static void vsetc(CType *type, int r, CValue *vc)
0d1ed741 grischka2009-05-05 20:18:10 +0200342{
343 int v;
344
345 if (vtop >= vstack + (VSTACK_SIZE - 1))
2bd0daab grischka2014-01-06 19:56:26 +0100346 tcc_error("memory full (vstack)");
0d1ed741 grischka2009-05-05 20:18:10 +0200347 /* cannot let cpu flags if other instruction are generated. Also
348 avoid leaving VT_JMP anywhere except on the top of the stack
349 because it would complicate the code generator. */
350 if (vtop >= vstack) {
351 v = vtop->r & VT_VALMASK;
352 if (v == VT_CMP || (v & ~1) == VT_JMP)
353 gv(RC_INT);
354 }
355 vtop++;
356 vtop->type = *type;
357 vtop->r = r;
358 vtop->r2 = VT_CONST;
359 vtop->c = *vc;
360}
361
8de9b7a6 Thomas Preud'homme2010-04-11 01:53:40 +0200362/* push constant of type "type" with useless value */
822f4630 Urs Janssen2014-04-10 11:53:54 +0200363ST_FUNC void vpush(CType *type)
8de9b7a6
TP
Thomas Preud'homme2010-04-11 01:53:40 +0200364{
365 CValue cval;
366 vsetc(type, VT_CONST, &cval);
367}
368
0d1ed741 grischka2009-05-05 20:18:10 +0200369/* push integer constant */
88a3ccab grischka2009-12-20 01:53:49 +0100370ST_FUNC void vpushi(int v)
0d1ed741 grischka2009-05-05 20:18:10 +0200371{
372 CValue cval;
373 cval.i = v;
374 vsetc(&int_type, VT_CONST, &cval);
375}
376
718fd591 Michael Matz2012-04-16 01:13:25 +0200377/* push a pointer sized constant */
5879c854 grischka2014-04-04 20:18:39 +0200378static void vpushs(addr_t v)
718fd591
MM
Michael Matz2012-04-16 01:13:25 +0200379{
380 CValue cval;
5879c854 grischka2014-04-04 20:18:39 +0200381 cval.ptr_offset = v;
718fd591
MM
Michael Matz2012-04-16 01:13:25 +0200382 vsetc(&size_type, VT_CONST, &cval);
383}
384
8eb86ab7 Thomas Preud'homme2010-05-06 02:19:00 +0200385/* push arbitrary 64bit constant */
822f4630 Urs Janssen2014-04-10 11:53:54 +0200386ST_FUNC void vpush64(int ty, unsigned long long v)
8eb86ab7 Thomas Preud'homme2010-05-06 02:19:00 +0200387{
4bc83ac3 mingodad2014-03-26 20:14:39 +0000388 CValue cval;
5879c854 grischka2014-04-04 20:18:39 +0200389 CType ctype;
8eb86ab7 Thomas Preud'homme2010-05-06 02:19:00 +0200390 ctype.t = ty;
d6d7686b grischka2013-02-08 19:07:11 +0100391 ctype.ref = NULL;
8eb86ab7
TP
Thomas Preud'homme2010-05-06 02:19:00 +0200392 cval.ull = v;
393 vsetc(&ctype, VT_CONST, &cval);
394}
395
d6d7686b grischka2013-02-08 19:07:11 +0100396/* push long long constant */
397static inline void vpushll(long long v)
398{
399 vpush64(VT_LLONG, v);
400}
401
9e11476e
MM
Michael Matz2014-01-11 23:42:58 +0100402/* push a symbol value of TYPE */
403static inline void vpushsym(CType *type, Sym *sym)
404{
405 CValue cval;
5879c854 grischka2014-04-04 20:18:39 +0200406 cval.ptr_offset = 0;
9e11476e
MM
Michael Matz2014-01-11 23:42:58 +0100407 vsetc(type, VT_CONST | VT_SYM, &cval);
408 vtop->sym = sym;
409}
410
0d1ed741 grischka2009-05-05 20:18:10 +0200411/* Return a static symbol pointing to a section */
88a3ccab grischka2009-12-20 01:53:49 +0100412ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
0d1ed741 grischka2009-05-05 20:18:10 +0200413{
414 int v;
415 Sym *sym;
416
417 v = anon_sym++;
418 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
419 sym->type.ref = type->ref;
420 sym->r = VT_CONST | VT_SYM;
421 put_extern_sym(sym, sec, offset, size);
422 return sym;
423}
424
425/* push a reference to a section offset by adding a dummy symbol */
426static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
427{
9e11476e Michael Matz2014-01-11 23:42:58 +0100428 vpushsym(type, get_sym_ref(type, sec, offset, size));
0d1ed741 grischka2009-05-05 20:18:10 +0200429}
430
431/* define a new external reference to a symbol 'v' of type 'u' */
88a3ccab grischka2009-12-20 01:53:49 +0100432ST_FUNC Sym *external_global_sym(int v, CType *type, int r)
0d1ed741 grischka2009-05-05 20:18:10 +0200433{
434 Sym *s;
435
436 s = sym_find(v);
437 if (!s) {
438 /* push forward reference */
439 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
440 s->type.ref = type->ref;
441 s->r = r | VT_CONST | VT_SYM;
442 }
443 return s;
444}
445
32a682b8
TP
Thomas Preud'homme2011-02-07 22:42:38 +0100446/* define a new external reference to a symbol 'v' with alternate asm
447 name 'asm_label' of type 'u'. 'asm_label' is equal to NULL if there
448 is no alternate name (most cases) */
449static Sym *external_sym(int v, CType *type, int r, char *asm_label)
0d1ed741 grischka2009-05-05 20:18:10 +0200450{
451 Sym *s;
452
453 s = sym_find(v);
454 if (!s) {
455 /* push forward reference */
456 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
32a682b8 Thomas Preud'homme2011-02-07 22:42:38 +0100457 s->asm_label = asm_label;
0d1ed741 grischka2009-05-05 20:18:10 +0200458 s->type.t |= VT_EXTERN;
6a004ed1 grischka2009-06-17 02:09:52 +0200459 } else if (s->type.ref == func_old_type.ref) {
460 s->type.ref = type->ref;
461 s->r = r | VT_CONST | VT_SYM;
462 s->type.t |= VT_EXTERN;
463 } else if (!is_compatible_types(&s->type, type)) {
bf374a5f grischka2011-08-11 17:07:56 +0200464 tcc_error("incompatible types for redefinition of '%s'",
6a004ed1 grischka2009-06-17 02:09:52 +0200465 get_tok_str(v, NULL));
0d1ed741 grischka2009-05-05 20:18:10 +0200466 }
fbda78ae
MM
Michael Matz2014-04-14 02:53:11 +0200467 /* Merge some storage attributes. */
468 if (type->t & VT_WEAK)
469 weaken_symbol(s);
470
471 if (type->t & VT_VIS_MASK)
472 apply_visibility(s, type);
473
0d1ed741 grischka2009-05-05 20:18:10 +0200474 return s;
475}
476
477/* push a reference to global symbol v */
0de95730 grischka2009-12-20 20:33:41 +0100478ST_FUNC void vpush_global_sym(CType *type, int v)
0d1ed741 grischka2009-05-05 20:18:10 +0200479{
9e11476e Michael Matz2014-01-11 23:42:58 +0100480 vpushsym(type, external_global_sym(v, type, 0));
0d1ed741 grischka2009-05-05 20:18:10 +0200481}
482
88a3ccab grischka2009-12-20 01:53:49 +0100483ST_FUNC void vset(CType *type, int r, int v)
0d1ed741 grischka2009-05-05 20:18:10 +0200484{
9e11476e Michael Matz2014-01-11 23:42:58 +0100485 CValue cval;
0d1ed741 grischka2009-05-05 20:18:10 +0200486
487 cval.i = v;
488 vsetc(type, r, &cval);
489}
490
88a3ccab grischka2009-12-20 01:53:49 +0100491static void vseti(int r, int v)
0d1ed741 grischka2009-05-05 20:18:10 +0200492{
493 CType type;
494 type.t = VT_INT;
41e11236 grischka2009-12-19 22:10:13 +0100495 type.ref = 0;
0d1ed741 grischka2009-05-05 20:18:10 +0200496 vset(&type, r, v);
497}
498
88a3ccab grischka2009-12-20 01:53:49 +0100499ST_FUNC void vswap(void)
0d1ed741 grischka2009-05-05 20:18:10 +0200500{
c5892fe4 grischka2013-01-14 18:33:59 +0100501 SValue tmp;
9ca9c82f
MM
Michael Matz2012-04-16 02:52:15 +0200502 /* cannot let cpu flags if other instruction are generated. Also
503 avoid leaving VT_JMP anywhere except on the top of the stack
504 because it would complicate the code generator. */
505 if (vtop >= vstack) {
506 int v = vtop->r & VT_VALMASK;
507 if (v == VT_CMP || (v & ~1) == VT_JMP)
508 gv(RC_INT);
509 }
c5892fe4 grischka2013-01-14 18:33:59 +0100510 tmp = vtop[0];
511 vtop[0] = vtop[-1];
512 vtop[-1] = tmp;
63193d17 Kirill Smelkov2012-12-21 13:55:01 +0400513
c5892fe4 grischka2013-01-14 18:33:59 +0100514/* XXX: +2% overall speed possible with optimized memswap
515 *
516 * memswap(&vtop[0], &vtop[1], sizeof *vtop);
517 */
0d1ed741 grischka2009-05-05 20:18:10 +0200518}
519
4a01eb09 grischka2009-12-19 22:41:26 +0100520ST_FUNC void vpushv(SValue *v)
0d1ed741 grischka2009-05-05 20:18:10 +0200521{
522 if (vtop >= vstack + (VSTACK_SIZE - 1))
2bd0daab grischka2014-01-06 19:56:26 +0100523 tcc_error("memory full (vstack)");
0d1ed741 grischka2009-05-05 20:18:10 +0200524 vtop++;
525 *vtop = *v;
526}
527
4e04f67c seyko2015-05-14 07:32:24 +0300528ST_FUNC void vdup(void)
0d1ed741 grischka2009-05-05 20:18:10 +0200529{
530 vpushv(vtop);
531}
532
533/* save r to the memory stack, and mark it as being free */
88a3ccab grischka2009-12-20 01:53:49 +0100534ST_FUNC void save_reg(int r)
0d1ed741 grischka2009-05-05 20:18:10 +0200535{
536 int l, saved, size, align;
537 SValue *p, sv;
538 CType *type;
539
540 /* modify all stack values */
541 saved = 0;
542 l = 0;
543 for(p=vstack;p<=vtop;p++) {
544 if ((p->r & VT_VALMASK) == r ||
545 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
546 /* must save value on stack if not already done */
547 if (!saved) {
548 /* NOTE: must reload 'r' because r might be equal to r2 */
549 r = p->r & VT_VALMASK;
550 /* store register in the stack */
551 type = &p->type;
552 if ((p->r & VT_LVAL) ||
553 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +0000554#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
0d1ed741 grischka2009-05-05 20:18:10 +0200555 type = &char_pointer_type;
556#else
557 type = &int_type;
558#endif
559 size = type_size(type, &align);
560 loc = (loc - size) & -align;
561 sv.type.t = type->t;
562 sv.r = VT_LOCAL | VT_LVAL;
563 sv.c.ul = loc;
564 store(r, &sv);
565#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
566 /* x86 specific: need to pop fp register ST0 if saved */
567 if (r == TREG_ST0) {
c3701df1 Soloist Deng2009-06-08 19:26:19 +0200568 o(0xd8dd); /* fstp %st(0) */
0d1ed741 grischka2009-05-05 20:18:10 +0200569 }
570#endif
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +0000571#if !defined(TCC_TARGET_ARM64) && !defined(TCC_TARGET_X86_64)
0d1ed741 grischka2009-05-05 20:18:10 +0200572 /* special long long case */
573 if ((type->t & VT_BTYPE) == VT_LLONG) {
574 sv.c.ul += 4;
575 store(p->r2, &sv);
576 }
577#endif
578 l = loc;
579 saved = 1;
580 }
581 /* mark that stack entry as being saved on the stack */
582 if (p->r & VT_LVAL) {
583 /* also clear the bounded flag because the
584 relocation address of the function was stored in
585 p->c.ul */
586 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
587 } else {
588 p->r = lvalue_type(p->type.t) | VT_LOCAL;
589 }
590 p->r2 = VT_CONST;
591 p->c.ul = l;
592 }
593 }
594}
595
88a3ccab grischka2009-12-20 01:53:49 +0100596#ifdef TCC_TARGET_ARM
0d1ed741 grischka2009-05-05 20:18:10 +0200597/* find a register of class 'rc2' with at most one reference on stack.
598 * If none, call get_reg(rc) */
88a3ccab grischka2009-12-20 01:53:49 +0100599ST_FUNC int get_reg_ex(int rc, int rc2)
0d1ed741 grischka2009-05-05 20:18:10 +0200600{
601 int r;
602 SValue *p;
603
604 for(r=0;r<NB_REGS;r++) {
605 if (reg_classes[r] & rc2) {
606 int n;
607 n=0;
608 for(p = vstack; p <= vtop; p++) {
609 if ((p->r & VT_VALMASK) == r ||
610 (p->r2 & VT_VALMASK) == r)
611 n++;
612 }
613 if (n <= 1)
614 return r;
615 }
616 }
617 return get_reg(rc);
618}
88a3ccab grischka2009-12-20 01:53:49 +0100619#endif
0d1ed741 grischka2009-05-05 20:18:10 +0200620
621/* find a free register of class 'rc'. If none, save one register */
88a3ccab grischka2009-12-20 01:53:49 +0100622ST_FUNC int get_reg(int rc)
0d1ed741 grischka2009-05-05 20:18:10 +0200623{
624 int r;
625 SValue *p;
626
627 /* find a free register */
628 for(r=0;r<NB_REGS;r++) {
629 if (reg_classes[r] & rc) {
630 for(p=vstack;p<=vtop;p++) {
631 if ((p->r & VT_VALMASK) == r ||
632 (p->r2 & VT_VALMASK) == r)
633 goto notfound;
634 }
635 return r;
636 }
637 notfound: ;
638 }
639
640 /* no register left : free the first one on the stack (VERY
641 IMPORTANT to start from the bottom to ensure that we don't
642 spill registers used in gen_opi()) */
643 for(p=vstack;p<=vtop;p++) {
d1694f7d
TP
Thomas Preud'homme2012-07-11 23:39:05 +0200644 /* look at second register (if long long) */
645 r = p->r2 & VT_VALMASK;
0d1ed741 grischka2009-05-05 20:18:10 +0200646 if (r < VT_CONST && (reg_classes[r] & rc))
647 goto save_found;
d1694f7d Thomas Preud'homme2012-07-11 23:39:05 +0200648 r = p->r & VT_VALMASK;
0d1ed741 grischka2009-05-05 20:18:10 +0200649 if (r < VT_CONST && (reg_classes[r] & rc)) {
650 save_found:
651 save_reg(r);
652 return r;
653 }
654 }
655 /* Should never comes here */
656 return -1;
657}
658
659/* save registers up to (vtop - n) stack entry */
88a3ccab grischka2009-12-20 01:53:49 +0100660ST_FUNC void save_regs(int n)
0d1ed741 grischka2009-05-05 20:18:10 +0200661{
662 int r;
663 SValue *p, *p1;
664 p1 = vtop - n;
665 for(p = vstack;p <= p1; p++) {
666 r = p->r & VT_VALMASK;
667 if (r < VT_CONST) {
668 save_reg(r);
669 }
670 }
671}
672
946afd23 James Lyon2013-04-19 18:31:24 +0100673/* move register 's' (of type 't') to 'r', and flush previous value of r to memory
0d1ed741 grischka2009-05-05 20:18:10 +0200674 if needed */
946afd23 James Lyon2013-04-19 18:31:24 +0100675static void move_reg(int r, int s, int t)
0d1ed741 grischka2009-05-05 20:18:10 +0200676{
677 SValue sv;
678
679 if (r != s) {
680 save_reg(r);
946afd23
JL
James Lyon2013-04-19 18:31:24 +0100681 sv.type.t = t;
682 sv.type.ref = NULL;
0d1ed741 grischka2009-05-05 20:18:10 +0200683 sv.r = s;
684 sv.c.ul = 0;
685 load(r, &sv);
686 }
687}
688
689/* get address of vtop (vtop MUST BE an lvalue) */
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +0000690ST_FUNC void gaddrof(void)
0d1ed741 grischka2009-05-05 20:18:10 +0200691{
5bcc3eed Thomas Preud'homme2015-03-10 23:23:00 +0800692 if (vtop->r & VT_REF && !nocode_wanted)
8d107d9f grischka2010-12-17 13:15:01 +0100693 gv(RC_INT);
0d1ed741 grischka2009-05-05 20:18:10 +0200694 vtop->r &= ~VT_LVAL;
695 /* tricky: if saved lvalue, then we can go back to lvalue */
696 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
697 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
8d107d9f grischka2010-12-17 13:15:01 +0100698
699
0d1ed741 grischka2009-05-05 20:18:10 +0200700}
701
702#ifdef CONFIG_TCC_BCHECK
703/* generate lvalue bound code */
88a3ccab grischka2009-12-20 01:53:49 +0100704static void gbound(void)
0d1ed741 grischka2009-05-05 20:18:10 +0200705{
706 int lval_type;
707 CType type1;
708
709 vtop->r &= ~VT_MUSTBOUND;
710 /* if lvalue, then use checking code before dereferencing */
711 if (vtop->r & VT_LVAL) {
712 /* if not VT_BOUNDED value, then make one */
713 if (!(vtop->r & VT_BOUNDED)) {
714 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
715 /* must save type because we must set it to int to get pointer */
716 type1 = vtop->type;
559675b9 seyko2015-04-10 15:17:22 +0300717 vtop->type.t = VT_PTR;
0d1ed741 grischka2009-05-05 20:18:10 +0200718 gaddrof();
719 vpushi(0);
720 gen_bounded_ptr_add();
721 vtop->r |= lval_type;
722 vtop->type = type1;
723 }
724 /* then check for dereferencing */
725 gen_bounded_ptr_deref();
726 }
727}
728#endif
729
730/* store vtop a register belonging to class 'rc'. lvalues are
731 converted to values. Cannot be used if cannot be converted to
732 register value (such as structures). */
88a3ccab grischka2009-12-20 01:53:49 +0100733ST_FUNC int gv(int rc)
0d1ed741 grischka2009-05-05 20:18:10 +0200734{
ee06ef9d Thomas Preud'homme2011-05-16 14:15:32 +0200735 int r, bit_pos, bit_size, size, align, i;
ee06ef9d Thomas Preud'homme2011-05-16 14:15:32 +0200736 int rc2;
0d1ed741 grischka2009-05-05 20:18:10 +0200737
738 /* NOTE: get_reg can modify vstack[] */
739 if (vtop->type.t & VT_BITFIELD) {
740 CType type;
741 int bits = 32;
742 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
743 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
744 /* remove bit field info to avoid loops */
745 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
746 /* cast to int to propagate signedness in following ops */
747 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
748 type.t = VT_LLONG;
749 bits = 64;
750 } else
751 type.t = VT_INT;
752 if((vtop->type.t & VT_UNSIGNED) ||
753 (vtop->type.t & VT_BTYPE) == VT_BOOL)
754 type.t |= VT_UNSIGNED;
755 gen_cast(&type);
756 /* generate shifts */
757 vpushi(bits - (bit_pos + bit_size));
758 gen_op(TOK_SHL);
759 vpushi(bits - bit_size);
760 /* NOTE: transformed to SHR if unsigned */
761 gen_op(TOK_SAR);
762 r = gv(rc);
763 } else {
764 if (is_float(vtop->type.t) &&
765 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
766 Sym *sym;
767 int *ptr;
768 unsigned long offset;
769#if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
770 CValue check;
771#endif
772
773 /* XXX: unify with initializers handling ? */
774 /* CPUs usually cannot use float constants, so we store them
775 generically in data segment */
776 size = type_size(&vtop->type, &align);
777 offset = (data_section->data_offset + align - 1) & -align;
778 data_section->data_offset = offset;
779 /* XXX: not portable yet */
780#if defined(__i386__) || defined(__x86_64__)
781 /* Zero pad x87 tenbyte long doubles */
f115c123 grischka2011-08-06 16:08:03 +0200782 if (size == LDOUBLE_SIZE) {
0d1ed741 grischka2009-05-05 20:18:10 +0200783 vtop->c.tab[2] &= 0xffff;
f115c123 grischka2011-08-06 16:08:03 +0200784#if LDOUBLE_SIZE == 16
785 vtop->c.tab[3] = 0;
786#endif
787 }
0d1ed741 grischka2009-05-05 20:18:10 +0200788#endif
789 ptr = section_ptr_add(data_section, size);
790 size = size >> 2;
791#if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
792 check.d = 1;
793 if(check.tab[0])
794 for(i=0;i<size;i++)
795 ptr[i] = vtop->c.tab[size-1-i];
796 else
797#endif
798 for(i=0;i<size;i++)
799 ptr[i] = vtop->c.tab[i];
800 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
801 vtop->r |= VT_LVAL | VT_SYM;
802 vtop->sym = sym;
5879c854 grischka2014-04-04 20:18:39 +0200803 vtop->c.ptr_offset = 0;
0d1ed741 grischka2009-05-05 20:18:10 +0200804 }
805#ifdef CONFIG_TCC_BCHECK
806 if (vtop->r & VT_MUSTBOUND)
807 gbound();
808#endif
809
810 r = vtop->r & VT_VALMASK;
cbce6d2b James Lyon2013-04-19 22:05:49 +0100811 rc2 = (rc & RC_FLOAT) ? RC_FLOAT : RC_INT;
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +0000812#ifndef TCC_TARGET_ARM64
0d1ed741 grischka2009-05-05 20:18:10 +0200813 if (rc == RC_IRET)
814 rc2 = RC_LRET;
0e17671f
JL
James Lyon2013-04-19 15:33:16 +0100815#ifdef TCC_TARGET_X86_64
816 else if (rc == RC_FRET)
817 rc2 = RC_QRET;
ee06ef9d Thomas Preud'homme2011-05-16 14:15:32 +0200818#endif
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +0000819#endif
0e17671f James Lyon2013-04-19 15:33:16 +0100820
0d1ed741 grischka2009-05-05 20:18:10 +0200821 /* need to reload if:
822 - constant
823 - lvalue (need to dereference pointer)
824 - already a register, but not in the right class */
ab4a4ab2 grischka2009-12-17 21:09:53 +0100825 if (r >= VT_CONST
826 || (vtop->r & VT_LVAL)
827 || !(reg_classes[r] & rc)
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +0000828#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
0e17671f
JL
James Lyon2013-04-19 15:33:16 +0100829 || ((vtop->type.t & VT_BTYPE) == VT_QLONG && !(reg_classes[vtop->r2] & rc2))
830 || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT && !(reg_classes[vtop->r2] & rc2))
831#else
ab4a4ab2 grischka2009-12-17 21:09:53 +0100832 || ((vtop->type.t & VT_BTYPE) == VT_LLONG && !(reg_classes[vtop->r2] & rc2))
833#endif
834 )
835 {
0d1ed741 grischka2009-05-05 20:18:10 +0200836 r = get_reg(rc);
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +0000837#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
0e17671f James Lyon2013-04-19 15:33:16 +0100838 if (((vtop->type.t & VT_BTYPE) == VT_QLONG) || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT)) {
23f73e92 James Lyon2013-04-19 22:55:09 +0100839 int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE;
0e17671f James Lyon2013-04-19 15:33:16 +0100840#else
0d1ed741 grischka2009-05-05 20:18:10 +0200841 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
23f73e92 James Lyon2013-04-19 22:55:09 +0100842 int addr_type = VT_INT, load_size = 4, load_type = VT_INT;
0f5942c6 Thomas Preud'homme2013-09-24 15:36:04 +0200843 unsigned long long ll;
0e17671f James Lyon2013-04-19 15:33:16 +0100844#endif
23f73e92 James Lyon2013-04-19 22:55:09 +0100845 int r2, original_type;
23f73e92 James Lyon2013-04-19 22:55:09 +0100846 original_type = vtop->type.t;
0d1ed741 grischka2009-05-05 20:18:10 +0200847 /* two register type load : expand to two words
848 temporarily */
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +0000849#if !defined(TCC_TARGET_ARM64) && !defined(TCC_TARGET_X86_64)
0d1ed741 grischka2009-05-05 20:18:10 +0200850 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
851 /* load constant */
852 ll = vtop->c.ull;
853 vtop->c.ui = ll; /* first word */
854 load(r, vtop);
855 vtop->r = r; /* save register value */
856 vpushi(ll >> 32); /* second word */
0e17671f
JL
James Lyon2013-04-19 15:33:16 +0100857 } else
858#endif
859 if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
0d1ed741 grischka2009-05-05 20:18:10 +0200860 (vtop->r & VT_LVAL)) {
861 /* We do not want to modifier the long long
862 pointer here, so the safest (and less
863 efficient) is to save all the other registers
864 in the stack. XXX: totally inefficient. */
865 save_regs(1);
866 /* load from memory */
0e17671f James Lyon2013-04-19 15:33:16 +0100867 vtop->type.t = load_type;
0d1ed741 grischka2009-05-05 20:18:10 +0200868 load(r, vtop);
869 vdup();
870 vtop[-1].r = r; /* save register value */
871 /* increment pointer to get second word */
0e17671f James Lyon2013-04-19 15:33:16 +0100872 vtop->type.t = addr_type;
0d1ed741 grischka2009-05-05 20:18:10 +0200873 gaddrof();
0e17671f James Lyon2013-04-19 15:33:16 +0100874 vpushi(load_size);
0d1ed741 grischka2009-05-05 20:18:10 +0200875 gen_op('+');
876 vtop->r |= VT_LVAL;
0e17671f James Lyon2013-04-19 15:33:16 +0100877 vtop->type.t = load_type;
0d1ed741 grischka2009-05-05 20:18:10 +0200878 } else {
879 /* move registers */
880 load(r, vtop);
881 vdup();
882 vtop[-1].r = r; /* save register value */
883 vtop->r = vtop[-1].r2;
884 }
d1694f7d
TP
Thomas Preud'homme2012-07-11 23:39:05 +0200885 /* Allocate second register. Here we rely on the fact that
886 get_reg() tries first to free r2 of an SValue. */
0d1ed741 grischka2009-05-05 20:18:10 +0200887 r2 = get_reg(rc2);
888 load(r2, vtop);
889 vpop();
890 /* write second register */
891 vtop->r2 = r2;
23f73e92 James Lyon2013-04-19 22:55:09 +0100892 vtop->type.t = original_type;
0e17671f James Lyon2013-04-19 15:33:16 +0100893 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
0d1ed741 grischka2009-05-05 20:18:10 +0200894 int t1, t;
895 /* lvalue of scalar type : need to use lvalue type
896 because of possible cast */
897 t = vtop->type.t;
898 t1 = t;
899 /* compute memory access type */
5c35ba66 James Lyon2013-04-24 02:19:15 +0100900 if (vtop->r & VT_REF)
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +0000901#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
5c35ba66
JL
James Lyon2013-04-24 02:19:15 +0100902 t = VT_PTR;
903#else
904 t = VT_INT;
905#endif
906 else if (vtop->r & VT_LVAL_BYTE)
0d1ed741 grischka2009-05-05 20:18:10 +0200907 t = VT_BYTE;
908 else if (vtop->r & VT_LVAL_SHORT)
909 t = VT_SHORT;
910 if (vtop->r & VT_LVAL_UNSIGNED)
911 t |= VT_UNSIGNED;
912 vtop->type.t = t;
913 load(r, vtop);
914 /* restore wanted type */
915 vtop->type.t = t1;
916 } else {
917 /* one register type load */
918 load(r, vtop);
919 }
920 }
921 vtop->r = r;
922#ifdef TCC_TARGET_C67
923 /* uses register pairs for doubles */
924 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
925 vtop->r2 = r+1;
926#endif
927 }
928 return r;
929}
930
931/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
88a3ccab grischka2009-12-20 01:53:49 +0100932ST_FUNC void gv2(int rc1, int rc2)
0d1ed741 grischka2009-05-05 20:18:10 +0200933{
934 int v;
935
936 /* generate more generic register first. But VT_JMP or VT_CMP
937 values must be generated first in all cases to avoid possible
938 reload errors */
939 v = vtop[0].r & VT_VALMASK;
940 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
941 vswap();
942 gv(rc1);
943 vswap();
944 gv(rc2);
945 /* test if reload is needed for first register */
946 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
947 vswap();
948 gv(rc1);
949 vswap();
950 }
951 } else {
952 gv(rc2);
953 vswap();
954 gv(rc1);
955 vswap();
956 /* test if reload is needed for first register */
957 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
958 gv(rc2);
959 }
960 }
961}
962
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +0000963#ifndef TCC_TARGET_ARM64
0d1ed741 grischka2009-05-05 20:18:10 +0200964/* wrapper around RC_FRET to return a register by type */
88a3ccab grischka2009-12-20 01:53:49 +0100965static int rc_fret(int t)
0d1ed741 grischka2009-05-05 20:18:10 +0200966{
967#ifdef TCC_TARGET_X86_64
968 if (t == VT_LDOUBLE) {
969 return RC_ST0;
970 }
971#endif
972 return RC_FRET;
973}
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +0000974#endif
0d1ed741 grischka2009-05-05 20:18:10 +0200975
976/* wrapper around REG_FRET to return a register by type */
88a3ccab grischka2009-12-20 01:53:49 +0100977static int reg_fret(int t)
0d1ed741 grischka2009-05-05 20:18:10 +0200978{
979#ifdef TCC_TARGET_X86_64
980 if (t == VT_LDOUBLE) {
981 return TREG_ST0;
982 }
983#endif
984 return REG_FRET;
985}
986
987/* expand long long on stack in two int registers */
88a3ccab grischka2009-12-20 01:53:49 +0100988static void lexpand(void)
0d1ed741 grischka2009-05-05 20:18:10 +0200989{
990 int u;
991
b0b5165d Thomas Preud'homme2014-02-06 20:51:47 +0800992 u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED);
0d1ed741 grischka2009-05-05 20:18:10 +0200993 gv(RC_INT);
994 vdup();
995 vtop[0].r = vtop[-1].r2;
996 vtop[0].r2 = VT_CONST;
997 vtop[-1].r2 = VT_CONST;
998 vtop[0].type.t = VT_INT | u;
999 vtop[-1].type.t = VT_INT | u;
1000}
1001
1002#ifdef TCC_TARGET_ARM
1003/* expand long long on stack */
88a3ccab grischka2009-12-20 01:53:49 +01001004ST_FUNC void lexpand_nr(void)
0d1ed741 grischka2009-05-05 20:18:10 +02001005{
1006 int u,v;
1007
b0b5165d Thomas Preud'homme2014-02-06 20:51:47 +08001008 u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED);
0d1ed741 grischka2009-05-05 20:18:10 +02001009 vdup();
1010 vtop->r2 = VT_CONST;
1011 vtop->type.t = VT_INT | u;
1012 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
1013 if (v == VT_CONST) {
1014 vtop[-1].c.ui = vtop->c.ull;
1015 vtop->c.ui = vtop->c.ull >> 32;
1016 vtop->r = VT_CONST;
1017 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
1018 vtop->c.ui += 4;
1019 vtop->r = vtop[-1].r;
1020 } else if (v > VT_CONST) {
1021 vtop--;
1022 lexpand();
1023 } else
1024 vtop->r = vtop[-1].r2;
1025 vtop[-1].r2 = VT_CONST;
1026 vtop[-1].type.t = VT_INT | u;
1027}
1028#endif
1029
1030/* build a long long from two ints */
88a3ccab grischka2009-12-20 01:53:49 +01001031static void lbuild(int t)
0d1ed741 grischka2009-05-05 20:18:10 +02001032{
1033 gv2(RC_INT, RC_INT);
1034 vtop[-1].r2 = vtop[0].r;
1035 vtop[-1].type.t = t;
1036 vpop();
1037}
1038
1039/* rotate n first stack elements to the bottom
1040 I1 ... In -> I2 ... In I1 [top is right]
1041*/
bfb00494 Thomas Preud'homme2012-03-14 15:39:16 +01001042ST_FUNC void vrotb(int n)
0d1ed741 grischka2009-05-05 20:18:10 +02001043{
1044 int i;
1045 SValue tmp;
1046
1047 tmp = vtop[-n + 1];
1048 for(i=-n+1;i!=0;i++)
1049 vtop[i] = vtop[i+1];
1050 vtop[0] = tmp;
1051}
1052
7f6095bf
TP
Thomas Preud'homme2011-12-10 07:22:09 +01001053/* rotate the n elements before entry e towards the top
1054 I1 ... In ... -> In I1 ... I(n-1) ... [top is right]
0d1ed741 grischka2009-05-05 20:18:10 +02001055 */
7f6095bf Thomas Preud'homme2011-12-10 07:22:09 +01001056ST_FUNC void vrote(SValue *e, int n)
0d1ed741 grischka2009-05-05 20:18:10 +02001057{
1058 int i;
1059 SValue tmp;
1060
7f6095bf Thomas Preud'homme2011-12-10 07:22:09 +01001061 tmp = *e;
0d1ed741 grischka2009-05-05 20:18:10 +02001062 for(i = 0;i < n - 1; i++)
7f6095bf
TP
Thomas Preud'homme2011-12-10 07:22:09 +01001063 e[-i] = e[-i - 1];
1064 e[-n + 1] = tmp;
1065}
1066
1067/* rotate n first stack elements to the top
1068 I1 ... In -> In I1 ... I(n-1) [top is right]
1069 */
1070ST_FUNC void vrott(int n)
1071{
1072 vrote(vtop, n);
0d1ed741 grischka2009-05-05 20:18:10 +02001073}
1074
0d1ed741 grischka2009-05-05 20:18:10 +02001075/* pop stack value */
88a3ccab grischka2009-12-20 01:53:49 +01001076ST_FUNC void vpop(void)
0d1ed741 grischka2009-05-05 20:18:10 +02001077{
1078 int v;
1079 v = vtop->r & VT_VALMASK;
1080#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1081 /* for x86, we need to pop the FP stack */
1082 if (v == TREG_ST0 && !nocode_wanted) {
c3701df1 Soloist Deng2009-06-08 19:26:19 +02001083 o(0xd8dd); /* fstp %st(0) */
0d1ed741 grischka2009-05-05 20:18:10 +02001084 } else
1085#endif
1086 if (v == VT_JMP || v == VT_JMPI) {
1087 /* need to put correct jump if && or || without test */
1088 gsym(vtop->c.ul);
1089 }
1090 vtop--;
1091}
1092
1093/* convert stack entry to register and duplicate its value in another
1094 register */
88a3ccab grischka2009-12-20 01:53:49 +01001095static void gv_dup(void)
0d1ed741 grischka2009-05-05 20:18:10 +02001096{
1097 int rc, t, r, r1;
1098 SValue sv;
1099
1100 t = vtop->type.t;
1101 if ((t & VT_BTYPE) == VT_LLONG) {
1102 lexpand();
1103 gv_dup();
1104 vswap();
1105 vrotb(3);
1106 gv_dup();
1107 vrotb(4);
1108 /* stack: H L L1 H1 */
1109 lbuild(t);
1110 vrotb(3);
1111 vrotb(3);
1112 vswap();
1113 lbuild(t);
1114 vswap();
1115 } else {
1116 /* duplicate value */
1117 rc = RC_INT;
1118 sv.type.t = VT_INT;
1119 if (is_float(t)) {
1120 rc = RC_FLOAT;
1121#ifdef TCC_TARGET_X86_64
1122 if ((t & VT_BTYPE) == VT_LDOUBLE) {
1123 rc = RC_ST0;
1124 }
1125#endif
1126 sv.type.t = t;
1127 }
1128 r = gv(rc);
1129 r1 = get_reg(rc);
1130 sv.r = r;
1131 sv.c.ul = 0;
1132 load(r1, &sv); /* move r to r1 */
1133 vdup();
1134 /* duplicates value */
c3701df1
SD
Soloist Deng2009-06-08 19:26:19 +02001135 if (r != r1)
1136 vtop->r = r1;
0d1ed741 grischka2009-05-05 20:18:10 +02001137 }
1138}
1139
eda2c756
TP
Thomas Preud'homme2013-12-31 23:51:20 +08001140/* Generate value test
1141 *
1142 * Generate a test for any value (jump, comparison and integers) */
822f4630 Urs Janssen2014-04-10 11:53:54 +02001143ST_FUNC int gvtst(int inv, int t)
eda2c756
TP
Thomas Preud'homme2013-12-31 23:51:20 +08001144{
1145 int v = vtop->r & VT_VALMASK;
1146 if (v != VT_CMP && v != VT_JMP && v != VT_JMPI) {
1147 vpushi(0);
1148 gen_op(TOK_NE);
1149 }
1150 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1151 /* constant jmp optimization */
1152 if ((vtop->c.i != 0) != inv)
1153 t = gjmp(t);
1154 vtop--;
1155 return t;
1156 }
1157 return gtst(inv, t);
1158}
1159
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +00001160#if !defined(TCC_TARGET_ARM64) && !defined(TCC_TARGET_X86_64)
0d1ed741 grischka2009-05-05 20:18:10 +02001161/* generate CPU independent (unsigned) long long operations */
88a3ccab grischka2009-12-20 01:53:49 +01001162static void gen_opl(int op)
0d1ed741 grischka2009-05-05 20:18:10 +02001163{
1164 int t, a, b, op1, c, i;
1165 int func;
1166 unsigned short reg_iret = REG_IRET;
1167 unsigned short reg_lret = REG_LRET;
1168 SValue tmp;
1169
1170 switch(op) {
1171 case '/':
1172 case TOK_PDIV:
1173 func = TOK___divdi3;
1174 goto gen_func;
1175 case TOK_UDIV:
1176 func = TOK___udivdi3;
1177 goto gen_func;
1178 case '%':
1179 func = TOK___moddi3;
1180 goto gen_mod_func;
1181 case TOK_UMOD:
1182 func = TOK___umoddi3;
1183 gen_mod_func:
1184#ifdef TCC_ARM_EABI
1185 reg_iret = TREG_R2;
1186 reg_lret = TREG_R3;
1187#endif
1188 gen_func:
1189 /* call generic long long function */
1190 vpush_global_sym(&func_old_type, func);
1191 vrott(3);
1192 gfunc_call(2);
1193 vpushi(0);
1194 vtop->r = reg_iret;
1195 vtop->r2 = reg_lret;
1196 break;
1197 case '^':
1198 case '&':
1199 case '|':
1200 case '*':
1201 case '+':
1202 case '-':
1203 t = vtop->type.t;
1204 vswap();
1205 lexpand();
1206 vrotb(3);
1207 lexpand();
1208 /* stack: L1 H1 L2 H2 */
1209 tmp = vtop[0];
1210 vtop[0] = vtop[-3];
1211 vtop[-3] = tmp;
1212 tmp = vtop[-2];
1213 vtop[-2] = vtop[-3];
1214 vtop[-3] = tmp;
1215 vswap();
1216 /* stack: H1 H2 L1 L2 */
1217 if (op == '*') {
1218 vpushv(vtop - 1);
1219 vpushv(vtop - 1);
1220 gen_op(TOK_UMULL);
1221 lexpand();
1222 /* stack: H1 H2 L1 L2 ML MH */
1223 for(i=0;i<4;i++)
1224 vrotb(6);
1225 /* stack: ML MH H1 H2 L1 L2 */
1226 tmp = vtop[0];
1227 vtop[0] = vtop[-2];
1228 vtop[-2] = tmp;
1229 /* stack: ML MH H1 L2 H2 L1 */
1230 gen_op('*');
1231 vrotb(3);
1232 vrotb(3);
1233 gen_op('*');
1234 /* stack: ML MH M1 M2 */
1235 gen_op('+');
1236 gen_op('+');
1237 } else if (op == '+' || op == '-') {
1238 /* XXX: add non carry method too (for MIPS or alpha) */
1239 if (op == '+')
1240 op1 = TOK_ADDC1;
1241 else
1242 op1 = TOK_SUBC1;
1243 gen_op(op1);
1244 /* stack: H1 H2 (L1 op L2) */
1245 vrotb(3);
1246 vrotb(3);
1247 gen_op(op1 + 1); /* TOK_xxxC2 */
1248 } else {
1249 gen_op(op);
1250 /* stack: H1 H2 (L1 op L2) */
1251 vrotb(3);
1252 vrotb(3);
1253 /* stack: (L1 op L2) H1 H2 */
1254 gen_op(op);
1255 /* stack: (L1 op L2) (H1 op H2) */
1256 }
1257 /* stack: L H */
1258 lbuild(t);
1259 break;
1260 case TOK_SAR:
1261 case TOK_SHR:
1262 case TOK_SHL:
1263 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
1264 t = vtop[-1].type.t;
1265 vswap();
1266 lexpand();
1267 vrotb(3);
1268 /* stack: L H shift */
1269 c = (int)vtop->c.i;
1270 /* constant: simpler */
1271 /* NOTE: all comments are for SHL. the other cases are
1272 done by swaping words */
1273 vpop();
1274 if (op != TOK_SHL)
1275 vswap();
1276 if (c >= 32) {
1277 /* stack: L H */
1278 vpop();
1279 if (c > 32) {
1280 vpushi(c - 32);
1281 gen_op(op);
1282 }
1283 if (op != TOK_SAR) {
1284 vpushi(0);
1285 } else {
1286 gv_dup();
1287 vpushi(31);
1288 gen_op(TOK_SAR);
1289 }
1290 vswap();
1291 } else {
1292 vswap();
1293 gv_dup();
1294 /* stack: H L L */
1295 vpushi(c);
1296 gen_op(op);
1297 vswap();
1298 vpushi(32 - c);
1299 if (op == TOK_SHL)
1300 gen_op(TOK_SHR);
1301 else
1302 gen_op(TOK_SHL);
1303 vrotb(3);
1304 /* stack: L L H */
1305 vpushi(c);
1306 if (op == TOK_SHL)
1307 gen_op(TOK_SHL);
1308 else
1309 gen_op(TOK_SHR);
1310 gen_op('|');
1311 }
1312 if (op != TOK_SHL)
1313 vswap();
1314 lbuild(t);
1315 } else {
1316 /* XXX: should provide a faster fallback on x86 ? */
1317 switch(op) {
1318 case TOK_SAR:
1319 func = TOK___ashrdi3;
1320 goto gen_func;
1321 case TOK_SHR:
1322 func = TOK___lshrdi3;
1323 goto gen_func;
1324 case TOK_SHL:
1325 func = TOK___ashldi3;
1326 goto gen_func;
1327 }
1328 }
1329 break;
1330 default:
1331 /* compare operations */
1332 t = vtop->type.t;
1333 vswap();
1334 lexpand();
1335 vrotb(3);
1336 lexpand();
1337 /* stack: L1 H1 L2 H2 */
1338 tmp = vtop[-1];
1339 vtop[-1] = vtop[-2];
1340 vtop[-2] = tmp;
1341 /* stack: L1 L2 H1 H2 */
1342 /* compare high */
1343 op1 = op;
1344 /* when values are equal, we need to compare low words. since
1345 the jump is inverted, we invert the test too. */
1346 if (op1 == TOK_LT)
1347 op1 = TOK_LE;
1348 else if (op1 == TOK_GT)
1349 op1 = TOK_GE;
1350 else if (op1 == TOK_ULT)
1351 op1 = TOK_ULE;
1352 else if (op1 == TOK_UGT)
1353 op1 = TOK_UGE;
1354 a = 0;
1355 b = 0;
1356 gen_op(op1);
1357 if (op1 != TOK_NE) {
eda2c756 Thomas Preud'homme2013-12-31 23:51:20 +08001358 a = gvtst(1, 0);
0d1ed741 grischka2009-05-05 20:18:10 +02001359 }
1360 if (op != TOK_EQ) {
1361 /* generate non equal test */
1362 /* XXX: NOT PORTABLE yet */
1363 if (a == 0) {
eda2c756 Thomas Preud'homme2013-12-31 23:51:20 +08001364 b = gvtst(0, 0);
0d1ed741 grischka2009-05-05 20:18:10 +02001365 } else {
1366#if defined(TCC_TARGET_I386)
1367 b = psym(0x850f, 0);
1368#elif defined(TCC_TARGET_ARM)
1369 b = ind;
1370 o(0x1A000000 | encbranch(ind, 0, 1));
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +00001371#elif defined(TCC_TARGET_C67) || defined(TCC_TARGET_ARM64)
bf374a5f grischka2011-08-11 17:07:56 +02001372 tcc_error("not implemented");
0d1ed741 grischka2009-05-05 20:18:10 +02001373#else
1374#error not supported
1375#endif
1376 }
1377 }
1378 /* compare low. Always unsigned */
1379 op1 = op;
1380 if (op1 == TOK_LT)
1381 op1 = TOK_ULT;
1382 else if (op1 == TOK_LE)
1383 op1 = TOK_ULE;
1384 else if (op1 == TOK_GT)
1385 op1 = TOK_UGT;
1386 else if (op1 == TOK_GE)
1387 op1 = TOK_UGE;
1388 gen_op(op1);
eda2c756 Thomas Preud'homme2013-12-31 23:51:20 +08001389 a = gvtst(1, a);
0d1ed741 grischka2009-05-05 20:18:10 +02001390 gsym(b);
1391 vseti(VT_JMPI, a);
1392 break;
1393 }
1394}
1395#endif
1396
1397/* handle integer constant optimizations and various machine
1398 independent opt */
88a3ccab grischka2009-12-20 01:53:49 +01001399static void gen_opic(int op)
0d1ed741 grischka2009-05-05 20:18:10 +02001400{
1401 int c1, c2, t1, t2, n;
1402 SValue *v1, *v2;
1403 long long l1, l2;
1404 typedef unsigned long long U;
1405
1406 v1 = vtop - 1;
1407 v2 = vtop;
1408 t1 = v1->type.t & VT_BTYPE;
1409 t2 = v2->type.t & VT_BTYPE;
1410
1411 if (t1 == VT_LLONG)
1412 l1 = v1->c.ll;
1413 else if (v1->type.t & VT_UNSIGNED)
1414 l1 = v1->c.ui;
1415 else
1416 l1 = v1->c.i;
1417
1418 if (t2 == VT_LLONG)
1419 l2 = v2->c.ll;
1420 else if (v2->type.t & VT_UNSIGNED)
1421 l2 = v2->c.ui;
1422 else
1423 l2 = v2->c.i;
1424
1425 /* currently, we cannot do computations with forward symbols */
1426 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
1427 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
1428 if (c1 && c2) {
1429 switch(op) {
1430 case '+': l1 += l2; break;
1431 case '-': l1 -= l2; break;
1432 case '&': l1 &= l2; break;
1433 case '^': l1 ^= l2; break;
1434 case '|': l1 |= l2; break;
1435 case '*': l1 *= l2; break;
1436
1437 case TOK_PDIV:
1438 case '/':
1439 case '%':
1440 case TOK_UDIV:
1441 case TOK_UMOD:
1442 /* if division by zero, generate explicit division */
1443 if (l2 == 0) {
1444 if (const_wanted)
bf374a5f grischka2011-08-11 17:07:56 +02001445 tcc_error("division by zero in constant");
0d1ed741 grischka2009-05-05 20:18:10 +02001446 goto general_case;
1447 }
1448 switch(op) {
1449 default: l1 /= l2; break;
1450 case '%': l1 %= l2; break;
1451 case TOK_UDIV: l1 = (U)l1 / l2; break;
1452 case TOK_UMOD: l1 = (U)l1 % l2; break;
1453 }
1454 break;
1455 case TOK_SHL: l1 <<= l2; break;
1456 case TOK_SHR: l1 = (U)l1 >> l2; break;
1457 case TOK_SAR: l1 >>= l2; break;
1458 /* tests */
1459 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
1460 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
1461 case TOK_EQ: l1 = l1 == l2; break;
1462 case TOK_NE: l1 = l1 != l2; break;
1463 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
1464 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
1465 case TOK_LT: l1 = l1 < l2; break;
1466 case TOK_GE: l1 = l1 >= l2; break;
1467 case TOK_LE: l1 = l1 <= l2; break;
1468 case TOK_GT: l1 = l1 > l2; break;
1469 /* logical */
1470 case TOK_LAND: l1 = l1 && l2; break;
1471 case TOK_LOR: l1 = l1 || l2; break;
1472 default:
1473 goto general_case;
1474 }
1475 v1->c.ll = l1;
1476 vtop--;
1477 } else {
1478 /* if commutative ops, put c2 as constant */
1479 if (c1 && (op == '+' || op == '&' || op == '^' ||
1480 op == '|' || op == '*')) {
1481 vswap();
1482 c2 = c1; //c = c1, c1 = c2, c2 = c;
1483 l2 = l1; //l = l1, l1 = l2, l2 = l;
1484 }
ac70e6b8
EGE
Edmund Grimley Evans2015-03-07 11:25:27 +00001485 if (!const_wanted &&
1486 c1 && ((l1 == 0 &&
1487 (op == TOK_SHL || op == TOK_SHR || op == TOK_SAR)) ||
1488 (l1 == -1 && op == TOK_SAR))) {
1489 /* treat (0 << x), (0 >> x) and (-1 >> x) as constant */
1490 vtop--;
1491 } else if (!const_wanted &&
1492 c2 && ((l2 == 0 && (op == '&' || op == '*')) ||
1493 (l2 == -1 && op == '|') ||
1494 (l2 == 0xffffffff && t2 != VT_LLONG && op == '|') ||
1495 (l2 == 1 && (op == '%' || op == TOK_UMOD)))) {
1496 /* treat (x & 0), (x * 0), (x | -1) and (x % 1) as constant */
1497 if (l2 == 1)
1498 vtop->c.ll = 0;
1499 vswap();
1500 vtop--;
1501 } else if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
1502 op == TOK_PDIV) &&
1503 l2 == 1) ||
1504 ((op == '+' || op == '-' || op == '|' || op == '^' ||
1505 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
1506 l2 == 0) ||
1507 (op == '&' &&
1508 l2 == -1))) {
1509 /* filter out NOP operations like x*1, x-0, x&-1... */
0d1ed741 grischka2009-05-05 20:18:10 +02001510 vtop--;
1511 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
1512 /* try to use shifts instead of muls or divs */
1513 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
1514 n = -1;
1515 while (l2) {
1516 l2 >>= 1;
1517 n++;
1518 }
1519 vtop->c.ll = n;
1520 if (op == '*')
1521 op = TOK_SHL;
1522 else if (op == TOK_PDIV)
1523 op = TOK_SAR;
1524 else
1525 op = TOK_SHR;
1526 }
1527 goto general_case;
1528 } else if (c2 && (op == '+' || op == '-') &&
2341ee51 grischka2010-01-14 20:55:51 +01001529 (((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM))
1530 || (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
0d1ed741 grischka2009-05-05 20:18:10 +02001531 /* symbol + constant case */
1532 if (op == '-')
1533 l2 = -l2;
1534 vtop--;
1535 vtop->c.ll += l2;
1536 } else {
1537 general_case:
1538 if (!nocode_wanted) {
1539 /* call low level op generator */
b14ef0e2
EGE
Edmund Grimley Evans2015-02-13 18:58:31 +00001540 if (t1 == VT_LLONG || t2 == VT_LLONG ||
1541 (PTR_SIZE == 8 && (t1 == VT_PTR || t2 == VT_PTR)))
0d1ed741 grischka2009-05-05 20:18:10 +02001542 gen_opl(op);
1543 else
1544 gen_opi(op);
1545 } else {
1546 vtop--;
1547 }
1548 }
1549 }
1550}
1551
1552/* generate a floating point operation with constant propagation */
88a3ccab grischka2009-12-20 01:53:49 +01001553static void gen_opif(int op)
0d1ed741 grischka2009-05-05 20:18:10 +02001554{
1555 int c1, c2;
1556 SValue *v1, *v2;
1557 long double f1, f2;
1558
1559 v1 = vtop - 1;
1560 v2 = vtop;
1561 /* currently, we cannot do computations with forward symbols */
1562 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
1563 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
1564 if (c1 && c2) {
1565 if (v1->type.t == VT_FLOAT) {
1566 f1 = v1->c.f;
1567 f2 = v2->c.f;
1568 } else if (v1->type.t == VT_DOUBLE) {
1569 f1 = v1->c.d;
1570 f2 = v2->c.d;
1571 } else {
1572 f1 = v1->c.ld;
1573 f2 = v2->c.ld;
1574 }
1575
1576 /* NOTE: we only do constant propagation if finite number (not
1577 NaN or infinity) (ANSI spec) */
1578 if (!ieee_finite(f1) || !ieee_finite(f2))
1579 goto general_case;
1580
1581 switch(op) {
1582 case '+': f1 += f2; break;
1583 case '-': f1 -= f2; break;
1584 case '*': f1 *= f2; break;
1585 case '/':
1586 if (f2 == 0.0) {
1587 if (const_wanted)
bf374a5f grischka2011-08-11 17:07:56 +02001588 tcc_error("division by zero in constant");
0d1ed741 grischka2009-05-05 20:18:10 +02001589 goto general_case;
1590 }
1591 f1 /= f2;
1592 break;
1593 /* XXX: also handles tests ? */
1594 default:
1595 goto general_case;
1596 }
1597 /* XXX: overflow test ? */
1598 if (v1->type.t == VT_FLOAT) {
1599 v1->c.f = f1;
1600 } else if (v1->type.t == VT_DOUBLE) {
1601 v1->c.d = f1;
1602 } else {
1603 v1->c.ld = f1;
1604 }
1605 vtop--;
1606 } else {
1607 general_case:
1608 if (!nocode_wanted) {
1609 gen_opf(op);
1610 } else {
1611 vtop--;
1612 }
1613 }
1614}
1615
1616static int pointed_size(CType *type)
1617{
1618 int align;
1619 return type_size(pointed_type(type), &align);
1620}
1621
ace0f7f2
JS
Joe Soroka2011-04-06 09:17:03 -07001622static void vla_runtime_pointed_size(CType *type)
1623{
1624 int align;
1625 vla_runtime_type_size(pointed_type(type), &align);
1626}
1627
0d1ed741 grischka2009-05-05 20:18:10 +02001628static inline int is_null_pointer(SValue *p)
1629{
1630 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
1631 return 0;
1632 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
6471ec0a Michael Matz2012-04-14 23:50:21 +02001633 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0) ||
5879c854 grischka2014-04-04 20:18:39 +02001634 ((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr_offset == 0);
0d1ed741 grischka2009-05-05 20:18:10 +02001635}
1636
1637static inline int is_integer_btype(int bt)
1638{
1639 return (bt == VT_BYTE || bt == VT_SHORT ||
1640 bt == VT_INT || bt == VT_LLONG);
1641}
1642
3e9a7e9d Vincent Lefevre2014-04-07 13:31:00 +02001643/* check types for comparison or subtraction of pointers */
0d1ed741 grischka2009-05-05 20:18:10 +02001644static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
1645{
1646 CType *type1, *type2, tmp_type1, tmp_type2;
1647 int bt1, bt2;
1648
1649 /* null pointers are accepted for all comparisons as gcc */
1650 if (is_null_pointer(p1) || is_null_pointer(p2))
1651 return;
1652 type1 = &p1->type;
1653 type2 = &p2->type;
1654 bt1 = type1->t & VT_BTYPE;
1655 bt2 = type2->t & VT_BTYPE;
1656 /* accept comparison between pointer and integer with a warning */
1657 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
1658 if (op != TOK_LOR && op != TOK_LAND )
bf374a5f grischka2011-08-11 17:07:56 +02001659 tcc_warning("comparison between pointer and integer");
0d1ed741 grischka2009-05-05 20:18:10 +02001660 return;
1661 }
1662
1663 /* both must be pointers or implicit function pointers */
1664 if (bt1 == VT_PTR) {
1665 type1 = pointed_type(type1);
1666 } else if (bt1 != VT_FUNC)
1667 goto invalid_operands;
1668
1669 if (bt2 == VT_PTR) {
1670 type2 = pointed_type(type2);
1671 } else if (bt2 != VT_FUNC) {
1672 invalid_operands:
bf374a5f grischka2011-08-11 17:07:56 +02001673 tcc_error("invalid operands to binary %s", get_tok_str(op, NULL));
0d1ed741 grischka2009-05-05 20:18:10 +02001674 }
1675 if ((type1->t & VT_BTYPE) == VT_VOID ||
1676 (type2->t & VT_BTYPE) == VT_VOID)
1677 return;
1678 tmp_type1 = *type1;
1679 tmp_type2 = *type2;
b0b5165d
TP
Thomas Preud'homme2014-02-06 20:51:47 +08001680 tmp_type1.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
1681 tmp_type2.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
0d1ed741 grischka2009-05-05 20:18:10 +02001682 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
1683 /* gcc-like error if '-' is used */
1684 if (op == '-')
1685 goto invalid_operands;
1686 else
bf374a5f grischka2011-08-11 17:07:56 +02001687 tcc_warning("comparison of distinct pointer types lacks a cast");
0d1ed741 grischka2009-05-05 20:18:10 +02001688 }
1689}
1690
1691/* generic gen_op: handles types problems */
88a3ccab grischka2009-12-20 01:53:49 +01001692ST_FUNC void gen_op(int op)
0d1ed741 grischka2009-05-05 20:18:10 +02001693{
1694 int u, t1, t2, bt1, bt2, t;
1695 CType type1;
1696
1697 t1 = vtop[-1].type.t;
1698 t2 = vtop[0].type.t;
1699 bt1 = t1 & VT_BTYPE;
1700 bt2 = t2 & VT_BTYPE;
1701
1702 if (bt1 == VT_PTR || bt2 == VT_PTR) {
1703 /* at least one operand is a pointer */
1704 /* relationnal op: must be both pointers */
1705 if (op >= TOK_ULT && op <= TOK_LOR) {
1706 check_comparison_pointer_types(vtop - 1, vtop, op);
1707 /* pointers are handled are unsigned */
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +00001708#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
0d1ed741 grischka2009-05-05 20:18:10 +02001709 t = VT_LLONG | VT_UNSIGNED;
1710#else
1711 t = VT_INT | VT_UNSIGNED;
1712#endif
1713 goto std_op;
1714 }
1715 /* if both pointers, then it must be the '-' op */
1716 if (bt1 == VT_PTR && bt2 == VT_PTR) {
1717 if (op != '-')
bf374a5f grischka2011-08-11 17:07:56 +02001718 tcc_error("cannot use pointers here");
0d1ed741 grischka2009-05-05 20:18:10 +02001719 check_comparison_pointer_types(vtop - 1, vtop, op);
1720 /* XXX: check that types are compatible */
ace0f7f2
JS
Joe Soroka2011-04-06 09:17:03 -07001721 if (vtop[-1].type.t & VT_VLA) {
1722 vla_runtime_pointed_size(&vtop[-1].type);
ace0f7f2 Joe Soroka2011-04-06 09:17:03 -07001723 } else {
812781cd Joe Soroka2011-04-11 23:39:27 -07001724 vpushi(pointed_size(&vtop[-1].type));
ace0f7f2 Joe Soroka2011-04-06 09:17:03 -07001725 }
812781cd Joe Soroka2011-04-11 23:39:27 -07001726 vrott(3);
0d1ed741 grischka2009-05-05 20:18:10 +02001727 gen_opic(op);
1728 /* set to integer type */
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +00001729#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
0d1ed741 grischka2009-05-05 20:18:10 +02001730 vtop->type.t = VT_LLONG;
1731#else
1732 vtop->type.t = VT_INT;
1733#endif
812781cd Joe Soroka2011-04-11 23:39:27 -07001734 vswap();
0d1ed741 grischka2009-05-05 20:18:10 +02001735 gen_op(TOK_PDIV);
1736 } else {
1737 /* exactly one pointer : must be '+' or '-'. */
1738 if (op != '-' && op != '+')
bf374a5f grischka2011-08-11 17:07:56 +02001739 tcc_error("cannot use pointers here");
0d1ed741 grischka2009-05-05 20:18:10 +02001740 /* Put pointer as first operand */
1741 if (bt2 == VT_PTR) {
1742 vswap();
1743 swap(&t1, &t2);
1744 }
1745 type1 = vtop[-1].type;
7c7ca3c6 Joe Soroka2011-04-08 01:09:39 -07001746 type1.t &= ~VT_ARRAY;
ace0f7f2
JS
Joe Soroka2011-04-06 09:17:03 -07001747 if (vtop[-1].type.t & VT_VLA)
1748 vla_runtime_pointed_size(&vtop[-1].type);
1749 else {
1750 u = pointed_size(&vtop[-1].type);
1751 if (u < 0)
bf374a5f grischka2011-08-11 17:07:56 +02001752 tcc_error("unknown array element size");
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +00001753#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
ace0f7f2 Joe Soroka2011-04-06 09:17:03 -07001754 vpushll(u);
0d1ed741 grischka2009-05-05 20:18:10 +02001755#else
ace0f7f2
JS
Joe Soroka2011-04-06 09:17:03 -07001756 /* XXX: cast to int ? (long long case) */
1757 vpushi(u);
0d1ed741 grischka2009-05-05 20:18:10 +02001758#endif
ace0f7f2 Joe Soroka2011-04-06 09:17:03 -07001759 }
0d1ed741 grischka2009-05-05 20:18:10 +02001760 gen_op('*');
559675b9 seyko2015-04-10 15:17:22 +03001761#if 0
1762/* #ifdef CONFIG_TCC_BCHECK
1763 The main reason to removing this code:
1764 #include <stdio.h>
1765 int main ()
1766 {
1767 int v[10];
1768 int i = 10;
1769 int j = 9;
1770 fprintf(stderr, "v+i-j = %p\n", v+i-j);
1771 fprintf(stderr, "v+(i-j) = %p\n", v+(i-j));
1772 }
1773 When this code is on. then the output looks like
1774 v+i-j = 0xfffffffe
1775 v+(i-j) = 0xbff84000
1776 */
0d1ed741 grischka2009-05-05 20:18:10 +02001777 /* if evaluating constant expression, no code should be
1778 generated, so no bound check */
f9181416 grischka2009-05-11 18:45:44 +02001779 if (tcc_state->do_bounds_check && !const_wanted) {
0d1ed741 grischka2009-05-05 20:18:10 +02001780 /* if bounded pointers, we generate a special code to
1781 test bounds */
1782 if (op == '-') {
1783 vpushi(0);
1784 vswap();
1785 gen_op('-');
1786 }
1787 gen_bounded_ptr_add();
1788 } else
1789#endif
1790 {
1791 gen_opic(op);
1792 }
1793 /* put again type if gen_opic() swaped operands */
1794 vtop->type = type1;
1795 }
1796 } else if (is_float(bt1) || is_float(bt2)) {
1797 /* compute bigger type and do implicit casts */
1798 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
1799 t = VT_LDOUBLE;
1800 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
1801 t = VT_DOUBLE;
1802 } else {
1803 t = VT_FLOAT;
1804 }
1805 /* floats can only be used for a few operations */
1806 if (op != '+' && op != '-' && op != '*' && op != '/' &&
1807 (op < TOK_ULT || op > TOK_GT))
bf374a5f grischka2011-08-11 17:07:56 +02001808 tcc_error("invalid operands for binary operation");
0d1ed741 grischka2009-05-05 20:18:10 +02001809 goto std_op;
240064c0 Vincent Lefevre2012-06-27 13:31:44 +02001810 } else if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL) {
d27a0b35
VL
Vincent Lefevre2012-07-06 14:22:37 +02001811 t = bt1 == VT_LLONG ? VT_LLONG : VT_INT;
1812 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (t | VT_UNSIGNED))
1813 t |= VT_UNSIGNED;
240064c0 Vincent Lefevre2012-06-27 13:31:44 +02001814 goto std_op;
0d1ed741 grischka2009-05-05 20:18:10 +02001815 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
1816 /* cast to biggest op */
1817 t = VT_LLONG;
1818 /* convert to unsigned if it does not fit in a long long */
1819 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
1820 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
1821 t |= VT_UNSIGNED;
1822 goto std_op;
5eb64357
HM
Hitoshi Mitake2012-11-05 12:26:26 +09001823 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
1824 tcc_error("comparison of struct");
0d1ed741 grischka2009-05-05 20:18:10 +02001825 } else {
1826 /* integer operations */
1827 t = VT_INT;
1828 /* convert to unsigned if it does not fit in an integer */
1829 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
1830 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
1831 t |= VT_UNSIGNED;
1832 std_op:
1833 /* XXX: currently, some unsigned operations are explicit, so
1834 we modify them here */
1835 if (t & VT_UNSIGNED) {
1836 if (op == TOK_SAR)
1837 op = TOK_SHR;
1838 else if (op == '/')
1839 op = TOK_UDIV;
1840 else if (op == '%')
1841 op = TOK_UMOD;
1842 else if (op == TOK_LT)
1843 op = TOK_ULT;
1844 else if (op == TOK_GT)
1845 op = TOK_UGT;
1846 else if (op == TOK_LE)
1847 op = TOK_ULE;
1848 else if (op == TOK_GE)
1849 op = TOK_UGE;
1850 }
1851 vswap();
1852 type1.t = t;
1853 gen_cast(&type1);
1854 vswap();
1855 /* special case for shifts and long long: we keep the shift as
1856 an integer */
1857 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
1858 type1.t = VT_INT;
1859 gen_cast(&type1);
1860 if (is_float(t))
1861 gen_opif(op);
1862 else
1863 gen_opic(op);
1864 if (op >= TOK_ULT && op <= TOK_GT) {
1865 /* relationnal op: the result is an int */
1866 vtop->type.t = VT_INT;
1867 } else {
1868 vtop->type.t = t;
1869 }
1870 }
40f7e11c Edmund Grimley Evans2015-02-20 22:18:41 +00001871 // Make sure that we have converted to an rvalue:
5bcc3eed Thomas Preud'homme2015-03-10 23:23:00 +08001872 if (vtop->r & VT_LVAL && !nocode_wanted)
40f7e11c Edmund Grimley Evans2015-02-20 22:18:41 +00001873 gv(is_float(vtop->type.t & VT_BTYPE) ? RC_FLOAT : RC_INT);
0d1ed741 grischka2009-05-05 20:18:10 +02001874}
1875
1876#ifndef TCC_TARGET_ARM
1877/* generic itof for unsigned long long case */
88a3ccab grischka2009-12-20 01:53:49 +01001878static void gen_cvt_itof1(int t)
0d1ed741 grischka2009-05-05 20:18:10 +02001879{
b14ef0e2
EGE
Edmund Grimley Evans2015-02-13 18:58:31 +00001880#ifdef TCC_TARGET_ARM64
1881 gen_cvt_itof(t);
1882#else
0d1ed741 grischka2009-05-05 20:18:10 +02001883 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
1884 (VT_LLONG | VT_UNSIGNED)) {
1885
1886 if (t == VT_FLOAT)
1887 vpush_global_sym(&func_old_type, TOK___floatundisf);
1888#if LDOUBLE_SIZE != 8
1889 else if (t == VT_LDOUBLE)
1890 vpush_global_sym(&func_old_type, TOK___floatundixf);
1891#endif
1892 else
1893 vpush_global_sym(&func_old_type, TOK___floatundidf);
1894 vrott(2);
1895 gfunc_call(1);
1896 vpushi(0);
1897 vtop->r = reg_fret(t);
1898 } else {
1899 gen_cvt_itof(t);
1900 }
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +00001901#endif
0d1ed741 grischka2009-05-05 20:18:10 +02001902}
1903#endif
1904
1905/* generic ftoi for unsigned long long case */
88a3ccab grischka2009-12-20 01:53:49 +01001906static void gen_cvt_ftoi1(int t)
0d1ed741 grischka2009-05-05 20:18:10 +02001907{
b14ef0e2
EGE
Edmund Grimley Evans2015-02-13 18:58:31 +00001908#ifdef TCC_TARGET_ARM64
1909 gen_cvt_ftoi(t);
1910#else
0d1ed741 grischka2009-05-05 20:18:10 +02001911 int st;
1912
1913 if (t == (VT_LLONG | VT_UNSIGNED)) {
1914 /* not handled natively */
1915 st = vtop->type.t & VT_BTYPE;
1916 if (st == VT_FLOAT)
1917 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
1918#if LDOUBLE_SIZE != 8
1919 else if (st == VT_LDOUBLE)
1920 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
1921#endif
1922 else
1923 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
1924 vrott(2);
1925 gfunc_call(1);
1926 vpushi(0);
1927 vtop->r = REG_IRET;
1928 vtop->r2 = REG_LRET;
1929 } else {
1930 gen_cvt_ftoi(t);
1931 }
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +00001932#endif
0d1ed741 grischka2009-05-05 20:18:10 +02001933}
1934
1935/* force char or short cast */
88a3ccab grischka2009-12-20 01:53:49 +01001936static void force_charshort_cast(int t)
0d1ed741 grischka2009-05-05 20:18:10 +02001937{
1938 int bits, dbt;
1939 dbt = t & VT_BTYPE;
1940 /* XXX: add optimization if lvalue : just change type and offset */
1941 if (dbt == VT_BYTE)
1942 bits = 8;
1943 else
1944 bits = 16;
1945 if (t & VT_UNSIGNED) {
1946 vpushi((1 << bits) - 1);
1947 gen_op('&');
1948 } else {
1949 bits = 32 - bits;
1950 vpushi(bits);
1951 gen_op(TOK_SHL);
1952 /* result must be signed or the SAR is converted to an SHL
1953 This was not the case when "t" was a signed short
1954 and the last value on the stack was an unsigned int */
1955 vtop->type.t &= ~VT_UNSIGNED;
1956 vpushi(bits);
1957 gen_op(TOK_SAR);
1958 }
1959}
1960
1961/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
1962static void gen_cast(CType *type)
1963{
1964 int sbt, dbt, sf, df, c, p;
1965
1966 /* special delayed cast for char/short */
1967 /* XXX: in some cases (multiple cascaded casts), it may still
1968 be incorrect */
1969 if (vtop->r & VT_MUSTCAST) {
1970 vtop->r &= ~VT_MUSTCAST;
1971 force_charshort_cast(vtop->type.t);
1972 }
1973
1974 /* bitfields first get cast to ints */
5bcc3eed Thomas Preud'homme2015-03-10 23:23:00 +08001975 if (vtop->type.t & VT_BITFIELD && !nocode_wanted) {
0d1ed741 grischka2009-05-05 20:18:10 +02001976 gv(RC_INT);
1977 }
1978
1979 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
1980 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
1981
1982 if (sbt != dbt) {
1983 sf = is_float(sbt);
1984 df = is_float(dbt);
1985 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
1986 p = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM);
1987 if (c) {
1988 /* constant case: we can do it now */
1989 /* XXX: in ISOC, cannot do it if error in convert */
1990 if (sbt == VT_FLOAT)
1991 vtop->c.ld = vtop->c.f;
1992 else if (sbt == VT_DOUBLE)
1993 vtop->c.ld = vtop->c.d;
1994
1995 if (df) {
1996 if ((sbt & VT_BTYPE) == VT_LLONG) {
1997 if (sbt & VT_UNSIGNED)
1998 vtop->c.ld = vtop->c.ull;
1999 else
2000 vtop->c.ld = vtop->c.ll;
2001 } else if(!sf) {
2002 if (sbt & VT_UNSIGNED)
2003 vtop->c.ld = vtop->c.ui;
2004 else
2005 vtop->c.ld = vtop->c.i;
2006 }
2007
2008 if (dbt == VT_FLOAT)
2009 vtop->c.f = (float)vtop->c.ld;
2010 else if (dbt == VT_DOUBLE)
2011 vtop->c.d = (double)vtop->c.ld;
2012 } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
2013 vtop->c.ull = (unsigned long long)vtop->c.ld;
2014 } else if (sf && dbt == VT_BOOL) {
2015 vtop->c.i = (vtop->c.ld != 0);
2016 } else {
2017 if(sf)
2018 vtop->c.ll = (long long)vtop->c.ld;
2019 else if (sbt == (VT_LLONG|VT_UNSIGNED))
2020 vtop->c.ll = vtop->c.ull;
2021 else if (sbt & VT_UNSIGNED)
2022 vtop->c.ll = vtop->c.ui;
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +00002023#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
614790dc
CJ
Christian Jullien2009-12-15 17:45:15 +01002024 else if (sbt == VT_PTR)
2025 ;
2026#endif
0d1ed741 grischka2009-05-05 20:18:10 +02002027 else if (sbt != VT_LLONG)
2028 vtop->c.ll = vtop->c.i;
2029
2030 if (dbt == (VT_LLONG|VT_UNSIGNED))
2031 vtop->c.ull = vtop->c.ll;
2032 else if (dbt == VT_BOOL)
2033 vtop->c.i = (vtop->c.ll != 0);
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +00002034#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
9e11476e
MM
Michael Matz2014-01-11 23:42:58 +01002035 else if (dbt == VT_PTR)
2036 ;
2037#endif
0d1ed741 grischka2009-05-05 20:18:10 +02002038 else if (dbt != VT_LLONG) {
2039 int s = 0;
2040 if ((dbt & VT_BTYPE) == VT_BYTE)
2041 s = 24;
2042 else if ((dbt & VT_BTYPE) == VT_SHORT)
2043 s = 16;
0d1ed741 grischka2009-05-05 20:18:10 +02002044 if(dbt & VT_UNSIGNED)
2045 vtop->c.ui = ((unsigned int)vtop->c.ll << s) >> s;
2046 else
2047 vtop->c.i = ((int)vtop->c.ll << s) >> s;
2048 }
2049 }
2050 } else if (p && dbt == VT_BOOL) {
2051 vtop->r = VT_CONST;
2052 vtop->c.i = 1;
2053 } else if (!nocode_wanted) {
2054 /* non constant case: generate code */
2055 if (sf && df) {
2056 /* convert from fp to fp */
2057 gen_cvt_ftof(dbt);
2058 } else if (df) {
2059 /* convert int to fp */
2060 gen_cvt_itof1(dbt);
2061 } else if (sf) {
2062 /* convert fp to int */
2063 if (dbt == VT_BOOL) {
2064 vpushi(0);
2065 gen_op(TOK_NE);
2066 } else {
2067 /* we handle char/short/etc... with generic code */
2068 if (dbt != (VT_INT | VT_UNSIGNED) &&
2069 dbt != (VT_LLONG | VT_UNSIGNED) &&
2070 dbt != VT_LLONG)
2071 dbt = VT_INT;
2072 gen_cvt_ftoi1(dbt);
2073 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
2074 /* additional cast for char/short... */
2075 vtop->type.t = dbt;
2076 gen_cast(type);
2077 }
2078 }
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +00002079#if !defined(TCC_TARGET_ARM64) && !defined(TCC_TARGET_X86_64)
0d1ed741 grischka2009-05-05 20:18:10 +02002080 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5bcc3eed Thomas Preud'homme2015-03-10 23:23:00 +08002081 if ((sbt & VT_BTYPE) != VT_LLONG && !nocode_wanted) {
0d1ed741 grischka2009-05-05 20:18:10 +02002082 /* scalar to long long */
2083 /* machine independent conversion */
2084 gv(RC_INT);
2085 /* generate high word */
2086 if (sbt == (VT_INT | VT_UNSIGNED)) {
2087 vpushi(0);
2088 gv(RC_INT);
2089 } else {
2090 if (sbt == VT_PTR) {
2091 /* cast from pointer to int before we apply
2092 shift operation, which pointers don't support*/
2093 gen_cast(&int_type);
2094 }
2095 gv_dup();
2096 vpushi(31);
2097 gen_op(TOK_SAR);
2098 }
2099 /* patch second register */
2100 vtop[-1].r2 = vtop->r;
2101 vpop();
2102 }
2103#else
2104 } else if ((dbt & VT_BTYPE) == VT_LLONG ||
c31dc7aa
SH
Shinichiro Hamaji2010-08-31 08:35:31 +09002105 (dbt & VT_BTYPE) == VT_PTR ||
2106 (dbt & VT_BTYPE) == VT_FUNC) {
2107 if ((sbt & VT_BTYPE) != VT_LLONG &&
2108 (sbt & VT_BTYPE) != VT_PTR &&
5bcc3eed Thomas Preud'homme2015-03-10 23:23:00 +08002109 (sbt & VT_BTYPE) != VT_FUNC && !nocode_wanted) {
c31dc7aa Shinichiro Hamaji2010-08-31 08:35:31 +09002110 /* need to convert from 32bit to 64bit */
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +00002111 gv(RC_INT);
c31dc7aa Shinichiro Hamaji2010-08-31 08:35:31 +09002112 if (sbt != (VT_INT | VT_UNSIGNED)) {
b14ef0e2
EGE
Edmund Grimley Evans2015-02-13 18:58:31 +00002113#if defined(TCC_TARGET_ARM64)
2114 gen_cvt_sxtw();
2115#elif defined(TCC_TARGET_X86_64)
2116 int r = gv(RC_INT);
0d1ed741 grischka2009-05-05 20:18:10 +02002117 /* x86_64 specific: movslq */
2118 o(0x6348);
2119 o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r));
b14ef0e2
EGE
Edmund Grimley Evans2015-02-13 18:58:31 +00002120#else
2121#error
2122#endif
0d1ed741 grischka2009-05-05 20:18:10 +02002123 }
2124 }
2125#endif
2126 } else if (dbt == VT_BOOL) {
2127 /* scalar to bool */
2128 vpushi(0);
2129 gen_op(TOK_NE);
2130 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
2131 (dbt & VT_BTYPE) == VT_SHORT) {
2132 if (sbt == VT_PTR) {
2133 vtop->type.t = VT_INT;
bf374a5f grischka2011-08-11 17:07:56 +02002134 tcc_warning("nonportable conversion from pointer to char/short");
0d1ed741 grischka2009-05-05 20:18:10 +02002135 }
2136 force_charshort_cast(dbt);
2137 } else if ((dbt & VT_BTYPE) == VT_INT) {
2138 /* scalar to int */
5bcc3eed Thomas Preud'homme2015-03-10 23:23:00 +08002139 if (sbt == VT_LLONG && !nocode_wanted) {
0d1ed741 grischka2009-05-05 20:18:10 +02002140 /* from long long: just take low order word */
2141 lexpand();
2142 vpop();
2143 }
2144 /* if lvalue and single word type, nothing to do because
2145 the lvalue already contains the real type size (see
2146 VT_LVAL_xxx constants) */
2147 }
2148 }
2149 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
2150 /* if we are casting between pointer types,
2151 we must update the VT_LVAL_xxx size */
2152 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
2153 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
2154 }
2155 vtop->type = *type;
2156}
2157
ace0f7f2 Joe Soroka2011-04-06 09:17:03 -07002158/* return type size as known at compile time. Put alignment at 'a' */
88a3ccab grischka2009-12-20 01:53:49 +01002159ST_FUNC int type_size(CType *type, int *a)
0d1ed741 grischka2009-05-05 20:18:10 +02002160{
2161 Sym *s;
2162 int bt;
2163
2164 bt = type->t & VT_BTYPE;
2165 if (bt == VT_STRUCT) {
2166 /* struct/union */
2167 s = type->ref;
06a7c415 Joe Soroka2011-03-18 17:47:35 -07002168 *a = s->r;
0d1ed741 grischka2009-05-05 20:18:10 +02002169 return s->c;
2170 } else if (bt == VT_PTR) {
7c7ca3c6 Joe Soroka2011-04-08 01:09:39 -07002171 if (type->t & VT_ARRAY) {
0d1ed741 grischka2009-05-05 20:18:10 +02002172 int ts;
2173
2174 s = type->ref;
2175 ts = type_size(&s->type, a);
2176
2177 if (ts < 0 && s->c < 0)
2178 ts = -ts;
2179
2180 return ts * s->c;
2181 } else {
2182 *a = PTR_SIZE;
2183 return PTR_SIZE;
2184 }
2185 } else if (bt == VT_LDOUBLE) {
2186 *a = LDOUBLE_ALIGN;
2187 return LDOUBLE_SIZE;
2188 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
2189#ifdef TCC_TARGET_I386
2190#ifdef TCC_TARGET_PE
2191 *a = 8;
2192#else
2193 *a = 4;
2194#endif
2195#elif defined(TCC_TARGET_ARM)
2196#ifdef TCC_ARM_EABI
2197 *a = 8;
2198#else
2199 *a = 4;
2200#endif
2201#else
2202 *a = 8;
2203#endif
2204 return 8;
2205 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
2206 *a = 4;
2207 return 4;
2208 } else if (bt == VT_SHORT) {
2209 *a = 2;
2210 return 2;
b961ba53
JL
James Lyon2013-04-19 11:08:12 +01002211 } else if (bt == VT_QLONG || bt == VT_QFLOAT) {
2212 *a = 8;
2213 return 16;
0d1ed741 grischka2009-05-05 20:18:10 +02002214 } else {
2215 /* char, void, function, _Bool */
2216 *a = 1;
2217 return 1;
2218 }
2219}
2220
ace0f7f2
JS
Joe Soroka2011-04-06 09:17:03 -07002221/* push type size as known at runtime time on top of value stack. Put
2222 alignment at 'a' */
2223ST_FUNC void vla_runtime_type_size(CType *type, int *a)
2224{
2225 if (type->t & VT_VLA) {
1446b543 Joe Soroka2011-04-09 22:52:25 -07002226 vset(&int_type, VT_LOCAL|VT_LVAL, type->ref->c);
ace0f7f2 Joe Soroka2011-04-06 09:17:03 -07002227 } else {
1446b543 Joe Soroka2011-04-09 22:52:25 -07002228 vpushi(type_size(type, a));
ace0f7f2
JS
Joe Soroka2011-04-06 09:17:03 -07002229 }
2230}
2231
999274ca seyko2015-05-04 04:09:05 +03002232static void vla_sp_restore(void) {
2233 if (vlas_in_scope) {
2234 gen_vla_sp_restore(vla_sp_loc);
41b3c7a5 James Lyon2013-04-27 20:39:34 +01002235 }
999274ca seyko2015-05-04 04:09:05 +03002236}
2237
2238static void vla_sp_restore_root(void) {
2239 if (vlas_in_scope) {
2240 gen_vla_sp_restore(vla_sp_root_loc);
41b3c7a5
JL
James Lyon2013-04-27 20:39:34 +01002241 }
2242}
2243
0d1ed741 grischka2009-05-05 20:18:10 +02002244/* return the pointed type of t */
2245static inline CType *pointed_type(CType *type)
2246{
2247 return &type->ref->type;
2248}
2249
2250/* modify type so that its it is a pointer to type. */
88a3ccab grischka2009-12-20 01:53:49 +01002251ST_FUNC void mk_pointer(CType *type)
0d1ed741 grischka2009-05-05 20:18:10 +02002252{
2253 Sym *s;
2254 s = sym_push(SYM_FIELD, type, 0, -1);
2255 type->t = VT_PTR | (type->t & ~VT_TYPE);
2256 type->ref = s;
2257}
2258
2259/* compare function types. OLD functions match any new functions */
2260static int is_compatible_func(CType *type1, CType *type2)
2261{
2262 Sym *s1, *s2;
2263
2264 s1 = type1->ref;
2265 s2 = type2->ref;
2266 if (!is_compatible_types(&s1->type, &s2->type))
2267 return 0;
2268 /* check func_call */
3fe2a95d grischka2014-01-07 14:57:07 +01002269 if (s1->a.func_call != s2->a.func_call)
0d1ed741 grischka2009-05-05 20:18:10 +02002270 return 0;
2271 /* XXX: not complete */
2272 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
2273 return 1;
2274 if (s1->c != s2->c)
2275 return 0;
2276 while (s1 != NULL) {
2277 if (s2 == NULL)
2278 return 0;
2279 if (!is_compatible_parameter_types(&s1->type, &s2->type))
2280 return 0;
2281 s1 = s1->next;
2282 s2 = s2->next;
2283 }
2284 if (s2)
2285 return 0;
2286 return 1;
2287}
2288
2289/* return true if type1 and type2 are the same. If unqualified is
2290 true, qualifiers on the types are ignored.
2291
2292 - enums are not checked as gcc __builtin_types_compatible_p ()
2293 */
2294static int compare_types(CType *type1, CType *type2, int unqualified)
2295{
2296 int bt1, t1, t2;
2297
2298 t1 = type1->t & VT_TYPE;
2299 t2 = type2->t & VT_TYPE;
2300 if (unqualified) {
2301 /* strip qualifiers before comparing */
2302 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
2303 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
2304 }
b0b5165d
TP
Thomas Preud'homme2014-02-06 20:51:47 +08002305 /* Default Vs explicit signedness only matters for char */
2306 if ((t1 & VT_BTYPE) != VT_BYTE) {
2307 t1 &= ~VT_DEFSIGN;
2308 t2 &= ~VT_DEFSIGN;
2309 }
0d1ed741 grischka2009-05-05 20:18:10 +02002310 /* XXX: bitfields ? */
2311 if (t1 != t2)
2312 return 0;
2313 /* test more complicated cases */
2314 bt1 = t1 & VT_BTYPE;
2315 if (bt1 == VT_PTR) {
2316 type1 = pointed_type(type1);
2317 type2 = pointed_type(type2);
2318 return is_compatible_types(type1, type2);
2319 } else if (bt1 == VT_STRUCT) {
2320 return (type1->ref == type2->ref);
2321 } else if (bt1 == VT_FUNC) {
2322 return is_compatible_func(type1, type2);
2323 } else {
2324 return 1;
2325 }
2326}
2327
2328/* return true if type1 and type2 are exactly the same (including
2329 qualifiers).
2330*/
2331static int is_compatible_types(CType *type1, CType *type2)
2332{
2333 return compare_types(type1,type2,0);
2334}
2335
2336/* return true if type1 and type2 are the same (ignoring qualifiers).
2337*/
2338static int is_compatible_parameter_types(CType *type1, CType *type2)
2339{
2340 return compare_types(type1,type2,1);
2341}
2342
2343/* print a type. If 'varstr' is not NULL, then the variable is also
2344 printed in the type */
2345/* XXX: union */
2346/* XXX: add array and function pointers */
88a3ccab grischka2009-12-20 01:53:49 +01002347static void type_to_str(char *buf, int buf_size,
0d1ed741 grischka2009-05-05 20:18:10 +02002348 CType *type, const char *varstr)
2349{
2350 int bt, v, t;
2351 Sym *s, *sa;
2352 char buf1[256];
2353 const char *tstr;
2354
2355 t = type->t & VT_TYPE;
2356 bt = t & VT_BTYPE;
2357 buf[0] = '\0';
2358 if (t & VT_CONSTANT)
2359 pstrcat(buf, buf_size, "const ");
2360 if (t & VT_VOLATILE)
2361 pstrcat(buf, buf_size, "volatile ");
33cea54d Thomas Preud'homme2014-03-09 13:32:24 +08002362 if ((t & (VT_DEFSIGN | VT_UNSIGNED)) == (VT_DEFSIGN | VT_UNSIGNED))
0d1ed741 grischka2009-05-05 20:18:10 +02002363 pstrcat(buf, buf_size, "unsigned ");
b0b5165d
TP
Thomas Preud'homme2014-02-06 20:51:47 +08002364 else if (t & VT_DEFSIGN)
2365 pstrcat(buf, buf_size, "signed ");
0d1ed741 grischka2009-05-05 20:18:10 +02002366 switch(bt) {
2367 case VT_VOID:
2368 tstr = "void";
2369 goto add_tstr;
2370 case VT_BOOL:
2371 tstr = "_Bool";
2372 goto add_tstr;
2373 case VT_BYTE:
2374 tstr = "char";
2375 goto add_tstr;
2376 case VT_SHORT:
2377 tstr = "short";
2378 goto add_tstr;
2379 case VT_INT:
2380 tstr = "int";
2381 goto add_tstr;
2382 case VT_LONG:
2383 tstr = "long";
2384 goto add_tstr;
2385 case VT_LLONG:
2386 tstr = "long long";
2387 goto add_tstr;
2388 case VT_FLOAT:
2389 tstr = "float";
2390 goto add_tstr;
2391 case VT_DOUBLE:
2392 tstr = "double";
2393 goto add_tstr;
2394 case VT_LDOUBLE:
2395 tstr = "long double";
2396 add_tstr:
2397 pstrcat(buf, buf_size, tstr);
2398 break;
2399 case VT_ENUM:
2400 case VT_STRUCT:
2401 if (bt == VT_STRUCT)
2402 tstr = "struct ";
2403 else
2404 tstr = "enum ";
2405 pstrcat(buf, buf_size, tstr);
2406 v = type->ref->v & ~SYM_STRUCT;
2407 if (v >= SYM_FIRST_ANOM)
2408 pstrcat(buf, buf_size, "<anonymous>");
2409 else
2410 pstrcat(buf, buf_size, get_tok_str(v, NULL));
2411 break;
2412 case VT_FUNC:
2413 s = type->ref;
2414 type_to_str(buf, buf_size, &s->type, varstr);
2415 pstrcat(buf, buf_size, "(");
2416 sa = s->next;
2417 while (sa != NULL) {
2418 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
2419 pstrcat(buf, buf_size, buf1);
2420 sa = sa->next;
2421 if (sa)
2422 pstrcat(buf, buf_size, ", ");
2423 }
2424 pstrcat(buf, buf_size, ")");
2425 goto no_var;
2426 case VT_PTR:
2427 s = type->ref;
2428 pstrcpy(buf1, sizeof(buf1), "*");
2429 if (varstr)
2430 pstrcat(buf1, sizeof(buf1), varstr);
2431 type_to_str(buf, buf_size, &s->type, buf1);
2432 goto no_var;
2433 }
2434 if (varstr) {
2435 pstrcat(buf, buf_size, " ");
2436 pstrcat(buf, buf_size, varstr);
2437 }
2438 no_var: ;
2439}
2440
2441/* verify type compatibility to store vtop in 'dt' type, and generate
2442 casts if needed. */
2443static void gen_assign_cast(CType *dt)
2444{
2445 CType *st, *type1, *type2, tmp_type1, tmp_type2;
2446 char buf1[256], buf2[256];
2447 int dbt, sbt;
2448
2449 st = &vtop->type; /* source type */
2450 dbt = dt->t & VT_BTYPE;
2451 sbt = st->t & VT_BTYPE;
6fd4e5ba seyko2015-03-03 15:39:57 +03002452 if (sbt == VT_VOID || dbt == VT_VOID) {
2453 if (sbt == VT_VOID && dbt == VT_VOID)
2454 ; /*
2455 It is Ok if both are void
2456 A test program:
2457 void func1() {}
2458 void func2() {
2459 return func1();
2460 }
2461 gcc accepts this program
2462 */
2463 else
2464 tcc_error("cannot cast from/to void");
2465 }
0d1ed741 grischka2009-05-05 20:18:10 +02002466 if (dt->t & VT_CONSTANT)
bf374a5f grischka2011-08-11 17:07:56 +02002467 tcc_warning("assignment of read-only location");
0d1ed741 grischka2009-05-05 20:18:10 +02002468 switch(dbt) {
2469 case VT_PTR:
2470 /* special cases for pointers */
2471 /* '0' can also be a pointer */
2472 if (is_null_pointer(vtop))
2473 goto type_ok;
2474 /* accept implicit pointer to integer cast with warning */
2475 if (is_integer_btype(sbt)) {
bf374a5f grischka2011-08-11 17:07:56 +02002476 tcc_warning("assignment makes pointer from integer without a cast");
0d1ed741 grischka2009-05-05 20:18:10 +02002477 goto type_ok;
2478 }
2479 type1 = pointed_type(dt);
2480 /* a function is implicitely a function pointer */
2481 if (sbt == VT_FUNC) {
2482 if ((type1->t & VT_BTYPE) != VT_VOID &&
2483 !is_compatible_types(pointed_type(dt), st))
bf374a5f grischka2011-08-11 17:07:56 +02002484 tcc_warning("assignment from incompatible pointer type");
956b4bee grischka2009-06-17 02:10:24 +02002485 goto type_ok;
0d1ed741 grischka2009-05-05 20:18:10 +02002486 }
2487 if (sbt != VT_PTR)
2488 goto error;
2489 type2 = pointed_type(st);
2490 if ((type1->t & VT_BTYPE) == VT_VOID ||
2491 (type2->t & VT_BTYPE) == VT_VOID) {
2492 /* void * can match anything */
2493 } else {
2494 /* exact type match, except for unsigned */
2495 tmp_type1 = *type1;
2496 tmp_type2 = *type2;
b0b5165d
TP
Thomas Preud'homme2014-02-06 20:51:47 +08002497 tmp_type1.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT |
2498 VT_VOLATILE);
2499 tmp_type2.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT |
2500 VT_VOLATILE);
0d1ed741 grischka2009-05-05 20:18:10 +02002501 if (!is_compatible_types(&tmp_type1, &tmp_type2))
bf374a5f grischka2011-08-11 17:07:56 +02002502 tcc_warning("assignment from incompatible pointer type");
0d1ed741 grischka2009-05-05 20:18:10 +02002503 }
2504 /* check const and volatile */
2505 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
2506 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
bf374a5f grischka2011-08-11 17:07:56 +02002507 tcc_warning("assignment discards qualifiers from pointer target type");
0d1ed741 grischka2009-05-05 20:18:10 +02002508 break;
2509 case VT_BYTE:
2510 case VT_SHORT:
2511 case VT_INT:
2512 case VT_LLONG:
2513 if (sbt == VT_PTR || sbt == VT_FUNC) {
bf374a5f grischka2011-08-11 17:07:56 +02002514 tcc_warning("assignment makes integer from pointer without a cast");
0d1ed741 grischka2009-05-05 20:18:10 +02002515 }
2516 /* XXX: more tests */
2517 break;
2518 case VT_STRUCT:
2519 tmp_type1 = *dt;
2520 tmp_type2 = *st;
2521 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
2522 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
2523 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
2524 error:
2525 type_to_str(buf1, sizeof(buf1), st, NULL);
2526 type_to_str(buf2, sizeof(buf2), dt, NULL);
bf374a5f grischka2011-08-11 17:07:56 +02002527 tcc_error("cannot cast '%s' to '%s'", buf1, buf2);
0d1ed741 grischka2009-05-05 20:18:10 +02002528 }
2529 break;
2530 }
2531 type_ok:
2532 gen_cast(dt);
2533}
2534
2535/* store vtop in lvalue pushed on stack */
88a3ccab grischka2009-12-20 01:53:49 +01002536ST_FUNC void vstore(void)
0d1ed741 grischka2009-05-05 20:18:10 +02002537{
2538 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
2539
2540 ft = vtop[-1].type.t;
2541 sbt = vtop->type.t & VT_BTYPE;
2542 dbt = ft & VT_BTYPE;
5c0a2366
MM
Michael Matz2012-04-15 01:06:46 +02002543 if ((((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
2544 (sbt == VT_INT && dbt == VT_SHORT))
2545 && !(vtop->type.t & VT_BITFIELD)) {
0d1ed741 grischka2009-05-05 20:18:10 +02002546 /* optimize char/short casts */
2547 delayed_cast = VT_MUSTCAST;
2548 vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));
2549 /* XXX: factorize */
2550 if (ft & VT_CONSTANT)
bf374a5f grischka2011-08-11 17:07:56 +02002551 tcc_warning("assignment of read-only location");
0d1ed741 grischka2009-05-05 20:18:10 +02002552 } else {
2553 delayed_cast = 0;
2554 if (!(ft & VT_BITFIELD))
2555 gen_assign_cast(&vtop[-1].type);
2556 }
2557
2558 if (sbt == VT_STRUCT) {
2559 /* if structure, only generate pointer */
2560 /* structure assignment : generate memcpy */
2561 /* XXX: optimize if small size */
2562 if (!nocode_wanted) {
2563 size = type_size(&vtop->type, &align);
2564
c0620c8a bobbl2009-11-30 19:33:44 +01002565 /* destination */
2566 vswap();
2567 vtop->type.t = VT_PTR;
2568 gaddrof();
2569
2570 /* address of memcpy() */
0d1ed741 grischka2009-05-05 20:18:10 +02002571#ifdef TCC_ARM_EABI
2572 if(!(align & 7))
2573 vpush_global_sym(&func_old_type, TOK_memcpy8);
2574 else if(!(align & 3))
2575 vpush_global_sym(&func_old_type, TOK_memcpy4);
2576 else
2577#endif
2578 vpush_global_sym(&func_old_type, TOK_memcpy);
2579
c0620c8a bobbl2009-11-30 19:33:44 +01002580 vswap();
0d1ed741 grischka2009-05-05 20:18:10 +02002581 /* source */
2582 vpushv(vtop - 2);
2583 vtop->type.t = VT_PTR;
2584 gaddrof();
2585 /* type size */
2586 vpushi(size);
2587 gfunc_call(3);
0d1ed741 grischka2009-05-05 20:18:10 +02002588 } else {
2589 vswap();
2590 vpop();
2591 }
2592 /* leave source on stack */
2593 } else if (ft & VT_BITFIELD) {
2594 /* bitfield store handling */
9d7fb333 grischka2014-09-23 12:30:08 +02002595
2596 /* save lvalue as expression result (example: s.b = s.a = n;) */
2597 vdup(), vtop[-1] = vtop[-2];
2598
0d1ed741 grischka2009-05-05 20:18:10 +02002599 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
2600 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2601 /* remove bit field info to avoid loops */
2602 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2603
0d1ed741 grischka2009-05-05 20:18:10 +02002604 if((ft & VT_BTYPE) == VT_BOOL) {
2605 gen_cast(&vtop[-1].type);
2606 vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
2607 }
2608
2609 /* duplicate destination */
2610 vdup();
2611 vtop[-1] = vtop[-2];
2612
2613 /* mask and shift source */
2614 if((ft & VT_BTYPE) != VT_BOOL) {
2615 if((ft & VT_BTYPE) == VT_LLONG) {
2616 vpushll((1ULL << bit_size) - 1ULL);
2617 } else {
2618 vpushi((1 << bit_size) - 1);
2619 }
2620 gen_op('&');
2621 }
2622 vpushi(bit_pos);
2623 gen_op(TOK_SHL);
2624 /* load destination, mask and or with source */
2625 vswap();
2626 if((ft & VT_BTYPE) == VT_LLONG) {
2627 vpushll(~(((1ULL << bit_size) - 1ULL) << bit_pos));
2628 } else {
2629 vpushi(~(((1 << bit_size) - 1) << bit_pos));
2630 }
2631 gen_op('&');
2632 gen_op('|');
2633 /* store result */
2634 vstore();
9d7fb333 grischka2014-09-23 12:30:08 +02002635 /* ... and discard */
0d1ed741 grischka2009-05-05 20:18:10 +02002636 vpop();
2637
2638 } else {
5bcc3eed Thomas Preud'homme2015-03-10 23:23:00 +08002639 if (!nocode_wanted) {
0d1ed741 grischka2009-05-05 20:18:10 +02002640#ifdef CONFIG_TCC_BCHECK
5bcc3eed
TP
Thomas Preud'homme2015-03-10 23:23:00 +08002641 /* bound check case */
2642 if (vtop[-1].r & VT_MUSTBOUND) {
2643 vswap();
2644 gbound();
2645 vswap();
2646 }
0d1ed741 grischka2009-05-05 20:18:10 +02002647#endif
0d1ed741 grischka2009-05-05 20:18:10 +02002648 rc = RC_INT;
2649 if (is_float(ft)) {
2650 rc = RC_FLOAT;
2651#ifdef TCC_TARGET_X86_64
2652 if ((ft & VT_BTYPE) == VT_LDOUBLE) {
2653 rc = RC_ST0;
0e17671f
JL
James Lyon2013-04-19 15:33:16 +01002654 } else if ((ft & VT_BTYPE) == VT_QFLOAT) {
2655 rc = RC_FRET;
0d1ed741 grischka2009-05-05 20:18:10 +02002656 }
2657#endif
2658 }
2659 r = gv(rc); /* generate value */
2660 /* if lvalue was saved on stack, must read it */
2661 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
2662 SValue sv;
2663 t = get_reg(RC_INT);
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +00002664#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
0d1ed741 grischka2009-05-05 20:18:10 +02002665 sv.type.t = VT_PTR;
2666#else
2667 sv.type.t = VT_INT;
2668#endif
2669 sv.r = VT_LOCAL | VT_LVAL;
2670 sv.c.ul = vtop[-1].c.ul;
2671 load(t, &sv);
2672 vtop[-1].r = t | VT_LVAL;
2673 }
55ea6d3f James Lyon2013-04-19 00:40:48 +01002674 /* two word case handling : store second register at word + 4 (or +8 for x86-64) */
b14ef0e2 Edmund Grimley Evans2015-02-13 18:58:31 +00002675#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
0e17671f
JL
James Lyon2013-04-19 15:33:16 +01002676 if (((ft & VT_BTYPE) == VT_QLONG) || ((ft & VT_BTYPE) == VT_QFLOAT)) {
2677 int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE;
55ea6d3f James Lyon2013-04-19 00:40:48 +01002678#else
0d1ed741 grischka2009-05-05 20:18:10 +02002679 if ((ft & VT_BTYPE) == VT_LLONG) {
0e17671f James Lyon2013-04-19 15:33:16 +01002680 int addr_type = VT_INT, load_size = 4, load_type = VT_INT;
55ea6d3f James Lyon2013-04-19 00:40:48 +01002681#endif
0e17671f
JL
James Lyon2013-04-19 15:33:16 +01002682 vtop[-1].type.t = load_type;
2683 store(r, vtop - 1);
0d1ed741 grischka2009-05-05 20:18:10 +02002684 vswap();
2685 /* convert to int to increment easily */
0e17671f James Lyon2013-04-19 15:33:16 +01002686 vtop->type.t = addr_type;
0d1ed741 grischka2009-05-05 20:18:10 +02002687 gaddrof();
0e17671f James Lyon2013-04-19 15:33:16 +01002688 vpushi(load_size);
0d1ed741 grischka2009-05-05 20:18:10 +02002689 gen_op('+');
2690 vtop->r |= VT_LVAL;
2691 vswap();
0e17671f James Lyon2013-04-19 15:33:16 +01002692 vtop[-1].type.t = load_type;
0d1ed741 grischka2009-05-05 20:18:10 +02002693 /* XXX: it works because r2 is spilled last ! */
2694 store(vtop->r2, vtop - 1);
0e17671f
JL
James Lyon2013-04-19 15:33:16 +01002695 } else {
2696 store(r, vtop - 1);
0d1ed741 grischka2009-05-05 20:18:10 +02002697 }
0d1ed741 grischka2009-05-05 20:18:10 +02002698 }
2699 vswap();
2700 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
2701 vtop->r |= delayed_cast;
2702 }
2703}
2704
2705/* post defines POST/PRE add. c is the token ++ or -- */
88a3ccab grischka2009-12-20 01:53:49 +01002706ST_FUNC void inc(int post, int c)
0d1ed741 grischka2009-05-05 20:18:10 +02002707{
2708 test_lvalue();
2709 vdup(); /* save lvalue */
2710 if (post) {
5bcc3eed
TP
Thomas Preud'homme2015-03-10 23:23:00 +08002711 if (!nocode_wanted)
2712 gv_dup(); /* duplicate value */
2713 else
2714 vdup(); /* duplicate value */
0d1ed741 grischka2009-05-05 20:18:10 +02002715 vrotb(3);
2716 vrotb(3);
2717 }
2718 /* add constant */
2719 vpushi(c - TOK_MID);
2720 gen_op('+');
2721 vstore(); /* store value */
2722 if (post)
2723 vpop(); /* if post op, return saved value */
2724}
2725
2726/* Parse GNUC __attribute__ extension. Currently, the following
2727 extensions are recognized:
2728 - aligned(n) : set data/function alignment.
2729 - packed : force data alignment to 1
2730 - section(x) : generate data/code in this section.
2731 - unused : currently ignored, but may be used someday.
2732 - regparm(n) : pass function parameters in registers (i386 only)
2733 */
2734static void parse_attribute(AttributeDef *ad)
2735{
2736 int t, n;
2737
2738 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
2739 next();
2740 skip('(');
2741 skip('(');
2742 while (tok != ')') {
2743 if (tok < TOK_IDENT)
2744 expect("attribute name");
2745 t = tok;
2746 next();
2747 switch(t) {
2748 case TOK_SECTION1:
2749 case TOK_SECTION2:
2750 skip('(');
2751 if (tok != TOK_STR)
2752 expect("section name");
2753 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
2754 next();
2755 skip(')');
2756 break;
c93eca4f
JS
Joe Soroka2011-03-03 01:58:45 -08002757 case TOK_ALIAS1:
2758 case TOK_ALIAS2:
2759 skip('(');
2760 if (tok != TOK_STR)
2761 expect("alias(\"target\")");
2762 ad->alias_target = /* save string as token, for later */
2763 tok_alloc((char*)tokc.cstr->data, tokc.cstr->size-1)->tok;
2764 next();
2765 skip(')');
2766 break;
fbda78ae
MM
Michael Matz2014-04-14 02:53:11 +02002767 case TOK_VISIBILITY1:
2768 case TOK_VISIBILITY2:
2769 skip('(');
2770 if (tok != TOK_STR)
2771 expect("visibility(\"default|hidden|internal|protected\")");
2772 if (!strcmp (tokc.cstr->data, "default"))
2773 ad->a.visibility = STV_DEFAULT;
2774 else if (!strcmp (tokc.cstr->data, "hidden"))
2775 ad->a.visibility = STV_HIDDEN;
2776 else if (!strcmp (tokc.cstr->data, "internal"))
2777 ad->a.visibility = STV_INTERNAL;
2778 else if (!strcmp (tokc.cstr->data, "protected"))
2779 ad->a.visibility = STV_PROTECTED;
2780 else
2781 expect("visibility(\"default|hidden|internal|protected\")");
2782 next();
2783 skip(')');
2784 break;
0d1ed741 grischka2009-05-05 20:18:10 +02002785 case TOK_ALIGNED1:
2786 case TOK_ALIGNED2:
2787 if (tok == '(') {
2788 next();
2789 n = expr_const();
2790 if (n <= 0 || (n & (n - 1)) != 0)
bf374a5f grischka2011-08-11 17:07:56 +02002791 tcc_error("alignment must be a positive power of two");
0d1ed741 grischka2009-05-05 20:18:10 +02002792 skip(')');
2793 } else {
2794 n = MAX_ALIGN;
2795 }
3fe2a95d grischka2014-01-07 14:57:07 +01002796 ad->a.aligned = n;
0d1ed741 grischka2009-05-05 20:18:10 +02002797 break;
2798 case TOK_PACKED1:
2799 case TOK_PACKED2:
3fe2a95d grischka2014-01-07 14:57:07 +01002800 ad->a.packed = 1;
0d1ed741 grischka2009-05-05 20:18:10 +02002801 break;
95b9a477
MS
Manuel Simoni2010-02-27 17:37:59 +01002802 case TOK_WEAK1:
2803 case TOK_WEAK2:
3fe2a95d grischka2014-01-07 14:57:07 +01002804 ad->a.weak = 1;
95b9a477 Manuel Simoni2010-02-27 17:37:59 +01002805 break;
0d1ed741 grischka2009-05-05 20:18:10 +02002806 case TOK_UNUSED1:
2807 case TOK_UNUSED2:
2808 /* currently, no need to handle it because tcc does not
2809 track unused objects */
2810 break;
2811 case TOK_NORETURN1:
2812 case TOK_NORETURN2:
2813 /* currently, no need to handle it because tcc does not
2814 track unused objects */
2815 break;
2816 case TOK_CDECL1:
2817 case TOK_CDECL2:
2818 case TOK_CDECL3:
3fe2a95d grischka2014-01-07 14:57:07 +01002819 ad->a.func_call = FUNC_CDECL;
0d1ed741 grischka2009-05-05 20:18:10 +02002820 break;
2821 case TOK_STDCALL1:
2822 case TOK_STDCALL2:
2823 case TOK_STDCALL3:
3fe2a95d grischka2014-01-07 14:57:07 +01002824 ad->a.func_call = FUNC_STDCALL;
0d1ed741 grischka2009-05-05 20:18:10 +02002825 break;
2826#ifdef TCC_TARGET_I386
2827 case TOK_REGPARM1:
2828 case TOK_REGPARM2:
2829 skip('(');
2830 n = expr_const();
2831 if (n > 3)
2832 n = 3;
2833 else if (n < 0)
2834 n = 0;
2835 if (n > 0)
3fe2a95d grischka2014-01-07 14:57:07 +01002836 ad->a.func_call = FUNC_FASTCALL1 + n - 1;
0d1ed741 grischka2009-05-05 20:18:10 +02002837 skip(')');
2838 break;
2839 case TOK_FASTCALL1:
2840 case TOK_FASTCALL2:
2841 case TOK_FASTCALL3:
3fe2a95d grischka2014-01-07 14:57:07 +01002842 ad->a.func_call = FUNC_FASTCALLW;
0d1ed741 grischka2009-05-05 20:18:10 +02002843 break;
2844#endif
a975008a
DR
Detlef Riekenberg2010-01-26 22:56:22 +01002845 case TOK_MODE:
2846 skip('(');
2847 switch(tok) {
2848 case TOK_MODE_DI:
3fe2a95d grischka2014-01-07 14:57:07 +01002849 ad->a.mode = VT_LLONG + 1;
a975008a
DR
Detlef Riekenberg2010-01-26 22:56:22 +01002850 break;
2851 case TOK_MODE_HI:
3fe2a95d grischka2014-01-07 14:57:07 +01002852 ad->a.mode = VT_SHORT + 1;
a975008a
DR
Detlef Riekenberg2010-01-26 22:56:22 +01002853 break;
2854 case TOK_MODE_SI:
3fe2a95d grischka2014-01-07 14:57:07 +01002855 ad->a.mode = VT_INT + 1;
a975008a
DR
Detlef Riekenberg2010-01-26 22:56:22 +01002856 break;
2857 default:
bf374a5f grischka2011-08-11 17:07:56 +02002858 tcc_warning("__mode__(%s) not supported\n", get_tok_str(tok, NULL));
a975008a
DR
Detlef Riekenberg2010-01-26 22:56:22 +01002859 break;
2860 }
2861 next();
2862 skip(')');
2863 break;
0d1ed741 grischka2009-05-05 20:18:10 +02002864 case TOK_DLLEXPORT:
3fe2a95d grischka2014-01-07 14:57:07 +01002865 ad->a.func_export = 1;
0d1ed741 grischka2009-05-05 20:18:10 +02002866 break;
5b113f3e grischka2009-11-13 17:14:05 +01002867 case TOK_DLLIMPORT:
3fe2a95d grischka2014-01-07 14:57:07 +01002868 ad->a.func_import = 1;
5b113f3e grischka2009-11-13 17:14:05 +01002869 break;
0d1ed741 grischka2009-05-05 20:18:10 +02002870 default:
2871 if (tcc_state->warn_unsupported)
bf374a5f grischka2011-08-11 17:07:56 +02002872 tcc_warning("'%s' attribute ignored", get_tok_str(t, NULL));
0d1ed741 grischka2009-05-05 20:18:10 +02002873 /* skip parameters */
2874 if (tok == '(') {
2875 int parenthesis = 0;
2876 do {
2877 if (tok == '(')
2878 parenthesis++;
2879 else if (tok == ')')
2880 parenthesis--;
2881 next();
2882 } while (parenthesis && tok != -1);
2883 }
2884 break;
2885 }
2886 if (tok != ',')
2887 break;
2888 next();
2889 }
2890 skip(')');
2891 skip(')');
2892 }
2893}
2894
2895/* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
82969f04 Thomas Preud'homme2013-09-20 21:16:53 +02002896static void struct_decl(CType *type, int u, int tdef)
0d1ed741 grischka2009-05-05 20:18:10 +02002897{
3b07a15f Amine Najahi2013-10-06 14:43:16 +02002898 int a, v, size, align, maxalign, c, offset, flexible;
06a7c415 Joe Soroka2011-03-18 17:47:35 -07002899 int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt;
0d1ed741 grischka2009-05-05 20:18:10 +02002900 Sym *s, *ss, *ass, **ps;
2901 AttributeDef ad;
2902 CType type1, btype;
2903
2904 a = tok; /* save decl type */
2905 next();
2906 if (tok != '{') {
2907 v = tok;
2908 next();
2909 /* struct already defined ? return it */
2910 if (v < TOK_IDENT)
2911 expect("struct/union/enum name");
2912 s = struct_find(v);
2913 if (s) {
2914 if (s->type.t != a)
bf374a5f grischka2011-08-11 17:07:56 +02002915 tcc_error("invalid type");
0d1ed741 grischka2009-05-05 20:18:10 +02002916 goto do_decl;
82969f04
TP
Thomas Preud'homme2013-09-20 21:16:53 +02002917 } else if (tok >= TOK_IDENT && !tdef)
2918 tcc_error("unknown struct/union/enum");
0d1ed741 grischka2009-05-05 20:18:10 +02002919 } else {
2920 v = anon_sym++;
2921 }
2922 type1.t = a;
69c2e7f9 grischka2013-07-24 17:06:13 +02002923 type1.ref = NULL;
0d1ed741 grischka2009-05-05 20:18:10 +02002924 /* we put an undefined size for struct/union */
2925 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
2926 s->r = 0; /* default alignment is zero as gcc */
2927 /* put struct/union/enum name in type */
2928 do_decl:
2929 type->t = u;
2930 type->ref = s;
2931
2932 if (tok == '{') {
2933 next();
2934 if (s->c != -1)
bf374a5f grischka2011-08-11 17:07:56 +02002935 tcc_error("struct/union/enum already defined");
0d1ed741 grischka2009-05-05 20:18:10 +02002936 /* cannot be empty */
2937 c = 0;
2938 /* non empty enums are not allowed */
2939 if (a == TOK_ENUM) {
2940 for(;;) {
2941 v = tok;
2942 if (v < TOK_UIDENT)
2943 expect("identifier");
673befd2 Thomas Preud'homme2013-09-20 22:49:49 +02002944 ss = sym_find(v);
3e565842 Thomas Preud'homme2014-03-31 22:58:17 +08002945 if (ss && !local_stack)
673befd2
TP
Thomas Preud'homme2013-09-20 22:49:49 +02002946 tcc_error("redefinition of enumerator '%s'",
2947 get_tok_str(v, NULL));
0d1ed741 grischka2009-05-05 20:18:10 +02002948 next();
2949 if (tok == '=') {
2950 next();
2951 c = expr_const();
2952 }
2953 /* enum symbols have static storage */
2954 ss = sym_push(v, &int_type, VT_CONST, c);
2955 ss->type.t |= VT_STATIC;
2956 if (tok != ',')
2957 break;
2958 next();
2959 c++;
2960 /* NOTE: we accept a trailing comma */
2961 if (tok == '}')
2962 break;
2963 }
0f522fb3 Thomas Preud'homme2013-09-20 01:06:43 +02002964 s->c = type_size(&int_type, &align);
0d1ed741 grischka2009-05-05 20:18:10 +02002965 skip('}');
2966 } else {
2967 maxalign = 1;
2968 ps = &s->next;
2969 prevbt = VT_INT;
2970 bit_pos = 0;
2971 offset = 0;
3b07a15f Amine Najahi2013-10-06 14:43:16 +02002972 flexible = 0;
0d1ed741 grischka2009-05-05 20:18:10 +02002973 while (tok != '}') {
370547a5 Thomas Preud'homme2013-01-31 13:02:04 +01002974 parse_btype(&btype, &ad);
0d1ed741 grischka2009-05-05 20:18:10 +02002975 while (1) {
3b07a15f
AN
Amine Najahi2013-10-06 14:43:16 +02002976 if (flexible)
2977 tcc_error("flexible array member '%s' not at the end of struct",
2978 get_tok_str(v, NULL));
0d1ed741 grischka2009-05-05 20:18:10 +02002979 bit_size = -1;
2980 v = 0;
2981 type1 = btype;
2982 if (tok != ':') {
2983 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
dec95935 seyko2015-04-10 06:31:58 +03002984 if (v == 0) {
2985 if ((type1.t & VT_BTYPE) != VT_STRUCT)
2986 expect("identifier");
2987 else {
2988 int v = btype.ref->v;
2989 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
2990 if (tcc_state->ms_extensions == 0)
2991 expect("identifier");
2992 }
2993 }
2994 }
3b07a15f
AN
Amine Najahi2013-10-06 14:43:16 +02002995 if (type_size(&type1, &align) < 0) {
2996 if ((a == TOK_STRUCT) && (type1.t & VT_ARRAY) && c)
2997 flexible = 1;
2998 else
2999 tcc_error("field '%s' has incomplete type",
3000 get_tok_str(v, NULL));
3001 }
0d1ed741 grischka2009-05-05 20:18:10 +02003002 if ((type1.t & VT_BTYPE) == VT_FUNC ||
3003 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
bf374a5f grischka2011-08-11 17:07:56 +02003004 tcc_error("invalid type for '%s'",
0d1ed741 grischka2009-05-05 20:18:10 +02003005 get_tok_str(v, NULL));
3006 }
3007 if (tok == ':') {
3008 next();
3009 bit_size = expr_const();
3010 /* XXX: handle v = 0 case for messages */
3011 if (bit_size < 0)
bf374a5f grischka2011-08-11 17:07:56 +02003012 tcc_error("negative width in bit-field '%s'",
0d1ed741 grischka2009-05-05 20:18:10 +02003013 get_tok_str(v, NULL));
3014 if (v && bit_size == 0)
bf374a5f grischka2011-08-11 17:07:56 +02003015 tcc_error("zero width for bit-field '%s'",
0d1ed741 grischka2009-05-05 20:18:10 +02003016 get_tok_str(v, NULL));
3017 }
3018 size = type_size(&type1, &align);
3fe2a95d grischka2014-01-07 14:57:07 +01003019 if (ad.a.aligned) {
3020 if (align < ad.a.aligned)
3021 align = ad.a.aligned;
3022 } else if (ad.a.packed) {
0d1ed741 grischka2009-05-05 20:18:10 +02003023 align = 1;
3024 } else if (*tcc_state->pack_stack_ptr) {
3025 if (align > *tcc_state->pack_stack_ptr)
3026 align = *tcc_state->pack_stack_ptr;
3027 }
3028 lbit_pos = 0;
3029 if (bit_size >= 0) {
3030 bt = type1.t & VT_BTYPE;
3031 if (bt != VT_INT &&
3032 bt != VT_BYTE &&
3033 bt != VT_SHORT &&
3034 bt != VT_BOOL &&
3035 bt != VT_ENUM &&
3036 bt != VT_LLONG)
bf374a5f grischka2011-08-11 17:07:56 +02003037 tcc_error("bitfields must have scalar type");
0d1ed741 grischka2009-05-05 20:18:10 +02003038 bsize = size * 8;
3039 if (bit_size > bsize) {
bf374a5f grischka2011-08-11 17:07:56 +02003040 tcc_error("width of '%s' exceeds its type",
0d1ed741 grischka2009-05-05 20:18:10 +02003041 get_tok_str(v, NULL));
3042 } else if (bit_size == bsize) {
3043 /* no need for bit fields */
3044 bit_pos = 0;
3045 } else if (bit_size == 0) {
3046 /* XXX: what to do if only padding in a
3047 structure ? */
3048 /* zero size: means to pad */
3049 bit_pos = 0;
3050 } else {
3051 /* we do not have enough room ?
3052 did the type change?
3053 is it a union? */
3054 if ((bit_pos + bit_size) > bsize ||
3055 bt != prevbt || a == TOK_UNION)
3056 bit_pos = 0;
3057 lbit_pos = bit_pos;
3058 /* XXX: handle LSB first */
3059 type1.t |= VT_BITFIELD |
3060 (bit_pos << VT_STRUCT_SHIFT) |
3061 (bit_size << (VT_STRUCT_SHIFT + 6));
3062 bit_pos += bit_size;
3063 }
3064 prevbt = bt;
3065 } else {
3066 bit_pos = 0;
3067 }
3068 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
3069 /* add new memory data only if starting
3070 bit field */
3071 if (lbit_pos == 0) {
3072 if (a == TOK_STRUCT) {
3073 c = (c + align - 1) & -align;
3074 offset = c;
3075 if (size > 0)
3076 c += size;
3077 } else {
3078 offset = 0;
3079 if (size > c)
3080 c = size;
3081 }
3082 if (align > maxalign)
3083 maxalign = align;
3084 }
3085#if 0
3086 printf("add field %s offset=%d",
3087 get_tok_str(v, NULL), offset);
3088 if (type1.t & VT_BITFIELD) {
3089 printf(" pos=%d size=%d",
3090 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
3091 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
3092 }
3093 printf("\n");
3094#endif
3095 }
3096 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
3097 ass = type1.ref;
3098 while ((ass = ass->next) != NULL) {
3099 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
3100 *ps = ss;
3101 ps = &ss->next;
3102 }
3103 } else if (v) {
3104 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
3105 *ps = ss;
3106 ps = &ss->next;
3107 }
3108 if (tok == ';' || tok == TOK_EOF)
3109 break;
3110 skip(',');
3111 }
3112 skip(';');
3113 }
3114 skip('}');
3115 /* store size and alignment */
3116 s->c = (c + maxalign - 1) & -maxalign;
06a7c415 Joe Soroka2011-03-18 17:47:35 -07003117 s->r = maxalign;
0d1ed741 grischka2009-05-05 20:18:10 +02003118 }
3119 }
3120}
3121
b68499e9 Thomas Preud'homme2014-03-24 23:28:56 +08003122/* return 1 if basic type is a type size (short, long, long long) */
822f4630 Urs Janssen2014-04-10 11:53:54 +02003123ST_FUNC int is_btype_size(int bt)
b68499e9
TP
Thomas Preud'homme2014-03-24 23:28:56 +08003124{
3125 return bt == VT_SHORT || bt == VT_LONG || bt == VT_LLONG;
3126}
3127
0d1ed741 grischka2009-05-05 20:18:10 +02003128/* return 0 if no type declaration. otherwise, return the basic type
3129 and skip it.
3130 */
3131static int parse_btype(CType *type, AttributeDef *ad)
3132{
b68499e9 Thomas Preud'homme2014-03-24 23:28:56 +08003133 int t, u, bt_size, complete, type_found, typespec_found;
0d1ed741 grischka2009-05-05 20:18:10 +02003134 Sym *s;
3135 CType type1;
3136
3137 memset(ad, 0, sizeof(AttributeDef));
b68499e9 Thomas Preud'homme2014-03-24 23:28:56 +08003138 complete = 0;
0d1ed741 grischka2009-05-05 20:18:10 +02003139 type_found = 0;
3140 typespec_found = 0;
0d1ed741 grischka2009-05-05 20:18:10 +02003141 t = 0;
3142 while(1) {
3143 switch(tok) {
3144 case TOK_EXTENSION:
3145 /* currently, we really ignore extension */
3146 next();
3147 continue;
3148
3149 /* basic types */
3150 case TOK_CHAR:
3151 u = VT_BYTE;
3152 basic_type:
3153 next();
3154 basic_type1:
b68499e9 Thomas Preud'homme2014-03-24 23:28:56 +08003155 if (complete)
bf374a5f grischka2011-08-11 17:07:56 +02003156 tcc_error("too many basic types");
0d1ed741 grischka2009-05-05 20:18:10 +02003157 t |= u;
b68499e9
TP
Thomas Preud'homme2014-03-24 23:28:56 +08003158 bt_size = is_btype_size (u & VT_BTYPE);
3159 if (u == VT_INT || (!bt_size && !(t & VT_TYPEDEF)))
3160 complete = 1;
0d1ed741 grischka2009-05-05 20:18:10 +02003161 typespec_found = 1;
3162 break;
3163 case TOK_VOID:
3164 u = VT_VOID;
3165 goto basic_type;
3166 case TOK_SHORT:
3167 u = VT_SHORT;
3168 goto basic_type;
3169 case TOK_INT:
b68499e9
TP
Thomas Preud'homme2014-03-24 23:28:56 +08003170 u = VT_INT;
3171 goto basic_type;
0d1ed741 grischka2009-05-05 20:18:10 +02003172 case TOK_LONG:
3173 next();
3174 if ((t & VT_BTYPE) == VT_DOUBLE) {
9fda4f42 grischka2009-07-18 22:07:17 +02003175#ifndef TCC_TARGET_PE
0d1ed741 grischka2009-05-05 20:18:10 +02003176 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
9fda4f42 grischka2009-07-18 22:07:17 +02003177#endif
0d1ed741 grischka2009-05-05 20:18:10 +02003178 } else if ((t & VT_BTYPE) == VT_LONG) {
3179 t = (t & ~VT_BTYPE) | VT_LLONG;
3180 } else {
3181 u = VT_LONG;
3182 goto basic_type1;
3183 }
3184 break;
b14ef0e2
EGE
Edmund Grimley Evans2015-02-13 18:58:31 +00003185#ifdef TCC_TARGET_ARM64
3186 case TOK_UINT128:
3187 /* GCC's __uint128_t appears in some Linux header files. Make it a
3188 synonym for long double to get the size and alignment right. */
3189 u = VT_LDOUBLE;
3190 goto basic_type;
3191#endif
0d1ed741 grischka2009-05-05 20:18:10 +02003192 case TOK_BOOL:
3193 u = VT_BOOL;
3194 goto basic_type;
3195 case TOK_FLOAT:
3196 u = VT_FLOAT;
3197 goto basic_type;
3198 case TOK_DOUBLE:
3199 next();
3200 if ((t & VT_BTYPE) == VT_LONG) {
9fda4f42 grischka2009-07-18 22:07:17 +02003201#ifdef TCC_TARGET_PE
3202 t = (t & ~VT_BTYPE) | VT_DOUBLE;
3203#else
0d1ed741 grischka2009-05-05 20:18:10 +02003204 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
9fda4f42 grischka2009-07-18 22:07:17 +02003205#endif
0d1ed741 grischka2009-05-05 20:18:10 +02003206 } else {
3207 u = VT_DOUBLE;
3208 goto basic_type1;
3209 }
3210 break;
3211 case TOK_ENUM:
bbf8221e seyko2015-03-03 15:00:13 +03003212 struct_decl(&type1, VT_ENUM, t & (VT_TYPEDEF | VT_EXTERN));
0d1ed741 grischka2009-05-05 20:18:10 +02003213 basic_type2:
3214 u = type1.t;
3215 type->ref = type1.ref;
3216 goto basic_type1;
3217 case TOK_STRUCT:
3218 case TOK_UNION:
bbf8221e seyko2015-03-03 15:00:13 +03003219 struct_decl(&type1, VT_STRUCT, t & (VT_TYPEDEF | VT_EXTERN));
0d1ed741 grischka2009-05-05 20:18:10 +02003220 goto basic_type2;
3221
3222 /* type modifiers */
3223 case TOK_CONST1:
3224 case TOK_CONST2:
3225 case TOK_CONST3:
3226 t |= VT_CONSTANT;
3227 next();
3228 break;
3229 case TOK_VOLATILE1:
3230 case TOK_VOLATILE2:
3231 case TOK_VOLATILE3:
3232 t |= VT_VOLATILE;
3233 next();
3234 break;
3235 case TOK_SIGNED1:
3236 case TOK_SIGNED2:
3237 case TOK_SIGNED3:
b0b5165d
TP
Thomas Preud'homme2014-02-06 20:51:47 +08003238 if ((t & (VT_DEFSIGN|VT_UNSIGNED)) == (VT_DEFSIGN|VT_UNSIGNED))
3239 tcc_error("signed and unsigned modifier");
0d1ed741 grischka2009-05-05 20:18:10 +02003240 typespec_found = 1;
b0b5165d Thomas Preud'homme2014-02-06 20:51:47 +08003241 t |= VT_DEFSIGN;
0d1ed741 grischka2009-05-05 20:18:10 +02003242 next();
3243 break;
3244 case TOK_REGISTER:
3245 case TOK_AUTO:
3246 case TOK_RESTRICT1:
3247 case TOK_RESTRICT2:
3248 case TOK_RESTRICT3:
3249 next();
3250 break;
3251 case TOK_UNSIGNED:
b0b5165d
TP
Thomas Preud'homme2014-02-06 20:51:47 +08003252 if ((t & (VT_DEFSIGN|VT_UNSIGNED)) == VT_DEFSIGN)
3253 tcc_error("signed and unsigned modifier");
3254 t |= VT_DEFSIGN | VT_UNSIGNED;
0d1ed741 grischka2009-05-05 20:18:10 +02003255 next();
3256 typespec_found = 1;
3257 break;
3258
3259 /* storage */
3260 case TOK_EXTERN:
3261 t |= VT_EXTERN;
3262 next();
3263 break;
3264 case TOK_STATIC:
3265 t |= VT_STATIC;
3266 next();
3267 break;
3268 case TOK_TYPEDEF:
3269 t |= VT_TYPEDEF;
3270 next();
3271 break;
3272 case TOK_INLINE1:
3273 case TOK_INLINE2:
3274 case TOK_INLINE3:
3275 t |= VT_INLINE;
3276 next();
3277 break;
3278
3279 /* GNUC attribute */
3280 case TOK_ATTRIBUTE1:
3281 case TOK_ATTRIBUTE2:
3282 parse_attribute(ad);
3fe2a95d grischka2014-01-07 14:57:07 +01003283 if (ad->a.mode) {
3284 u = ad->a.mode -1;
a975008a
DR
Detlef Riekenberg2010-01-26 22:56:22 +01003285 t = (t & ~VT_BTYPE) | u;
3286 }
0d1ed741 grischka2009-05-05 20:18:10 +02003287 break;
3288 /* GNUC typeof */
3289 case TOK_TYPEOF1:
3290 case TOK_TYPEOF2:
3291 case TOK_TYPEOF3:
3292 next();
3293 parse_expr_type(&type1);
38cbb40e
JS
Joe Soroka2011-03-06 22:32:35 -08003294 /* remove all storage modifiers except typedef */
3295 type1.t &= ~(VT_STORAGE&~VT_TYPEDEF);
0d1ed741 grischka2009-05-05 20:18:10 +02003296 goto basic_type2;
3297 default:
b68499e9 Thomas Preud'homme2014-03-24 23:28:56 +08003298 if (typespec_found)
0d1ed741 grischka2009-05-05 20:18:10 +02003299 goto the_end;
3300 s = sym_find(tok);
3301 if (!s || !(s->type.t & VT_TYPEDEF))
3302 goto the_end;
0d1ed741 grischka2009-05-05 20:18:10 +02003303 t |= (s->type.t & ~VT_TYPEDEF);
3304 type->ref = s->type.ref;
56d6abdb grischka2009-12-06 17:37:33 +01003305 if (s->r) {
3306 /* get attributes from typedef */
3fe2a95d grischka2014-01-07 14:57:07 +01003307 if (0 == ad->a.aligned)
3308 ad->a.aligned = s->a.aligned;
3309 if (0 == ad->a.func_call)
3310 ad->a.func_call = s->a.func_call;
3311 ad->a.packed |= s->a.packed;
56d6abdb grischka2009-12-06 17:37:33 +01003312 }
0d1ed741 grischka2009-05-05 20:18:10 +02003313 next();
3314 typespec_found = 1;
3315 break;
3316 }
3317 type_found = 1;
3318 }
3319the_end:
0d1ed741 grischka2009-05-05 20:18:10 +02003320 if (tcc_state->char_is_unsigned) {
b0b5165d Thomas Preud'homme2014-02-06 20:51:47 +08003321 if ((t & (VT_DEFSIGN|VT_BTYPE)) == VT_BYTE)
0d1ed741 grischka2009-05-05 20:18:10 +02003322 t |= VT_UNSIGNED;
3323 }
0d1ed741 grischka2009-05-05 20:18:10 +02003324
3325 /* long is never used as type */
3326 if ((t & VT_BTYPE) == VT_LONG)
b14ef0e2
EGE
Edmund Grimley Evans2015-02-13 18:58:31 +00003327#if (!defined TCC_TARGET_X86_64 && !defined TCC_TARGET_ARM64) || \
3328 defined TCC_TARGET_PE
0d1ed741 grischka2009-05-05 20:18:10 +02003329 t = (t & ~VT_BTYPE) | VT_INT;
3330#else
3331 t = (t & ~VT_BTYPE) | VT_LLONG;
3332#endif
3333 type->t = t;
3334 return type_found;
3335}
3336
3337/* convert a function parameter type (array to pointer and function to
3338 function pointer) */
3339static inline void convert_parameter_type(CType *pt)
3340{
3341 /* remove const and volatile qualifiers (XXX: const could be used
3342 to indicate a const function parameter */
3343 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
3344 /* array must be transformed to pointer according to ANSI C */
3345 pt->t &= ~VT_ARRAY;
3346 if ((pt->t & VT_BTYPE) == VT_FUNC) {
3347 mk_pointer(pt);
3348 }
3349}
3350
b8adf009
TP
Thomas Preud'homme2010-09-14 19:17:39 +02003351ST_FUNC void parse_asm_str(CString *astr)
3352{
3353 skip('(');
3354 /* read the string */
3355 if (tok != TOK_STR)
3356 expect("string constant");
3357 cstr_new(astr);
3358 while (tok == TOK_STR) {
3359 /* XXX: add \0 handling too ? */
3360 cstr_cat(astr, tokc.cstr->data);
3361 next();
3362 }
3363 cstr_ccat(astr, '\0');
3364}
3365
3366/* Parse an asm label and return the label
3367 * Don't forget to free the CString in the caller! */
3368static void asm_label_instr(CString *astr)
3369{
3370 next();
3371 parse_asm_str(astr);
3372 skip(')');
3373#ifdef ASM_DEBUG
3374 printf("asm_alias: \"%s\"\n", (char *)astr->data);
3375#endif
3376}
3377
b3a8eed4 Joe Soroka2011-03-08 12:56:13 -08003378static void post_type(CType *type, AttributeDef *ad)
0d1ed741 grischka2009-05-05 20:18:10 +02003379{
3380 int n, l, t1, arg_size, align;
3381 Sym **plast, *s, *first;
3382 AttributeDef ad1;
3383 CType pt;
3384
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003385 if (tok == '(') {
3386 /* function declaration */
3387 next();
3388 l = 0;
3389 first = NULL;
3390 plast = &first;
3391 arg_size = 0;
3392 if (tok != ')') {
3393 for(;;) {
3394 /* read param name and compute offset */
3395 if (l != FUNC_OLD) {
3396 if (!parse_btype(&pt, &ad1)) {
3397 if (l) {
bf374a5f grischka2011-08-11 17:07:56 +02003398 tcc_error("invalid type");
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003399 } else {
3400 l = FUNC_OLD;
3401 goto old_proto;
3402 }
0d1ed741 grischka2009-05-05 20:18:10 +02003403 }
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003404 l = FUNC_NEW;
3405 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
3406 break;
3407 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
3408 if ((pt.t & VT_BTYPE) == VT_VOID)
bf374a5f grischka2011-08-11 17:07:56 +02003409 tcc_error("parameter declared as void");
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003410 arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE;
3411 } else {
3412 old_proto:
3413 n = tok;
3414 if (n < TOK_UIDENT)
3415 expect("identifier");
3416 pt.t = VT_INT;
3417 next();
0d1ed741 grischka2009-05-05 20:18:10 +02003418 }
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003419 convert_parameter_type(&pt);
3420 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
3421 *plast = s;
3422 plast = &s->next;
3423 if (tok == ')')
0d1ed741 grischka2009-05-05 20:18:10 +02003424 break;
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003425 skip(',');
3426 if (l == FUNC_NEW && tok == TOK_DOTS) {
3427 l = FUNC_ELLIPSIS;
3428 next();
3429 break;
3430 }
0d1ed741 grischka2009-05-05 20:18:10 +02003431 }
3432 }
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003433 /* if no parameters, then old type prototype */
3434 if (l == 0)
3435 l = FUNC_OLD;
3436 skip(')');
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003437 /* NOTE: const is ignored in returned type as it has a special
3438 meaning in gcc / C++ */
9ff91d4c Joe Soroka2011-03-08 15:12:09 -08003439 type->t &= ~VT_CONSTANT;
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003440 /* some ancient pre-K&R C allows a function to return an array
3441 and the array brackets to be put after the arguments, such
9ff91d4c
JS
Joe Soroka2011-03-08 15:12:09 -08003442 that "int c()[]" means something like "int[] c()" */
3443 if (tok == '[') {
3444 next();
3445 skip(']'); /* only handle simple "[]" */
3446 type->t |= VT_PTR;
3447 }
b3a8eed4 Joe Soroka2011-03-08 12:56:13 -08003448 /* we push a anonymous symbol which will contain the function prototype */
3fe2a95d grischka2014-01-07 14:57:07 +01003449 ad->a.func_args = arg_size;
3450 s = sym_push(SYM_FIELD, type, 0, l);
3451 s->a = ad->a;
b3a8eed4 Joe Soroka2011-03-08 12:56:13 -08003452 s->next = first;
810aca9e Joe Soroka2011-04-06 12:08:50 -07003453 type->t = VT_FUNC;
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003454 type->ref = s;
3455 } else if (tok == '[') {
3456 /* array definition */
0d1ed741 grischka2009-05-05 20:18:10 +02003457 next();
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003458 if (tok == TOK_RESTRICT1)
3459 next();
3460 n = -1;
810aca9e Joe Soroka2011-04-06 12:08:50 -07003461 t1 = 0;
b3a8eed4 Joe Soroka2011-03-08 12:56:13 -08003462 if (tok != ']') {
9b52e16a
JS
Joe Soroka2011-07-22 02:09:28 -07003463 if (!local_stack || nocode_wanted)
3464 vpushi(expr_const());
3465 else gexpr();
ace0f7f2
JS
Joe Soroka2011-04-06 09:17:03 -07003466 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
3467 n = vtop->c.i;
ace0f7f2 Joe Soroka2011-04-06 09:17:03 -07003468 if (n < 0)
bf374a5f grischka2011-08-11 17:07:56 +02003469 tcc_error("invalid array size");
ace0f7f2
JS
Joe Soroka2011-04-06 09:17:03 -07003470 } else {
3471 if (!is_integer_btype(vtop->type.t & VT_BTYPE))
bf374a5f grischka2011-08-11 17:07:56 +02003472 tcc_error("size of variable length array should be an integer");
810aca9e Joe Soroka2011-04-06 12:08:50 -07003473 t1 = VT_VLA;
ace0f7f2 Joe Soroka2011-04-06 09:17:03 -07003474 }
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003475 }
3476 skip(']');
3477 /* parse next post type */
b3a8eed4 Joe Soroka2011-03-08 12:56:13 -08003478 post_type(type, ad);
a465b7f5
TP
Thomas Preud'homme2013-09-19 18:58:46 +02003479 if (type->t == VT_FUNC)
3480 tcc_error("declaration of an array of functions");
ace0f7f2 Joe Soroka2011-04-06 09:17:03 -07003481 t1 |= type->t & VT_VLA;
b3a8eed4 Joe Soroka2011-03-08 12:56:13 -08003482
1446b543
JS
Joe Soroka2011-04-09 22:52:25 -07003483 if (t1 & VT_VLA) {
3484 loc -= type_size(&int_type, &align);
3485 loc &= -align;
3486 n = loc;
3487
3488 vla_runtime_type_size(type, &align);
3489 gen_op('*');
44c330d6 Philip2015-04-28 09:23:29 +00003490 vset(&int_type, VT_LOCAL|VT_LVAL, n);
1446b543
JS
Joe Soroka2011-04-09 22:52:25 -07003491 vswap();
3492 vstore();
3493 }
3494 if (n != -1)
3495 vpop();
3496
ace0f7f2 Joe Soroka2011-04-06 09:17:03 -07003497 /* we push an anonymous symbol which will contain the array
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003498 element type */
3499 s = sym_push(SYM_FIELD, type, 0, n);
7c7ca3c6 Joe Soroka2011-04-08 01:09:39 -07003500 type->t = (t1 ? VT_VLA : VT_ARRAY) | VT_PTR;
b3a8eed4
JS
Joe Soroka2011-03-08 12:56:13 -08003501 type->ref = s;
3502 }
0d1ed741 grischka2009-05-05 20:18:10 +02003503}
3504
3505/* Parse a type declaration (except basic type), and return the type
3506 in 'type'. 'td' is a bitmask indicating which kind of type decl is
3507 expected. 'type' should contain the basic type. 'ad' is the
3508 attribute definition of the basic type. It can be modified by
3509 type_decl().
3510 */
3511static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
3512{
3513 Sym *s;
3514 CType type1, *type2;
2358b378 grischka2013-01-06 17:20:44 +01003515 int qualifiers, storage;
3516
0d1ed741 grischka2009-05-05 20:18:10 +02003517 while (tok == '*') {
3518 qualifiers = 0;
3519 redo:
3520 next();
3521 switch(tok) {
3522 case TOK_CONST1:
3523 case TOK_CONST2:
3524 case TOK_CONST3:
3525 qualifiers |= VT_CONSTANT;
3526 goto redo;
3527 case TOK_VOLATILE1:
3528 case TOK_VOLATILE2:
3529 case TOK_VOLATILE3:
3530 qualifiers |= VT_VOLATILE;
3531 goto redo;
3532 case TOK_RESTRICT1:
3533 case TOK_RESTRICT2:
3534 case TOK_RESTRICT3:
3535 goto redo;
3536 }
3537 mk_pointer(type);
3538 type->t |= qualifiers;
3539 }
3540
3541 /* XXX: clarify attribute handling */
3542 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
3543 parse_attribute(ad);
3544
3545 /* recursive type */
3546 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
3547 type1.t = 0; /* XXX: same as int */
3548 if (tok == '(') {
3549 next();
3550 /* XXX: this is not correct to modify 'ad' at this point, but
3551 the syntax is not clear */
3552 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
3553 parse_attribute(ad);
3554 type_decl(&type1, ad, v, td);
3555 skip(')');
3556 } else {
3557 /* type identifier */
3558 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
3559 *v = tok;
3560 next();
3561 } else {
3562 if (!(td & TYPE_ABSTRACT))
3563 expect("identifier");
3564 *v = 0;
3565 }
3566 }
810aca9e
JS
Joe Soroka2011-04-06 12:08:50 -07003567 storage = type->t & VT_STORAGE;
3568 type->t &= ~VT_STORAGE;
85f6fad3 Thomas Preud'homme2012-10-25 18:07:13 +02003569 if (storage & VT_STATIC) {
2358b378 grischka2013-01-06 17:20:44 +01003570 int saved_nocode_wanted = nocode_wanted;
85f6fad3 Thomas Preud'homme2012-10-25 18:07:13 +02003571 nocode_wanted = 1;
2358b378 grischka2013-01-06 17:20:44 +01003572 post_type(type, ad);
508df168 Thomas Preud'homme2012-10-25 20:14:55 +02003573 nocode_wanted = saved_nocode_wanted;
2358b378 grischka2013-01-06 17:20:44 +01003574 } else
3575 post_type(type, ad);
810aca9e Joe Soroka2011-04-06 12:08:50 -07003576 type->t |= storage;
0d1ed741 grischka2009-05-05 20:18:10 +02003577 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
3578 parse_attribute(ad);
4d5105c8 Joe Soroka2011-02-01 00:37:53 -08003579
0d1ed741 grischka2009-05-05 20:18:10 +02003580 if (!type1.t)
3581 return;
3582 /* append type at the end of type1 */
3583 type2 = &type1;
3584 for(;;) {
3585 s = type2->ref;
3586 type2 = &s->type;
3587 if (!type2->t) {
3588 *type2 = *type;
3589 break;
3590 }
3591 }
3592 *type = type1;
3593}
3594
3595/* compute the lvalue VT_LVAL_xxx needed to match type t. */
88a3ccab grischka2009-12-20 01:53:49 +01003596ST_FUNC int lvalue_type(int t)
0d1ed741 grischka2009-05-05 20:18:10 +02003597{
3598 int bt, r;
3599 r = VT_LVAL;
3600 bt = t & VT_BTYPE;
3601 if (bt == VT_BYTE || bt == VT_BOOL)
3602 r |= VT_LVAL_BYTE;
3603 else if (bt == VT_SHORT)
3604 r |= VT_LVAL_SHORT;
3605 else
3606 return r;
3607 if (t & VT_UNSIGNED)
3608 r |= VT_LVAL_UNSIGNED;
3609 return r;
3610}
3611
3612/* indirection with full error checking and bound check */
88a3ccab grischka2009-12-20 01:53:49 +01003613ST_FUNC void indir(void)
0d1ed741 grischka2009-05-05 20:18:10 +02003614{
3615 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
3616 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
3617 return;
3618 expect("pointer");
3619 }
3620 if ((vtop->r & VT_LVAL) && !nocode_wanted)
3621 gv(RC_INT);
3622 vtop->type = *pointed_type(&vtop->type);
3623 /* Arrays and functions are never lvalues */
7c7ca3c6 Joe Soroka2011-04-08 01:09:39 -07003624 if (!(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_VLA)
0d1ed741 grischka2009-05-05 20:18:10 +02003625 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
3626 vtop->r |= lvalue_type(vtop->type.t);
3627 /* if bound checking, the referenced pointer must be checked */
7fa712e0 grischka2009-12-19 22:22:43 +01003628#ifdef CONFIG_TCC_BCHECK
f9181416 grischka2009-05-11 18:45:44 +02003629 if (tcc_state->do_bounds_check)
0d1ed741 grischka2009-05-05 20:18:10 +02003630 vtop->r |= VT_MUSTBOUND;
7fa712e0 grischka2009-12-19 22:22:43 +01003631#endif
0d1ed741 grischka2009-05-05 20:18:10 +02003632 }
3633}
3634
3635/* pass a parameter to a function and do type checking and casting */
3636static void gfunc_param_typed(Sym *func, Sym *arg)
3637{
3638 int func_type;
3639 CType type;
3640
3641 func_type = func->c;
3642 if (func_type == FUNC_OLD ||
3643 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
3644 /* default casting : only need to convert float to double */
3645 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
3646 type.t = VT_DOUBLE;
3647 gen_cast(&type);
17314a1f
TP
Thomas Preud'homme2014-02-04 20:54:28 +08003648 } else if (vtop->type.t & VT_BITFIELD) {
3649 type.t = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
3650 gen_cast(&type);
0d1ed741 grischka2009-05-05 20:18:10 +02003651 }
3652 } else if (arg == NULL) {
bf374a5f grischka2011-08-11 17:07:56 +02003653 tcc_error("too many arguments to function");
0d1ed741 grischka2009-05-05 20:18:10 +02003654 } else {
3655 type = arg->type;
3656 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
3657 gen_assign_cast(&type);
3658 }
3659}
3660
3661/* parse an expression of the form '(type)' or '(expr)' and return its
3662 type */
3663static void parse_expr_type(CType *type)
3664{
3665 int n;
3666 AttributeDef ad;
3667
3668 skip('(');
3669 if (parse_btype(type, &ad)) {
3670 type_decl(type, &ad, &n, TYPE_ABSTRACT);
3671 } else {
3672 expr_type(type);
3673 }
3674 skip(')');
3675}
3676
3677static void parse_type(CType *type)
3678{
3679 AttributeDef ad;
3680 int n;
3681
3682 if (!parse_btype(type, &ad)) {
3683 expect("type");
3684 }
3685 type_decl(type, &ad, &n, TYPE_ABSTRACT);
3686}
3687
3688static void vpush_tokc(int t)
3689{
3690 CType type;
3691 type.t = t;
41e11236 grischka2009-12-19 22:10:13 +01003692 type.ref = 0;
0d1ed741 grischka2009-05-05 20:18:10 +02003693 vsetc(&type, VT_CONST, &tokc);
3694}
3695
88a3ccab grischka2009-12-20 01:53:49 +01003696ST_FUNC void unary(void)
0d1ed741 grischka2009-05-05 20:18:10 +02003697{
8de9b7a6 Thomas Preud'homme2010-04-11 01:53:40 +02003698 int n, t, align, size, r, sizeof_caller;
0d1ed741 grischka2009-05-05 20:18:10 +02003699 CType type;
3700 Sym *s;
3701 AttributeDef ad;
8de9b7a6 Thomas Preud'homme2010-04-11 01:53:40 +02003702 static int in_sizeof = 0;
0d1ed741 grischka2009-05-05 20:18:10 +02003703
8de9b7a6
TP
Thomas Preud'homme2010-04-11 01:53:40 +02003704 sizeof_caller = in_sizeof;
3705 in_sizeof = 0;
0d1ed741 grischka2009-05-05 20:18:10 +02003706 /* XXX: GCC 2.95.3 does not generate a table although it should be
3707 better here */
3708 tok_next:
3709 switch(tok) {
3710 case TOK_EXTENSION:
3711 next();
3712 goto tok_next;
3713 case TOK_CINT:
3714 case TOK_CCHAR:
3715 case TOK_LCHAR:
3716 vpushi(tokc.i);
3717 next();
3718 break;
3719 case TOK_CUINT:
3720 vpush_tokc(VT_INT | VT_UNSIGNED);
3721 next();
3722 break;
3723 case TOK_CLLONG:
3724 vpush_tokc(VT_LLONG);
3725 next();
3726 break;
3727 case TOK_CULLONG:
3728 vpush_tokc(VT_LLONG | VT_UNSIGNED);
3729 next();
3730 break;