fix function call and ! operator
[tinycc.git] / tcc.c
blob119ab807841dbd87699f806de21162a2a22f60d3
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 /* number of available temporary registers */
47 #define NB_REGS 3
48 /* return register for functions */
49 #define FUNC_RET_REG 0
50 /* defined if function parameters must be evaluated in reverse order */
51 #define INVERT_FUNC_PARAMS
52 /* defined if structures are passed as pointers. Otherwise structures
53 are directly pushed on stack. */
54 //#define FUNC_STRUCT_PARAM_AS_PTR
56 /* token symbol management */
57 typedef struct TokenSym {
58 struct TokenSym *hash_next;
59 int tok; /* token number */
60 int len;
61 char str[1];
62 } TokenSym;
64 /* symbol management */
65 typedef struct Sym {
66 int v; /* symbol token */
67 int t; /* associated type */
68 int c; /* associated number */
69 struct Sym *next; /* next related symbol */
70 struct Sym *prev; /* prev symbol in stack */
71 struct Sym *hash_next; /* next symbol in hash table */
72 } Sym;
74 typedef struct SymStack {
75 struct Sym *top;
76 struct Sym *hash[SYM_HASH_SIZE];
77 } SymStack;
79 /* relocation entry (currently only used for functions or variables */
80 typedef struct Reloc {
81 int type; /* type of relocation */
82 int addr; /* address of relocation */
83 struct Reloc *next; /* next relocation */
84 } Reloc;
86 #define RELOC_ADDR32 1 /* 32 bits relocation */
87 #define RELOC_REL32 2 /* 32 bits relative relocation */
90 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
91 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
92 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
94 #define FUNC_NEW 1 /* ansi function prototype */
95 #define FUNC_OLD 2 /* old function prototype */
96 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
98 /* field 'Sym.t' for macros */
99 #define MACRO_OBJ 0 /* object like macro */
100 #define MACRO_FUNC 1 /* function like macro */
102 /* type_decl() types */
103 #define TYPE_ABSTRACT 1 /* type without variable */
104 #define TYPE_DIRECT 2 /* type with variable */
106 typedef struct {
107 FILE *file;
108 char *filename;
109 int line_num;
110 } IncludeFile;
112 /* parser */
113 FILE *file;
114 int ch, ch1, tok, tokc, tok1, tok1c;
116 /* loc : local variable index
117 glo : global variable index
118 ind : output code ptr
119 rsym: return symbol
120 prog: output code
121 anon_sym: anonymous symbol index
123 int rsym, anon_sym,
124 prog, ind, loc, glo, vt, vc, const_wanted, line_num;
125 int global_expr; /* true if compound literals must be allocated
126 globally (used during initializers parsing */
127 int func_vt, func_vc; /* current function return type (used by
128 return instruction) */
129 int tok_ident;
130 TokenSym **table_ident;
131 TokenSym *hash_ident[TOK_HASH_SIZE];
132 char token_buf[STRING_MAX_SIZE + 1];
133 char *filename, *funcname;
134 /* contains global symbols which remain between each translation unit */
135 SymStack extern_stack;
136 SymStack define_stack, global_stack, local_stack, label_stack;
138 int vstack[VSTACK_SIZE], *vstack_ptr;
139 int *macro_ptr, *macro_ptr_allocated;
140 IncludeFile include_stack[INCLUDE_STACK_SIZE], *include_stack_ptr;
141 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
142 char *include_paths[INCLUDE_PATHS_MAX];
143 int nb_include_paths;
145 /* use GNU C extensions */
146 int gnu_ext = 1;
148 /* The current value can be: */
149 #define VT_VALMASK 0x000f
150 #define VT_CONST 0x000a /* constant in vc
151 (must be first non register value) */
152 #define VT_LLOCAL 0x000b /* lvalue, offset on stack */
153 #define VT_LOCAL 0x000c /* offset on stack */
154 #define VT_CMP 0x000d /* the value is stored in processor flags (in vc) */
155 #define VT_JMP 0x000e /* value is the consequence of jmp true */
156 #define VT_JMPI 0x000f /* value is the consequence of jmp false */
157 #define VT_LVAL 0x0010 /* var is an lvalue */
158 #define VT_LVALN -17 /* ~VT_LVAL */
159 #define VT_FORWARD 0x0020 /* value is forward reference
160 (only used for functions) */
162 /* types */
163 #define VT_INT 0
164 #define VT_VOID 0x00040
165 #define VT_BYTE 0x00080 /* signed byte type */
166 #define VT_PTR 0x00100 /* pointer increment */
167 #define VT_UNSIGNED 0x00200 /* unsigned type */
168 #define VT_ARRAY 0x00400 /* array type (only used in parsing) */
169 #define VT_ENUM 0x00800 /* enum definition */
170 #define VT_FUNC 0x01000 /* function type */
171 #define VT_STRUCT 0x002000 /* struct/union definition */
172 #define VT_SHORT 0x004000 /* short type */
173 #define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */
175 #define VT_TYPE 0xfffc7fc0 /* type mask */
177 /* storage */
178 #define VT_EXTERN 0x00008000 /* extern definition */
179 #define VT_STATIC 0x00010000 /* static variable */
180 #define VT_TYPEDEF 0x00020000 /* typedef definition */
183 /* token values */
185 /* warning: the following compare tokens depend on i386 asm code */
186 #define TOK_ULT 0x92
187 #define TOK_UGE 0x93
188 #define TOK_EQ 0x94
189 #define TOK_NE 0x95
190 #define TOK_ULE 0x96
191 #define TOK_UGT 0x97
192 #define TOK_LT 0x9c
193 #define TOK_GE 0x9d
194 #define TOK_LE 0x9e
195 #define TOK_GT 0x9f
197 #define TOK_LAND 0xa0
198 #define TOK_LOR 0xa1
200 #define TOK_DEC 0xa2
201 #define TOK_MID 0xa3 /* inc/dec, to void constant */
202 #define TOK_INC 0xa4
203 #define TOK_ARROW 0xa7
204 #define TOK_DOTS 0xa8 /* three dots */
205 #define TOK_SHR 0xa9 /* unsigned shift right */
206 #define TOK_UDIV 0xb0 /* unsigned division */
207 #define TOK_UMOD 0xb1 /* unsigned modulo */
208 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
209 #define TOK_NUM 0xb3 /* number in tokc */
210 #define TOK_CCHAR 0xb4 /* char constant in tokc */
211 #define TOK_STR 0xb5 /* pointer to string in tokc */
212 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
213 #define TOK_LCHAR 0xb7
214 #define TOK_LSTR 0xb8
216 #define TOK_SHL 0x01 /* shift left */
217 #define TOK_SAR 0x02 /* signed shift right */
219 /* assignement operators : normal operator or 0x80 */
220 #define TOK_A_MOD 0xa5
221 #define TOK_A_AND 0xa6
222 #define TOK_A_MUL 0xaa
223 #define TOK_A_ADD 0xab
224 #define TOK_A_SUB 0xad
225 #define TOK_A_DIV 0xaf
226 #define TOK_A_XOR 0xde
227 #define TOK_A_OR 0xfc
228 #define TOK_A_SHL 0x81
229 #define TOK_A_SAR 0x82
231 /* all identificators and strings have token above that */
232 #define TOK_IDENT 256
234 enum {
235 TOK_INT = TOK_IDENT,
236 TOK_VOID,
237 TOK_CHAR,
238 TOK_IF,
239 TOK_ELSE,
240 TOK_WHILE,
241 TOK_BREAK,
242 TOK_RETURN,
243 TOK_FOR,
244 TOK_EXTERN,
245 TOK_STATIC,
246 TOK_UNSIGNED,
247 TOK_GOTO,
248 TOK_DO,
249 TOK_CONTINUE,
250 TOK_SWITCH,
251 TOK_CASE,
253 /* ignored types Must have contiguous values */
254 TOK_CONST,
255 TOK_VOLATILE,
256 TOK_LONG,
257 TOK_REGISTER,
258 TOK_SIGNED,
259 TOK_AUTO,
260 TOK_INLINE,
261 TOK_RESTRICT,
263 /* unsupported type */
264 TOK_FLOAT,
265 TOK_DOUBLE,
267 TOK_SHORT,
268 TOK_STRUCT,
269 TOK_UNION,
270 TOK_TYPEDEF,
271 TOK_DEFAULT,
272 TOK_ENUM,
273 TOK_SIZEOF,
275 /* preprocessor only */
276 TOK_UIDENT, /* first "user" ident (not keyword) */
277 TOK_DEFINE = TOK_UIDENT,
278 TOK_INCLUDE,
279 TOK_IFDEF,
280 TOK_IFNDEF,
281 TOK_ELIF,
282 TOK_ENDIF,
283 TOK_DEFINED,
284 TOK_UNDEF,
285 TOK_ERROR,
286 TOK_LINE,
287 TOK___LINE__,
288 TOK___FILE__,
289 TOK___DATE__,
290 TOK___TIME__,
291 TOK___VA_ARGS__,
293 /* special identifiers */
294 TOK___FUNC__,
295 TOK_MAIN,
298 void sum();
299 void next(void);
300 void next_nomacro();
301 int expr_const();
302 void expr_eq();
303 void expr(void);
304 void decl(int l);
305 void decl_initializer(int t, int c, int first, int size_only);
306 int decl_initializer_alloc(int t, int has_init);
307 int gv(void);
308 void move_reg();
309 void save_reg();
310 void vpush(void);
311 int get_reg(void);
312 void macro_subst(int **tok_str, int *tok_len,
313 Sym **nested_list, int *macro_str);
314 int save_reg_forced(int r);
315 void vstore(void);
316 int type_size(int t, int *a);
317 int pointed_type(int t);
318 int pointed_size(int t);
319 int ist(void);
320 int type_decl(int *v, int t, int td);
322 #ifdef CONFIG_TCC_STATIC
324 #define RTLD_LAZY 0x001
325 #define RTLD_NOW 0x002
326 #define RTLD_GLOBAL 0x100
328 /* dummy function for profiling */
329 void *dlopen(const char *filename, int flag)
331 return NULL;
334 const char *dlerror(void)
336 return "error";
339 typedef struct TCCSyms {
340 char *str;
341 void *ptr;
342 } TCCSyms;
344 #define TCCSYM(a) { #a, &a, },
346 /* add the symbol you want here if no dynamic linking is done */
347 static TCCSyms tcc_syms[] = {
348 TCCSYM(printf)
349 TCCSYM(fprintf)
350 TCCSYM(fopen)
351 TCCSYM(fclose)
352 { NULL, NULL },
355 void *dlsym(void *handle, char *symbol)
357 TCCSyms *p;
358 p = tcc_syms;
359 while (p->str != NULL) {
360 if (!strcmp(p->str, symbol))
361 return p->ptr;
362 p++;
364 return NULL;
367 #endif
369 inline int isid(c)
371 return (c >= 'a' && c <= 'z') ||
372 (c >= 'A' && c <= 'Z') ||
373 c == '_';
376 inline int isnum(c)
378 return c >= '0' & c <= '9';
381 void printline()
383 IncludeFile *f;
384 for(f = include_stack; f < include_stack_ptr; f++)
385 fprintf(stderr, "In file included from %s:%d:\n",
386 f->filename, f->line_num);
387 fprintf(stderr, "%s:%d: ", filename, line_num);
390 void error(const char *fmt, ...)
392 va_list ap;
393 va_start(ap, fmt);
394 printline();
395 vfprintf(stderr, fmt, ap);
396 fprintf(stderr, "\n");
397 exit(1);
398 va_end(ap);
401 void expect(const char *msg)
403 error("%s expected", msg);
406 void warning(const char *msg)
408 printline();
409 fprintf(stderr, "warning: %s\n", msg);
412 void skip(c)
414 if (tok != c)
415 error("'%c' expected", c);
416 next();
419 void test_lvalue()
421 if (!(vt & VT_LVAL))
422 expect("lvalue");
425 TokenSym *tok_alloc(char *str, int len)
427 TokenSym *ts, **pts, **ptable;
428 int h, i;
430 if (len <= 0)
431 len = strlen(str);
432 h = 1;
433 for(i=0;i<len;i++)
434 h = ((h << 8) | (str[i] & 0xff)) % TOK_HASH_SIZE;
436 pts = &hash_ident[h];
437 while (1) {
438 ts = *pts;
439 if (!ts)
440 break;
441 if (ts->len == len && !memcmp(ts->str, str, len))
442 return ts;
443 pts = &(ts->hash_next);
445 /* expand token table if needed */
446 i = tok_ident - TOK_IDENT;
447 if ((i % TOK_ALLOC_INCR) == 0) {
448 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
449 if (!ptable)
450 error("memory full");
451 table_ident = ptable;
453 ts = malloc(sizeof(TokenSym) + len);
454 if (!ts || tok_ident >= SYM_FIRST_ANOM)
455 error("memory full");
456 table_ident[i] = ts;
457 ts->tok = tok_ident++;
458 ts->len = len;
459 ts->hash_next = NULL;
460 memcpy(ts->str, str, len + 1);
461 *pts = ts;
462 return ts;
465 void add_char(char **pp, int c)
467 char *p;
468 p = *pp;
469 if (c == '\'' || c == '\"' || c == '\\') {
470 /* XXX: could be more precise if char or string */
471 *p++ = '\\';
473 if (c >= 32 && c <= 126) {
474 *p++ = c;
475 } else {
476 *p++ = '\\';
477 if (c == '\n') {
478 *p++ = 'n';
479 } else {
480 *p++ = '0' + ((c >> 6) & 7);
481 *p++ = '0' + ((c >> 3) & 7);
482 *p++ = '0' + (c & 7);
485 *pp = p;
488 /* XXX: buffer overflow */
489 char *get_tok_str(int v, int c)
491 static char buf[STRING_MAX_SIZE + 1];
492 TokenSym *ts;
493 char *p;
494 int i;
496 if (v == TOK_NUM) {
497 sprintf(buf, "%d", c);
498 return buf;
499 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
500 p = buf;
501 *p++ = '\'';
502 add_char(&p, c);
503 *p++ = '\'';
504 *p = '\0';
505 return buf;
506 } else if (v == TOK_STR || v == TOK_LSTR) {
507 ts = (TokenSym *)c;
508 p = buf;
509 *p++ = '\"';
510 for(i=0;i<ts->len;i++)
511 add_char(&p, ts->str[i]);
512 *p++ = '\"';
513 *p = '\0';
514 return buf;
515 } else if (v < TOK_IDENT) {
516 p = buf;
517 *p++ = v;
518 *p = '\0';
519 return buf;
520 } else if (v < tok_ident) {
521 return table_ident[v - TOK_IDENT]->str;
522 } else {
523 /* should never happen */
524 return NULL;
528 /* push, without hashing */
529 Sym *sym_push2(Sym **ps, int v, int t, int c)
531 Sym *s;
532 s = malloc(sizeof(Sym));
533 if (!s)
534 error("memory full");
535 s->v = v;
536 s->t = t;
537 s->c = c;
538 s->next = NULL;
539 /* add in stack */
540 s->prev = *ps;
541 *ps = s;
542 return s;
545 /* find a symbol and return its associated structure. 's' is the top
546 of the symbol stack */
547 Sym *sym_find2(Sym *s, int v)
549 while (s) {
550 if (s->v == v)
551 return s;
552 s = s->prev;
554 return NULL;
557 /* find a symbol and return its associated structure. 'st' is the
558 symbol stack */
559 Sym *sym_find1(SymStack *st, int v)
561 Sym *s;
563 s = st->hash[v % SYM_HASH_SIZE];
564 while (s) {
565 if (s->v == v)
566 return s;
567 s = s->hash_next;
569 return 0;
572 Sym *sym_push1(SymStack *st, int v, int t, int c)
574 Sym *s, **ps;
575 s = sym_push2(&st->top, v, t, c);
576 /* add in hash table */
577 ps = &st->hash[s->v % SYM_HASH_SIZE];
578 s->hash_next = *ps;
579 *ps = s;
580 return s;
583 /* find a symbol in the right symbol space */
584 Sym *sym_find(int v)
586 Sym *s;
587 s = sym_find1(&local_stack, v);
588 if (!s)
589 s = sym_find1(&global_stack, v);
590 return s;
593 /* push a given symbol on the symbol stack */
594 Sym *sym_push(int v, int t, int c)
596 if (local_stack.top)
597 return sym_push1(&local_stack, v, t, c);
598 else
599 return sym_push1(&global_stack, v, t, c);
602 /* pop symbols until top reaches 'b' */
603 void sym_pop(SymStack *st, Sym *b)
605 Sym *s, *ss;
607 s = st->top;
608 while(s != b) {
609 ss = s->prev;
610 /* free hash table entry */
611 st->hash[s->v % SYM_HASH_SIZE] = s->hash_next;
612 free(s);
613 s = ss;
615 st->top = b;
618 /* undefined a hashed symbol (used for #undef). Its name is set to
619 zero */
620 void sym_undef(SymStack *st, Sym *s)
622 Sym **ss;
623 ss = &st->hash[s->v % SYM_HASH_SIZE];
624 while (*ss != NULL) {
625 if (*ss == s)
626 break;
627 ss = &(*ss)->hash_next;
629 *ss = s->hash_next;
630 s->v = 0;
633 /* no need to put that inline */
634 int handle_eof(void)
636 if (include_stack_ptr == include_stack)
637 return -1;
638 /* pop include stack */
639 fclose(file);
640 free(filename);
641 include_stack_ptr--;
642 file = include_stack_ptr->file;
643 filename = include_stack_ptr->filename;
644 line_num = include_stack_ptr->line_num;
645 return 0;
648 /* read next char from current input file */
649 static inline void inp(void)
651 redo:
652 /* faster than fgetc */
653 ch1 = getc_unlocked(file);
654 if (ch1 == -1) {
655 if (handle_eof() < 0)
656 return;
657 else
658 goto redo;
660 if (ch1 == '\n')
661 line_num++;
662 // printf("ch1=%c 0x%x\n", ch1, ch1);
665 /* input with '\\n' handling */
666 static inline void minp(void)
668 redo:
669 ch = ch1;
670 inp();
671 if (ch == '\\' && ch1 == '\n') {
672 inp();
673 goto redo;
675 //printf("ch=%c 0x%x\n", ch, ch);
679 /* same as minp, but also skip comments */
680 void cinp(void)
682 int c;
684 if (ch1 == '/') {
685 inp();
686 if (ch1 == '/') {
687 /* single line C++ comments */
688 inp();
689 while (ch1 != '\n' && ch1 != -1)
690 inp();
691 inp();
692 ch = ' '; /* return space */
693 } else if (ch1 == '*') {
694 /* C comments */
695 inp();
696 while (ch1 != -1) {
697 c = ch1;
698 inp();
699 if (c == '*' && ch1 == '/') {
700 inp();
701 ch = ' '; /* return space */
702 break;
705 } else {
706 ch = '/';
708 } else {
709 minp();
713 void skip_spaces(void)
715 while (ch == ' ' || ch == '\t')
716 cinp();
719 /* skip block of text until #else, #elif or #endif. skip also pairs of
720 #if/#endif */
721 void preprocess_skip()
723 int a;
724 a = 0;
725 while (1) {
726 while (ch != '\n') {
727 if (ch == -1)
728 expect("#endif");
729 cinp();
731 cinp();
732 skip_spaces();
733 if (ch == '#') {
734 cinp();
735 next_nomacro();
736 if (a == 0 &&
737 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
738 break;
739 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
740 a++;
741 else if (tok == TOK_ENDIF)
742 a--;
747 inline int is_long_tok(int t)
749 return (t == TOK_NUM ||
750 t == TOK_CCHAR || t == TOK_LCHAR ||
751 t == TOK_STR || t == TOK_LSTR);
754 void tok_add(int **tok_str, int *tok_len, int t)
756 int len, *str;
757 len = *tok_len;
758 str = *tok_str;
759 if ((len & 63) == 0) {
760 str = realloc(str, (len + 64) * sizeof(int));
761 if (!str)
762 return;
763 *tok_str = str;
765 str[len++] = t;
766 *tok_len = len;
769 void tok_add2(int **tok_str, int *tok_len, int t, int c)
771 tok_add(tok_str, tok_len, t);
772 if (is_long_tok(t))
773 tok_add(tok_str, tok_len, c);
776 /* eval an expression for #if/#elif */
777 int expr_preprocess()
779 int *str, len, c, t;
781 str = NULL;
782 len = 0;
783 while (1) {
784 skip_spaces();
785 if (ch == '\n')
786 break;
787 next(); /* do macro subst */
788 if (tok == TOK_DEFINED) {
789 next_nomacro();
790 t = tok;
791 if (t == '(')
792 next_nomacro();
793 c = sym_find1(&define_stack, tok) != 0;
794 if (t == '(')
795 next_nomacro();
796 tok = TOK_NUM;
797 tokc = c;
798 } else if (tok >= TOK_IDENT) {
799 /* if undefined macro */
800 tok = TOK_NUM;
801 tokc = 0;
803 tok_add2(&str, &len, tok, tokc);
805 tok_add(&str, &len, -1); /* simulate end of file */
806 tok_add(&str, &len, 0);
807 /* now evaluate C constant expression */
808 macro_ptr = str;
809 next();
810 c = expr_const();
811 macro_ptr = NULL;
812 free(str);
813 return c != 0;
816 #ifdef DEBUG
817 void tok_print(int *str)
819 int t, c;
821 while (1) {
822 t = *str++;
823 if (!t)
824 break;
825 c = 0;
826 if (is_long_tok(t))
827 c = *str++;
828 printf(" %s", get_tok_str(t, c));
830 printf("\n");
832 #endif
834 /* XXX: should be more factorized */
835 void define_symbol(char *sym)
837 TokenSym *ts;
838 int *str, len;
840 ts = tok_alloc(sym, 0);
841 str = NULL;
842 len = 0;
843 tok_add2(&str, &len, TOK_NUM, 1);
844 tok_add(&str, &len, 0);
845 sym_push1(&define_stack, ts->tok, MACRO_OBJ, (int)str);
848 void preprocess()
850 int size, i, c, v, t, *str, len;
851 char buf[1024], *q, *p;
852 char buf1[1024];
853 FILE *f;
854 Sym **ps, *first, *s;
856 cinp();
857 next_nomacro();
858 redo:
859 if (tok == TOK_DEFINE) {
860 next_nomacro();
861 v = tok;
862 /* XXX: should check if same macro (ANSI) */
863 first = NULL;
864 t = MACRO_OBJ;
865 /* '(' must be just after macro definition for MACRO_FUNC */
866 if (ch == '(') {
867 next_nomacro();
868 next_nomacro();
869 ps = &first;
870 while (tok != ')') {
871 if (tok == TOK_DOTS)
872 tok = TOK___VA_ARGS__;
873 s = sym_push1(&define_stack, tok | SYM_FIELD, 0, 0);
874 *ps = s;
875 ps = &s->next;
876 next_nomacro();
877 if (tok != ',')
878 break;
879 next_nomacro();
881 t = MACRO_FUNC;
883 str = NULL;
884 len = 0;
885 while (1) {
886 skip_spaces();
887 if (ch == '\n' || ch == -1)
888 break;
889 next_nomacro();
890 tok_add2(&str, &len, tok, tokc);
892 tok_add(&str, &len, 0);
893 #ifdef PP_DEBUG
894 printf("define %s %d: ", get_tok_str(v, 0), t);
895 tok_print(str);
896 #endif
897 s = sym_push1(&define_stack, v, t, (int)str);
898 s->next = first;
899 } else if (tok == TOK_UNDEF) {
900 next_nomacro();
901 s = sym_find1(&define_stack, tok);
902 /* undefine symbol by putting an invalid name */
903 if (s)
904 sym_undef(&define_stack, s);
905 } else if (tok == TOK_INCLUDE) {
906 skip_spaces();
907 if (ch == '<') {
908 c = '>';
909 goto read_name;
910 } else if (ch == '\"') {
911 c = ch;
912 read_name:
913 minp();
914 q = buf;
915 while (ch != c && ch != '\n' && ch != -1) {
916 if ((q - buf) < sizeof(buf) - 1)
917 *q++ = ch;
918 minp();
920 *q = '\0';
921 } else {
922 next();
923 if (tok != TOK_STR)
924 error("#include syntax error");
925 /* XXX: buffer overflow */
926 strcpy(buf, get_tok_str(tok, tokc));
927 c = '\"';
929 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
930 error("memory full");
931 if (c == '\"') {
932 /* first search in current dir if "header.h" */
933 /* XXX: buffer overflow */
934 size = 0;
935 p = strrchr(filename, '/');
936 if (p)
937 size = p + 1 - filename;
938 memcpy(buf1, filename, size);
939 buf1[size] = '\0';
940 strcat(buf1, buf);
941 f = fopen(buf1, "r");
942 if (f)
943 goto found;
945 /* now search in standard include path */
946 for(i=nb_include_paths - 1;i>=0;i--) {
947 strcpy(buf1, include_paths[i]);
948 strcat(buf1, "/");
949 strcat(buf1, buf);
950 f = fopen(buf1, "r");
951 if (f)
952 goto found;
954 error("include file '%s' not found", buf1);
955 f = NULL;
956 found:
957 /* push current file in stack */
958 /* XXX: fix current line init */
959 include_stack_ptr->file = file;
960 include_stack_ptr->filename = filename;
961 include_stack_ptr->line_num = line_num;
962 include_stack_ptr++;
963 file = f;
964 filename = strdup(buf1);
965 line_num = 1;
966 } else if (tok == TOK_IFNDEF) {
967 c = 1;
968 goto do_ifdef;
969 } else if (tok == TOK_IF) {
970 c = expr_preprocess();
971 goto do_if;
972 } else if (tok == TOK_IFDEF) {
973 c = 0;
974 do_ifdef:
975 next_nomacro();
976 c = (sym_find1(&define_stack, tok) != 0) ^ c;
977 do_if:
978 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
979 error("memory full");
980 *ifdef_stack_ptr++ = c;
981 goto test_skip;
982 } else if (tok == TOK_ELSE) {
983 if (ifdef_stack_ptr == ifdef_stack ||
984 (ifdef_stack_ptr[-1] & 2))
985 error("#else after #else");
986 c = (ifdef_stack_ptr[-1] ^= 3);
987 goto test_skip;
988 } else if (tok == TOK_ELIF) {
989 if (ifdef_stack_ptr == ifdef_stack ||
990 ifdef_stack_ptr[-1] > 1)
991 error("#elif after #else");
992 c = expr_preprocess();
993 ifdef_stack_ptr[-1] = c;
994 test_skip:
995 if (!(c & 1)) {
996 preprocess_skip();
997 goto redo;
999 } else if (tok == TOK_ENDIF) {
1000 if (ifdef_stack_ptr == ifdef_stack)
1001 expect("#if");
1002 ifdef_stack_ptr--;
1003 } else if (tok == TOK_LINE) {
1004 next();
1005 if (tok != TOK_NUM)
1006 error("#line");
1007 line_num = tokc;
1008 skip_spaces();
1009 if (ch != '\n') {
1010 next();
1011 if (tok != TOK_STR)
1012 error("#line");
1013 /* XXX: potential memory leak */
1014 filename = strdup(get_tok_str(tok, tokc));
1016 } else if (tok == TOK_ERROR) {
1017 error("#error");
1019 /* ignore other preprocess commands or #! for C scripts */
1020 while (ch != '\n' && ch != -1)
1021 cinp();
1024 /* read a number in base b */
1025 int getn(b)
1027 int n, t;
1028 n = 0;
1029 while (1) {
1030 if (ch >= 'a' & ch <= 'f')
1031 t = ch - 'a' + 10;
1032 else if (ch >= 'A' & ch <= 'F')
1033 t = ch - 'A' + 10;
1034 else if (isnum(ch))
1035 t = ch - '0';
1036 else
1037 break;
1038 if (t < 0 | t >= b)
1039 break;
1040 n = n * b + t;
1041 cinp();
1043 return n;
1046 /* read a character for string or char constant and eval escape codes */
1047 int getq()
1049 int c;
1051 c = ch;
1052 minp();
1053 if (c == '\\') {
1054 if (isnum(ch)) {
1055 /* at most three octal digits */
1056 c = ch - '0';
1057 minp();
1058 if (isnum(ch)) {
1059 c = c * 8 + ch - '0';
1060 minp();
1061 if (isnum(ch)) {
1062 c = c * 8 + ch - '0';
1063 minp();
1066 return c;
1067 } else if (ch == 'x') {
1068 minp();
1069 return getn(16);
1070 } else {
1071 if (ch == 'a')
1072 c = '\a';
1073 else if (ch == 'b')
1074 c = '\b';
1075 else if (ch == 'f')
1076 c = '\f';
1077 else if (ch == 'n')
1078 c = '\n';
1079 else if (ch == 'r')
1080 c = '\r';
1081 else if (ch == 't')
1082 c = '\t';
1083 else if (ch == 'v')
1084 c = '\v';
1085 else
1086 c = ch;
1087 minp();
1090 return c;
1093 /* return next token without macro substitution */
1094 void next_nomacro1()
1096 int b;
1097 char *q;
1098 TokenSym *ts;
1100 /* skip spaces */
1101 while(1) {
1102 while (ch == '\n') {
1103 cinp();
1104 while (ch == ' ' || ch == 9)
1105 cinp();
1106 if (ch == '#') {
1107 /* preprocessor command if # at start of line after
1108 spaces */
1109 preprocess();
1112 if (ch != ' ' && ch != '\t' && ch != '\f')
1113 break;
1114 cinp();
1116 if (isid(ch)) {
1117 q = token_buf;
1118 *q++ = ch;
1119 cinp();
1120 if (q[-1] == 'L') {
1121 if (ch == '\'') {
1122 tok = TOK_LCHAR;
1123 goto char_const;
1125 if (ch == '\"') {
1126 tok = TOK_LSTR;
1127 goto str_const;
1130 while (isid(ch) | isnum(ch)) {
1131 if (q >= token_buf + STRING_MAX_SIZE)
1132 error("ident too long");
1133 *q++ = ch;
1134 cinp();
1136 *q = '\0';
1137 ts = tok_alloc(token_buf, q - token_buf);
1138 tok = ts->tok;
1139 } else if (isnum(ch)) {
1140 /* number */
1141 b = 10;
1142 if (ch == '0') {
1143 cinp();
1144 b = 8;
1145 if (ch == 'x' || ch == 'X') {
1146 cinp();
1147 b = 16;
1148 } else if (ch == 'b' || ch == 'B') {
1149 cinp();
1150 b = 2;
1153 tokc = getn(b);
1154 /* XXX: add unsigned constant support (ANSI) */
1155 while (ch == 'L' || ch == 'l' || ch == 'U' || ch == 'u')
1156 cinp();
1157 tok = TOK_NUM;
1158 } else if (ch == '\'') {
1159 tok = TOK_CCHAR;
1160 char_const:
1161 minp();
1162 tokc = getq();
1163 if (ch != '\'')
1164 expect("\'");
1165 minp();
1166 } else if (ch == '\"') {
1167 tok = TOK_STR;
1168 str_const:
1169 minp();
1170 q = token_buf;
1171 while (ch != '\"') {
1172 b = getq();
1173 if (ch == -1)
1174 error("unterminated string");
1175 if (q >= token_buf + STRING_MAX_SIZE)
1176 error("string too long");
1177 *q++ = b;
1179 *q = '\0';
1180 tokc = (int)tok_alloc(token_buf, q - token_buf);
1181 minp();
1182 } else {
1183 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\247..\250##\266";
1184 /* two chars */
1185 tok = ch;
1186 cinp();
1187 while (*q) {
1188 if (*q == tok & q[1] == ch) {
1189 cinp();
1190 tok = q[2] & 0xff;
1191 /* three chars tests */
1192 if (tok == TOK_SHL | tok == TOK_SAR) {
1193 if (ch == '=') {
1194 tok = tok | 0x80;
1195 cinp();
1197 } else if (tok == TOK_DOTS) {
1198 if (ch != '.')
1199 error("parse error");
1200 cinp();
1202 return;
1204 q = q + 3;
1206 /* single char substitutions */
1207 if (tok == '<')
1208 tok = TOK_LT;
1209 else if (tok == '>')
1210 tok = TOK_GT;
1214 /* return next token without macro substitution. Can read input from
1215 macro_ptr buffer */
1216 void next_nomacro()
1218 if (macro_ptr) {
1219 tok = *macro_ptr;
1220 if (tok) {
1221 macro_ptr++;
1222 if (is_long_tok(tok))
1223 tokc = *macro_ptr++;
1225 } else {
1226 next_nomacro1();
1230 /* substitute args in macro_str and return allocated string */
1231 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
1233 int *st, last_tok, t, c, notfirst, *str, len;
1234 Sym *s;
1235 TokenSym *ts;
1237 str = NULL;
1238 len = 0;
1239 last_tok = 0;
1240 while(1) {
1241 t = *macro_str++;
1242 if (!t)
1243 break;
1244 if (t == '#') {
1245 /* stringize */
1246 t = *macro_str++;
1247 if (!t)
1248 break;
1249 s = sym_find2(args, t);
1250 if (s) {
1251 token_buf[0] = '\0';
1252 st = (int *)s->c;
1253 /* XXX: buffer overflow */
1254 notfirst = 0;
1255 while (*st) {
1256 if (notfirst)
1257 strcat(token_buf, " ");
1258 t = *st++;
1259 c = 0;
1260 if (is_long_tok(t))
1261 c = *st++;
1262 strcat(token_buf, get_tok_str(t, c));
1263 notfirst = 1;
1265 #ifdef PP_DEBUG
1266 printf("stringize: %s\n", token_buf);
1267 #endif
1268 /* add string */
1269 ts = tok_alloc(token_buf, 0);
1270 tok_add2(&str, &len, TOK_STR, (int)ts);
1271 } else {
1272 tok_add(&str, &len, t);
1274 } else if (is_long_tok(t)) {
1275 tok_add2(&str, &len, t, *macro_str++);
1276 } else {
1277 s = sym_find2(args, t);
1278 if (s) {
1279 st = (int *)s->c;
1280 /* if '##' is present before or after , no arg substitution */
1281 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
1282 while (*st)
1283 tok_add(&str, &len, *st++);
1284 } else {
1285 macro_subst(&str, &len, nested_list, st);
1287 } else {
1288 tok_add(&str, &len, t);
1291 last_tok = t;
1293 tok_add(&str, &len, 0);
1294 return str;
1297 /* handle the '##' operator */
1298 int *macro_twosharps(int *macro_str)
1300 TokenSym *ts;
1301 int *macro_str1, macro_str1_len, *macro_ptr1;
1302 int t, c;
1303 char *p;
1305 macro_str1 = NULL;
1306 macro_str1_len = 0;
1307 tok = 0;
1308 while (1) {
1309 next_nomacro();
1310 if (tok == 0)
1311 break;
1312 if (*macro_ptr == TOK_TWOSHARPS) {
1313 macro_ptr++;
1314 macro_ptr1 = macro_ptr;
1315 t = *macro_ptr;
1316 if (t) {
1317 macro_ptr++;
1318 c = 0;
1319 if (is_long_tok(t))
1320 c = *macro_ptr++;
1321 /* XXX: we handle only most common cases:
1322 ident + ident or ident + number */
1323 if (tok >= TOK_IDENT &&
1324 (t >= TOK_IDENT || t == TOK_NUM)) {
1325 /* XXX: buffer overflow */
1326 p = get_tok_str(tok, tokc);
1327 strcpy(token_buf, p);
1328 p = get_tok_str(t, c);
1329 strcat(token_buf, p);
1330 ts = tok_alloc(token_buf, 0);
1331 tok_add2(&macro_str1, &macro_str1_len, ts->tok, 0);
1332 } else {
1333 /* cannot merge tokens: skip '##' */
1334 macro_ptr = macro_ptr1;
1337 } else {
1338 tok_add2(&macro_str1, &macro_str1_len, tok, tokc);
1341 tok_add(&macro_str1, &macro_str1_len, 0);
1342 return macro_str1;
1347 /* do macro substitution of macro_str and add result to
1348 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1349 substituted. 'nested_list' is the list of all macros we got inside
1350 to avoid recursing. */
1351 void macro_subst(int **tok_str, int *tok_len,
1352 Sym **nested_list, int *macro_str)
1354 Sym *s, *args, *sa, *sa1;
1355 int *str, parlevel, len, *mstr, t, *saved_macro_ptr;
1356 int mstr_allocated, *macro_str1;
1358 saved_macro_ptr = macro_ptr;
1359 macro_ptr = macro_str;
1360 macro_str1 = NULL;
1361 if (macro_str) {
1362 /* first scan for '##' operator handling */
1363 macro_str1 = macro_twosharps(macro_str);
1364 macro_ptr = macro_str1;
1367 while (1) {
1368 next_nomacro();
1369 if (tok == 0)
1370 break;
1371 /* special macros */
1372 if (tok == TOK___LINE__) {
1373 tok_add2(tok_str, tok_len, TOK_NUM, line_num);
1374 } else if (tok == TOK___FILE__) {
1375 tok_add2(tok_str, tok_len, TOK_STR,
1376 (int)tok_alloc(filename, 0));
1377 } else if (tok == TOK___DATE__) {
1378 tok_add2(tok_str, tok_len, TOK_STR,
1379 (int)tok_alloc("Jan 1 1970", 0));
1380 } else if (tok == TOK___TIME__) {
1381 tok_add2(tok_str, tok_len, TOK_STR,
1382 (int)tok_alloc("00:00:00", 0));
1383 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
1384 /* if symbol is a macro, prepare substitution */
1385 /* if nested substitution, do nothing */
1386 if (sym_find2(*nested_list, tok))
1387 goto no_subst;
1388 mstr = (int *)s->c;
1389 mstr_allocated = 0;
1390 if (s->t == MACRO_FUNC) {
1391 /* NOTE: we do not use next_nomacro to avoid eating the
1392 next token. XXX: find better solution */
1393 if (macro_ptr) {
1394 t = *macro_ptr;
1395 } else {
1396 while (ch == ' ' || ch == '\t' || ch == '\n')
1397 cinp();
1398 t = ch;
1400 if (t != '(') /* no macro subst */
1401 goto no_subst;
1403 /* argument macro */
1404 next_nomacro();
1405 next_nomacro();
1406 args = NULL;
1407 sa = s->next;
1408 while (tok != ')' && sa) {
1409 len = 0;
1410 str = NULL;
1411 parlevel = 0;
1412 while ((parlevel > 0 ||
1413 (tok != ')' &&
1414 (tok != ',' ||
1415 sa->v == (TOK___VA_ARGS__ | SYM_FIELD)))) &&
1416 tok != -1) {
1417 if (tok == '(')
1418 parlevel++;
1419 else if (tok == ')')
1420 parlevel--;
1421 tok_add2(&str, &len, tok, tokc);
1422 next_nomacro();
1424 tok_add(&str, &len, 0);
1425 sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
1426 if (tok != ',')
1427 break;
1428 next_nomacro();
1429 sa = sa->next;
1431 if (tok != ')')
1432 expect(")");
1433 /* now subst each arg */
1434 mstr = macro_arg_subst(nested_list, mstr, args);
1435 /* free memory */
1436 sa = args;
1437 while (sa) {
1438 sa1 = sa->prev;
1439 free((int *)sa->c);
1440 free(sa);
1441 sa = sa1;
1443 mstr_allocated = 1;
1445 sym_push2(nested_list, s->v, 0, 0);
1446 macro_subst(tok_str, tok_len, nested_list, mstr);
1447 /* pop nested defined symbol */
1448 sa1 = *nested_list;
1449 *nested_list = sa1->prev;
1450 free(sa1);
1451 if (mstr_allocated)
1452 free(mstr);
1453 } else {
1454 no_subst:
1455 /* no need to add if reading input stream */
1456 if (!macro_str)
1457 return;
1458 tok_add2(tok_str, tok_len, tok, tokc);
1460 /* only replace one macro while parsing input stream */
1461 if (!macro_str)
1462 return;
1464 macro_ptr = saved_macro_ptr;
1465 if (macro_str1)
1466 free(macro_str1);
1469 /* return next token with macro substitution */
1470 void next()
1472 int len, *ptr;
1473 Sym *nested_list;
1475 /* special 'ungettok' case for label parsing */
1476 if (tok1) {
1477 tok = tok1;
1478 tokc = tok1c;
1479 tok1 = 0;
1480 } else {
1481 redo:
1482 if (!macro_ptr) {
1483 /* if not reading from macro substuted string, then try to substitute */
1484 len = 0;
1485 ptr = NULL;
1486 nested_list = NULL;
1487 macro_subst(&ptr, &len, &nested_list, NULL);
1488 if (ptr) {
1489 tok_add(&ptr, &len, 0);
1490 macro_ptr = ptr;
1491 macro_ptr_allocated = ptr;
1492 goto redo;
1494 if (tok == 0)
1495 goto redo;
1496 } else {
1497 next_nomacro();
1498 if (tok == 0) {
1499 /* end of macro string: free it */
1500 free(macro_ptr_allocated);
1501 macro_ptr = NULL;
1502 goto redo;
1506 #if defined(DEBUG)
1507 printf("token = %s\n", get_tok_str(tok, tokc));
1508 #endif
1511 void swap(int *p, int *q)
1513 int t;
1514 t = *p;
1515 *p = *q;
1516 *q = t;
1519 void vset(t, v)
1521 vt = t;
1522 vc = v;
1525 /******************************************************/
1526 /* X86 code generator */
1528 typedef struct GFuncContext {
1529 int args_size;
1530 } GFuncContext;
1532 void g(int c)
1534 *(char *)ind++ = c;
1537 void o(int c)
1539 while (c) {
1540 g(c);
1541 c = c / 256;
1545 void gen_le32(int c)
1547 g(c);
1548 g(c >> 8);
1549 g(c >> 16);
1550 g(c >> 24);
1553 /* add a new relocation entry to symbol 's' */
1554 void greloc(Sym *s, int addr, int type)
1556 Reloc *p;
1557 p = malloc(sizeof(Reloc));
1558 if (!p)
1559 error("memory full");
1560 p->type = type;
1561 p->addr = addr;
1562 p->next = (Reloc *)s->c;
1563 s->c = (int)p;
1566 /* patch each relocation entry with value 'val' */
1567 void greloc_patch(Sym *s, int val)
1569 Reloc *p, *p1;
1571 p = (Reloc *)s->c;
1572 while (p != NULL) {
1573 p1 = p->next;
1574 switch(p->type) {
1575 case RELOC_ADDR32:
1576 *(int *)p->addr = val;
1577 break;
1578 case RELOC_REL32:
1579 *(int *)p->addr = val - p->addr - 4;
1580 break;
1582 free(p);
1583 p = p1;
1585 s->c = val;
1586 s->t &= ~VT_FORWARD;
1589 /* output a symbol and patch all calls to it */
1590 void gsym_addr(t, a)
1592 int n;
1593 while (t) {
1594 n = *(int *)t; /* next value */
1595 *(int *)t = a - t - 4;
1596 t = n;
1600 void gsym(t)
1602 gsym_addr(t, ind);
1605 /* psym is used to put an instruction with a data field which is a
1606 reference to a symbol. It is in fact the same as oad ! */
1607 #define psym oad
1609 /* instruction + 4 bytes data. Return the address of the data */
1610 int oad(int c, int s)
1612 o(c);
1613 *(int *)ind = s;
1614 s = ind;
1615 ind = ind + 4;
1616 return s;
1619 /* output constant with relocation if 't & VT_FORWARD' is true */
1620 void gen_addr32(int c, int t)
1622 if (!(t & VT_FORWARD)) {
1623 gen_le32(c);
1624 } else {
1625 greloc((Sym *)c, ind, RELOC_ADDR32);
1626 gen_le32(0);
1630 /* XXX: generate correct pointer for forward references to functions */
1631 /* r = (ft, fc) */
1632 void load(r, ft, fc)
1634 int v, t;
1636 v = ft & VT_VALMASK;
1637 if (ft & VT_LVAL) {
1638 if (v == VT_LLOCAL) {
1639 load(r, VT_LOCAL | VT_LVAL, fc);
1640 v = r;
1642 if ((ft & VT_TYPE) == VT_BYTE)
1643 o(0xbe0f); /* movsbl */
1644 else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED))
1645 o(0xb60f); /* movzbl */
1646 else if ((ft & VT_TYPE) == VT_SHORT)
1647 o(0xbf0f); /* movswl */
1648 else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED))
1649 o(0xb70f); /* movzwl */
1650 else
1651 o(0x8b); /* movl */
1652 if (v == VT_CONST) {
1653 o(0x05 + r * 8); /* 0xXX, r */
1654 gen_addr32(fc, ft);
1655 } else if (v == VT_LOCAL) {
1656 oad(0x85 + r * 8, fc); /* xx(%ebp), r */
1657 } else {
1658 g(0x00 + r * 8 + v); /* (v), r */
1660 } else {
1661 if (v == VT_CONST) {
1662 o(0xb8 + r); /* mov $xx, r */
1663 gen_addr32(fc, ft);
1664 } else if (v == VT_LOCAL) {
1665 o(0x8d);
1666 oad(0x85 + r * 8, fc); /* lea xxx(%ebp), r */
1667 } else if (v == VT_CMP) {
1668 oad(0xb8 + r, 0); /* mov $0, r */
1669 o(0x0f); /* setxx %br */
1670 o(fc);
1671 o(0xc0 + r);
1672 } else if (v == VT_JMP || v == VT_JMPI) {
1673 t = v & 1;
1674 oad(0xb8 + r, t); /* mov $1, r */
1675 oad(0xe9, 5); /* jmp after */
1676 gsym(fc);
1677 oad(0xb8 + r, t ^ 1); /* mov $0, r */
1678 } else if (v != r) {
1679 o(0x89);
1680 o(0xc0 + r + v * 8); /* mov v, r */
1685 /* (ft, fc) = r */
1686 /* WARNING: r must not be allocated on the stack */
1687 void store(r, ft, fc)
1689 int fr, b;
1691 fr = ft & VT_VALMASK;
1692 b = (ft & VT_TYPE) == VT_BYTE;
1693 /* XXX: incorrect if reg to reg */
1694 if (ft & VT_SHORT)
1695 o(0x66);
1696 o(0x89 - b);
1697 if (fr == VT_CONST) {
1698 o(0x05 + r * 8); /* mov r,xxx */
1699 gen_addr32(fc, ft);
1700 } else if (fr == VT_LOCAL) {
1701 oad(0x85 + r * 8, fc); /* mov r,xxx(%ebp) */
1702 } else if (ft & VT_LVAL) {
1703 g(fr + r * 8); /* mov r, (fr) */
1704 } else if (fr != r) {
1705 o(0xc0 + fr + r * 8); /* mov r, fr */
1709 /* start function call and return function call context */
1710 void gfunc_start(GFuncContext *c)
1712 c->args_size = 0;
1715 /* push function parameter which is in (vt, vc) */
1716 void gfunc_param(GFuncContext *c)
1718 int size, align, ft, fc, r;
1720 if ((vt & (VT_STRUCT | VT_LVAL)) == (VT_STRUCT | VT_LVAL)) {
1721 size = type_size(vt, &align);
1722 /* align to stack align size */
1723 size = (size + 3) & ~3;
1724 /* allocate the necessary size on stack */
1725 oad(0xec81, size); /* sub $xxx, %esp */
1726 /* generate structure store */
1727 r = get_reg();
1728 o(0x89); /* mov %esp, r */
1729 o(0xe0 + r);
1730 ft = vt;
1731 fc = vc;
1732 vset(VT_INT | r, 0);
1733 vpush();
1734 vt = ft;
1735 vc = fc;
1736 vstore();
1737 c->args_size += size;
1738 } else {
1739 /* simple type (currently always same size) */
1740 /* XXX: implicit cast ? */
1741 r = gv();
1742 o(0x50 + r); /* push r */
1743 c->args_size += 4;
1747 /* generate function call with address in (vt, vc) and free function
1748 context */
1749 void gfunc_call(GFuncContext *c)
1751 int r;
1752 if ((vt & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1753 /* constant case */
1754 /* forward reference */
1755 if (vt & VT_FORWARD) {
1756 greloc((Sym *)vc, ind + 1, RELOC_REL32);
1757 oad(0xe8, 0);
1758 } else {
1759 oad(0xe8, vc - ind - 5);
1761 } else {
1762 /* otherwise, indirect call */
1763 r = gv();
1764 o(0xff); /* call *r */
1765 o(0xd0 + r);
1767 if (c->args_size)
1768 oad(0xc481, c->args_size); /* add $xxx, %esp */
1771 int gjmp(int t)
1773 return psym(0xe9, t);
1776 /* generate a test. set 'inv' to invert test */
1777 int gtst(int inv, int t)
1779 int v, *p;
1780 v = vt & VT_VALMASK;
1781 if (v == VT_CMP) {
1782 /* fast case : can jump directly since flags are set */
1783 g(0x0f);
1784 t = psym((vc - 16) ^ inv, t);
1785 } else if (v == VT_JMP || v == VT_JMPI) {
1786 /* && or || optimization */
1787 if ((v & 1) == inv) {
1788 /* insert vc jump list in t */
1789 p = &vc;
1790 while (*p != 0)
1791 p = (int *)*p;
1792 *p = t;
1793 t = vc;
1794 } else {
1795 t = gjmp(t);
1796 gsym(vc);
1798 } else if ((vt & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1799 /* constant jmp optimization */
1800 if ((vc != 0) != inv)
1801 t = gjmp(t);
1802 } else {
1803 v = gv();
1804 o(0x85);
1805 o(0xc0 + v * 9);
1806 g(0x0f);
1807 t = psym(0x85 ^ inv, t);
1809 return t;
1812 /* generate a binary operation 'v = r op fr' instruction and modifies
1813 (vt,vc) if needed */
1814 void gen_op1(int op, int r, int fr)
1816 int t;
1817 if (op == '+') {
1818 o(0x01);
1819 o(0xc0 + r + fr * 8);
1820 } else if (op == '-') {
1821 o(0x29);
1822 o(0xc0 + r + fr * 8);
1823 } else if (op == '&') {
1824 o(0x21);
1825 o(0xc0 + r + fr * 8);
1826 } else if (op == '^') {
1827 o(0x31);
1828 o(0xc0 + r + fr * 8);
1829 } else if (op == '|') {
1830 o(0x09);
1831 o(0xc0 + r + fr * 8);
1832 } else if (op == '*') {
1833 o(0xaf0f); /* imul fr, r */
1834 o(0xc0 + fr + r * 8);
1835 } else if (op == TOK_SHL | op == TOK_SHR | op == TOK_SAR) {
1836 /* op2 is %ecx */
1837 if (fr != 1) {
1838 if (r == 1) {
1839 r = fr;
1840 fr = 1;
1841 o(0x87); /* xchg r, %ecx */
1842 o(0xc1 + r * 8);
1843 } else
1844 move_reg(1, fr);
1846 o(0xd3); /* shl/shr/sar %cl, r */
1847 if (op == TOK_SHL)
1848 o(0xe0 + r);
1849 else if (op == TOK_SHR)
1850 o(0xe8 + r);
1851 else
1852 o(0xf8 + r);
1853 vt = (vt & VT_TYPE) | r;
1854 } else if (op == '/' | op == TOK_UDIV | op == TOK_PDIV |
1855 op == '%' | op == TOK_UMOD) {
1856 save_reg(2); /* save edx */
1857 t = save_reg_forced(fr); /* save fr and get op2 location */
1858 move_reg(0, r); /* op1 is %eax */
1859 if (op == TOK_UDIV | op == TOK_UMOD) {
1860 o(0xf7d231); /* xor %edx, %edx, div t(%ebp), %eax */
1861 oad(0xb5, t);
1862 } else {
1863 o(0xf799); /* cltd, idiv t(%ebp), %eax */
1864 oad(0xbd, t);
1866 if (op == '%' | op == TOK_UMOD)
1867 r = 2;
1868 else
1869 r = 0;
1870 vt = (vt & VT_TYPE) | r;
1871 } else {
1872 o(0x39);
1873 o(0xc0 + r + fr * 8); /* cmp fr, r */
1874 vset(VT_CMP, op);
1878 /* end of X86 code generator */
1879 /*************************************************************/
1881 int save_reg_forced(int r)
1883 int i, l, *p, t;
1884 /* store register */
1885 loc = (loc - 4) & -3;
1886 store(r, VT_LOCAL, loc);
1887 l = loc;
1889 /* modify all stack values */
1890 for(p=vstack;p<vstack_ptr;p+=2) {
1891 i = p[0] & VT_VALMASK;
1892 if (i == r) {
1893 if (p[0] & VT_LVAL)
1894 t = VT_LLOCAL;
1895 else
1896 t = VT_LOCAL;
1897 p[0] = (p[0] & VT_TYPE) | VT_LVAL | t;
1898 p[1] = l;
1901 return l;
1904 /* save r to memory. and mark it as being free */
1905 void save_reg(r)
1907 int i, *p;
1909 /* modify all stack values */
1910 for(p=vstack;p<vstack_ptr;p+=2) {
1911 i = p[0] & VT_VALMASK;
1912 if (i == r) {
1913 save_reg_forced(r);
1914 break;
1919 /* find a free register. If none, save one register */
1920 int get_reg(void)
1922 int r, i, *p;
1924 /* find a free register */
1925 for(r=0;r<NB_REGS;r++) {
1926 for(p=vstack;p<vstack_ptr;p+=2) {
1927 i = p[0] & VT_VALMASK;
1928 if (i == r)
1929 goto notfound;
1931 return r;
1932 notfound: ;
1935 /* no register left : free the first one on the stack (very
1936 important to start from the bottom to ensure that we don't
1937 spill registers used in gen_op()) */
1938 for(p=vstack;p<vstack_ptr;p+=2) {
1939 r = p[0] & VT_VALMASK;
1940 if (r < VT_CONST) {
1941 save_reg(r);
1942 break;
1945 return r;
1948 void save_regs()
1950 int r, *p;
1951 for(p=vstack;p<vstack_ptr;p+=2) {
1952 r = p[0] & VT_VALMASK;
1953 if (r < VT_CONST) {
1954 save_reg(r);
1959 /* move register 's' to 'r', and flush previous value of r to memory
1960 if needed */
1961 void move_reg(r, s)
1963 if (r != s) {
1964 save_reg(r);
1965 load(r, s, 0);
1969 /* convert a stack entry in register. lvalues are converted as
1970 values. Cannot be used if cannot be converted to register value
1971 (such as structures). */
1972 int gvp(int *p)
1974 int r;
1975 r = p[0] & VT_VALMASK;
1976 if (r >= VT_CONST || (p[0] & VT_LVAL))
1977 r = get_reg();
1978 /* NOTE: get_reg can modify p[] */
1979 load(r, p[0], p[1]);
1980 p[0] = (p[0] & VT_TYPE) | r;
1981 return r;
1984 void vpush(void)
1986 if (vstack_ptr >= vstack + VSTACK_SIZE)
1987 error("memory full");
1988 *vstack_ptr++ = vt;
1989 *vstack_ptr++ = vc;
1990 /* cannot let cpu flags if other instruction are generated */
1991 /* XXX: VT_JMP test too ? */
1992 if ((vt & VT_VALMASK) == VT_CMP)
1993 gvp(vstack_ptr - 2);
1996 void vpop(int *ft, int *fc)
1998 *fc = *--vstack_ptr;
1999 *ft = *--vstack_ptr;
2002 /* generate a value in a register from vt and vc */
2003 int gv(void)
2005 int r;
2006 vpush();
2007 r = gvp(vstack_ptr - 2);
2008 vpop(&vt, &vc);
2009 return r;
2012 /* handle constant optimizations and various machine independant opt */
2013 void gen_opc(op)
2015 int fr, ft, fc, r, c1, c2, n;
2017 vpop(&ft, &fc);
2018 vpop(&vt, &vc);
2019 c1 = (vt & (VT_VALMASK | VT_LVAL)) == VT_CONST;
2020 c2 = (ft & (VT_VALMASK | VT_LVAL)) == VT_CONST;
2021 if (c1 && c2) {
2022 switch(op) {
2023 case '+': vc += fc; break;
2024 case '-': vc -= fc; break;
2025 case '&': vc &= fc; break;
2026 case '^': vc ^= fc; break;
2027 case '|': vc |= fc; break;
2028 case '*': vc *= fc; break;
2029 case TOK_PDIV:
2030 case '/': vc /= fc; break; /* XXX: zero case ? */
2031 case '%': vc %= fc; break; /* XXX: zero case ? */
2032 case TOK_UDIV: vc = (unsigned)vc / fc; break; /* XXX: zero case ? */
2033 case TOK_UMOD: vc = (unsigned)vc % fc; break; /* XXX: zero case ? */
2034 case TOK_SHL: vc <<= fc; break;
2035 case TOK_SHR: vc = (unsigned)vc >> fc; break;
2036 case TOK_SAR: vc >>= fc; break;
2037 /* tests */
2038 case TOK_ULT: vc = (unsigned)vc < (unsigned)fc; break;
2039 case TOK_UGE: vc = (unsigned)vc >= (unsigned)fc; break;
2040 case TOK_EQ: vc = vc == fc; break;
2041 case TOK_NE: vc = vc != fc; break;
2042 case TOK_ULE: vc = (unsigned)vc <= (unsigned)fc; break;
2043 case TOK_UGT: vc = (unsigned)vc > (unsigned)fc; break;
2044 case TOK_LT: vc = vc < fc; break;
2045 case TOK_GE: vc = vc >= fc; break;
2046 case TOK_LE: vc = vc <= fc; break;
2047 case TOK_GT: vc = vc > fc; break;
2048 /* logical */
2049 case TOK_LAND: vc = vc && fc; break;
2050 case TOK_LOR: vc = vc || fc; break;
2051 default:
2052 goto general_case;
2054 } else {
2055 /* if commutative ops, put c2 as constant */
2056 if (c1 && (op == '+' || op == '&' || op == '^' ||
2057 op == '|' || op == '*')) {
2058 swap(&vt, &ft);
2059 swap(&vc, &fc);
2060 swap(&c1, &c2);
2062 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
2063 op == TOK_PDIV) &&
2064 fc == 1) ||
2065 ((op == '+' || op == '-' || op == '|' || op == '^' ||
2066 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
2067 fc == 0) ||
2068 (op == '&' &&
2069 fc == -1))) {
2070 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
2071 /* try to use shifts instead of muls or divs */
2072 if (fc > 0 && (fc & (fc - 1)) == 0) {
2073 n = -1;
2074 while (fc) {
2075 fc >>= 1;
2076 n++;
2078 fc = n;
2079 if (op == '*')
2080 op = TOK_SHL;
2081 else if (op == TOK_PDIV)
2082 op = TOK_SAR;
2083 else
2084 op = TOK_SHR;
2086 goto general_case;
2087 } else {
2088 general_case:
2089 vpush();
2090 vt = ft;
2091 vc = fc;
2092 vpush();
2093 r = gvp(vstack_ptr - 4);
2094 fr = gvp(vstack_ptr - 2);
2095 vpop(&ft, &fc);
2096 vpop(&vt, &vc);
2097 /* call low level op generator */
2098 gen_op1(op, r, fr);
2103 int pointed_size(int t)
2105 return type_size(pointed_type(t), &t);
2108 /* generic gen_op: handles types problems */
2109 void gen_op(int op)
2111 int u, t1, t2;
2113 vpush();
2114 t1 = vstack_ptr[-4];
2115 t2 = vstack_ptr[-2];
2116 if (op == '+' | op == '-') {
2117 if ((t1 & VT_PTR) && (t2 & VT_PTR)) {
2118 if (op != '-')
2119 error("invalid type");
2120 /* XXX: check that types are compatible */
2121 u = pointed_size(t1);
2122 gen_opc(op);
2123 vpush();
2124 vstack_ptr[-2] &= ~VT_TYPE; /* set to integer */
2125 vset(VT_CONST, u);
2126 gen_op(TOK_PDIV);
2127 } else if ((t1 | t2) & VT_PTR) {
2128 if (t2 & VT_PTR) {
2129 swap(vstack_ptr - 4, vstack_ptr - 2);
2130 swap(vstack_ptr - 3, vstack_ptr - 1);
2131 swap(&t1, &t2);
2133 /* stack-4 contains pointer, stack-2 value to add */
2134 vset(VT_CONST, pointed_size(vstack_ptr[-4]));
2135 gen_op('*');
2136 vpush();
2137 gen_opc(op);
2138 /* put again type if gen_opc() swaped operands */
2139 vt = (vt & ~VT_TYPE) | (t1 & VT_TYPE);
2140 } else {
2141 gen_opc(op);
2143 } else {
2144 /* XXX: test types and compute returned value */
2145 if ((t1 | t2) & (VT_UNSIGNED | VT_PTR)) {
2146 if (op == TOK_SAR)
2147 op = TOK_SHR;
2148 else if (op == '/')
2149 op = TOK_UDIV;
2150 else if (op == '%')
2151 op = TOK_UMOD;
2152 else if (op == TOK_LT)
2153 op = TOK_ULT;
2154 else if (op == TOK_GT)
2155 op = TOK_UGT;
2156 else if (op == TOK_LE)
2157 op = TOK_ULE;
2158 else if (op == TOK_GE)
2159 op = TOK_UGE;
2161 gen_opc(op);
2165 /* cast (vt, vc) to 't' type */
2166 void gen_cast(int t)
2168 int r, bits;
2169 r = vt & VT_VALMASK;
2170 if (!(t & VT_LVAL)) {
2171 /* if not lvalue, then we convert now */
2172 if ((t & VT_TYPE & ~VT_UNSIGNED) == VT_BYTE)
2173 bits = 8;
2174 else if ((t & VT_TYPE & ~VT_UNSIGNED) == VT_SHORT)
2175 bits = 16;
2176 else
2177 goto the_end;
2178 vpush();
2179 if (t & VT_UNSIGNED) {
2180 vset(VT_CONST, (1 << bits) - 1);
2181 gen_op('&');
2182 } else {
2183 bits = 32 - bits;
2184 vset(VT_CONST, bits);
2185 gen_op(TOK_SHL);
2186 vpush();
2187 vset(VT_CONST, bits);
2188 gen_op(TOK_SAR);
2191 the_end:
2192 vt = (vt & ~VT_TYPE) | t;
2195 /* return type size. Put alignment at 'a' */
2196 int type_size(int t, int *a)
2198 Sym *s;
2200 /* int, enum or pointer */
2201 if (t & VT_STRUCT) {
2202 /* struct/union */
2203 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
2204 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
2205 return s->c;
2206 } else if (t & VT_ARRAY) {
2207 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
2208 return type_size(s->t, a) * s->c;
2209 } else if ((t & VT_PTR) ||
2210 (t & VT_TYPE & ~VT_UNSIGNED) == VT_INT ||
2211 (t & VT_ENUM)) {
2212 *a = 4;
2213 return 4;
2214 } else if (t & VT_SHORT) {
2215 *a = 2;
2216 return 2;
2217 } else {
2218 *a = 1;
2219 return 1;
2223 /* return the pointed type of t */
2224 int pointed_type(int t)
2226 Sym *s;
2227 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
2228 return s->t | (t & ~VT_TYPE);
2231 int mk_pointer(int t)
2233 int p;
2234 p = anon_sym++;
2235 sym_push(p, t, -1);
2236 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
2239 /* store value in lvalue pushed on stack */
2240 void vstore(void)
2242 int ft, fc, r, t, size, align;
2243 GFuncContext gf;
2245 if (vt & VT_STRUCT) {
2246 /* if structure, only generate pointer */
2247 /* structure assignment : generate memcpy */
2248 /* XXX: optimize if small size */
2250 gfunc_start(&gf);
2251 /* type size */
2252 ft = vt;
2253 fc = vc;
2254 size = type_size(vt, &align);
2255 vset(VT_CONST, size);
2256 gfunc_param(&gf);
2257 /* source */
2258 vt = ft & ~VT_LVAL;
2259 vc = fc;
2260 gfunc_param(&gf);
2261 /* destination */
2262 vpop(&vt, &vc);
2263 vt &= ~VT_LVAL;
2264 gfunc_param(&gf);
2266 save_regs();
2267 vset(VT_CONST, (int)&memcpy);
2268 gfunc_call(&gf);
2270 /* generate again current type */
2271 vt = ft;
2272 vc = fc;
2273 } else {
2274 r = gv(); /* generate value */
2275 vpush();
2276 ft = vstack_ptr[-4];
2277 fc = vstack_ptr[-3];
2278 /* if lvalue was saved on stack, must read it */
2279 if ((ft & VT_VALMASK) == VT_LLOCAL) {
2280 t = get_reg();
2281 load(t, VT_LOCAL | VT_LVAL, fc);
2282 ft = (ft & ~VT_VALMASK) | t;
2284 store(r, ft, fc);
2285 vstack_ptr -= 4;
2289 /* post defines POST/PRE add. c is the token ++ or -- */
2290 void inc(post, c)
2292 int r, r1;
2293 test_lvalue();
2294 if (post)
2295 vpush(); /* room for returned value */
2296 vpush(); /* save lvalue */
2297 r = gv();
2298 vpush(); /* save value */
2299 if (post) {
2300 /* duplicate value */
2301 r1 = get_reg();
2302 load(r1, r, 0); /* move r to r1 */
2303 vstack_ptr[-6] = (vt & VT_TYPE) | r1;
2304 vstack_ptr[-5] = 0;
2306 /* add constant */
2307 vset(VT_CONST, c - TOK_MID);
2308 gen_op('+');
2309 vstore(); /* store value */
2310 if (post)
2311 vpop(&vt, &vc);
2314 /* enum/struct/union declaration */
2315 int struct_decl(int u)
2317 int a, t, b, v, size, align, maxalign, c;
2318 Sym *s, *ss, **ps;
2320 a = tok; /* save decl type */
2321 next();
2322 if (tok != '{') {
2323 v = tok;
2324 next();
2325 /* struct already defined ? return it */
2326 /* XXX: check consistency */
2327 if (s = sym_find(v | SYM_STRUCT)) {
2328 if (s->t != a)
2329 error("invalid type");
2330 goto do_decl;
2332 } else {
2333 v = anon_sym++;
2335 s = sym_push(v | SYM_STRUCT, a, 0);
2336 /* put struct/union/enum name in type */
2337 do_decl:
2338 u = u | (v << VT_STRUCT_SHIFT);
2340 if (tok == '{') {
2341 next();
2342 if (s->c)
2343 error("struct/union/enum already defined");
2344 /* cannot be empty */
2345 c = 0;
2346 maxalign = 0;
2347 ps = &s->next;
2348 while (1) {
2349 if (a == TOK_ENUM) {
2350 v = tok;
2351 next();
2352 if (tok == '=') {
2353 next();
2354 c = expr_const();
2356 /* enum symbols have static storage */
2357 sym_push(v, VT_CONST | VT_STATIC, c);
2358 if (tok == ',')
2359 next();
2360 c++;
2361 } else {
2362 b = ist();
2363 while (1) {
2364 t = type_decl(&v, b, TYPE_DIRECT);
2365 if (t & (VT_FUNC | VT_TYPEDEF))
2366 error("invalid type");
2367 /* XXX: align & correct type size */
2368 v |= SYM_FIELD;
2369 size = type_size(t, &align);
2370 if (a == TOK_STRUCT) {
2371 c = (c + align - 1) & -align;
2372 ss = sym_push(v, t, c);
2373 c += size;
2374 } else {
2375 ss = sym_push(v, t, 0);
2376 if (size > c)
2377 c = size;
2379 if (align > maxalign)
2380 maxalign = align;
2381 *ps = ss;
2382 ps = &ss->next;
2383 if (tok == ';' || tok == -1)
2384 break;
2385 skip(',');
2387 skip(';');
2389 if (tok == '}')
2390 break;
2392 skip('}');
2393 /* size for struct/union, dummy for enum */
2394 s->c = (c + maxalign - 1) & -maxalign;
2396 return u;
2399 /* return 0 if no type declaration. otherwise, return the basic type
2400 and skip it.
2401 XXX: A '2' is ored to ensure non zero return if int type.
2403 int ist(void)
2405 int t;
2406 Sym *s;
2408 t = 0;
2409 while(1) {
2410 if (tok == TOK_ENUM) {
2411 t |= struct_decl(VT_ENUM);
2412 } else if (tok == TOK_STRUCT || tok == TOK_UNION) {
2413 t |= struct_decl(VT_STRUCT);
2414 } else {
2415 if (tok == TOK_CHAR) {
2416 t |= VT_BYTE;
2417 } else if (tok == TOK_VOID) {
2418 t |= VT_VOID;
2419 } else if (tok == TOK_SHORT) {
2420 t |= VT_SHORT;
2421 } else if (tok == TOK_INT |
2422 (tok >= TOK_CONST & tok <= TOK_INLINE)) {
2423 /* ignored types */
2424 } else if (tok == TOK_FLOAT || tok == TOK_DOUBLE) {
2425 /* We allow that to compile standard headers */
2426 // warning("floats not supported");
2427 } else if (tok == TOK_EXTERN) {
2428 t |= VT_EXTERN;
2429 } else if (tok == TOK_STATIC) {
2430 t |= VT_STATIC;
2431 } else if (tok == TOK_UNSIGNED) {
2432 t |= VT_UNSIGNED;
2433 } else if (tok == TOK_TYPEDEF) {
2434 t |= VT_TYPEDEF;
2435 } else {
2436 s = sym_find(tok);
2437 if (!s || !(s->t & VT_TYPEDEF))
2438 break;
2439 t |= (s->t & ~VT_TYPEDEF);
2441 next();
2443 t |= 2;
2445 return t;
2448 int post_type(int t)
2450 int p, n, pt, l, t1;
2451 Sym **plast, *s, *first;
2453 if (tok == '(') {
2454 /* function declaration */
2455 next();
2456 l = 0;
2457 first = NULL;
2458 plast = &first;
2459 while (tok != ')') {
2460 /* read param name and compute offset */
2461 if (l != FUNC_OLD) {
2462 if (!(pt = ist())) {
2463 if (l) {
2464 error("invalid type");
2465 } else {
2466 l = FUNC_OLD;
2467 goto old_proto;
2470 if (pt & VT_VOID && tok == ')')
2471 break;
2472 l = FUNC_NEW;
2473 pt = type_decl(&n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
2474 } else {
2475 old_proto:
2476 n = tok;
2477 pt = VT_INT;
2478 next();
2480 /* array must be transformed to pointer according to ANSI C */
2481 pt &= ~VT_ARRAY;
2482 s = sym_push(n | SYM_FIELD, pt, 0);
2483 *plast = s;
2484 plast = &s->next;
2485 if (tok == ',') {
2486 next();
2487 if (l == FUNC_NEW && tok == TOK_DOTS) {
2488 l = FUNC_ELLIPSIS;
2489 next();
2490 break;
2494 skip(')');
2495 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
2496 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
2497 /* we push a anonymous symbol which will contain the function prototype */
2498 p = anon_sym++;
2499 s = sym_push(p, t, l);
2500 s->next = first;
2501 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
2502 } else if (tok == '[') {
2503 /* array definition */
2504 next();
2505 n = -1;
2506 if (tok != ']') {
2507 n = expr_const();
2508 if (n < 0)
2509 error("invalid array size");
2511 skip(']');
2512 /* parse next post type */
2513 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
2514 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
2516 /* we push a anonymous symbol which will contain the array
2517 element type */
2518 p = anon_sym++;
2519 sym_push(p, t, n);
2520 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
2522 return t;
2525 /* Read a type declaration (except basic type), and return the
2526 type. If v is true, then also put variable name in 'vc' */
2527 int type_decl(int *v, int t, int td)
2529 int u, p;
2530 Sym *s;
2532 t = t & -3; /* suppress the ored '2' */
2533 while (tok == '*') {
2534 next();
2535 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
2536 next();
2537 t = mk_pointer(t);
2540 /* recursive type */
2541 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
2542 if (tok == '(') {
2543 next();
2544 u = type_decl(v, 0, td);
2545 skip(')');
2546 } else {
2547 u = 0;
2548 /* type identifier */
2549 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
2550 *v = tok;
2551 next();
2552 } else {
2553 if (!(td & TYPE_ABSTRACT))
2554 expect("identifier");
2555 *v = 0;
2558 /* append t at the end of u */
2559 t = post_type(t);
2560 if (!u)
2561 return t;
2562 p = u;
2563 while(1) {
2564 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
2565 p = s->t;
2566 if (!p) {
2567 s->t = t;
2568 break;
2571 return u;
2574 /* define a new external reference to a function 'v' of type 'u' */
2575 Sym *external_sym(int v, int u)
2577 Sym *s;
2578 s = sym_find(v);
2579 if (!s) {
2580 /* push forward reference */
2581 s = sym_push1(&global_stack,
2582 v, u | VT_CONST | VT_FORWARD, 0);
2584 return s;
2587 void indir(void)
2589 if (vt & VT_LVAL)
2590 gv();
2591 if (!(vt & VT_PTR))
2592 expect("pointer");
2593 vt = pointed_type(vt);
2594 if (!(vt & VT_ARRAY)) /* an array is never an lvalue */
2595 vt |= VT_LVAL;
2598 void unary(void)
2600 int n, t, ft, fc, p, align, size;
2601 Sym *s;
2602 GFuncContext gf;
2604 if (tok == TOK_NUM || tok == TOK_CCHAR || tok == TOK_LCHAR) {
2605 vset(VT_CONST, tokc);
2606 next();
2607 } else if (tok == TOK___FUNC__) {
2608 /* special function name identifier */
2609 /* generate (char *) type */
2610 vset(VT_CONST | mk_pointer(VT_BYTE), glo);
2611 strcpy((void *)glo, funcname);
2612 glo += strlen(funcname) + 1;
2613 next();
2614 } else if (tok == TOK_LSTR) {
2615 t = VT_INT;
2616 goto str_init;
2617 } else if (tok == TOK_STR) {
2618 /* string parsing */
2619 t = VT_BYTE;
2620 str_init:
2621 type_size(t, &align);
2622 glo = (glo + align - 1) & -align;
2623 fc = glo;
2624 /* we must declare it as an array first to use initializer parser */
2625 t = VT_CONST | VT_ARRAY | mk_pointer(t);
2626 decl_initializer(t, glo, 1, 0);
2627 glo += type_size(t, &align);
2628 /* put it as pointer */
2629 vset(t & ~VT_ARRAY, fc);
2630 } else {
2631 t = tok;
2632 next();
2633 if (t == '(') {
2634 /* cast ? */
2635 if (t = ist()) {
2636 ft = type_decl(&n, t, TYPE_ABSTRACT);
2637 skip(')');
2638 /* check ISOC99 compound literal */
2639 if (tok == '{') {
2640 /* data is allocated locally by default */
2641 if (global_expr)
2642 ft |= VT_CONST;
2643 else
2644 ft |= VT_LOCAL;
2645 /* all except arrays are lvalues */
2646 if (!(ft & VT_ARRAY))
2647 ft |= VT_LVAL;
2648 fc = decl_initializer_alloc(ft, 1);
2649 vset(ft, fc);
2650 } else {
2651 unary();
2652 gen_cast(ft);
2654 } else {
2655 expr();
2656 skip(')');
2658 } else if (t == '*') {
2659 unary();
2660 indir();
2661 } else if (t == '&') {
2662 unary();
2663 /* functions names must be treated as function pointers,
2664 except for unary '&' and sizeof. Since we consider that
2665 functions are not lvalues, we only have to handle it
2666 there and in function calls. */
2667 if (!(vt & VT_FUNC))
2668 test_lvalue();
2669 vt = mk_pointer(vt & VT_LVALN);
2670 } else
2671 if (t == '!') {
2672 unary();
2673 if ((vt & (VT_VALMASK | VT_LVAL)) == VT_CONST)
2674 vc = !vc;
2675 else if ((vt & VT_VALMASK) == VT_CMP)
2676 vc = vc ^ 1;
2677 else
2678 vset(VT_JMP, gtst(1, 0));
2679 } else
2680 if (t == '~') {
2681 unary();
2682 vpush();
2683 vset(VT_CONST, -1);
2684 gen_op('^');
2685 } else
2686 if (t == '+') {
2687 unary();
2688 } else
2689 if (t == TOK_SIZEOF) {
2690 /* XXX: some code can be generated */
2691 if (tok == '(') {
2692 next();
2693 if (t = ist())
2694 vt = type_decl(&n, t, TYPE_ABSTRACT);
2695 else
2696 expr();
2697 skip(')');
2698 } else {
2699 unary();
2701 vset(VT_CONST, type_size(vt, &t));
2702 } else
2703 if (t == TOK_INC | t == TOK_DEC) {
2704 unary();
2705 inc(0, t);
2706 } else if (t == '-') {
2707 vset(VT_CONST, 0);
2708 vpush();
2709 unary();
2710 gen_op('-');
2711 } else
2713 s = sym_find(t);
2714 if (!s) {
2715 if (tok != '(')
2716 error("'%s' undeclared", get_tok_str(t, 0));
2717 /* for simple function calls, we tolerate undeclared
2718 external reference */
2719 p = anon_sym++;
2720 sym_push1(&global_stack, p, 0, FUNC_OLD);
2721 /* int() function */
2722 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT));
2724 vset(s->t, s->c);
2725 /* if forward reference, we must point to s */
2726 if (vt & VT_FORWARD)
2727 vc = (int)s;
2731 /* post operations */
2732 while (1) {
2733 if (tok == TOK_INC | tok == TOK_DEC) {
2734 inc(1, tok);
2735 next();
2736 } else if (tok == '.' | tok == TOK_ARROW) {
2737 /* field */
2738 if (tok == TOK_ARROW)
2739 indir();
2740 test_lvalue();
2741 vt &= VT_LVALN;
2742 next();
2743 /* expect pointer on structure */
2744 if (!(vt & VT_STRUCT))
2745 expect("struct or union");
2746 s = sym_find(((unsigned)vt >> VT_STRUCT_SHIFT) | SYM_STRUCT);
2747 /* find field */
2748 tok |= SYM_FIELD;
2749 while (s = s->next) {
2750 if (s->v == tok)
2751 break;
2753 if (!s)
2754 error("field not found");
2755 /* add field offset to pointer */
2756 vt = (vt & ~VT_TYPE) | VT_INT; /* change type to int */
2757 vpush();
2758 vset(VT_CONST, s->c);
2759 gen_op('+');
2760 /* change type to field type, and set to lvalue */
2761 vt = (vt & ~VT_TYPE) | s->t;
2762 /* an array is never an lvalue */
2763 if (!(vt & VT_ARRAY))
2764 vt |= VT_LVAL;
2765 next();
2766 } else if (tok == '[') {
2767 next();
2768 vpush();
2769 expr();
2770 gen_op('+');
2771 indir();
2772 skip(']');
2773 } else if (tok == '(') {
2774 int rett, retc;
2776 /* function call */
2777 if (!(vt & VT_FUNC)) {
2778 if ((vt & (VT_PTR | VT_ARRAY)) == VT_PTR) {
2779 vt = pointed_type(vt);
2780 if (!(vt & VT_FUNC))
2781 goto error_func;
2782 } else {
2783 error_func:
2784 expect("function pointer");
2786 } else {
2787 vt &= ~VT_LVAL; /* no lvalue */
2790 /* get return type */
2791 s = sym_find((unsigned)vt >> VT_STRUCT_SHIFT);
2792 vpush(); /* push function address */
2793 save_regs(); /* save used temporary registers */
2794 gfunc_start(&gf);
2795 next();
2796 #ifdef INVERT_FUNC_PARAMS
2798 int *str, len, parlevel, *saved_macro_ptr;
2799 Sym *args, *s1;
2801 /* read each argument and store it on a stack */
2802 /* XXX: merge it with macro args ? */
2803 args = NULL;
2804 while (tok != ')') {
2805 len = 0;
2806 str = NULL;
2807 parlevel = 0;
2808 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
2809 tok != -1) {
2810 if (tok == '(')
2811 parlevel++;
2812 else if (tok == ')')
2813 parlevel--;
2814 tok_add2(&str, &len, tok, tokc);
2815 next();
2817 tok_add(&str, &len, -1); /* end of file added */
2818 tok_add(&str, &len, 0);
2819 sym_push2(&args, 0, 0, (int)str);
2820 if (tok != ',')
2821 break;
2822 next();
2824 if (tok != ')')
2825 expect(")");
2827 /* now generate code in reverse order by reading the stack */
2828 saved_macro_ptr = macro_ptr;
2829 while (args) {
2830 macro_ptr = (int *)args->c;
2831 next();
2832 expr_eq();
2833 if (tok != -1)
2834 expect("',' or ')'");
2835 gfunc_param(&gf);
2836 s1 = args->prev;
2837 free((int *)args->c);
2838 free(args);
2839 args = s1;
2841 macro_ptr = saved_macro_ptr;
2842 /* restore token */
2843 tok = ')';
2845 #endif
2846 /* compute first implicit argument if a structure is returned */
2847 if (s->t & VT_STRUCT) {
2848 /* get some space for the returned structure */
2849 size = type_size(s->t, &align);
2850 loc = (loc - size) & -align;
2851 rett = s->t | VT_LOCAL | VT_LVAL;
2852 /* pass it as 'int' to avoid structure arg passing
2853 problems */
2854 vset(VT_INT | VT_LOCAL, loc);
2855 retc = vc;
2856 gfunc_param(&gf);
2857 } else {
2858 rett = s->t | FUNC_RET_REG; /* return in register */
2859 retc = 0;
2861 #ifndef INVERT_FUNC_PARAMS
2862 while (tok != ')') {
2863 expr_eq();
2864 gfunc_param(&gf);
2865 if (tok == ',')
2866 next();
2868 #endif
2869 skip(')');
2870 vpop(&vt, &vc);
2871 gfunc_call(&gf);
2872 /* return value */
2873 vt = rett;
2874 vc = retc;
2875 } else {
2876 break;
2881 int is_compatible_types(int t1, int t2)
2883 Sym *s1, *s2;
2885 t1 &= VT_TYPE;
2886 t2 &= VT_TYPE;
2887 if (t1 & VT_PTR) {
2888 t1 = pointed_type(t1);
2889 /* if function, then convert implictely to function pointer */
2890 if (!(t2 & VT_FUNC)) {
2891 if (!(t2 & VT_PTR))
2892 return 0;
2893 t2 = pointed_type(t2);
2895 /* void matches everything */
2896 t1 &= VT_TYPE;
2897 t2 &= VT_TYPE;
2898 if (t1 == VT_VOID || t2 == VT_VOID)
2899 return 1;
2900 return is_compatible_types(t1, t2);
2901 } else if (t1 & VT_STRUCT) {
2902 return (t2 == t1);
2903 } else if (t1 & VT_FUNC) {
2904 if (!(t2 & VT_FUNC))
2905 return 0;
2906 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
2907 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
2908 if (!is_compatible_types(s1->t, s2->t))
2909 return 0;
2910 /* XXX: not complete */
2911 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
2912 return 1;
2913 if (s1->c != s2->c)
2914 return 0;
2915 while (s1 != NULL) {
2916 if (s2 == NULL)
2917 return 0;
2918 if (!is_compatible_types(s1->t, s2->t))
2919 return 0;
2920 s1 = s1->next;
2921 s2 = s2->next;
2923 if (s2)
2924 return 0;
2925 return 1;
2926 } else {
2927 /* XXX: not complete */
2928 return 1;
2932 int check_assign_types(int t1, int t2)
2934 t1 &= VT_TYPE;
2935 t2 &= VT_TYPE;
2936 if ((t1 & VT_PTR) && (t2 & VT_FUNC)) {
2937 return is_compatible_types(pointed_type(t1), t2);
2938 } else {
2939 return is_compatible_types(t1, t2);
2944 void uneq()
2946 int t;
2948 unary();
2949 if (tok == '=' |
2950 (tok >= TOK_A_MOD & tok <= TOK_A_DIV) |
2951 tok == TOK_A_XOR | tok == TOK_A_OR |
2952 tok == TOK_A_SHL | tok == TOK_A_SAR) {
2953 test_lvalue();
2954 vpush();
2955 t = tok;
2956 next();
2957 if (t == '=') {
2958 expr_eq();
2959 if (!check_assign_types(vstack_ptr[-2], vt))
2960 warning("incompatible types");
2961 } else {
2962 vpush();
2963 expr_eq();
2964 gen_op(t & 0x7f);
2966 vstore();
2970 void sum(l)
2972 int t;
2974 if (l == 0)
2975 uneq();
2976 else {
2977 sum(--l);
2978 while ((l == 0 & (tok == '*' | tok == '/' | tok == '%')) |
2979 (l == 1 & (tok == '+' | tok == '-')) |
2980 (l == 2 & (tok == TOK_SHL | tok == TOK_SAR)) |
2981 (l == 3 & ((tok >= TOK_ULE & tok <= TOK_GT) |
2982 tok == TOK_ULT | tok == TOK_UGE)) |
2983 (l == 4 & (tok == TOK_EQ | tok == TOK_NE)) |
2984 (l == 5 & tok == '&') |
2985 (l == 6 & tok == '^') |
2986 (l == 7 & tok == '|') |
2987 (l == 8 & tok == TOK_LAND) |
2988 (l == 9 & tok == TOK_LOR)) {
2989 vpush();
2990 t = tok;
2991 next();
2992 sum(l);
2993 gen_op(t);
2998 /* only used if non constant */
2999 void eand(void)
3001 int t;
3003 sum(8);
3004 t = 0;
3005 while (1) {
3006 if (tok != TOK_LAND) {
3007 if (t) {
3008 t = gtst(1, t);
3009 vset(VT_JMPI, t);
3011 break;
3013 t = gtst(1, t);
3014 next();
3015 sum(8);
3019 void eor(void)
3021 int t;
3023 eand();
3024 t = 0;
3025 while (1) {
3026 if (tok != TOK_LOR) {
3027 if (t) {
3028 t = gtst(0, t);
3029 vset(VT_JMP, t);
3031 break;
3033 t = gtst(0, t);
3034 next();
3035 eand();
3039 /* XXX: better constant handling */
3040 void expr_eq()
3042 int t, u, c, r1, r2;
3044 if (const_wanted) {
3045 sum(10);
3046 if (tok == '?') {
3047 c = vc;
3048 next();
3049 expr();
3050 t = vc;
3051 skip(':');
3052 expr_eq();
3053 if (c)
3054 vc = t;
3056 } else {
3057 eor();
3058 if (tok == '?') {
3059 next();
3060 t = gtst(1, 0);
3061 expr();
3062 r1 = gv();
3063 skip(':');
3064 u = gjmp(0);
3065 gsym(t);
3066 expr_eq();
3067 r2 = gv();
3068 move_reg(r1, r2);
3069 vt = (vt & VT_TYPE) | r1;
3070 gsym(u);
3075 void expr()
3077 while (1) {
3078 expr_eq();
3079 if (tok != ',')
3080 break;
3081 next();
3085 int expr_const()
3087 int a;
3088 a = const_wanted;
3089 const_wanted = 1;
3090 expr_eq();
3091 if ((vt & (VT_CONST | VT_LVAL)) != VT_CONST)
3092 expect("constant");
3093 const_wanted = a;
3094 return vc;
3097 /* return the label token if current token is a label, otherwise
3098 return zero */
3099 int is_label(void)
3101 int t, c;
3103 /* fast test first */
3104 if (tok < TOK_UIDENT)
3105 return 0;
3106 t = tok;
3107 c = tokc;
3108 next();
3109 if (tok == ':') {
3110 next();
3111 return t;
3112 } else {
3113 /* XXX: may not work in all cases (macros ?) */
3114 tok1 = tok;
3115 tok1c = tokc;
3116 tok = t;
3117 tokc = c;
3118 return 0;
3122 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
3124 int a, b, c, d;
3125 Sym *s;
3127 if (tok == TOK_IF) {
3128 /* if test */
3129 next();
3130 skip('(');
3131 expr();
3132 skip(')');
3133 a = gtst(1, 0);
3134 block(bsym, csym, case_sym, def_sym, case_reg);
3135 c = tok;
3136 if (c == TOK_ELSE) {
3137 next();
3138 d = gjmp(0);
3139 gsym(a);
3140 block(bsym, csym, case_sym, def_sym, case_reg);
3141 gsym(d); /* patch else jmp */
3142 } else
3143 gsym(a);
3144 } else if (tok == TOK_WHILE) {
3145 next();
3146 d = ind;
3147 skip('(');
3148 expr();
3149 skip(')');
3150 a = gtst(1, 0);
3151 b = 0;
3152 block(&a, &b, case_sym, def_sym, case_reg);
3153 oad(0xe9, d - ind - 5); /* jmp */
3154 gsym(a);
3155 gsym_addr(b, d);
3156 } else if (tok == '{') {
3157 next();
3158 /* declarations */
3159 s = local_stack.top;
3160 while (tok != '}') {
3161 decl(VT_LOCAL);
3162 if (tok != '}')
3163 block(bsym, csym, case_sym, def_sym, case_reg);
3165 /* pop locally defined symbols */
3166 sym_pop(&local_stack, s);
3167 next();
3168 } else if (tok == TOK_RETURN) {
3169 next();
3170 if (tok != ';') {
3171 if (func_vt & VT_STRUCT) {
3172 /* if returning structure, must copy it to implicit
3173 first pointer arg location */
3174 vset(mk_pointer(func_vt) | VT_LOCAL | VT_LVAL, func_vc);
3175 indir();
3176 vpush();
3178 expr();
3179 if (func_vt & VT_STRUCT) {
3180 /* copy structure value to pointer */
3181 vstore();
3182 } else {
3183 /* move return value to standard return register */
3184 move_reg(FUNC_RET_REG, gv());
3187 skip(';');
3188 rsym = gjmp(rsym); /* jmp */
3189 } else if (tok == TOK_BREAK) {
3190 /* compute jump */
3191 if (!bsym)
3192 error("cannot break");
3193 *bsym = gjmp(*bsym);
3194 next();
3195 skip(';');
3196 } else if (tok == TOK_CONTINUE) {
3197 /* compute jump */
3198 if (!csym)
3199 error("cannot continue");
3200 *csym = gjmp(*csym);
3201 next();
3202 skip(';');
3203 } else if (tok == TOK_FOR) {
3204 int e;
3205 next();
3206 skip('(');
3207 if (tok != ';')
3208 expr();
3209 skip(';');
3210 d = ind;
3211 c = ind;
3212 a = 0;
3213 b = 0;
3214 if (tok != ';') {
3215 expr();
3216 a = gtst(1, 0);
3218 skip(';');
3219 if (tok != ')') {
3220 e = gjmp(0);
3221 c = ind;
3222 expr();
3223 oad(0xe9, d - ind - 5); /* jmp */
3224 gsym(e);
3226 skip(')');
3227 block(&a, &b, case_sym, def_sym, case_reg);
3228 oad(0xe9, c - ind - 5); /* jmp */
3229 gsym(a);
3230 gsym_addr(b, c);
3231 } else
3232 if (tok == TOK_DO) {
3233 next();
3234 a = 0;
3235 b = 0;
3236 d = ind;
3237 block(&a, &b, case_sym, def_sym, case_reg);
3238 skip(TOK_WHILE);
3239 skip('(');
3240 gsym(b);
3241 expr();
3242 c = gtst(0, 0);
3243 gsym_addr(c, d);
3244 skip(')');
3245 gsym(a);
3246 skip(';');
3247 } else
3248 if (tok == TOK_SWITCH) {
3249 next();
3250 skip('(');
3251 expr();
3252 case_reg = gv();
3253 skip(')');
3254 a = 0;
3255 b = 0;
3256 c = 0;
3257 block(&a, csym, &b, &c, case_reg);
3258 /* if no default, jmp after switch */
3259 if (c == 0)
3260 c = ind;
3261 /* default label */
3262 gsym_addr(b, c);
3263 /* break label */
3264 gsym(a);
3265 } else
3266 if (tok == TOK_CASE) {
3267 next();
3268 a = expr_const();
3269 if (!case_sym)
3270 expect("switch");
3271 gsym(*case_sym);
3272 vset(case_reg, 0);
3273 vpush();
3274 vset(VT_CONST, a);
3275 gen_op(TOK_EQ);
3276 *case_sym = gtst(1, 0);
3277 skip(':');
3278 block(bsym, csym, case_sym, def_sym, case_reg);
3279 } else
3280 if (tok == TOK_DEFAULT) {
3281 next();
3282 skip(':');
3283 if (!def_sym)
3284 expect("switch");
3285 if (*def_sym)
3286 error("too many 'default'");
3287 *def_sym = ind;
3288 block(bsym, csym, case_sym, def_sym, case_reg);
3289 } else
3290 if (tok == TOK_GOTO) {
3291 next();
3292 s = sym_find1(&label_stack, tok);
3293 /* put forward definition if needed */
3294 if (!s)
3295 s = sym_push1(&label_stack, tok, VT_FORWARD, 0);
3296 /* label already defined */
3297 if (s->t & VT_FORWARD)
3298 s->c = gjmp(s->c); /* jmp xxx */
3299 else
3300 oad(0xe9, s->c - ind - 5); /* jmp xxx */
3301 next();
3302 skip(';');
3303 } else {
3304 b = is_label();
3305 if (b) {
3306 /* label case */
3307 s = sym_find1(&label_stack, b);
3308 if (s) {
3309 if (!(s->t & VT_FORWARD))
3310 error("multiple defined label");
3311 gsym(s->c);
3312 s->c = ind;
3313 s->t = 0;
3314 } else {
3315 sym_push1(&label_stack, b, 0, ind);
3317 /* we accept this, but it is a mistake */
3318 if (tok == '}')
3319 warning("deprecated use of label at end of compound statement");
3320 else
3321 block(bsym, csym, case_sym, def_sym, case_reg);
3322 } else {
3323 /* expression case */
3324 if (tok != ';') {
3325 expr();
3327 skip(';');
3332 /* t is the array or struct type. c is the array or struct
3333 address. cur_index/cur_field is the pointer to the current
3334 value. 'size_only' is true if only size info is needed (only used
3335 in arrays) */
3336 void decl_designator(int t, int c,
3337 int *cur_index, Sym **cur_field,
3338 int size_only)
3340 Sym *s, *f;
3341 int notfirst, index, align, l;
3343 notfirst = 0;
3344 if (gnu_ext && (l = is_label()) != 0)
3345 goto struct_field;
3347 while (tok == '[' || tok == '.') {
3348 if (tok == '[') {
3349 if (!(t & VT_ARRAY))
3350 expect("array type");
3351 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3352 next();
3353 index = expr_const();
3354 if (index < 0 || (s->c >= 0 && index >= s->c))
3355 expect("invalid index");
3356 skip(']');
3357 if (!notfirst)
3358 *cur_index = index;
3359 t = pointed_type(t);
3360 c += index * type_size(t, &align);
3361 } else {
3362 next();
3363 l = tok;
3364 next();
3365 struct_field:
3366 if (!(t & VT_STRUCT))
3367 expect("struct/union type");
3368 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3369 l |= SYM_FIELD;
3370 f = s->next;
3371 while (f) {
3372 if (f->v == l)
3373 break;
3374 f = f->next;
3376 if (!f)
3377 expect("field");
3378 if (!notfirst)
3379 *cur_field = f;
3380 t = f->t | (t & ~VT_TYPE);
3381 c += f->c;
3383 notfirst = 1;
3385 if (notfirst) {
3386 if (tok == '=') {
3387 next();
3388 } else {
3389 if (!gnu_ext)
3390 expect("=");
3392 } else {
3393 if (t & VT_ARRAY) {
3394 index = *cur_index;
3395 t = pointed_type(t);
3396 c += index * type_size(t, &align);
3397 } else {
3398 f = *cur_field;
3399 if (!f)
3400 error("too many field init");
3401 t = f->t | (t & ~VT_TYPE);
3402 c += f->c;
3405 decl_initializer(t, c, 0, size_only);
3408 /* store a value or an expression directly in global data or in local array */
3410 void init_putv(int t, int c, int v, int is_expr)
3412 int saved_global_expr;
3414 if ((t & VT_VALMASK) == VT_CONST) {
3415 if (is_expr) {
3416 /* compound literals must be allocated globally in this case */
3417 saved_global_expr = global_expr;
3418 global_expr = 1;
3419 v = expr_const();
3420 global_expr = saved_global_expr;
3422 if (t & VT_BYTE)
3423 *(char *)c = v;
3424 else if (t & VT_SHORT)
3425 *(short *)c = v;
3426 else
3427 *(int *)c = v;
3428 } else {
3429 vt = t;
3430 vc = c;
3431 vpush();
3432 if (is_expr)
3433 expr_eq();
3434 else
3435 vset(VT_CONST, v);
3436 vstore();
3440 /* put zeros for variable based init */
3441 void init_putz(int t, int c, int size)
3443 GFuncContext gf;
3445 if ((t & VT_VALMASK) == VT_CONST) {
3446 /* nothing to do because global are already set to zero */
3447 } else {
3448 gfunc_start(&gf);
3449 vset(VT_CONST, size);
3450 gfunc_param(&gf);
3451 vset(VT_CONST, 0);
3452 gfunc_param(&gf);
3453 vset(VT_LOCAL, c);
3454 gfunc_param(&gf);
3455 vset(VT_CONST, (int)&memset);
3456 gfunc_call(&gf);
3460 /* 't' contains the type and storage info. c is the address of the
3461 object. 'first' is true if array '{' must be read (multi dimension
3462 implicit array init handling). 'size_only' is true if size only
3463 evaluation is wanted (only for arrays). */
3464 void decl_initializer(int t, int c, int first, int size_only)
3466 int index, array_length, n, no_oblock, nb, parlevel, i;
3467 int t1, size1, align1;
3468 Sym *s, *f;
3469 TokenSym *ts;
3471 if (t & VT_ARRAY) {
3472 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3473 n = s->c;
3474 array_length = 0;
3475 t1 = pointed_type(t);
3476 size1 = type_size(t1, &align1);
3478 no_oblock = 1;
3479 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
3480 tok == '{') {
3481 skip('{');
3482 no_oblock = 0;
3485 /* only parse strings here if correct type (otherwise: handle
3486 them as ((w)char *) expressions */
3487 if ((tok == TOK_LSTR &&
3488 (t1 & VT_TYPE & ~VT_UNSIGNED) == VT_INT) ||
3489 (tok == TOK_STR &&
3490 (t1 & VT_TYPE & ~VT_UNSIGNED) == VT_BYTE)) {
3491 /* XXX: move multiple string parsing in parser ? */
3492 while (tok == TOK_STR || tok == TOK_LSTR) {
3493 ts = (TokenSym *)tokc;
3494 /* compute maximum number of chars wanted */
3495 nb = ts->len;
3496 if (n >= 0 && nb > (n - array_length))
3497 nb = n - array_length;
3498 if (!size_only) {
3499 if (ts->len > nb)
3500 warning("initializer-string for array is too long");
3501 for(i=0;i<nb;i++) {
3502 init_putv(t1, c + (array_length + i) * size1,
3503 ts->str[i], 0);
3506 array_length += nb;
3507 next();
3509 /* only add trailing zero if enough storage (no
3510 warning in this case since it is standard) */
3511 if (n < 0 || array_length < n) {
3512 if (!size_only) {
3513 init_putv(t1, c + (array_length * size1), 0, 0);
3515 array_length++;
3517 } else {
3518 index = 0;
3519 while (tok != '}') {
3520 decl_designator(t, c, &index, NULL, size_only);
3521 if (n >= 0 && index >= n)
3522 error("index too large");
3523 /* must put zero in holes (note that doing it that way
3524 ensures that it even works with designators) */
3525 if (!size_only && array_length < index) {
3526 init_putz(t1, c + array_length * size1,
3527 (index - array_length) * size1);
3529 index++;
3530 if (index > array_length)
3531 array_length = index;
3532 /* special test for multi dimensional arrays (may not
3533 be strictly correct if designators are used at the
3534 same time) */
3535 if (index >= n && no_oblock)
3536 break;
3537 if (tok == '}')
3538 break;
3539 skip(',');
3542 if (!no_oblock)
3543 skip('}');
3544 /* put zeros at the end */
3545 if (!size_only && n >= 0 && array_length < n) {
3546 init_putz(t1, c + array_length * size1,
3547 (n - array_length) * size1);
3549 /* patch type size if needed */
3550 if (n < 0)
3551 s->c = array_length;
3552 } else if ((t & VT_STRUCT) && tok == '{') {
3553 /* XXX: union needs only one init */
3554 next();
3555 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3556 f = s->next;
3557 array_length = 0;
3558 index = 0;
3559 n = s->c;
3560 while (tok != '}') {
3561 decl_designator(t, c, NULL, &f, size_only);
3562 /* fill with zero between fields */
3563 index = f->c;
3564 if (!size_only && array_length < index) {
3565 init_putz(t, c + array_length,
3566 index - array_length);
3568 index = index + type_size(f->t, &align1);
3569 if (index > array_length)
3570 array_length = index;
3571 if (tok == '}')
3572 break;
3573 skip(',');
3574 f = f->next;
3576 /* put zeros at the end */
3577 if (!size_only && array_length < n) {
3578 init_putz(t, c + array_length,
3579 n - array_length);
3581 skip('}');
3582 } else if (tok == '{') {
3583 next();
3584 decl_initializer(t, c, first, size_only);
3585 skip('}');
3586 } else if (size_only) {
3587 /* just skip expression */
3588 parlevel = 0;
3589 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
3590 tok != -1) {
3591 if (tok == '(')
3592 parlevel++;
3593 else if (tok == ')')
3594 parlevel--;
3595 next();
3597 } else {
3598 init_putv(t, c, 0, 1);
3602 /* parse an initializer for type 't' if 'has_init' is true, and
3603 allocate space in local or global data space. The allocated address
3604 in returned */
3605 int decl_initializer_alloc(int t, int has_init)
3607 int size, align, addr, tok1;
3608 int *init_str, init_len, level, *saved_macro_ptr;
3610 size = type_size(t, &align);
3611 /* If unknown size, we must evaluate it before
3612 evaluating initializers because
3613 initializers can generate global data too
3614 (e.g. string pointers or ISOC99 compound
3615 literals). It also simplifies local
3616 initializers handling */
3617 init_len = 0;
3618 init_str = NULL;
3619 saved_macro_ptr = NULL; /* avoid warning */
3620 tok1 = 0;
3621 if (size < 0) {
3622 if (!has_init)
3623 error("unknown type size");
3624 /* get all init string */
3625 level = 0;
3626 while (level > 0 || (tok != ',' && tok != ';')) {
3627 if (tok < 0)
3628 error("unexpect end of file in initializer");
3629 tok_add2(&init_str, &init_len, tok, tokc);
3630 if (tok == '{')
3631 level++;
3632 else if (tok == '}') {
3633 if (level == 0)
3634 break;
3635 level--;
3637 next();
3639 tok1 = tok;
3640 tok_add(&init_str, &init_len, -1);
3641 tok_add(&init_str, &init_len, 0);
3643 /* compute size */
3644 saved_macro_ptr = macro_ptr;
3645 macro_ptr = init_str;
3646 next();
3647 decl_initializer(t, 0, 1, 1);
3648 /* prepare second initializer parsing */
3649 macro_ptr = init_str;
3650 next();
3652 /* if still unknown size, error */
3653 size = type_size(t, &align);
3654 if (size < 0)
3655 error("unknown type size");
3657 if ((t & VT_VALMASK) == VT_LOCAL) {
3658 loc = (loc - size) & -align;
3659 addr = loc;
3660 } else {
3661 glo = (glo + align - 1) & -align;
3662 addr = glo;
3663 /* very important to increment global
3664 pointer at this time because
3665 initializers themselves can create new
3666 initializers */
3667 glo += size;
3669 if (has_init) {
3670 decl_initializer(t, addr, 1, 0);
3671 /* restore parse state if needed */
3672 if (init_str) {
3673 free(init_str);
3674 macro_ptr = saved_macro_ptr;
3675 tok = tok1;
3678 return addr;
3682 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
3683 void decl(int l)
3685 int *a, t, b, v, u, addr, has_init, size, align;
3686 Sym *sym;
3688 while (1) {
3689 b = ist();
3690 if (!b) {
3691 /* skip redundant ';' */
3692 /* XXX: find more elegant solution */
3693 if (tok == ';') {
3694 next();
3695 continue;
3697 /* special test for old K&R protos without explicit int
3698 type. Only accepted when defining global data */
3699 if (l == VT_LOCAL || tok < TOK_DEFINE)
3700 break;
3701 b = VT_INT;
3703 if ((b & (VT_ENUM | VT_STRUCT)) && tok == ';') {
3704 /* we accept no variable after */
3705 next();
3706 continue;
3708 while (1) { /* iterate thru each declaration */
3709 t = type_decl(&v, b, TYPE_DIRECT);
3710 if (tok == '{') {
3711 if (l == VT_LOCAL)
3712 error("cannot use local functions");
3713 if (!(t & VT_FUNC))
3714 expect("function definition");
3715 /* patch forward references */
3716 if ((sym = sym_find(v)) && (sym->t & VT_FORWARD)) {
3717 greloc_patch(sym, ind);
3718 sym->t = VT_CONST | t;
3719 } else {
3720 /* put function address */
3721 sym_push1(&global_stack, v, VT_CONST | t, ind);
3723 funcname = get_tok_str(v, 0);
3724 /* push a dummy symbol to enable local sym storage */
3725 sym_push1(&local_stack, 0, 0, 0);
3726 /* define parameters */
3727 sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3728 /* XXX: the following is x86 dependant -> move it to
3729 x86 code gen */
3730 addr = 8;
3731 /* if the function returns a structure, then add an
3732 implicit pointer parameter */
3733 func_vt = sym->t;
3734 if (func_vt & VT_STRUCT) {
3735 func_vc = addr;
3736 addr += 4;
3738 while (sym = sym->next) {
3739 u = sym->t;
3740 sym_push(sym->v & ~SYM_FIELD,
3741 u | VT_LOCAL | VT_LVAL,
3742 addr);
3743 if (u & VT_STRUCT) {
3744 #ifdef FUNC_STRUCT_PARAM_AS_PTR
3745 /* structs are passed as pointer */
3746 size = 4;
3747 #else
3748 /* structs are directly put on stack (x86
3749 like) */
3750 size = type_size(u, &align);
3751 size = (size + 3) & ~3;
3752 #endif
3753 } else {
3754 /* XXX: size will be different someday */
3755 size = 4;
3757 addr += size;
3759 loc = 0;
3760 o(0xe58955); /* push %ebp, mov %esp, %ebp */
3761 a = (int *)oad(0xec81, 0); /* sub $xxx, %esp */
3762 rsym = 0;
3763 block(0, 0, 0, 0, 0);
3764 gsym(rsym);
3765 o(0xc3c9); /* leave, ret */
3766 *a = (-loc + 3) & -4; /* align local size to word &
3767 save local variables */
3768 sym_pop(&label_stack, 0); /* reset label stack */
3769 sym_pop(&local_stack, 0); /* reset local stack */
3770 funcname = ""; /* for safety */
3771 func_vt = VT_VOID; /* for safety */
3772 break;
3773 } else {
3774 if (b & VT_TYPEDEF) {
3775 /* save typedefed type */
3776 /* XXX: test storage specifiers ? */
3777 sym_push(v, t | VT_TYPEDEF, 0);
3778 } else if (t & VT_FUNC) {
3779 /* external function definition */
3780 external_sym(v, t);
3781 } else {
3782 /* not lvalue if array */
3783 if (!(t & VT_ARRAY))
3784 t |= VT_LVAL;
3785 if (b & VT_EXTERN) {
3786 /* external variable */
3787 external_sym(v, t);
3788 } else {
3789 u = l;
3790 if (t & VT_STATIC)
3791 u = VT_CONST;
3792 u |= t;
3793 has_init = (tok == '=');
3794 if (has_init)
3795 next();
3796 addr = decl_initializer_alloc(u, has_init);
3797 if (l == VT_CONST) {
3798 /* global scope: see if already defined */
3799 sym = sym_find(v);
3800 if (!sym)
3801 goto do_def;
3802 if (!is_compatible_types(sym->t, u))
3803 error("incompatible types for redefinition of '%s'",
3804 get_tok_str(v, 0));
3805 if (!(sym->t & VT_FORWARD))
3806 error("redefinition of '%s'", get_tok_str(v, 0));
3807 greloc_patch(sym, addr);
3808 } else {
3809 do_def:
3810 sym_push(v, u, addr);
3814 if (tok != ',') {
3815 skip(';');
3816 break;
3818 next();
3824 /* put all global symbols in the extern stack and do all the
3825 resolving which can be done without using external symbols from DLLs */
3826 /* XXX: could try to verify types, but would not to save them in
3827 extern_stack too */
3828 void resolve_global_syms(void)
3830 Sym *s, *s1, *ext_sym;
3831 Reloc **p;
3833 s = global_stack.top;
3834 while (s != NULL) {
3835 s1 = s->prev;
3836 /* do not save static or typedefed symbols or types */
3837 if (!(s->t & (VT_STATIC | VT_TYPEDEF)) &&
3838 !(s->v & (SYM_FIELD | SYM_STRUCT)) &&
3839 (s->v < SYM_FIRST_ANOM)) {
3840 ext_sym = sym_find1(&extern_stack, s->v);
3841 if (!ext_sym) {
3842 /* if the symbol do not exist, we simply save it */
3843 sym_push1(&extern_stack, s->v, s->t, s->c);
3844 } else if (ext_sym->t & VT_FORWARD) {
3845 /* external symbol already exists, but only as forward
3846 definition */
3847 if (!(s->t & VT_FORWARD)) {
3848 /* s is not forward, so we can relocate all symbols */
3849 greloc_patch(ext_sym, s->c);
3850 } else {
3851 /* the two symbols are forward: merge them */
3852 p = (Reloc **)&ext_sym->c;
3853 while (*p != NULL)
3854 p = &(*p)->next;
3855 *p = (Reloc *)s->c;
3857 } else {
3858 /* external symbol already exists and is defined :
3859 patch all references to it */
3860 if (!(s->t & VT_FORWARD))
3861 error("'%s' defined twice", get_tok_str(s->v, 0));
3862 greloc_patch(s, ext_sym->c);
3865 s = s1;
3869 /* compile a C file. Return non zero if errors. */
3870 int tcc_compile_file(const char *filename1)
3872 Sym *define_start;
3874 filename = (char *)filename1;
3876 line_num = 1;
3877 funcname = "";
3878 file = fopen(filename, "r");
3879 if (!file)
3880 error("file '%s' not found", filename);
3881 include_stack_ptr = include_stack;
3882 ifdef_stack_ptr = ifdef_stack;
3884 vstack_ptr = vstack;
3885 anon_sym = SYM_FIRST_ANOM;
3887 define_start = define_stack.top;
3888 inp();
3889 ch = '\n'; /* needed to parse correctly first preprocessor command */
3890 next();
3891 decl(VT_CONST);
3892 if (tok != -1)
3893 expect("declaration");
3894 fclose(file);
3896 /* reset define stack, but leave -Dsymbols (may be incorrect if
3897 they are undefined) */
3898 sym_pop(&define_stack, define_start);
3900 resolve_global_syms();
3902 sym_pop(&global_stack, NULL);
3904 return 0;
3907 /* open a dynamic library so that its symbol are available for
3908 compiled programs */
3909 void open_dll(char *libname)
3911 char buf[1024];
3912 void *h;
3914 snprintf(buf, sizeof(buf), "lib%s.so", libname);
3915 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
3916 if (!h)
3917 error((char *)dlerror());
3920 void resolve_extern_syms(void)
3922 Sym *s, *s1;
3923 char *str;
3924 int addr;
3926 s = extern_stack.top;
3927 while (s != NULL) {
3928 s1 = s->prev;
3929 if (s->t & VT_FORWARD) {
3930 /* if there is at least one relocation to do, then find it
3931 and patch it */
3932 if (s->c) {
3933 str = get_tok_str(s->v, 0);
3934 addr = (int)dlsym(NULL, str);
3935 if (!addr)
3936 error("unresolved external reference '%s'", str);
3937 greloc_patch(s, addr);
3940 s = s1;
3944 /* output a binary file (for testing) */
3945 void build_exe(char *filename)
3947 FILE *f;
3948 f = fopen(filename, "w");
3949 fwrite((void *)prog, 1, ind - prog, f);
3950 fclose(f);
3953 int main(int argc, char **argv)
3955 Sym *s;
3956 int (*t)();
3957 char *p, *r, *outfile;
3958 int optind;
3960 include_paths[0] = "/usr/include";
3961 include_paths[1] = "/usr/lib/tcc";
3962 include_paths[2] = "/usr/local/lib/tcc";
3963 nb_include_paths = 3;
3965 /* add all tokens */
3966 tok_ident = TOK_IDENT;
3967 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\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";
3968 while (*p) {
3969 r = p;
3970 while (*r++);
3971 tok_alloc(p, r - p - 1);
3972 p = r;
3975 /* standard defines */
3976 define_symbol("__STDC__");
3977 #ifdef __i386__
3978 define_symbol("__i386__");
3979 #endif
3980 /* tiny C specific defines */
3981 define_symbol("__TINYC__");
3983 glo = (int)malloc(DATA_SIZE);
3984 memset((void *)glo, 0, DATA_SIZE);
3985 prog = (int)malloc(TEXT_SIZE);
3986 ind = prog;
3988 optind = 1;
3989 outfile = NULL;
3990 while (1) {
3991 if (optind >= argc) {
3992 show_help:
3993 printf("tcc version 0.9.1 - Tiny C Compiler - Copyright (C) 2001 Fabrice Bellard\n"
3994 "usage: tcc [-Idir] [-Dsym] [-llib] [-i infile]... infile [infile_args...]\n");
3995 return 1;
3997 r = argv[optind];
3998 if (r[0] != '-')
3999 break;
4000 optind++;
4001 if (r[1] == 'I') {
4002 if (nb_include_paths >= INCLUDE_PATHS_MAX)
4003 error("too many include paths");
4004 include_paths[nb_include_paths++] = r + 2;
4005 } else if (r[1] == 'D') {
4006 define_symbol(r + 2);
4007 } else if (r[1] == 'l') {
4008 open_dll(r + 2);
4009 } else if (r[1] == 'i') {
4010 if (optind >= argc)
4011 goto show_help;
4012 tcc_compile_file(argv[optind++]);
4013 } else if (r[1] == 'o') {
4014 /* currently, only for testing, so not documented */
4015 if (optind >= argc)
4016 goto show_help;
4017 outfile = argv[optind++];
4018 } else {
4019 fprintf(stderr, "invalid option -- '%s'\n", r);
4020 exit(1);
4024 tcc_compile_file(argv[optind]);
4026 resolve_extern_syms();
4028 if (outfile) {
4029 build_exe(outfile);
4030 return 0;
4031 } else {
4032 s = sym_find1(&extern_stack, TOK_MAIN);
4033 if (!s || (s->t & VT_FORWARD))
4034 error("main() not defined");
4035 t = (int (*)())s->c;
4036 return (*t)(argc - optind, argv + optind);