began to integrate floating point numbers - separated i386 code generator - fixed...
[tinycc.git] / tcc.c
blob59700f2adf74a0c5d30bc00f29b67a16519aedbb
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #ifndef CONFIG_TCC_STATIC
24 #include <dlfcn.h>
25 #endif
27 //#define DEBUG
28 /* preprocessor debug */
29 //#define PP_DEBUG
31 /* these sizes are dummy for unix, because malloc() does not use
32 memory when the pages are not used */
33 #define TEXT_SIZE (4*1024*1024)
34 #define DATA_SIZE (4*1024*1024)
36 #define INCLUDE_STACK_SIZE 32
37 #define IFDEF_STACK_SIZE 64
38 #define VSTACK_SIZE 64
39 #define STRING_MAX_SIZE 1024
40 #define INCLUDE_PATHS_MAX 32
42 #define TOK_HASH_SIZE 521
43 #define TOK_ALLOC_INCR 256 /* must be a power of two */
44 #define SYM_HASH_SIZE 263
46 /* token symbol management */
47 typedef struct TokenSym {
48 struct TokenSym *hash_next;
49 int tok; /* token number */
50 int len;
51 char str[1];
52 } TokenSym;
54 /* symbol management */
55 typedef struct Sym {
56 int v; /* symbol token */
57 int t; /* associated type */
58 int c; /* associated number */
59 struct Sym *next; /* next related symbol */
60 struct Sym *prev; /* prev symbol in stack */
61 struct Sym *hash_next; /* next symbol in hash table */
62 } Sym;
64 typedef struct SymStack {
65 struct Sym *top;
66 struct Sym *hash[SYM_HASH_SIZE];
67 } SymStack;
69 /* relocation entry (currently only used for functions or variables */
70 typedef struct Reloc {
71 int type; /* type of relocation */
72 int addr; /* address of relocation */
73 struct Reloc *next; /* next relocation */
74 } Reloc;
76 #define RELOC_ADDR32 1 /* 32 bits relocation */
77 #define RELOC_REL32 2 /* 32 bits relative relocation */
80 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
81 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
82 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
84 #define FUNC_NEW 1 /* ansi function prototype */
85 #define FUNC_OLD 2 /* old function prototype */
86 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
88 /* field 'Sym.t' for macros */
89 #define MACRO_OBJ 0 /* object like macro */
90 #define MACRO_FUNC 1 /* function like macro */
92 /* type_decl() types */
93 #define TYPE_ABSTRACT 1 /* type without variable */
94 #define TYPE_DIRECT 2 /* type with variable */
96 typedef struct {
97 FILE *file;
98 char *filename;
99 int line_num;
100 } IncludeFile;
102 /* parser */
103 FILE *file;
104 int ch, ch1, tok, tokc, tok1, tok1c;
106 /* loc : local variable index
107 glo : global variable index
108 ind : output code ptr
109 rsym: return symbol
110 prog: output code
111 anon_sym: anonymous symbol index
113 int rsym, anon_sym,
114 prog, ind, loc, glo, vt, vc, const_wanted, line_num;
115 int global_expr; /* true if compound literals must be allocated
116 globally (used during initializers parsing */
117 int func_vt, func_vc; /* current function return type (used by
118 return instruction) */
119 int tok_ident;
120 TokenSym **table_ident;
121 TokenSym *hash_ident[TOK_HASH_SIZE];
122 char token_buf[STRING_MAX_SIZE + 1];
123 char *filename, *funcname;
124 /* contains global symbols which remain between each translation unit */
125 SymStack extern_stack;
126 SymStack define_stack, global_stack, local_stack, label_stack;
128 int vstack[VSTACK_SIZE], *vstack_ptr;
129 int *macro_ptr, *macro_ptr_allocated;
130 IncludeFile include_stack[INCLUDE_STACK_SIZE], *include_stack_ptr;
131 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
132 char *include_paths[INCLUDE_PATHS_MAX];
133 int nb_include_paths;
135 /* use GNU C extensions */
136 int gnu_ext = 1;
138 /* The current value can be: */
139 #define VT_VALMASK 0x000f
140 #define VT_CONST 0x000a /* constant in vc
141 (must be first non register value) */
142 #define VT_LLOCAL 0x000b /* lvalue, offset on stack */
143 #define VT_LOCAL 0x000c /* offset on stack */
144 #define VT_CMP 0x000d /* the value is stored in processor flags (in vc) */
145 #define VT_JMP 0x000e /* value is the consequence of jmp true */
146 #define VT_JMPI 0x000f /* value is the consequence of jmp false */
147 #define VT_LVAL 0x0010 /* var is an lvalue */
148 #define VT_LVALN -17 /* ~VT_LVAL */
149 #define VT_FORWARD 0x0020 /* value is forward reference
150 (only used for functions) */
151 /* storage */
152 #define VT_EXTERN 0x00000040 /* extern definition */
153 #define VT_STATIC 0x00000080 /* static variable */
154 #define VT_TYPEDEF 0x00000100 /* typedef definition */
156 /* types */
157 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
159 #define VT_BTYPE_SHIFT 9
160 #define VT_INT (0 << VT_BTYPE_SHIFT) /* integer type */
161 #define VT_BYTE (1 << VT_BTYPE_SHIFT) /* signed byte type */
162 #define VT_SHORT (2 << VT_BTYPE_SHIFT) /* short type */
163 #define VT_VOID (3 << VT_BTYPE_SHIFT) /* void type */
164 #define VT_PTR (4 << VT_BTYPE_SHIFT) /* pointer increment */
165 #define VT_ENUM (5 << VT_BTYPE_SHIFT) /* enum definition */
166 #define VT_FUNC (6 << VT_BTYPE_SHIFT) /* function type */
167 #define VT_STRUCT (7 << VT_BTYPE_SHIFT) /* struct/union definition */
168 #define VT_FLOAT (8 << VT_BTYPE_SHIFT) /* IEEE float */
169 #define VT_DOUBLE (9 << VT_BTYPE_SHIFT) /* IEEE double */
170 #define VT_BOOL (10 << VT_BTYPE_SHIFT) /* ISOC99 boolean type */
171 #define VT_BTYPE (0xf << VT_BTYPE_SHIFT) /* mask for basic type */
172 #define VT_UNSIGNED (0x10 << VT_BTYPE_SHIFT) /* unsigned type */
173 #define VT_ARRAY (0x20 << VT_BTYPE_SHIFT) /* array type (also has VT_PTR) */
174 #define VT_BITFIELD (0x40 << VT_BTYPE_SHIFT) /* bitfield modifier */
176 #define VT_TYPE 0xfffffe00 /* type mask */
178 /* token values */
180 /* warning: the following compare tokens depend on i386 asm code */
181 #define TOK_ULT 0x92
182 #define TOK_UGE 0x93
183 #define TOK_EQ 0x94
184 #define TOK_NE 0x95
185 #define TOK_ULE 0x96
186 #define TOK_UGT 0x97
187 #define TOK_LT 0x9c
188 #define TOK_GE 0x9d
189 #define TOK_LE 0x9e
190 #define TOK_GT 0x9f
192 #define TOK_LAND 0xa0
193 #define TOK_LOR 0xa1
195 #define TOK_DEC 0xa2
196 #define TOK_MID 0xa3 /* inc/dec, to void constant */
197 #define TOK_INC 0xa4
198 #define TOK_ARROW 0xa7
199 #define TOK_DOTS 0xa8 /* three dots */
200 #define TOK_SHR 0xa9 /* unsigned shift right */
201 #define TOK_UDIV 0xb0 /* unsigned division */
202 #define TOK_UMOD 0xb1 /* unsigned modulo */
203 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
204 #define TOK_NUM 0xb3 /* number in tokc */
205 #define TOK_CCHAR 0xb4 /* char constant in tokc */
206 #define TOK_STR 0xb5 /* pointer to string in tokc */
207 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
208 #define TOK_LCHAR 0xb7
209 #define TOK_LSTR 0xb8
211 #define TOK_SHL 0x01 /* shift left */
212 #define TOK_SAR 0x02 /* signed shift right */
214 /* assignement operators : normal operator or 0x80 */
215 #define TOK_A_MOD 0xa5
216 #define TOK_A_AND 0xa6
217 #define TOK_A_MUL 0xaa
218 #define TOK_A_ADD 0xab
219 #define TOK_A_SUB 0xad
220 #define TOK_A_DIV 0xaf
221 #define TOK_A_XOR 0xde
222 #define TOK_A_OR 0xfc
223 #define TOK_A_SHL 0x81
224 #define TOK_A_SAR 0x82
226 /* all identificators and strings have token above that */
227 #define TOK_IDENT 256
229 enum {
230 TOK_INT = TOK_IDENT,
231 TOK_VOID,
232 TOK_CHAR,
233 TOK_IF,
234 TOK_ELSE,
235 TOK_WHILE,
236 TOK_BREAK,
237 TOK_RETURN,
238 TOK_FOR,
239 TOK_EXTERN,
240 TOK_STATIC,
241 TOK_UNSIGNED,
242 TOK_GOTO,
243 TOK_DO,
244 TOK_CONTINUE,
245 TOK_SWITCH,
246 TOK_CASE,
248 /* ignored types Must have contiguous values */
249 TOK_CONST,
250 TOK_VOLATILE,
251 TOK_LONG,
252 TOK_REGISTER,
253 TOK_SIGNED,
254 TOK_AUTO,
255 TOK_INLINE,
256 TOK_RESTRICT,
258 /* unsupported type */
259 TOK_FLOAT,
260 TOK_DOUBLE,
261 TOK_BOOL,
263 TOK_SHORT,
264 TOK_STRUCT,
265 TOK_UNION,
266 TOK_TYPEDEF,
267 TOK_DEFAULT,
268 TOK_ENUM,
269 TOK_SIZEOF,
271 /* preprocessor only */
272 TOK_UIDENT, /* first "user" ident (not keyword) */
273 TOK_DEFINE = TOK_UIDENT,
274 TOK_INCLUDE,
275 TOK_IFDEF,
276 TOK_IFNDEF,
277 TOK_ELIF,
278 TOK_ENDIF,
279 TOK_DEFINED,
280 TOK_UNDEF,
281 TOK_ERROR,
282 TOK_LINE,
283 TOK___LINE__,
284 TOK___FILE__,
285 TOK___DATE__,
286 TOK___TIME__,
287 TOK___VA_ARGS__,
289 /* special identifiers */
290 TOK___FUNC__,
291 TOK_MAIN,
294 void sum();
295 void next(void);
296 void next_nomacro();
297 int expr_const();
298 void expr_eq();
299 void expr(void);
300 void decl(int l);
301 void decl_initializer(int t, int c, int first, int size_only);
302 int decl_initializer_alloc(int t, int has_init);
303 int gv(void);
304 void move_reg(int r, int s);
305 void save_reg(int r);
306 void vpush(void);
307 void vpop(int *ft, int *fc);
308 void vswap(void);
309 int get_reg(int rc);
311 void macro_subst(int **tok_str, int *tok_len,
312 Sym **nested_list, int *macro_str);
313 int save_reg_forced(int r);
314 void gen_op(int op);
315 void gen_cast(int t);
316 void vstore(void);
317 int type_size(int t, int *a);
318 int pointed_type(int t);
319 int pointed_size(int t);
320 int ist(void);
321 int type_decl(int *v, int t, int td);
323 #ifdef CONFIG_TCC_STATIC
325 #define RTLD_LAZY 0x001
326 #define RTLD_NOW 0x002
327 #define RTLD_GLOBAL 0x100
329 /* dummy function for profiling */
330 void *dlopen(const char *filename, int flag)
332 return NULL;
335 const char *dlerror(void)
337 return "error";
340 typedef struct TCCSyms {
341 char *str;
342 void *ptr;
343 } TCCSyms;
345 #define TCCSYM(a) { #a, &a, },
347 /* add the symbol you want here if no dynamic linking is done */
348 static TCCSyms tcc_syms[] = {
349 TCCSYM(printf)
350 TCCSYM(fprintf)
351 TCCSYM(fopen)
352 TCCSYM(fclose)
353 { NULL, NULL },
356 void *dlsym(void *handle, char *symbol)
358 TCCSyms *p;
359 p = tcc_syms;
360 while (p->str != NULL) {
361 if (!strcmp(p->str, symbol))
362 return p->ptr;
363 p++;
365 return NULL;
368 #endif
370 inline int isid(int c)
372 return (c >= 'a' && c <= 'z') ||
373 (c >= 'A' && c <= 'Z') ||
374 c == '_';
377 inline int isnum(int c)
379 return c >= '0' & c <= '9';
382 void printline(void)
384 IncludeFile *f;
385 for(f = include_stack; f < include_stack_ptr; f++)
386 fprintf(stderr, "In file included from %s:%d:\n",
387 f->filename, f->line_num);
388 fprintf(stderr, "%s:%d: ", filename, line_num);
391 void error(const char *fmt, ...)
393 va_list ap;
394 va_start(ap, fmt);
395 printline();
396 vfprintf(stderr, fmt, ap);
397 fprintf(stderr, "\n");
398 exit(1);
399 va_end(ap);
402 void expect(const char *msg)
404 error("%s expected", msg);
407 void warning(const char *msg)
409 printline();
410 fprintf(stderr, "warning: %s\n", msg);
413 void skip(int c)
415 if (tok != c)
416 error("'%c' expected", c);
417 next();
420 void test_lvalue(void)
422 if (!(vt & VT_LVAL))
423 expect("lvalue");
426 TokenSym *tok_alloc(char *str, int len)
428 TokenSym *ts, **pts, **ptable;
429 int h, i;
431 if (len <= 0)
432 len = strlen(str);
433 h = 1;
434 for(i=0;i<len;i++)
435 h = ((h << 8) | (str[i] & 0xff)) % TOK_HASH_SIZE;
437 pts = &hash_ident[h];
438 while (1) {
439 ts = *pts;
440 if (!ts)
441 break;
442 if (ts->len == len && !memcmp(ts->str, str, len))
443 return ts;
444 pts = &(ts->hash_next);
447 if (tok_ident >= SYM_FIRST_ANOM)
448 error("memory full");
450 /* expand token table if needed */
451 i = tok_ident - TOK_IDENT;
452 if ((i % TOK_ALLOC_INCR) == 0) {
453 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
454 if (!ptable)
455 error("memory full");
456 table_ident = ptable;
459 ts = malloc(sizeof(TokenSym) + len);
460 if (!ts)
461 error("memory full");
462 table_ident[i] = ts;
463 ts->tok = tok_ident++;
464 ts->len = len;
465 ts->hash_next = NULL;
466 memcpy(ts->str, str, len + 1);
467 *pts = ts;
468 return ts;
471 void add_char(char **pp, int c)
473 char *p;
474 p = *pp;
475 if (c == '\'' || c == '\"' || c == '\\') {
476 /* XXX: could be more precise if char or string */
477 *p++ = '\\';
479 if (c >= 32 && c <= 126) {
480 *p++ = c;
481 } else {
482 *p++ = '\\';
483 if (c == '\n') {
484 *p++ = 'n';
485 } else {
486 *p++ = '0' + ((c >> 6) & 7);
487 *p++ = '0' + ((c >> 3) & 7);
488 *p++ = '0' + (c & 7);
491 *pp = p;
494 /* XXX: buffer overflow */
495 char *get_tok_str(int v, int c)
497 static char buf[STRING_MAX_SIZE + 1];
498 TokenSym *ts;
499 char *p;
500 int i;
502 if (v == TOK_NUM) {
503 sprintf(buf, "%d", c);
504 return buf;
505 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
506 p = buf;
507 *p++ = '\'';
508 add_char(&p, c);
509 *p++ = '\'';
510 *p = '\0';
511 return buf;
512 } else if (v == TOK_STR || v == TOK_LSTR) {
513 ts = (TokenSym *)c;
514 p = buf;
515 *p++ = '\"';
516 for(i=0;i<ts->len;i++)
517 add_char(&p, ts->str[i]);
518 *p++ = '\"';
519 *p = '\0';
520 return buf;
521 } else if (v < TOK_IDENT) {
522 p = buf;
523 *p++ = v;
524 *p = '\0';
525 return buf;
526 } else if (v < tok_ident) {
527 return table_ident[v - TOK_IDENT]->str;
528 } else {
529 /* should never happen */
530 return NULL;
534 /* push, without hashing */
535 Sym *sym_push2(Sym **ps, int v, int t, int c)
537 Sym *s;
538 s = malloc(sizeof(Sym));
539 if (!s)
540 error("memory full");
541 s->v = v;
542 s->t = t;
543 s->c = c;
544 s->next = NULL;
545 /* add in stack */
546 s->prev = *ps;
547 *ps = s;
548 return s;
551 /* find a symbol and return its associated structure. 's' is the top
552 of the symbol stack */
553 Sym *sym_find2(Sym *s, int v)
555 while (s) {
556 if (s->v == v)
557 return s;
558 s = s->prev;
560 return NULL;
563 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
565 /* find a symbol and return its associated structure. 'st' is the
566 symbol stack */
567 Sym *sym_find1(SymStack *st, int v)
569 Sym *s;
571 s = st->hash[HASH_SYM(v)];
572 while (s) {
573 if (s->v == v)
574 return s;
575 s = s->hash_next;
577 return 0;
580 Sym *sym_push1(SymStack *st, int v, int t, int c)
582 Sym *s, **ps;
583 s = sym_push2(&st->top, v, t, c);
584 /* add in hash table */
585 if (v) {
586 ps = &st->hash[HASH_SYM(v)];
587 s->hash_next = *ps;
588 *ps = s;
590 return s;
593 /* find a symbol in the right symbol space */
594 Sym *sym_find(int v)
596 Sym *s;
597 s = sym_find1(&local_stack, v);
598 if (!s)
599 s = sym_find1(&global_stack, v);
600 return s;
603 /* push a given symbol on the symbol stack */
604 Sym *sym_push(int v, int t, int c)
606 if (local_stack.top)
607 return sym_push1(&local_stack, v, t, c);
608 else
609 return sym_push1(&global_stack, v, t, c);
612 /* pop symbols until top reaches 'b' */
613 void sym_pop(SymStack *st, Sym *b)
615 Sym *s, *ss;
617 s = st->top;
618 while(s != b) {
619 ss = s->prev;
620 /* free hash table entry, except if symbol was freed (only
621 used for #undef symbols) */
622 if (s->v)
623 st->hash[HASH_SYM(s->v)] = s->hash_next;
624 free(s);
625 s = ss;
627 st->top = b;
630 /* undefined a hashed symbol (used for #undef). Its name is set to
631 zero */
632 void sym_undef(SymStack *st, Sym *s)
634 Sym **ss;
635 ss = &st->hash[HASH_SYM(s->v)];
636 while (*ss != NULL) {
637 if (*ss == s)
638 break;
639 ss = &(*ss)->hash_next;
641 *ss = s->hash_next;
642 s->v = 0;
645 /* no need to put that inline */
646 int handle_eof(void)
648 if (include_stack_ptr == include_stack)
649 return -1;
650 /* pop include stack */
651 fclose(file);
652 free(filename);
653 include_stack_ptr--;
654 file = include_stack_ptr->file;
655 filename = include_stack_ptr->filename;
656 line_num = include_stack_ptr->line_num;
657 return 0;
660 /* read next char from current input file */
661 static inline void inp(void)
663 redo:
664 /* faster than fgetc */
665 ch1 = getc_unlocked(file);
666 if (ch1 == -1) {
667 if (handle_eof() < 0)
668 return;
669 else
670 goto redo;
672 if (ch1 == '\n')
673 line_num++;
674 // printf("ch1=%c 0x%x\n", ch1, ch1);
677 /* input with '\\n' handling */
678 static inline void minp(void)
680 redo:
681 ch = ch1;
682 inp();
683 if (ch == '\\' && ch1 == '\n') {
684 inp();
685 goto redo;
687 //printf("ch=%c 0x%x\n", ch, ch);
691 /* same as minp, but also skip comments */
692 void cinp(void)
694 int c;
696 if (ch1 == '/') {
697 inp();
698 if (ch1 == '/') {
699 /* single line C++ comments */
700 inp();
701 while (ch1 != '\n' && ch1 != -1)
702 inp();
703 inp();
704 ch = ' '; /* return space */
705 } else if (ch1 == '*') {
706 /* C comments */
707 inp();
708 while (ch1 != -1) {
709 c = ch1;
710 inp();
711 if (c == '*' && ch1 == '/') {
712 inp();
713 ch = ' '; /* return space */
714 break;
717 } else {
718 ch = '/';
720 } else {
721 minp();
725 void skip_spaces(void)
727 while (ch == ' ' || ch == '\t')
728 cinp();
731 /* skip block of text until #else, #elif or #endif. skip also pairs of
732 #if/#endif */
733 void preprocess_skip()
735 int a;
736 a = 0;
737 while (1) {
738 while (ch != '\n') {
739 if (ch == -1)
740 expect("#endif");
741 cinp();
743 cinp();
744 skip_spaces();
745 if (ch == '#') {
746 cinp();
747 next_nomacro();
748 if (a == 0 &&
749 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
750 break;
751 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
752 a++;
753 else if (tok == TOK_ENDIF)
754 a--;
759 inline int is_long_tok(int t)
761 return (t == TOK_NUM ||
762 t == TOK_CCHAR || t == TOK_LCHAR ||
763 t == TOK_STR || t == TOK_LSTR);
766 void tok_add(int **tok_str, int *tok_len, int t)
768 int len, *str;
769 len = *tok_len;
770 str = *tok_str;
771 if ((len & 63) == 0) {
772 str = realloc(str, (len + 64) * sizeof(int));
773 if (!str)
774 return;
775 *tok_str = str;
777 str[len++] = t;
778 *tok_len = len;
781 void tok_add2(int **tok_str, int *tok_len, int t, int c)
783 tok_add(tok_str, tok_len, t);
784 if (is_long_tok(t))
785 tok_add(tok_str, tok_len, c);
788 /* eval an expression for #if/#elif */
789 int expr_preprocess()
791 int *str, len, c, t;
793 str = NULL;
794 len = 0;
795 while (1) {
796 skip_spaces();
797 if (ch == '\n')
798 break;
799 next(); /* do macro subst */
800 if (tok == TOK_DEFINED) {
801 next_nomacro();
802 t = tok;
803 if (t == '(')
804 next_nomacro();
805 c = sym_find1(&define_stack, tok) != 0;
806 if (t == '(')
807 next_nomacro();
808 tok = TOK_NUM;
809 tokc = c;
810 } else if (tok >= TOK_IDENT) {
811 /* if undefined macro */
812 tok = TOK_NUM;
813 tokc = 0;
815 tok_add2(&str, &len, tok, tokc);
817 tok_add(&str, &len, -1); /* simulate end of file */
818 tok_add(&str, &len, 0);
819 /* now evaluate C constant expression */
820 macro_ptr = str;
821 next();
822 c = expr_const();
823 macro_ptr = NULL;
824 free(str);
825 return c != 0;
828 #ifdef DEBUG
829 void tok_print(int *str)
831 int t, c;
833 while (1) {
834 t = *str++;
835 if (!t)
836 break;
837 c = 0;
838 if (is_long_tok(t))
839 c = *str++;
840 printf(" %s", get_tok_str(t, c));
842 printf("\n");
844 #endif
846 /* XXX: should be more factorized */
847 void define_symbol(char *sym)
849 TokenSym *ts;
850 int *str, len;
852 ts = tok_alloc(sym, 0);
853 str = NULL;
854 len = 0;
855 tok_add2(&str, &len, TOK_NUM, 1);
856 tok_add(&str, &len, 0);
857 sym_push1(&define_stack, ts->tok, MACRO_OBJ, (int)str);
860 void preprocess()
862 int size, i, c, v, t, *str, len;
863 char buf[1024], *q, *p;
864 char buf1[1024];
865 FILE *f;
866 Sym **ps, *first, *s;
868 cinp();
869 next_nomacro();
870 redo:
871 if (tok == TOK_DEFINE) {
872 next_nomacro();
873 v = tok;
874 /* XXX: should check if same macro (ANSI) */
875 first = NULL;
876 t = MACRO_OBJ;
877 /* '(' must be just after macro definition for MACRO_FUNC */
878 if (ch == '(') {
879 next_nomacro();
880 next_nomacro();
881 ps = &first;
882 while (tok != ')') {
883 if (tok == TOK_DOTS)
884 tok = TOK___VA_ARGS__;
885 s = sym_push1(&define_stack, tok | SYM_FIELD, 0, 0);
886 *ps = s;
887 ps = &s->next;
888 next_nomacro();
889 if (tok != ',')
890 break;
891 next_nomacro();
893 t = MACRO_FUNC;
895 str = NULL;
896 len = 0;
897 while (1) {
898 skip_spaces();
899 if (ch == '\n' || ch == -1)
900 break;
901 next_nomacro();
902 tok_add2(&str, &len, tok, tokc);
904 tok_add(&str, &len, 0);
905 #ifdef PP_DEBUG
906 printf("define %s %d: ", get_tok_str(v, 0), t);
907 tok_print(str);
908 #endif
909 s = sym_push1(&define_stack, v, t, (int)str);
910 s->next = first;
911 } else if (tok == TOK_UNDEF) {
912 next_nomacro();
913 s = sym_find1(&define_stack, tok);
914 /* undefine symbol by putting an invalid name */
915 if (s)
916 sym_undef(&define_stack, s);
917 } else if (tok == TOK_INCLUDE) {
918 skip_spaces();
919 if (ch == '<') {
920 c = '>';
921 goto read_name;
922 } else if (ch == '\"') {
923 c = ch;
924 read_name:
925 minp();
926 q = buf;
927 while (ch != c && ch != '\n' && ch != -1) {
928 if ((q - buf) < sizeof(buf) - 1)
929 *q++ = ch;
930 minp();
932 *q = '\0';
933 } else {
934 next();
935 if (tok != TOK_STR)
936 error("#include syntax error");
937 /* XXX: buffer overflow */
938 strcpy(buf, get_tok_str(tok, tokc));
939 c = '\"';
941 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
942 error("memory full");
943 if (c == '\"') {
944 /* first search in current dir if "header.h" */
945 /* XXX: buffer overflow */
946 size = 0;
947 p = strrchr(filename, '/');
948 if (p)
949 size = p + 1 - filename;
950 memcpy(buf1, filename, size);
951 buf1[size] = '\0';
952 strcat(buf1, buf);
953 f = fopen(buf1, "r");
954 if (f)
955 goto found;
957 /* now search in standard include path */
958 for(i=nb_include_paths - 1;i>=0;i--) {
959 strcpy(buf1, include_paths[i]);
960 strcat(buf1, "/");
961 strcat(buf1, buf);
962 f = fopen(buf1, "r");
963 if (f)
964 goto found;
966 error("include file '%s' not found", buf1);
967 f = NULL;
968 found:
969 /* push current file in stack */
970 /* XXX: fix current line init */
971 include_stack_ptr->file = file;
972 include_stack_ptr->filename = filename;
973 include_stack_ptr->line_num = line_num;
974 include_stack_ptr++;
975 file = f;
976 filename = strdup(buf1);
977 line_num = 1;
978 } else if (tok == TOK_IFNDEF) {
979 c = 1;
980 goto do_ifdef;
981 } else if (tok == TOK_IF) {
982 c = expr_preprocess();
983 goto do_if;
984 } else if (tok == TOK_IFDEF) {
985 c = 0;
986 do_ifdef:
987 next_nomacro();
988 c = (sym_find1(&define_stack, tok) != 0) ^ c;
989 do_if:
990 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
991 error("memory full");
992 *ifdef_stack_ptr++ = c;
993 goto test_skip;
994 } else if (tok == TOK_ELSE) {
995 if (ifdef_stack_ptr == ifdef_stack ||
996 (ifdef_stack_ptr[-1] & 2))
997 error("#else after #else");
998 c = (ifdef_stack_ptr[-1] ^= 3);
999 goto test_skip;
1000 } else if (tok == TOK_ELIF) {
1001 if (ifdef_stack_ptr == ifdef_stack ||
1002 ifdef_stack_ptr[-1] > 1)
1003 error("#elif after #else");
1004 c = expr_preprocess();
1005 ifdef_stack_ptr[-1] = c;
1006 test_skip:
1007 if (!(c & 1)) {
1008 preprocess_skip();
1009 goto redo;
1011 } else if (tok == TOK_ENDIF) {
1012 if (ifdef_stack_ptr == ifdef_stack)
1013 expect("#if");
1014 ifdef_stack_ptr--;
1015 } else if (tok == TOK_LINE) {
1016 next();
1017 if (tok != TOK_NUM)
1018 error("#line");
1019 line_num = tokc;
1020 skip_spaces();
1021 if (ch != '\n') {
1022 next();
1023 if (tok != TOK_STR)
1024 error("#line");
1025 /* XXX: potential memory leak */
1026 filename = strdup(get_tok_str(tok, tokc));
1028 } else if (tok == TOK_ERROR) {
1029 error("#error");
1031 /* ignore other preprocess commands or #! for C scripts */
1032 while (ch != '\n' && ch != -1)
1033 cinp();
1036 /* read a number in base b */
1037 int getn(b)
1039 int n, t;
1040 n = 0;
1041 while (1) {
1042 if (ch >= 'a' & ch <= 'f')
1043 t = ch - 'a' + 10;
1044 else if (ch >= 'A' & ch <= 'F')
1045 t = ch - 'A' + 10;
1046 else if (isnum(ch))
1047 t = ch - '0';
1048 else
1049 break;
1050 if (t < 0 | t >= b)
1051 break;
1052 n = n * b + t;
1053 cinp();
1055 return n;
1058 /* read a character for string or char constant and eval escape codes */
1059 int getq()
1061 int c;
1063 c = ch;
1064 minp();
1065 if (c == '\\') {
1066 if (isnum(ch)) {
1067 /* at most three octal digits */
1068 c = ch - '0';
1069 minp();
1070 if (isnum(ch)) {
1071 c = c * 8 + ch - '0';
1072 minp();
1073 if (isnum(ch)) {
1074 c = c * 8 + ch - '0';
1075 minp();
1078 return c;
1079 } else if (ch == 'x') {
1080 minp();
1081 return getn(16);
1082 } else {
1083 if (ch == 'a')
1084 c = '\a';
1085 else if (ch == 'b')
1086 c = '\b';
1087 else if (ch == 'f')
1088 c = '\f';
1089 else if (ch == 'n')
1090 c = '\n';
1091 else if (ch == 'r')
1092 c = '\r';
1093 else if (ch == 't')
1094 c = '\t';
1095 else if (ch == 'v')
1096 c = '\v';
1097 else if (ch == 'e' && gnu_ext)
1098 c = 27;
1099 else if (ch == '\'' || ch == '\"' || ch == '\\')
1100 c = ch;
1101 else
1102 error("invalid escaped char");
1103 minp();
1106 return c;
1109 /* return next token without macro substitution */
1110 void next_nomacro1()
1112 int b;
1113 char *q;
1114 TokenSym *ts;
1116 /* skip spaces */
1117 while(1) {
1118 while (ch == '\n') {
1119 cinp();
1120 while (ch == ' ' || ch == 9)
1121 cinp();
1122 if (ch == '#') {
1123 /* preprocessor command if # at start of line after
1124 spaces */
1125 preprocess();
1128 if (ch != ' ' && ch != '\t' && ch != '\f')
1129 break;
1130 cinp();
1132 if (isid(ch)) {
1133 q = token_buf;
1134 *q++ = ch;
1135 cinp();
1136 if (q[-1] == 'L') {
1137 if (ch == '\'') {
1138 tok = TOK_LCHAR;
1139 goto char_const;
1141 if (ch == '\"') {
1142 tok = TOK_LSTR;
1143 goto str_const;
1146 while (isid(ch) || isnum(ch)) {
1147 if (q >= token_buf + STRING_MAX_SIZE)
1148 error("ident too long");
1149 *q++ = ch;
1150 cinp();
1152 *q = '\0';
1153 ts = tok_alloc(token_buf, q - token_buf);
1154 tok = ts->tok;
1155 } else if (isnum(ch)) {
1156 /* number */
1157 b = 10;
1158 if (ch == '0') {
1159 cinp();
1160 b = 8;
1161 if (ch == 'x' || ch == 'X') {
1162 cinp();
1163 b = 16;
1164 } else if (ch == 'b' || ch == 'B') {
1165 cinp();
1166 b = 2;
1169 tokc = getn(b);
1170 /* XXX: add unsigned constant support (ANSI) */
1171 while (ch == 'L' || ch == 'l' || ch == 'U' || ch == 'u')
1172 cinp();
1173 tok = TOK_NUM;
1174 } else if (ch == '\'') {
1175 tok = TOK_CCHAR;
1176 char_const:
1177 minp();
1178 tokc = getq();
1179 if (ch != '\'')
1180 expect("\'");
1181 minp();
1182 } else if (ch == '\"') {
1183 tok = TOK_STR;
1184 str_const:
1185 minp();
1186 q = token_buf;
1187 while (ch != '\"') {
1188 b = getq();
1189 if (ch == -1)
1190 error("unterminated string");
1191 if (q >= token_buf + STRING_MAX_SIZE)
1192 error("string too long");
1193 *q++ = b;
1195 *q = '\0';
1196 tokc = (int)tok_alloc(token_buf, q - token_buf);
1197 minp();
1198 } else {
1199 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\247..\250##\266";
1200 /* two chars */
1201 tok = ch;
1202 cinp();
1203 while (*q) {
1204 if (*q == tok & q[1] == ch) {
1205 cinp();
1206 tok = q[2] & 0xff;
1207 /* three chars tests */
1208 if (tok == TOK_SHL | tok == TOK_SAR) {
1209 if (ch == '=') {
1210 tok = tok | 0x80;
1211 cinp();
1213 } else if (tok == TOK_DOTS) {
1214 if (ch != '.')
1215 error("parse error");
1216 cinp();
1218 return;
1220 q = q + 3;
1222 /* single char substitutions */
1223 if (tok == '<')
1224 tok = TOK_LT;
1225 else if (tok == '>')
1226 tok = TOK_GT;
1230 /* return next token without macro substitution. Can read input from
1231 macro_ptr buffer */
1232 void next_nomacro()
1234 if (macro_ptr) {
1235 tok = *macro_ptr;
1236 if (tok) {
1237 macro_ptr++;
1238 if (is_long_tok(tok))
1239 tokc = *macro_ptr++;
1241 } else {
1242 next_nomacro1();
1246 /* substitute args in macro_str and return allocated string */
1247 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
1249 int *st, last_tok, t, c, notfirst, *str, len;
1250 Sym *s;
1251 TokenSym *ts;
1253 str = NULL;
1254 len = 0;
1255 last_tok = 0;
1256 while(1) {
1257 t = *macro_str++;
1258 if (!t)
1259 break;
1260 if (t == '#') {
1261 /* stringize */
1262 t = *macro_str++;
1263 if (!t)
1264 break;
1265 s = sym_find2(args, t);
1266 if (s) {
1267 token_buf[0] = '\0';
1268 st = (int *)s->c;
1269 /* XXX: buffer overflow */
1270 notfirst = 0;
1271 while (*st) {
1272 if (notfirst)
1273 strcat(token_buf, " ");
1274 t = *st++;
1275 c = 0;
1276 if (is_long_tok(t))
1277 c = *st++;
1278 strcat(token_buf, get_tok_str(t, c));
1279 notfirst = 1;
1281 #ifdef PP_DEBUG
1282 printf("stringize: %s\n", token_buf);
1283 #endif
1284 /* add string */
1285 ts = tok_alloc(token_buf, 0);
1286 tok_add2(&str, &len, TOK_STR, (int)ts);
1287 } else {
1288 tok_add(&str, &len, t);
1290 } else if (is_long_tok(t)) {
1291 tok_add2(&str, &len, t, *macro_str++);
1292 } else {
1293 s = sym_find2(args, t);
1294 if (s) {
1295 st = (int *)s->c;
1296 /* if '##' is present before or after , no arg substitution */
1297 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
1298 while (*st)
1299 tok_add(&str, &len, *st++);
1300 } else {
1301 macro_subst(&str, &len, nested_list, st);
1303 } else {
1304 tok_add(&str, &len, t);
1307 last_tok = t;
1309 tok_add(&str, &len, 0);
1310 return str;
1313 /* handle the '##' operator */
1314 int *macro_twosharps(int *macro_str)
1316 TokenSym *ts;
1317 int *macro_str1, macro_str1_len, *macro_ptr1;
1318 int t, c;
1319 char *p;
1321 macro_str1 = NULL;
1322 macro_str1_len = 0;
1323 tok = 0;
1324 while (1) {
1325 next_nomacro();
1326 if (tok == 0)
1327 break;
1328 if (*macro_ptr == TOK_TWOSHARPS) {
1329 macro_ptr++;
1330 macro_ptr1 = macro_ptr;
1331 t = *macro_ptr;
1332 if (t) {
1333 macro_ptr++;
1334 c = 0;
1335 if (is_long_tok(t))
1336 c = *macro_ptr++;
1337 /* XXX: we handle only most common cases:
1338 ident + ident or ident + number */
1339 if (tok >= TOK_IDENT &&
1340 (t >= TOK_IDENT || t == TOK_NUM)) {
1341 /* XXX: buffer overflow */
1342 p = get_tok_str(tok, tokc);
1343 strcpy(token_buf, p);
1344 p = get_tok_str(t, c);
1345 strcat(token_buf, p);
1346 ts = tok_alloc(token_buf, 0);
1347 tok_add2(&macro_str1, &macro_str1_len, ts->tok, 0);
1348 } else {
1349 /* cannot merge tokens: skip '##' */
1350 macro_ptr = macro_ptr1;
1353 } else {
1354 tok_add2(&macro_str1, &macro_str1_len, tok, tokc);
1357 tok_add(&macro_str1, &macro_str1_len, 0);
1358 return macro_str1;
1363 /* do macro substitution of macro_str and add result to
1364 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1365 substituted. 'nested_list' is the list of all macros we got inside
1366 to avoid recursing. */
1367 void macro_subst(int **tok_str, int *tok_len,
1368 Sym **nested_list, int *macro_str)
1370 Sym *s, *args, *sa, *sa1;
1371 int *str, parlevel, len, *mstr, t, *saved_macro_ptr;
1372 int mstr_allocated, *macro_str1;
1374 saved_macro_ptr = macro_ptr;
1375 macro_ptr = macro_str;
1376 macro_str1 = NULL;
1377 if (macro_str) {
1378 /* first scan for '##' operator handling */
1379 macro_str1 = macro_twosharps(macro_str);
1380 macro_ptr = macro_str1;
1383 while (1) {
1384 next_nomacro();
1385 if (tok == 0)
1386 break;
1387 /* special macros */
1388 if (tok == TOK___LINE__) {
1389 tok_add2(tok_str, tok_len, TOK_NUM, line_num);
1390 } else if (tok == TOK___FILE__) {
1391 tok_add2(tok_str, tok_len, TOK_STR,
1392 (int)tok_alloc(filename, 0));
1393 } else if (tok == TOK___DATE__) {
1394 tok_add2(tok_str, tok_len, TOK_STR,
1395 (int)tok_alloc("Jan 1 1970", 0));
1396 } else if (tok == TOK___TIME__) {
1397 tok_add2(tok_str, tok_len, TOK_STR,
1398 (int)tok_alloc("00:00:00", 0));
1399 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
1400 /* if symbol is a macro, prepare substitution */
1401 /* if nested substitution, do nothing */
1402 if (sym_find2(*nested_list, tok))
1403 goto no_subst;
1404 mstr = (int *)s->c;
1405 mstr_allocated = 0;
1406 if (s->t == MACRO_FUNC) {
1407 /* NOTE: we do not use next_nomacro to avoid eating the
1408 next token. XXX: find better solution */
1409 if (macro_ptr) {
1410 t = *macro_ptr;
1411 } else {
1412 while (ch == ' ' || ch == '\t' || ch == '\n')
1413 cinp();
1414 t = ch;
1416 if (t != '(') /* no macro subst */
1417 goto no_subst;
1419 /* argument macro */
1420 next_nomacro();
1421 next_nomacro();
1422 args = NULL;
1423 sa = s->next;
1424 while (tok != ')' && sa) {
1425 len = 0;
1426 str = NULL;
1427 parlevel = 0;
1428 while ((parlevel > 0 ||
1429 (tok != ')' &&
1430 (tok != ',' ||
1431 sa->v == (TOK___VA_ARGS__ | SYM_FIELD)))) &&
1432 tok != -1) {
1433 if (tok == '(')
1434 parlevel++;
1435 else if (tok == ')')
1436 parlevel--;
1437 tok_add2(&str, &len, tok, tokc);
1438 next_nomacro();
1440 tok_add(&str, &len, 0);
1441 sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
1442 if (tok != ',')
1443 break;
1444 next_nomacro();
1445 sa = sa->next;
1447 if (tok != ')')
1448 expect(")");
1449 /* now subst each arg */
1450 mstr = macro_arg_subst(nested_list, mstr, args);
1451 /* free memory */
1452 sa = args;
1453 while (sa) {
1454 sa1 = sa->prev;
1455 free((int *)sa->c);
1456 free(sa);
1457 sa = sa1;
1459 mstr_allocated = 1;
1461 sym_push2(nested_list, s->v, 0, 0);
1462 macro_subst(tok_str, tok_len, nested_list, mstr);
1463 /* pop nested defined symbol */
1464 sa1 = *nested_list;
1465 *nested_list = sa1->prev;
1466 free(sa1);
1467 if (mstr_allocated)
1468 free(mstr);
1469 } else {
1470 no_subst:
1471 /* no need to add if reading input stream */
1472 if (!macro_str)
1473 return;
1474 tok_add2(tok_str, tok_len, tok, tokc);
1476 /* only replace one macro while parsing input stream */
1477 if (!macro_str)
1478 return;
1480 macro_ptr = saved_macro_ptr;
1481 if (macro_str1)
1482 free(macro_str1);
1485 /* return next token with macro substitution */
1486 void next(void)
1488 int len, *ptr;
1489 Sym *nested_list;
1491 /* special 'ungettok' case for label parsing */
1492 if (tok1) {
1493 tok = tok1;
1494 tokc = tok1c;
1495 tok1 = 0;
1496 } else {
1497 redo:
1498 if (!macro_ptr) {
1499 /* if not reading from macro substuted string, then try to substitute */
1500 len = 0;
1501 ptr = NULL;
1502 nested_list = NULL;
1503 macro_subst(&ptr, &len, &nested_list, NULL);
1504 if (ptr) {
1505 tok_add(&ptr, &len, 0);
1506 macro_ptr = ptr;
1507 macro_ptr_allocated = ptr;
1508 goto redo;
1510 if (tok == 0)
1511 goto redo;
1512 } else {
1513 next_nomacro();
1514 if (tok == 0) {
1515 /* end of macro string: free it */
1516 free(macro_ptr_allocated);
1517 macro_ptr = NULL;
1518 goto redo;
1522 #if defined(DEBUG)
1523 printf("token = %s\n", get_tok_str(tok, tokc));
1524 #endif
1527 void swap(int *p, int *q)
1529 int t;
1530 t = *p;
1531 *p = *q;
1532 *q = t;
1535 void vset(int t, int v)
1537 vt = t;
1538 vc = v;
1541 #include "i386-gen.c"
1543 int save_reg_forced(int r)
1545 int i, l, *p, t;
1547 /* store register */
1548 loc = (loc - 4) & -3;
1549 store(r, VT_LOCAL, loc);
1550 l = loc;
1552 /* modify all stack values */
1553 for(p=vstack;p<vstack_ptr;p+=2) {
1554 i = p[0] & VT_VALMASK;
1555 if (i == r) {
1556 if (p[0] & VT_LVAL)
1557 t = VT_LLOCAL;
1558 else
1559 t = VT_LOCAL;
1560 p[0] = (p[0] & VT_TYPE) | VT_LVAL | t;
1561 p[1] = l;
1564 return l;
1567 /* save r to memory. and mark it as being free */
1568 void save_reg(int r)
1570 int i, *p;
1572 /* modify all stack values */
1573 for(p=vstack;p<vstack_ptr;p+=2) {
1574 i = p[0] & VT_VALMASK;
1575 if (i == r) {
1576 save_reg_forced(r);
1577 break;
1582 /* find a free register of class 'rc'. If none, save one register */
1583 int get_reg(int rc)
1585 int r, i, *p;
1587 /* find a free register */
1588 for(r=0;r<NB_REGS;r++) {
1589 if (reg_classes[r] & rc) {
1590 for(p=vstack;p<vstack_ptr;p+=2) {
1591 i = p[0] & VT_VALMASK;
1592 if (i == r)
1593 goto notfound;
1595 return r;
1597 notfound: ;
1600 /* no register left : free the first one on the stack (very
1601 important to start from the bottom to ensure that we don't
1602 spill registers used in gen_op()) */
1603 for(p=vstack;p<vstack_ptr;p+=2) {
1604 r = p[0] & VT_VALMASK;
1605 if (r < VT_CONST && (reg_classes[r] & rc)) {
1606 save_reg(r);
1607 break;
1610 return r;
1613 void save_regs()
1615 int r, *p;
1616 for(p=vstack;p<vstack_ptr;p+=2) {
1617 r = p[0] & VT_VALMASK;
1618 if (r < VT_CONST) {
1619 save_reg(r);
1624 /* move register 's' to 'r', and flush previous value of r to memory
1625 if needed */
1626 void move_reg(int r, int s)
1628 if (r != s) {
1629 save_reg(r);
1630 load(r, s, 0);
1634 /* convert a (vt, vc) in register. lvalues are converted as
1635 values. Cannot be used if cannot be converted to register value
1636 (such as structures). */
1637 int gvp(void)
1639 int r, bit_pos, bit_size, rc;
1641 /* NOTE: get_reg can modify vstack[] */
1642 if (vt & VT_BITFIELD) {
1643 bit_pos = (vt >> VT_STRUCT_SHIFT) & 0x3f;
1644 bit_size = (vt >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
1645 /* remove bit field info to avoid loops */
1646 vt &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
1647 /* generate shifts */
1648 vpush();
1649 vset(VT_CONST, 32 - (bit_pos + bit_size));
1650 gen_op(TOK_SHL);
1651 vpush();
1652 vset(VT_CONST, 32 - bit_size);
1653 /* NOTE: transformed to SHR if unsigned */
1654 gen_op(TOK_SAR);
1655 r = gv();
1656 } else {
1657 r = vt & VT_VALMASK;
1658 if (r >= VT_CONST || (vt & VT_LVAL)) {
1659 if ((vt & VT_BTYPE) == VT_FLOAT ||
1660 (vt & VT_BTYPE) == VT_DOUBLE)
1661 rc = REG_CLASS_FLOAT;
1662 else
1663 rc = REG_CLASS_INT;
1664 r = get_reg(rc);
1666 load(r, vt, vc);
1667 vt = (vt & VT_TYPE) | r;
1669 return r;
1672 void vpush(void)
1674 if (vstack_ptr >= vstack + VSTACK_SIZE)
1675 error("memory full");
1676 /* cannot let cpu flags if other instruction are generated */
1677 /* XXX: VT_JMP test too ? */
1678 if ((vt & VT_VALMASK) == VT_CMP)
1679 gvp();
1680 *vstack_ptr++ = vt;
1681 *vstack_ptr++ = vc;
1684 void vpop(int *ft, int *fc)
1686 *fc = *--vstack_ptr;
1687 *ft = *--vstack_ptr;
1690 void vswap(void)
1692 swap(vstack_ptr - 4, vstack_ptr - 2);
1693 swap(vstack_ptr - 3, vstack_ptr - 1);
1696 /* generate a value in a register from vt and vc */
1697 int gv(void)
1699 int r;
1700 vpush(); /* need so that gvp does not allocate the register we
1701 currently use */
1702 r = gvp();
1703 vstack_ptr -= 2;
1704 return r;
1707 /* handle constant optimizations and various machine independant opt */
1708 void gen_opc(int op)
1710 int fr, ft, fc, r, c1, c2, n;
1712 vpop(&ft, &fc);
1713 vpop(&vt, &vc);
1714 /* currently, we cannot do computations with forward symbols */
1715 c1 = (vt & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
1716 c2 = (ft & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
1717 if (c1 && c2) {
1718 switch(op) {
1719 case '+': vc += fc; break;
1720 case '-': vc -= fc; break;
1721 case '&': vc &= fc; break;
1722 case '^': vc ^= fc; break;
1723 case '|': vc |= fc; break;
1724 case '*': vc *= fc; break;
1725 case TOK_PDIV:
1726 case '/': vc /= fc; break; /* XXX: zero case ? */
1727 case '%': vc %= fc; break; /* XXX: zero case ? */
1728 case TOK_UDIV: vc = (unsigned)vc / fc; break; /* XXX: zero case ? */
1729 case TOK_UMOD: vc = (unsigned)vc % fc; break; /* XXX: zero case ? */
1730 case TOK_SHL: vc <<= fc; break;
1731 case TOK_SHR: vc = (unsigned)vc >> fc; break;
1732 case TOK_SAR: vc >>= fc; break;
1733 /* tests */
1734 case TOK_ULT: vc = (unsigned)vc < (unsigned)fc; break;
1735 case TOK_UGE: vc = (unsigned)vc >= (unsigned)fc; break;
1736 case TOK_EQ: vc = vc == fc; break;
1737 case TOK_NE: vc = vc != fc; break;
1738 case TOK_ULE: vc = (unsigned)vc <= (unsigned)fc; break;
1739 case TOK_UGT: vc = (unsigned)vc > (unsigned)fc; break;
1740 case TOK_LT: vc = vc < fc; break;
1741 case TOK_GE: vc = vc >= fc; break;
1742 case TOK_LE: vc = vc <= fc; break;
1743 case TOK_GT: vc = vc > fc; break;
1744 /* logical */
1745 case TOK_LAND: vc = vc && fc; break;
1746 case TOK_LOR: vc = vc || fc; break;
1747 default:
1748 goto general_case;
1750 } else {
1751 /* if commutative ops, put c2 as constant */
1752 if (c1 && (op == '+' || op == '&' || op == '^' ||
1753 op == '|' || op == '*')) {
1754 swap(&vt, &ft);
1755 swap(&vc, &fc);
1756 swap(&c1, &c2);
1758 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
1759 op == TOK_PDIV) &&
1760 fc == 1) ||
1761 ((op == '+' || op == '-' || op == '|' || op == '^' ||
1762 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
1763 fc == 0) ||
1764 (op == '&' &&
1765 fc == -1))) {
1766 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
1767 /* try to use shifts instead of muls or divs */
1768 if (fc > 0 && (fc & (fc - 1)) == 0) {
1769 n = -1;
1770 while (fc) {
1771 fc >>= 1;
1772 n++;
1774 fc = n;
1775 if (op == '*')
1776 op = TOK_SHL;
1777 else if (op == TOK_PDIV)
1778 op = TOK_SAR;
1779 else
1780 op = TOK_SHR;
1782 goto general_case;
1783 } else {
1784 general_case:
1785 vpush();
1786 vt = ft;
1787 vc = fc;
1789 fr = gv(); /* second operand */
1790 vpop(&ft, &fc);
1791 vpush();
1792 vt = ft;
1793 vc = fc;
1794 r = gv(); /* first operand */
1795 vpop(&ft, &fc);
1797 /* call low level op generator */
1798 gen_opi(op, r, fr);
1803 int pointed_size(int t)
1805 return type_size(pointed_type(t), &t);
1808 /* generic gen_op: handles types problems */
1809 void gen_op(int op)
1811 int u, t1, t2, bt1, bt2, t;
1813 vpush();
1814 t1 = vstack_ptr[-4];
1815 t2 = vstack_ptr[-2];
1816 bt1 = t1 & VT_BTYPE;
1817 bt2 = t2 & VT_BTYPE;
1819 if (bt1 == VT_FLOAT || bt1 == VT_DOUBLE ||
1820 bt2 == VT_FLOAT || bt2 == VT_DOUBLE) {
1821 /* compute bigger type and do implicit casts */
1822 if (bt1 != VT_DOUBLE && bt2 != VT_DOUBLE) {
1823 t = VT_FLOAT;
1824 } else {
1825 t = VT_DOUBLE;
1827 if (op != '+' && op != '-' && op != '*' && op != '/' &&
1828 op < TOK_EQ || op > TOK_GT)
1829 error("invalid operands for binary operation");
1830 if (bt2 != t) {
1831 vpop(&vt, &vc);
1832 gen_cast(t);
1833 vpush();
1835 if (bt1 != t) {
1836 vswap();
1837 vpop(&vt, &vc);
1838 gen_cast(t);
1839 vpush();
1840 vswap();
1842 gen_opf(op);
1843 if (op >= TOK_EQ && op <= TOK_GT) {
1844 /* the result is an int */
1845 vt = (vt & ~VT_TYPE) | VT_INT;
1846 } else {
1847 vt = (vt & ~VT_TYPE) | t;
1849 } else if (op == '+' | op == '-') {
1850 if ((t1 & VT_BTYPE) == VT_PTR &&
1851 (t2 & VT_BTYPE) == VT_PTR) {
1852 if (op != '-')
1853 error("invalid type");
1854 /* XXX: check that types are compatible */
1855 u = pointed_size(t1);
1856 gen_opc(op);
1857 vpush();
1858 vstack_ptr[-2] &= ~VT_TYPE; /* set to integer */
1859 vset(VT_CONST, u);
1860 gen_op(TOK_PDIV);
1861 } else if ((t1 & VT_BTYPE) == VT_PTR ||
1862 (t2 & VT_BTYPE) == VT_PTR) {
1863 if ((t2 & VT_BTYPE) == VT_PTR) {
1864 swap(vstack_ptr - 4, vstack_ptr - 2);
1865 swap(vstack_ptr - 3, vstack_ptr - 1);
1866 swap(&t1, &t2);
1868 /* stack-4 contains pointer, stack-2 value to add */
1869 vset(VT_CONST, pointed_size(vstack_ptr[-4]));
1870 gen_op('*');
1871 vpush();
1872 gen_opc(op);
1873 /* put again type if gen_opc() swaped operands */
1874 vt = (vt & ~VT_TYPE) | (t1 & VT_TYPE);
1875 } else {
1876 gen_opc(op);
1878 } else {
1879 /* XXX: test types and compute returned value */
1880 if ((t1 | t2) & VT_UNSIGNED ||
1881 (t1 & VT_BTYPE) == VT_PTR ||
1882 (t2 & VT_BTYPE) == VT_PTR) {
1883 if (op == TOK_SAR)
1884 op = TOK_SHR;
1885 else if (op == '/')
1886 op = TOK_UDIV;
1887 else if (op == '%')
1888 op = TOK_UMOD;
1889 else if (op == TOK_LT)
1890 op = TOK_ULT;
1891 else if (op == TOK_GT)
1892 op = TOK_UGT;
1893 else if (op == TOK_LE)
1894 op = TOK_ULE;
1895 else if (op == TOK_GE)
1896 op = TOK_UGE;
1898 gen_opc(op);
1902 /* cast (vt, vc) to 't' type */
1903 void gen_cast(int t)
1905 int r, bits, bt;
1907 r = vt & VT_VALMASK;
1908 if (!(t & VT_LVAL)) {
1909 /* if not lvalue, then we convert now */
1910 bt = t & VT_BTYPE;
1911 if (bt == VT_FLOAT || bt == VT_DOUBLE) {
1912 if ((vt & VT_BTYPE) != bt) {
1913 /* need to generate value and do explicit cast */
1914 gv();
1915 gen_cvtf(bt);
1917 goto the_end;
1918 } else if (bt == VT_BOOL) {
1919 vpush();
1920 vset(VT_CONST, 0);
1921 gen_op(TOK_NE);
1922 goto the_end;
1923 } else if (bt == VT_BYTE)
1924 bits = 8;
1925 else if (bt == VT_SHORT)
1926 bits = 16;
1927 else
1928 goto the_end;
1929 vpush();
1930 if (t & VT_UNSIGNED) {
1931 vset(VT_CONST, (1 << bits) - 1);
1932 gen_op('&');
1933 } else {
1934 bits = 32 - bits;
1935 vset(VT_CONST, bits);
1936 gen_op(TOK_SHL);
1937 vpush();
1938 vset(VT_CONST, bits);
1939 gen_op(TOK_SAR);
1942 the_end:
1943 vt = (vt & ~VT_TYPE) | t;
1946 /* return type size. Put alignment at 'a' */
1947 int type_size(int t, int *a)
1949 Sym *s;
1950 int bt;
1952 bt = t & VT_BTYPE;
1953 if (bt == VT_STRUCT) {
1954 /* struct/union */
1955 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
1956 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
1957 return s->c;
1958 } else if (bt == VT_PTR) {
1959 if (t & VT_ARRAY) {
1960 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
1961 return type_size(s->t, a) * s->c;
1962 } else {
1963 *a = 4;
1964 return 4;
1966 } else if (bt == VT_DOUBLE) {
1967 *a = 8;
1968 return 8;
1969 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
1970 *a = 4;
1971 return 4;
1972 } else if (bt == VT_SHORT) {
1973 *a = 2;
1974 return 2;
1975 } else {
1976 /* char, void, function, _Bool */
1977 *a = 1;
1978 return 1;
1982 /* return the pointed type of t */
1983 int pointed_type(int t)
1985 Sym *s;
1986 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
1987 return s->t | (t & ~VT_TYPE);
1990 int mk_pointer(int t)
1992 int p;
1993 p = anon_sym++;
1994 sym_push(p, t, -1);
1995 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
1998 /* store value in lvalue pushed on stack */
1999 void vstore(void)
2001 int ft, fc, r, t, size, align, bit_size, bit_pos;
2002 GFuncContext gf;
2004 if ((vt & VT_BTYPE) == VT_STRUCT) {
2005 /* if structure, only generate pointer */
2006 /* structure assignment : generate memcpy */
2007 /* XXX: optimize if small size */
2009 gfunc_start(&gf);
2010 /* type size */
2011 ft = vt;
2012 fc = vc;
2013 size = type_size(vt, &align);
2014 vset(VT_CONST, size);
2015 gfunc_param(&gf);
2016 /* source */
2017 vt = ft & ~VT_LVAL;
2018 vc = fc;
2019 gfunc_param(&gf);
2020 /* destination */
2021 vpop(&vt, &vc);
2022 vt &= ~VT_LVAL;
2023 gfunc_param(&gf);
2025 save_regs();
2026 vset(VT_CONST, (int)&memcpy);
2027 gfunc_call(&gf);
2029 /* generate again current type */
2030 vt = ft;
2031 vc = fc;
2032 } else if (vstack_ptr[-2] & VT_BITFIELD) {
2033 /* bitfield store handling */
2034 ft = vstack_ptr[-2];
2035 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
2036 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2037 /* remove bit field info to avoid loops */
2038 vstack_ptr[-2] = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2040 /* mask and shift source */
2041 vpush();
2042 vset(VT_CONST, (1 << bit_size) - 1);
2043 gen_op('&');
2044 vpush();
2045 vset(VT_CONST, bit_pos);
2046 gen_op(TOK_SHL);
2047 vpush();
2048 /* load destination, mask and or with source */
2049 vt = vstack_ptr[-4];
2050 vc = vstack_ptr[-3];
2051 vpush();
2052 vset(VT_CONST, ~(((1 << bit_size) - 1) << bit_pos));
2053 gen_op('&');
2054 gen_op('|');
2055 /* store result */
2056 vstore();
2057 } else {
2058 if ((vstack_ptr[-2] & VT_BTYPE) == VT_BOOL) {
2059 /* implicit cast for bool */
2060 gen_cast(VT_BOOL);
2062 r = gv(); /* generate value */
2063 vpush();
2064 ft = vstack_ptr[-4];
2065 fc = vstack_ptr[-3];
2066 /* if lvalue was saved on stack, must read it */
2067 if ((ft & VT_VALMASK) == VT_LLOCAL) {
2068 t = get_reg(REG_CLASS_INT);
2069 load(t, VT_LOCAL | VT_LVAL, fc);
2070 ft = (ft & ~VT_VALMASK) | t;
2072 store(r, ft, fc);
2073 vstack_ptr -= 4;
2077 /* post defines POST/PRE add. c is the token ++ or -- */
2078 void inc(int post, int c)
2080 int r, r1;
2081 test_lvalue();
2082 if (post)
2083 vpush(); /* room for returned value */
2084 vpush(); /* save lvalue */
2085 r = gv();
2086 vpush(); /* save value */
2087 if (post) {
2088 /* duplicate value */
2089 /* XXX: handle floats */
2090 r1 = get_reg(REG_CLASS_INT);
2091 load(r1, r, 0); /* move r to r1 */
2092 vstack_ptr[-6] = (vt & VT_TYPE) | r1;
2093 vstack_ptr[-5] = 0;
2095 /* add constant */
2096 vset(VT_CONST, c - TOK_MID);
2097 gen_op('+');
2098 vstore(); /* store value */
2099 if (post)
2100 vpop(&vt, &vc);
2103 /* enum/struct/union declaration */
2104 int struct_decl(int u)
2106 int a, t, b, v, size, align, maxalign, c, offset;
2107 int bit_size, bit_pos, bsize, bt, lbit_pos;
2108 Sym *s, *ss, **ps;
2110 a = tok; /* save decl type */
2111 next();
2112 if (tok != '{') {
2113 v = tok;
2114 next();
2115 /* struct already defined ? return it */
2116 /* XXX: check consistency */
2117 if (s = sym_find(v | SYM_STRUCT)) {
2118 if (s->t != a)
2119 error("invalid type");
2120 goto do_decl;
2122 } else {
2123 v = anon_sym++;
2125 s = sym_push(v | SYM_STRUCT, a, 0);
2126 /* put struct/union/enum name in type */
2127 do_decl:
2128 u = u | (v << VT_STRUCT_SHIFT);
2130 if (tok == '{') {
2131 next();
2132 if (s->c)
2133 error("struct/union/enum already defined");
2134 /* cannot be empty */
2135 c = 0;
2136 maxalign = 0;
2137 ps = &s->next;
2138 bit_pos = 0;
2139 offset = 0;
2140 while (1) {
2141 if (a == TOK_ENUM) {
2142 v = tok;
2143 next();
2144 if (tok == '=') {
2145 next();
2146 c = expr_const();
2148 /* enum symbols have static storage */
2149 sym_push(v, VT_CONST | VT_STATIC, c);
2150 if (tok == ',')
2151 next();
2152 c++;
2153 } else {
2154 b = ist();
2155 while (1) {
2156 bit_size = -1;
2157 v = 0;
2158 if (tok != ':') {
2159 t = type_decl(&v, b, TYPE_DIRECT);
2160 if ((t & VT_BTYPE) == VT_FUNC ||
2161 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
2162 error("invalid type for '%s'", get_tok_str(v, 0));
2163 } else {
2164 t = b;
2166 if (tok == ':') {
2167 next();
2168 bit_size = expr_const();
2169 /* XXX: handle v = 0 case for messages */
2170 if (bit_size < 0)
2171 error("negative width in bit-field '%s'",
2172 get_tok_str(v, 0));
2173 if (v && bit_size == 0)
2174 error("zero width for bit-field '%s'",
2175 get_tok_str(v, 0));
2177 size = type_size(t, &align);
2178 lbit_pos = 0;
2179 if (bit_size >= 0) {
2180 bt = t & VT_BTYPE;
2181 if (bt != VT_INT &&
2182 bt != VT_BYTE &&
2183 bt != VT_SHORT)
2184 error("bitfields must have scalar type");
2185 bsize = size * 8;
2186 if (bit_size > bsize) {
2187 error("width of '%s' exceeds its type",
2188 get_tok_str(v, 0));
2189 } else if (bit_size == bsize) {
2190 /* no need for bit fields */
2191 bit_pos = 0;
2192 } else if (bit_size == 0) {
2193 /* XXX: what to do if only padding in a
2194 structure ? */
2195 /* zero size: means to pad */
2196 if (bit_pos > 0)
2197 bit_pos = bsize;
2198 } else {
2199 /* we do not have enough room ? */
2200 if ((bit_pos + bit_size) > bsize)
2201 bit_pos = 0;
2202 lbit_pos = bit_pos;
2203 /* XXX: handle LSB first */
2204 t |= VT_BITFIELD |
2205 (bit_pos << VT_STRUCT_SHIFT) |
2206 (bit_size << (VT_STRUCT_SHIFT + 6));
2207 bit_pos += bit_size;
2209 } else {
2210 bit_pos = 0;
2212 if (v) {
2213 /* add new memory data only if starting
2214 bit field */
2215 if (lbit_pos == 0) {
2216 if (a == TOK_STRUCT) {
2217 c = (c + align - 1) & -align;
2218 offset = c;
2219 c += size;
2220 } else {
2221 offset = 0;
2222 if (size > c)
2223 c = size;
2225 if (align > maxalign)
2226 maxalign = align;
2228 #if 0
2229 printf("add field %s offset=%d",
2230 get_tok_str(v, 0), offset);
2231 if (t & VT_BITFIELD) {
2232 printf(" pos=%d size=%d",
2233 (t >> VT_STRUCT_SHIFT) & 0x3f,
2234 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
2236 printf("\n");
2237 #endif
2238 ss = sym_push(v | SYM_FIELD, t, offset);
2239 *ps = ss;
2240 ps = &ss->next;
2242 if (tok == ';' || tok == -1)
2243 break;
2244 skip(',');
2246 skip(';');
2248 if (tok == '}')
2249 break;
2251 skip('}');
2252 /* size for struct/union, dummy for enum */
2253 s->c = (c + maxalign - 1) & -maxalign;
2255 return u;
2258 /* return 0 if no type declaration. otherwise, return the basic type
2259 and skip it.
2260 XXX: A '2' is ored to ensure non zero return if int type.
2262 int ist(void)
2264 int t, u;
2265 Sym *s;
2267 t = 0;
2268 while(1) {
2269 switch(tok) {
2270 /* basic types */
2271 case TOK_CHAR:
2272 u = VT_BYTE;
2273 basic_type:
2274 next();
2275 basic_type1:
2276 if ((t & VT_BTYPE) != 0)
2277 error("too many basic types %x", t);
2278 t |= u;
2279 break;
2280 case TOK_VOID:
2281 u = VT_VOID;
2282 goto basic_type;
2283 case TOK_SHORT:
2284 u = VT_SHORT;
2285 goto basic_type;
2286 case TOK_INT:
2287 next();
2288 break;
2289 case TOK_LONG:
2290 /* XXX: add long type */
2291 u = VT_INT;
2292 goto basic_type;
2293 case TOK_BOOL:
2294 u = VT_BOOL;
2295 goto basic_type;
2296 case TOK_FLOAT:
2297 u = VT_FLOAT;
2298 goto basic_type;
2299 case TOK_DOUBLE:
2300 u = VT_DOUBLE;
2301 goto basic_type;
2302 case TOK_ENUM:
2303 u = struct_decl(VT_ENUM);
2304 goto basic_type1;
2305 case TOK_STRUCT:
2306 case TOK_UNION:
2307 u = struct_decl(VT_STRUCT);
2308 goto basic_type1;
2310 /* type modifiers */
2311 case TOK_CONST:
2312 case TOK_VOLATILE:
2313 case TOK_REGISTER:
2314 case TOK_SIGNED:
2315 case TOK_AUTO:
2316 case TOK_INLINE:
2317 case TOK_RESTRICT:
2318 next();
2319 break;
2320 case TOK_UNSIGNED:
2321 t |= VT_UNSIGNED;
2322 next();
2323 break;
2325 /* storage */
2326 case TOK_EXTERN:
2327 t |= VT_EXTERN;
2328 next();
2329 break;
2330 case TOK_STATIC:
2331 t |= VT_STATIC;
2332 next();
2333 break;
2334 case TOK_TYPEDEF:
2335 t |= VT_TYPEDEF;
2336 next();
2337 break;
2338 default:
2339 s = sym_find(tok);
2340 if (!s || !(s->t & VT_TYPEDEF))
2341 goto the_end;
2342 t |= (s->t & ~VT_TYPEDEF);
2343 next();
2344 break;
2346 t |= 2;
2348 the_end:
2349 return t;
2352 int post_type(int t)
2354 int p, n, pt, l, t1;
2355 Sym **plast, *s, *first;
2357 if (tok == '(') {
2358 /* function declaration */
2359 next();
2360 l = 0;
2361 first = NULL;
2362 plast = &first;
2363 while (tok != ')') {
2364 /* read param name and compute offset */
2365 if (l != FUNC_OLD) {
2366 if (!(pt = ist())) {
2367 if (l) {
2368 error("invalid type");
2369 } else {
2370 l = FUNC_OLD;
2371 goto old_proto;
2374 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
2375 break;
2376 l = FUNC_NEW;
2377 pt = type_decl(&n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
2378 } else {
2379 old_proto:
2380 n = tok;
2381 pt = VT_INT;
2382 next();
2384 /* array must be transformed to pointer according to ANSI C */
2385 pt &= ~VT_ARRAY;
2386 s = sym_push(n | SYM_FIELD, pt, 0);
2387 *plast = s;
2388 plast = &s->next;
2389 if (tok == ',') {
2390 next();
2391 if (l == FUNC_NEW && tok == TOK_DOTS) {
2392 l = FUNC_ELLIPSIS;
2393 next();
2394 break;
2398 skip(')');
2399 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
2400 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
2401 /* we push a anonymous symbol which will contain the function prototype */
2402 p = anon_sym++;
2403 s = sym_push(p, t, l);
2404 s->next = first;
2405 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
2406 } else if (tok == '[') {
2407 /* array definition */
2408 next();
2409 n = -1;
2410 if (tok != ']') {
2411 n = expr_const();
2412 if (n < 0)
2413 error("invalid array size");
2415 skip(']');
2416 /* parse next post type */
2417 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
2418 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
2420 /* we push a anonymous symbol which will contain the array
2421 element type */
2422 p = anon_sym++;
2423 sym_push(p, t, n);
2424 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
2426 return t;
2429 /* Read a type declaration (except basic type), and return the
2430 type. If v is true, then also put variable name in 'vc' */
2431 int type_decl(int *v, int t, int td)
2433 int u, p;
2434 Sym *s;
2436 t = t & -3; /* suppress the ored '2' */
2437 while (tok == '*') {
2438 next();
2439 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
2440 next();
2441 t = mk_pointer(t);
2444 /* recursive type */
2445 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
2446 if (tok == '(') {
2447 next();
2448 u = type_decl(v, 0, td);
2449 skip(')');
2450 } else {
2451 u = 0;
2452 /* type identifier */
2453 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
2454 *v = tok;
2455 next();
2456 } else {
2457 if (!(td & TYPE_ABSTRACT))
2458 expect("identifier");
2459 *v = 0;
2462 /* append t at the end of u */
2463 t = post_type(t);
2464 if (!u)
2465 return t;
2466 p = u;
2467 while(1) {
2468 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
2469 p = s->t;
2470 if (!p) {
2471 s->t = t;
2472 break;
2475 return u;
2478 /* define a new external reference to a function 'v' of type 'u' */
2479 Sym *external_sym(int v, int u)
2481 Sym *s;
2482 s = sym_find(v);
2483 if (!s) {
2484 /* push forward reference */
2485 s = sym_push1(&global_stack,
2486 v, u | VT_CONST | VT_FORWARD, 0);
2488 return s;
2491 void indir(void)
2493 if (vt & VT_LVAL)
2494 gv();
2495 if ((vt & VT_BTYPE) != VT_PTR)
2496 expect("pointer");
2497 vt = pointed_type(vt);
2498 if (!(vt & VT_ARRAY)) /* an array is never an lvalue */
2499 vt |= VT_LVAL;
2502 void unary(void)
2504 int n, t, ft, fc, p, align, size;
2505 Sym *s;
2506 GFuncContext gf;
2508 if (tok == TOK_NUM || tok == TOK_CCHAR || tok == TOK_LCHAR) {
2509 vset(VT_CONST, tokc);
2510 next();
2511 } else if (tok == TOK___FUNC__) {
2512 /* special function name identifier */
2513 /* generate (char *) type */
2514 vset(VT_CONST | mk_pointer(VT_BYTE), glo);
2515 strcpy((void *)glo, funcname);
2516 glo += strlen(funcname) + 1;
2517 next();
2518 } else if (tok == TOK_LSTR) {
2519 t = VT_INT;
2520 goto str_init;
2521 } else if (tok == TOK_STR) {
2522 /* string parsing */
2523 t = VT_BYTE;
2524 str_init:
2525 type_size(t, &align);
2526 glo = (glo + align - 1) & -align;
2527 fc = glo;
2528 /* we must declare it as an array first to use initializer parser */
2529 t = VT_CONST | VT_ARRAY | mk_pointer(t);
2530 decl_initializer(t, glo, 1, 0);
2531 glo += type_size(t, &align);
2532 /* put it as pointer */
2533 vset(t & ~VT_ARRAY, fc);
2534 } else {
2535 t = tok;
2536 next();
2537 if (t == '(') {
2538 /* cast ? */
2539 if (t = ist()) {
2540 ft = type_decl(&n, t, TYPE_ABSTRACT);
2541 skip(')');
2542 /* check ISOC99 compound literal */
2543 if (tok == '{') {
2544 /* data is allocated locally by default */
2545 if (global_expr)
2546 ft |= VT_CONST;
2547 else
2548 ft |= VT_LOCAL;
2549 /* all except arrays are lvalues */
2550 if (!(ft & VT_ARRAY))
2551 ft |= VT_LVAL;
2552 fc = decl_initializer_alloc(ft, 1);
2553 vset(ft, fc);
2554 } else {
2555 unary();
2556 gen_cast(ft);
2558 } else {
2559 expr();
2560 skip(')');
2562 } else if (t == '*') {
2563 unary();
2564 indir();
2565 } else if (t == '&') {
2566 unary();
2567 /* functions names must be treated as function pointers,
2568 except for unary '&' and sizeof. Since we consider that
2569 functions are not lvalues, we only have to handle it
2570 there and in function calls. */
2571 if ((vt & VT_BTYPE) != VT_FUNC)
2572 test_lvalue();
2573 vt = mk_pointer(vt & VT_LVALN);
2574 } else
2575 if (t == '!') {
2576 unary();
2577 if ((vt & (VT_VALMASK | VT_LVAL)) == VT_CONST)
2578 vc = !vc;
2579 else if ((vt & VT_VALMASK) == VT_CMP)
2580 vc = vc ^ 1;
2581 else
2582 vset(VT_JMP, gtst(1, 0));
2583 } else
2584 if (t == '~') {
2585 unary();
2586 vpush();
2587 vset(VT_CONST, -1);
2588 gen_op('^');
2589 } else
2590 if (t == '+') {
2591 unary();
2592 } else
2593 if (t == TOK_SIZEOF) {
2594 /* XXX: some code can be generated */
2595 if (tok == '(') {
2596 next();
2597 if (t = ist())
2598 vt = type_decl(&n, t, TYPE_ABSTRACT);
2599 else
2600 expr();
2601 skip(')');
2602 } else {
2603 unary();
2605 vset(VT_CONST, type_size(vt, &t));
2606 } else
2607 if (t == TOK_INC | t == TOK_DEC) {
2608 unary();
2609 inc(0, t);
2610 } else if (t == '-') {
2611 vset(VT_CONST, 0);
2612 vpush();
2613 unary();
2614 gen_op('-');
2615 } else
2617 s = sym_find(t);
2618 if (!s) {
2619 if (tok != '(')
2620 error("'%s' undeclared", get_tok_str(t, 0));
2621 /* for simple function calls, we tolerate undeclared
2622 external reference */
2623 p = anon_sym++;
2624 sym_push1(&global_stack, p, 0, FUNC_OLD);
2625 /* int() function */
2626 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT));
2628 vset(s->t, s->c);
2629 /* if forward reference, we must point to s */
2630 if (vt & VT_FORWARD)
2631 vc = (int)s;
2635 /* post operations */
2636 while (1) {
2637 if (tok == TOK_INC | tok == TOK_DEC) {
2638 inc(1, tok);
2639 next();
2640 } else if (tok == '.' | tok == TOK_ARROW) {
2641 /* field */
2642 if (tok == TOK_ARROW)
2643 indir();
2644 test_lvalue();
2645 vt &= VT_LVALN;
2646 next();
2647 /* expect pointer on structure */
2648 if ((vt & VT_BTYPE) != VT_STRUCT)
2649 expect("struct or union");
2650 s = sym_find(((unsigned)vt >> VT_STRUCT_SHIFT) | SYM_STRUCT);
2651 /* find field */
2652 tok |= SYM_FIELD;
2653 while (s = s->next) {
2654 if (s->v == tok)
2655 break;
2657 if (!s)
2658 error("field not found");
2659 /* add field offset to pointer */
2660 vt = (vt & ~VT_TYPE) | VT_INT; /* change type to int */
2661 vpush();
2662 vset(VT_CONST, s->c);
2663 gen_op('+');
2664 /* change type to field type, and set to lvalue */
2665 vt = (vt & ~VT_TYPE) | s->t;
2666 /* an array is never an lvalue */
2667 if (!(vt & VT_ARRAY))
2668 vt |= VT_LVAL;
2669 next();
2670 } else if (tok == '[') {
2671 next();
2672 vpush();
2673 expr();
2674 gen_op('+');
2675 indir();
2676 skip(']');
2677 } else if (tok == '(') {
2678 int rett, retc;
2680 /* function call */
2681 if ((vt & VT_BTYPE) != VT_FUNC) {
2682 /* pointer test (no array accepted) */
2683 if ((vt & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
2684 vt = pointed_type(vt);
2685 if ((vt & VT_BTYPE) != VT_FUNC)
2686 goto error_func;
2687 } else {
2688 error_func:
2689 expect("function pointer");
2691 } else {
2692 vt &= ~VT_LVAL; /* no lvalue */
2695 /* get return type */
2696 s = sym_find((unsigned)vt >> VT_STRUCT_SHIFT);
2697 vpush(); /* push function address */
2698 save_regs(); /* save used temporary registers */
2699 gfunc_start(&gf);
2700 next();
2701 #ifdef INVERT_FUNC_PARAMS
2703 int *str, len, parlevel, *saved_macro_ptr;
2704 Sym *args, *s1;
2706 /* read each argument and store it on a stack */
2707 /* XXX: merge it with macro args ? */
2708 args = NULL;
2709 while (tok != ')') {
2710 len = 0;
2711 str = NULL;
2712 parlevel = 0;
2713 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
2714 tok != -1) {
2715 if (tok == '(')
2716 parlevel++;
2717 else if (tok == ')')
2718 parlevel--;
2719 tok_add2(&str, &len, tok, tokc);
2720 next();
2722 tok_add(&str, &len, -1); /* end of file added */
2723 tok_add(&str, &len, 0);
2724 sym_push2(&args, 0, 0, (int)str);
2725 if (tok != ',')
2726 break;
2727 next();
2729 if (tok != ')')
2730 expect(")");
2732 /* now generate code in reverse order by reading the stack */
2733 saved_macro_ptr = macro_ptr;
2734 while (args) {
2735 macro_ptr = (int *)args->c;
2736 next();
2737 expr_eq();
2738 if (tok != -1)
2739 expect("',' or ')'");
2740 gfunc_param(&gf);
2741 s1 = args->prev;
2742 free((int *)args->c);
2743 free(args);
2744 args = s1;
2746 macro_ptr = saved_macro_ptr;
2747 /* restore token */
2748 tok = ')';
2750 #endif
2751 /* compute first implicit argument if a structure is returned */
2752 if ((s->t & VT_BTYPE) == VT_STRUCT) {
2753 /* get some space for the returned structure */
2754 size = type_size(s->t, &align);
2755 loc = (loc - size) & -align;
2756 rett = s->t | VT_LOCAL | VT_LVAL;
2757 /* pass it as 'int' to avoid structure arg passing
2758 problems */
2759 vset(VT_INT | VT_LOCAL, loc);
2760 retc = vc;
2761 gfunc_param(&gf);
2762 } else {
2763 rett = s->t | FUNC_RET_REG; /* return in register */
2764 retc = 0;
2766 #ifndef INVERT_FUNC_PARAMS
2767 while (tok != ')') {
2768 expr_eq();
2769 gfunc_param(&gf);
2770 if (tok == ',')
2771 next();
2773 #endif
2774 skip(')');
2775 vpop(&vt, &vc);
2776 gfunc_call(&gf);
2777 /* return value */
2778 vt = rett;
2779 vc = retc;
2780 } else {
2781 break;
2786 int is_compatible_types(int t1, int t2)
2788 Sym *s1, *s2;
2789 int bt1, bt2;
2791 t1 &= VT_TYPE;
2792 t2 &= VT_TYPE;
2793 bt1 = t1 & VT_BTYPE;
2794 bt2 = t2 & VT_BTYPE;
2795 if (bt1 == VT_PTR) {
2796 t1 = pointed_type(t1);
2797 /* if function, then convert implictely to function pointer */
2798 if (bt2 != VT_FUNC) {
2799 if (bt2 != VT_PTR)
2800 return 0;
2801 t2 = pointed_type(t2);
2803 /* void matches everything */
2804 t1 &= VT_TYPE;
2805 t2 &= VT_TYPE;
2806 if (t1 == VT_VOID || t2 == VT_VOID)
2807 return 1;
2808 return is_compatible_types(t1, t2);
2809 } else if (bt1 == VT_STRUCT) {
2810 return (t2 == t1);
2811 } else if (bt1 == VT_FUNC) {
2812 if (bt2 != VT_FUNC)
2813 return 0;
2814 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
2815 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
2816 if (!is_compatible_types(s1->t, s2->t))
2817 return 0;
2818 /* XXX: not complete */
2819 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
2820 return 1;
2821 if (s1->c != s2->c)
2822 return 0;
2823 while (s1 != NULL) {
2824 if (s2 == NULL)
2825 return 0;
2826 if (!is_compatible_types(s1->t, s2->t))
2827 return 0;
2828 s1 = s1->next;
2829 s2 = s2->next;
2831 if (s2)
2832 return 0;
2833 return 1;
2834 } else {
2835 /* XXX: not complete */
2836 return 1;
2840 int check_assign_types(int t1, int t2)
2842 t1 &= VT_TYPE;
2843 t2 &= VT_TYPE;
2844 if ((t1 & VT_BTYPE) == VT_PTR &&
2845 (t2 & VT_BTYPE) == VT_FUNC) {
2846 return is_compatible_types(pointed_type(t1), t2);
2847 } else {
2848 return is_compatible_types(t1, t2);
2853 void uneq(void)
2855 int t;
2857 unary();
2858 if (tok == '=' ||
2859 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
2860 tok == TOK_A_XOR || tok == TOK_A_OR ||
2861 tok == TOK_A_SHL || tok == TOK_A_SAR) {
2862 test_lvalue();
2863 vpush();
2864 t = tok;
2865 next();
2866 if (t == '=') {
2867 expr_eq();
2868 if (!check_assign_types(vstack_ptr[-2], vt))
2869 warning("incompatible types");
2870 } else {
2871 vpush();
2872 expr_eq();
2873 gen_op(t & 0x7f);
2875 vstore();
2879 void sum(l)
2881 int t;
2883 if (l == 0)
2884 uneq();
2885 else {
2886 sum(--l);
2887 while ((l == 0 & (tok == '*' | tok == '/' | tok == '%')) |
2888 (l == 1 & (tok == '+' | tok == '-')) |
2889 (l == 2 & (tok == TOK_SHL | tok == TOK_SAR)) |
2890 (l == 3 & ((tok >= TOK_ULE & tok <= TOK_GT) |
2891 tok == TOK_ULT | tok == TOK_UGE)) |
2892 (l == 4 & (tok == TOK_EQ | tok == TOK_NE)) |
2893 (l == 5 & tok == '&') |
2894 (l == 6 & tok == '^') |
2895 (l == 7 & tok == '|') |
2896 (l == 8 & tok == TOK_LAND) |
2897 (l == 9 & tok == TOK_LOR)) {
2898 vpush();
2899 t = tok;
2900 next();
2901 sum(l);
2902 gen_op(t);
2907 /* only used if non constant */
2908 void eand(void)
2910 int t;
2912 sum(8);
2913 t = 0;
2914 while (1) {
2915 if (tok != TOK_LAND) {
2916 if (t) {
2917 t = gtst(1, t);
2918 vset(VT_JMPI, t);
2920 break;
2922 t = gtst(1, t);
2923 next();
2924 sum(8);
2928 void eor(void)
2930 int t;
2932 eand();
2933 t = 0;
2934 while (1) {
2935 if (tok != TOK_LOR) {
2936 if (t) {
2937 t = gtst(0, t);
2938 vset(VT_JMP, t);
2940 break;
2942 t = gtst(0, t);
2943 next();
2944 eand();
2948 /* XXX: better constant handling */
2949 void expr_eq()
2951 int t, u, c, r1, r2;
2953 if (const_wanted) {
2954 sum(10);
2955 if (tok == '?') {
2956 c = vc;
2957 next();
2958 expr();
2959 t = vc;
2960 skip(':');
2961 expr_eq();
2962 if (c)
2963 vc = t;
2965 } else {
2966 eor();
2967 if (tok == '?') {
2968 next();
2969 t = gtst(1, 0);
2970 expr();
2971 r1 = gv();
2972 skip(':');
2973 u = gjmp(0);
2974 gsym(t);
2975 expr_eq();
2976 r2 = gv();
2977 move_reg(r1, r2);
2978 vt = (vt & VT_TYPE) | r1;
2979 gsym(u);
2984 void expr()
2986 while (1) {
2987 expr_eq();
2988 if (tok != ',')
2989 break;
2990 next();
2994 int expr_const()
2996 int a;
2997 a = const_wanted;
2998 const_wanted = 1;
2999 expr_eq();
3000 if ((vt & (VT_CONST | VT_LVAL)) != VT_CONST)
3001 expect("constant");
3002 const_wanted = a;
3003 return vc;
3006 /* return the label token if current token is a label, otherwise
3007 return zero */
3008 int is_label(void)
3010 int t, c;
3012 /* fast test first */
3013 if (tok < TOK_UIDENT)
3014 return 0;
3015 t = tok;
3016 c = tokc;
3017 next();
3018 if (tok == ':') {
3019 next();
3020 return t;
3021 } else {
3022 /* XXX: may not work in all cases (macros ?) */
3023 tok1 = tok;
3024 tok1c = tokc;
3025 tok = t;
3026 tokc = c;
3027 return 0;
3031 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
3033 int a, b, c, d;
3034 Sym *s;
3036 if (tok == TOK_IF) {
3037 /* if test */
3038 next();
3039 skip('(');
3040 expr();
3041 skip(')');
3042 a = gtst(1, 0);
3043 block(bsym, csym, case_sym, def_sym, case_reg);
3044 c = tok;
3045 if (c == TOK_ELSE) {
3046 next();
3047 d = gjmp(0);
3048 gsym(a);
3049 block(bsym, csym, case_sym, def_sym, case_reg);
3050 gsym(d); /* patch else jmp */
3051 } else
3052 gsym(a);
3053 } else if (tok == TOK_WHILE) {
3054 next();
3055 d = ind;
3056 skip('(');
3057 expr();
3058 skip(')');
3059 a = gtst(1, 0);
3060 b = 0;
3061 block(&a, &b, case_sym, def_sym, case_reg);
3062 oad(0xe9, d - ind - 5); /* jmp */
3063 gsym(a);
3064 gsym_addr(b, d);
3065 } else if (tok == '{') {
3066 next();
3067 /* declarations */
3068 s = local_stack.top;
3069 while (tok != '}') {
3070 decl(VT_LOCAL);
3071 if (tok != '}')
3072 block(bsym, csym, case_sym, def_sym, case_reg);
3074 /* pop locally defined symbols */
3075 sym_pop(&local_stack, s);
3076 next();
3077 } else if (tok == TOK_RETURN) {
3078 next();
3079 if (tok != ';') {
3080 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
3081 /* if returning structure, must copy it to implicit
3082 first pointer arg location */
3083 vset(mk_pointer(func_vt) | VT_LOCAL | VT_LVAL, func_vc);
3084 indir();
3085 vpush();
3087 expr();
3088 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
3089 /* copy structure value to pointer */
3090 vstore();
3091 } else {
3092 /* move return value to standard return register */
3093 move_reg(FUNC_RET_REG, gv());
3096 skip(';');
3097 rsym = gjmp(rsym); /* jmp */
3098 } else if (tok == TOK_BREAK) {
3099 /* compute jump */
3100 if (!bsym)
3101 error("cannot break");
3102 *bsym = gjmp(*bsym);
3103 next();
3104 skip(';');
3105 } else if (tok == TOK_CONTINUE) {
3106 /* compute jump */
3107 if (!csym)
3108 error("cannot continue");
3109 *csym = gjmp(*csym);
3110 next();
3111 skip(';');
3112 } else if (tok == TOK_FOR) {
3113 int e;
3114 next();
3115 skip('(');
3116 if (tok != ';')
3117 expr();
3118 skip(';');
3119 d = ind;
3120 c = ind;
3121 a = 0;
3122 b = 0;
3123 if (tok != ';') {
3124 expr();
3125 a = gtst(1, 0);
3127 skip(';');
3128 if (tok != ')') {
3129 e = gjmp(0);
3130 c = ind;
3131 expr();
3132 oad(0xe9, d - ind - 5); /* jmp */
3133 gsym(e);
3135 skip(')');
3136 block(&a, &b, case_sym, def_sym, case_reg);
3137 oad(0xe9, c - ind - 5); /* jmp */
3138 gsym(a);
3139 gsym_addr(b, c);
3140 } else
3141 if (tok == TOK_DO) {
3142 next();
3143 a = 0;
3144 b = 0;
3145 d = ind;
3146 block(&a, &b, case_sym, def_sym, case_reg);
3147 skip(TOK_WHILE);
3148 skip('(');
3149 gsym(b);
3150 expr();
3151 c = gtst(0, 0);
3152 gsym_addr(c, d);
3153 skip(')');
3154 gsym(a);
3155 skip(';');
3156 } else
3157 if (tok == TOK_SWITCH) {
3158 next();
3159 skip('(');
3160 expr();
3161 case_reg = gv();
3162 skip(')');
3163 a = 0;
3164 b = gjmp(0); /* jump to first case */
3165 c = 0;
3166 block(&a, csym, &b, &c, case_reg);
3167 /* if no default, jmp after switch */
3168 if (c == 0)
3169 c = ind;
3170 /* default label */
3171 gsym_addr(b, c);
3172 /* break label */
3173 gsym(a);
3174 } else
3175 if (tok == TOK_CASE) {
3176 next();
3177 a = expr_const();
3178 if (!case_sym)
3179 expect("switch");
3180 /* since a case is like a label, we must skip it with a jmp */
3181 b = gjmp(0);
3182 gsym(*case_sym);
3183 vset(case_reg, 0);
3184 vpush();
3185 vset(VT_CONST, a);
3186 gen_op(TOK_EQ);
3187 *case_sym = gtst(1, 0);
3188 gsym(b);
3189 skip(':');
3190 block(bsym, csym, case_sym, def_sym, case_reg);
3191 } else
3192 if (tok == TOK_DEFAULT) {
3193 next();
3194 skip(':');
3195 if (!def_sym)
3196 expect("switch");
3197 if (*def_sym)
3198 error("too many 'default'");
3199 *def_sym = ind;
3200 block(bsym, csym, case_sym, def_sym, case_reg);
3201 } else
3202 if (tok == TOK_GOTO) {
3203 next();
3204 s = sym_find1(&label_stack, tok);
3205 /* put forward definition if needed */
3206 if (!s)
3207 s = sym_push1(&label_stack, tok, VT_FORWARD, 0);
3208 /* label already defined */
3209 if (s->t & VT_FORWARD)
3210 s->c = gjmp(s->c); /* jmp xxx */
3211 else
3212 oad(0xe9, s->c - ind - 5); /* jmp xxx */
3213 next();
3214 skip(';');
3215 } else {
3216 b = is_label();
3217 if (b) {
3218 /* label case */
3219 s = sym_find1(&label_stack, b);
3220 if (s) {
3221 if (!(s->t & VT_FORWARD))
3222 error("multiple defined label");
3223 gsym(s->c);
3224 s->c = ind;
3225 s->t = 0;
3226 } else {
3227 sym_push1(&label_stack, b, 0, ind);
3229 /* we accept this, but it is a mistake */
3230 if (tok == '}')
3231 warning("deprecated use of label at end of compound statement");
3232 else
3233 block(bsym, csym, case_sym, def_sym, case_reg);
3234 } else {
3235 /* expression case */
3236 if (tok != ';') {
3237 expr();
3239 skip(';');
3244 /* t is the array or struct type. c is the array or struct
3245 address. cur_index/cur_field is the pointer to the current
3246 value. 'size_only' is true if only size info is needed (only used
3247 in arrays) */
3248 void decl_designator(int t, int c,
3249 int *cur_index, Sym **cur_field,
3250 int size_only)
3252 Sym *s, *f;
3253 int notfirst, index, align, l;
3255 notfirst = 0;
3256 if (gnu_ext && (l = is_label()) != 0)
3257 goto struct_field;
3259 while (tok == '[' || tok == '.') {
3260 if (tok == '[') {
3261 if (!(t & VT_ARRAY))
3262 expect("array type");
3263 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3264 next();
3265 index = expr_const();
3266 if (index < 0 || (s->c >= 0 && index >= s->c))
3267 expect("invalid index");
3268 skip(']');
3269 if (!notfirst)
3270 *cur_index = index;
3271 t = pointed_type(t);
3272 c += index * type_size(t, &align);
3273 } else {
3274 next();
3275 l = tok;
3276 next();
3277 struct_field:
3278 if ((t & VT_BTYPE) != VT_STRUCT)
3279 expect("struct/union type");
3280 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3281 l |= SYM_FIELD;
3282 f = s->next;
3283 while (f) {
3284 if (f->v == l)
3285 break;
3286 f = f->next;
3288 if (!f)
3289 expect("field");
3290 if (!notfirst)
3291 *cur_field = f;
3292 t = f->t | (t & ~VT_TYPE);
3293 c += f->c;
3295 notfirst = 1;
3297 if (notfirst) {
3298 if (tok == '=') {
3299 next();
3300 } else {
3301 if (!gnu_ext)
3302 expect("=");
3304 } else {
3305 if (t & VT_ARRAY) {
3306 index = *cur_index;
3307 t = pointed_type(t);
3308 c += index * type_size(t, &align);
3309 } else {
3310 f = *cur_field;
3311 if (!f)
3312 error("too many field init");
3313 t = f->t | (t & ~VT_TYPE);
3314 c += f->c;
3317 decl_initializer(t, c, 0, size_only);
3320 /* store a value or an expression directly in global data or in local array */
3322 void init_putv(int t, int c, int v, int is_expr)
3324 int saved_global_expr;
3326 if ((t & VT_VALMASK) == VT_CONST) {
3327 if (is_expr) {
3328 /* compound literals must be allocated globally in this case */
3329 saved_global_expr = global_expr;
3330 global_expr = 1;
3331 v = expr_const();
3332 global_expr = saved_global_expr;
3334 if ((t & VT_BTYPE) == VT_BYTE)
3335 *(char *)c = v;
3336 else if ((t & VT_BTYPE) == VT_SHORT)
3337 *(short *)c = v;
3338 else
3339 *(int *)c = v;
3340 } else {
3341 vt = t;
3342 vc = c;
3343 vpush();
3344 if (is_expr)
3345 expr_eq();
3346 else
3347 vset(VT_CONST, v);
3348 vstore();
3352 /* put zeros for variable based init */
3353 void init_putz(int t, int c, int size)
3355 GFuncContext gf;
3357 if ((t & VT_VALMASK) == VT_CONST) {
3358 /* nothing to do because global are already set to zero */
3359 } else {
3360 gfunc_start(&gf);
3361 vset(VT_CONST, size);
3362 gfunc_param(&gf);
3363 vset(VT_CONST, 0);
3364 gfunc_param(&gf);
3365 vset(VT_LOCAL, c);
3366 gfunc_param(&gf);
3367 vset(VT_CONST, (int)&memset);
3368 gfunc_call(&gf);
3372 /* 't' contains the type and storage info. c is the address of the
3373 object. 'first' is true if array '{' must be read (multi dimension
3374 implicit array init handling). 'size_only' is true if size only
3375 evaluation is wanted (only for arrays). */
3376 void decl_initializer(int t, int c, int first, int size_only)
3378 int index, array_length, n, no_oblock, nb, parlevel, i;
3379 int t1, size1, align1;
3380 Sym *s, *f;
3381 TokenSym *ts;
3383 if (t & VT_ARRAY) {
3384 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3385 n = s->c;
3386 array_length = 0;
3387 t1 = pointed_type(t);
3388 size1 = type_size(t1, &align1);
3390 no_oblock = 1;
3391 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
3392 tok == '{') {
3393 skip('{');
3394 no_oblock = 0;
3397 /* only parse strings here if correct type (otherwise: handle
3398 them as ((w)char *) expressions */
3399 if ((tok == TOK_LSTR &&
3400 (t1 & VT_BTYPE) == VT_INT) ||
3401 (tok == TOK_STR &&
3402 (t1 & VT_BTYPE) == VT_BYTE)) {
3403 /* XXX: move multiple string parsing in parser ? */
3404 while (tok == TOK_STR || tok == TOK_LSTR) {
3405 ts = (TokenSym *)tokc;
3406 /* compute maximum number of chars wanted */
3407 nb = ts->len;
3408 if (n >= 0 && nb > (n - array_length))
3409 nb = n - array_length;
3410 if (!size_only) {
3411 if (ts->len > nb)
3412 warning("initializer-string for array is too long");
3413 for(i=0;i<nb;i++) {
3414 init_putv(t1, c + (array_length + i) * size1,
3415 ts->str[i], 0);
3418 array_length += nb;
3419 next();
3421 /* only add trailing zero if enough storage (no
3422 warning in this case since it is standard) */
3423 if (n < 0 || array_length < n) {
3424 if (!size_only) {
3425 init_putv(t1, c + (array_length * size1), 0, 0);
3427 array_length++;
3429 } else {
3430 index = 0;
3431 while (tok != '}') {
3432 decl_designator(t, c, &index, NULL, size_only);
3433 if (n >= 0 && index >= n)
3434 error("index too large");
3435 /* must put zero in holes (note that doing it that way
3436 ensures that it even works with designators) */
3437 if (!size_only && array_length < index) {
3438 init_putz(t1, c + array_length * size1,
3439 (index - array_length) * size1);
3441 index++;
3442 if (index > array_length)
3443 array_length = index;
3444 /* special test for multi dimensional arrays (may not
3445 be strictly correct if designators are used at the
3446 same time) */
3447 if (index >= n && no_oblock)
3448 break;
3449 if (tok == '}')
3450 break;
3451 skip(',');
3454 if (!no_oblock)
3455 skip('}');
3456 /* put zeros at the end */
3457 if (!size_only && n >= 0 && array_length < n) {
3458 init_putz(t1, c + array_length * size1,
3459 (n - array_length) * size1);
3461 /* patch type size if needed */
3462 if (n < 0)
3463 s->c = array_length;
3464 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
3465 /* XXX: union needs only one init */
3466 next();
3467 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3468 f = s->next;
3469 array_length = 0;
3470 index = 0;
3471 n = s->c;
3472 while (tok != '}') {
3473 decl_designator(t, c, NULL, &f, size_only);
3474 /* fill with zero between fields */
3475 index = f->c;
3476 if (!size_only && array_length < index) {
3477 init_putz(t, c + array_length,
3478 index - array_length);
3480 index = index + type_size(f->t, &align1);
3481 if (index > array_length)
3482 array_length = index;
3483 if (tok == '}')
3484 break;
3485 skip(',');
3486 f = f->next;
3488 /* put zeros at the end */
3489 if (!size_only && array_length < n) {
3490 init_putz(t, c + array_length,
3491 n - array_length);
3493 skip('}');
3494 } else if (tok == '{') {
3495 next();
3496 decl_initializer(t, c, first, size_only);
3497 skip('}');
3498 } else if (size_only) {
3499 /* just skip expression */
3500 parlevel = 0;
3501 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
3502 tok != -1) {
3503 if (tok == '(')
3504 parlevel++;
3505 else if (tok == ')')
3506 parlevel--;
3507 next();
3509 } else {
3510 init_putv(t, c, 0, 1);
3514 /* parse an initializer for type 't' if 'has_init' is true, and
3515 allocate space in local or global data space. The allocated address
3516 in returned */
3517 int decl_initializer_alloc(int t, int has_init)
3519 int size, align, addr, tok1;
3520 int *init_str, init_len, level, *saved_macro_ptr;
3522 size = type_size(t, &align);
3523 /* If unknown size, we must evaluate it before
3524 evaluating initializers because
3525 initializers can generate global data too
3526 (e.g. string pointers or ISOC99 compound
3527 literals). It also simplifies local
3528 initializers handling */
3529 init_len = 0;
3530 init_str = NULL;
3531 saved_macro_ptr = NULL; /* avoid warning */
3532 tok1 = 0;
3533 if (size < 0) {
3534 if (!has_init)
3535 error("unknown type size");
3536 /* get all init string */
3537 level = 0;
3538 while (level > 0 || (tok != ',' && tok != ';')) {
3539 if (tok < 0)
3540 error("unexpect end of file in initializer");
3541 tok_add2(&init_str, &init_len, tok, tokc);
3542 if (tok == '{')
3543 level++;
3544 else if (tok == '}') {
3545 if (level == 0)
3546 break;
3547 level--;
3549 next();
3551 tok1 = tok;
3552 tok_add(&init_str, &init_len, -1);
3553 tok_add(&init_str, &init_len, 0);
3555 /* compute size */
3556 saved_macro_ptr = macro_ptr;
3557 macro_ptr = init_str;
3558 next();
3559 decl_initializer(t, 0, 1, 1);
3560 /* prepare second initializer parsing */
3561 macro_ptr = init_str;
3562 next();
3564 /* if still unknown size, error */
3565 size = type_size(t, &align);
3566 if (size < 0)
3567 error("unknown type size");
3569 if ((t & VT_VALMASK) == VT_LOCAL) {
3570 loc = (loc - size) & -align;
3571 addr = loc;
3572 } else {
3573 glo = (glo + align - 1) & -align;
3574 addr = glo;
3575 /* very important to increment global
3576 pointer at this time because
3577 initializers themselves can create new
3578 initializers */
3579 glo += size;
3581 if (has_init) {
3582 decl_initializer(t, addr, 1, 0);
3583 /* restore parse state if needed */
3584 if (init_str) {
3585 free(init_str);
3586 macro_ptr = saved_macro_ptr;
3587 tok = tok1;
3590 return addr;
3594 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
3595 void decl(int l)
3597 int *a, t, b, v, u, addr, has_init, size, align;
3598 Sym *sym;
3600 while (1) {
3601 b = ist();
3602 if (!b) {
3603 /* skip redundant ';' */
3604 /* XXX: find more elegant solution */
3605 if (tok == ';') {
3606 next();
3607 continue;
3609 /* special test for old K&R protos without explicit int
3610 type. Only accepted when defining global data */
3611 if (l == VT_LOCAL || tok < TOK_DEFINE)
3612 break;
3613 b = VT_INT;
3615 if (((b & VT_BTYPE) == VT_ENUM ||
3616 (b & VT_BTYPE) == VT_STRUCT) &&
3617 tok == ';') {
3618 /* we accept no variable after */
3619 next();
3620 continue;
3622 while (1) { /* iterate thru each declaration */
3623 t = type_decl(&v, b, TYPE_DIRECT);
3624 if (tok == '{') {
3625 if (l == VT_LOCAL)
3626 error("cannot use local functions");
3627 if (!(t & VT_FUNC))
3628 expect("function definition");
3629 /* patch forward references */
3630 if ((sym = sym_find(v)) && (sym->t & VT_FORWARD)) {
3631 greloc_patch(sym, ind);
3632 sym->t = VT_CONST | t;
3633 } else {
3634 /* put function address */
3635 sym_push1(&global_stack, v, VT_CONST | t, ind);
3637 funcname = get_tok_str(v, 0);
3638 /* push a dummy symbol to enable local sym storage */
3639 sym_push1(&local_stack, 0, 0, 0);
3640 /* define parameters */
3641 sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3642 /* XXX: the following is x86 dependant -> move it to
3643 x86 code gen */
3644 addr = 8;
3645 /* if the function returns a structure, then add an
3646 implicit pointer parameter */
3647 func_vt = sym->t;
3648 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
3649 func_vc = addr;
3650 addr += 4;
3652 while (sym = sym->next) {
3653 u = sym->t;
3654 sym_push(sym->v & ~SYM_FIELD,
3655 u | VT_LOCAL | VT_LVAL,
3656 addr);
3657 if ((u & VT_BTYPE) == VT_STRUCT) {
3658 #ifdef FUNC_STRUCT_PARAM_AS_PTR
3659 /* structs are passed as pointer */
3660 size = 4;
3661 #else
3662 /* structs are directly put on stack (x86
3663 like) */
3664 size = type_size(u, &align);
3665 size = (size + 3) & ~3;
3666 #endif
3667 } else {
3668 /* XXX: size will be different someday */
3669 size = 4;
3671 addr += size;
3673 loc = 0;
3674 o(0xe58955); /* push %ebp, mov %esp, %ebp */
3675 a = (int *)oad(0xec81, 0); /* sub $xxx, %esp */
3676 rsym = 0;
3677 block(0, 0, 0, 0, 0);
3678 gsym(rsym);
3679 o(0xc3c9); /* leave, ret */
3680 *a = (-loc + 3) & -4; /* align local size to word &
3681 save local variables */
3682 sym_pop(&label_stack, NULL); /* reset label stack */
3683 sym_pop(&local_stack, NULL); /* reset local stack */
3684 funcname = ""; /* for safety */
3685 func_vt = VT_VOID; /* for safety */
3686 break;
3687 } else {
3688 if (b & VT_TYPEDEF) {
3689 /* save typedefed type */
3690 /* XXX: test storage specifiers ? */
3691 sym_push(v, t | VT_TYPEDEF, 0);
3692 } else if ((t & VT_BTYPE) == VT_FUNC) {
3693 /* external function definition */
3694 external_sym(v, t);
3695 } else {
3696 /* not lvalue if array */
3697 if (!(t & VT_ARRAY))
3698 t |= VT_LVAL;
3699 if (b & VT_EXTERN) {
3700 /* external variable */
3701 external_sym(v, t);
3702 } else {
3703 u = l;
3704 if (t & VT_STATIC)
3705 u = VT_CONST;
3706 u |= t;
3707 has_init = (tok == '=');
3708 if (has_init)
3709 next();
3710 addr = decl_initializer_alloc(u, has_init);
3711 if (l == VT_CONST) {
3712 /* global scope: see if already defined */
3713 sym = sym_find(v);
3714 if (!sym)
3715 goto do_def;
3716 if (!is_compatible_types(sym->t, u))
3717 error("incompatible types for redefinition of '%s'",
3718 get_tok_str(v, 0));
3719 if (!(sym->t & VT_FORWARD))
3720 error("redefinition of '%s'", get_tok_str(v, 0));
3721 greloc_patch(sym, addr);
3722 } else {
3723 do_def:
3724 sym_push(v, u, addr);
3728 if (tok != ',') {
3729 skip(';');
3730 break;
3732 next();
3738 /* put all global symbols in the extern stack and do all the
3739 resolving which can be done without using external symbols from DLLs */
3740 /* XXX: could try to verify types, but would not to save them in
3741 extern_stack too */
3742 void resolve_global_syms(void)
3744 Sym *s, *s1, *ext_sym;
3745 Reloc **p;
3747 s = global_stack.top;
3748 while (s != NULL) {
3749 s1 = s->prev;
3750 /* do not save static or typedefed symbols or types */
3751 if (!(s->t & (VT_STATIC | VT_TYPEDEF)) &&
3752 !(s->v & (SYM_FIELD | SYM_STRUCT)) &&
3753 (s->v < SYM_FIRST_ANOM)) {
3754 ext_sym = sym_find1(&extern_stack, s->v);
3755 if (!ext_sym) {
3756 /* if the symbol do not exist, we simply save it */
3757 sym_push1(&extern_stack, s->v, s->t, s->c);
3758 } else if (ext_sym->t & VT_FORWARD) {
3759 /* external symbol already exists, but only as forward
3760 definition */
3761 if (!(s->t & VT_FORWARD)) {
3762 /* s is not forward, so we can relocate all symbols */
3763 greloc_patch(ext_sym, s->c);
3764 } else {
3765 /* the two symbols are forward: merge them */
3766 p = (Reloc **)&ext_sym->c;
3767 while (*p != NULL)
3768 p = &(*p)->next;
3769 *p = (Reloc *)s->c;
3771 } else {
3772 /* external symbol already exists and is defined :
3773 patch all references to it */
3774 if (!(s->t & VT_FORWARD))
3775 error("'%s' defined twice", get_tok_str(s->v, 0));
3776 greloc_patch(s, ext_sym->c);
3779 s = s1;
3783 /* compile a C file. Return non zero if errors. */
3784 int tcc_compile_file(const char *filename1)
3786 Sym *define_start;
3788 filename = (char *)filename1;
3790 line_num = 1;
3791 funcname = "";
3792 file = fopen(filename, "r");
3793 if (!file)
3794 error("file '%s' not found", filename);
3795 include_stack_ptr = include_stack;
3796 ifdef_stack_ptr = ifdef_stack;
3798 vstack_ptr = vstack;
3799 anon_sym = SYM_FIRST_ANOM;
3801 define_start = define_stack.top;
3802 inp();
3803 ch = '\n'; /* needed to parse correctly first preprocessor command */
3804 next();
3805 decl(VT_CONST);
3806 if (tok != -1)
3807 expect("declaration");
3808 fclose(file);
3810 /* reset define stack, but leave -Dsymbols (may be incorrect if
3811 they are undefined) */
3812 sym_pop(&define_stack, define_start);
3814 resolve_global_syms();
3816 sym_pop(&global_stack, NULL);
3818 return 0;
3821 /* open a dynamic library so that its symbol are available for
3822 compiled programs */
3823 void open_dll(char *libname)
3825 char buf[1024];
3826 void *h;
3828 snprintf(buf, sizeof(buf), "lib%s.so", libname);
3829 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
3830 if (!h)
3831 error((char *)dlerror());
3834 void resolve_extern_syms(void)
3836 Sym *s, *s1;
3837 char *str;
3838 int addr;
3840 s = extern_stack.top;
3841 while (s != NULL) {
3842 s1 = s->prev;
3843 if (s->t & VT_FORWARD) {
3844 /* if there is at least one relocation to do, then find it
3845 and patch it */
3846 if (s->c) {
3847 str = get_tok_str(s->v, 0);
3848 addr = (int)dlsym(NULL, str);
3849 if (!addr)
3850 error("unresolved external reference '%s'", str);
3851 greloc_patch(s, addr);
3854 s = s1;
3858 /* output a binary file (for testing) */
3859 void build_exe(char *filename)
3861 FILE *f;
3862 f = fopen(filename, "w");
3863 fwrite((void *)prog, 1, ind - prog, f);
3864 fclose(f);
3867 int main(int argc, char **argv)
3869 Sym *s;
3870 int (*t)();
3871 char *p, *r, *outfile;
3872 int optind;
3874 include_paths[0] = "/usr/include";
3875 include_paths[1] = "/usr/lib/tcc";
3876 include_paths[2] = "/usr/local/lib/tcc";
3877 nb_include_paths = 3;
3879 /* add all tokens */
3880 tok_ident = TOK_IDENT;
3881 p = "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0register\0signed\0auto\0inline\0restrict\0float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0sizeof\0define\0include\0ifdef\0ifndef\0elif\0endif\0defined\0undef\0error\0line\0__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0__func__\0main\0";
3882 while (*p) {
3883 r = p;
3884 while (*r++);
3885 tok_alloc(p, r - p - 1);
3886 p = r;
3889 /* standard defines */
3890 define_symbol("__STDC__");
3891 #ifdef __i386__
3892 define_symbol("__i386__");
3893 #endif
3894 /* tiny C specific defines */
3895 define_symbol("__TINYC__");
3897 glo = (int)malloc(DATA_SIZE);
3898 memset((void *)glo, 0, DATA_SIZE);
3899 prog = (int)malloc(TEXT_SIZE);
3900 ind = prog;
3902 optind = 1;
3903 outfile = NULL;
3904 while (1) {
3905 if (optind >= argc) {
3906 show_help:
3907 printf("tcc version 0.9.2 - Tiny C Compiler - Copyright (C) 2001 Fabrice Bellard\n"
3908 "usage: tcc [-Idir] [-Dsym] [-llib] [-i infile] infile [infile_args...]\n");
3909 return 1;
3911 r = argv[optind];
3912 if (r[0] != '-')
3913 break;
3914 optind++;
3915 if (r[1] == 'I') {
3916 if (nb_include_paths >= INCLUDE_PATHS_MAX)
3917 error("too many include paths");
3918 include_paths[nb_include_paths++] = r + 2;
3919 } else if (r[1] == 'D') {
3920 define_symbol(r + 2);
3921 } else if (r[1] == 'l') {
3922 open_dll(r + 2);
3923 } else if (r[1] == 'i') {
3924 if (optind >= argc)
3925 goto show_help;
3926 tcc_compile_file(argv[optind++]);
3927 } else if (r[1] == 'o') {
3928 /* currently, only for testing, so not documented */
3929 if (optind >= argc)
3930 goto show_help;
3931 outfile = argv[optind++];
3932 } else {
3933 fprintf(stderr, "invalid option -- '%s'\n", r);
3934 exit(1);
3938 tcc_compile_file(argv[optind]);
3940 resolve_extern_syms();
3942 if (outfile) {
3943 build_exe(outfile);
3944 return 0;
3945 } else {
3946 s = sym_find1(&extern_stack, TOK_MAIN);
3947 if (!s || (s->t & VT_FORWARD))
3948 error("main() not defined");
3949 t = (int (*)())s->c;
3950 return (*t)(argc - optind, argv + optind);