better external allocs handling
[tinycc.git] / tcc.c
blob5f3f06a8bca472b2f8eef06040039bf35808303f
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 <tcclib.h>
22 //#define DEBUG
23 /* preprocessor debug */
24 //#define PP_DEBUG
26 /* these sizes are dummy for unix, because malloc() does not use
27 memory when the pages are not used */
28 #define TEXT_SIZE (4*1024*1024)
29 #define DATA_SIZE (4*1024*1024)
31 #define INCLUDE_STACK_SIZE 32
32 #define IFDEF_STACK_SIZE 64
33 #define VSTACK_SIZE 64
34 #define STRING_MAX_SIZE 1024
35 #define INCLUDE_PATHS_MAX 32
37 #define TOK_HASH_SIZE 521
38 #define TOK_ALLOC_INCR 256 /* must be a power of two */
39 #define SYM_HASH_SIZE 263
41 /* number of available temporary registers */
42 #define NB_REGS 3
43 /* return register for functions */
44 #define FUNC_RET_REG 0
45 /* defined if function parameters must be evaluated in reverse order */
46 #define INVERT_FUNC_PARAMS
47 /* defined if structures are passed as pointers. Otherwise structures
48 are directly pushed on stack. */
49 //#define FUNC_STRUCT_PARAM_AS_PTR
51 /* token symbol management */
52 typedef struct TokenSym {
53 struct TokenSym *hash_next;
54 int tok; /* token number */
55 int len;
56 char str[1];
57 } TokenSym;
59 /* symbol management */
60 typedef struct Sym {
61 int v; /* symbol token */
62 int t; /* associated type */
63 int c; /* associated number */
64 struct Sym *next; /* next related symbol */
65 struct Sym *prev; /* prev symbol in stack */
66 struct Sym *hash_next; /* next symbol in hash table */
67 } Sym;
69 typedef struct SymStack {
70 struct Sym *top;
71 struct Sym *hash[SYM_HASH_SIZE];
72 } SymStack;
74 /* relocation entry (currently only used for functions or variables */
75 typedef struct Reloc {
76 int type; /* type of relocation */
77 int addr; /* address of relocation */
78 struct Reloc *next; /* next relocation */
79 } Reloc;
81 #define RELOC_ADDR32 1 /* 32 bits relocation */
82 #define RELOC_REL32 2 /* 32 bits relative relocation */
85 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
86 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
88 #define FUNC_NEW 1 /* ansi function prototype */
89 #define FUNC_OLD 2 /* old function prototype */
90 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
92 /* field 'Sym.t' for macros */
93 #define MACRO_OBJ 0 /* object like macro */
94 #define MACRO_FUNC 1 /* function like macro */
96 /* type_decl() types */
97 #define TYPE_ABSTRACT 1 /* type without variable */
98 #define TYPE_DIRECT 2 /* type with variable */
100 typedef struct {
101 FILE *file;
102 char *filename;
103 int line_num;
104 } IncludeFile;
106 /* loc : local variable index
107 glo : global variable index
108 ind : output code ptr
109 rsym: return symbol
110 prog: output code
111 anon_sym: anonymous symbol index
113 FILE *file;
114 int tok, tok1, tokc, rsym, anon_sym,
115 prog, ind, loc, glo, vt, vc, const_wanted, line_num;
116 int global_expr; /* true if compound literals must be allocated
117 globally (used during initializers parsing */
118 int func_vt, func_vc; /* current function return type (used by
119 return instruction) */
120 int tok_ident;
121 TokenSym **table_ident;
122 TokenSym *hash_ident[521];
123 char token_buf[STRING_MAX_SIZE + 1];
124 char *filename, *funcname;
125 SymStack define_stack, global_stack, local_stack, label_stack;
127 int vstack[VSTACK_SIZE], *vstack_ptr;
128 int *macro_ptr, *macro_ptr_allocated;
129 IncludeFile include_stack[INCLUDE_STACK_SIZE], *include_stack_ptr;
130 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
131 char *include_paths[INCLUDE_PATHS_MAX];
132 int nb_include_paths;
134 /* The current value can be: */
135 #define VT_VALMASK 0x000f
136 #define VT_CONST 0x000a /* constant in vc
137 (must be first non register value) */
138 #define VT_LLOCAL 0x000b /* lvalue, offset on stack */
139 #define VT_LOCAL 0x000c /* offset on stack */
140 #define VT_CMP 0x000d /* the value is stored in processor flags (in vc) */
141 #define VT_JMP 0x000e /* value is the consequence of jmp true */
142 #define VT_JMPI 0x000f /* value is the consequence of jmp false */
143 #define VT_LVAL 0x0010 /* var is an lvalue */
144 #define VT_LVALN -17 /* ~VT_LVAL */
145 #define VT_FORWARD 0x0020 /* value is forward reference
146 (only used for functions) */
148 /* types */
149 #define VT_INT 0
150 #define VT_VOID 0x00040
151 #define VT_BYTE 0x00080 /* signed byte type */
152 #define VT_PTR 0x00100 /* pointer increment */
153 #define VT_UNSIGNED 0x00200 /* unsigned type */
154 #define VT_ARRAY 0x00400 /* array type (only used in parsing) */
155 #define VT_ENUM 0x00800 /* enum definition */
156 #define VT_FUNC 0x01000 /* function type */
157 #define VT_STRUCT 0x002000 /* struct/union definition */
158 #define VT_SHORT 0x004000 /* short type */
159 #define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */
161 /* storage */
162 #define VT_EXTERN 0x00008000 /* extern definition */
163 #define VT_STATIC 0x00010000 /* static variable */
164 #define VT_TYPEDEF 0x00020000 /* typedef definition */
166 #define VT_TYPE 0xfffc7fc0 /* type mask */
167 #define VT_TYPEN 0x0000003f /* ~VT_TYPE */
168 #define VT_FUNCN -4097 /* ~VT_FUNC */
170 /* token values */
172 /* warning: the following compare tokens depend on i386 asm code */
173 #define TOK_ULT 0x92
174 #define TOK_UGE 0x93
175 #define TOK_EQ 0x94
176 #define TOK_NE 0x95
177 #define TOK_ULE 0x96
178 #define TOK_UGT 0x97
179 #define TOK_LT 0x9c
180 #define TOK_GE 0x9d
181 #define TOK_LE 0x9e
182 #define TOK_GT 0x9f
184 #define TOK_LAND 0xa0
185 #define TOK_LOR 0xa1
187 #define TOK_DEC 0xa2
188 #define TOK_MID 0xa3 /* inc/dec, to void constant */
189 #define TOK_INC 0xa4
190 #define TOK_ARROW 0xa7
191 #define TOK_DOTS 0xa8 /* three dots */
192 #define TOK_SHR 0xa9 /* unsigned shift right */
193 #define TOK_UDIV 0xb0 /* unsigned division */
194 #define TOK_UMOD 0xb1 /* unsigned modulo */
195 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
196 #define TOK_NUM 0xb3 /* number in tokc */
197 #define TOK_CCHAR 0xb4 /* char constant in tokc */
198 #define TOK_STR 0xb5 /* pointer to string in tokc */
199 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
200 #define TOK_LCHAR 0xb7
201 #define TOK_LSTR 0xb8
203 #define TOK_SHL 0x01 /* shift left */
204 #define TOK_SAR 0x02 /* signed shift right */
206 /* assignement operators : normal operator or 0x80 */
207 #define TOK_A_MOD 0xa5
208 #define TOK_A_AND 0xa6
209 #define TOK_A_MUL 0xaa
210 #define TOK_A_ADD 0xab
211 #define TOK_A_SUB 0xad
212 #define TOK_A_DIV 0xaf
213 #define TOK_A_XOR 0xde
214 #define TOK_A_OR 0xfc
215 #define TOK_A_SHL 0x81
216 #define TOK_A_SAR 0x82
218 /* all identificators and strings have token above that */
219 #define TOK_IDENT 256
221 enum {
222 TOK_INT = TOK_IDENT,
223 TOK_VOID,
224 TOK_CHAR,
225 TOK_IF,
226 TOK_ELSE,
227 TOK_WHILE,
228 TOK_BREAK,
229 TOK_RETURN,
230 TOK_FOR,
231 TOK_EXTERN,
232 TOK_STATIC,
233 TOK_UNSIGNED,
234 TOK_GOTO,
235 TOK_DO,
236 TOK_CONTINUE,
237 TOK_SWITCH,
238 TOK_CASE,
240 /* ignored types Must have contiguous values */
241 TOK_CONST,
242 TOK_VOLATILE,
243 TOK_LONG,
244 TOK_REGISTER,
245 TOK_SIGNED,
246 TOK_AUTO,
247 TOK_INLINE,
248 TOK_RESTRICT,
250 /* unsupported type */
251 TOK_FLOAT,
252 TOK_DOUBLE,
254 TOK_SHORT,
255 TOK_STRUCT,
256 TOK_UNION,
257 TOK_TYPEDEF,
258 TOK_DEFAULT,
259 TOK_ENUM,
260 TOK_SIZEOF,
262 /* preprocessor only */
263 TOK_DEFINE,
264 TOK_INCLUDE,
265 TOK_IFDEF,
266 TOK_IFNDEF,
267 TOK_ELIF,
268 TOK_ENDIF,
269 TOK_DEFINED,
270 TOK_UNDEF,
271 TOK_ERROR,
272 TOK_LINE,
273 TOK___LINE__,
274 TOK___FILE__,
275 TOK___DATE__,
276 TOK___TIME__,
277 TOK___VA_ARGS__,
279 /* special identifiers */
280 TOK___FUNC__,
281 TOK_MAIN,
284 void sum();
285 void next(void);
286 void next_nomacro();
287 int expr_const();
288 void expr_eq();
289 void expr(void);
290 void decl(int l);
291 void decl_initializer(int t, int c, int first, int size_only);
292 int decl_initializer_alloc(int t, int has_init);
293 int gv(void);
294 void move_reg();
295 void save_reg();
296 void vpush(void);
297 int get_reg(void);
298 void macro_subst(int **tok_str, int *tok_len,
299 Sym **nested_list, int *macro_str);
300 int save_reg_forced(int r);
301 void vstore(void);
302 int type_size(int t, int *a);
303 int pointed_type(int t);
304 int pointed_size(int t);
305 int ist(void);
306 int type_decl(int *v, int t, int td);
308 #ifdef PROFILE
309 /* dummy function for profiling */
310 void *dlopen(const char *filename, int flag)
312 return (void *)1;
314 const char *dlerror(void)
316 return "error";
319 void *dlsym(void *handle, char *symbol)
321 return (void *)1;
324 #endif
326 inline int isid(c)
328 return (c >= 'a' && c <= 'z') ||
329 (c >= 'A' && c <= 'Z') ||
330 c == '_';
333 inline int isnum(c)
335 return c >= '0' & c <= '9';
338 void printline()
340 IncludeFile *f;
341 for(f = include_stack; f < include_stack_ptr; f++)
342 fprintf(stderr, "In file included from %s:%d:\n",
343 f->filename, f->line_num);
344 fprintf(stderr, "%s:%d: ", filename, line_num);
347 void error(const char *fmt, ...)
349 va_list ap;
350 va_start(ap, fmt);
351 printline();
352 vfprintf(stderr, fmt, ap);
353 fprintf(stderr, "\n");
354 exit(1);
355 va_end(ap);
358 void expect(const char *msg)
360 error("%s expected", msg);
363 void warning(const char *msg)
365 printline();
366 fprintf(stderr, "warning: %s\n", msg);
369 void skip(c)
371 if (tok != c)
372 error("'%c' expected", c);
373 next();
376 void test_lvalue()
378 if (!(vt & VT_LVAL))
379 expect("lvalue");
382 TokenSym *tok_alloc(char *str, int len)
384 TokenSym *ts, **pts, **ptable;
385 int h, i;
387 if (len <= 0)
388 len = strlen(str);
389 h = 1;
390 for(i=0;i<len;i++)
391 h = ((h << 8) | (str[i] & 0xff)) % TOK_HASH_SIZE;
393 pts = &hash_ident[h];
394 while (1) {
395 ts = *pts;
396 if (!ts)
397 break;
398 if (ts->len == len && !memcmp(ts->str, str, len))
399 return ts;
400 pts = &(ts->hash_next);
402 /* expand token table if needed */
403 i = tok_ident - TOK_IDENT;
404 if ((i % TOK_ALLOC_INCR) == 0) {
405 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
406 if (!ptable)
407 error("memory full");
408 table_ident = ptable;
410 ts = malloc(sizeof(TokenSym) + len);
411 if (!ts)
412 error("memory full");
413 table_ident[i] = ts;
414 ts->tok = tok_ident++;
415 ts->len = len;
416 ts->hash_next = NULL;
417 memcpy(ts->str, str, len + 1);
418 *pts = ts;
419 return ts;
422 void add_char(char **pp, int c)
424 char *p;
425 p = *pp;
426 if (c == '\'' || c == '\"' || c == '\\') {
427 /* XXX: could be more precise if char or string */
428 *p++ = '\\';
430 if (c >= 32 && c <= 126) {
431 *p++ = c;
432 } else {
433 *p++ = '\\';
434 if (c == '\n') {
435 *p++ = 'n';
436 } else {
437 *p++ = '0' + ((c >> 6) & 7);
438 *p++ = '0' + ((c >> 3) & 7);
439 *p++ = '0' + (c & 7);
442 *pp = p;
445 /* XXX: buffer overflow */
446 char *get_tok_str(int v, int c)
448 static char buf[STRING_MAX_SIZE + 1];
449 TokenSym *ts;
450 char *p;
451 int i;
453 if (v == TOK_NUM) {
454 sprintf(buf, "%d", c);
455 return buf;
456 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
457 p = buf;
458 *p++ = '\'';
459 add_char(&p, c);
460 *p++ = '\'';
461 *p = '\0';
462 return buf;
463 } else if (v == TOK_STR || v == TOK_LSTR) {
464 ts = (TokenSym *)c;
465 p = buf;
466 *p++ = '\"';
467 for(i=0;i<ts->len;i++)
468 add_char(&p, ts->str[i]);
469 *p++ = '\"';
470 *p = '\0';
471 return buf;
472 } else if (v < TOK_IDENT) {
473 p = buf;
474 *p++ = v;
475 *p = '\0';
476 return buf;
477 } else if (v < tok_ident) {
478 return table_ident[v - TOK_IDENT]->str;
479 } else {
480 /* should never happen */
481 return NULL;
485 /* push, without hashing */
486 Sym *sym_push2(Sym **ps, int v, int t, int c)
488 Sym *s;
489 s = malloc(sizeof(Sym));
490 if (!s)
491 error("memory full");
492 s->v = v;
493 s->t = t;
494 s->c = c;
495 s->next = NULL;
496 /* add in stack */
497 s->prev = *ps;
498 *ps = s;
499 return s;
502 /* find a symbol and return its associated structure. 's' is the top
503 of the symbol stack */
504 Sym *sym_find2(Sym *s, int v)
506 while (s) {
507 if (s->v == v)
508 return s;
509 s = s->prev;
511 return NULL;
514 /* find a symbol and return its associated structure. 'st' is the
515 symbol stack */
516 Sym *sym_find1(SymStack *st, int v)
518 Sym *s;
520 s = st->hash[v % SYM_HASH_SIZE];
521 while (s) {
522 if (s->v == v)
523 return s;
524 s = s->hash_next;
526 return 0;
529 Sym *sym_push1(SymStack *st, int v, int t, int c)
531 Sym *s, **ps;
532 s = sym_push2(&st->top, v, t, c);
533 /* add in hash table */
534 ps = &st->hash[s->v % SYM_HASH_SIZE];
535 s->hash_next = *ps;
536 *ps = s;
537 return s;
540 /* find a symbol in the right symbol space */
541 Sym *sym_find(int v)
543 Sym *s;
544 s = sym_find1(&local_stack, v);
545 if (!s)
546 s = sym_find1(&global_stack, v);
547 return s;
550 /* push a given symbol on the symbol stack */
551 Sym *sym_push(int v, int t, int c)
553 if (local_stack.top)
554 return sym_push1(&local_stack, v, t, c);
555 else
556 return sym_push1(&global_stack, v, t, c);
559 /* pop symbols until top reaches 'b' */
560 void sym_pop(SymStack *st, Sym *b)
562 Sym *s, *ss;
564 s = st->top;
565 while(s != b) {
566 ss = s->prev;
567 /* free hash table entry */
568 st->hash[s->v % SYM_HASH_SIZE] = s->hash_next;
569 free(s);
570 s = ss;
572 st->top = b;
575 int ch, ch1;
577 /* read next char from current input file */
578 void inp()
580 redo:
581 ch1 = fgetc(file);
582 if (ch1 == -1) {
583 if (include_stack_ptr == include_stack)
584 return;
585 /* pop include stack */
586 fclose(file);
587 free(filename);
588 include_stack_ptr--;
589 file = include_stack_ptr->file;
590 filename = include_stack_ptr->filename;
591 line_num = include_stack_ptr->line_num;
592 goto redo;
594 if (ch1 == '\n')
595 line_num++;
596 // printf("ch1=%c 0x%x\n", ch1, ch1);
599 /* input with '\\n' handling */
600 void minp()
602 redo:
603 ch = ch1;
604 inp();
605 if (ch == '\\' && ch1 == '\n') {
606 inp();
607 goto redo;
609 //printf("ch=%c 0x%x\n", ch, ch);
612 /* same as minp, but also skip comments */
613 void cinp()
615 int c;
617 if (ch1 == '/') {
618 inp();
619 if (ch1 == '/') {
620 /* single line C++ comments */
621 inp();
622 while (ch1 != '\n' && ch1 != -1)
623 inp();
624 inp();
625 ch = ' '; /* return space */
626 } else if (ch1 == '*') {
627 /* C comments */
628 inp();
629 while (ch1 != -1) {
630 c = ch1;
631 inp();
632 if (c == '*' && ch1 == '/') {
633 inp();
634 ch = ' '; /* return space */
635 break;
638 } else {
639 ch = '/';
641 } else {
642 minp();
646 void skip_spaces()
648 while (ch == ' ' || ch == '\t')
649 cinp();
652 /* skip block of text until #else, #elif or #endif. skip also pairs of
653 #if/#endif */
654 void preprocess_skip()
656 int a;
657 a = 0;
658 while (1) {
659 while (ch != '\n') {
660 if (ch == -1)
661 expect("#endif");
662 cinp();
664 cinp();
665 skip_spaces();
666 if (ch == '#') {
667 cinp();
668 next_nomacro();
669 if (a == 0 &&
670 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
671 break;
672 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
673 a++;
674 else if (tok == TOK_ENDIF)
675 a--;
680 inline int is_long_tok(int t)
682 return (t == TOK_NUM ||
683 t == TOK_CCHAR || t == TOK_LCHAR ||
684 t == TOK_STR || t == TOK_LSTR);
687 void tok_add(int **tok_str, int *tok_len, int t)
689 int len, *str;
690 len = *tok_len;
691 str = *tok_str;
692 if ((len & 63) == 0) {
693 str = realloc(str, (len + 64) * sizeof(int));
694 if (!str)
695 return;
696 *tok_str = str;
698 str[len++] = t;
699 *tok_len = len;
702 void tok_add2(int **tok_str, int *tok_len, int t, int c)
704 tok_add(tok_str, tok_len, t);
705 if (is_long_tok(t))
706 tok_add(tok_str, tok_len, c);
709 /* eval an expression for #if/#elif */
710 int expr_preprocess()
712 int *str, len, c, t;
714 str = NULL;
715 len = 0;
716 while (1) {
717 skip_spaces();
718 if (ch == '\n')
719 break;
720 next(); /* do macro subst */
721 if (tok == TOK_DEFINED) {
722 next_nomacro();
723 t = tok;
724 if (t == '(')
725 next_nomacro();
726 c = sym_find1(&define_stack, tok) != 0;
727 if (t == '(')
728 next_nomacro();
729 tok = TOK_NUM;
730 tokc = c;
731 } else if (tok >= TOK_IDENT) {
732 /* if undefined macro */
733 tok = TOK_NUM;
734 tokc = 0;
736 tok_add2(&str, &len, tok, tokc);
738 tok_add(&str, &len, -1); /* simulate end of file */
739 tok_add(&str, &len, 0);
740 /* now evaluate C constant expression */
741 macro_ptr = str;
742 next();
743 c = expr_const();
744 macro_ptr = NULL;
745 free(str);
746 return c != 0;
749 #ifdef DEBUG
750 void tok_print(int *str)
752 int t, c;
754 while (1) {
755 t = *str++;
756 if (!t)
757 break;
758 c = 0;
759 if (is_long_tok(t))
760 c = *str++;
761 printf(" %s", get_tok_str(t, c));
763 printf("\n");
765 #endif
767 /* XXX: should be more factorized */
768 void define_symbol(char *sym)
770 TokenSym *ts;
771 int *str, len;
773 ts = tok_alloc(sym, 0);
774 str = NULL;
775 len = 0;
776 tok_add2(&str, &len, TOK_NUM, 1);
777 tok_add(&str, &len, 0);
778 sym_push1(&define_stack, ts->tok, MACRO_OBJ, (int)str);
781 void preprocess()
783 int size, i, c, v, t, *str, len;
784 char buf[1024], *q, *p;
785 char buf1[1024];
786 FILE *f;
787 Sym **ps, *first, *s;
789 cinp();
790 next_nomacro();
791 redo:
792 if (tok == TOK_DEFINE) {
793 next_nomacro();
794 v = tok;
795 /* XXX: should check if same macro (ANSI) */
796 first = NULL;
797 t = MACRO_OBJ;
798 /* '(' must be just after macro definition for MACRO_FUNC */
799 if (ch == '(') {
800 next_nomacro();
801 next_nomacro();
802 ps = &first;
803 while (tok != ')') {
804 if (tok == TOK_DOTS)
805 tok = TOK___VA_ARGS__;
806 s = sym_push1(&define_stack, tok | SYM_FIELD, 0, 0);
807 *ps = s;
808 ps = &s->next;
809 next_nomacro();
810 if (tok != ',')
811 break;
812 next_nomacro();
814 t = MACRO_FUNC;
816 str = NULL;
817 len = 0;
818 while (1) {
819 skip_spaces();
820 if (ch == '\n' || ch == -1)
821 break;
822 next_nomacro();
823 tok_add2(&str, &len, tok, tokc);
825 tok_add(&str, &len, 0);
826 #ifdef PP_DEBUG
827 printf("define %s %d: ", get_tok_str(v, 0), t);
828 tok_print(str);
829 #endif
830 s = sym_push1(&define_stack, v, t, (int)str);
831 s->next = first;
832 } else if (tok == TOK_UNDEF) {
833 next_nomacro();
834 s = sym_find1(&define_stack, tok);
835 /* undefine symbol by putting an invalid name */
836 if (s)
837 s->v = 0;
838 } else if (tok == TOK_INCLUDE) {
839 skip_spaces();
840 if (ch == '<') {
841 c = '>';
842 goto read_name;
843 } else if (ch == '\"') {
844 c = ch;
845 read_name:
846 minp();
847 q = buf;
848 while (ch != c && ch != '\n' && ch != -1) {
849 if ((q - buf) < sizeof(buf) - 1)
850 *q++ = ch;
851 minp();
853 *q = '\0';
854 } else {
855 next();
856 if (tok != TOK_STR)
857 error("#include syntax error");
858 /* XXX: buffer overflow */
859 strcpy(buf, get_tok_str(tok, tokc));
860 c = '\"';
862 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
863 error("memory full");
864 if (c == '\"') {
865 /* first search in current dir if "header.h" */
866 /* XXX: buffer overflow */
867 size = 0;
868 p = strrchr(filename, '/');
869 if (p)
870 size = p + 1 - filename;
871 memcpy(buf1, filename, size);
872 buf1[size] = '\0';
873 strcat(buf1, buf);
874 f = fopen(buf1, "r");
875 if (f)
876 goto found;
878 /* now search in standard include path */
879 for(i=nb_include_paths - 1;i>=0;i--) {
880 strcpy(buf1, include_paths[i]);
881 strcat(buf1, "/");
882 strcat(buf1, buf);
883 f = fopen(buf1, "r");
884 if (f)
885 goto found;
887 error("include file not found");
888 f = NULL;
889 found:
890 /* push current file in stack */
891 /* XXX: fix current line init */
892 include_stack_ptr->file = file;
893 include_stack_ptr->filename = filename;
894 include_stack_ptr->line_num = line_num;
895 include_stack_ptr++;
896 file = f;
897 filename = strdup(buf1);
898 line_num = 1;
899 } else if (tok == TOK_IFNDEF) {
900 c = 1;
901 goto do_ifdef;
902 } else if (tok == TOK_IF) {
903 c = expr_preprocess();
904 goto do_if;
905 } else if (tok == TOK_IFDEF) {
906 c = 0;
907 do_ifdef:
908 next_nomacro();
909 c = (sym_find1(&define_stack, tok) != 0) ^ c;
910 do_if:
911 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
912 error("memory full");
913 *ifdef_stack_ptr++ = c;
914 goto test_skip;
915 } else if (tok == TOK_ELSE) {
916 if (ifdef_stack_ptr == ifdef_stack ||
917 (ifdef_stack_ptr[-1] & 2))
918 error("#else after #else");
919 c = (ifdef_stack_ptr[-1] ^= 3);
920 goto test_skip;
921 } else if (tok == TOK_ELIF) {
922 if (ifdef_stack_ptr == ifdef_stack ||
923 ifdef_stack_ptr[-1] > 1)
924 error("#elif after #else");
925 c = expr_preprocess();
926 ifdef_stack_ptr[-1] = c;
927 test_skip:
928 if (!(c & 1)) {
929 preprocess_skip();
930 goto redo;
932 } else if (tok == TOK_ENDIF) {
933 if (ifdef_stack_ptr == ifdef_stack)
934 expect("#if");
935 ifdef_stack_ptr--;
936 } else if (tok == TOK_LINE) {
937 next();
938 if (tok != TOK_NUM)
939 error("#line");
940 line_num = tokc;
941 skip_spaces();
942 if (ch != '\n') {
943 next();
944 if (tok != TOK_STR)
945 error("#line");
946 /* XXX: potential memory leak */
947 filename = strdup(get_tok_str(tok, tokc));
949 } else if (tok == TOK_ERROR) {
950 error("#error");
952 /* ignore other preprocess commands or #! for C scripts */
953 while (ch != '\n' && ch != -1)
954 cinp();
957 /* read a number in base b */
958 int getn(b)
960 int n, t;
961 n = 0;
962 while (1) {
963 if (ch >= 'a' & ch <= 'f')
964 t = ch - 'a' + 10;
965 else if (ch >= 'A' & ch <= 'F')
966 t = ch - 'A' + 10;
967 else if (isnum(ch))
968 t = ch - '0';
969 else
970 break;
971 if (t < 0 | t >= b)
972 break;
973 n = n * b + t;
974 cinp();
976 return n;
979 /* read a character for string or char constant and eval escape codes */
980 int getq()
982 int c;
984 c = ch;
985 minp();
986 if (c == '\\') {
987 if (isnum(ch)) {
988 /* at most three octal digits */
989 c = ch - '0';
990 minp();
991 if (isnum(ch)) {
992 c = c * 8 + ch - '0';
993 minp();
994 if (isnum(ch)) {
995 c = c * 8 + ch - '0';
996 minp();
999 return c;
1000 } else if (ch == 'x') {
1001 minp();
1002 return getn(16);
1003 } else {
1004 if (ch == 'a')
1005 c = '\a';
1006 else if (ch == 'b')
1007 c = '\b';
1008 else if (ch == 'f')
1009 c = '\f';
1010 else if (ch == 'n')
1011 c = '\n';
1012 else if (ch == 'r')
1013 c = '\r';
1014 else if (ch == 't')
1015 c = '\t';
1016 else if (ch == 'v')
1017 c = '\v';
1018 else
1019 c = ch;
1020 minp();
1023 return c;
1026 /* return next token without macro substitution */
1027 void next_nomacro1()
1029 int b;
1030 char *q;
1031 TokenSym *ts;
1033 /* skip spaces */
1034 while(1) {
1035 while (ch == '\n') {
1036 cinp();
1037 while (ch == ' ' || ch == 9)
1038 cinp();
1039 if (ch == '#') {
1040 /* preprocessor command if # at start of line after
1041 spaces */
1042 preprocess();
1045 if (ch != ' ' && ch != '\t' && ch != '\f')
1046 break;
1047 cinp();
1049 if (isid(ch)) {
1050 q = token_buf;
1051 *q++ = ch;
1052 cinp();
1053 if (q[-1] == 'L') {
1054 /* XXX: not supported entirely (needs different
1055 preprocessor architecture) */
1056 if (ch == '\'') {
1057 tok = TOK_LCHAR;
1058 goto char_const;
1060 if (ch == '\"') {
1061 tok = TOK_LSTR;
1062 goto str_const;
1065 while (isid(ch) | isnum(ch)) {
1066 if (q >= token_buf + STRING_MAX_SIZE)
1067 error("ident too long");
1068 *q++ = ch;
1069 cinp();
1071 *q = '\0';
1072 ts = tok_alloc(token_buf, q - token_buf);
1073 tok = ts->tok;
1074 } else if (isnum(ch)) {
1075 /* number */
1076 b = 10;
1077 if (ch == '0') {
1078 cinp();
1079 b = 8;
1080 if (ch == 'x' || ch == 'X') {
1081 cinp();
1082 b = 16;
1083 } else if (ch == 'b' || ch == 'B') {
1084 cinp();
1085 b = 2;
1088 tokc = getn(b);
1089 /* XXX: add unsigned constant support (ANSI) */
1090 while (ch == 'L' || ch == 'l' || ch == 'U' || ch == 'u')
1091 cinp();
1092 tok = TOK_NUM;
1093 } else if (ch == '\'') {
1094 tok = TOK_CCHAR;
1095 char_const:
1096 minp();
1097 tokc = getq();
1098 if (ch != '\'')
1099 expect("\'");
1100 minp();
1101 } else if (ch == '\"') {
1102 tok = TOK_STR;
1103 str_const:
1104 minp();
1105 q = token_buf;
1106 while (ch != '\"') {
1107 b = getq();
1108 if (ch == -1)
1109 error("unterminated string");
1110 if (q >= token_buf + STRING_MAX_SIZE)
1111 error("string too long");
1112 *q++ = b;
1114 *q = '\0';
1115 tokc = (int)tok_alloc(token_buf, q - token_buf);
1116 minp();
1117 } else {
1118 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\247..\250##\266";
1119 /* two chars */
1120 tok = ch;
1121 cinp();
1122 while (*q) {
1123 if (*q == tok & q[1] == ch) {
1124 cinp();
1125 tok = q[2] & 0xff;
1126 /* three chars tests */
1127 if (tok == TOK_SHL | tok == TOK_SAR) {
1128 if (ch == '=') {
1129 tok = tok | 0x80;
1130 cinp();
1132 } else if (tok == TOK_DOTS) {
1133 if (ch != '.')
1134 error("parse error");
1135 cinp();
1137 return;
1139 q = q + 3;
1141 /* single char substitutions */
1142 if (tok == '<')
1143 tok = TOK_LT;
1144 else if (tok == '>')
1145 tok = TOK_GT;
1149 /* return next token without macro substitution. Can read input from
1150 macro_ptr buffer */
1151 void next_nomacro()
1153 if (macro_ptr) {
1154 tok = *macro_ptr;
1155 if (tok) {
1156 macro_ptr++;
1157 if (is_long_tok(tok))
1158 tokc = *macro_ptr++;
1160 } else {
1161 next_nomacro1();
1165 /* substitute args in macro_str and return allocated string */
1166 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
1168 int *st, last_tok, t, c, notfirst, *str, len;
1169 Sym *s;
1170 TokenSym *ts;
1172 str = NULL;
1173 len = 0;
1174 last_tok = 0;
1175 while(1) {
1176 t = *macro_str++;
1177 if (!t)
1178 break;
1179 if (t == '#') {
1180 /* stringize */
1181 t = *macro_str++;
1182 if (!t)
1183 break;
1184 s = sym_find2(args, t);
1185 if (s) {
1186 token_buf[0] = '\0';
1187 st = (int *)s->c;
1188 /* XXX: buffer overflow */
1189 notfirst = 0;
1190 while (*st) {
1191 if (notfirst)
1192 strcat(token_buf, " ");
1193 t = *st++;
1194 c = 0;
1195 if (is_long_tok(t))
1196 c = *st++;
1197 strcat(token_buf, get_tok_str(t, c));
1198 notfirst = 1;
1200 #ifdef PP_DEBUG
1201 printf("stringize: %s\n", token_buf);
1202 #endif
1203 /* add string */
1204 ts = tok_alloc(token_buf, 0);
1205 tok_add2(&str, &len, TOK_STR, (int)ts);
1206 } else {
1207 tok_add(&str, &len, t);
1209 } else if (is_long_tok(t)) {
1210 tok_add2(&str, &len, t, *macro_str++);
1211 } else {
1212 s = sym_find2(args, t);
1213 if (s) {
1214 st = (int *)s->c;
1215 /* if '##' is present before or after , no arg substitution */
1216 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
1217 while (*st)
1218 tok_add(&str, &len, *st++);
1219 } else {
1220 macro_subst(&str, &len, nested_list, st);
1222 } else {
1223 tok_add(&str, &len, t);
1226 last_tok = t;
1228 tok_add(&str, &len, 0);
1229 return str;
1232 /* handle the '##' operator */
1233 int *macro_twosharps(int *macro_str)
1235 TokenSym *ts;
1236 int *macro_str1, macro_str1_len, *macro_ptr1;
1237 int t, c;
1238 char *p;
1240 macro_str1 = NULL;
1241 macro_str1_len = 0;
1242 tok = 0;
1243 while (1) {
1244 next_nomacro();
1245 if (tok == 0)
1246 break;
1247 if (*macro_ptr == TOK_TWOSHARPS) {
1248 macro_ptr++;
1249 macro_ptr1 = macro_ptr;
1250 t = *macro_ptr;
1251 if (t) {
1252 macro_ptr++;
1253 c = 0;
1254 if (is_long_tok(t))
1255 c = *macro_ptr++;
1256 /* XXX: we handle only most common cases:
1257 ident + ident or ident + number */
1258 if (tok >= TOK_IDENT &&
1259 (t >= TOK_IDENT || t == TOK_NUM)) {
1260 /* XXX: buffer overflow */
1261 p = get_tok_str(tok, tokc);
1262 strcpy(token_buf, p);
1263 p = get_tok_str(t, c);
1264 strcat(token_buf, p);
1265 ts = tok_alloc(token_buf, 0);
1266 tok_add2(&macro_str1, &macro_str1_len, ts->tok, 0);
1267 } else {
1268 /* cannot merge tokens: skip '##' */
1269 macro_ptr = macro_ptr1;
1272 } else {
1273 tok_add2(&macro_str1, &macro_str1_len, tok, tokc);
1276 tok_add(&macro_str1, &macro_str1_len, 0);
1277 return macro_str1;
1282 /* do macro substitution of macro_str and add result to
1283 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1284 substituted. 'nested_list' is the list of all macros we got inside
1285 to avoid recursing. */
1286 void macro_subst(int **tok_str, int *tok_len,
1287 Sym **nested_list, int *macro_str)
1289 Sym *s, *args, *sa, *sa1;
1290 int *str, parlevel, len, *mstr, t, *saved_macro_ptr;
1291 int mstr_allocated, *macro_str1;
1293 saved_macro_ptr = macro_ptr;
1294 macro_ptr = macro_str;
1295 macro_str1 = NULL;
1296 if (macro_str) {
1297 /* first scan for '##' operator handling */
1298 macro_str1 = macro_twosharps(macro_str);
1299 macro_ptr = macro_str1;
1302 while (1) {
1303 next_nomacro();
1304 if (tok == 0)
1305 break;
1306 /* special macros */
1307 if (tok == TOK___LINE__) {
1308 tok_add2(tok_str, tok_len, TOK_NUM, line_num);
1309 } else if (tok == TOK___FILE__) {
1310 tok_add2(tok_str, tok_len, TOK_STR,
1311 (int)tok_alloc(filename, 0));
1312 } else if (tok == TOK___DATE__) {
1313 tok_add2(tok_str, tok_len, TOK_STR,
1314 (int)tok_alloc("Jan 1 1970", 0));
1315 } else if (tok == TOK___TIME__) {
1316 tok_add2(tok_str, tok_len, TOK_STR,
1317 (int)tok_alloc("00:00:00", 0));
1318 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
1319 /* if symbol is a macro, prepare substitution */
1320 /* if nested substitution, do nothing */
1321 if (sym_find2(*nested_list, tok))
1322 goto no_subst;
1323 mstr = (int *)s->c;
1324 mstr_allocated = 0;
1325 if (s->t == MACRO_FUNC) {
1326 /* NOTE: we do not use next_nomacro to avoid eating the
1327 next token. XXX: find better solution */
1328 if (macro_ptr) {
1329 t = *macro_ptr;
1330 } else {
1331 while (ch == ' ' || ch == '\t' || ch == '\n')
1332 cinp();
1333 t = ch;
1335 if (t != '(') /* no macro subst */
1336 goto no_subst;
1338 /* argument macro */
1339 next_nomacro();
1340 next_nomacro();
1341 args = NULL;
1342 sa = s->next;
1343 while (tok != ')' && sa) {
1344 len = 0;
1345 str = NULL;
1346 parlevel = 0;
1347 while ((parlevel > 0 ||
1348 (tok != ')' &&
1349 (tok != ',' ||
1350 sa->v == (TOK___VA_ARGS__ | SYM_FIELD)))) &&
1351 tok != -1) {
1352 if (tok == '(')
1353 parlevel++;
1354 else if (tok == ')')
1355 parlevel--;
1356 tok_add2(&str, &len, tok, tokc);
1357 next_nomacro();
1359 tok_add(&str, &len, 0);
1360 sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
1361 if (tok != ',')
1362 break;
1363 next_nomacro();
1364 sa = sa->next;
1366 if (tok != ')')
1367 expect(")");
1368 /* now subst each arg */
1369 mstr = macro_arg_subst(nested_list, mstr, args);
1370 /* free memory */
1371 sa = args;
1372 while (sa) {
1373 sa1 = sa->prev;
1374 free((int *)sa->c);
1375 free(sa);
1376 sa = sa1;
1378 mstr_allocated = 1;
1380 sym_push2(nested_list, s->v, 0, 0);
1381 macro_subst(tok_str, tok_len, nested_list, mstr);
1382 /* pop nested defined symbol */
1383 sa1 = *nested_list;
1384 *nested_list = sa1->prev;
1385 free(sa1);
1386 if (mstr_allocated)
1387 free(mstr);
1388 } else {
1389 no_subst:
1390 /* no need to add if reading input stream */
1391 if (!macro_str)
1392 return;
1393 tok_add2(tok_str, tok_len, tok, tokc);
1395 /* only replace one macro while parsing input stream */
1396 if (!macro_str)
1397 return;
1399 macro_ptr = saved_macro_ptr;
1400 if (macro_str1)
1401 free(macro_str1);
1404 /* return next token with macro substitution */
1405 void next()
1407 int len, *ptr;
1408 Sym *nested_list;
1410 /* special 'ungettok' case for label parsing */
1411 if (tok1) {
1412 tok = tok1;
1413 tok1 = 0;
1414 } else {
1415 redo:
1416 if (!macro_ptr) {
1417 /* if not reading from macro substuted string, then try to substitute */
1418 len = 0;
1419 ptr = NULL;
1420 nested_list = NULL;
1421 macro_subst(&ptr, &len, &nested_list, NULL);
1422 if (ptr) {
1423 tok_add(&ptr, &len, 0);
1424 macro_ptr = ptr;
1425 macro_ptr_allocated = ptr;
1426 goto redo;
1428 if (tok == 0)
1429 goto redo;
1430 } else {
1431 next_nomacro();
1432 if (tok == 0) {
1433 /* end of macro string: free it */
1434 free(macro_ptr_allocated);
1435 macro_ptr = NULL;
1436 goto redo;
1440 #ifdef DEBUG
1441 printf("token = %s\n", get_tok_str(tok, tokc));
1442 #endif
1445 void swap(int *p, int *q)
1447 int t;
1448 t = *p;
1449 *p = *q;
1450 *q = t;
1453 void vset(t, v)
1455 vt = t;
1456 vc = v;
1459 /******************************************************/
1460 /* X86 code generator */
1462 typedef struct GFuncContext {
1463 int args_size;
1464 } GFuncContext;
1466 void g(int c)
1468 *(char *)ind++ = c;
1471 void o(int c)
1473 while (c) {
1474 g(c);
1475 c = c / 256;
1479 void gen_le32(int c)
1481 g(c);
1482 g(c >> 8);
1483 g(c >> 16);
1484 g(c >> 24);
1487 /* add a new relocation entry to symbol 's' */
1488 void greloc(Sym *s, int addr, int type)
1490 Reloc *p;
1491 p = malloc(sizeof(Reloc));
1492 if (!p)
1493 error("memory full");
1494 p->type = type;
1495 p->addr = addr;
1496 p->next = (Reloc *)s->c;
1497 s->c = (int)p;
1500 /* patch each relocation entry with value 'val' */
1501 void greloc_patch(Sym *s, int val)
1503 Reloc *p, *p1;
1505 p = (Reloc *)s->c;
1506 while (p != NULL) {
1507 p1 = p->next;
1508 switch(p->type) {
1509 case RELOC_ADDR32:
1510 *(int *)p->addr = val;
1511 break;
1512 case RELOC_REL32:
1513 *(int *)p->addr = val - p->addr - 4;
1514 break;
1516 free(p);
1517 p = p1;
1519 s->c = val;
1522 /* output a symbol and patch all calls to it */
1523 void gsym_addr(t, a)
1525 int n;
1526 while (t) {
1527 n = *(int *)t; /* next value */
1528 *(int *)t = a - t - 4;
1529 t = n;
1533 void gsym(t)
1535 gsym_addr(t, ind);
1538 /* psym is used to put an instruction with a data field which is a
1539 reference to a symbol. It is in fact the same as oad ! */
1540 #define psym oad
1542 /* instruction + 4 bytes data. Return the address of the data */
1543 int oad(int c, int s)
1545 o(c);
1546 *(int *)ind = s;
1547 s = ind;
1548 ind = ind + 4;
1549 return s;
1552 /* output constant with relocation if 't & VT_FORWARD' is true */
1553 void gen_addr32(int c, int t)
1555 if (!(t & VT_FORWARD)) {
1556 gen_le32(c);
1557 } else {
1558 greloc((Sym *)c, ind, RELOC_ADDR32);
1559 gen_le32(0);
1563 /* XXX: generate correct pointer for forward references to functions */
1564 /* r = (ft, fc) */
1565 void load(r, ft, fc)
1567 int v, t;
1569 v = ft & VT_VALMASK;
1570 if (ft & VT_LVAL) {
1571 if (v == VT_LLOCAL) {
1572 load(r, VT_LOCAL | VT_LVAL, fc);
1573 v = r;
1575 if ((ft & VT_TYPE) == VT_BYTE)
1576 o(0xbe0f); /* movsbl */
1577 else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED))
1578 o(0xb60f); /* movzbl */
1579 else if ((ft & VT_TYPE) == VT_SHORT)
1580 o(0xbf0f); /* movswl */
1581 else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED))
1582 o(0xb70f); /* movzwl */
1583 else
1584 o(0x8b); /* movl */
1585 if (v == VT_CONST) {
1586 o(0x05 + r * 8); /* 0xXX, r */
1587 gen_addr32(fc, ft);
1588 } else if (v == VT_LOCAL) {
1589 oad(0x85 + r * 8, fc); /* xx(%ebp), r */
1590 } else {
1591 g(0x00 + r * 8 + v); /* (v), r */
1593 } else {
1594 if (v == VT_CONST) {
1595 o(0xb8 + r); /* mov $xx, r */
1596 gen_addr32(fc, ft);
1597 } else if (v == VT_LOCAL) {
1598 o(0x8d);
1599 oad(0x85 + r * 8, fc); /* lea xxx(%ebp), r */
1600 } else if (v == VT_CMP) {
1601 oad(0xb8 + r, 0); /* mov $0, r */
1602 o(0x0f); /* setxx %br */
1603 o(fc);
1604 o(0xc0 + r);
1605 } else if (v == VT_JMP || v == VT_JMPI) {
1606 t = v & 1;
1607 oad(0xb8 + r, t); /* mov $1, r */
1608 oad(0xe9, 5); /* jmp after */
1609 gsym(fc);
1610 oad(0xb8 + r, t ^ 1); /* mov $0, r */
1611 } else if (v != r) {
1612 o(0x89);
1613 o(0xc0 + r + v * 8); /* mov v, r */
1618 /* (ft, fc) = r */
1619 /* WARNING: r must not be allocated on the stack */
1620 void store(r, ft, fc)
1622 int fr, b;
1624 fr = ft & VT_VALMASK;
1625 b = (ft & VT_TYPE) == VT_BYTE;
1626 /* XXX: incorrect if reg to reg */
1627 if (ft & VT_SHORT)
1628 o(0x66);
1629 o(0x89 - b);
1630 if (fr == VT_CONST) {
1631 o(0x05 + r * 8); /* mov r,xxx */
1632 gen_addr32(fc, ft);
1633 } else if (fr == VT_LOCAL) {
1634 oad(0x85 + r * 8, fc); /* mov r,xxx(%ebp) */
1635 } else if (ft & VT_LVAL) {
1636 g(fr + r * 8); /* mov r, (fr) */
1637 } else if (fr != r) {
1638 o(0xc0 + fr + r * 8); /* mov r, fr */
1642 /* start function call and return function call context */
1643 void gfunc_start(GFuncContext *c)
1645 c->args_size = 0;
1648 /* push function parameter which is in (vt, vc) */
1649 void gfunc_param(GFuncContext *c)
1651 int size, align, ft, fc, r;
1653 if ((vt & (VT_STRUCT | VT_LVAL)) == (VT_STRUCT | VT_LVAL)) {
1654 size = type_size(vt, &align);
1655 /* align to stack align size */
1656 size = (size + 3) & ~3;
1657 /* allocate the necessary size on stack */
1658 oad(0xec81, size); /* sub $xxx, %esp */
1659 /* generate structure store */
1660 r = get_reg();
1661 o(0x89); /* mov %esp, r */
1662 o(0xe0 + r);
1663 ft = vt;
1664 fc = vc;
1665 vset(VT_INT | r, 0);
1666 vpush();
1667 vt = ft;
1668 vc = fc;
1669 vstore();
1670 c->args_size += size;
1671 } else {
1672 /* simple type (currently always same size) */
1673 /* XXX: implicit cast ? */
1674 r = gv();
1675 o(0x50 + r); /* push r */
1676 c->args_size += 4;
1680 /* generate function call with address in (ft, fc) and free function */
1681 void gfunc_call(GFuncContext *c, int ft, int fc)
1683 int r;
1684 r = ft & VT_VALMASK;
1685 if (r == VT_CONST) {
1686 /* forward reference */
1687 if (ft & VT_FORWARD) {
1688 greloc((Sym *)fc, ind + 1, RELOC_REL32);
1689 oad(0xe8, 0);
1690 } else {
1691 oad(0xe8, fc - ind - 5);
1693 } else if (r == VT_LOCAL) {
1694 oad(0x95ff, fc); /* call *xxx(%ebp) */
1695 } else {
1696 /* not actually used */
1697 o(0xff); /* call *r */
1698 o(0xd0 + r);
1700 if (c->args_size)
1701 oad(0xc481, c->args_size); /* add $xxx, %esp */
1704 int gjmp(int t)
1706 return psym(0xe9, t);
1709 /* generate a test. set 'inv' to invert test */
1710 int gtst(inv, t)
1712 int v, *p;
1713 v = vt & VT_VALMASK;
1714 if (v == VT_CMP) {
1715 /* fast case : can jump directly since flags are set */
1716 g(0x0f);
1717 t = psym((vc - 16) ^ inv, t);
1718 } else if (v == VT_JMP || v == VT_JMPI) {
1719 /* && or || optimization */
1720 if ((v & 1) == inv) {
1721 /* insert vc jump list in t */
1722 p = &vc;
1723 while (*p != 0)
1724 p = (int *)*p;
1725 *p = t;
1726 t = vc;
1727 } else {
1728 t = gjmp(t);
1729 gsym(vc);
1731 } else if ((vt & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1732 /* constant jmp optimization */
1733 if ((vc != 0) != inv)
1734 t = gjmp(t);
1735 } else {
1736 v = gv();
1737 o(0x85);
1738 o(0xc0 + v * 9);
1739 g(0x0f);
1740 t = psym(0x85 ^ inv, t);
1742 return t;
1745 /* generate a binary operation 'v = r op fr' instruction and modifies
1746 (vt,vc) if needed */
1747 void gen_op1(op, r, fr)
1749 int t;
1750 if (op == '+') {
1751 o(0x01);
1752 o(0xc0 + r + fr * 8);
1753 } else if (op == '-') {
1754 o(0x29);
1755 o(0xc0 + r + fr * 8);
1756 } else if (op == '&') {
1757 o(0x21);
1758 o(0xc0 + r + fr * 8);
1759 } else if (op == '^') {
1760 o(0x31);
1761 o(0xc0 + r + fr * 8);
1762 } else if (op == '|') {
1763 o(0x09);
1764 o(0xc0 + r + fr * 8);
1765 } else if (op == '*') {
1766 o(0xaf0f); /* imul fr, r */
1767 o(0xc0 + fr + r * 8);
1768 } else if (op == TOK_SHL | op == TOK_SHR | op == TOK_SAR) {
1769 /* op2 is %ecx */
1770 if (fr != 1) {
1771 if (r == 1) {
1772 r = fr;
1773 fr = 1;
1774 o(0x87); /* xchg r, %ecx */
1775 o(0xc1 + r * 8);
1776 } else
1777 move_reg(1, fr);
1779 o(0xd3); /* shl/shr/sar %cl, r */
1780 if (op == TOK_SHL)
1781 o(0xe0 + r);
1782 else if (op == TOK_SHR)
1783 o(0xe8 + r);
1784 else
1785 o(0xf8 + r);
1786 vt = (vt & VT_TYPE) | r;
1787 } else if (op == '/' | op == TOK_UDIV | op == TOK_PDIV |
1788 op == '%' | op == TOK_UMOD) {
1789 save_reg(2); /* save edx */
1790 t = save_reg_forced(fr); /* save fr and get op2 location */
1791 move_reg(0, r); /* op1 is %eax */
1792 if (op == TOK_UDIV | op == TOK_UMOD) {
1793 o(0xf7d231); /* xor %edx, %edx, div t(%ebp), %eax */
1794 oad(0xb5, t);
1795 } else {
1796 o(0xf799); /* cltd, idiv t(%ebp), %eax */
1797 oad(0xbd, t);
1799 if (op == '%' | op == TOK_UMOD)
1800 r = 2;
1801 else
1802 r = 0;
1803 vt = (vt & VT_TYPE) | r;
1804 } else {
1805 o(0x39);
1806 o(0xc0 + r + fr * 8); /* cmp fr, r */
1807 vset(VT_CMP, op);
1811 /* end of X86 code generator */
1812 /*************************************************************/
1814 int save_reg_forced(int r)
1816 int i, l, *p, t;
1817 /* store register */
1818 loc = (loc - 4) & -3;
1819 store(r, VT_LOCAL, loc);
1820 l = loc;
1822 /* modify all stack values */
1823 for(p=vstack;p<vstack_ptr;p+=2) {
1824 i = p[0] & VT_VALMASK;
1825 if (i == r) {
1826 if (p[0] & VT_LVAL)
1827 t = VT_LLOCAL;
1828 else
1829 t = VT_LOCAL;
1830 p[0] = (p[0] & VT_TYPE) | VT_LVAL | t;
1831 p[1] = l;
1834 return l;
1837 /* save r to memory. and mark it as being free */
1838 void save_reg(r)
1840 int i, *p;
1842 /* modify all stack values */
1843 for(p=vstack;p<vstack_ptr;p+=2) {
1844 i = p[0] & VT_VALMASK;
1845 if (i == r) {
1846 save_reg_forced(r);
1847 break;
1852 /* find a free register. If none, save one register */
1853 int get_reg(void)
1855 int r, i, *p;
1857 /* find a free register */
1858 for(r=0;r<NB_REGS;r++) {
1859 for(p=vstack;p<vstack_ptr;p+=2) {
1860 i = p[0] & VT_VALMASK;
1861 if (i == r)
1862 goto notfound;
1864 return r;
1865 notfound: ;
1868 /* no register left : free the first one on the stack (very
1869 important to start from the bottom to ensure that we don't
1870 spill registers used in gen_op()) */
1871 for(p=vstack;p<vstack_ptr;p+=2) {
1872 r = p[0] & VT_VALMASK;
1873 if (r < VT_CONST) {
1874 save_reg(r);
1875 break;
1878 return r;
1881 void save_regs()
1883 int r, *p;
1884 for(p=vstack;p<vstack_ptr;p+=2) {
1885 r = p[0] & VT_VALMASK;
1886 if (r < VT_CONST) {
1887 save_reg(r);
1892 /* move register 's' to 'r', and flush previous value of r to memory
1893 if needed */
1894 void move_reg(r, s)
1896 if (r != s) {
1897 save_reg(r);
1898 load(r, s, 0);
1902 /* convert a stack entry in register. lvalues are converted as
1903 values. Cannot be used if cannot be converted to register value
1904 (such as structures). */
1905 int gvp(int *p)
1907 int r;
1908 r = p[0] & VT_VALMASK;
1909 if (r >= VT_CONST || (p[0] & VT_LVAL))
1910 r = get_reg();
1911 /* NOTE: get_reg can modify p[] */
1912 load(r, p[0], p[1]);
1913 p[0] = (p[0] & VT_TYPE) | r;
1914 return r;
1917 void vpush(void)
1919 if (vstack_ptr >= vstack + VSTACK_SIZE)
1920 error("memory full");
1921 *vstack_ptr++ = vt;
1922 *vstack_ptr++ = vc;
1923 /* cannot let cpu flags if other instruction are generated */
1924 if ((vt & VT_VALMASK) == VT_CMP)
1925 gvp(vstack_ptr - 2);
1928 void vpop(int *ft, int *fc)
1930 *fc = *--vstack_ptr;
1931 *ft = *--vstack_ptr;
1934 /* generate a value in a register from vt and vc */
1935 int gv(void)
1937 int r;
1938 vpush();
1939 r = gvp(vstack_ptr - 2);
1940 vpop(&vt, &vc);
1941 return r;
1944 /* handle constant optimizations and various machine independant opt */
1945 void gen_opc(op)
1947 int fr, ft, fc, r, c1, c2, n;
1949 vpop(&ft, &fc);
1950 vpop(&vt, &vc);
1951 c1 = (vt & (VT_VALMASK | VT_LVAL)) == VT_CONST;
1952 c2 = (ft & (VT_VALMASK | VT_LVAL)) == VT_CONST;
1953 if (c1 && c2) {
1954 switch(op) {
1955 case '+': vc += fc; break;
1956 case '-': vc -= fc; break;
1957 case '&': vc &= fc; break;
1958 case '^': vc ^= fc; break;
1959 case '|': vc |= fc; break;
1960 case '*': vc *= fc; break;
1961 case TOK_PDIV:
1962 case '/': vc /= fc; break; /* XXX: zero case ? */
1963 case '%': vc %= fc; break; /* XXX: zero case ? */
1964 case TOK_UDIV: vc = (unsigned)vc / fc; break; /* XXX: zero case ? */
1965 case TOK_UMOD: vc = (unsigned)vc % fc; break; /* XXX: zero case ? */
1966 case TOK_SHL: vc <<= fc; break;
1967 case TOK_SHR: vc = (unsigned)vc >> fc; break;
1968 case TOK_SAR: vc >>= fc; break;
1969 /* tests */
1970 case TOK_ULT: vc = (unsigned)vc < (unsigned)fc; break;
1971 case TOK_UGE: vc = (unsigned)vc >= (unsigned)fc; break;
1972 case TOK_EQ: vc = vc == fc; break;
1973 case TOK_NE: vc = vc != fc; break;
1974 case TOK_ULE: vc = (unsigned)vc <= (unsigned)fc; break;
1975 case TOK_UGT: vc = (unsigned)vc > (unsigned)fc; break;
1976 case TOK_LT: vc = vc < fc; break;
1977 case TOK_GE: vc = vc >= fc; break;
1978 case TOK_LE: vc = vc <= fc; break;
1979 case TOK_GT: vc = vc > fc; break;
1980 /* logical */
1981 case TOK_LAND: vc = vc && fc; break;
1982 case TOK_LOR: vc = vc || fc; break;
1983 default:
1984 goto general_case;
1986 } else {
1987 /* if commutative ops, put c2 as constant */
1988 if (c1 && (op == '+' || op == '&' || op == '^' ||
1989 op == '|' || op == '*')) {
1990 swap(&vt, &ft);
1991 swap(&vc, &fc);
1992 swap(&c1, &c2);
1994 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
1995 op == TOK_PDIV) &&
1996 fc == 1) ||
1997 ((op == '+' || op == '-' || op == '|' || op == '^' ||
1998 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
1999 fc == 0) ||
2000 (op == '&' &&
2001 fc == -1))) {
2002 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
2003 /* try to use shifts instead of muls or divs */
2004 if (fc > 0 && (fc & (fc - 1)) == 0) {
2005 n = -1;
2006 while (fc) {
2007 fc >>= 1;
2008 n++;
2010 fc = n;
2011 if (op == '*')
2012 op = TOK_SHL;
2013 else if (op == TOK_PDIV)
2014 op = TOK_SAR;
2015 else
2016 op = TOK_SHR;
2018 goto general_case;
2019 } else {
2020 general_case:
2021 vpush();
2022 vt = ft;
2023 vc = fc;
2024 vpush();
2025 r = gvp(vstack_ptr - 4);
2026 fr = gvp(vstack_ptr - 2);
2027 vpop(&ft, &fc);
2028 vpop(&vt, &vc);
2029 /* call low level op generator */
2030 gen_op1(op, r, fr);
2035 int pointed_size(int t)
2037 return type_size(pointed_type(t), &t);
2040 /* generic gen_op: handles types problems */
2041 void gen_op(int op)
2043 int u, t1, t2;
2045 vpush();
2046 t1 = vstack_ptr[-4];
2047 t2 = vstack_ptr[-2];
2048 if (op == '+' | op == '-') {
2049 if ((t1 & VT_PTR) && (t2 & VT_PTR)) {
2050 if (op != '-')
2051 error("invalid type");
2052 /* XXX: check that types are compatible */
2053 u = pointed_size(t1);
2054 gen_opc(op);
2055 vpush();
2056 vstack_ptr[-2] &= ~VT_TYPE; /* set to integer */
2057 vset(VT_CONST, u);
2058 gen_op(TOK_PDIV);
2059 } else if ((t1 | t2) & VT_PTR) {
2060 if (t2 & VT_PTR) {
2061 swap(vstack_ptr - 4, vstack_ptr - 2);
2062 swap(vstack_ptr - 3, vstack_ptr - 1);
2063 swap(&t1, &t2);
2065 /* stack-4 contains pointer, stack-2 value to add */
2066 vset(VT_CONST, pointed_size(vstack_ptr[-4]));
2067 gen_op('*');
2068 vpush();
2069 gen_opc(op);
2070 /* put again type if gen_opc() swaped operands */
2071 vt = (vt & VT_TYPEN) | (t1 & VT_TYPE);
2072 } else {
2073 gen_opc(op);
2075 } else {
2076 /* XXX: test types and compute returned value */
2077 if ((t1 | t2) & (VT_UNSIGNED | VT_PTR)) {
2078 if (op == TOK_SAR)
2079 op = TOK_SHR;
2080 else if (op == '/')
2081 op = TOK_UDIV;
2082 else if (op == '%')
2083 op = TOK_UMOD;
2084 else if (op == TOK_LT)
2085 op = TOK_ULT;
2086 else if (op == TOK_GT)
2087 op = TOK_UGT;
2088 else if (op == TOK_LE)
2089 op = TOK_ULE;
2090 else if (op == TOK_GE)
2091 op = TOK_UGE;
2093 gen_opc(op);
2097 /* cast (vt, vc) to 't' type */
2098 void gen_cast(int t)
2100 int r, bits;
2101 r = vt & VT_VALMASK;
2102 if (!(t & VT_LVAL)) {
2103 /* if not lvalue, then we convert now */
2104 if ((t & VT_TYPE & ~VT_UNSIGNED) == VT_BYTE)
2105 bits = 8;
2106 else if ((t & VT_TYPE & ~VT_UNSIGNED) == VT_SHORT)
2107 bits = 16;
2108 else
2109 goto the_end;
2110 vpush();
2111 if (t & VT_UNSIGNED) {
2112 vset(VT_CONST, (1 << bits) - 1);
2113 gen_op('&');
2114 } else {
2115 bits = 32 - bits;
2116 vset(VT_CONST, bits);
2117 gen_op(TOK_SHL);
2118 vpush();
2119 vset(VT_CONST, bits);
2120 gen_op(TOK_SAR);
2123 the_end:
2124 vt = (vt & VT_TYPEN) | t;
2127 /* return type size. Put alignment at 'a' */
2128 int type_size(int t, int *a)
2130 Sym *s;
2132 /* int, enum or pointer */
2133 if (t & VT_STRUCT) {
2134 /* struct/union */
2135 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
2136 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
2137 return s->c;
2138 } else if (t & VT_ARRAY) {
2139 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
2140 return type_size(s->t, a) * s->c;
2141 } else if ((t & VT_PTR) |
2142 (t & VT_TYPE) == 0 |
2143 (t & VT_ENUM)) {
2144 *a = 4;
2145 return 4;
2146 } else if (t & VT_SHORT) {
2147 *a = 2;
2148 return 2;
2149 } else {
2150 *a = 1;
2151 return 1;
2155 /* return the pointed type of t */
2156 int pointed_type(int t)
2158 Sym *s;
2159 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
2160 return s->t | (t & VT_TYPEN);
2163 int mk_pointer(int t)
2165 int p;
2166 p = anon_sym++;
2167 sym_push(p, t, -1);
2168 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & VT_TYPEN);
2171 /* store value in lvalue pushed on stack */
2172 void vstore(void)
2174 int ft, fc, r, t, size, align;
2175 GFuncContext gf;
2177 if (vt & VT_STRUCT) {
2178 /* if structure, only generate pointer */
2179 /* structure assignment : generate memcpy */
2180 /* XXX: optimize if small size */
2182 gfunc_start(&gf);
2183 /* type size */
2184 ft = vt;
2185 fc = vc;
2186 size = type_size(vt, &align);
2187 vset(VT_CONST, size);
2188 gfunc_param(&gf);
2189 /* source */
2190 vt = ft & ~VT_LVAL;
2191 vc = fc;
2192 gfunc_param(&gf);
2193 /* destination */
2194 vpop(&vt, &vc);
2195 vt &= ~VT_LVAL;
2196 gfunc_param(&gf);
2198 save_regs();
2199 gfunc_call(&gf, VT_CONST, (int)&memcpy);
2201 /* generate again current type */
2202 vt = ft;
2203 vc = fc;
2204 } else {
2205 r = gv(); /* generate value */
2206 vpush();
2207 ft = vstack_ptr[-4];
2208 fc = vstack_ptr[-3];
2209 /* if lvalue was saved on stack, must read it */
2210 if ((ft & VT_VALMASK) == VT_LLOCAL) {
2211 t = get_reg();
2212 load(t, VT_LOCAL | VT_LVAL, fc);
2213 ft = (ft & ~VT_VALMASK) | t;
2215 store(r, ft, fc);
2216 vstack_ptr -= 4;
2220 /* post defines POST/PRE add. c is the token ++ or -- */
2221 void inc(post, c)
2223 int r, r1;
2224 test_lvalue();
2225 if (post)
2226 vpush(); /* room for returned value */
2227 vpush(); /* save lvalue */
2228 r = gv();
2229 vpush(); /* save value */
2230 if (post) {
2231 /* duplicate value */
2232 r1 = get_reg();
2233 load(r1, r, 0); /* move r to r1 */
2234 vstack_ptr[-6] = (vt & VT_TYPE) | r1;
2235 vstack_ptr[-5] = 0;
2237 /* add constant */
2238 vset(VT_CONST, c - TOK_MID);
2239 gen_op('+');
2240 vstore(); /* store value */
2241 if (post)
2242 vpop(&vt, &vc);
2245 /* enum/struct/union declaration */
2246 int struct_decl(int u)
2248 int a, t, b, v, size, align, maxalign, c;
2249 Sym *s, *ss, **ps;
2251 a = tok; /* save decl type */
2252 next();
2253 if (tok != '{') {
2254 v = tok;
2255 next();
2256 /* struct already defined ? return it */
2257 /* XXX: check consistency */
2258 if (s = sym_find(v | SYM_STRUCT)) {
2259 if (s->t != a)
2260 error("invalid type");
2261 goto do_decl;
2263 } else {
2264 v = anon_sym++;
2266 s = sym_push(v | SYM_STRUCT, a, 0);
2267 /* put struct/union/enum name in type */
2268 do_decl:
2269 u = u | (v << VT_STRUCT_SHIFT);
2271 if (tok == '{') {
2272 next();
2273 if (s->c)
2274 error("struct/union/enum already defined");
2275 /* cannot be empty */
2276 c = 0;
2277 maxalign = 0;
2278 ps = &s->next;
2279 while (1) {
2280 if (a == TOK_ENUM) {
2281 v = tok;
2282 next();
2283 if (tok == '=') {
2284 next();
2285 c = expr_const();
2287 sym_push(v, VT_CONST, c);
2288 if (tok == ',')
2289 next();
2290 c++;
2291 } else {
2292 b = ist();
2293 while (1) {
2294 t = type_decl(&v, b, TYPE_DIRECT);
2295 if (t & (VT_FUNC | VT_TYPEDEF))
2296 error("invalid type");
2297 /* XXX: align & correct type size */
2298 v |= SYM_FIELD;
2299 size = type_size(t, &align);
2300 if (a == TOK_STRUCT) {
2301 c = (c + align - 1) & -align;
2302 ss = sym_push(v, t, c);
2303 c += size;
2304 } else {
2305 ss = sym_push(v, t, 0);
2306 if (size > c)
2307 c = size;
2309 if (align > maxalign)
2310 maxalign = align;
2311 *ps = ss;
2312 ps = &ss->next;
2313 if (tok == ';' || tok == -1)
2314 break;
2315 skip(',');
2317 skip(';');
2319 if (tok == '}')
2320 break;
2322 skip('}');
2323 /* size for struct/union, dummy for enum */
2324 s->c = (c + maxalign - 1) & -maxalign;
2326 return u;
2329 /* return 0 if no type declaration. otherwise, return the basic type
2330 and skip it.
2331 XXX: A '2' is ored to ensure non zero return if int type.
2333 int ist(void)
2335 int t;
2336 Sym *s;
2338 t = 0;
2339 while(1) {
2340 if (tok == TOK_ENUM) {
2341 t |= struct_decl(VT_ENUM);
2342 } else if (tok == TOK_STRUCT || tok == TOK_UNION) {
2343 t |= struct_decl(VT_STRUCT);
2344 } else {
2345 if (tok == TOK_CHAR) {
2346 t |= VT_BYTE;
2347 } else if (tok == TOK_VOID) {
2348 t |= VT_VOID;
2349 } else if (tok == TOK_SHORT) {
2350 t |= VT_SHORT;
2351 } else if (tok == TOK_INT |
2352 (tok >= TOK_CONST & tok <= TOK_INLINE)) {
2353 /* ignored types */
2354 } else if (tok == TOK_FLOAT || tok == TOK_DOUBLE) {
2355 /* We allow that to compile standard headers */
2356 // warning("floats not supported");
2357 } else if (tok == TOK_EXTERN) {
2358 t |= VT_EXTERN;
2359 } else if (tok == TOK_STATIC) {
2360 t |= VT_STATIC;
2361 } else if (tok == TOK_UNSIGNED) {
2362 t |= VT_UNSIGNED;
2363 } else if (tok == TOK_TYPEDEF) {
2364 t |= VT_TYPEDEF;
2365 } else {
2366 s = sym_find(tok);
2367 if (!s || !(s->t & VT_TYPEDEF))
2368 break;
2369 t |= (s->t & ~VT_TYPEDEF);
2371 next();
2373 t |= 2;
2375 return t;
2378 int post_type(t)
2380 int p, n, pt, l;
2381 Sym **plast, *s, *first;
2383 if (tok == '(') {
2384 /* function declaration */
2385 next();
2386 l = 0;
2387 first = NULL;
2388 plast = &first;
2389 while (tok != ')') {
2390 /* read param name and compute offset */
2391 if (l != FUNC_OLD) {
2392 if (!(pt = ist())) {
2393 if (l) {
2394 error("invalid type");
2395 } else {
2396 l = FUNC_OLD;
2397 goto old_proto;
2400 if (pt & VT_VOID && tok == ')')
2401 break;
2402 l = FUNC_NEW;
2403 pt = type_decl(&n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
2404 } else {
2405 old_proto:
2406 n = tok;
2407 pt = VT_INT;
2408 next();
2410 /* array must be transformed to pointer according to ANSI C */
2411 pt &= ~VT_ARRAY;
2412 s = sym_push(n | SYM_FIELD, pt, 0);
2413 *plast = s;
2414 plast = &s->next;
2415 if (tok == ',') {
2416 next();
2417 if (l == FUNC_NEW && tok == TOK_DOTS) {
2418 l = FUNC_ELLIPSIS;
2419 next();
2420 break;
2424 skip(')');
2425 t = post_type(t);
2426 /* we push a anonymous symbol which will contain the function prototype */
2427 p = anon_sym++;
2428 s = sym_push(p, t, l);
2429 s->next = first;
2430 t = VT_FUNC | (p << VT_STRUCT_SHIFT);
2431 } else if (tok == '[') {
2432 /* array definition */
2433 next();
2434 n = -1;
2435 if (tok != ']') {
2436 n = expr_const();
2437 if (n < 0)
2438 error("invalid array size");
2440 skip(']');
2441 /* parse next post type */
2442 t = post_type(t);
2444 /* we push a anonymous symbol which will contain the array
2445 element type */
2446 p = anon_sym++;
2447 sym_push(p, t, n);
2448 t = VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
2450 return t;
2453 /* Read a type declaration (except basic type), and return the
2454 type. If v is true, then also put variable name in 'vc' */
2455 int type_decl(int *v, int t, int td)
2457 int u, p;
2458 Sym *s;
2460 t = t & -3; /* suppress the ored '2' */
2461 while (tok == '*') {
2462 next();
2463 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
2464 next();
2465 t = mk_pointer(t);
2468 /* recursive type */
2469 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
2470 if (tok == '(') {
2471 next();
2472 u = type_decl(v, 0, td);
2473 skip(')');
2474 } else {
2475 u = 0;
2476 /* type identifier */
2477 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
2478 *v = tok;
2479 next();
2480 } else {
2481 if (!(td & TYPE_ABSTRACT))
2482 expect("identifier");
2483 *v = 0;
2486 /* append t at the end of u */
2487 t = post_type(t);
2488 if (!u)
2489 return t;
2490 p = u;
2491 while(1) {
2492 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
2493 p = s->t;
2494 if (!p) {
2495 s->t = t;
2496 break;
2499 return u;
2502 /* define a new external reference to a function 'v' of type 'u' */
2503 Sym *external_sym(int v, int u)
2505 Sym *s;
2506 s = sym_find(v);
2507 if (!s) {
2508 /* push forward reference */
2509 s = sym_push1(&global_stack,
2510 v, u | VT_CONST | VT_FORWARD, 0);
2512 return s;
2515 void indir(void)
2517 if (vt & VT_LVAL)
2518 gv();
2519 if (!(vt & VT_PTR))
2520 expect("pointer");
2521 vt = pointed_type(vt);
2522 if (!(vt & VT_ARRAY)) /* an array is never an lvalue */
2523 vt |= VT_LVAL;
2526 void unary(void)
2528 int n, t, ft, fc, p, align, size;
2529 Sym *s;
2530 GFuncContext gf;
2532 if (tok == TOK_NUM || tok == TOK_CCHAR || tok == TOK_LCHAR) {
2533 vset(VT_CONST, tokc);
2534 next();
2535 } else if (tok == TOK___FUNC__) {
2536 /* special function name identifier */
2537 /* generate (char *) type */
2538 vset(VT_CONST | mk_pointer(VT_BYTE), glo);
2539 strcpy((void *)glo, funcname);
2540 glo += strlen(funcname) + 1;
2541 } else if (tok == TOK_LSTR) {
2542 t = VT_INT;
2543 goto str_init;
2544 } else if (tok == TOK_STR) {
2545 /* string parsing */
2546 t = VT_BYTE;
2547 str_init:
2548 type_size(t, &align);
2549 glo = (glo + align - 1) & -align;
2550 fc = glo;
2551 /* we must declare it as an array first to use initializer parser */
2552 t = VT_CONST | VT_ARRAY | mk_pointer(t);
2553 decl_initializer(t, glo, 1, 0);
2554 glo += type_size(t, &align);
2555 /* put it as pointer */
2556 vset(t & ~VT_ARRAY, fc);
2557 } else {
2558 t = tok;
2559 next();
2560 if (t == '(') {
2561 /* cast ? */
2562 if (t = ist()) {
2563 ft = type_decl(&n, t, TYPE_ABSTRACT);
2564 skip(')');
2565 /* check ISOC99 compound literal */
2566 if (tok == '{') {
2567 /* data is allocated locally by default */
2568 if (global_expr)
2569 ft |= VT_CONST;
2570 else
2571 ft |= VT_LOCAL;
2572 /* all except arrays are lvalues */
2573 if (!(ft & VT_ARRAY))
2574 ft |= VT_LVAL;
2575 fc = decl_initializer_alloc(ft, 1);
2576 vset(ft, fc);
2577 } else {
2578 unary();
2579 gen_cast(ft);
2581 } else {
2582 expr();
2583 skip(')');
2585 } else if (t == '*') {
2586 unary();
2587 indir();
2588 } else if (t == '&') {
2589 unary();
2590 /* functions names must be treated as function pointers,
2591 except for unary '&' and sizeof. Since we consider that
2592 functions are not lvalues, we only have to handle it
2593 there and in function calls. */
2594 if (!(vt & VT_FUNC))
2595 test_lvalue();
2596 vt = mk_pointer(vt & VT_LVALN);
2597 } else
2598 if (t == '!') {
2599 unary();
2600 if ((vt & (VT_CONST | VT_LVAL)) == VT_CONST)
2601 vc = !vc;
2602 else if ((vt & VT_VALMASK) == VT_CMP)
2603 vc = vc ^ 1;
2604 else
2605 vset(VT_JMP, gtst(1, 0));
2606 } else
2607 if (t == '~') {
2608 unary();
2609 vpush();
2610 vset(VT_CONST, -1);
2611 gen_op('^');
2612 } else
2613 if (t == '+') {
2614 unary();
2615 } else
2616 if (t == TOK_SIZEOF) {
2617 /* XXX: some code can be generated */
2618 if (tok == '(') {
2619 next();
2620 if (t = ist())
2621 vt = type_decl(&n, t, TYPE_ABSTRACT);
2622 else
2623 expr();
2624 skip(')');
2625 } else {
2626 unary();
2628 vset(VT_CONST, type_size(vt, &t));
2629 } else
2630 if (t == TOK_INC | t == TOK_DEC) {
2631 unary();
2632 inc(0, t);
2633 } else if (t == '-') {
2634 vset(VT_CONST, 0);
2635 vpush();
2636 unary();
2637 gen_op('-');
2638 } else
2640 s = sym_find(t);
2641 if (!s) {
2642 if (tok != '(')
2643 error("'%s' undeclared", get_tok_str(t, 0));
2644 /* for simple function calls, we tolerate undeclared
2645 external reference */
2646 p = anon_sym++;
2647 sym_push1(&global_stack, p, 0, FUNC_OLD);
2648 /* int() function */
2649 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT));
2651 vset(s->t, s->c);
2652 /* if forward reference, we must point to s */
2653 if (vt & VT_FORWARD)
2654 vc = (int)s;
2658 /* post operations */
2659 while (1) {
2660 if (tok == TOK_INC | tok == TOK_DEC) {
2661 inc(1, tok);
2662 next();
2663 } else if (tok == '.' | tok == TOK_ARROW) {
2664 /* field */
2665 if (tok == TOK_ARROW)
2666 indir();
2667 test_lvalue();
2668 vt &= VT_LVALN;
2669 next();
2670 /* expect pointer on structure */
2671 if (!(vt & VT_STRUCT))
2672 expect("struct or union");
2673 s = sym_find(((unsigned)vt >> VT_STRUCT_SHIFT) | SYM_STRUCT);
2674 /* find field */
2675 tok |= SYM_FIELD;
2676 while (s = s->next) {
2677 if (s->v == tok)
2678 break;
2680 if (!s)
2681 error("field not found");
2682 /* add field offset to pointer */
2683 vt = vt & VT_TYPEN; /* change type to int */
2684 vpush();
2685 vset(VT_CONST, s->c);
2686 gen_op('+');
2687 /* change type to field type, and set to lvalue */
2688 vt = (vt & VT_TYPEN) | s->t;
2689 /* an array is never an lvalue */
2690 if (!(vt & VT_ARRAY))
2691 vt |= VT_LVAL;
2692 next();
2693 } else if (tok == '[') {
2694 next();
2695 vpush();
2696 expr();
2697 gen_op('+');
2698 indir();
2699 skip(']');
2700 } else if (tok == '(') {
2701 int rett, retc;
2703 /* function call */
2704 if (!(vt & VT_FUNC)) {
2705 if ((vt & (VT_PTR | VT_ARRAY)) == VT_PTR) {
2706 vt = pointed_type(vt);
2707 if (!(vt & VT_FUNC))
2708 goto error_func;
2709 } else {
2710 error_func:
2711 expect("function type");
2714 /* get return type */
2715 s = sym_find((unsigned)vt >> VT_STRUCT_SHIFT);
2717 vt &= ~VT_LVAL; /* no lvalue */
2718 vpush(); /* push function address */
2719 save_regs(); /* save used temporary registers */
2720 gfunc_start(&gf);
2721 next();
2722 #ifdef INVERT_FUNC_PARAMS
2724 int *str, len, parlevel, *saved_macro_ptr;
2725 Sym *args, *s1;
2727 /* read each argument and store it on a stack */
2728 /* XXX: merge it with macro args ? */
2729 args = NULL;
2730 while (tok != ')') {
2731 len = 0;
2732 str = NULL;
2733 parlevel = 0;
2734 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
2735 tok != -1) {
2736 if (tok == '(')
2737 parlevel++;
2738 else if (tok == ')')
2739 parlevel--;
2740 tok_add2(&str, &len, tok, tokc);
2741 next();
2743 tok_add(&str, &len, -1); /* end of file added */
2744 tok_add(&str, &len, 0);
2745 sym_push2(&args, 0, 0, (int)str);
2746 if (tok != ',')
2747 break;
2748 next();
2750 if (tok != ')')
2751 expect(")");
2753 /* now generate code in reverse order by reading the stack */
2754 saved_macro_ptr = macro_ptr;
2755 while (args) {
2756 macro_ptr = (int *)args->c;
2757 next();
2758 expr_eq();
2759 gfunc_param(&gf);
2760 s1 = args->prev;
2761 free((int *)args->c);
2762 free(args);
2763 args = s1;
2765 macro_ptr = saved_macro_ptr;
2766 /* restore token */
2767 tok = ')';
2769 #endif
2770 /* compute first implicit argument if a structure is returned */
2771 if (s->t & VT_STRUCT) {
2772 /* get some space for the returned structure */
2773 size = type_size(s->t, &align);
2774 loc = (loc - size) & -align;
2775 rett = s->t | VT_LOCAL | VT_LVAL;
2776 /* pass it as 'int' to avoid structure arg passing
2777 problems */
2778 vset(VT_INT | VT_LOCAL, loc);
2779 retc = vc;
2780 gfunc_param(&gf);
2781 } else {
2782 rett = s->t | FUNC_RET_REG; /* return in register */
2783 retc = 0;
2785 #ifndef INVERT_FUNC_PARAMS
2786 while (tok != ')') {
2787 expr_eq();
2788 gfunc_param(&gf);
2789 if (tok == ',')
2790 next();
2792 #endif
2793 skip(')');
2794 vpop(&ft, &fc);
2795 gfunc_call(&gf, ft, fc);
2796 /* return value */
2797 vt = rett;
2798 vc = retc;
2799 } else {
2800 break;
2805 /* check if types are compatible for assignation */
2806 int same_types(int t1, int t2)
2808 t1 &= VT_TYPE;
2809 t2 &= VT_TYPE;
2810 if (t1 & VT_PTR) {
2811 /* XXX: zero test ? */
2812 if (!(t2 & VT_PTR))
2813 return 0;
2814 t1 = pointed_type(t1);
2815 t2 = pointed_type(t2);
2816 /* void matches everything */
2817 if (t1 == VT_VOID || t2 == VT_VOID)
2818 return 1;
2819 return same_types(t1, t2);
2820 } else if (t1 & VT_STRUCT) {
2821 return (t2 == t1);
2822 } else {
2823 /* XXX: not complete */
2824 return 1;
2829 void uneq()
2831 int t;
2833 unary();
2834 if (tok == '=' |
2835 (tok >= TOK_A_MOD & tok <= TOK_A_DIV) |
2836 tok == TOK_A_XOR | tok == TOK_A_OR |
2837 tok == TOK_A_SHL | tok == TOK_A_SAR) {
2838 test_lvalue();
2839 vpush();
2840 t = tok;
2841 next();
2842 if (t == '=') {
2843 expr_eq();
2844 if (!same_types(vt, vstack_ptr[-2]))
2845 error("incompatible types");
2846 } else {
2847 vpush();
2848 expr_eq();
2849 gen_op(t & 0x7f);
2851 vstore();
2855 void sum(l)
2857 int t;
2859 if (l == 0)
2860 uneq();
2861 else {
2862 sum(--l);
2863 while ((l == 0 & (tok == '*' | tok == '/' | tok == '%')) |
2864 (l == 1 & (tok == '+' | tok == '-')) |
2865 (l == 2 & (tok == TOK_SHL | tok == TOK_SAR)) |
2866 (l == 3 & ((tok >= TOK_ULE & tok <= TOK_GT) |
2867 tok == TOK_ULT | tok == TOK_UGE)) |
2868 (l == 4 & (tok == TOK_EQ | tok == TOK_NE)) |
2869 (l == 5 & tok == '&') |
2870 (l == 6 & tok == '^') |
2871 (l == 7 & tok == '|') |
2872 (l == 8 & tok == TOK_LAND) |
2873 (l == 9 & tok == TOK_LOR)) {
2874 vpush();
2875 t = tok;
2876 next();
2877 sum(l);
2878 gen_op(t);
2883 /* only used if non constant */
2884 void eand()
2886 int t;
2888 sum(8);
2889 t = 0;
2890 while (1) {
2891 if (tok != TOK_LAND) {
2892 if (t) {
2893 t = gtst(1, t);
2894 vset(VT_JMPI, t);
2896 break;
2898 t = gtst(1, t);
2899 next();
2900 sum(8);
2904 void eor()
2906 int t;
2908 eand();
2909 t = 0;
2910 while (1) {
2911 if (tok != TOK_LOR) {
2912 if (t) {
2913 t = gtst(0, t);
2914 vset(VT_JMP, t);
2916 break;
2918 t = gtst(0, t);
2919 next();
2920 eand();
2924 /* XXX: better constant handling */
2925 void expr_eq()
2927 int t, u, c, r1, r2;
2929 if (const_wanted) {
2930 sum(10);
2931 if (tok == '?') {
2932 c = vc;
2933 next();
2934 expr();
2935 t = vc;
2936 skip(':');
2937 expr_eq();
2938 if (c)
2939 vc = t;
2941 } else {
2942 eor();
2943 if (tok == '?') {
2944 next();
2945 t = gtst(1, 0);
2946 expr();
2947 r1 = gv();
2948 skip(':');
2949 u = gjmp(0);
2950 gsym(t);
2951 expr_eq();
2952 r2 = gv();
2953 move_reg(r1, r2);
2954 vt = (vt & VT_TYPE) | r1;
2955 gsym(u);
2960 void expr()
2962 while (1) {
2963 expr_eq();
2964 if (tok != ',')
2965 break;
2966 next();
2970 int expr_const()
2972 int a;
2973 a = const_wanted;
2974 const_wanted = 1;
2975 expr_eq();
2976 if ((vt & (VT_CONST | VT_LVAL)) != VT_CONST)
2977 expect("constant");
2978 const_wanted = a;
2979 return vc;
2982 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
2984 int a, b, c, d;
2985 Sym *s;
2987 if (tok == TOK_IF) {
2988 /* if test */
2989 next();
2990 skip('(');
2991 expr();
2992 skip(')');
2993 a = gtst(1, 0);
2994 block(bsym, csym, case_sym, def_sym, case_reg);
2995 c = tok;
2996 if (c == TOK_ELSE) {
2997 next();
2998 d = gjmp(0);
2999 gsym(a);
3000 block(bsym, csym, case_sym, def_sym, case_reg);
3001 gsym(d); /* patch else jmp */
3002 } else
3003 gsym(a);
3004 } else if (tok == TOK_WHILE) {
3005 next();
3006 d = ind;
3007 skip('(');
3008 expr();
3009 skip(')');
3010 a = gtst(1, 0);
3011 b = 0;
3012 block(&a, &b, case_sym, def_sym, case_reg);
3013 oad(0xe9, d - ind - 5); /* jmp */
3014 gsym(a);
3015 gsym_addr(b, d);
3016 } else if (tok == '{') {
3017 next();
3018 /* declarations */
3019 s = local_stack.top;
3020 while (tok != '}') {
3021 decl(VT_LOCAL);
3022 if (tok != '}')
3023 block(bsym, csym, case_sym, def_sym, case_reg);
3025 /* pop locally defined symbols */
3026 sym_pop(&local_stack, s);
3027 next();
3028 } else if (tok == TOK_RETURN) {
3029 next();
3030 if (tok != ';') {
3031 if (func_vt & VT_STRUCT) {
3032 /* if returning structure, must copy it to implicit
3033 first pointer arg location */
3034 vset(mk_pointer(func_vt) | VT_LOCAL | VT_LVAL, func_vc);
3035 indir();
3036 vpush();
3038 expr();
3039 if (func_vt & VT_STRUCT) {
3040 /* copy structure value to pointer */
3041 vstore();
3042 } else {
3043 /* move return value to standard return register */
3044 move_reg(FUNC_RET_REG, gv());
3047 skip(';');
3048 rsym = gjmp(rsym); /* jmp */
3049 } else if (tok == TOK_BREAK) {
3050 /* compute jump */
3051 if (!bsym)
3052 error("cannot break");
3053 *bsym = gjmp(*bsym);
3054 next();
3055 skip(';');
3056 } else if (tok == TOK_CONTINUE) {
3057 /* compute jump */
3058 if (!csym)
3059 error("cannot continue");
3060 *csym = gjmp(*csym);
3061 next();
3062 skip(';');
3063 } else if (tok == TOK_FOR) {
3064 int e;
3065 next();
3066 skip('(');
3067 if (tok != ';')
3068 expr();
3069 skip(';');
3070 d = ind;
3071 c = ind;
3072 a = 0;
3073 b = 0;
3074 if (tok != ';') {
3075 expr();
3076 a = gtst(1, 0);
3078 skip(';');
3079 if (tok != ')') {
3080 e = gjmp(0);
3081 c = ind;
3082 expr();
3083 oad(0xe9, d - ind - 5); /* jmp */
3084 gsym(e);
3086 skip(')');
3087 block(&a, &b, case_sym, def_sym, case_reg);
3088 oad(0xe9, c - ind - 5); /* jmp */
3089 gsym(a);
3090 gsym_addr(b, c);
3091 } else
3092 if (tok == TOK_DO) {
3093 next();
3094 a = 0;
3095 b = 0;
3096 d = ind;
3097 block(&a, &b, case_sym, def_sym, case_reg);
3098 skip(TOK_WHILE);
3099 skip('(');
3100 gsym(b);
3101 expr();
3102 c = gtst(0, 0);
3103 gsym_addr(c, d);
3104 skip(')');
3105 gsym(a);
3106 skip(';');
3107 } else
3108 if (tok == TOK_SWITCH) {
3109 next();
3110 skip('(');
3111 expr();
3112 case_reg = gv();
3113 skip(')');
3114 a = 0;
3115 b = 0;
3116 c = 0;
3117 block(&a, csym, &b, &c, case_reg);
3118 /* if no default, jmp after switch */
3119 if (c == 0)
3120 c = ind;
3121 /* default label */
3122 gsym_addr(b, c);
3123 /* break label */
3124 gsym(a);
3125 } else
3126 if (tok == TOK_CASE) {
3127 next();
3128 a = expr_const();
3129 if (!case_sym)
3130 expect("switch");
3131 gsym(*case_sym);
3132 vset(case_reg, 0);
3133 vpush();
3134 vset(VT_CONST, a);
3135 gen_op(TOK_EQ);
3136 *case_sym = gtst(1, 0);
3137 skip(':');
3138 block(bsym, csym, case_sym, def_sym, case_reg);
3139 } else
3140 if (tok == TOK_DEFAULT) {
3141 next();
3142 skip(':');
3143 if (!def_sym)
3144 expect("switch");
3145 if (*def_sym)
3146 error("too many 'default'");
3147 *def_sym = ind;
3148 block(bsym, csym, case_sym, def_sym, case_reg);
3149 } else
3150 if (tok == TOK_GOTO) {
3151 next();
3152 s = sym_find1(&label_stack, tok);
3153 /* put forward definition if needed */
3154 if (!s)
3155 s = sym_push1(&label_stack, tok, VT_FORWARD, 0);
3156 /* label already defined */
3157 if (s->t & VT_FORWARD)
3158 s->c = gjmp(s->c); /* jmp xxx */
3159 else
3160 oad(0xe9, s->c - ind - 5); /* jmp xxx */
3161 next();
3162 skip(';');
3163 } else {
3164 b = tok;
3165 next();
3166 if (tok == ':') {
3167 next();
3168 /* label case */
3169 s = sym_find1(&label_stack, b);
3170 if (s) {
3171 if (!(s->t & VT_FORWARD))
3172 error("multiple defined label");
3173 gsym(s->c);
3174 s->c = ind;
3175 s->t = 0;
3176 } else {
3177 sym_push1(&label_stack, b, 0, ind);
3179 block(bsym, csym, case_sym, def_sym, case_reg);
3180 } else {
3181 /* expression case: go backward of one token */
3182 /* XXX: currently incorrect if number/string/char */
3183 tok1 = tok;
3184 tok = b;
3185 if (tok != ';') {
3186 expr();
3188 skip(';');
3193 /* t is the array or struct type. c is the array or struct
3194 address. cur_index/cur_field is the pointer to the current
3195 value. 'size_only' is true if only size info is needed (only used
3196 in arrays) */
3197 void decl_designator(int t, int c,
3198 int *cur_index, Sym **cur_field,
3199 int size_only)
3201 Sym *s, *f;
3202 int notfirst, index, align;
3204 notfirst = 0;
3205 while (tok == '[' || tok == '.') {
3206 if (tok == '[') {
3207 if (!(t & VT_ARRAY))
3208 expect("array type");
3209 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3210 next();
3211 index = expr_const();
3212 if (index < 0 || (s->c >= 0 && index >= s->c))
3213 expect("invalid index");
3214 skip(']');
3215 if (!notfirst)
3216 *cur_index = index;
3217 t = pointed_type(t);
3218 c += index * type_size(t, &align);
3219 } else {
3220 if (!(t & VT_STRUCT))
3221 expect("struct/union type");
3222 next();
3223 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3224 tok |= SYM_FIELD;
3225 f = s->next;
3226 while (f) {
3227 if (f->v == tok)
3228 break;
3229 f = f->next;
3231 if (!f)
3232 expect("field");
3233 next();
3234 if (!notfirst)
3235 *cur_field = f;
3236 t = f->t | (t & VT_TYPEN);
3237 c += f->c;
3239 notfirst = 1;
3241 if (notfirst) {
3242 skip('=');
3243 } else {
3244 if (t & VT_ARRAY) {
3245 index = *cur_index;
3246 t = pointed_type(t);
3247 c += index * type_size(t, &align);
3248 } else {
3249 f = *cur_field;
3250 if (!f)
3251 error("too many field init");
3252 t = f->t | (t & VT_TYPEN);
3253 c += f->c;
3256 decl_initializer(t, c, 0, size_only);
3259 /* store a value or an expression directly in global data or in local array */
3261 void init_putv(int t, int c, int v, int is_expr)
3263 int saved_global_expr;
3265 if ((t & VT_VALMASK) == VT_CONST) {
3266 if (is_expr) {
3267 /* compound literals must be allocated globally in this case */
3268 saved_global_expr = global_expr;
3269 global_expr = 1;
3270 v = expr_const();
3271 global_expr = saved_global_expr;
3273 if (t & VT_BYTE)
3274 *(char *)c = v;
3275 else if (t & VT_SHORT)
3276 *(short *)c = v;
3277 else
3278 *(int *)c = v;
3279 } else {
3280 vt = t;
3281 vc = c;
3282 vpush();
3283 if (is_expr)
3284 expr_eq();
3285 else
3286 vset(VT_CONST, v);
3287 vstore();
3291 /* put zeros for variable based init */
3292 void init_putz(int t, int c, int size)
3294 GFuncContext gf;
3296 if ((t & VT_VALMASK) == VT_CONST) {
3297 /* nothing to do because global are already set to zero */
3298 } else {
3299 gfunc_start(&gf);
3300 vset(VT_CONST, size);
3301 gfunc_param(&gf);
3302 vset(VT_CONST, 0);
3303 gfunc_param(&gf);
3304 vset(VT_LOCAL, c);
3305 gfunc_param(&gf);
3306 gfunc_call(&gf, VT_CONST, (int)&memset);
3310 /* 't' contains the type and storage info. c is the address of the
3311 object. 'first' is true if array '{' must be read (multi dimension
3312 implicit array init handling). 'size_only' is true if size only
3313 evaluation is wanted (only for arrays). */
3314 void decl_initializer(int t, int c, int first, int size_only)
3316 int index, array_length, n, no_oblock, nb, parlevel, i;
3317 int t1, size1, align1;
3318 Sym *s, *f;
3319 TokenSym *ts;
3321 if (t & VT_ARRAY) {
3322 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3323 n = s->c;
3324 array_length = 0;
3325 t1 = pointed_type(t);
3326 size1 = type_size(t1, &align1);
3328 no_oblock = 1;
3329 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
3330 tok == '{') {
3331 skip('{');
3332 no_oblock = 0;
3335 /* only parse strings here if correct type (otherwise: handle
3336 them as ((w)char *) expressions */
3337 if ((tok == TOK_LSTR &&
3338 (t1 & VT_TYPE & ~VT_UNSIGNED) == VT_INT) ||
3339 (tok == TOK_STR &&
3340 (t1 & VT_TYPE & ~VT_UNSIGNED) == VT_BYTE)) {
3341 /* XXX: move multiple string parsing in parser ? */
3342 while (tok == TOK_STR || tok == TOK_LSTR) {
3343 ts = (TokenSym *)tokc;
3344 /* compute maximum number of chars wanted */
3345 nb = ts->len;
3346 if (n >= 0 && nb > (n - array_length))
3347 nb = n - array_length;
3348 if (!size_only) {
3349 if (ts->len > nb)
3350 warning("initializer-string for array is too long");
3351 for(i=0;i<nb;i++) {
3352 init_putv(t1, c + (array_length + i) * size1,
3353 ts->str[i], 0);
3356 array_length += nb;
3357 next();
3359 /* only add trailing zero if enough storage (no
3360 warning in this case since it is standard) */
3361 if (n < 0 || array_length < n) {
3362 if (!size_only) {
3363 init_putv(t1, c + (array_length * size1), 0, 0);
3365 array_length++;
3367 } else {
3368 index = 0;
3369 while (tok != '}') {
3370 decl_designator(t, c, &index, NULL, size_only);
3371 if (n >= 0 && index >= n)
3372 error("index too large");
3373 /* must put zero in holes (note that doing it that way
3374 ensures that it even works with designators) */
3375 if (!size_only && array_length < index) {
3376 init_putz(t1, c + array_length * size1,
3377 (index - array_length) * size1);
3379 index++;
3380 if (index > array_length)
3381 array_length = index;
3382 /* special test for multi dimensional arrays (may not
3383 be strictly correct if designators are used at the
3384 same time) */
3385 if (index >= n && no_oblock)
3386 break;
3387 if (tok == '}')
3388 break;
3389 skip(',');
3392 if (!no_oblock)
3393 skip('}');
3394 /* put zeros at the end */
3395 if (!size_only && n >= 0 && array_length < n) {
3396 init_putz(t1, c + array_length * size1,
3397 (n - array_length) * size1);
3399 /* patch type size if needed */
3400 if (n < 0)
3401 s->c = array_length;
3402 } else if ((t & VT_STRUCT) && tok == '{') {
3403 /* XXX: union needs only one init */
3404 next();
3405 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3406 f = s->next;
3407 array_length = 0;
3408 index = 0;
3409 n = s->c;
3410 while (tok != '}') {
3411 decl_designator(t, c, NULL, &f, size_only);
3412 /* fill with zero between fields */
3413 index = f->c;
3414 if (!size_only && array_length < index) {
3415 init_putz(t, c + array_length,
3416 index - array_length);
3418 index = index + type_size(f->t, &align1);
3419 if (index > array_length)
3420 array_length = index;
3421 if (tok == '}')
3422 break;
3423 skip(',');
3424 f = f->next;
3426 /* put zeros at the end */
3427 if (!size_only && array_length < n) {
3428 init_putz(t, c + array_length,
3429 n - array_length);
3431 skip('}');
3432 } else if (tok == '{') {
3433 next();
3434 decl_initializer(t, c, first, size_only);
3435 skip('}');
3436 } else if (size_only) {
3437 /* just skip expression */
3438 parlevel = 0;
3439 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
3440 tok != -1) {
3441 if (tok == '(')
3442 parlevel++;
3443 else if (tok == ')')
3444 parlevel--;
3445 next();
3447 } else {
3448 init_putv(t, c, 0, 1);
3452 /* parse an initializer for type 't' if 'has_init' is true, and
3453 allocate space in local or global data space. The allocated address
3454 in returned */
3455 int decl_initializer_alloc(int t, int has_init)
3457 int size, align, addr, tok1;
3458 int *init_str, init_len, level, *saved_macro_ptr;
3460 size = type_size(t, &align);
3461 /* If unknown size, we must evaluate it before
3462 evaluating initializers because
3463 initializers can generate global data too
3464 (e.g. string pointers or ISOC99 compound
3465 literals). It also simplifies local
3466 initializers handling */
3467 init_len = 0;
3468 init_str = NULL;
3469 saved_macro_ptr = NULL; /* avoid warning */
3470 tok1 = 0;
3471 if (size < 0) {
3472 if (!has_init)
3473 error("unknown type size");
3474 /* get all init string */
3475 level = 0;
3476 while (level > 0 || (tok != ',' && tok != ';')) {
3477 if (tok < 0)
3478 error("unexpect end of file in initializer");
3479 tok_add2(&init_str, &init_len, tok, tokc);
3480 if (tok == '{')
3481 level++;
3482 else if (tok == '}') {
3483 if (level == 0)
3484 break;
3485 level--;
3487 next();
3489 tok1 = tok;
3490 tok_add(&init_str, &init_len, -1);
3491 tok_add(&init_str, &init_len, 0);
3493 /* compute size */
3494 saved_macro_ptr = macro_ptr;
3495 macro_ptr = init_str;
3496 next();
3497 decl_initializer(t, 0, 1, 1);
3498 /* prepare second initializer parsing */
3499 macro_ptr = init_str;
3500 next();
3502 /* if still unknown size, error */
3503 size = type_size(t, &align);
3504 if (size < 0)
3505 error("unknown type size");
3507 if ((t & VT_VALMASK) == VT_LOCAL) {
3508 loc = (loc - size) & -align;
3509 addr = loc;
3510 } else {
3511 glo = (glo + align - 1) & -align;
3512 addr = glo;
3513 /* very important to increment global
3514 pointer at this time because
3515 initializers themselves can create new
3516 initializers */
3517 glo += size;
3519 if (has_init) {
3520 decl_initializer(t, addr, 1, 0);
3521 /* restore parse state if needed */
3522 if (init_str) {
3523 free(init_str);
3524 macro_ptr = saved_macro_ptr;
3525 tok = tok1;
3528 return addr;
3532 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
3533 void decl(int l)
3535 int *a, t, b, v, u, addr, has_init, size, align;
3536 Sym *sym;
3538 while (1) {
3539 b = ist();
3540 if (!b) {
3541 /* skip redundant ';' */
3542 /* XXX: find more elegant solution */
3543 if (tok == ';') {
3544 next();
3545 continue;
3547 /* special test for old K&R protos without explicit int
3548 type. Only accepted when defining global data */
3549 if (l == VT_LOCAL || tok < TOK_DEFINE)
3550 break;
3551 b = VT_INT;
3553 if ((b & (VT_ENUM | VT_STRUCT)) && tok == ';') {
3554 /* we accept no variable after */
3555 next();
3556 continue;
3558 while (1) { /* iterate thru each declaration */
3559 t = type_decl(&v, b, TYPE_DIRECT);
3560 if (tok == '{') {
3561 if (l == VT_LOCAL)
3562 error("cannot use local functions");
3563 if (!(t & VT_FUNC))
3564 expect("function definition");
3565 /* patch forward references */
3566 if ((sym = sym_find(v)) && (sym->t & VT_FORWARD)) {
3567 greloc_patch(sym, ind);
3568 sym->t = VT_CONST | t;
3569 } else {
3570 /* put function address */
3571 sym_push1(&global_stack, v, VT_CONST | t, ind);
3573 funcname = get_tok_str(v, 0);
3574 /* push a dummy symbol to enable local sym storage */
3575 sym_push1(&local_stack, 0, 0, 0);
3576 /* define parameters */
3577 sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3578 /* XXX: the following is x86 dependant -> move it to
3579 x86 code gen */
3580 addr = 8;
3581 /* if the function returns a structure, then add an
3582 implicit pointer parameter */
3583 func_vt = sym->t;
3584 if (func_vt & VT_STRUCT) {
3585 func_vc = addr;
3586 addr += 4;
3588 while (sym = sym->next) {
3589 u = sym->t;
3590 sym_push(sym->v & ~SYM_FIELD,
3591 u | VT_LOCAL | VT_LVAL,
3592 addr);
3593 if (u & VT_STRUCT) {
3594 #ifdef FUNC_STRUCT_PARAM_AS_PTR
3595 /* structs are passed as pointer */
3596 size = 4;
3597 #else
3598 /* structs are directly put on stack (x86
3599 like) */
3600 size = type_size(u, &align);
3601 size = (size + 3) & ~3;
3602 #endif
3603 } else {
3604 /* XXX: size will be different someday */
3605 size = 4;
3607 addr += size;
3609 loc = 0;
3610 o(0xe58955); /* push %ebp, mov %esp, %ebp */
3611 a = (int *)oad(0xec81, 0); /* sub $xxx, %esp */
3612 rsym = 0;
3613 block(0, 0, 0, 0, 0);
3614 gsym(rsym);
3615 o(0xc3c9); /* leave, ret */
3616 *a = (-loc + 3) & -4; /* align local size to word &
3617 save local variables */
3618 sym_pop(&label_stack, 0); /* reset label stack */
3619 sym_pop(&local_stack, 0); /* reset local stack */
3620 funcname = ""; /* for safety */
3621 func_vt = VT_VOID; /* for safety */
3622 break;
3623 } else {
3624 if (b & VT_TYPEDEF) {
3625 /* save typedefed type */
3626 sym_push(v, t | VT_TYPEDEF, 0);
3627 } else if (t & VT_FUNC) {
3628 /* external function definition */
3629 external_sym(v, t);
3630 } else {
3631 /* not lvalue if array */
3632 if (!(t & VT_ARRAY))
3633 t |= VT_LVAL;
3634 if (b & VT_EXTERN) {
3635 /* external variable */
3636 external_sym(v, t);
3637 } else {
3638 u = l;
3639 if (t & VT_STATIC)
3640 u = VT_CONST;
3641 u |= t;
3642 has_init = (tok == '=');
3643 if (has_init)
3644 next();
3645 addr = decl_initializer_alloc(u, has_init);
3646 sym_push(v, u, addr);
3649 if (tok != ',') {
3650 skip(';');
3651 break;
3653 next();
3659 /* open a dynamic library so that its symbol are available for
3660 compiled programs */
3661 void open_dll(char *libname)
3663 char buf[1024];
3664 void *h;
3666 snprintf(buf, sizeof(buf), "lib%s.so", libname);
3667 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
3668 if (!h)
3669 error((char *)dlerror());
3672 void reloc_external_syms(void)
3674 Sym *s, *s1;
3675 char *str;
3676 int addr;
3678 s = global_stack.top;
3679 while (s != NULL) {
3680 s1 = s->prev;
3681 if (s->t & VT_FORWARD) {
3682 /* if there is at least one relocation to do, then find it
3683 and patch it */
3684 if (s->c) {
3685 str = get_tok_str(s->v, 0);
3686 addr = (int)dlsym(NULL, str);
3687 if (!addr)
3688 error("unresolved external reference '%s'", str);
3689 greloc_patch(s, addr);
3692 s = s1;
3696 /* output a binary file (for testing) */
3697 void build_exe(char *filename)
3699 FILE *f;
3700 f = fopen(filename, "w");
3701 fwrite((void *)prog, 1, ind - prog, f);
3702 fclose(f);
3705 int main(int argc, char **argv)
3707 Sym *s;
3708 int (*t)();
3709 char *p, *r, *outfile;
3710 int optind;
3712 include_paths[0] = "/usr/include";
3713 include_paths[1] = "/usr/lib/tcc";
3714 include_paths[2] = "/usr/local/lib/tcc";
3715 nb_include_paths = 3;
3717 /* add all tokens */
3718 tok_ident = TOK_IDENT;
3719 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";
3720 while (*p) {
3721 r = p;
3722 while (*r++);
3723 tok_alloc(p, r - p - 1);
3724 p = r;
3727 /* standard defines */
3728 define_symbol("__STDC__");
3729 #ifdef __i386__
3730 define_symbol("__i386__");
3731 #endif
3733 optind = 1;
3734 outfile = NULL;
3735 while (1) {
3736 if (optind >= argc) {
3737 show_help:
3738 printf("tcc version 0.9.1 - Tiny C Compiler - Copyright (C) 2001 Fabrice Bellard\n"
3739 "usage: tcc [-Idir] [-Dsym] [-llib] infile [infile_arg...]\n");
3740 return 1;
3742 r = argv[optind];
3743 if (r[0] != '-')
3744 break;
3745 optind++;
3746 if (r[1] == 'I') {
3747 if (nb_include_paths >= INCLUDE_PATHS_MAX)
3748 error("too many include paths");
3749 include_paths[nb_include_paths++] = r + 2;
3750 } else if (r[1] == 'D') {
3751 define_symbol(r + 2);
3752 } else if (r[1] == 'l') {
3753 open_dll(r + 2);
3754 } else if (r[1] == 'o') {
3755 /* currently, only for testing, so not documented */
3756 if (optind >= argc)
3757 goto show_help;
3758 outfile = argv[optind++];
3759 } else {
3760 fprintf(stderr, "invalid option -- '%s'\n", r);
3761 exit(1);
3765 filename = argv[optind];
3766 line_num = 1;
3767 funcname = "";
3768 file = fopen(filename, "r");
3769 if (!file) {
3770 perror(filename);
3771 exit(1);
3773 include_stack_ptr = include_stack;
3774 ifdef_stack_ptr = ifdef_stack;
3776 glo = (int)malloc(DATA_SIZE);
3777 memset((void *)glo, 0, DATA_SIZE);
3778 prog = (int)malloc(TEXT_SIZE);
3779 vstack_ptr = vstack;
3780 anon_sym = 1 << (31 - VT_STRUCT_SHIFT);
3781 ind = prog;
3782 inp();
3783 ch = '\n'; /* needed to parse correctly first preprocessor command */
3784 next();
3785 decl(VT_CONST);
3786 if (tok != -1)
3787 expect("declaration");
3788 reloc_external_syms();
3789 if (outfile) {
3790 build_exe(outfile);
3791 return 0;
3792 } else {
3793 s = sym_find(TOK_MAIN);
3794 if (!s)
3795 error("main() not defined");
3796 t = (int (*)())s->c;
3797 #ifdef PROFILE
3798 return 1;
3799 #else
3800 return (*t)(argc - optind, argv + optind);
3801 #endif