added full long long support - added section support - added __attribute__ parsing...
[tinycc.git] / tcc.c
blob58de4232104a9d5bc596402b0d1a65a949e976e2
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 <stdarg.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <math.h>
26 #include <sys/mman.h>
27 #ifndef CONFIG_TCC_STATIC
28 #include <dlfcn.h>
29 #endif
31 //#define DEBUG
32 /* preprocessor debug */
33 //#define PP_DEBUG
35 /* these sizes are dummy for unix, because malloc() does not use
36 memory when the pages are not used */
37 #define TEXT_SIZE (4*1024*1024)
38 #define DATA_SIZE (4*1024*1024)
40 /* amount of virtual memory associate to a section (currently, we do
41 not realloc them) */
42 #define SECTION_VSIZE (1024 * 1024)
44 #define INCLUDE_STACK_SIZE 32
45 #define IFDEF_STACK_SIZE 64
46 #define VSTACK_SIZE 64
47 #define STRING_MAX_SIZE 1024
48 #define INCLUDE_PATHS_MAX 32
50 #define TOK_HASH_SIZE 521
51 #define TOK_ALLOC_INCR 256 /* must be a power of two */
52 #define SYM_HASH_SIZE 263
54 /* token symbol management */
55 typedef struct TokenSym {
56 struct TokenSym *hash_next;
57 int tok; /* token number */
58 int len;
59 char str[1];
60 } TokenSym;
62 /* constant value */
63 typedef union CValue {
64 long double ld;
65 double d;
66 float f;
67 int i;
68 unsigned int ui;
69 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
70 long long ll;
71 unsigned long long ull;
72 struct TokenSym *ts;
73 struct Sym *sym;
74 int tab[1];
75 } CValue;
77 /* value on stack */
78 typedef struct SValue {
79 int t; /* type */
80 unsigned short r; /* register + flags */
81 unsigned short r2; /* second register, used for 'long long'
82 type. If not used, set to VT_CONST */
83 CValue c; /* constant */
84 } SValue;
86 /* symbol management */
87 typedef struct Sym {
88 int v; /* symbol token */
89 int t; /* associated type */
90 int r; /* associated register */
91 int c; /* associated number */
92 struct Sym *next; /* next related symbol */
93 struct Sym *prev; /* prev symbol in stack */
94 struct Sym *hash_next; /* next symbol in hash table */
95 } Sym;
97 typedef struct SymStack {
98 struct Sym *top;
99 struct Sym *hash[SYM_HASH_SIZE];
100 } SymStack;
102 /* relocation entry (currently only used for functions or variables */
103 typedef struct Reloc {
104 int type; /* type of relocation */
105 int addr; /* address of relocation */
106 struct Reloc *next; /* next relocation */
107 } Reloc;
109 #define RELOC_ADDR32 1 /* 32 bits relocation */
110 #define RELOC_REL32 2 /* 32 bits relative relocation */
112 /* section definition */
113 typedef struct Section {
114 char name[64]; /* section name */
115 unsigned char *data; /* section data */
116 unsigned char *data_ptr; /* current data pointer */
117 struct Section *next;
118 } Section;
120 /* GNUC attribute definition */
121 typedef struct AttributeDef {
122 int aligned;
123 Section *section;
124 } AttributeDef;
126 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
127 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
128 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
130 #define FUNC_NEW 1 /* ansi function prototype */
131 #define FUNC_OLD 2 /* old function prototype */
132 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
134 /* field 'Sym.t' for macros */
135 #define MACRO_OBJ 0 /* object like macro */
136 #define MACRO_FUNC 1 /* function like macro */
138 /* type_decl() types */
139 #define TYPE_ABSTRACT 1 /* type without variable */
140 #define TYPE_DIRECT 2 /* type with variable */
142 typedef struct {
143 FILE *file;
144 char *filename;
145 int line_num;
146 } IncludeFile;
148 /* parser */
149 FILE *file;
150 int line_num;
151 int ch, ch1, tok, tok1;
152 CValue tokc, tok1c;
154 /* sections */
155 Section *first_section;
156 Section *text_section, *data_section, *bss_section; /* predefined sections */
157 Section *cur_text_section; /* current section where function code is
158 generated */
160 /* loc : local variable index
161 ind : output code index
162 rsym: return symbol
163 anon_sym: anonymous symbol index
165 int rsym, anon_sym,
166 prog, ind, loc, const_wanted;
167 int global_expr; /* true if compound literals must be allocated
168 globally (used during initializers parsing */
169 int func_vt, func_vc; /* current function return type (used by
170 return instruction) */
171 int tok_ident;
172 TokenSym **table_ident;
173 TokenSym *hash_ident[TOK_HASH_SIZE];
174 char token_buf[STRING_MAX_SIZE + 1];
175 char *filename, *funcname;
176 /* contains global symbols which remain between each translation unit */
177 SymStack extern_stack;
178 SymStack define_stack, global_stack, local_stack, label_stack;
180 SValue vstack[VSTACK_SIZE], *vtop;
181 int *macro_ptr, *macro_ptr_allocated;
182 IncludeFile include_stack[INCLUDE_STACK_SIZE], *include_stack_ptr;
183 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
184 char *include_paths[INCLUDE_PATHS_MAX];
185 int nb_include_paths;
187 /* use GNU C extensions */
188 int gnu_ext = 1;
190 /* use Tiny C extensions */
191 int tcc_ext = 1;
193 /* The current value can be: */
194 #define VT_VALMASK 0x00ff
195 #define VT_CONST 0x00f0 /* constant in vc
196 (must be first non register value) */
197 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
198 #define VT_LOCAL 0x00f2 /* offset on stack */
199 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
200 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
201 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
202 #define VT_LVAL 0x0100 /* var is an lvalue */
203 #define VT_FORWARD 0x0200 /* value is forward reference */
204 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (user for
205 bool/char/short stored in int registers) */
207 /* types */
208 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
210 #define VT_INT 0 /* integer type */
211 #define VT_BYTE 1 /* signed byte type */
212 #define VT_SHORT 2 /* short type */
213 #define VT_VOID 3 /* void type */
214 #define VT_PTR 4 /* pointer increment */
215 #define VT_ENUM 5 /* enum definition */
216 #define VT_FUNC 6 /* function type */
217 #define VT_STRUCT 7 /* struct/union definition */
218 #define VT_FLOAT 8 /* IEEE float */
219 #define VT_DOUBLE 9 /* IEEE double */
220 #define VT_LDOUBLE 10 /* IEEE long double */
221 #define VT_BOOL 11 /* ISOC99 boolean type */
222 #define VT_LLONG 12 /* 64 bit integer */
223 #define VT_LONG 13 /* long integer (NEVER USED as type, only
224 during parsing) */
225 #define VT_BTYPE 0x000f /* mask for basic type */
226 #define VT_UNSIGNED 0x0010 /* unsigned type */
227 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
228 #define VT_BITFIELD 0x0040 /* bitfield modifier */
230 /* storage */
231 #define VT_EXTERN 0x00000080 /* extern definition */
232 #define VT_STATIC 0x00000100 /* static variable */
233 #define VT_TYPEDEF 0x00000200 /* typedef definition */
235 /* type mask (except storage) */
236 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
238 /* token values */
240 /* warning: the following compare tokens depend on i386 asm code */
241 #define TOK_ULT 0x92
242 #define TOK_UGE 0x93
243 #define TOK_EQ 0x94
244 #define TOK_NE 0x95
245 #define TOK_ULE 0x96
246 #define TOK_UGT 0x97
247 #define TOK_LT 0x9c
248 #define TOK_GE 0x9d
249 #define TOK_LE 0x9e
250 #define TOK_GT 0x9f
252 #define TOK_LAND 0xa0
253 #define TOK_LOR 0xa1
255 #define TOK_DEC 0xa2
256 #define TOK_MID 0xa3 /* inc/dec, to void constant */
257 #define TOK_INC 0xa4
258 #define TOK_UDIV 0xb0 /* unsigned division */
259 #define TOK_UMOD 0xb1 /* unsigned modulo */
260 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
261 #define TOK_CINT 0xb3 /* number in tokc */
262 #define TOK_CCHAR 0xb4 /* char constant in tokc */
263 #define TOK_STR 0xb5 /* pointer to string in tokc */
264 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
265 #define TOK_LCHAR 0xb7
266 #define TOK_LSTR 0xb8
267 #define TOK_CFLOAT 0xb9 /* float constant */
268 #define TOK_CDOUBLE 0xc0 /* double constant */
269 #define TOK_CLDOUBLE 0xc1 /* long double constant */
270 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
271 #define TOK_ADDC1 0xc3 /* add with carry generation */
272 #define TOK_ADDC2 0xc4 /* add with carry use */
273 #define TOK_SUBC1 0xc5 /* add with carry generation */
274 #define TOK_SUBC2 0xc6 /* add with carry use */
275 #define TOK_CUINT 0xc8 /* unsigned int constant */
276 #define TOK_CLLONG 0xc9 /* long long constant */
277 #define TOK_CULLONG 0xca /* unsigned long long constant */
278 #define TOK_ARROW 0xcb
279 #define TOK_DOTS 0xcc /* three dots */
280 #define TOK_SHR 0xcd /* unsigned shift right */
282 #define TOK_SHL 0x01 /* shift left */
283 #define TOK_SAR 0x02 /* signed shift right */
285 /* assignement operators : normal operator or 0x80 */
286 #define TOK_A_MOD 0xa5
287 #define TOK_A_AND 0xa6
288 #define TOK_A_MUL 0xaa
289 #define TOK_A_ADD 0xab
290 #define TOK_A_SUB 0xad
291 #define TOK_A_DIV 0xaf
292 #define TOK_A_XOR 0xde
293 #define TOK_A_OR 0xfc
294 #define TOK_A_SHL 0x81
295 #define TOK_A_SAR 0x82
297 /* all identificators and strings have token above that */
298 #define TOK_IDENT 256
300 enum {
301 TOK_INT = TOK_IDENT,
302 TOK_VOID,
303 TOK_CHAR,
304 TOK_IF,
305 TOK_ELSE,
306 TOK_WHILE,
307 TOK_BREAK,
308 TOK_RETURN,
309 TOK_FOR,
310 TOK_EXTERN,
311 TOK_STATIC,
312 TOK_UNSIGNED,
313 TOK_GOTO,
314 TOK_DO,
315 TOK_CONTINUE,
316 TOK_SWITCH,
317 TOK_CASE,
319 /* ignored types Must have contiguous values */
320 TOK_CONST,
321 TOK_VOLATILE,
322 TOK_LONG,
323 TOK_REGISTER,
324 TOK_SIGNED,
325 TOK_AUTO,
326 TOK_INLINE,
327 TOK_RESTRICT,
329 /* unsupported type */
330 TOK_FLOAT,
331 TOK_DOUBLE,
332 TOK_BOOL,
334 TOK_SHORT,
335 TOK_STRUCT,
336 TOK_UNION,
337 TOK_TYPEDEF,
338 TOK_DEFAULT,
339 TOK_ENUM,
340 TOK_SIZEOF,
341 TOK___ATTRIBUTE__,
343 /* preprocessor only */
344 TOK_UIDENT, /* first "user" ident (not keyword) */
345 TOK_DEFINE = TOK_UIDENT,
346 TOK_INCLUDE,
347 TOK_IFDEF,
348 TOK_IFNDEF,
349 TOK_ELIF,
350 TOK_ENDIF,
351 TOK_DEFINED,
352 TOK_UNDEF,
353 TOK_ERROR,
354 TOK_LINE,
355 TOK___LINE__,
356 TOK___FILE__,
357 TOK___DATE__,
358 TOK___TIME__,
359 TOK___VA_ARGS__,
361 /* special identifiers */
362 TOK___FUNC__,
363 TOK_MAIN,
364 /* attribute identifiers */
365 TOK_SECTION,
366 TOK___SECTION__,
367 TOK_ALIGNED,
368 TOK___ALIGNED__,
369 TOK_UNUSED,
370 TOK___UNUSED__,
373 /* XXX: need to define this to use them in non ISOC99 context */
374 extern float strtof (const char *__nptr, char **__endptr);
375 extern long double strtold (const char *__nptr, char **__endptr);
377 void sum(int l);
378 void next(void);
379 void next_nomacro(void);
380 int expr_const(void);
381 void expr_eq(void);
382 void gexpr(void);
383 void decl(int l);
384 void decl_initializer(int t, int r, int c, int first, int size_only);
385 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init);
386 int gv(int rc);
387 void move_reg(int r, int s);
388 void save_reg(int r);
389 void vpop(void);
390 void vswap(void);
391 void vdup(void);
392 int get_reg(int rc);
394 void macro_subst(int **tok_str, int *tok_len,
395 Sym **nested_list, int *macro_str);
396 int save_reg_forced(int r);
397 void gen_op(int op);
398 void force_charshort_cast(int t);
399 void gen_cast(int t);
400 void vstore(void);
402 /* type handling */
403 int type_size(int t, int *a);
404 int pointed_type(int t);
405 int pointed_size(int t);
406 int is_compatible_types(int t1, int t2);
407 int parse_btype(int *type_ptr, AttributeDef *ad);
408 int type_decl(int *v, int t, int td);
410 void error(const char *fmt, ...);
411 void vpushi(int v);
412 void vset(int t, int r, int v);
413 void greloc(Sym *s, int addr, int type);
414 void type_to_str(char *buf, int buf_size,
415 int t, const char *varstr);
417 /* true if float/double/long double type */
418 static inline int is_float(int t)
420 int bt;
421 bt = t & VT_BTYPE;
422 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
425 #include "i386-gen.c"
427 #ifdef CONFIG_TCC_STATIC
429 #define RTLD_LAZY 0x001
430 #define RTLD_NOW 0x002
431 #define RTLD_GLOBAL 0x100
433 /* dummy function for profiling */
434 void *dlopen(const char *filename, int flag)
436 return NULL;
439 const char *dlerror(void)
441 return "error";
444 typedef struct TCCSyms {
445 char *str;
446 void *ptr;
447 } TCCSyms;
449 #define TCCSYM(a) { #a, &a, },
451 /* add the symbol you want here if no dynamic linking is done */
452 static TCCSyms tcc_syms[] = {
453 TCCSYM(printf)
454 TCCSYM(fprintf)
455 TCCSYM(fopen)
456 TCCSYM(fclose)
457 { NULL, NULL },
460 void *dlsym(void *handle, char *symbol)
462 TCCSyms *p;
463 p = tcc_syms;
464 while (p->str != NULL) {
465 if (!strcmp(p->str, symbol))
466 return p->ptr;
467 p++;
469 return NULL;
472 #endif
474 /********************************************************/
475 /* runtime library is there */
476 /* XXX: we suppose that the host compiler handles 'long long'. It
477 would not be difficult to suppress this assumption */
479 /* XXX: these functions are defined in libgcc. Should provide a
480 portable code too. */
481 long long __divll(long long a, long long b)
483 return a / b;
486 long long __modll(long long a, long long b)
488 return a % b;
491 unsigned long long __divull(unsigned long long a, unsigned long long b)
493 return a / b;
496 unsigned long long __modull(unsigned long long a, unsigned long long b)
498 return a % b;
501 long long __sardi3(long long a, int b)
503 return a >> b;
506 unsigned long long __shrdi3(unsigned long long a, int b)
508 return a >> b;
511 long long __shldi3(long long a, int b)
513 return a << b;
516 float __ulltof(unsigned long long a)
518 return (float)a;
521 double __ulltod(unsigned long long a)
523 return (double)a;
526 long double __ulltold(unsigned long long a)
528 return (long double)a;
531 unsigned long long __ftoull(float a)
533 return (unsigned long long)a;
536 unsigned long long __dtoull(double a)
538 return (unsigned long long)a;
541 unsigned long long __ldtoull(long double a)
543 return (unsigned long long)a;
547 /********************************************************/
549 /* copy a string and trucate it */
550 char *pstrcpy(char *buf, int buf_size, const char *s)
552 char *q, *q_end;
553 int c;
555 q = buf;
556 q_end = buf + buf_size - 1;
557 while (q < q_end) {
558 c = *s++;
559 if (c == '\0')
560 break;
561 *q++ = c;
563 *q = '\0';
564 return buf;
567 Section *new_section(const char *name)
569 Section *sec, **psec;
570 void *data;
572 sec = malloc(sizeof(Section));
573 if (!sec)
574 error("memory full");
575 pstrcpy(sec->name, sizeof(sec->name), name);
576 data = mmap(NULL, SECTION_VSIZE,
577 PROT_EXEC | PROT_READ | PROT_WRITE,
578 MAP_PRIVATE | MAP_ANONYMOUS,
579 -1, 0);
580 if (data == (void *)(-1))
581 error("could not mmap section '%s'", name);
582 sec->data = data;
583 sec->data_ptr = data;
584 psec = &first_section;
585 while (*psec != NULL)
586 psec = &(*psec)->next;
587 sec->next = NULL;
588 *psec = sec;
589 return sec;
592 /* return a reference to a section, and create it if it does not
593 exists */
594 Section *find_section(const char *name)
596 Section *sec;
598 for(sec = first_section; sec != NULL; sec = sec->next) {
599 if (!strcmp(name, sec->name))
600 return sec;
602 return new_section(name);
605 /* add a new relocation entry to symbol 's' */
606 void greloc(Sym *s, int addr, int type)
608 Reloc *p;
609 p = malloc(sizeof(Reloc));
610 if (!p)
611 error("memory full");
612 p->type = type;
613 p->addr = addr;
614 p->next = (Reloc *)s->c;
615 s->c = (int)p;
618 /* patch each relocation entry with value 'val' */
619 void greloc_patch(Sym *s, int val)
621 Reloc *p, *p1;
623 p = (Reloc *)s->c;
624 while (p != NULL) {
625 p1 = p->next;
626 greloc_patch1(p, val);
627 free(p);
628 p = p1;
630 s->c = val;
631 s->r &= ~VT_FORWARD;
635 static inline int isid(int c)
637 return (c >= 'a' && c <= 'z') ||
638 (c >= 'A' && c <= 'Z') ||
639 c == '_';
642 static inline int isnum(int c)
644 return c >= '0' && c <= '9';
647 static inline int toup(int c)
649 if (ch >= 'a' && ch <= 'z')
650 return ch - 'a' + 'A';
651 else
652 return ch;
655 void printline(void)
657 IncludeFile *f;
658 for(f = include_stack; f < include_stack_ptr; f++)
659 fprintf(stderr, "In file included from %s:%d:\n",
660 f->filename, f->line_num);
661 fprintf(stderr, "%s:%d: ", filename, line_num);
664 void error(const char *fmt, ...)
666 va_list ap;
667 va_start(ap, fmt);
668 printline();
669 vfprintf(stderr, fmt, ap);
670 fprintf(stderr, "\n");
671 exit(1);
672 va_end(ap);
675 void expect(const char *msg)
677 error("%s expected", msg);
680 void warning(const char *fmt, ...)
682 va_list ap;
684 va_start(ap, fmt);
685 printline();
686 fprintf(stderr, "warning: ");
687 vfprintf(stderr, fmt, ap);
688 fprintf(stderr, "\n");
689 va_end(ap);
692 void skip(int c)
694 if (tok != c)
695 error("'%c' expected", c);
696 next();
699 void test_lvalue(void)
701 if (!(vtop->r & VT_LVAL))
702 expect("lvalue");
705 TokenSym *tok_alloc(const char *str, int len)
707 TokenSym *ts, **pts, **ptable;
708 int h, i;
710 if (len <= 0)
711 len = strlen(str);
712 h = 1;
713 for(i=0;i<len;i++)
714 h = ((h << 8) | (str[i] & 0xff)) % TOK_HASH_SIZE;
716 pts = &hash_ident[h];
717 while (1) {
718 ts = *pts;
719 if (!ts)
720 break;
721 if (ts->len == len && !memcmp(ts->str, str, len))
722 return ts;
723 pts = &(ts->hash_next);
726 if (tok_ident >= SYM_FIRST_ANOM)
727 error("memory full");
729 /* expand token table if needed */
730 i = tok_ident - TOK_IDENT;
731 if ((i % TOK_ALLOC_INCR) == 0) {
732 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
733 if (!ptable)
734 error("memory full");
735 table_ident = ptable;
738 ts = malloc(sizeof(TokenSym) + len);
739 if (!ts)
740 error("memory full");
741 table_ident[i] = ts;
742 ts->tok = tok_ident++;
743 ts->len = len;
744 ts->hash_next = NULL;
745 memcpy(ts->str, str, len + 1);
746 *pts = ts;
747 return ts;
750 void add_char(char **pp, int c)
752 char *p;
753 p = *pp;
754 if (c == '\'' || c == '\"' || c == '\\') {
755 /* XXX: could be more precise if char or string */
756 *p++ = '\\';
758 if (c >= 32 && c <= 126) {
759 *p++ = c;
760 } else {
761 *p++ = '\\';
762 if (c == '\n') {
763 *p++ = 'n';
764 } else {
765 *p++ = '0' + ((c >> 6) & 7);
766 *p++ = '0' + ((c >> 3) & 7);
767 *p++ = '0' + (c & 7);
770 *pp = p;
773 /* XXX: buffer overflow */
774 char *get_tok_str(int v, CValue *cv)
776 static char buf[STRING_MAX_SIZE + 1];
777 TokenSym *ts;
778 char *p;
779 int i;
781 if (v == TOK_CINT || v == TOK_CUINT) {
782 sprintf(buf, "%u", cv->ui);
783 return buf;
784 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
785 p = buf;
786 *p++ = '\'';
787 add_char(&p, cv->i);
788 *p++ = '\'';
789 *p = '\0';
790 return buf;
791 } else if (v == TOK_STR || v == TOK_LSTR) {
792 ts = cv->ts;
793 p = buf;
794 *p++ = '\"';
795 for(i=0;i<ts->len;i++)
796 add_char(&p, ts->str[i]);
797 *p++ = '\"';
798 *p = '\0';
799 return buf;
800 } else if (v < TOK_IDENT) {
801 p = buf;
802 *p++ = v;
803 *p = '\0';
804 return buf;
805 } else if (v < tok_ident) {
806 return table_ident[v - TOK_IDENT]->str;
807 } else {
808 /* should never happen */
809 return NULL;
813 /* push, without hashing */
814 Sym *sym_push2(Sym **ps, int v, int t, int c)
816 Sym *s;
817 s = malloc(sizeof(Sym));
818 if (!s)
819 error("memory full");
820 s->v = v;
821 s->t = t;
822 s->c = c;
823 s->next = NULL;
824 /* add in stack */
825 s->prev = *ps;
826 *ps = s;
827 return s;
830 /* find a symbol and return its associated structure. 's' is the top
831 of the symbol stack */
832 Sym *sym_find2(Sym *s, int v)
834 while (s) {
835 if (s->v == v)
836 return s;
837 s = s->prev;
839 return NULL;
842 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
844 /* find a symbol and return its associated structure. 'st' is the
845 symbol stack */
846 Sym *sym_find1(SymStack *st, int v)
848 Sym *s;
850 s = st->hash[HASH_SYM(v)];
851 while (s) {
852 if (s->v == v)
853 return s;
854 s = s->hash_next;
856 return NULL;
859 Sym *sym_push1(SymStack *st, int v, int t, int c)
861 Sym *s, **ps;
862 s = sym_push2(&st->top, v, t, c);
863 /* add in hash table */
864 if (v) {
865 ps = &st->hash[HASH_SYM(v)];
866 s->hash_next = *ps;
867 *ps = s;
869 return s;
872 /* find a symbol in the right symbol space */
873 Sym *sym_find(int v)
875 Sym *s;
876 s = sym_find1(&local_stack, v);
877 if (!s)
878 s = sym_find1(&global_stack, v);
879 return s;
882 /* push a given symbol on the symbol stack */
883 Sym *sym_push(int v, int t, int r, int c)
885 Sym *s;
886 if (local_stack.top)
887 s = sym_push1(&local_stack, v, t, c);
888 else
889 s = sym_push1(&global_stack, v, t, c);
890 s->r = r;
891 return s;
894 /* pop symbols until top reaches 'b' */
895 void sym_pop(SymStack *st, Sym *b)
897 Sym *s, *ss;
899 s = st->top;
900 while(s != b) {
901 ss = s->prev;
902 /* free hash table entry, except if symbol was freed (only
903 used for #undef symbols) */
904 if (s->v)
905 st->hash[HASH_SYM(s->v)] = s->hash_next;
906 free(s);
907 s = ss;
909 st->top = b;
912 /* undefined a hashed symbol (used for #undef). Its name is set to
913 zero */
914 void sym_undef(SymStack *st, Sym *s)
916 Sym **ss;
917 ss = &st->hash[HASH_SYM(s->v)];
918 while (*ss != NULL) {
919 if (*ss == s)
920 break;
921 ss = &(*ss)->hash_next;
923 *ss = s->hash_next;
924 s->v = 0;
927 /* no need to put that inline */
928 int handle_eof(void)
930 if (include_stack_ptr == include_stack)
931 return -1;
932 /* pop include stack */
933 fclose(file);
934 free(filename);
935 include_stack_ptr--;
936 file = include_stack_ptr->file;
937 filename = include_stack_ptr->filename;
938 line_num = include_stack_ptr->line_num;
939 return 0;
942 /* read next char from current input file */
943 static inline void inp(void)
945 redo:
946 /* faster than fgetc */
947 ch1 = getc_unlocked(file);
948 if (ch1 == -1) {
949 if (handle_eof() < 0)
950 return;
951 else
952 goto redo;
954 if (ch1 == '\n')
955 line_num++;
956 // printf("ch1=%c 0x%x\n", ch1, ch1);
959 /* input with '\\n' handling */
960 static inline void minp(void)
962 redo:
963 ch = ch1;
964 inp();
965 if (ch == '\\' && ch1 == '\n') {
966 inp();
967 goto redo;
969 //printf("ch=%c 0x%x\n", ch, ch);
973 /* same as minp, but also skip comments */
974 void cinp(void)
976 int c;
978 if (ch1 == '/') {
979 inp();
980 if (ch1 == '/') {
981 /* single line C++ comments */
982 inp();
983 while (ch1 != '\n' && ch1 != -1)
984 inp();
985 inp();
986 ch = ' '; /* return space */
987 } else if (ch1 == '*') {
988 /* C comments */
989 inp();
990 while (ch1 != -1) {
991 c = ch1;
992 inp();
993 if (c == '*' && ch1 == '/') {
994 inp();
995 ch = ' '; /* return space */
996 break;
999 } else {
1000 ch = '/';
1002 } else {
1003 minp();
1007 void skip_spaces(void)
1009 while (ch == ' ' || ch == '\t')
1010 cinp();
1013 /* skip block of text until #else, #elif or #endif. skip also pairs of
1014 #if/#endif */
1015 void preprocess_skip()
1017 int a;
1018 a = 0;
1019 while (1) {
1020 while (ch != '\n') {
1021 if (ch == -1)
1022 expect("#endif");
1023 cinp();
1025 cinp();
1026 skip_spaces();
1027 if (ch == '#') {
1028 cinp();
1029 next_nomacro();
1030 if (a == 0 &&
1031 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1032 break;
1033 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1034 a++;
1035 else if (tok == TOK_ENDIF)
1036 a--;
1041 /* return the number of additionnal 'ints' necessary to store the
1042 token */
1043 static inline int tok_ext_size(int t)
1045 switch(t) {
1046 /* 4 bytes */
1047 case TOK_CINT:
1048 case TOK_CUINT:
1049 case TOK_CCHAR:
1050 case TOK_LCHAR:
1051 case TOK_STR:
1052 case TOK_LSTR:
1053 case TOK_CFLOAT:
1054 return 1;
1055 case TOK_CDOUBLE:
1056 case TOK_CLLONG:
1057 case TOK_CULLONG:
1058 return 2;
1059 case TOK_CLDOUBLE:
1060 return LDOUBLE_SIZE / 4;
1061 default:
1062 return 0;
1066 void tok_add(int **tok_str, int *tok_len, int t)
1068 int len, *str;
1069 len = *tok_len;
1070 str = *tok_str;
1071 if ((len & 63) == 0) {
1072 str = realloc(str, (len + 64) * sizeof(int));
1073 if (!str)
1074 return;
1075 *tok_str = str;
1077 str[len++] = t;
1078 *tok_len = len;
1081 void tok_add2(int **tok_str, int *tok_len, int t, CValue *cv)
1083 int n, i;
1085 tok_add(tok_str, tok_len, t);
1086 n = tok_ext_size(t);
1087 for(i=0;i<n;i++)
1088 tok_add(tok_str, tok_len, cv->tab[i]);
1091 /* get a token from an integer array and increment pointer accordingly */
1092 int tok_get(int **tok_str, CValue *cv)
1094 int *p, t, n, i;
1096 p = *tok_str;
1097 t = *p++;
1098 n = tok_ext_size(t);
1099 for(i=0;i<n;i++)
1100 cv->tab[i] = *p++;
1101 *tok_str = p;
1102 return t;
1105 /* eval an expression for #if/#elif */
1106 int expr_preprocess(void)
1108 int *str, len, c, t;
1110 str = NULL;
1111 len = 0;
1112 while (1) {
1113 skip_spaces();
1114 if (ch == '\n')
1115 break;
1116 next(); /* do macro subst */
1117 if (tok == TOK_DEFINED) {
1118 next_nomacro();
1119 t = tok;
1120 if (t == '(')
1121 next_nomacro();
1122 c = sym_find1(&define_stack, tok) != 0;
1123 if (t == '(')
1124 next_nomacro();
1125 tok = TOK_CINT;
1126 tokc.i = c;
1127 } else if (tok >= TOK_IDENT) {
1128 /* if undefined macro */
1129 tok = TOK_CINT;
1130 tokc.i = 0;
1132 tok_add2(&str, &len, tok, &tokc);
1134 tok_add(&str, &len, -1); /* simulate end of file */
1135 tok_add(&str, &len, 0);
1136 /* now evaluate C constant expression */
1137 macro_ptr = str;
1138 next();
1139 c = expr_const();
1140 macro_ptr = NULL;
1141 free(str);
1142 return c != 0;
1145 #if defined(DEBUG)
1146 void tok_print(int *str)
1148 int t;
1149 CValue cval;
1151 while (1) {
1152 t = tok_get(&str, &cval);
1153 if (!t)
1154 break;
1155 printf(" %s", get_tok_str(t, &cval));
1157 printf("\n");
1159 #endif
1161 void preprocess(void)
1163 int size, i, c, v, t, *str, len;
1164 char buf[1024], *q, *p;
1165 char buf1[1024];
1166 FILE *f;
1167 Sym **ps, *first, *s;
1169 cinp();
1170 next_nomacro();
1171 redo:
1172 if (tok == TOK_DEFINE) {
1173 next_nomacro();
1174 v = tok;
1175 /* XXX: should check if same macro (ANSI) */
1176 first = NULL;
1177 t = MACRO_OBJ;
1178 /* '(' must be just after macro definition for MACRO_FUNC */
1179 if (ch == '(') {
1180 next_nomacro();
1181 next_nomacro();
1182 ps = &first;
1183 while (tok != ')') {
1184 if (tok == TOK_DOTS)
1185 tok = TOK___VA_ARGS__;
1186 s = sym_push1(&define_stack, tok | SYM_FIELD, 0, 0);
1187 *ps = s;
1188 ps = &s->next;
1189 next_nomacro();
1190 if (tok != ',')
1191 break;
1192 next_nomacro();
1194 t = MACRO_FUNC;
1196 str = NULL;
1197 len = 0;
1198 while (1) {
1199 skip_spaces();
1200 if (ch == '\n' || ch == -1)
1201 break;
1202 next_nomacro();
1203 tok_add2(&str, &len, tok, &tokc);
1205 tok_add(&str, &len, 0);
1206 #ifdef PP_DEBUG
1207 printf("define %s %d: ", get_tok_str(v, NULL), t);
1208 tok_print(str);
1209 #endif
1210 s = sym_push1(&define_stack, v, t, (int)str);
1211 s->next = first;
1212 } else if (tok == TOK_UNDEF) {
1213 next_nomacro();
1214 s = sym_find1(&define_stack, tok);
1215 /* undefine symbol by putting an invalid name */
1216 if (s)
1217 sym_undef(&define_stack, s);
1218 } else if (tok == TOK_INCLUDE) {
1219 skip_spaces();
1220 if (ch == '<') {
1221 c = '>';
1222 goto read_name;
1223 } else if (ch == '\"') {
1224 c = ch;
1225 read_name:
1226 minp();
1227 q = buf;
1228 while (ch != c && ch != '\n' && ch != -1) {
1229 if ((q - buf) < sizeof(buf) - 1)
1230 *q++ = ch;
1231 minp();
1233 *q = '\0';
1234 } else {
1235 next();
1236 if (tok != TOK_STR)
1237 error("#include syntax error");
1238 /* XXX: buffer overflow */
1239 strcpy(buf, get_tok_str(tok, &tokc));
1240 c = '\"';
1242 /* eat all spaces and comments after include */
1243 /* XXX: slightly incorrect */
1244 while (ch1 != '\n' && ch1 != -1)
1245 inp();
1247 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
1248 error("memory full");
1249 if (c == '\"') {
1250 /* first search in current dir if "header.h" */
1251 /* XXX: buffer overflow */
1252 size = 0;
1253 p = strrchr(filename, '/');
1254 if (p)
1255 size = p + 1 - filename;
1256 memcpy(buf1, filename, size);
1257 buf1[size] = '\0';
1258 strcat(buf1, buf);
1259 f = fopen(buf1, "r");
1260 if (f)
1261 goto found;
1263 /* now search in standard include path */
1264 for(i=nb_include_paths - 1;i>=0;i--) {
1265 strcpy(buf1, include_paths[i]);
1266 strcat(buf1, "/");
1267 strcat(buf1, buf);
1268 f = fopen(buf1, "r");
1269 if (f)
1270 goto found;
1272 error("include file '%s' not found", buf1);
1273 f = NULL;
1274 found:
1275 /* push current file in stack */
1276 /* XXX: fix current line init */
1277 include_stack_ptr->file = file;
1278 include_stack_ptr->filename = filename;
1279 include_stack_ptr->line_num = line_num;
1280 include_stack_ptr++;
1281 file = f;
1282 filename = strdup(buf1);
1283 line_num = 1;
1284 } else if (tok == TOK_IFNDEF) {
1285 c = 1;
1286 goto do_ifdef;
1287 } else if (tok == TOK_IF) {
1288 c = expr_preprocess();
1289 goto do_if;
1290 } else if (tok == TOK_IFDEF) {
1291 c = 0;
1292 do_ifdef:
1293 next_nomacro();
1294 c = (sym_find1(&define_stack, tok) != 0) ^ c;
1295 do_if:
1296 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
1297 error("memory full");
1298 *ifdef_stack_ptr++ = c;
1299 goto test_skip;
1300 } else if (tok == TOK_ELSE) {
1301 if (ifdef_stack_ptr == ifdef_stack ||
1302 (ifdef_stack_ptr[-1] & 2))
1303 error("#else after #else");
1304 c = (ifdef_stack_ptr[-1] ^= 3);
1305 goto test_skip;
1306 } else if (tok == TOK_ELIF) {
1307 if (ifdef_stack_ptr == ifdef_stack ||
1308 ifdef_stack_ptr[-1] > 1)
1309 error("#elif after #else");
1310 c = expr_preprocess();
1311 ifdef_stack_ptr[-1] = c;
1312 test_skip:
1313 if (!(c & 1)) {
1314 preprocess_skip();
1315 goto redo;
1317 } else if (tok == TOK_ENDIF) {
1318 if (ifdef_stack_ptr == ifdef_stack)
1319 expect("#if");
1320 ifdef_stack_ptr--;
1321 } else if (tok == TOK_LINE) {
1322 next();
1323 if (tok != TOK_CINT)
1324 error("#line");
1325 line_num = tokc.i;
1326 skip_spaces();
1327 if (ch != '\n') {
1328 next();
1329 if (tok != TOK_STR)
1330 error("#line");
1331 /* XXX: potential memory leak */
1332 filename = strdup(get_tok_str(tok, &tokc));
1334 } else if (tok == TOK_ERROR) {
1335 error("#error");
1337 /* ignore other preprocess commands or #! for C scripts */
1338 while (ch != '\n' && ch != -1)
1339 cinp();
1342 /* read a number in base b */
1343 int getn(b)
1345 int n, t;
1346 n = 0;
1347 while (1) {
1348 if (ch >= 'a' && ch <= 'f')
1349 t = ch - 'a' + 10;
1350 else if (ch >= 'A' && ch <= 'F')
1351 t = ch - 'A' + 10;
1352 else if (isnum(ch))
1353 t = ch - '0';
1354 else
1355 break;
1356 if (t < 0 || t >= b)
1357 break;
1358 n = n * b + t;
1359 cinp();
1361 return n;
1364 /* read a character for string or char constant and eval escape codes */
1365 int getq()
1367 int c;
1369 c = ch;
1370 minp();
1371 if (c == '\\') {
1372 if (isnum(ch)) {
1373 /* at most three octal digits */
1374 c = ch - '0';
1375 minp();
1376 if (isnum(ch)) {
1377 c = c * 8 + ch - '0';
1378 minp();
1379 if (isnum(ch)) {
1380 c = c * 8 + ch - '0';
1381 minp();
1384 return c;
1385 } else if (ch == 'x') {
1386 minp();
1387 return getn(16);
1388 } else {
1389 if (ch == 'a')
1390 c = '\a';
1391 else if (ch == 'b')
1392 c = '\b';
1393 else if (ch == 'f')
1394 c = '\f';
1395 else if (ch == 'n')
1396 c = '\n';
1397 else if (ch == 'r')
1398 c = '\r';
1399 else if (ch == 't')
1400 c = '\t';
1401 else if (ch == 'v')
1402 c = '\v';
1403 else if (ch == 'e' && gnu_ext)
1404 c = 27;
1405 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
1406 c = ch;
1407 else
1408 error("invalid escaped char");
1409 minp();
1412 return c;
1415 /* we use 64 bit numbers */
1416 #define BN_SIZE 2
1418 /* bn = (bn << shift) | or_val */
1419 void bn_lshift(unsigned int *bn, int shift, int or_val)
1421 int i;
1422 unsigned int v;
1423 for(i=0;i<BN_SIZE;i++) {
1424 v = bn[i];
1425 bn[i] = (v << shift) | or_val;
1426 or_val = v >> (32 - shift);
1430 void bn_zero(unsigned int *bn)
1432 int i;
1433 for(i=0;i<BN_SIZE;i++) {
1434 bn[i] = 0;
1438 void parse_number(void)
1440 int b, t, shift, frac_bits, s, exp_val;
1441 char *q;
1442 unsigned int bn[BN_SIZE];
1443 double d;
1445 /* number */
1446 q = token_buf;
1447 t = ch;
1448 cinp();
1449 *q++ = t;
1450 b = 10;
1451 if (t == '.') {
1452 /* special dot handling */
1453 if (ch >= '0' && ch <= '9') {
1454 goto float_frac_parse;
1455 } else if (ch == '.') {
1456 cinp();
1457 if (ch != '.')
1458 expect("'.'");
1459 cinp();
1460 tok = TOK_DOTS;
1461 } else {
1462 /* dots */
1463 tok = t;
1465 return;
1466 } else if (t == '0') {
1467 if (ch == 'x' || ch == 'X') {
1468 q--;
1469 cinp();
1470 b = 16;
1471 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1472 q--;
1473 cinp();
1474 b = 2;
1477 /* parse all digits. cannot check octal numbers at this stage
1478 because of floating point constants */
1479 while (1) {
1480 if (ch >= 'a' && ch <= 'f')
1481 t = ch - 'a' + 10;
1482 else if (ch >= 'A' && ch <= 'F')
1483 t = ch - 'A' + 10;
1484 else if (isnum(ch))
1485 t = ch - '0';
1486 else
1487 break;
1488 if (t >= b)
1489 break;
1490 if (q >= token_buf + STRING_MAX_SIZE) {
1491 num_too_long:
1492 error("number too long");
1494 *q++ = ch;
1495 cinp();
1497 if (ch == '.' ||
1498 ((ch == 'e' || ch == 'E') && b == 10) ||
1499 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1500 if (b != 10) {
1501 /* NOTE: strtox should support that for hexa numbers, but
1502 non ISOC99 libcs do not support it, so we prefer to do
1503 it by hand */
1504 /* hexadecimal or binary floats */
1505 /* XXX: handle overflows */
1506 *q = '\0';
1507 if (b == 16)
1508 shift = 4;
1509 else
1510 shift = 2;
1511 bn_zero(bn);
1512 q = token_buf;
1513 while (1) {
1514 t = *q++;
1515 if (t == '\0') {
1516 break;
1517 } else if (t >= 'a') {
1518 t = t - 'a' + 10;
1519 } else if (t >= 'A') {
1520 t = t - 'A' + 10;
1521 } else {
1522 t = t - '0';
1524 bn_lshift(bn, shift, t);
1526 frac_bits = 0;
1527 if (ch == '.') {
1528 cinp();
1529 while (1) {
1530 t = ch;
1531 if (t >= 'a' && t <= 'f') {
1532 t = t - 'a' + 10;
1533 } else if (t >= 'A' && t <= 'F') {
1534 t = t - 'A' + 10;
1535 } else if (t >= '0' && t <= '9') {
1536 t = t - '0';
1537 } else {
1538 break;
1540 if (t >= b)
1541 error("invalid digit");
1542 bn_lshift(bn, shift, t);
1543 frac_bits += shift;
1544 cinp();
1547 if (ch != 'p' && ch != 'P')
1548 error("exponent expected");
1549 cinp();
1550 s = 1;
1551 exp_val = 0;
1552 if (ch == '+') {
1553 cinp();
1554 } else if (ch == '-') {
1555 s = -1;
1556 cinp();
1558 if (ch < '0' || ch > '9')
1559 error("exponent digits expected");
1560 while (ch >= '0' && ch <= '9') {
1561 exp_val = exp_val * 10 + ch - '0';
1562 cinp();
1564 exp_val = exp_val * s;
1566 /* now we can generate the number */
1567 /* XXX: should patch directly float number */
1568 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1569 d = ldexp(d, exp_val - frac_bits);
1570 t = toup(ch);
1571 if (t == 'F') {
1572 cinp();
1573 tok = TOK_CFLOAT;
1574 /* float : should handle overflow */
1575 tokc.f = (float)d;
1576 } else if (t == 'L') {
1577 cinp();
1578 tok = TOK_CLDOUBLE;
1579 /* XXX: not large enough */
1580 tokc.ld = (long double)d;
1581 } else {
1582 tok = TOK_CDOUBLE;
1583 tokc.d = d;
1585 } else {
1586 /* decimal floats */
1587 if (ch == '.') {
1588 if (q >= token_buf + STRING_MAX_SIZE)
1589 goto num_too_long;
1590 *q++ = ch;
1591 cinp();
1592 float_frac_parse:
1593 while (ch >= '0' && ch <= '9') {
1594 if (q >= token_buf + STRING_MAX_SIZE)
1595 goto num_too_long;
1596 *q++ = ch;
1597 cinp();
1600 if (ch == 'e' || ch == 'E') {
1601 if (q >= token_buf + STRING_MAX_SIZE)
1602 goto num_too_long;
1603 *q++ = ch;
1604 cinp();
1605 if (ch == '-' || ch == '+') {
1606 if (q >= token_buf + STRING_MAX_SIZE)
1607 goto num_too_long;
1608 *q++ = ch;
1609 cinp();
1611 if (ch < '0' || ch > '9')
1612 error("exponent digits expected");
1613 while (ch >= '0' && ch <= '9') {
1614 if (q >= token_buf + STRING_MAX_SIZE)
1615 goto num_too_long;
1616 *q++ = ch;
1617 cinp();
1620 *q = '\0';
1621 t = toup(ch);
1622 errno = 0;
1623 if (t == 'F') {
1624 cinp();
1625 tok = TOK_CFLOAT;
1626 tokc.f = strtof(token_buf, NULL);
1627 } else if (t == 'L') {
1628 cinp();
1629 tok = TOK_CLDOUBLE;
1630 tokc.ld = strtold(token_buf, NULL);
1631 } else {
1632 tok = TOK_CDOUBLE;
1633 tokc.d = strtod(token_buf, NULL);
1636 } else {
1637 unsigned long long n, n1;
1638 int lcount;
1640 /* integer number */
1641 *q = '\0';
1642 q = token_buf;
1643 if (b == 10 && *q == '0') {
1644 b = 8;
1645 q++;
1647 n = 0;
1648 while(1) {
1649 t = *q++;
1650 /* no need for checks except for base 10 / 8 errors */
1651 if (t == '\0') {
1652 break;
1653 } else if (t >= 'a') {
1654 t = t - 'a' + 10;
1655 } else if (t >= 'A') {
1656 t = t - 'A' + 10;
1657 } else {
1658 t = t - '0';
1659 if (t >= b)
1660 error("invalid digit");
1662 n1 = n;
1663 n = n * b + t;
1664 /* detect overflow */
1665 if (n < n1)
1666 error("integer constant overflow");
1669 /* XXX: not exactly ANSI compliant */
1670 if ((n & 0xffffffff00000000LL) != 0) {
1671 if ((n >> 63) != 0)
1672 tok = TOK_CULLONG;
1673 else
1674 tok = TOK_CLLONG;
1675 } else if (n > 0x7fffffff) {
1676 tok = TOK_CUINT;
1677 } else {
1678 tok = TOK_CINT;
1680 lcount = 0;
1681 for(;;) {
1682 t = toup(ch);
1683 if (t == 'L') {
1684 if (lcount >= 2)
1685 error("three 'l' in integer constant");
1686 lcount++;
1687 if (lcount == 2) {
1688 if (tok == TOK_CINT)
1689 tok = TOK_CLLONG;
1690 else if (tok == TOK_CUINT)
1691 tok = TOK_CULLONG;
1693 cinp();
1694 } else if (t == 'U') {
1695 if (tok == TOK_CINT)
1696 tok = TOK_CUINT;
1697 else if (tok == TOK_CLLONG)
1698 tok = TOK_CULLONG;
1699 cinp();
1700 } else {
1701 break;
1704 if (tok == TOK_CINT || tok == TOK_CUINT)
1705 tokc.ui = n;
1706 else
1707 tokc.ull = n;
1712 /* return next token without macro substitution */
1713 void next_nomacro1(void)
1715 int b;
1716 char *q;
1717 TokenSym *ts;
1719 /* skip spaces */
1720 while(1) {
1721 while (ch == '\n') {
1722 cinp();
1723 while (ch == ' ' || ch == 9)
1724 cinp();
1725 if (ch == '#') {
1726 /* preprocessor command if # at start of line after
1727 spaces */
1728 preprocess();
1731 if (ch != ' ' && ch != '\t' && ch != '\f')
1732 break;
1733 cinp();
1735 if (isid(ch)) {
1736 q = token_buf;
1737 *q++ = ch;
1738 cinp();
1739 if (q[-1] == 'L') {
1740 if (ch == '\'') {
1741 tok = TOK_LCHAR;
1742 goto char_const;
1744 if (ch == '\"') {
1745 tok = TOK_LSTR;
1746 goto str_const;
1749 while (isid(ch) || isnum(ch)) {
1750 if (q >= token_buf + STRING_MAX_SIZE)
1751 error("ident too long");
1752 *q++ = ch;
1753 cinp();
1755 *q = '\0';
1756 ts = tok_alloc(token_buf, q - token_buf);
1757 tok = ts->tok;
1758 } else if (isnum(ch) || ch == '.') {
1759 parse_number();
1760 } else if (ch == '\'') {
1761 tok = TOK_CCHAR;
1762 char_const:
1763 minp();
1764 tokc.i = getq();
1765 if (ch != '\'')
1766 expect("\'");
1767 minp();
1768 } else if (ch == '\"') {
1769 tok = TOK_STR;
1770 str_const:
1771 minp();
1772 q = token_buf;
1773 while (ch != '\"') {
1774 b = getq();
1775 if (ch == -1)
1776 error("unterminated string");
1777 if (q >= token_buf + STRING_MAX_SIZE)
1778 error("string too long");
1779 *q++ = b;
1781 *q = '\0';
1782 tokc.ts = tok_alloc(token_buf, q - token_buf);
1783 minp();
1784 } else {
1785 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
1786 /* two chars */
1787 tok = ch;
1788 cinp();
1789 while (*q) {
1790 if (*q == tok && q[1] == ch) {
1791 cinp();
1792 tok = q[2] & 0xff;
1793 /* three chars tests */
1794 if (tok == TOK_SHL || tok == TOK_SAR) {
1795 if (ch == '=') {
1796 tok = tok | 0x80;
1797 cinp();
1799 } else if (tok == TOK_DOTS) {
1800 if (ch != '.')
1801 error("parse error");
1802 cinp();
1804 return;
1806 q = q + 3;
1808 /* single char substitutions */
1809 if (tok == '<')
1810 tok = TOK_LT;
1811 else if (tok == '>')
1812 tok = TOK_GT;
1816 /* return next token without macro substitution. Can read input from
1817 macro_ptr buffer */
1818 void next_nomacro()
1820 if (macro_ptr) {
1821 tok = *macro_ptr;
1822 if (tok)
1823 tok = tok_get(&macro_ptr, &tokc);
1824 } else {
1825 next_nomacro1();
1829 /* substitute args in macro_str and return allocated string */
1830 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
1832 int *st, last_tok, t, notfirst, *str, len;
1833 Sym *s;
1834 TokenSym *ts;
1835 CValue cval;
1837 str = NULL;
1838 len = 0;
1839 last_tok = 0;
1840 while(1) {
1841 t = tok_get(&macro_str, &cval);
1842 if (!t)
1843 break;
1844 if (t == '#') {
1845 /* stringize */
1846 t = tok_get(&macro_str, &cval);
1847 if (!t)
1848 break;
1849 s = sym_find2(args, t);
1850 if (s) {
1851 token_buf[0] = '\0';
1852 st = (int *)s->c;
1853 /* XXX: buffer overflow */
1854 notfirst = 0;
1855 while (*st) {
1856 if (notfirst)
1857 strcat(token_buf, " ");
1858 t = tok_get(&st, &cval);
1859 strcat(token_buf, get_tok_str(t, &cval));
1860 notfirst = 1;
1862 #ifdef PP_DEBUG
1863 printf("stringize: %s\n", token_buf);
1864 #endif
1865 /* add string */
1866 ts = tok_alloc(token_buf, 0);
1867 cval.ts = ts;
1868 tok_add2(&str, &len, TOK_STR, &cval);
1869 } else {
1870 tok_add2(&str, &len, t, &cval);
1872 } else if (t >= TOK_IDENT) {
1873 s = sym_find2(args, t);
1874 if (s) {
1875 st = (int *)s->c;
1876 /* if '##' is present before or after , no arg substitution */
1877 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
1878 while (*st)
1879 tok_add(&str, &len, *st++);
1880 } else {
1881 macro_subst(&str, &len, nested_list, st);
1883 } else {
1884 tok_add(&str, &len, t);
1886 } else {
1887 tok_add2(&str, &len, t, &cval);
1889 last_tok = t;
1891 tok_add(&str, &len, 0);
1892 return str;
1895 /* handle the '##' operator */
1896 int *macro_twosharps(int *macro_str)
1898 TokenSym *ts;
1899 int *macro_str1, macro_str1_len, *macro_ptr1;
1900 int t;
1901 char *p;
1902 CValue cval;
1904 macro_str1 = NULL;
1905 macro_str1_len = 0;
1906 tok = 0;
1907 while (1) {
1908 next_nomacro();
1909 if (tok == 0)
1910 break;
1911 while (*macro_ptr == TOK_TWOSHARPS) {
1912 macro_ptr++;
1913 macro_ptr1 = macro_ptr;
1914 t = *macro_ptr;
1915 if (t) {
1916 t = tok_get(&macro_ptr, &cval);
1917 /* XXX: we handle only most common cases:
1918 ident + ident or ident + number */
1919 if (tok >= TOK_IDENT &&
1920 (t >= TOK_IDENT || t == TOK_CINT)) {
1921 /* XXX: buffer overflow */
1922 p = get_tok_str(tok, &tokc);
1923 strcpy(token_buf, p);
1924 p = get_tok_str(t, &cval);
1925 strcat(token_buf, p);
1926 ts = tok_alloc(token_buf, 0);
1927 tok = ts->tok; /* modify current token */
1928 } else {
1929 /* cannot merge tokens: skip '##' */
1930 macro_ptr = macro_ptr1;
1931 break;
1935 tok_add2(&macro_str1, &macro_str1_len, tok, &tokc);
1937 tok_add(&macro_str1, &macro_str1_len, 0);
1938 return macro_str1;
1943 /* do macro substitution of macro_str and add result to
1944 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1945 substituted. 'nested_list' is the list of all macros we got inside
1946 to avoid recursing. */
1947 void macro_subst(int **tok_str, int *tok_len,
1948 Sym **nested_list, int *macro_str)
1950 Sym *s, *args, *sa, *sa1;
1951 int *str, parlevel, len, *mstr, t, *saved_macro_ptr;
1952 int mstr_allocated, *macro_str1;
1953 CValue cval;
1955 saved_macro_ptr = macro_ptr;
1956 macro_ptr = macro_str;
1957 macro_str1 = NULL;
1958 if (macro_str) {
1959 /* first scan for '##' operator handling */
1960 macro_str1 = macro_twosharps(macro_str);
1961 macro_ptr = macro_str1;
1964 while (1) {
1965 next_nomacro();
1966 if (tok == 0)
1967 break;
1968 /* special macros */
1969 if (tok == TOK___LINE__) {
1970 cval.i = line_num;
1971 tok_add2(tok_str, tok_len, TOK_CINT, &cval);
1972 } else if (tok == TOK___FILE__) {
1973 cval.ts = tok_alloc(filename, 0);
1974 tok_add2(tok_str, tok_len, TOK_STR, &cval);
1975 } else if (tok == TOK___DATE__) {
1976 cval.ts = tok_alloc("Jan 1 1970", 0);
1977 tok_add2(tok_str, tok_len, TOK_STR, &cval);
1978 } else if (tok == TOK___TIME__) {
1979 cval.ts = tok_alloc("00:00:00", 0);
1980 tok_add2(tok_str, tok_len, TOK_STR, &cval);
1981 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
1982 /* if symbol is a macro, prepare substitution */
1983 /* if nested substitution, do nothing */
1984 if (sym_find2(*nested_list, tok))
1985 goto no_subst;
1986 mstr = (int *)s->c;
1987 mstr_allocated = 0;
1988 if (s->t == MACRO_FUNC) {
1989 /* NOTE: we do not use next_nomacro to avoid eating the
1990 next token. XXX: find better solution */
1991 if (macro_ptr) {
1992 t = *macro_ptr;
1993 } else {
1994 while (ch == ' ' || ch == '\t' || ch == '\n')
1995 cinp();
1996 t = ch;
1998 if (t != '(') /* no macro subst */
1999 goto no_subst;
2001 /* argument macro */
2002 next_nomacro();
2003 next_nomacro();
2004 args = NULL;
2005 sa = s->next;
2006 while (tok != ')' && sa) {
2007 len = 0;
2008 str = NULL;
2009 parlevel = 0;
2010 while ((parlevel > 0 ||
2011 (tok != ')' &&
2012 (tok != ',' ||
2013 sa->v == (TOK___VA_ARGS__ | SYM_FIELD)))) &&
2014 tok != -1) {
2015 if (tok == '(')
2016 parlevel++;
2017 else if (tok == ')')
2018 parlevel--;
2019 tok_add2(&str, &len, tok, &tokc);
2020 next_nomacro();
2022 tok_add(&str, &len, 0);
2023 sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
2024 if (tok != ',')
2025 break;
2026 next_nomacro();
2027 sa = sa->next;
2029 if (tok != ')')
2030 expect(")");
2031 /* now subst each arg */
2032 mstr = macro_arg_subst(nested_list, mstr, args);
2033 /* free memory */
2034 sa = args;
2035 while (sa) {
2036 sa1 = sa->prev;
2037 free((int *)sa->c);
2038 free(sa);
2039 sa = sa1;
2041 mstr_allocated = 1;
2043 sym_push2(nested_list, s->v, 0, 0);
2044 macro_subst(tok_str, tok_len, nested_list, mstr);
2045 /* pop nested defined symbol */
2046 sa1 = *nested_list;
2047 *nested_list = sa1->prev;
2048 free(sa1);
2049 if (mstr_allocated)
2050 free(mstr);
2051 } else {
2052 no_subst:
2053 /* no need to add if reading input stream */
2054 if (!macro_str)
2055 return;
2056 tok_add2(tok_str, tok_len, tok, &tokc);
2058 /* only replace one macro while parsing input stream */
2059 if (!macro_str)
2060 return;
2062 macro_ptr = saved_macro_ptr;
2063 if (macro_str1)
2064 free(macro_str1);
2067 /* return next token with macro substitution */
2068 void next(void)
2070 int len, *ptr;
2071 Sym *nested_list;
2073 /* special 'ungettok' case for label parsing */
2074 if (tok1) {
2075 tok = tok1;
2076 tokc = tok1c;
2077 tok1 = 0;
2078 } else {
2079 redo:
2080 if (!macro_ptr) {
2081 /* if not reading from macro substuted string, then try to substitute */
2082 len = 0;
2083 ptr = NULL;
2084 nested_list = NULL;
2085 macro_subst(&ptr, &len, &nested_list, NULL);
2086 if (ptr) {
2087 tok_add(&ptr, &len, 0);
2088 macro_ptr = ptr;
2089 macro_ptr_allocated = ptr;
2090 goto redo;
2092 if (tok == 0)
2093 goto redo;
2094 } else {
2095 next_nomacro();
2096 if (tok == 0) {
2097 /* end of macro string: free it */
2098 free(macro_ptr_allocated);
2099 macro_ptr = NULL;
2100 goto redo;
2104 #if defined(DEBUG)
2105 printf("token = %s\n", get_tok_str(tok, tokc));
2106 #endif
2109 void swap(int *p, int *q)
2111 int t;
2112 t = *p;
2113 *p = *q;
2114 *q = t;
2117 void vsetc(int t, int r, CValue *vc)
2119 if (vtop >= vstack + VSTACK_SIZE)
2120 error("memory full");
2121 /* cannot let cpu flags if other instruction are generated */
2122 /* XXX: VT_JMP test too ? */
2123 if ((vtop->r & VT_VALMASK) == VT_CMP)
2124 gv(RC_INT);
2125 vtop++;
2126 vtop->t = t;
2127 vtop->r = r;
2128 vtop->r2 = VT_CONST;
2129 vtop->c = *vc;
2132 /* push integer constant */
2133 void vpushi(int v)
2135 CValue cval;
2136 cval.i = v;
2137 vsetc(VT_INT, VT_CONST, &cval);
2140 void vset(int t, int r, int v)
2142 CValue cval;
2144 cval.i = v;
2145 vsetc(t, r, &cval);
2148 void vswap(void)
2150 SValue tmp;
2152 tmp = vtop[0];
2153 vtop[0] = vtop[-1];
2154 vtop[-1] = tmp;
2157 void vpushv(SValue *v)
2159 if (vtop >= vstack + VSTACK_SIZE)
2160 error("memory full");
2161 vtop++;
2162 *vtop = *v;
2165 void vdup(void)
2167 vpushv(vtop);
2170 /* save r to the memory stack, and mark it as being free */
2171 void save_reg(int r)
2173 int l, i, saved, t, size, align;
2174 SValue *p, sv;
2176 /* modify all stack values */
2177 saved = 0;
2178 l = 0;
2179 for(p=vstack;p<=vtop;p++) {
2180 i = p->r & VT_VALMASK;
2181 if ((p->r & VT_VALMASK) == r ||
2182 (p->r2 & VT_VALMASK) == r) {
2183 /* must save value on stack if not already done */
2184 if (!saved) {
2185 /* store register in the stack */
2186 t = p->t;
2187 if (!is_float(t) && (t & VT_BTYPE) != VT_LLONG)
2188 t = VT_INT;
2189 size = type_size(t, &align);
2190 loc = (loc - size) & -align;
2191 sv.t = t;
2192 sv.r = VT_LOCAL | VT_LVAL;
2193 sv.c.ul = loc;
2194 store(r, &sv);
2195 /* XXX: x86 specific: need to pop fp register ST0 if saved */
2196 if (r == REG_ST0) {
2197 o(0xd9dd); /* fstp %st(1) */
2199 /* special long long case */
2200 if ((p->t & VT_BTYPE) == VT_LLONG) {
2201 sv.c.ul += 4;
2202 store(p->r2, &sv);
2204 l = loc;
2205 saved = 1;
2207 /* mark that stack entry as being saved on the stack */
2208 if (p->r & VT_LVAL)
2209 t = VT_LLOCAL;
2210 else
2211 t = VT_LOCAL;
2212 p->r = VT_LVAL | t;
2213 p->r2 = VT_CONST;
2214 p->c.ul = l;
2219 /* find a free register of class 'rc'. If none, save one register */
2220 int get_reg(int rc)
2222 int r;
2223 SValue *p;
2225 /* find a free register */
2226 for(r=0;r<NB_REGS;r++) {
2227 if (reg_classes[r] & rc) {
2228 for(p=vstack;p<=vtop;p++) {
2229 if ((p->r & VT_VALMASK) == r ||
2230 (p->r2 & VT_VALMASK) == r)
2231 goto notfound;
2233 return r;
2235 notfound: ;
2238 /* no register left : free the first one on the stack (VERY
2239 IMPORTANT to start from the bottom to ensure that we don't
2240 spill registers used in gen_opi()) */
2241 for(p=vstack;p<=vtop;p++) {
2242 r = p->r & VT_VALMASK;
2243 if (r < VT_CONST && (reg_classes[r] & rc)) {
2244 save_reg(r);
2245 break;
2248 return r;
2251 void save_regs(void)
2253 int r;
2254 SValue *p;
2256 for(p=vstack;p<=vtop;p++) {
2257 r = p->r & VT_VALMASK;
2258 if (r < VT_CONST) {
2259 save_reg(r);
2264 /* move register 's' to 'r', and flush previous value of r to memory
2265 if needed */
2266 void move_reg(int r, int s)
2268 SValue sv;
2270 if (r != s) {
2271 save_reg(r);
2272 sv.t = VT_INT;
2273 sv.r = s;
2274 sv.c.ul = 0;
2275 load(r, &sv);
2279 /* store vtop a register belonging to class 'rc'. lvalues are
2280 converted to values. Cannot be used if cannot be converted to
2281 register value (such as structures). */
2282 int gv(int rc)
2284 int r, r2, rc2, bit_pos, bit_size, size, align, i, data_offset;
2285 unsigned long long ll;
2287 /* NOTE: get_reg can modify vstack[] */
2288 if (vtop->t & VT_BITFIELD) {
2289 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
2290 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2291 /* remove bit field info to avoid loops */
2292 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2293 /* generate shifts */
2294 vpushi(32 - (bit_pos + bit_size));
2295 gen_op(TOK_SHL);
2296 vpushi(32 - bit_size);
2297 /* NOTE: transformed to SHR if unsigned */
2298 gen_op(TOK_SAR);
2299 r = gv(rc);
2300 } else {
2301 if (is_float(vtop->t) &&
2302 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2303 /* CPUs usually cannot use float constants, so we store them
2304 generically in data segment */
2305 size = type_size(vtop->t, &align);
2306 data_offset = (int)data_section->data_ptr;
2307 data_offset = (data_offset + align - 1) & -align;
2308 /* XXX: not portable yet */
2309 size = size >> 2;
2310 for(i=0;i<size;i++)
2311 ((int *)data_offset)[i] = vtop->c.tab[i];
2312 vtop->r |= VT_LVAL;
2313 vtop->c.ul = data_offset;
2314 data_offset += size << 2;
2315 data_section->data_ptr = (unsigned char *)data_offset;
2317 r = vtop->r & VT_VALMASK;
2318 /* need to reload if:
2319 - constant
2320 - lvalue (need to dereference pointer)
2321 - already a register, but not in the right class */
2322 if (r >= VT_CONST ||
2323 (vtop->r & VT_LVAL) ||
2324 !(reg_classes[r] & rc) ||
2325 ((vtop->t & VT_BTYPE) == VT_LLONG &&
2326 !(reg_classes[vtop->r2] & rc))) {
2327 r = get_reg(rc);
2328 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
2329 /* two register type load : expand to two words
2330 temporarily */
2331 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2332 /* load constant */
2333 ll = vtop->c.ull;
2334 vtop->c.ui = ll; /* first word */
2335 load(r, vtop);
2336 vtop->r = r; /* save register value */
2337 vpushi(ll >> 32); /* second word */
2338 } else if (r >= VT_CONST ||
2339 (vtop->r & VT_LVAL)) {
2340 /* load from memory */
2341 load(r, vtop);
2342 vdup();
2343 vtop[-1].r = r; /* save register value */
2344 /* increment pointer to get second word */
2345 vtop->t = VT_INT;
2346 vtop->r &= ~VT_LVAL;
2347 vpushi(4);
2348 gen_op('+');
2349 vtop->r |= VT_LVAL;
2350 } else {
2351 /* move registers */
2352 load(r, vtop);
2353 vdup();
2354 vtop[-1].r = r; /* save register value */
2355 vtop->r = vtop[-1].r2;
2357 /* allocate second register */
2358 rc2 = RC_INT;
2359 if (rc == RC_IRET)
2360 rc2 = RC_LRET;
2361 r2 = get_reg(rc2);
2362 load(r2, vtop);
2363 vpop();
2364 /* write second register */
2365 vtop->r2 = r2;
2366 } else {
2367 /* one register type load */
2368 load(r, vtop);
2371 vtop->r = r;
2373 return r;
2376 /* expand long long on stack in two int registers */
2377 void lexpand(void)
2379 int u;
2381 u = vtop->t & VT_UNSIGNED;
2382 gv(RC_INT);
2383 vdup();
2384 vtop[0].r = vtop[-1].r2;
2385 vtop[0].r2 = VT_CONST;
2386 vtop[-1].r2 = VT_CONST;
2387 vtop[0].t = VT_INT | u;
2388 vtop[-1].t = VT_INT | u;
2391 /* build a long long from two ints */
2392 void lbuild(int t)
2394 vswap();
2395 gv(RC_INT);
2396 vswap();
2397 gv(RC_INT);
2398 vtop[-1].r2 = vtop[0].r;
2399 vtop[-1].t = t;
2400 vpop();
2403 /* rotate n first stack elements to the bottom */
2404 void vrotb(int n)
2406 int i;
2407 SValue tmp;
2409 tmp = vtop[-n + 1];
2410 for(i=-n+1;i!=0;i++)
2411 vtop[i] = vtop[i+1];
2412 vtop[0] = tmp;
2415 /* pop stack value */
2416 void vpop(void)
2418 /* for x86, we need to pop the FP stack */
2419 if ((vtop->r & VT_VALMASK) == REG_ST0) {
2420 o(0xd9dd); /* fstp %st(1) */
2422 vtop--;
2425 /* convert stack entry to register and duplicate its value in another
2426 register */
2427 void gv_dup(void)
2429 int rc, t, r, r1;
2430 SValue sv;
2432 t = vtop->t;
2433 if ((t & VT_BTYPE) == VT_LLONG) {
2434 lexpand();
2435 gv_dup();
2436 vswap();
2437 vrotb(3);
2438 gv_dup();
2439 vrotb(4);
2440 /* stack: H L L1 H1 */
2441 lbuild(t);
2442 vrotb(3);
2443 vrotb(3);
2444 vswap();
2445 lbuild(t);
2446 vswap();
2447 } else {
2448 /* duplicate value */
2449 rc = RC_INT;
2450 sv.t = VT_INT;
2451 if (is_float(t)) {
2452 rc = RC_FLOAT;
2453 sv.t = t;
2455 r = gv(rc);
2456 r1 = get_reg(rc);
2457 sv.r = r;
2458 sv.c.ul = 0;
2459 load(r1, &sv); /* move r to r1 */
2460 vdup();
2461 /* duplicates value */
2462 vtop->r = r1;
2466 /* generate CPU independent (unsigned) long long operations */
2467 void gen_opl(int op)
2469 int t, a, b, op1, c, i;
2470 void *func;
2471 GFuncContext gf;
2472 SValue tmp;
2474 switch(op) {
2475 case '/':
2476 case TOK_PDIV:
2477 func = __divll;
2478 goto gen_func;
2479 case TOK_UDIV:
2480 func = __divull;
2481 goto gen_func;
2482 case '%':
2483 func = __modll;
2484 goto gen_func;
2485 case TOK_UMOD:
2486 func = __modull;
2487 gen_func:
2488 /* call generic long long function */
2489 gfunc_start(&gf);
2490 gfunc_param(&gf);
2491 gfunc_param(&gf);
2492 vpushi((int)func);
2493 gfunc_call(&gf);
2494 vpushi(0);
2495 vtop->r = REG_IRET;
2496 vtop->r2 = REG_LRET;
2497 break;
2498 case '^':
2499 case '&':
2500 case '|':
2501 case '*':
2502 case '+':
2503 case '-':
2504 t = vtop->t;
2505 vswap();
2506 lexpand();
2507 vrotb(3);
2508 lexpand();
2509 /* stack: L1 H1 L2 H2 */
2510 tmp = vtop[0];
2511 vtop[0] = vtop[-3];
2512 vtop[-3] = tmp;
2513 tmp = vtop[-2];
2514 vtop[-2] = vtop[-3];
2515 vtop[-3] = tmp;
2516 vswap();
2517 /* stack: H1 H2 L1 L2 */
2518 if (op == '*') {
2519 vpushv(vtop - 1);
2520 vpushv(vtop - 1);
2521 gen_op(TOK_UMULL);
2522 lexpand();
2523 /* stack: H1 H2 L1 L2 ML MH */
2524 for(i=0;i<4;i++)
2525 vrotb(6);
2526 /* stack: ML MH H1 H2 L1 L2 */
2527 tmp = vtop[0];
2528 vtop[0] = vtop[-2];
2529 vtop[-2] = tmp;
2530 /* stack: ML MH H1 L2 H2 L1 */
2531 gen_op('*');
2532 vrotb(3);
2533 vrotb(3);
2534 gen_op('*');
2535 /* stack: ML MH M1 M2 */
2536 gen_op('+');
2537 gen_op('+');
2538 } else if (op == '+' || op == '-') {
2539 /* XXX: add non carry method too (for MIPS ?) */
2540 if (op == '+')
2541 op1 = TOK_ADDC1;
2542 else
2543 op1 = TOK_SUBC1;
2544 gen_op(op1);
2545 /* stack: H1 H2 (L1 op L2) */
2546 vrotb(3);
2547 vrotb(3);
2548 gen_op(op1 + 1); /* TOK_xxxC2 */
2549 } else {
2550 gen_op(op);
2551 /* stack: H1 H2 (L1 op L2) */
2552 vrotb(3);
2553 vrotb(3);
2554 /* stack: (L1 op L2) H1 H2 */
2555 gen_op(op);
2556 /* stack: (L1 op L2) (H1 op H2) */
2558 /* stack: L H */
2559 lbuild(t);
2560 break;
2561 case TOK_SAR:
2562 case TOK_SHR:
2563 case TOK_SHL:
2564 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
2565 t = vtop[-1].t;
2566 vswap();
2567 lexpand();
2568 vrotb(3);
2569 /* stack: L H shift */
2570 c = (int)vtop->c.i;
2571 /* constant: simpler */
2572 /* NOTE: all comments are for SHL. the other cases are
2573 done by swaping words */
2574 vpop();
2575 if (op != TOK_SHL)
2576 vswap();
2577 if (c >= 32) {
2578 /* stack: L H */
2579 vpop();
2580 if (c > 32) {
2581 vpushi(c - 32);
2582 gen_op(op);
2584 if (op != TOK_SAR) {
2585 vpushi(0);
2586 } else {
2587 gv_dup();
2588 vpushi(31);
2589 gen_op(TOK_SAR);
2591 vswap();
2592 } else {
2593 vswap();
2594 gv_dup();
2595 /* stack: H L L */
2596 vpushi(c);
2597 gen_op(op);
2598 vswap();
2599 vpushi(32 - c);
2600 if (op == TOK_SHL)
2601 gen_op(TOK_SHR);
2602 else
2603 gen_op(TOK_SHL);
2604 vrotb(3);
2605 /* stack: L L H */
2606 vpushi(c);
2607 gen_op(op);
2608 gen_op('|');
2610 if (op != TOK_SHL)
2611 vswap();
2612 lbuild(t);
2613 } else {
2614 /* XXX: should provide a faster fallback on x86 ? */
2615 switch(op) {
2616 case TOK_SAR:
2617 func = __sardi3;
2618 goto gen_func;
2619 case TOK_SHR:
2620 func = __shrdi3;
2621 goto gen_func;
2622 case TOK_SHL:
2623 func = __shldi3;
2624 goto gen_func;
2627 break;
2628 default:
2629 /* compare operations */
2630 t = vtop->t;
2631 vswap();
2632 lexpand();
2633 vrotb(3);
2634 lexpand();
2635 /* stack: L1 H1 L2 H2 */
2636 tmp = vtop[-1];
2637 vtop[-1] = vtop[-2];
2638 vtop[-2] = tmp;
2639 /* stack: L1 L2 H1 H2 */
2640 /* compare high */
2641 op1 = op;
2642 /* when values are equal, we need to compare low words. since
2643 the jump is inverted, we invert the test too. */
2644 if (op1 == TOK_LT)
2645 op1 = TOK_LE;
2646 else if (op1 == TOK_GT)
2647 op1 = TOK_GE;
2648 else if (op1 == TOK_ULT)
2649 op1 = TOK_ULE;
2650 else if (op1 == TOK_UGT)
2651 op1 = TOK_UGE;
2652 a = 0;
2653 b = 0;
2654 gen_op(op1);
2655 if (op1 != TOK_NE) {
2656 a = gtst(1, 0);
2658 if (op != TOK_EQ) {
2659 /* generate non equal test */
2660 /* XXX: NOT PORTABLE yet */
2661 if (a == 0)
2662 b = gtst(0, 0);
2663 else
2664 b = psym(0x850f, 0);
2666 /* compare low */
2667 gen_op(op);
2668 a = gtst(1, a);
2669 gsym(b);
2670 vset(VT_INT, VT_JMPI, a);
2671 break;
2675 /* handle constant optimizations and various machine independant opt */
2676 void gen_opc(int op)
2678 int fc, c1, c2, n;
2679 SValue *v1, *v2;
2681 v1 = vtop - 1;
2682 v2 = vtop;
2683 /* currently, we cannot do computations with forward symbols */
2684 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2685 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2686 if (c1 && c2) {
2687 fc = v2->c.i;
2688 switch(op) {
2689 case '+': v1->c.i += fc; break;
2690 case '-': v1->c.i -= fc; break;
2691 case '&': v1->c.i &= fc; break;
2692 case '^': v1->c.i ^= fc; break;
2693 case '|': v1->c.i |= fc; break;
2694 case '*': v1->c.i *= fc; break;
2695 case TOK_PDIV:
2696 case '/': v1->c.i /= fc; break; /* XXX: zero case ? */
2697 case '%': v1->c.i %= fc; break; /* XXX: zero case ? */
2698 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break; /* XXX: zero case ? */
2699 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break; /* XXX: zero case ? */
2700 case TOK_SHL: v1->c.i <<= fc; break;
2701 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
2702 case TOK_SAR: v1->c.i >>= fc; break;
2703 /* tests */
2704 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
2705 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
2706 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
2707 case TOK_NE: v1->c.i = v1->c.i != fc; break;
2708 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
2709 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
2710 case TOK_LT: v1->c.i = v1->c.i < fc; break;
2711 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
2712 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
2713 case TOK_GT: v1->c.i = v1->c.i > fc; break;
2714 /* logical */
2715 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
2716 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
2717 default:
2718 goto general_case;
2720 vtop--;
2721 } else {
2722 /* if commutative ops, put c2 as constant */
2723 if (c1 && (op == '+' || op == '&' || op == '^' ||
2724 op == '|' || op == '*')) {
2725 vswap();
2726 swap(&c1, &c2);
2728 fc = vtop->c.i;
2729 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
2730 op == TOK_PDIV) &&
2731 fc == 1) ||
2732 ((op == '+' || op == '-' || op == '|' || op == '^' ||
2733 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
2734 fc == 0) ||
2735 (op == '&' &&
2736 fc == -1))) {
2737 /* nothing to do */
2738 vtop--;
2739 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
2740 /* try to use shifts instead of muls or divs */
2741 if (fc > 0 && (fc & (fc - 1)) == 0) {
2742 n = -1;
2743 while (fc) {
2744 fc >>= 1;
2745 n++;
2747 vtop->c.i = n;
2748 if (op == '*')
2749 op = TOK_SHL;
2750 else if (op == TOK_PDIV)
2751 op = TOK_SAR;
2752 else
2753 op = TOK_SHR;
2755 goto general_case;
2756 } else {
2757 general_case:
2758 /* call low level op generator */
2759 /* XXX: remove explicit registers */
2760 gen_opi(op);
2765 int pointed_size(int t)
2767 return type_size(pointed_type(t), &t);
2770 #if 0
2771 void check_pointer_types(SValue *p1, SValue *p2)
2773 char buf1[256], buf2[256];
2774 int t1, t2;
2775 t1 = p1->t;
2776 t2 = p2->t;
2777 if (!is_compatible_types(t1, t2)) {
2778 type_to_str(buf1, sizeof(buf1), t1, NULL);
2779 type_to_str(buf2, sizeof(buf2), t2, NULL);
2780 error("incompatible pointers '%s' and '%s'", buf1, buf2);
2783 #endif
2785 /* generic gen_op: handles types problems */
2786 void gen_op(int op)
2788 int u, t1, t2, bt1, bt2, t;
2790 t1 = vtop[-1].t;
2791 t2 = vtop[0].t;
2792 bt1 = t1 & VT_BTYPE;
2793 bt2 = t2 & VT_BTYPE;
2795 if (bt1 == VT_PTR || bt2 == VT_PTR) {
2796 /* at least one operand is a pointer */
2797 /* relationnal op: must be both pointers */
2798 if (op >= TOK_ULT && op <= TOK_GT) {
2799 // check_pointer_types(vtop, vtop - 1);
2800 /* pointers are handled are unsigned */
2801 t = VT_INT | VT_UNSIGNED;
2802 goto std_op;
2804 /* if both pointers, then it must be the '-' op */
2805 if ((t1 & VT_BTYPE) == VT_PTR &&
2806 (t2 & VT_BTYPE) == VT_PTR) {
2807 if (op != '-')
2808 error("cannot use pointers here");
2809 // check_pointer_types(vtop - 1, vtop);
2810 /* XXX: check that types are compatible */
2811 u = pointed_size(t1);
2812 gen_opc(op);
2813 /* set to integer type */
2814 vtop->t = VT_INT;
2815 vpushi(u);
2816 gen_op(TOK_PDIV);
2817 } else {
2818 /* exactly one pointer : must be '+' or '-'. */
2819 if (op != '-' && op != '+')
2820 error("cannot use pointers here");
2821 /* Put pointer as first operand */
2822 if ((t2 & VT_BTYPE) == VT_PTR) {
2823 vswap();
2824 swap(&t1, &t2);
2826 /* XXX: cast to int ? (long long case) */
2827 vpushi(pointed_size(vtop[-1].t));
2828 gen_op('*');
2829 gen_opc(op);
2830 /* put again type if gen_opc() swaped operands */
2831 vtop->t = t1;
2833 } else if (is_float(bt1) || is_float(bt2)) {
2834 /* compute bigger type and do implicit casts */
2835 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
2836 t = VT_LDOUBLE;
2837 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
2838 t = VT_DOUBLE;
2839 } else {
2840 t = VT_FLOAT;
2842 /* floats can only be used for a few operations */
2843 if (op != '+' && op != '-' && op != '*' && op != '/' &&
2844 (op < TOK_ULT || op > TOK_GT))
2845 error("invalid operands for binary operation");
2846 goto std_op;
2847 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
2848 /* cast to biggest op */
2849 t = VT_LLONG;
2850 /* convert to unsigned if it does not fit in a long long */
2851 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
2852 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
2853 t |= VT_UNSIGNED;
2854 goto std_op;
2855 } else {
2856 /* integer operations */
2857 t = VT_INT;
2858 /* convert to unsigned if it does not fit in an integer */
2859 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
2860 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
2861 t |= VT_UNSIGNED;
2862 std_op:
2863 /* XXX: currently, some unsigned operations are explicit, so
2864 we modify them here */
2865 if (t & VT_UNSIGNED) {
2866 if (op == TOK_SAR)
2867 op = TOK_SHR;
2868 else if (op == '/')
2869 op = TOK_UDIV;
2870 else if (op == '%')
2871 op = TOK_UMOD;
2872 else if (op == TOK_LT)
2873 op = TOK_ULT;
2874 else if (op == TOK_GT)
2875 op = TOK_UGT;
2876 else if (op == TOK_LE)
2877 op = TOK_ULE;
2878 else if (op == TOK_GE)
2879 op = TOK_UGE;
2881 vswap();
2882 gen_cast(t);
2883 vswap();
2884 /* special case for shifts and long long: we keep the shift as
2885 an integer */
2886 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
2887 gen_cast(VT_INT);
2888 else
2889 gen_cast(t);
2890 if (is_float(t))
2891 gen_opf(op);
2892 else if ((t & VT_BTYPE) == VT_LLONG)
2893 gen_opl(op);
2894 else
2895 gen_opc(op);
2896 if (op >= TOK_ULT && op <= TOK_GT) {
2897 /* relationnal op: the result is an int */
2898 vtop->t = VT_INT;
2899 } else {
2900 vtop->t = t;
2905 /* generic itof for unsigned long long case */
2906 void gen_cvt_itof1(int t)
2908 GFuncContext gf;
2910 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
2911 (VT_LLONG | VT_UNSIGNED)) {
2913 gfunc_start(&gf);
2914 gfunc_param(&gf);
2915 if (t == VT_FLOAT)
2916 vpushi((int)&__ulltof);
2917 else if (t == VT_DOUBLE)
2918 vpushi((int)&__ulltod);
2919 else
2920 vpushi((int)&__ulltold);
2921 gfunc_call(&gf);
2922 vpushi(0);
2923 vtop->r = REG_FRET;
2924 } else {
2925 gen_cvt_itof(t);
2929 /* generic ftoi for unsigned long long case */
2930 void gen_cvt_ftoi1(int t)
2932 GFuncContext gf;
2933 int st;
2935 if (t == (VT_LLONG | VT_UNSIGNED)) {
2936 /* not handled natively */
2937 gfunc_start(&gf);
2938 st = vtop->t & VT_BTYPE;
2939 gfunc_param(&gf);
2940 if (st == VT_FLOAT)
2941 vpushi((int)&__ftoull);
2942 else if (st == VT_DOUBLE)
2943 vpushi((int)&__dtoull);
2944 else
2945 vpushi((int)&__ldtoull);
2946 gfunc_call(&gf);
2947 vpushi(0);
2948 vtop->r = REG_IRET;
2949 vtop->r2 = REG_LRET;
2950 } else {
2951 gen_cvt_ftoi(t);
2955 /* force char or short cast */
2956 void force_charshort_cast(int t)
2958 int bits, dbt;
2959 dbt = t & VT_BTYPE;
2960 /* XXX: add optimization if lvalue : just change type and offset */
2961 if (dbt == VT_BYTE)
2962 bits = 8;
2963 else
2964 bits = 16;
2965 if (t & VT_UNSIGNED) {
2966 vpushi((1 << bits) - 1);
2967 gen_op('&');
2968 } else {
2969 bits = 32 - bits;
2970 vpushi(bits);
2971 gen_op(TOK_SHL);
2972 vpushi(bits);
2973 gen_op(TOK_SAR);
2977 /* cast 'vtop' to 't' type */
2978 void gen_cast(int t)
2980 int sbt, dbt, sf, df, c, st1, dt1;
2982 /* special delayed cast for char/short */
2983 /* XXX: in some cases (multiple cascaded casts), it may still
2984 be incorrect */
2985 if (vtop->r & VT_MUSTCAST) {
2986 vtop->r &= ~VT_MUSTCAST;
2987 force_charshort_cast(vtop->t);
2990 dbt = t & VT_BTYPE;
2991 sbt = vtop->t & VT_BTYPE;
2993 if (sbt != dbt) {
2994 sf = is_float(sbt);
2995 df = is_float(dbt);
2996 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2997 if (sf && df) {
2998 /* convert from fp to fp */
2999 if (c) {
3000 /* constant case: we can do it now */
3001 /* XXX: in ISOC, cannot do it if error in convert */
3002 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
3003 vtop->c.f = (float)vtop->c.d;
3004 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
3005 vtop->c.f = (float)vtop->c.ld;
3006 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
3007 vtop->c.d = (double)vtop->c.f;
3008 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
3009 vtop->c.d = (double)vtop->c.ld;
3010 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
3011 vtop->c.ld = (long double)vtop->c.f;
3012 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
3013 vtop->c.ld = (long double)vtop->c.d;
3014 } else {
3015 /* non constant case: generate code */
3016 gen_cvt_ftof(dbt);
3018 } else if (df) {
3019 /* convert int to fp */
3020 st1 = vtop->t & (VT_BTYPE | VT_UNSIGNED);
3021 if (c) {
3022 switch(st1) {
3023 case VT_LLONG | VT_UNSIGNED:
3024 case VT_LLONG:
3025 /* XXX: add const cases for long long */
3026 goto do_itof;
3027 case VT_INT | VT_UNSIGNED:
3028 switch(dbt) {
3029 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
3030 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
3031 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
3033 break;
3034 default:
3035 switch(dbt) {
3036 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
3037 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
3038 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
3040 break;
3042 } else {
3043 do_itof:
3044 gen_cvt_itof1(dbt);
3046 } else if (sf) {
3047 /* convert fp to int */
3048 dt1 = t & (VT_BTYPE | VT_UNSIGNED);
3049 /* we handle char/short/etc... with generic code */
3050 if (dt1 != (VT_INT | VT_UNSIGNED) &&
3051 dt1 != (VT_LLONG | VT_UNSIGNED) &&
3052 dt1 != VT_LLONG)
3053 dt1 = VT_INT;
3054 if (c) {
3055 switch(dt1) {
3056 case VT_LLONG | VT_UNSIGNED:
3057 case VT_LLONG:
3058 /* XXX: add const cases for long long */
3059 goto do_ftoi;
3060 case VT_INT | VT_UNSIGNED:
3061 switch(sbt) {
3062 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
3063 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3064 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3066 break;
3067 default:
3068 /* int case */
3069 switch(sbt) {
3070 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
3071 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
3072 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
3074 break;
3076 } else {
3077 do_ftoi:
3078 gen_cvt_ftoi1(dt1);
3080 if (dt1 == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dt1) {
3081 /* additionnal cast for char/short/bool... */
3082 vtop->t = dt1;
3083 gen_cast(t);
3085 } else if (dbt == VT_LLONG) {
3086 /* scalar to long long */
3087 if (c) {
3088 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3089 vtop->c.ll = vtop->c.ui;
3090 else
3091 vtop->c.ll = vtop->c.i;
3092 } else {
3093 /* machine independant conversion */
3094 gv(RC_INT);
3095 /* generate high word */
3096 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) {
3097 vpushi(0);
3098 gv(RC_INT);
3099 } else {
3100 gv_dup();
3101 vpushi(31);
3102 gen_op(TOK_SAR);
3104 /* patch second register */
3105 vtop[-1].r2 = vtop->r;
3106 vpop();
3108 } else if (dbt == VT_BOOL) {
3109 /* scalar to bool */
3110 vpushi(0);
3111 gen_op(TOK_NE);
3112 } else if (dbt == VT_BYTE || dbt == VT_SHORT) {
3113 force_charshort_cast(t);
3114 } else if (dbt == VT_INT) {
3115 /* scalar to int */
3116 if (sbt == VT_LLONG) {
3117 /* from long long: just take low order word */
3118 lexpand();
3119 vpop();
3120 } else if (vtop->r & VT_LVAL) {
3121 /* if lvalue and single word type, nothing to do (XXX:
3122 maybe incorrect for sizeof op) */
3123 goto no_cast;
3127 vtop->t = t;
3128 no_cast: ;
3131 /* return type size. Put alignment at 'a' */
3132 int type_size(int t, int *a)
3134 Sym *s;
3135 int bt;
3137 bt = t & VT_BTYPE;
3138 if (bt == VT_STRUCT) {
3139 /* struct/union */
3140 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3141 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
3142 return s->c;
3143 } else if (bt == VT_PTR) {
3144 if (t & VT_ARRAY) {
3145 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3146 return type_size(s->t, a) * s->c;
3147 } else {
3148 *a = PTR_SIZE;
3149 return PTR_SIZE;
3151 } else if (bt == VT_LDOUBLE) {
3152 *a = LDOUBLE_ALIGN;
3153 return LDOUBLE_SIZE;
3154 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
3155 *a = 8;
3156 return 8;
3157 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
3158 *a = 4;
3159 return 4;
3160 } else if (bt == VT_SHORT) {
3161 *a = 2;
3162 return 2;
3163 } else {
3164 /* char, void, function, _Bool */
3165 *a = 1;
3166 return 1;
3170 /* return the pointed type of t */
3171 int pointed_type(int t)
3173 Sym *s;
3174 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3175 return s->t | (t & ~VT_TYPE);
3178 int mk_pointer(int t)
3180 int p;
3181 p = anon_sym++;
3182 sym_push(p, t, 0, -1);
3183 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
3186 int is_compatible_types(int t1, int t2)
3188 Sym *s1, *s2;
3189 int bt1, bt2;
3191 t1 &= VT_TYPE;
3192 t2 &= VT_TYPE;
3193 bt1 = t1 & VT_BTYPE;
3194 bt2 = t2 & VT_BTYPE;
3195 if (bt1 == VT_PTR) {
3196 t1 = pointed_type(t1);
3197 /* if function, then convert implicitely to function pointer */
3198 if (bt2 != VT_FUNC) {
3199 if (bt2 != VT_PTR)
3200 return 0;
3201 t2 = pointed_type(t2);
3203 /* void matches everything */
3204 t1 &= VT_TYPE;
3205 t2 &= VT_TYPE;
3206 if (t1 == VT_VOID || t2 == VT_VOID)
3207 return 1;
3208 return is_compatible_types(t1, t2);
3209 } else if (bt1 == VT_STRUCT) {
3210 return (t2 == t1);
3211 } else if (bt1 == VT_FUNC) {
3212 if (bt2 != VT_FUNC)
3213 return 0;
3214 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
3215 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
3216 if (!is_compatible_types(s1->t, s2->t))
3217 return 0;
3218 /* XXX: not complete */
3219 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
3220 return 1;
3221 if (s1->c != s2->c)
3222 return 0;
3223 while (s1 != NULL) {
3224 if (s2 == NULL)
3225 return 0;
3226 if (!is_compatible_types(s1->t, s2->t))
3227 return 0;
3228 s1 = s1->next;
3229 s2 = s2->next;
3231 if (s2)
3232 return 0;
3233 return 1;
3234 } else {
3235 /* XXX: not complete */
3236 return 1;
3240 int check_assign_types(int t1, int t2)
3242 t1 &= VT_TYPE;
3243 t2 &= VT_TYPE;
3244 if ((t1 & VT_BTYPE) == VT_PTR &&
3245 (t2 & VT_BTYPE) == VT_FUNC) {
3246 return is_compatible_types(pointed_type(t1), t2);
3247 } else {
3248 return is_compatible_types(t1, t2);
3252 /* print a type. If 'varstr' is not NULL, then the variable is also
3253 printed in the type */
3254 /* XXX: union */
3255 /* XXX: add array and function pointers */
3256 /* XXX: buffer overflows */
3257 void type_to_str(char *buf, int buf_size,
3258 int t, const char *varstr)
3260 int bt, v;
3261 Sym *s, *sa;
3262 char buf1[256];
3264 t = t & VT_TYPE;
3265 bt = t & VT_BTYPE;
3266 buf[0] = '\0';
3267 if (t & VT_UNSIGNED)
3268 strcat(buf, "unsigned ");
3269 switch(bt) {
3270 case VT_VOID:
3271 strcat(buf, "void");
3272 break;
3273 case VT_BOOL:
3274 strcat(buf, "_Bool");
3275 break;
3276 case VT_BYTE:
3277 strcat(buf, "char");
3278 break;
3279 case VT_SHORT:
3280 strcat(buf, "short");
3281 break;
3282 case VT_INT:
3283 strcat(buf, "int");
3284 break;
3285 case VT_LONG:
3286 strcat(buf, "long");
3287 break;
3288 case VT_LLONG:
3289 strcat(buf, "long long");
3290 break;
3291 case VT_FLOAT:
3292 strcat(buf, "float");
3293 break;
3294 case VT_DOUBLE:
3295 strcat(buf, "double");
3296 break;
3297 case VT_LDOUBLE:
3298 strcat(buf, "long double");
3299 break;
3300 case VT_ENUM:
3301 case VT_STRUCT:
3302 if (bt == VT_STRUCT)
3303 strcat(buf, "struct ");
3304 else
3305 strcat(buf, "enum ");
3306 v = (unsigned)t >> VT_STRUCT_SHIFT;
3307 if (v >= SYM_FIRST_ANOM)
3308 strcat(buf, "<anonymous>");
3309 else
3310 strcat(buf, get_tok_str(v, NULL));
3311 break;
3312 case VT_FUNC:
3313 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3314 type_to_str(buf, buf_size, s->t, varstr);
3315 strcat(buf, "(");
3316 sa = s->next;
3317 while (sa != NULL) {
3318 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
3319 strcat(buf, buf1);
3320 sa = sa->next;
3321 if (sa)
3322 strcat(buf, ", ");
3324 strcat(buf, ")");
3325 goto no_var;
3326 case VT_PTR:
3327 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3328 strcpy(buf1, "*");
3329 if (varstr)
3330 strcat(buf1, varstr);
3331 type_to_str(buf, buf_size, s->t, buf1);
3332 goto no_var;
3334 if (varstr) {
3335 strcat(buf, " ");
3336 strcat(buf, varstr);
3338 no_var: ;
3343 /* verify type compatibility to store vtop in 'st' type, and generate
3344 casts if needed. */
3345 void gen_assign_cast(int dt)
3347 int st;
3348 char buf1[256], buf2[256];
3350 st = vtop->t; /* destination type */
3351 if (!check_assign_types(dt, st)) {
3352 type_to_str(buf1, sizeof(buf1), st, NULL);
3353 type_to_str(buf2, sizeof(buf2), dt, NULL);
3354 error("cannot cast '%s' to '%s'", buf1, buf2);
3356 gen_cast(dt);
3360 /* store vtop in lvalue pushed on stack */
3361 void vstore(void)
3363 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
3364 GFuncContext gf;
3366 ft = vtop[-1].t;
3367 sbt = vtop->t & VT_BTYPE;
3368 dbt = ft & VT_BTYPE;
3369 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
3370 (sbt == VT_INT && dbt == VT_SHORT)) {
3371 /* optimize char/short casts */
3372 delayed_cast = VT_MUSTCAST;
3373 vtop->t = ft & VT_TYPE;
3374 } else {
3375 delayed_cast = 0;
3376 gen_assign_cast(ft & VT_TYPE);
3379 if (sbt == VT_STRUCT) {
3380 /* if structure, only generate pointer */
3381 /* structure assignment : generate memcpy */
3382 /* XXX: optimize if small size */
3384 vdup();
3385 gfunc_start(&gf);
3386 /* type size */
3387 size = type_size(vtop->t, &align);
3388 vpushi(size);
3389 gfunc_param(&gf);
3390 /* source */
3391 vtop->t = VT_INT;
3392 vtop->r &= ~VT_LVAL;
3393 gfunc_param(&gf);
3394 /* destination */
3395 vswap();
3396 vtop->t = VT_INT;
3397 vtop->r &= ~VT_LVAL;
3398 gfunc_param(&gf);
3400 save_regs();
3401 vpushi((int)&memcpy);
3402 gfunc_call(&gf);
3403 /* leave source on stack */
3404 } else if (ft & VT_BITFIELD) {
3405 /* bitfield store handling */
3406 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
3407 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3408 /* remove bit field info to avoid loops */
3409 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3411 /* duplicate destination */
3412 vdup();
3413 vtop[-1] = vtop[-2];
3415 /* mask and shift source */
3416 vpushi((1 << bit_size) - 1);
3417 gen_op('&');
3418 vpushi(bit_pos);
3419 gen_op(TOK_SHL);
3420 /* load destination, mask and or with source */
3421 vswap();
3422 vpushi(~(((1 << bit_size) - 1) << bit_pos));
3423 gen_op('&');
3424 gen_op('|');
3425 /* store result */
3426 vstore();
3427 } else {
3428 rc = RC_INT;
3429 if (is_float(ft))
3430 rc = RC_FLOAT;
3431 r = gv(rc); /* generate value (XXX: move that to store code) */
3432 /* if lvalue was saved on stack, must read it */
3433 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
3434 SValue sv;
3435 t = get_reg(RC_INT);
3436 sv.t = VT_INT;
3437 sv.r = VT_LOCAL | VT_LVAL;
3438 sv.c.ul = vtop[-1].c.ul;
3439 load(t, &sv);
3440 vtop[-1].r = t | VT_LVAL;
3442 store(r, vtop - 1);
3443 /* two word case handling : store second register at word + 4 */
3444 if ((ft & VT_BTYPE) == VT_LLONG) {
3445 vswap();
3446 /* convert to int to increment easily */
3447 vtop->t = VT_INT;
3448 vtop->r &= ~VT_LVAL;
3449 vpushi(4);
3450 gen_op('+');
3451 vtop->r |= VT_LVAL;
3452 vswap();
3453 /* XXX: it works because r2 is spilled last ! */
3454 store(vtop->r2, vtop - 1);
3456 vswap();
3457 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
3458 vtop->r |= delayed_cast;
3462 /* post defines POST/PRE add. c is the token ++ or -- */
3463 void inc(int post, int c)
3465 test_lvalue();
3466 vdup(); /* save lvalue */
3467 if (post) {
3468 gv_dup(); /* duplicate value */
3469 vrotb(3);
3470 vrotb(3);
3472 /* add constant */
3473 vpushi(c - TOK_MID);
3474 gen_op('+');
3475 vstore(); /* store value */
3476 if (post)
3477 vpop(); /* if post op, return saved value */
3480 /* Parse GNUC __attribute__ extension. Currently, the following
3481 extensions are recognized:
3482 - aligned(n) : set data/function alignment.
3483 - section(x) : generate data/code in this section.
3484 - unused : currently ignored, but may be used someday.
3486 void parse_attribute(AttributeDef *ad)
3488 int t, n;
3490 next();
3491 skip('(');
3492 skip('(');
3493 while (tok != ')') {
3494 if (tok < TOK_IDENT)
3495 expect("attribute name");
3496 t = tok;
3497 next();
3498 switch(t) {
3499 case TOK_SECTION:
3500 case TOK___SECTION__:
3501 skip('(');
3502 if (tok != TOK_STR)
3503 expect("section name");
3504 ad->section = find_section(tokc.ts->str);
3505 next();
3506 skip(')');
3507 break;
3508 case TOK_ALIGNED:
3509 case TOK___ALIGNED__:
3510 skip('(');
3511 n = expr_const();
3512 if (n <= 0 || (n & (n - 1)) != 0)
3513 error("alignment must be a positive power of two");
3514 ad->aligned = n;
3515 skip(')');
3516 break;
3517 case TOK_UNUSED:
3518 case TOK___UNUSED__:
3519 /* currently, no need to handle it because tcc does not
3520 track unused objects */
3521 break;
3522 default:
3523 warning("'%s' attribute ignored", get_tok_str(t, NULL));
3524 /* skip parameters */
3525 /* XXX: skip parenthesis too */
3526 if (tok == '(') {
3527 next();
3528 while (tok != ')' && tok != -1)
3529 next();
3530 next();
3532 break;
3534 if (tok != ',')
3535 break;
3536 next();
3538 skip(')');
3539 skip(')');
3542 /* enum/struct/union declaration */
3543 int struct_decl(int u)
3545 int a, t, b, v, size, align, maxalign, c, offset;
3546 int bit_size, bit_pos, bsize, bt, lbit_pos;
3547 Sym *s, *ss, **ps;
3548 AttributeDef ad;
3550 a = tok; /* save decl type */
3551 next();
3552 if (tok != '{') {
3553 v = tok;
3554 next();
3555 /* struct already defined ? return it */
3556 /* XXX: check consistency */
3557 s = sym_find(v | SYM_STRUCT);
3558 if (s) {
3559 if (s->t != a)
3560 error("invalid type");
3561 goto do_decl;
3563 } else {
3564 v = anon_sym++;
3566 s = sym_push(v | SYM_STRUCT, a, 0, 0);
3567 /* put struct/union/enum name in type */
3568 do_decl:
3569 u = u | (v << VT_STRUCT_SHIFT);
3571 if (tok == '{') {
3572 next();
3573 if (s->c)
3574 error("struct/union/enum already defined");
3575 /* cannot be empty */
3576 c = 0;
3577 maxalign = 0;
3578 ps = &s->next;
3579 bit_pos = 0;
3580 offset = 0;
3581 while (1) {
3582 if (a == TOK_ENUM) {
3583 v = tok;
3584 next();
3585 if (tok == '=') {
3586 next();
3587 c = expr_const();
3589 /* enum symbols have static storage */
3590 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
3591 if (tok == ',')
3592 next();
3593 c++;
3594 } else {
3595 parse_btype(&b, &ad);
3596 while (1) {
3597 bit_size = -1;
3598 v = 0;
3599 if (tok != ':') {
3600 t = type_decl(&v, b, TYPE_DIRECT);
3601 if ((t & VT_BTYPE) == VT_FUNC ||
3602 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
3603 error("invalid type for '%s'",
3604 get_tok_str(v, NULL));
3605 } else {
3606 t = b;
3608 if (tok == ':') {
3609 next();
3610 bit_size = expr_const();
3611 /* XXX: handle v = 0 case for messages */
3612 if (bit_size < 0)
3613 error("negative width in bit-field '%s'",
3614 get_tok_str(v, NULL));
3615 if (v && bit_size == 0)
3616 error("zero width for bit-field '%s'",
3617 get_tok_str(v, NULL));
3619 size = type_size(t, &align);
3620 lbit_pos = 0;
3621 if (bit_size >= 0) {
3622 bt = t & VT_BTYPE;
3623 if (bt != VT_INT &&
3624 bt != VT_BYTE &&
3625 bt != VT_SHORT)
3626 error("bitfields must have scalar type");
3627 bsize = size * 8;
3628 if (bit_size > bsize) {
3629 error("width of '%s' exceeds its type",
3630 get_tok_str(v, NULL));
3631 } else if (bit_size == bsize) {
3632 /* no need for bit fields */
3633 bit_pos = 0;
3634 } else if (bit_size == 0) {
3635 /* XXX: what to do if only padding in a
3636 structure ? */
3637 /* zero size: means to pad */
3638 if (bit_pos > 0)
3639 bit_pos = bsize;
3640 } else {
3641 /* we do not have enough room ? */
3642 if ((bit_pos + bit_size) > bsize)
3643 bit_pos = 0;
3644 lbit_pos = bit_pos;
3645 /* XXX: handle LSB first */
3646 t |= VT_BITFIELD |
3647 (bit_pos << VT_STRUCT_SHIFT) |
3648 (bit_size << (VT_STRUCT_SHIFT + 6));
3649 bit_pos += bit_size;
3651 } else {
3652 bit_pos = 0;
3654 if (v) {
3655 /* add new memory data only if starting
3656 bit field */
3657 if (lbit_pos == 0) {
3658 if (a == TOK_STRUCT) {
3659 c = (c + align - 1) & -align;
3660 offset = c;
3661 c += size;
3662 } else {
3663 offset = 0;
3664 if (size > c)
3665 c = size;
3667 if (align > maxalign)
3668 maxalign = align;
3670 #if 0
3671 printf("add field %s offset=%d",
3672 get_tok_str(v, NULL), offset);
3673 if (t & VT_BITFIELD) {
3674 printf(" pos=%d size=%d",
3675 (t >> VT_STRUCT_SHIFT) & 0x3f,
3676 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
3678 printf("\n");
3679 #endif
3680 ss = sym_push(v | SYM_FIELD, t, 0, offset);
3681 *ps = ss;
3682 ps = &ss->next;
3684 if (tok == ';' || tok == -1)
3685 break;
3686 skip(',');
3688 skip(';');
3690 if (tok == '}')
3691 break;
3693 skip('}');
3694 /* size for struct/union, dummy for enum */
3695 s->c = (c + maxalign - 1) & -maxalign;
3697 return u;
3700 /* return 0 if no type declaration. otherwise, return the basic type
3701 and skip it.
3703 int parse_btype(int *type_ptr, AttributeDef *ad)
3705 int t, u, type_found;
3706 Sym *s;
3708 memset(ad, 0, sizeof(AttributeDef));
3709 type_found = 0;
3710 t = 0;
3711 while(1) {
3712 switch(tok) {
3713 /* basic types */
3714 case TOK_CHAR:
3715 u = VT_BYTE;
3716 basic_type:
3717 next();
3718 basic_type1:
3719 if ((t & VT_BTYPE) != 0)
3720 error("too many basic types");
3721 t |= u;
3722 break;
3723 case TOK_VOID:
3724 u = VT_VOID;
3725 goto basic_type;
3726 case TOK_SHORT:
3727 u = VT_SHORT;
3728 goto basic_type;
3729 case TOK_INT:
3730 next();
3731 break;
3732 case TOK_LONG:
3733 next();
3734 if ((t & VT_BTYPE) == VT_DOUBLE) {
3735 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
3736 } else if ((t & VT_BTYPE) == VT_LONG) {
3737 t = (t & ~VT_BTYPE) | VT_LLONG;
3738 } else {
3739 u = VT_LONG;
3740 goto basic_type1;
3742 break;
3743 case TOK_BOOL:
3744 u = VT_BOOL;
3745 goto basic_type;
3746 case TOK_FLOAT:
3747 u = VT_FLOAT;
3748 goto basic_type;
3749 case TOK_DOUBLE:
3750 next();
3751 if ((t & VT_BTYPE) == VT_LONG) {
3752 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
3753 } else {
3754 u = VT_DOUBLE;
3755 goto basic_type1;
3757 break;
3758 case TOK_ENUM:
3759 u = struct_decl(VT_ENUM);
3760 goto basic_type1;
3761 case TOK_STRUCT:
3762 case TOK_UNION:
3763 u = struct_decl(VT_STRUCT);
3764 goto basic_type1;
3766 /* type modifiers */
3767 case TOK_CONST:
3768 case TOK_VOLATILE:
3769 case TOK_REGISTER:
3770 case TOK_SIGNED:
3771 case TOK_AUTO:
3772 case TOK_INLINE:
3773 case TOK_RESTRICT:
3774 next();
3775 break;
3776 case TOK_UNSIGNED:
3777 t |= VT_UNSIGNED;
3778 next();
3779 break;
3781 /* storage */
3782 case TOK_EXTERN:
3783 t |= VT_EXTERN;
3784 next();
3785 break;
3786 case TOK_STATIC:
3787 t |= VT_STATIC;
3788 next();
3789 break;
3790 case TOK_TYPEDEF:
3791 t |= VT_TYPEDEF;
3792 next();
3793 break;
3794 /* GNUC attribute */
3795 case TOK___ATTRIBUTE__:
3796 parse_attribute(ad);
3797 break;
3798 default:
3799 s = sym_find(tok);
3800 if (!s || !(s->t & VT_TYPEDEF))
3801 goto the_end;
3802 t |= (s->t & ~VT_TYPEDEF);
3803 next();
3804 break;
3806 type_found = 1;
3808 the_end:
3809 /* long is never used as type */
3810 if ((t & VT_BTYPE) == VT_LONG)
3811 t = (t & ~VT_BTYPE) | VT_INT;
3812 *type_ptr = t;
3813 return type_found;
3816 int post_type(int t)
3818 int p, n, pt, l, t1;
3819 Sym **plast, *s, *first;
3820 AttributeDef ad;
3822 if (tok == '(') {
3823 /* function declaration */
3824 next();
3825 l = 0;
3826 first = NULL;
3827 plast = &first;
3828 while (tok != ')') {
3829 /* read param name and compute offset */
3830 if (l != FUNC_OLD) {
3831 if (!parse_btype(&pt, &ad)) {
3832 if (l) {
3833 error("invalid type");
3834 } else {
3835 l = FUNC_OLD;
3836 goto old_proto;
3839 l = FUNC_NEW;
3840 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
3841 break;
3842 pt = type_decl(&n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
3843 if ((pt & VT_BTYPE) == VT_VOID)
3844 error("parameter declared as void");
3845 } else {
3846 old_proto:
3847 n = tok;
3848 pt = VT_INT;
3849 next();
3851 /* array must be transformed to pointer according to ANSI C */
3852 pt &= ~VT_ARRAY;
3853 s = sym_push(n | SYM_FIELD, pt, 0, 0);
3854 *plast = s;
3855 plast = &s->next;
3856 if (tok == ',') {
3857 next();
3858 if (l == FUNC_NEW && tok == TOK_DOTS) {
3859 l = FUNC_ELLIPSIS;
3860 next();
3861 break;
3865 /* if no parameters, then old type prototype */
3866 if (l == 0)
3867 l = FUNC_OLD;
3868 skip(')');
3869 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
3870 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
3871 /* we push a anonymous symbol which will contain the function prototype */
3872 p = anon_sym++;
3873 s = sym_push(p, t, 0, l);
3874 s->next = first;
3875 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
3876 } else if (tok == '[') {
3877 /* array definition */
3878 next();
3879 n = -1;
3880 if (tok != ']') {
3881 n = expr_const();
3882 if (n < 0)
3883 error("invalid array size");
3885 skip(']');
3886 /* parse next post type */
3887 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
3888 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
3890 /* we push a anonymous symbol which will contain the array
3891 element type */
3892 p = anon_sym++;
3893 sym_push(p, t, 0, n);
3894 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
3896 return t;
3899 /* Read a type declaration (except basic type), and return the
3900 type. If v is true, then also put variable name in 'vtop->c' */
3901 int type_decl(int *v, int t, int td)
3903 int u, p;
3904 Sym *s;
3906 while (tok == '*') {
3907 next();
3908 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
3909 next();
3910 t = mk_pointer(t);
3913 /* recursive type */
3914 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
3915 if (tok == '(') {
3916 next();
3917 u = type_decl(v, 0, td);
3918 skip(')');
3919 } else {
3920 u = 0;
3921 /* type identifier */
3922 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
3923 *v = tok;
3924 next();
3925 } else {
3926 if (!(td & TYPE_ABSTRACT))
3927 expect("identifier");
3928 *v = 0;
3931 /* append t at the end of u */
3932 t = post_type(t);
3933 if (!u)
3934 return t;
3935 p = u;
3936 while(1) {
3937 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
3938 p = s->t;
3939 if (!p) {
3940 s->t = t;
3941 break;
3944 return u;
3947 /* define a new external reference to a function 'v' of type 'u' */
3948 Sym *external_sym(int v, int u, int r)
3950 Sym *s;
3951 s = sym_find(v);
3952 if (!s) {
3953 /* push forward reference */
3954 s = sym_push1(&global_stack,
3955 v, u, 0);
3956 s->r = r | VT_CONST | VT_FORWARD;
3958 return s;
3961 void indir(void)
3963 if ((vtop->t & VT_BTYPE) != VT_PTR)
3964 expect("pointer");
3965 if (vtop->r & VT_LVAL)
3966 gv(RC_INT);
3967 vtop->t = pointed_type(vtop->t);
3968 if (!(vtop->t & VT_ARRAY)) /* an array is never an lvalue */
3969 vtop->r |= VT_LVAL;
3972 /* pass a parameter to a function and do type checking and casting */
3973 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
3975 int func_type;
3976 func_type = func->c;
3977 if (func_type == FUNC_OLD ||
3978 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
3979 /* default casting : only need to convert float to double */
3980 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
3981 gen_cast(VT_DOUBLE);
3982 } else if (arg == NULL) {
3983 error("too many arguments to function");
3984 } else {
3985 gen_assign_cast(arg->t);
3987 gfunc_param(gf);
3990 void unary(void)
3992 int n, t, ft, fc, p, align, size, r, data_offset;
3993 Sym *s;
3994 GFuncContext gf;
3995 AttributeDef ad;
3997 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
3998 vpushi(tokc.i);
3999 next();
4000 } else if (tok == TOK_CUINT) {
4001 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
4002 next();
4003 } else if (tok == TOK_CLLONG) {
4004 vsetc(VT_LLONG, VT_CONST, &tokc);
4005 next();
4006 } else if (tok == TOK_CULLONG) {
4007 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
4008 next();
4009 } else if (tok == TOK_CFLOAT) {
4010 vsetc(VT_FLOAT, VT_CONST, &tokc);
4011 next();
4012 } else if (tok == TOK_CDOUBLE) {
4013 vsetc(VT_DOUBLE, VT_CONST, &tokc);
4014 next();
4015 } else if (tok == TOK_CLDOUBLE) {
4016 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
4017 next();
4018 } else if (tok == TOK___FUNC__) {
4019 /* special function name identifier */
4020 /* generate (char *) type */
4021 data_offset = (int)data_section->data_ptr;
4022 vset(mk_pointer(VT_BYTE), VT_CONST, data_offset);
4023 strcpy((void *)data_offset, funcname);
4024 data_offset += strlen(funcname) + 1;
4025 data_section->data_ptr = (unsigned char *)data_offset;
4026 next();
4027 } else if (tok == TOK_LSTR) {
4028 t = VT_INT;
4029 goto str_init;
4030 } else if (tok == TOK_STR) {
4031 /* string parsing */
4032 t = VT_BYTE;
4033 str_init:
4034 type_size(t, &align);
4035 data_offset = (int)data_section->data_ptr;
4036 data_offset = (data_offset + align - 1) & -align;
4037 fc = data_offset;
4038 /* we must declare it as an array first to use initializer parser */
4039 t = VT_ARRAY | mk_pointer(t);
4040 decl_initializer(t, VT_CONST, data_offset, 1, 0);
4041 data_offset += type_size(t, &align);
4042 /* put it as pointer */
4043 vset(t & ~VT_ARRAY, VT_CONST, fc);
4044 data_section->data_ptr = (unsigned char *)data_offset;
4045 } else {
4046 t = tok;
4047 next();
4048 if (t == '(') {
4049 /* cast ? */
4050 if (parse_btype(&t, &ad)) {
4051 ft = type_decl(&n, t, TYPE_ABSTRACT);
4052 skip(')');
4053 /* check ISOC99 compound literal */
4054 if (tok == '{') {
4055 /* data is allocated locally by default */
4056 if (global_expr)
4057 r = VT_CONST;
4058 else
4059 r = VT_LOCAL;
4060 /* all except arrays are lvalues */
4061 if (!(ft & VT_ARRAY))
4062 r |= VT_LVAL;
4063 memset(&ad, 0, sizeof(AttributeDef));
4064 fc = decl_initializer_alloc(ft, &ad, r, 1);
4065 vset(ft, r, fc);
4066 } else {
4067 unary();
4068 gen_cast(ft);
4070 } else {
4071 gexpr();
4072 skip(')');
4074 } else if (t == '*') {
4075 unary();
4076 indir();
4077 } else if (t == '&') {
4078 unary();
4079 /* functions names must be treated as function pointers,
4080 except for unary '&' and sizeof. Since we consider that
4081 functions are not lvalues, we only have to handle it
4082 there and in function calls. */
4083 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4084 test_lvalue();
4085 vtop->t = mk_pointer(vtop->t);
4086 vtop->r &= ~VT_LVAL;
4087 } else
4088 if (t == '!') {
4089 unary();
4090 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
4091 vtop->c.i = !vtop->c.i;
4092 else if ((vtop->r & VT_VALMASK) == VT_CMP)
4093 vtop->c.i = vtop->c.i ^ 1;
4094 else
4095 vset(VT_INT, VT_JMP, gtst(1, 0));
4096 } else
4097 if (t == '~') {
4098 unary();
4099 vpushi(-1);
4100 gen_op('^');
4101 } else
4102 if (t == '+') {
4103 unary();
4104 } else
4105 if (t == TOK_SIZEOF) {
4106 if (tok == '(') {
4107 next();
4108 if (parse_btype(&t, &ad)) {
4109 t = type_decl(&n, t, TYPE_ABSTRACT);
4110 } else {
4111 /* XXX: some code could be generated: add eval
4112 flag */
4113 gexpr();
4114 t = vtop->t;
4115 vpop();
4117 skip(')');
4118 } else {
4119 unary();
4120 t = vtop->t;
4121 vpop();
4123 vpushi(type_size(t, &t));
4124 } else
4125 if (t == TOK_INC || t == TOK_DEC) {
4126 unary();
4127 inc(0, t);
4128 } else if (t == '-') {
4129 vpushi(0);
4130 unary();
4131 gen_op('-');
4132 } else
4134 s = sym_find(t);
4135 if (!s) {
4136 if (tok != '(')
4137 error("'%s' undeclared", get_tok_str(t, NULL));
4138 /* for simple function calls, we tolerate undeclared
4139 external reference */
4140 p = anon_sym++;
4141 sym_push1(&global_stack, p, 0, FUNC_OLD);
4142 /* int() function */
4143 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT), 0);
4145 vset(s->t, s->r, s->c);
4146 /* if forward reference, we must point to s */
4147 if (vtop->r & VT_FORWARD)
4148 vtop->c.sym = s;
4152 /* post operations */
4153 while (1) {
4154 if (tok == TOK_INC || tok == TOK_DEC) {
4155 inc(1, tok);
4156 next();
4157 } else if (tok == '.' || tok == TOK_ARROW) {
4158 /* field */
4159 if (tok == TOK_ARROW)
4160 indir();
4161 test_lvalue();
4162 vtop->r &= ~VT_LVAL;
4163 next();
4164 /* expect pointer on structure */
4165 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
4166 expect("struct or union");
4167 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4168 /* find field */
4169 tok |= SYM_FIELD;
4170 while ((s = s->next) != NULL) {
4171 if (s->v == tok)
4172 break;
4174 if (!s)
4175 error("field not found");
4176 /* add field offset to pointer */
4177 vtop->t = VT_INT; /* change type to int */
4178 vpushi(s->c);
4179 gen_op('+');
4180 /* change type to field type, and set to lvalue */
4181 vtop->t = s->t;
4182 /* an array is never an lvalue */
4183 if (!(vtop->t & VT_ARRAY))
4184 vtop->r |= VT_LVAL;
4185 next();
4186 } else if (tok == '[') {
4187 next();
4188 gexpr();
4189 gen_op('+');
4190 indir();
4191 skip(']');
4192 } else if (tok == '(') {
4193 SValue ret;
4194 Sym *sa;
4196 /* function call */
4197 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
4198 /* pointer test (no array accepted) */
4199 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
4200 vtop->t = pointed_type(vtop->t);
4201 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4202 goto error_func;
4203 } else {
4204 error_func:
4205 expect("function pointer");
4207 } else {
4208 vtop->r &= ~VT_LVAL; /* no lvalue */
4210 /* get return type */
4211 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
4212 save_regs(); /* save used temporary registers */
4213 gfunc_start(&gf);
4214 next();
4215 sa = s->next; /* first parameter */
4216 #ifdef INVERT_FUNC_PARAMS
4218 int *str, len, parlevel, *saved_macro_ptr;
4219 Sym *args, *s1;
4221 /* read each argument and store it on a stack */
4222 /* XXX: merge it with macro args ? */
4223 args = NULL;
4224 while (tok != ')') {
4225 len = 0;
4226 str = NULL;
4227 parlevel = 0;
4228 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
4229 tok != -1) {
4230 if (tok == '(')
4231 parlevel++;
4232 else if (tok == ')')
4233 parlevel--;
4234 tok_add2(&str, &len, tok, &tokc);
4235 next();
4237 tok_add(&str, &len, -1); /* end of file added */
4238 tok_add(&str, &len, 0);
4239 s1 = sym_push2(&args, 0, 0, (int)str);
4240 s1->next = sa; /* add reference to argument */
4241 if (sa)
4242 sa = sa->next;
4243 if (tok != ',')
4244 break;
4245 next();
4247 if (tok != ')')
4248 expect(")");
4250 /* now generate code in reverse order by reading the stack */
4251 saved_macro_ptr = macro_ptr;
4252 while (args) {
4253 macro_ptr = (int *)args->c;
4254 next();
4255 expr_eq();
4256 if (tok != -1)
4257 expect("',' or ')'");
4258 gfunc_param_typed(&gf, s, args->next);
4259 s1 = args->prev;
4260 free((int *)args->c);
4261 free(args);
4262 args = s1;
4264 macro_ptr = saved_macro_ptr;
4265 /* restore token */
4266 tok = ')';
4268 #endif
4269 /* compute first implicit argument if a structure is returned */
4270 if ((s->t & VT_BTYPE) == VT_STRUCT) {
4271 /* get some space for the returned structure */
4272 size = type_size(s->t, &align);
4273 loc = (loc - size) & -align;
4274 ret.t = s->t;
4275 ret.r = VT_LOCAL | VT_LVAL;
4276 /* pass it as 'int' to avoid structure arg passing
4277 problems */
4278 vset(VT_INT, VT_LOCAL, loc);
4279 ret.c = vtop->c;
4280 gfunc_param(&gf);
4281 } else {
4282 ret.t = s->t;
4283 ret.r2 = VT_CONST;
4284 /* return in register */
4285 if (is_float(ret.t)) {
4286 ret.r = REG_FRET;
4287 } else {
4288 if ((ret.t & VT_BTYPE) == VT_LLONG)
4289 ret.r2 = REG_LRET;
4290 ret.r = REG_IRET;
4292 ret.c.i = 0;
4294 #ifndef INVERT_FUNC_PARAMS
4295 while (tok != ')') {
4296 expr_eq();
4297 gfunc_param_typed(&gf, s, sa);
4298 if (sa)
4299 sa = sa->next;
4300 if (tok == ',')
4301 next();
4303 #endif
4304 if (sa)
4305 error("too few arguments to function");
4306 skip(')');
4307 gfunc_call(&gf);
4308 /* return value */
4309 vsetc(ret.t, ret.r, &ret.c);
4310 vtop->r2 = ret.r2;
4311 } else {
4312 break;
4317 void uneq(void)
4319 int t;
4321 unary();
4322 if (tok == '=' ||
4323 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
4324 tok == TOK_A_XOR || tok == TOK_A_OR ||
4325 tok == TOK_A_SHL || tok == TOK_A_SAR) {
4326 test_lvalue();
4327 t = tok;
4328 next();
4329 if (t == '=') {
4330 expr_eq();
4331 } else {
4332 vdup();
4333 expr_eq();
4334 gen_op(t & 0x7f);
4336 vstore();
4340 void sum(int l)
4342 int t;
4344 if (l == 0)
4345 uneq();
4346 else {
4347 sum(--l);
4348 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
4349 (l == 1 && (tok == '+' || tok == '-')) ||
4350 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
4351 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
4352 tok == TOK_ULT || tok == TOK_UGE)) ||
4353 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
4354 (l == 5 && tok == '&') ||
4355 (l == 6 && tok == '^') ||
4356 (l == 7 && tok == '|') ||
4357 (l == 8 && tok == TOK_LAND) ||
4358 (l == 9 && tok == TOK_LOR)) {
4359 t = tok;
4360 next();
4361 sum(l);
4362 gen_op(t);
4367 /* only used if non constant */
4368 void eand(void)
4370 int t;
4372 sum(8);
4373 t = 0;
4374 while (1) {
4375 if (tok != TOK_LAND) {
4376 if (t) {
4377 t = gtst(1, t);
4378 vset(VT_INT, VT_JMPI, t);
4380 break;
4382 t = gtst(1, t);
4383 next();
4384 sum(8);
4388 void eor(void)
4390 int t;
4392 eand();
4393 t = 0;
4394 while (1) {
4395 if (tok != TOK_LOR) {
4396 if (t) {
4397 t = gtst(0, t);
4398 vset(VT_INT, VT_JMP, t);
4400 break;
4402 t = gtst(0, t);
4403 next();
4404 eand();
4408 /* XXX: better constant handling */
4409 void expr_eq(void)
4411 int t, u, c, r1, r2, rc;
4413 if (const_wanted) {
4414 sum(10);
4415 if (tok == '?') {
4416 c = vtop->c.i;
4417 vpop();
4418 next();
4419 gexpr();
4420 t = vtop->c.i;
4421 vpop();
4422 skip(':');
4423 expr_eq();
4424 if (c)
4425 vtop->c.i = t;
4427 } else {
4428 eor();
4429 if (tok == '?') {
4430 next();
4431 t = gtst(1, 0);
4432 gexpr();
4433 /* XXX: long long handling ? */
4434 rc = RC_INT;
4435 if (is_float(vtop->t))
4436 rc = RC_FLOAT;
4437 r1 = gv(rc);
4438 vpop();
4439 skip(':');
4440 u = gjmp(0);
4442 gsym(t);
4443 expr_eq();
4444 r2 = gv(rc);
4445 move_reg(r1, r2);
4446 vtop->r = r1;
4447 gsym(u);
4452 void gexpr(void)
4454 while (1) {
4455 expr_eq();
4456 if (tok != ',')
4457 break;
4458 vpop();
4459 next();
4463 /* parse a constant expression and return value in vtop */
4464 void expr_const1(void)
4466 int a;
4467 a = const_wanted;
4468 const_wanted = 1;
4469 expr_eq();
4470 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
4471 expect("constant");
4472 const_wanted = a;
4475 /* parse an integer constant and return its value */
4476 int expr_const(void)
4478 int c;
4479 expr_const1();
4480 c = vtop->c.i;
4481 vpop();
4482 return c;
4485 /* return the label token if current token is a label, otherwise
4486 return zero */
4487 int is_label(void)
4489 int t;
4490 CValue c;
4492 /* fast test first */
4493 if (tok < TOK_UIDENT)
4494 return 0;
4495 /* no need to save tokc since we expect an identifier */
4496 t = tok;
4497 c = tokc;
4498 next();
4499 if (tok == ':') {
4500 next();
4501 return t;
4502 } else {
4503 /* XXX: may not work in all cases (macros ?) */
4504 tok1 = tok;
4505 tok1c = tokc;
4506 tok = t;
4507 tokc = c;
4508 return 0;
4512 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
4514 int a, b, c, d;
4515 Sym *s;
4517 if (tok == TOK_IF) {
4518 /* if test */
4519 next();
4520 skip('(');
4521 gexpr();
4522 skip(')');
4523 a = gtst(1, 0);
4524 block(bsym, csym, case_sym, def_sym, case_reg);
4525 c = tok;
4526 if (c == TOK_ELSE) {
4527 next();
4528 d = gjmp(0);
4529 gsym(a);
4530 block(bsym, csym, case_sym, def_sym, case_reg);
4531 gsym(d); /* patch else jmp */
4532 } else
4533 gsym(a);
4534 } else if (tok == TOK_WHILE) {
4535 next();
4536 d = ind;
4537 skip('(');
4538 gexpr();
4539 skip(')');
4540 a = gtst(1, 0);
4541 b = 0;
4542 block(&a, &b, case_sym, def_sym, case_reg);
4543 oad(0xe9, d - ind - 5); /* jmp */
4544 gsym(a);
4545 gsym_addr(b, d);
4546 } else if (tok == '{') {
4547 next();
4548 /* declarations */
4549 s = local_stack.top;
4550 while (tok != '}') {
4551 decl(VT_LOCAL);
4552 if (tok != '}')
4553 block(bsym, csym, case_sym, def_sym, case_reg);
4555 /* pop locally defined symbols */
4556 sym_pop(&local_stack, s);
4557 next();
4558 } else if (tok == TOK_RETURN) {
4559 next();
4560 if (tok != ';') {
4561 gexpr();
4562 gen_assign_cast(func_vt);
4563 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
4564 /* if returning structure, must copy it to implicit
4565 first pointer arg location */
4566 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
4567 indir();
4568 vswap();
4569 /* copy structure value to pointer */
4570 vstore();
4571 } else if (is_float(func_vt)) {
4572 gv(RC_FRET);
4573 } else {
4574 gv(RC_IRET);
4576 vpop();
4578 skip(';');
4579 rsym = gjmp(rsym); /* jmp */
4580 } else if (tok == TOK_BREAK) {
4581 /* compute jump */
4582 if (!bsym)
4583 error("cannot break");
4584 *bsym = gjmp(*bsym);
4585 next();
4586 skip(';');
4587 } else if (tok == TOK_CONTINUE) {
4588 /* compute jump */
4589 if (!csym)
4590 error("cannot continue");
4591 *csym = gjmp(*csym);
4592 next();
4593 skip(';');
4594 } else if (tok == TOK_FOR) {
4595 int e;
4596 next();
4597 skip('(');
4598 if (tok != ';') {
4599 gexpr();
4600 vpop();
4602 skip(';');
4603 d = ind;
4604 c = ind;
4605 a = 0;
4606 b = 0;
4607 if (tok != ';') {
4608 gexpr();
4609 a = gtst(1, 0);
4611 skip(';');
4612 if (tok != ')') {
4613 e = gjmp(0);
4614 c = ind;
4615 gexpr();
4616 vpop();
4617 oad(0xe9, d - ind - 5); /* jmp */
4618 gsym(e);
4620 skip(')');
4621 block(&a, &b, case_sym, def_sym, case_reg);
4622 oad(0xe9, c - ind - 5); /* jmp */
4623 gsym(a);
4624 gsym_addr(b, c);
4625 } else
4626 if (tok == TOK_DO) {
4627 next();
4628 a = 0;
4629 b = 0;
4630 d = ind;
4631 block(&a, &b, case_sym, def_sym, case_reg);
4632 skip(TOK_WHILE);
4633 skip('(');
4634 gsym(b);
4635 gexpr();
4636 c = gtst(0, 0);
4637 gsym_addr(c, d);
4638 skip(')');
4639 gsym(a);
4640 skip(';');
4641 } else
4642 if (tok == TOK_SWITCH) {
4643 next();
4644 skip('(');
4645 gexpr();
4646 /* XXX: other types than integer */
4647 case_reg = gv(RC_INT);
4648 vpop();
4649 skip(')');
4650 a = 0;
4651 b = gjmp(0); /* jump to first case */
4652 c = 0;
4653 block(&a, csym, &b, &c, case_reg);
4654 /* if no default, jmp after switch */
4655 if (c == 0)
4656 c = ind;
4657 /* default label */
4658 gsym_addr(b, c);
4659 /* break label */
4660 gsym(a);
4661 } else
4662 if (tok == TOK_CASE) {
4663 int v1, v2;
4664 if (!case_sym)
4665 expect("switch");
4666 next();
4667 v1 = expr_const();
4668 v2 = v1;
4669 if (gnu_ext && tok == TOK_DOTS) {
4670 next();
4671 v2 = expr_const();
4672 if (v2 < v1)
4673 warning("empty case range");
4675 /* since a case is like a label, we must skip it with a jmp */
4676 b = gjmp(0);
4677 gsym(*case_sym);
4678 vset(VT_INT, case_reg, 0);
4679 vpushi(v1);
4680 if (v1 == v2) {
4681 gen_op(TOK_EQ);
4682 *case_sym = gtst(1, 0);
4683 } else {
4684 gen_op(TOK_GE);
4685 *case_sym = gtst(1, 0);
4686 vset(VT_INT, case_reg, 0);
4687 vpushi(v2);
4688 gen_op(TOK_LE);
4689 *case_sym = gtst(1, *case_sym);
4691 gsym(b);
4692 skip(':');
4693 block(bsym, csym, case_sym, def_sym, case_reg);
4694 } else
4695 if (tok == TOK_DEFAULT) {
4696 next();
4697 skip(':');
4698 if (!def_sym)
4699 expect("switch");
4700 if (*def_sym)
4701 error("too many 'default'");
4702 *def_sym = ind;
4703 block(bsym, csym, case_sym, def_sym, case_reg);
4704 } else
4705 if (tok == TOK_GOTO) {
4706 next();
4707 s = sym_find1(&label_stack, tok);
4708 /* put forward definition if needed */
4709 if (!s)
4710 s = sym_push1(&label_stack, tok, VT_FORWARD, 0);
4711 /* label already defined */
4712 if (s->t & VT_FORWARD)
4713 s->c = gjmp(s->c); /* jmp xxx */
4714 else
4715 oad(0xe9, s->c - ind - 5); /* jmp xxx */
4716 next();
4717 skip(';');
4718 } else {
4719 b = is_label();
4720 if (b) {
4721 /* label case */
4722 s = sym_find1(&label_stack, b);
4723 if (s) {
4724 if (!(s->t & VT_FORWARD))
4725 error("multiple defined label");
4726 gsym(s->c);
4727 s->c = ind;
4728 s->t = 0;
4729 } else {
4730 sym_push1(&label_stack, b, 0, ind);
4732 /* we accept this, but it is a mistake */
4733 if (tok == '}')
4734 warning("deprecated use of label at end of compound statement");
4735 else
4736 block(bsym, csym, case_sym, def_sym, case_reg);
4737 } else {
4738 /* expression case */
4739 if (tok != ';') {
4740 gexpr();
4741 vpop();
4743 skip(';');
4748 /* t is the array or struct type. c is the array or struct
4749 address. cur_index/cur_field is the pointer to the current
4750 value. 'size_only' is true if only size info is needed (only used
4751 in arrays) */
4752 void decl_designator(int t, int r, int c,
4753 int *cur_index, Sym **cur_field,
4754 int size_only)
4756 Sym *s, *f;
4757 int notfirst, index, align, l;
4759 notfirst = 0;
4760 if (gnu_ext && (l = is_label()) != 0)
4761 goto struct_field;
4763 while (tok == '[' || tok == '.') {
4764 if (tok == '[') {
4765 if (!(t & VT_ARRAY))
4766 expect("array type");
4767 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
4768 next();
4769 index = expr_const();
4770 if (index < 0 || (s->c >= 0 && index >= s->c))
4771 expect("invalid index");
4772 skip(']');
4773 if (!notfirst)
4774 *cur_index = index;
4775 t = pointed_type(t);
4776 c += index * type_size(t, &align);
4777 } else {
4778 next();
4779 l = tok;
4780 next();
4781 struct_field:
4782 if ((t & VT_BTYPE) != VT_STRUCT)
4783 expect("struct/union type");
4784 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4785 l |= SYM_FIELD;
4786 f = s->next;
4787 while (f) {
4788 if (f->v == l)
4789 break;
4790 f = f->next;
4792 if (!f)
4793 expect("field");
4794 if (!notfirst)
4795 *cur_field = f;
4796 t = f->t | (t & ~VT_TYPE);
4797 c += f->c;
4799 notfirst = 1;
4801 if (notfirst) {
4802 if (tok == '=') {
4803 next();
4804 } else {
4805 if (!gnu_ext)
4806 expect("=");
4808 } else {
4809 if (t & VT_ARRAY) {
4810 index = *cur_index;
4811 t = pointed_type(t);
4812 c += index * type_size(t, &align);
4813 } else {
4814 f = *cur_field;
4815 if (!f)
4816 error("too many field init");
4817 t = f->t | (t & ~VT_TYPE);
4818 c += f->c;
4821 decl_initializer(t, r, c, 0, size_only);
4824 #define EXPR_VAL 0
4825 #define EXPR_CONST 1
4826 #define EXPR_ANY 2
4828 /* store a value or an expression directly in global data or in local array */
4829 void init_putv(int t, int r, int c,
4830 int v, int expr_type)
4832 int saved_global_expr, bt;
4834 switch(expr_type) {
4835 case EXPR_VAL:
4836 vpushi(v);
4837 break;
4838 case EXPR_CONST:
4839 /* compound literals must be allocated globally in this case */
4840 saved_global_expr = global_expr;
4841 global_expr = 1;
4842 expr_const1();
4843 global_expr = saved_global_expr;
4844 break;
4845 case EXPR_ANY:
4846 expr_eq();
4847 break;
4850 if ((r & VT_VALMASK) == VT_CONST) {
4851 /* XXX: do casting */
4852 /* XXX: not portable */
4853 bt = vtop->t & VT_BTYPE;
4854 switch(bt) {
4855 case VT_BYTE:
4856 *(char *)c = vtop->c.i;
4857 break;
4858 case VT_SHORT:
4859 *(short *)c = vtop->c.i;
4860 break;
4861 case VT_DOUBLE:
4862 *(double *)c = vtop->c.d;
4863 break;
4864 case VT_LDOUBLE:
4865 *(long double *)c = vtop->c.ld;
4866 break;
4867 #if 0
4868 case VT_LLONG:
4869 *(long long *)c = vtop->c.ll;
4870 break;
4871 #endif
4872 default:
4873 *(int *)c = vtop->c.i;
4874 break;
4876 vpop();
4877 } else {
4878 vset(t, r, c);
4879 vswap();
4880 vstore();
4881 vpop();
4885 /* put zeros for variable based init */
4886 void init_putz(int t, int r, int c, int size)
4888 GFuncContext gf;
4890 if ((r & VT_VALMASK) == VT_CONST) {
4891 /* nothing to do because global are already set to zero */
4892 } else {
4893 gfunc_start(&gf);
4894 vpushi(size);
4895 gfunc_param(&gf);
4896 vpushi(0);
4897 gfunc_param(&gf);
4898 vset(VT_INT, VT_LOCAL, c);
4899 gfunc_param(&gf);
4900 vpushi((int)&memset);
4901 gfunc_call(&gf);
4905 /* 't' contains the type and storage info. c is the address of the
4906 object. 'first' is true if array '{' must be read (multi dimension
4907 implicit array init handling). 'size_only' is true if size only
4908 evaluation is wanted (only for arrays). */
4909 void decl_initializer(int t, int r, int c, int first, int size_only)
4911 int index, array_length, n, no_oblock, nb, parlevel, i;
4912 int t1, size1, align1, expr_type;
4913 Sym *s, *f;
4914 TokenSym *ts;
4916 if (t & VT_ARRAY) {
4917 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
4918 n = s->c;
4919 array_length = 0;
4920 t1 = pointed_type(t);
4921 size1 = type_size(t1, &align1);
4923 no_oblock = 1;
4924 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
4925 tok == '{') {
4926 skip('{');
4927 no_oblock = 0;
4930 /* only parse strings here if correct type (otherwise: handle
4931 them as ((w)char *) expressions */
4932 if ((tok == TOK_LSTR &&
4933 (t1 & VT_BTYPE) == VT_INT) ||
4934 (tok == TOK_STR &&
4935 (t1 & VT_BTYPE) == VT_BYTE)) {
4936 /* XXX: move multiple string parsing in parser ? */
4937 while (tok == TOK_STR || tok == TOK_LSTR) {
4938 ts = tokc.ts;
4939 /* compute maximum number of chars wanted */
4940 nb = ts->len;
4941 if (n >= 0 && nb > (n - array_length))
4942 nb = n - array_length;
4943 if (!size_only) {
4944 if (ts->len > nb)
4945 warning("initializer-string for array is too long");
4946 for(i=0;i<nb;i++) {
4947 init_putv(t1, r, c + (array_length + i) * size1,
4948 ts->str[i], EXPR_VAL);
4951 array_length += nb;
4952 next();
4954 /* only add trailing zero if enough storage (no
4955 warning in this case since it is standard) */
4956 if (n < 0 || array_length < n) {
4957 if (!size_only) {
4958 init_putv(t1, r, c + (array_length * size1), 0, EXPR_VAL);
4960 array_length++;
4962 } else {
4963 index = 0;
4964 while (tok != '}') {
4965 decl_designator(t, r, c, &index, NULL, size_only);
4966 if (n >= 0 && index >= n)
4967 error("index too large");
4968 /* must put zero in holes (note that doing it that way
4969 ensures that it even works with designators) */
4970 if (!size_only && array_length < index) {
4971 init_putz(t1, r, c + array_length * size1,
4972 (index - array_length) * size1);
4974 index++;
4975 if (index > array_length)
4976 array_length = index;
4977 /* special test for multi dimensional arrays (may not
4978 be strictly correct if designators are used at the
4979 same time) */
4980 if (index >= n && no_oblock)
4981 break;
4982 if (tok == '}')
4983 break;
4984 skip(',');
4987 if (!no_oblock)
4988 skip('}');
4989 /* put zeros at the end */
4990 if (!size_only && n >= 0 && array_length < n) {
4991 init_putz(t1, r, c + array_length * size1,
4992 (n - array_length) * size1);
4994 /* patch type size if needed */
4995 if (n < 0)
4996 s->c = array_length;
4997 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
4998 /* XXX: union needs only one init */
4999 next();
5000 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5001 f = s->next;
5002 array_length = 0;
5003 index = 0;
5004 n = s->c;
5005 while (tok != '}') {
5006 decl_designator(t, r, c, NULL, &f, size_only);
5007 /* fill with zero between fields */
5008 index = f->c;
5009 if (!size_only && array_length < index) {
5010 init_putz(t, r, c + array_length,
5011 index - array_length);
5013 index = index + type_size(f->t, &align1);
5014 if (index > array_length)
5015 array_length = index;
5016 if (tok == '}')
5017 break;
5018 skip(',');
5019 f = f->next;
5021 /* put zeros at the end */
5022 if (!size_only && array_length < n) {
5023 init_putz(t, r, c + array_length,
5024 n - array_length);
5026 skip('}');
5027 } else if (tok == '{') {
5028 next();
5029 decl_initializer(t, r, c, first, size_only);
5030 skip('}');
5031 } else if (size_only) {
5032 /* just skip expression */
5033 parlevel = 0;
5034 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
5035 tok != -1) {
5036 if (tok == '(')
5037 parlevel++;
5038 else if (tok == ')')
5039 parlevel--;
5040 next();
5042 } else {
5043 /* currently, we always use constant expression for globals
5044 (may change for scripting case) */
5045 expr_type = EXPR_CONST;
5046 if ((r & VT_VALMASK) == VT_LOCAL)
5047 expr_type = EXPR_ANY;
5048 init_putv(t, r, c, 0, expr_type);
5052 /* parse an initializer for type 't' if 'has_init' is true, and
5053 allocate space in local or global data space ('r' is either
5054 VT_LOCAL or VT_CONST). The allocated address in returned */
5055 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init)
5057 int size, align, addr, tok1, data_offset;
5058 int *init_str, init_len, level, *saved_macro_ptr;
5059 Section *sec;
5061 size = type_size(t, &align);
5062 /* If unknown size, we must evaluate it before
5063 evaluating initializers because
5064 initializers can generate global data too
5065 (e.g. string pointers or ISOC99 compound
5066 literals). It also simplifies local
5067 initializers handling */
5068 init_len = 0;
5069 init_str = NULL;
5070 saved_macro_ptr = NULL; /* avoid warning */
5071 tok1 = 0;
5072 if (size < 0) {
5073 if (!has_init)
5074 error("unknown type size");
5075 /* get all init string */
5076 level = 0;
5077 while (level > 0 || (tok != ',' && tok != ';')) {
5078 if (tok < 0)
5079 error("unexpected end of file in initializer");
5080 tok_add2(&init_str, &init_len, tok, &tokc);
5081 if (tok == '{')
5082 level++;
5083 else if (tok == '}') {
5084 if (level == 0)
5085 break;
5086 level--;
5088 next();
5090 tok1 = tok;
5091 tok_add(&init_str, &init_len, -1);
5092 tok_add(&init_str, &init_len, 0);
5094 /* compute size */
5095 saved_macro_ptr = macro_ptr;
5096 macro_ptr = init_str;
5097 next();
5098 decl_initializer(t, r, 0, 1, 1);
5099 /* prepare second initializer parsing */
5100 macro_ptr = init_str;
5101 next();
5103 /* if still unknown size, error */
5104 size = type_size(t, &align);
5105 if (size < 0)
5106 error("unknown type size");
5108 /* take into account specified alignment if bigger */
5109 if (ad->aligned > align)
5110 align = ad->aligned;
5111 if ((r & VT_VALMASK) == VT_LOCAL) {
5112 loc = (loc - size) & -align;
5113 addr = loc;
5114 } else {
5115 /* compute section */
5116 sec = ad->section;
5117 if (!sec) {
5118 if (has_init)
5119 sec = data_section;
5120 else
5121 sec = bss_section;
5123 data_offset = (int)sec->data_ptr;
5124 data_offset = (data_offset + align - 1) & -align;
5125 addr = data_offset;
5126 /* very important to increment global
5127 pointer at this time because
5128 initializers themselves can create new
5129 initializers */
5130 data_offset += size;
5131 sec->data_ptr = (unsigned char *)data_offset;
5133 if (has_init) {
5134 decl_initializer(t, r, addr, 1, 0);
5135 /* restore parse state if needed */
5136 if (init_str) {
5137 free(init_str);
5138 macro_ptr = saved_macro_ptr;
5139 tok = tok1;
5142 return addr;
5145 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5146 void decl(int l)
5148 int *a, t, b, v, addr, has_init, size, align, r, u;
5149 Sym *sym;
5150 AttributeDef ad;
5152 while (1) {
5153 if (!parse_btype(&b, &ad)) {
5154 /* skip redundant ';' */
5155 /* XXX: find more elegant solution */
5156 if (tok == ';') {
5157 next();
5158 continue;
5160 /* special test for old K&R protos without explicit int
5161 type. Only accepted when defining global data */
5162 if (l == VT_LOCAL || tok < TOK_DEFINE)
5163 break;
5164 b = VT_INT;
5166 if (((b & VT_BTYPE) == VT_ENUM ||
5167 (b & VT_BTYPE) == VT_STRUCT) &&
5168 tok == ';') {
5169 /* we accept no variable after */
5170 next();
5171 continue;
5173 while (1) { /* iterate thru each declaration */
5174 t = type_decl(&v, b, TYPE_DIRECT);
5175 /* currently, we do not parse attribute in
5176 type_decl(). May change if needed */
5177 if (tok == TOK___ATTRIBUTE__)
5178 parse_attribute(&ad);
5179 #if 0
5181 char buf[500];
5182 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
5183 printf("type = '%s'\n", buf);
5185 #endif
5186 if (tok == '{') {
5187 if (l == VT_LOCAL)
5188 error("cannot use local functions");
5189 if (!(t & VT_FUNC))
5190 expect("function definition");
5191 /* compute text section */
5192 cur_text_section = ad.section;
5193 if (!cur_text_section)
5194 cur_text_section = text_section;
5195 ind = (int)cur_text_section->data_ptr;
5196 /* patch forward references */
5197 if ((sym = sym_find(v)) && (sym->r & VT_FORWARD)) {
5198 greloc_patch(sym, ind);
5199 sym->t = t;
5200 } else {
5201 /* put function address */
5202 sym = sym_push1(&global_stack, v, t, ind);
5204 sym->r = VT_CONST;
5205 funcname = get_tok_str(v, NULL);
5206 /* push a dummy symbol to enable local sym storage */
5207 sym_push1(&local_stack, 0, 0, 0);
5208 /* define parameters */
5209 sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
5210 /* XXX: the following is x86 dependant -> move it to
5211 x86 code gen */
5212 addr = 8;
5213 /* if the function returns a structure, then add an
5214 implicit pointer parameter */
5215 func_vt = sym->t;
5216 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
5217 func_vc = addr;
5218 addr += 4;
5220 while ((sym = sym->next) != NULL) {
5221 u = sym->t;
5222 sym_push(sym->v & ~SYM_FIELD, u,
5223 VT_LOCAL | VT_LVAL, addr);
5224 size = type_size(u, &align);
5225 size = (size + 3) & ~3;
5226 #ifdef FUNC_STRUCT_PARAM_AS_PTR
5227 /* structs are passed as pointer */
5228 if ((u & VT_BTYPE) == VT_STRUCT) {
5229 size = 4;
5231 #endif
5232 addr += size;
5234 loc = 0;
5235 o(0xe58955); /* push %ebp, mov %esp, %ebp */
5236 a = (int *)oad(0xec81, 0); /* sub $xxx, %esp */
5237 rsym = 0;
5238 block(NULL, NULL, NULL, NULL, 0);
5239 gsym(rsym);
5240 o(0xc3c9); /* leave, ret */
5241 *a = (-loc + 3) & -4; /* align local size to word &
5242 save local variables */
5243 cur_text_section->data_ptr = (unsigned char *)ind;
5244 sym_pop(&label_stack, NULL); /* reset label stack */
5245 sym_pop(&local_stack, NULL); /* reset local stack */
5246 funcname = ""; /* for safety */
5247 func_vt = VT_VOID; /* for safety */
5248 break;
5249 } else {
5250 if (b & VT_TYPEDEF) {
5251 /* save typedefed type */
5252 /* XXX: test storage specifiers ? */
5253 sym_push(v, t | VT_TYPEDEF, 0, 0);
5254 } else if ((t & VT_BTYPE) == VT_FUNC) {
5255 /* external function definition */
5256 external_sym(v, t, 0);
5257 } else {
5258 /* not lvalue if array */
5259 r = 0;
5260 if (!(t & VT_ARRAY))
5261 r |= VT_LVAL;
5262 if (b & VT_EXTERN) {
5263 /* external variable */
5264 external_sym(v, t, r);
5265 } else {
5266 if (t & VT_STATIC)
5267 r |= VT_CONST;
5268 else
5269 r |= l;
5270 has_init = (tok == '=');
5271 if (has_init)
5272 next();
5273 addr = decl_initializer_alloc(t, &ad, r,
5274 has_init);
5275 if (l == VT_CONST) {
5276 /* global scope: see if already defined */
5277 sym = sym_find(v);
5278 if (!sym)
5279 goto do_def;
5280 if (!is_compatible_types(sym->t, t))
5281 error("incompatible types for redefinition of '%s'",
5282 get_tok_str(v, NULL));
5283 if (!(sym->r & VT_FORWARD))
5284 error("redefinition of '%s'", get_tok_str(v, NULL));
5285 greloc_patch(sym, addr);
5286 } else {
5287 do_def:
5288 sym_push(v, t, r, addr);
5292 if (tok != ',') {
5293 skip(';');
5294 break;
5296 next();
5302 /* put all global symbols in the extern stack and do all the
5303 resolving which can be done without using external symbols from DLLs */
5304 /* XXX: could try to verify types, but would not to save them in
5305 extern_stack too */
5306 void resolve_global_syms(void)
5308 Sym *s, *s1, *ext_sym;
5309 Reloc **p;
5311 s = global_stack.top;
5312 while (s != NULL) {
5313 s1 = s->prev;
5314 /* do not save static or typedefed symbols or types */
5315 if (!(s->t & (VT_STATIC | VT_TYPEDEF)) &&
5316 !(s->v & (SYM_FIELD | SYM_STRUCT)) &&
5317 (s->v < SYM_FIRST_ANOM)) {
5318 ext_sym = sym_find1(&extern_stack, s->v);
5319 if (!ext_sym) {
5320 /* if the symbol do not exist, we simply save it */
5321 ext_sym = sym_push1(&extern_stack, s->v, s->t, s->c);
5322 ext_sym->r = s->r;
5323 } else if (ext_sym->r & VT_FORWARD) {
5324 /* external symbol already exists, but only as forward
5325 definition */
5326 if (!(s->r & VT_FORWARD)) {
5327 /* s is not forward, so we can relocate all symbols */
5328 greloc_patch(ext_sym, s->c);
5329 } else {
5330 /* the two symbols are forward: merge them */
5331 p = (Reloc **)&ext_sym->c;
5332 while (*p != NULL)
5333 p = &(*p)->next;
5334 *p = (Reloc *)s->c;
5336 } else {
5337 /* external symbol already exists and is defined :
5338 patch all references to it */
5339 if (!(s->r & VT_FORWARD))
5340 error("'%s' defined twice", get_tok_str(s->v, NULL));
5341 greloc_patch(s, ext_sym->c);
5344 s = s1;
5348 /* compile a C file. Return non zero if errors. */
5349 int tcc_compile_file(const char *filename1)
5351 Sym *define_start;
5353 line_num = 1;
5354 funcname = "";
5355 filename = (char *)filename1;
5357 file = fopen(filename, "r");
5358 if (!file)
5359 error("file '%s' not found", filename);
5360 include_stack_ptr = include_stack;
5361 ifdef_stack_ptr = ifdef_stack;
5363 vtop = vstack - 1;
5364 anon_sym = SYM_FIRST_ANOM;
5366 define_start = define_stack.top;
5367 inp();
5368 ch = '\n'; /* needed to parse correctly first preprocessor command */
5369 next();
5370 decl(VT_CONST);
5371 if (tok != -1)
5372 expect("declaration");
5373 fclose(file);
5375 /* reset define stack, but leave -Dsymbols (may be incorrect if
5376 they are undefined) */
5377 sym_pop(&define_stack, define_start);
5379 resolve_global_syms();
5381 sym_pop(&global_stack, NULL);
5383 return 0;
5386 /* define a symbol. A value can also be provided with the '=' operator */
5387 /* XXX: currently only handles integers and string defines. should use
5388 tcc parser, but would need a custom 'FILE *' */
5389 void define_symbol(const char *sym)
5391 TokenSym *ts;
5392 int *str, len;
5393 CValue cval;
5394 const char *p;
5395 char buf[256];
5397 p = strchr(sym, '=');
5398 if (!p) {
5399 /* XXX: buffer overflow */
5400 strcpy(buf, sym);
5401 p = "1";
5402 } else {
5403 len = p - sym;
5404 if (len > sizeof(buf) - 1)
5405 len = sizeof(buf) - 1;
5406 memcpy(buf, sym, len);
5407 buf[len] = '\0';
5408 p++;
5411 ts = tok_alloc(buf, 0);
5412 str = NULL;
5413 len = 0;
5414 if (isnum(*p)) {
5415 /* integer case */
5416 cval.i = atoi(p);
5417 tok_add2(&str, &len, TOK_CINT, &cval);
5418 } else {
5419 /* string case */
5420 cval.ts = tok_alloc(p, 0);
5421 tok_add2(&str, &len, TOK_STR, &cval);
5423 tok_add(&str, &len, 0);
5424 sym_push1(&define_stack, ts->tok, MACRO_OBJ, (int)str);
5427 void undef_symbol(const char *sym)
5429 TokenSym *ts;
5430 Sym *s;
5431 printf("undef %s\n", sym);
5432 ts = tok_alloc(sym, 0);
5433 s = sym_find1(&define_stack, tok);
5434 /* undefine symbol by putting an invalid name */
5435 if (s)
5436 sym_undef(&define_stack, s);
5439 /* open a dynamic library so that its symbol are available for
5440 compiled programs */
5441 void open_dll(char *libname)
5443 char buf[1024];
5444 void *h;
5446 snprintf(buf, sizeof(buf), "lib%s.so", libname);
5447 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
5448 if (!h)
5449 error((char *)dlerror());
5452 void resolve_extern_syms(void)
5454 Sym *s, *s1;
5455 char *str;
5456 int addr;
5458 s = extern_stack.top;
5459 while (s != NULL) {
5460 s1 = s->prev;
5461 if (s->r & VT_FORWARD) {
5462 /* if there is at least one relocation to do, then find it
5463 and patch it */
5464 if (s->c) {
5465 str = get_tok_str(s->v, NULL);
5466 addr = (int)dlsym(NULL, str);
5467 if (!addr)
5468 error("unresolved external reference '%s'", str);
5469 greloc_patch(s, addr);
5472 s = s1;
5476 /* output a binary file (for testing) */
5477 void build_exe(char *filename)
5479 FILE *f;
5480 f = fopen(filename, "w");
5481 fwrite(text_section->data, 1, text_section->data_ptr - text_section->data, f);
5482 fclose(f);
5485 void help(void)
5487 printf("tcc version 0.9.3 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
5488 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-i infile] infile [infile_args...]\n");
5491 int main(int argc, char **argv)
5493 Sym *s;
5494 int (*t)();
5495 char *p, *r, *outfile;
5496 int optind;
5498 include_paths[0] = "/usr/include";
5499 include_paths[1] = "/usr/lib/tcc";
5500 include_paths[2] = "/usr/local/lib/tcc";
5501 nb_include_paths = 3;
5503 /* add all tokens */
5504 tok_ident = TOK_IDENT;
5505 p = "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0register\0signed\0auto\0inline\0restrict\0float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0sizeof\0__attribute__\0define\0include\0ifdef\0ifndef\0elif\0endif\0defined\0undef\0error\0line\0__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0__func__\0main\0section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0";
5506 while (*p) {
5507 r = p;
5508 while (*r++);
5509 tok_alloc(p, r - p - 1);
5510 p = r;
5513 /* standard defines */
5514 define_symbol("__STDC__");
5515 #ifdef __i386__
5516 define_symbol("__i386__");
5517 #endif
5518 /* tiny C specific defines */
5519 define_symbol("__TINYC__");
5521 /* create standard sections */
5522 text_section = new_section(".text");
5523 data_section = new_section(".data");
5524 bss_section = new_section(".bss");
5526 optind = 1;
5527 outfile = NULL;
5528 while (1) {
5529 if (optind >= argc) {
5530 show_help:
5531 help();
5532 return 1;
5534 r = argv[optind];
5535 if (r[0] != '-')
5536 break;
5537 optind++;
5538 if (r[1] == 'I') {
5539 if (nb_include_paths >= INCLUDE_PATHS_MAX)
5540 error("too many include paths");
5541 include_paths[nb_include_paths++] = r + 2;
5542 } else if (r[1] == 'D') {
5543 define_symbol(r + 2);
5544 } else if (r[1] == 'U') {
5545 undef_symbol(r + 2);
5546 } else if (r[1] == 'l') {
5547 open_dll(r + 2);
5548 } else if (r[1] == 'i') {
5549 if (optind >= argc)
5550 goto show_help;
5551 tcc_compile_file(argv[optind++]);
5552 } else if (r[1] == 'o') {
5553 /* currently, only for testing, so not documented */
5554 if (optind >= argc)
5555 goto show_help;
5556 outfile = argv[optind++];
5557 } else {
5558 fprintf(stderr, "invalid option -- '%s'\n", r);
5559 exit(1);
5563 tcc_compile_file(argv[optind]);
5565 resolve_extern_syms();
5567 if (outfile) {
5568 build_exe(outfile);
5569 return 0;
5570 } else {
5571 s = sym_find1(&extern_stack, TOK_MAIN);
5572 if (!s || (s->r & VT_FORWARD))
5573 error("main() not defined");
5574 t = (int (*)())s->c;
5575 return (*t)(argc - optind, argv + optind);