added local bound generation
[tinycc.git] / tcc.c
blob1cca8308ff67e0059762abf27d92ced44596d3e8
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002 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 <unistd.h>
27 #include <signal.h>
28 #include <sys/ucontext.h>
29 #include <sys/mman.h>
30 #include <elf.h>
31 #include <stab.h>
32 #include <malloc.h>
33 #ifndef CONFIG_TCC_STATIC
34 #include <dlfcn.h>
35 #endif
37 //#define DEBUG
38 /* preprocessor debug */
39 //#define PP_DEBUG
41 /* amount of virtual memory associate to a section (currently, we do
42 not realloc them) */
43 #define SECTION_VSIZE (1024 * 1024)
45 #define INCLUDE_STACK_SIZE 32
46 #define IFDEF_STACK_SIZE 64
47 #define VSTACK_SIZE 64
48 #define STRING_MAX_SIZE 1024
49 #define INCLUDE_PATHS_MAX 32
51 #define TOK_HASH_SIZE 521
52 #define TOK_ALLOC_INCR 256 /* must be a power of two */
53 #define SYM_HASH_SIZE 263
55 /* token symbol management */
56 typedef struct TokenSym {
57 struct TokenSym *hash_next;
58 int tok; /* token number */
59 int len;
60 char str[1];
61 } TokenSym;
63 /* constant value */
64 typedef union CValue {
65 long double ld;
66 double d;
67 float f;
68 int i;
69 unsigned int ui;
70 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
71 long long ll;
72 unsigned long long ull;
73 struct TokenSym *ts;
74 struct Sym *sym;
75 int tab[1];
76 } CValue;
78 /* value on stack */
79 typedef struct SValue {
80 int t; /* type */
81 unsigned short r; /* register + flags */
82 unsigned short r2; /* second register, used for 'long long'
83 type. If not used, set to VT_CONST */
84 CValue c; /* constant */
85 } SValue;
87 /* symbol management */
88 typedef struct Sym {
89 int v; /* symbol token */
90 int t; /* associated type */
91 int r; /* associated register */
92 int c; /* associated number */
93 struct Sym *next; /* next related symbol */
94 struct Sym *prev; /* prev symbol in stack */
95 struct Sym *hash_next; /* next symbol in hash table */
96 } Sym;
98 typedef struct SymStack {
99 struct Sym *top;
100 struct Sym *hash[SYM_HASH_SIZE];
101 } SymStack;
103 /* relocation entry (currently only used for functions or variables */
104 typedef struct Reloc {
105 int type; /* type of relocation */
106 int addr; /* address of relocation */
107 struct Reloc *next; /* next relocation */
108 } Reloc;
110 #define RELOC_ADDR32 1 /* 32 bits relocation */
111 #define RELOC_REL32 2 /* 32 bits relative relocation */
113 /* section definition */
114 typedef struct Section {
115 char name[64]; /* section name */
116 unsigned char *data; /* section data */
117 unsigned char *data_ptr; /* current data pointer */
118 int sh_num; /* elf section number */
119 int sh_type; /* elf section type */
120 int sh_flags; /* elf section flags */
121 int sh_entsize; /* elf entry size */
122 struct Section *link; /* link to another section */
123 struct Section *next;
124 } Section;
126 /* GNUC attribute definition */
127 typedef struct AttributeDef {
128 int aligned;
129 Section *section;
130 } AttributeDef;
132 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
133 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
134 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
136 #define FUNC_NEW 1 /* ansi function prototype */
137 #define FUNC_OLD 2 /* old function prototype */
138 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
140 /* field 'Sym.t' for macros */
141 #define MACRO_OBJ 0 /* object like macro */
142 #define MACRO_FUNC 1 /* function like macro */
144 /* type_decl() types */
145 #define TYPE_ABSTRACT 1 /* type without variable */
146 #define TYPE_DIRECT 2 /* type with variable */
148 typedef struct {
149 FILE *file;
150 char *filename;
151 int line_num;
152 } IncludeFile;
154 /* parser */
155 FILE *file;
156 int line_num;
157 int ch, ch1, tok, tok1;
158 CValue tokc, tok1c;
160 /* sections */
161 Section *first_section;
162 int section_num;
163 Section *text_section, *data_section, *bss_section; /* predefined sections */
164 Section *cur_text_section; /* current section where function code is
165 generated */
166 /* bound check related sections */
167 Section *bounds_section; /* contains global data bound description */
168 Section *lbounds_section; /* contains local data bound description */
169 /* debug sections */
170 Section *stab_section, *stabstr_section, *symtab_section, *strtab_section;
172 /* loc : local variable index
173 ind : output code index
174 rsym: return symbol
175 anon_sym: anonymous symbol index
177 int rsym, anon_sym,
178 prog, ind, loc, const_wanted;
179 int global_expr; /* true if compound literals must be allocated
180 globally (used during initializers parsing */
181 int func_vt, func_vc; /* current function return type (used by
182 return instruction) */
183 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
184 int tok_ident;
185 TokenSym **table_ident;
186 TokenSym *hash_ident[TOK_HASH_SIZE];
187 char token_buf[STRING_MAX_SIZE + 1];
188 char *filename, *funcname;
189 /* contains global symbols which remain between each translation unit */
190 SymStack extern_stack;
191 SymStack define_stack, global_stack, local_stack, label_stack;
193 SValue vstack[VSTACK_SIZE], *vtop;
194 int *macro_ptr, *macro_ptr_allocated;
195 IncludeFile include_stack[INCLUDE_STACK_SIZE], *include_stack_ptr;
196 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
197 char *include_paths[INCLUDE_PATHS_MAX];
198 int nb_include_paths;
199 int char_pointer_type;
201 /* compile with debug symbol (and use them if error during execution) */
202 int do_debug = 0;
204 /* compile with built-in memory and bounds checker */
205 int do_bounds_check = 0;
207 /* use GNU C extensions */
208 int gnu_ext = 1;
210 /* use Tiny C extensions */
211 int tcc_ext = 1;
213 /* The current value can be: */
214 #define VT_VALMASK 0x00ff
215 #define VT_CONST 0x00f0 /* constant in vc
216 (must be first non register value) */
217 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
218 #define VT_LOCAL 0x00f2 /* offset on stack */
219 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
220 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
221 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
222 #define VT_LVAL 0x0100 /* var is an lvalue */
223 #define VT_FORWARD 0x0200 /* value is forward reference */
224 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
225 char/short stored in integer registers) */
226 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
227 dereferencing value */
229 /* types */
230 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
232 #define VT_INT 0 /* integer type */
233 #define VT_BYTE 1 /* signed byte type */
234 #define VT_SHORT 2 /* short type */
235 #define VT_VOID 3 /* void type */
236 #define VT_PTR 4 /* pointer increment */
237 #define VT_ENUM 5 /* enum definition */
238 #define VT_FUNC 6 /* function type */
239 #define VT_STRUCT 7 /* struct/union definition */
240 #define VT_FLOAT 8 /* IEEE float */
241 #define VT_DOUBLE 9 /* IEEE double */
242 #define VT_LDOUBLE 10 /* IEEE long double */
243 #define VT_BOOL 11 /* ISOC99 boolean type */
244 #define VT_LLONG 12 /* 64 bit integer */
245 #define VT_LONG 13 /* long integer (NEVER USED as type, only
246 during parsing) */
247 #define VT_BTYPE 0x000f /* mask for basic type */
248 #define VT_UNSIGNED 0x0010 /* unsigned type */
249 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
250 #define VT_BITFIELD 0x0040 /* bitfield modifier */
252 /* storage */
253 #define VT_EXTERN 0x00000080 /* extern definition */
254 #define VT_STATIC 0x00000100 /* static variable */
255 #define VT_TYPEDEF 0x00000200 /* typedef definition */
257 /* type mask (except storage) */
258 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
260 /* token values */
262 /* warning: the following compare tokens depend on i386 asm code */
263 #define TOK_ULT 0x92
264 #define TOK_UGE 0x93
265 #define TOK_EQ 0x94
266 #define TOK_NE 0x95
267 #define TOK_ULE 0x96
268 #define TOK_UGT 0x97
269 #define TOK_LT 0x9c
270 #define TOK_GE 0x9d
271 #define TOK_LE 0x9e
272 #define TOK_GT 0x9f
274 #define TOK_LAND 0xa0
275 #define TOK_LOR 0xa1
277 #define TOK_DEC 0xa2
278 #define TOK_MID 0xa3 /* inc/dec, to void constant */
279 #define TOK_INC 0xa4
280 #define TOK_UDIV 0xb0 /* unsigned division */
281 #define TOK_UMOD 0xb1 /* unsigned modulo */
282 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
283 #define TOK_CINT 0xb3 /* number in tokc */
284 #define TOK_CCHAR 0xb4 /* char constant in tokc */
285 #define TOK_STR 0xb5 /* pointer to string in tokc */
286 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
287 #define TOK_LCHAR 0xb7
288 #define TOK_LSTR 0xb8
289 #define TOK_CFLOAT 0xb9 /* float constant */
290 #define TOK_CDOUBLE 0xc0 /* double constant */
291 #define TOK_CLDOUBLE 0xc1 /* long double constant */
292 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
293 #define TOK_ADDC1 0xc3 /* add with carry generation */
294 #define TOK_ADDC2 0xc4 /* add with carry use */
295 #define TOK_SUBC1 0xc5 /* add with carry generation */
296 #define TOK_SUBC2 0xc6 /* add with carry use */
297 #define TOK_CUINT 0xc8 /* unsigned int constant */
298 #define TOK_CLLONG 0xc9 /* long long constant */
299 #define TOK_CULLONG 0xca /* unsigned long long constant */
300 #define TOK_ARROW 0xcb
301 #define TOK_DOTS 0xcc /* three dots */
302 #define TOK_SHR 0xcd /* unsigned shift right */
304 #define TOK_SHL 0x01 /* shift left */
305 #define TOK_SAR 0x02 /* signed shift right */
307 /* assignement operators : normal operator or 0x80 */
308 #define TOK_A_MOD 0xa5
309 #define TOK_A_AND 0xa6
310 #define TOK_A_MUL 0xaa
311 #define TOK_A_ADD 0xab
312 #define TOK_A_SUB 0xad
313 #define TOK_A_DIV 0xaf
314 #define TOK_A_XOR 0xde
315 #define TOK_A_OR 0xfc
316 #define TOK_A_SHL 0x81
317 #define TOK_A_SAR 0x82
319 /* all identificators and strings have token above that */
320 #define TOK_IDENT 256
322 enum {
323 TOK_INT = TOK_IDENT,
324 TOK_VOID,
325 TOK_CHAR,
326 TOK_IF,
327 TOK_ELSE,
328 TOK_WHILE,
329 TOK_BREAK,
330 TOK_RETURN,
331 TOK_FOR,
332 TOK_EXTERN,
333 TOK_STATIC,
334 TOK_UNSIGNED,
335 TOK_GOTO,
336 TOK_DO,
337 TOK_CONTINUE,
338 TOK_SWITCH,
339 TOK_CASE,
341 /* ignored types Must have contiguous values */
342 TOK_CONST,
343 TOK_VOLATILE,
344 TOK_LONG,
345 TOK_REGISTER,
346 TOK_SIGNED,
347 TOK_AUTO,
348 TOK_INLINE,
349 TOK_RESTRICT,
351 /* unsupported type */
352 TOK_FLOAT,
353 TOK_DOUBLE,
354 TOK_BOOL,
356 TOK_SHORT,
357 TOK_STRUCT,
358 TOK_UNION,
359 TOK_TYPEDEF,
360 TOK_DEFAULT,
361 TOK_ENUM,
362 TOK_SIZEOF,
363 TOK___ATTRIBUTE__,
365 /* preprocessor only */
366 TOK_UIDENT, /* first "user" ident (not keyword) */
367 TOK_DEFINE = TOK_UIDENT,
368 TOK_INCLUDE,
369 TOK_IFDEF,
370 TOK_IFNDEF,
371 TOK_ELIF,
372 TOK_ENDIF,
373 TOK_DEFINED,
374 TOK_UNDEF,
375 TOK_ERROR,
376 TOK_LINE,
377 TOK___LINE__,
378 TOK___FILE__,
379 TOK___DATE__,
380 TOK___TIME__,
381 TOK___VA_ARGS__,
383 /* special identifiers */
384 TOK___FUNC__,
385 TOK_MAIN,
386 /* attribute identifiers */
387 TOK_SECTION,
388 TOK___SECTION__,
389 TOK_ALIGNED,
390 TOK___ALIGNED__,
391 TOK_UNUSED,
392 TOK___UNUSED__,
395 /* XXX: need to define this to use them in non ISOC99 context */
396 extern float strtof (const char *__nptr, char **__endptr);
397 extern long double strtold (const char *__nptr, char **__endptr);
399 void sum(int l);
400 void next(void);
401 void next_nomacro(void);
402 int expr_const(void);
403 void expr_eq(void);
404 void gexpr(void);
405 void decl(int l);
406 void decl_initializer(int t, int r, int c, int first, int size_only);
407 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init);
408 int gv(int rc);
409 void gv2(int rc1, int rc2);
410 void move_reg(int r, int s);
411 void save_regs(void);
412 void save_reg(int r);
413 void vpop(void);
414 void vswap(void);
415 void vdup(void);
416 int get_reg(int rc);
418 void macro_subst(int **tok_str, int *tok_len,
419 Sym **nested_list, int *macro_str);
420 int save_reg_forced(int r);
421 void gen_op(int op);
422 void force_charshort_cast(int t);
423 void gen_cast(int t);
424 void vstore(void);
425 Sym *sym_find(int v);
426 Sym *sym_push(int v, int t, int r, int c);
428 /* type handling */
429 int type_size(int t, int *a);
430 int pointed_type(int t);
431 int pointed_size(int t);
432 int is_compatible_types(int t1, int t2);
433 int parse_btype(int *type_ptr, AttributeDef *ad);
434 int type_decl(int *v, int t, int td);
436 void error(const char *fmt, ...);
437 void vpushi(int v);
438 void vset(int t, int r, int v);
439 void type_to_str(char *buf, int buf_size,
440 int t, const char *varstr);
442 /* section generation */
443 void greloc(Sym *s, int addr, int type);
444 static int put_elf_str(Section *s, const char *sym);
445 static void put_elf_sym(Section *s,
446 unsigned long value, unsigned long size,
447 int info, int other, int shndx, const char *name);
448 static void put_stabs(const char *str, int type, int other, int desc, int value);
449 static void put_stabn(int type, int other, int desc, int value);
450 static void put_stabd(int type, int other, int desc);
452 /* true if float/double/long double type */
453 static inline int is_float(int t)
455 int bt;
456 bt = t & VT_BTYPE;
457 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
460 #include "bcheck.c"
462 #include "i386-gen.c"
464 #ifdef CONFIG_TCC_STATIC
466 #define RTLD_LAZY 0x001
467 #define RTLD_NOW 0x002
468 #define RTLD_GLOBAL 0x100
470 /* dummy function for profiling */
471 void *dlopen(const char *filename, int flag)
473 return NULL;
476 const char *dlerror(void)
478 return "error";
481 typedef struct TCCSyms {
482 char *str;
483 void *ptr;
484 } TCCSyms;
486 #define TCCSYM(a) { #a, &a, },
488 /* add the symbol you want here if no dynamic linking is done */
489 static TCCSyms tcc_syms[] = {
490 TCCSYM(printf)
491 TCCSYM(fprintf)
492 TCCSYM(fopen)
493 TCCSYM(fclose)
494 { NULL, NULL },
497 void *dlsym(void *handle, char *symbol)
499 TCCSyms *p;
500 p = tcc_syms;
501 while (p->str != NULL) {
502 if (!strcmp(p->str, symbol))
503 return p->ptr;
504 p++;
506 return NULL;
509 #endif
511 /********************************************************/
512 /* runtime library is there */
513 /* XXX: we suppose that the host compiler handles 'long long'. It
514 would not be difficult to suppress this assumption */
516 /* XXX: these functions are defined in libgcc. Should provide a
517 portable code too. */
518 long long __divll(long long a, long long b)
520 return a / b;
523 long long __modll(long long a, long long b)
525 return a % b;
528 unsigned long long __divull(unsigned long long a, unsigned long long b)
530 return a / b;
533 unsigned long long __modull(unsigned long long a, unsigned long long b)
535 return a % b;
538 long long __sardi3(long long a, int b)
540 return a >> b;
543 unsigned long long __shrdi3(unsigned long long a, int b)
545 return a >> b;
548 long long __shldi3(long long a, int b)
550 return a << b;
553 float __ulltof(unsigned long long a)
555 return (float)a;
558 double __ulltod(unsigned long long a)
560 return (double)a;
563 long double __ulltold(unsigned long long a)
565 return (long double)a;
568 unsigned long long __ftoull(float a)
570 return (unsigned long long)a;
573 unsigned long long __dtoull(double a)
575 return (unsigned long long)a;
578 unsigned long long __ldtoull(long double a)
580 return (unsigned long long)a;
584 /********************************************************/
586 /* copy a string and truncate it */
587 char *pstrcpy(char *buf, int buf_size, const char *s)
589 char *q, *q_end;
590 int c;
592 q = buf;
593 q_end = buf + buf_size - 1;
594 while (q < q_end) {
595 c = *s++;
596 if (c == '\0')
597 break;
598 *q++ = c;
600 *q = '\0';
601 return buf;
604 /* strcat and truncate */
605 char *pstrcat(char *buf, int buf_size, const char *s)
607 int len;
608 len = strlen(buf);
609 if (len < buf_size)
610 pstrcpy(buf + len, buf_size - len, s);
611 return buf;
614 Section *new_section(const char *name, int sh_type, int sh_flags)
616 Section *sec, **psec;
617 void *data;
619 sec = malloc(sizeof(Section));
620 if (!sec)
621 error("memory full");
622 memset(sec, 0, sizeof(Section));
623 pstrcpy(sec->name, sizeof(sec->name), name);
624 sec->link = NULL;
625 sec->sh_num = ++section_num;
626 sec->sh_type = sh_type;
627 sec->sh_flags = sh_flags;
628 data = mmap(NULL, SECTION_VSIZE,
629 PROT_EXEC | PROT_READ | PROT_WRITE,
630 MAP_PRIVATE | MAP_ANONYMOUS,
631 -1, 0);
632 if (data == (void *)(-1))
633 error("could not mmap section '%s'", name);
634 sec->data = data;
635 sec->data_ptr = data;
636 psec = &first_section;
637 while (*psec != NULL)
638 psec = &(*psec)->next;
639 sec->next = NULL;
640 *psec = sec;
641 return sec;
644 /* return a reference to a section, and create it if it does not
645 exists */
646 Section *find_section(const char *name)
648 Section *sec;
650 for(sec = first_section; sec != NULL; sec = sec->next) {
651 if (!strcmp(name, sec->name))
652 return sec;
654 /* sections are created as PROGBITS */
655 return new_section(name, SHT_PROGBITS, SHF_ALLOC);
658 /* add a new relocation entry to symbol 's' */
659 void greloc(Sym *s, int addr, int type)
661 Reloc *p;
662 p = malloc(sizeof(Reloc));
663 if (!p)
664 error("memory full");
665 p->type = type;
666 p->addr = addr;
667 p->next = (Reloc *)s->c;
668 s->c = (int)p;
671 /* patch each relocation entry with value 'val' */
672 void greloc_patch(Sym *s, int val)
674 Reloc *p, *p1;
676 p = (Reloc *)s->c;
677 while (p != NULL) {
678 p1 = p->next;
679 greloc_patch1(p, val);
680 free(p);
681 p = p1;
683 s->c = val;
684 s->r &= ~VT_FORWARD;
688 static inline int isid(int c)
690 return (c >= 'a' && c <= 'z') ||
691 (c >= 'A' && c <= 'Z') ||
692 c == '_';
695 static inline int isnum(int c)
697 return c >= '0' && c <= '9';
700 static inline int toup(int c)
702 if (ch >= 'a' && ch <= 'z')
703 return ch - 'a' + 'A';
704 else
705 return ch;
708 void printline(void)
710 IncludeFile *f;
711 for(f = include_stack; f < include_stack_ptr; f++)
712 fprintf(stderr, "In file included from %s:%d:\n",
713 f->filename, f->line_num);
714 fprintf(stderr, "%s:%d: ", filename, line_num);
717 void error(const char *fmt, ...)
719 va_list ap;
720 va_start(ap, fmt);
721 printline();
722 vfprintf(stderr, fmt, ap);
723 fprintf(stderr, "\n");
724 exit(1);
725 va_end(ap);
728 void expect(const char *msg)
730 error("%s expected", msg);
733 void warning(const char *fmt, ...)
735 va_list ap;
737 va_start(ap, fmt);
738 printline();
739 fprintf(stderr, "warning: ");
740 vfprintf(stderr, fmt, ap);
741 fprintf(stderr, "\n");
742 va_end(ap);
745 void skip(int c)
747 if (tok != c)
748 error("'%c' expected", c);
749 next();
752 void test_lvalue(void)
754 if (!(vtop->r & VT_LVAL))
755 expect("lvalue");
758 TokenSym *tok_alloc(const char *str, int len)
760 TokenSym *ts, **pts, **ptable;
761 int h, i;
763 if (len <= 0)
764 len = strlen(str);
765 h = 1;
766 for(i=0;i<len;i++)
767 h = ((h << 8) | (str[i] & 0xff)) % TOK_HASH_SIZE;
769 pts = &hash_ident[h];
770 while (1) {
771 ts = *pts;
772 if (!ts)
773 break;
774 if (ts->len == len && !memcmp(ts->str, str, len))
775 return ts;
776 pts = &(ts->hash_next);
779 if (tok_ident >= SYM_FIRST_ANOM)
780 error("memory full");
782 /* expand token table if needed */
783 i = tok_ident - TOK_IDENT;
784 if ((i % TOK_ALLOC_INCR) == 0) {
785 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
786 if (!ptable)
787 error("memory full");
788 table_ident = ptable;
791 ts = malloc(sizeof(TokenSym) + len);
792 if (!ts)
793 error("memory full");
794 table_ident[i] = ts;
795 ts->tok = tok_ident++;
796 ts->len = len;
797 ts->hash_next = NULL;
798 memcpy(ts->str, str, len + 1);
799 *pts = ts;
800 return ts;
803 void add_char(char **pp, int c)
805 char *p;
806 p = *pp;
807 if (c == '\'' || c == '\"' || c == '\\') {
808 /* XXX: could be more precise if char or string */
809 *p++ = '\\';
811 if (c >= 32 && c <= 126) {
812 *p++ = c;
813 } else {
814 *p++ = '\\';
815 if (c == '\n') {
816 *p++ = 'n';
817 } else {
818 *p++ = '0' + ((c >> 6) & 7);
819 *p++ = '0' + ((c >> 3) & 7);
820 *p++ = '0' + (c & 7);
823 *pp = p;
826 /* XXX: buffer overflow */
827 char *get_tok_str(int v, CValue *cv)
829 static char buf[STRING_MAX_SIZE + 1];
830 TokenSym *ts;
831 char *p;
832 int i;
834 if (v == TOK_CINT || v == TOK_CUINT) {
835 sprintf(buf, "%u", cv->ui);
836 return buf;
837 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
838 p = buf;
839 *p++ = '\'';
840 add_char(&p, cv->i);
841 *p++ = '\'';
842 *p = '\0';
843 return buf;
844 } else if (v == TOK_STR || v == TOK_LSTR) {
845 ts = cv->ts;
846 p = buf;
847 *p++ = '\"';
848 for(i=0;i<ts->len;i++)
849 add_char(&p, ts->str[i]);
850 *p++ = '\"';
851 *p = '\0';
852 return buf;
853 } else if (v < TOK_IDENT) {
854 p = buf;
855 *p++ = v;
856 *p = '\0';
857 return buf;
858 } else if (v < tok_ident) {
859 return table_ident[v - TOK_IDENT]->str;
860 } else {
861 /* should never happen */
862 return NULL;
866 /* push, without hashing */
867 Sym *sym_push2(Sym **ps, int v, int t, int c)
869 Sym *s;
870 s = malloc(sizeof(Sym));
871 if (!s)
872 error("memory full");
873 s->v = v;
874 s->t = t;
875 s->c = c;
876 s->next = NULL;
877 /* add in stack */
878 s->prev = *ps;
879 *ps = s;
880 return s;
883 /* find a symbol and return its associated structure. 's' is the top
884 of the symbol stack */
885 Sym *sym_find2(Sym *s, int v)
887 while (s) {
888 if (s->v == v)
889 return s;
890 s = s->prev;
892 return NULL;
895 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
897 /* find a symbol and return its associated structure. 'st' is the
898 symbol stack */
899 Sym *sym_find1(SymStack *st, int v)
901 Sym *s;
903 s = st->hash[HASH_SYM(v)];
904 while (s) {
905 if (s->v == v)
906 return s;
907 s = s->hash_next;
909 return NULL;
912 Sym *sym_push1(SymStack *st, int v, int t, int c)
914 Sym *s, **ps;
915 s = sym_push2(&st->top, v, t, c);
916 /* add in hash table */
917 if (v) {
918 ps = &st->hash[HASH_SYM(v)];
919 s->hash_next = *ps;
920 *ps = s;
922 return s;
925 /* find a symbol in the right symbol space */
926 Sym *sym_find(int v)
928 Sym *s;
929 s = sym_find1(&local_stack, v);
930 if (!s)
931 s = sym_find1(&global_stack, v);
932 return s;
935 /* push a given symbol on the symbol stack */
936 Sym *sym_push(int v, int t, int r, int c)
938 Sym *s;
939 if (local_stack.top)
940 s = sym_push1(&local_stack, v, t, c);
941 else
942 s = sym_push1(&global_stack, v, t, c);
943 s->r = r;
944 return s;
947 /* pop symbols until top reaches 'b' */
948 void sym_pop(SymStack *st, Sym *b)
950 Sym *s, *ss;
952 s = st->top;
953 while(s != b) {
954 ss = s->prev;
955 /* free hash table entry, except if symbol was freed (only
956 used for #undef symbols) */
957 if (s->v)
958 st->hash[HASH_SYM(s->v)] = s->hash_next;
959 free(s);
960 s = ss;
962 st->top = b;
965 /* undefined a hashed symbol (used for #undef). Its name is set to
966 zero */
967 void sym_undef(SymStack *st, Sym *s)
969 Sym **ss;
970 ss = &st->hash[HASH_SYM(s->v)];
971 while (*ss != NULL) {
972 if (*ss == s)
973 break;
974 ss = &(*ss)->hash_next;
976 *ss = s->hash_next;
977 s->v = 0;
980 /* no need to put that inline */
981 int handle_eof(void)
983 if (include_stack_ptr == include_stack)
984 return -1;
985 /* add end of include file debug info */
986 if (do_debug) {
987 put_stabd(N_EINCL, 0, 0);
989 /* pop include stack */
990 fclose(file);
991 free(filename);
992 include_stack_ptr--;
993 file = include_stack_ptr->file;
994 filename = include_stack_ptr->filename;
995 line_num = include_stack_ptr->line_num;
996 return 0;
999 /* read next char from current input file */
1000 static inline void inp(void)
1002 redo:
1003 /* faster than fgetc */
1004 ch1 = getc_unlocked(file);
1005 if (ch1 == -1) {
1006 if (handle_eof() < 0)
1007 return;
1008 else
1009 goto redo;
1011 if (ch1 == '\n')
1012 line_num++;
1013 // printf("ch1=%c 0x%x\n", ch1, ch1);
1016 /* input with '\\n' handling */
1017 static inline void minp(void)
1019 redo:
1020 ch = ch1;
1021 inp();
1022 if (ch == '\\' && ch1 == '\n') {
1023 inp();
1024 goto redo;
1026 //printf("ch=%c 0x%x\n", ch, ch);
1030 /* same as minp, but also skip comments */
1031 void cinp(void)
1033 int c;
1035 if (ch1 == '/') {
1036 inp();
1037 if (ch1 == '/') {
1038 /* single line C++ comments */
1039 inp();
1040 while (ch1 != '\n' && ch1 != -1)
1041 inp();
1042 inp();
1043 ch = ' '; /* return space */
1044 } else if (ch1 == '*') {
1045 /* C comments */
1046 inp();
1047 while (ch1 != -1) {
1048 c = ch1;
1049 inp();
1050 if (c == '*' && ch1 == '/') {
1051 inp();
1052 ch = ' '; /* return space */
1053 break;
1056 } else {
1057 ch = '/';
1059 } else {
1060 minp();
1064 void skip_spaces(void)
1066 while (ch == ' ' || ch == '\t')
1067 cinp();
1070 /* skip block of text until #else, #elif or #endif. skip also pairs of
1071 #if/#endif */
1072 void preprocess_skip()
1074 int a;
1075 a = 0;
1076 while (1) {
1077 while (ch != '\n') {
1078 if (ch == -1)
1079 expect("#endif");
1080 cinp();
1082 cinp();
1083 skip_spaces();
1084 if (ch == '#') {
1085 cinp();
1086 next_nomacro();
1087 if (a == 0 &&
1088 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1089 break;
1090 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1091 a++;
1092 else if (tok == TOK_ENDIF)
1093 a--;
1098 /* return the number of additionnal 'ints' necessary to store the
1099 token */
1100 static inline int tok_ext_size(int t)
1102 switch(t) {
1103 /* 4 bytes */
1104 case TOK_CINT:
1105 case TOK_CUINT:
1106 case TOK_CCHAR:
1107 case TOK_LCHAR:
1108 case TOK_STR:
1109 case TOK_LSTR:
1110 case TOK_CFLOAT:
1111 return 1;
1112 case TOK_CDOUBLE:
1113 case TOK_CLLONG:
1114 case TOK_CULLONG:
1115 return 2;
1116 case TOK_CLDOUBLE:
1117 return LDOUBLE_SIZE / 4;
1118 default:
1119 return 0;
1123 void tok_add(int **tok_str, int *tok_len, int t)
1125 int len, *str;
1126 len = *tok_len;
1127 str = *tok_str;
1128 if ((len & 63) == 0) {
1129 str = realloc(str, (len + 64) * sizeof(int));
1130 if (!str)
1131 return;
1132 *tok_str = str;
1134 str[len++] = t;
1135 *tok_len = len;
1138 void tok_add2(int **tok_str, int *tok_len, int t, CValue *cv)
1140 int n, i;
1142 tok_add(tok_str, tok_len, t);
1143 n = tok_ext_size(t);
1144 for(i=0;i<n;i++)
1145 tok_add(tok_str, tok_len, cv->tab[i]);
1148 /* get a token from an integer array and increment pointer accordingly */
1149 int tok_get(int **tok_str, CValue *cv)
1151 int *p, t, n, i;
1153 p = *tok_str;
1154 t = *p++;
1155 n = tok_ext_size(t);
1156 for(i=0;i<n;i++)
1157 cv->tab[i] = *p++;
1158 *tok_str = p;
1159 return t;
1162 /* eval an expression for #if/#elif */
1163 int expr_preprocess(void)
1165 int *str, len, c, t;
1167 str = NULL;
1168 len = 0;
1169 while (1) {
1170 skip_spaces();
1171 if (ch == '\n')
1172 break;
1173 next(); /* do macro subst */
1174 if (tok == TOK_DEFINED) {
1175 next_nomacro();
1176 t = tok;
1177 if (t == '(')
1178 next_nomacro();
1179 c = sym_find1(&define_stack, tok) != 0;
1180 if (t == '(')
1181 next_nomacro();
1182 tok = TOK_CINT;
1183 tokc.i = c;
1184 } else if (tok >= TOK_IDENT) {
1185 /* if undefined macro */
1186 tok = TOK_CINT;
1187 tokc.i = 0;
1189 tok_add2(&str, &len, tok, &tokc);
1191 tok_add(&str, &len, -1); /* simulate end of file */
1192 tok_add(&str, &len, 0);
1193 /* now evaluate C constant expression */
1194 macro_ptr = str;
1195 next();
1196 c = expr_const();
1197 macro_ptr = NULL;
1198 free(str);
1199 return c != 0;
1202 #if defined(DEBUG)
1203 void tok_print(int *str)
1205 int t;
1206 CValue cval;
1208 while (1) {
1209 t = tok_get(&str, &cval);
1210 if (!t)
1211 break;
1212 printf(" %s", get_tok_str(t, &cval));
1214 printf("\n");
1216 #endif
1218 void preprocess(void)
1220 int size, i, c, v, t, *str, len;
1221 char buf[1024], *q, *p;
1222 char buf1[1024];
1223 FILE *f;
1224 Sym **ps, *first, *s;
1226 cinp();
1227 next_nomacro();
1228 redo:
1229 if (tok == TOK_DEFINE) {
1230 next_nomacro();
1231 v = tok;
1232 /* XXX: should check if same macro (ANSI) */
1233 first = NULL;
1234 t = MACRO_OBJ;
1235 /* '(' must be just after macro definition for MACRO_FUNC */
1236 if (ch == '(') {
1237 next_nomacro();
1238 next_nomacro();
1239 ps = &first;
1240 while (tok != ')') {
1241 if (tok == TOK_DOTS)
1242 tok = TOK___VA_ARGS__;
1243 s = sym_push1(&define_stack, tok | SYM_FIELD, 0, 0);
1244 *ps = s;
1245 ps = &s->next;
1246 next_nomacro();
1247 if (tok != ',')
1248 break;
1249 next_nomacro();
1251 t = MACRO_FUNC;
1253 str = NULL;
1254 len = 0;
1255 while (1) {
1256 skip_spaces();
1257 if (ch == '\n' || ch == -1)
1258 break;
1259 next_nomacro();
1260 tok_add2(&str, &len, tok, &tokc);
1262 tok_add(&str, &len, 0);
1263 #ifdef PP_DEBUG
1264 printf("define %s %d: ", get_tok_str(v, NULL), t);
1265 tok_print(str);
1266 #endif
1267 s = sym_push1(&define_stack, v, t, (int)str);
1268 s->next = first;
1269 } else if (tok == TOK_UNDEF) {
1270 next_nomacro();
1271 s = sym_find1(&define_stack, tok);
1272 /* undefine symbol by putting an invalid name */
1273 if (s)
1274 sym_undef(&define_stack, s);
1275 } else if (tok == TOK_INCLUDE) {
1276 skip_spaces();
1277 if (ch == '<') {
1278 c = '>';
1279 goto read_name;
1280 } else if (ch == '\"') {
1281 c = ch;
1282 read_name:
1283 minp();
1284 q = buf;
1285 while (ch != c && ch != '\n' && ch != -1) {
1286 if ((q - buf) < sizeof(buf) - 1)
1287 *q++ = ch;
1288 minp();
1290 *q = '\0';
1291 } else {
1292 next();
1293 if (tok != TOK_STR)
1294 error("#include syntax error");
1295 pstrcpy(buf, sizeof(buf), get_tok_str(tok, &tokc));
1296 c = '\"';
1298 /* eat all spaces and comments after include */
1299 /* XXX: slightly incorrect */
1300 while (ch1 != '\n' && ch1 != -1)
1301 inp();
1303 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
1304 error("memory full");
1305 if (c == '\"') {
1306 /* first search in current dir if "header.h" */
1307 size = 0;
1308 p = strrchr(filename, '/');
1309 if (p)
1310 size = p + 1 - filename;
1311 if (size > sizeof(buf1) - 1)
1312 size = sizeof(buf1) - 1;
1313 memcpy(buf1, filename, size);
1314 buf1[size] = '\0';
1315 pstrcat(buf1, sizeof(buf1), buf);
1316 f = fopen(buf1, "r");
1317 if (f)
1318 goto found;
1320 /* now search in standard include path */
1321 for(i=nb_include_paths - 1;i>=0;i--) {
1322 strcpy(buf1, include_paths[i]);
1323 strcat(buf1, "/");
1324 strcat(buf1, buf);
1325 f = fopen(buf1, "r");
1326 if (f)
1327 goto found;
1329 error("include file '%s' not found", buf1);
1330 f = NULL;
1331 found:
1332 /* push current file in stack */
1333 /* XXX: fix current line init */
1334 include_stack_ptr->file = file;
1335 include_stack_ptr->filename = filename;
1336 include_stack_ptr->line_num = line_num;
1337 include_stack_ptr++;
1338 file = f;
1339 filename = strdup(buf1);
1340 line_num = 1;
1341 /* add include file debug info */
1342 if (do_debug) {
1343 put_stabs(filename, N_BINCL, 0, 0, 0);
1345 } else if (tok == TOK_IFNDEF) {
1346 c = 1;
1347 goto do_ifdef;
1348 } else if (tok == TOK_IF) {
1349 c = expr_preprocess();
1350 goto do_if;
1351 } else if (tok == TOK_IFDEF) {
1352 c = 0;
1353 do_ifdef:
1354 next_nomacro();
1355 c = (sym_find1(&define_stack, tok) != 0) ^ c;
1356 do_if:
1357 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
1358 error("memory full");
1359 *ifdef_stack_ptr++ = c;
1360 goto test_skip;
1361 } else if (tok == TOK_ELSE) {
1362 if (ifdef_stack_ptr == ifdef_stack ||
1363 (ifdef_stack_ptr[-1] & 2))
1364 error("#else after #else");
1365 c = (ifdef_stack_ptr[-1] ^= 3);
1366 goto test_skip;
1367 } else if (tok == TOK_ELIF) {
1368 if (ifdef_stack_ptr == ifdef_stack ||
1369 ifdef_stack_ptr[-1] > 1)
1370 error("#elif after #else");
1371 c = expr_preprocess();
1372 ifdef_stack_ptr[-1] = c;
1373 test_skip:
1374 if (!(c & 1)) {
1375 preprocess_skip();
1376 goto redo;
1378 } else if (tok == TOK_ENDIF) {
1379 if (ifdef_stack_ptr == ifdef_stack)
1380 expect("#if");
1381 ifdef_stack_ptr--;
1382 } else if (tok == TOK_LINE) {
1383 next();
1384 if (tok != TOK_CINT)
1385 error("#line");
1386 line_num = tokc.i;
1387 skip_spaces();
1388 if (ch != '\n') {
1389 next();
1390 if (tok != TOK_STR)
1391 error("#line");
1392 /* XXX: potential memory leak */
1393 filename = strdup(get_tok_str(tok, &tokc));
1395 } else if (tok == TOK_ERROR) {
1396 error("#error");
1398 /* ignore other preprocess commands or #! for C scripts */
1399 while (ch != '\n' && ch != -1)
1400 cinp();
1403 /* read a number in base b */
1404 int getn(b)
1406 int n, t;
1407 n = 0;
1408 while (1) {
1409 if (ch >= 'a' && ch <= 'f')
1410 t = ch - 'a' + 10;
1411 else if (ch >= 'A' && ch <= 'F')
1412 t = ch - 'A' + 10;
1413 else if (isnum(ch))
1414 t = ch - '0';
1415 else
1416 break;
1417 if (t < 0 || t >= b)
1418 break;
1419 n = n * b + t;
1420 cinp();
1422 return n;
1425 /* read a character for string or char constant and eval escape codes */
1426 int getq()
1428 int c;
1430 c = ch;
1431 minp();
1432 if (c == '\\') {
1433 if (isnum(ch)) {
1434 /* at most three octal digits */
1435 c = ch - '0';
1436 minp();
1437 if (isnum(ch)) {
1438 c = c * 8 + ch - '0';
1439 minp();
1440 if (isnum(ch)) {
1441 c = c * 8 + ch - '0';
1442 minp();
1445 return c;
1446 } else if (ch == 'x') {
1447 minp();
1448 return getn(16);
1449 } else {
1450 if (ch == 'a')
1451 c = '\a';
1452 else if (ch == 'b')
1453 c = '\b';
1454 else if (ch == 'f')
1455 c = '\f';
1456 else if (ch == 'n')
1457 c = '\n';
1458 else if (ch == 'r')
1459 c = '\r';
1460 else if (ch == 't')
1461 c = '\t';
1462 else if (ch == 'v')
1463 c = '\v';
1464 else if (ch == 'e' && gnu_ext)
1465 c = 27;
1466 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
1467 c = ch;
1468 else
1469 error("invalid escaped char");
1470 minp();
1473 return c;
1476 /* we use 64 bit numbers */
1477 #define BN_SIZE 2
1479 /* bn = (bn << shift) | or_val */
1480 void bn_lshift(unsigned int *bn, int shift, int or_val)
1482 int i;
1483 unsigned int v;
1484 for(i=0;i<BN_SIZE;i++) {
1485 v = bn[i];
1486 bn[i] = (v << shift) | or_val;
1487 or_val = v >> (32 - shift);
1491 void bn_zero(unsigned int *bn)
1493 int i;
1494 for(i=0;i<BN_SIZE;i++) {
1495 bn[i] = 0;
1499 void parse_number(void)
1501 int b, t, shift, frac_bits, s, exp_val;
1502 char *q;
1503 unsigned int bn[BN_SIZE];
1504 double d;
1506 /* number */
1507 q = token_buf;
1508 t = ch;
1509 cinp();
1510 *q++ = t;
1511 b = 10;
1512 if (t == '.') {
1513 /* special dot handling */
1514 if (ch >= '0' && ch <= '9') {
1515 goto float_frac_parse;
1516 } else if (ch == '.') {
1517 cinp();
1518 if (ch != '.')
1519 expect("'.'");
1520 cinp();
1521 tok = TOK_DOTS;
1522 } else {
1523 /* dots */
1524 tok = t;
1526 return;
1527 } else if (t == '0') {
1528 if (ch == 'x' || ch == 'X') {
1529 q--;
1530 cinp();
1531 b = 16;
1532 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1533 q--;
1534 cinp();
1535 b = 2;
1538 /* parse all digits. cannot check octal numbers at this stage
1539 because of floating point constants */
1540 while (1) {
1541 if (ch >= 'a' && ch <= 'f')
1542 t = ch - 'a' + 10;
1543 else if (ch >= 'A' && ch <= 'F')
1544 t = ch - 'A' + 10;
1545 else if (isnum(ch))
1546 t = ch - '0';
1547 else
1548 break;
1549 if (t >= b)
1550 break;
1551 if (q >= token_buf + STRING_MAX_SIZE) {
1552 num_too_long:
1553 error("number too long");
1555 *q++ = ch;
1556 cinp();
1558 if (ch == '.' ||
1559 ((ch == 'e' || ch == 'E') && b == 10) ||
1560 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1561 if (b != 10) {
1562 /* NOTE: strtox should support that for hexa numbers, but
1563 non ISOC99 libcs do not support it, so we prefer to do
1564 it by hand */
1565 /* hexadecimal or binary floats */
1566 /* XXX: handle overflows */
1567 *q = '\0';
1568 if (b == 16)
1569 shift = 4;
1570 else
1571 shift = 2;
1572 bn_zero(bn);
1573 q = token_buf;
1574 while (1) {
1575 t = *q++;
1576 if (t == '\0') {
1577 break;
1578 } else if (t >= 'a') {
1579 t = t - 'a' + 10;
1580 } else if (t >= 'A') {
1581 t = t - 'A' + 10;
1582 } else {
1583 t = t - '0';
1585 bn_lshift(bn, shift, t);
1587 frac_bits = 0;
1588 if (ch == '.') {
1589 cinp();
1590 while (1) {
1591 t = ch;
1592 if (t >= 'a' && t <= 'f') {
1593 t = t - 'a' + 10;
1594 } else if (t >= 'A' && t <= 'F') {
1595 t = t - 'A' + 10;
1596 } else if (t >= '0' && t <= '9') {
1597 t = t - '0';
1598 } else {
1599 break;
1601 if (t >= b)
1602 error("invalid digit");
1603 bn_lshift(bn, shift, t);
1604 frac_bits += shift;
1605 cinp();
1608 if (ch != 'p' && ch != 'P')
1609 error("exponent expected");
1610 cinp();
1611 s = 1;
1612 exp_val = 0;
1613 if (ch == '+') {
1614 cinp();
1615 } else if (ch == '-') {
1616 s = -1;
1617 cinp();
1619 if (ch < '0' || ch > '9')
1620 error("exponent digits expected");
1621 while (ch >= '0' && ch <= '9') {
1622 exp_val = exp_val * 10 + ch - '0';
1623 cinp();
1625 exp_val = exp_val * s;
1627 /* now we can generate the number */
1628 /* XXX: should patch directly float number */
1629 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1630 d = ldexp(d, exp_val - frac_bits);
1631 t = toup(ch);
1632 if (t == 'F') {
1633 cinp();
1634 tok = TOK_CFLOAT;
1635 /* float : should handle overflow */
1636 tokc.f = (float)d;
1637 } else if (t == 'L') {
1638 cinp();
1639 tok = TOK_CLDOUBLE;
1640 /* XXX: not large enough */
1641 tokc.ld = (long double)d;
1642 } else {
1643 tok = TOK_CDOUBLE;
1644 tokc.d = d;
1646 } else {
1647 /* decimal floats */
1648 if (ch == '.') {
1649 if (q >= token_buf + STRING_MAX_SIZE)
1650 goto num_too_long;
1651 *q++ = ch;
1652 cinp();
1653 float_frac_parse:
1654 while (ch >= '0' && ch <= '9') {
1655 if (q >= token_buf + STRING_MAX_SIZE)
1656 goto num_too_long;
1657 *q++ = ch;
1658 cinp();
1661 if (ch == 'e' || ch == 'E') {
1662 if (q >= token_buf + STRING_MAX_SIZE)
1663 goto num_too_long;
1664 *q++ = ch;
1665 cinp();
1666 if (ch == '-' || ch == '+') {
1667 if (q >= token_buf + STRING_MAX_SIZE)
1668 goto num_too_long;
1669 *q++ = ch;
1670 cinp();
1672 if (ch < '0' || ch > '9')
1673 error("exponent digits expected");
1674 while (ch >= '0' && ch <= '9') {
1675 if (q >= token_buf + STRING_MAX_SIZE)
1676 goto num_too_long;
1677 *q++ = ch;
1678 cinp();
1681 *q = '\0';
1682 t = toup(ch);
1683 errno = 0;
1684 if (t == 'F') {
1685 cinp();
1686 tok = TOK_CFLOAT;
1687 tokc.f = strtof(token_buf, NULL);
1688 } else if (t == 'L') {
1689 cinp();
1690 tok = TOK_CLDOUBLE;
1691 tokc.ld = strtold(token_buf, NULL);
1692 } else {
1693 tok = TOK_CDOUBLE;
1694 tokc.d = strtod(token_buf, NULL);
1697 } else {
1698 unsigned long long n, n1;
1699 int lcount;
1701 /* integer number */
1702 *q = '\0';
1703 q = token_buf;
1704 if (b == 10 && *q == '0') {
1705 b = 8;
1706 q++;
1708 n = 0;
1709 while(1) {
1710 t = *q++;
1711 /* no need for checks except for base 10 / 8 errors */
1712 if (t == '\0') {
1713 break;
1714 } else if (t >= 'a') {
1715 t = t - 'a' + 10;
1716 } else if (t >= 'A') {
1717 t = t - 'A' + 10;
1718 } else {
1719 t = t - '0';
1720 if (t >= b)
1721 error("invalid digit");
1723 n1 = n;
1724 n = n * b + t;
1725 /* detect overflow */
1726 if (n < n1)
1727 error("integer constant overflow");
1730 /* XXX: not exactly ANSI compliant */
1731 if ((n & 0xffffffff00000000LL) != 0) {
1732 if ((n >> 63) != 0)
1733 tok = TOK_CULLONG;
1734 else
1735 tok = TOK_CLLONG;
1736 } else if (n > 0x7fffffff) {
1737 tok = TOK_CUINT;
1738 } else {
1739 tok = TOK_CINT;
1741 lcount = 0;
1742 for(;;) {
1743 t = toup(ch);
1744 if (t == 'L') {
1745 if (lcount >= 2)
1746 error("three 'l' in integer constant");
1747 lcount++;
1748 if (lcount == 2) {
1749 if (tok == TOK_CINT)
1750 tok = TOK_CLLONG;
1751 else if (tok == TOK_CUINT)
1752 tok = TOK_CULLONG;
1754 cinp();
1755 } else if (t == 'U') {
1756 if (tok == TOK_CINT)
1757 tok = TOK_CUINT;
1758 else if (tok == TOK_CLLONG)
1759 tok = TOK_CULLONG;
1760 cinp();
1761 } else {
1762 break;
1765 if (tok == TOK_CINT || tok == TOK_CUINT)
1766 tokc.ui = n;
1767 else
1768 tokc.ull = n;
1773 /* return next token without macro substitution */
1774 void next_nomacro1(void)
1776 int b;
1777 char *q;
1778 TokenSym *ts;
1780 /* skip spaces */
1781 while(1) {
1782 while (ch == '\n') {
1783 cinp();
1784 while (ch == ' ' || ch == 9)
1785 cinp();
1786 if (ch == '#') {
1787 /* preprocessor command if # at start of line after
1788 spaces */
1789 preprocess();
1792 if (ch != ' ' && ch != '\t' && ch != '\f')
1793 break;
1794 cinp();
1796 if (isid(ch)) {
1797 q = token_buf;
1798 *q++ = ch;
1799 cinp();
1800 if (q[-1] == 'L') {
1801 if (ch == '\'') {
1802 tok = TOK_LCHAR;
1803 goto char_const;
1805 if (ch == '\"') {
1806 tok = TOK_LSTR;
1807 goto str_const;
1810 while (isid(ch) || isnum(ch)) {
1811 if (q >= token_buf + STRING_MAX_SIZE)
1812 error("ident too long");
1813 *q++ = ch;
1814 cinp();
1816 *q = '\0';
1817 ts = tok_alloc(token_buf, q - token_buf);
1818 tok = ts->tok;
1819 } else if (isnum(ch) || ch == '.') {
1820 parse_number();
1821 } else if (ch == '\'') {
1822 tok = TOK_CCHAR;
1823 char_const:
1824 minp();
1825 tokc.i = getq();
1826 if (ch != '\'')
1827 expect("\'");
1828 minp();
1829 } else if (ch == '\"') {
1830 tok = TOK_STR;
1831 str_const:
1832 minp();
1833 q = token_buf;
1834 while (ch != '\"') {
1835 b = getq();
1836 if (ch == -1)
1837 error("unterminated string");
1838 if (q >= token_buf + STRING_MAX_SIZE)
1839 error("string too long");
1840 *q++ = b;
1842 *q = '\0';
1843 tokc.ts = tok_alloc(token_buf, q - token_buf);
1844 minp();
1845 } else {
1846 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
1847 /* two chars */
1848 tok = ch;
1849 cinp();
1850 while (*q) {
1851 if (*q == tok && q[1] == ch) {
1852 cinp();
1853 tok = q[2] & 0xff;
1854 /* three chars tests */
1855 if (tok == TOK_SHL || tok == TOK_SAR) {
1856 if (ch == '=') {
1857 tok = tok | 0x80;
1858 cinp();
1860 } else if (tok == TOK_DOTS) {
1861 if (ch != '.')
1862 error("parse error");
1863 cinp();
1865 return;
1867 q = q + 3;
1869 /* single char substitutions */
1870 if (tok == '<')
1871 tok = TOK_LT;
1872 else if (tok == '>')
1873 tok = TOK_GT;
1877 /* return next token without macro substitution. Can read input from
1878 macro_ptr buffer */
1879 void next_nomacro()
1881 if (macro_ptr) {
1882 tok = *macro_ptr;
1883 if (tok)
1884 tok = tok_get(&macro_ptr, &tokc);
1885 } else {
1886 next_nomacro1();
1890 /* substitute args in macro_str and return allocated string */
1891 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
1893 int *st, last_tok, t, notfirst, *str, len;
1894 Sym *s;
1895 TokenSym *ts;
1896 CValue cval;
1898 str = NULL;
1899 len = 0;
1900 last_tok = 0;
1901 while(1) {
1902 t = tok_get(&macro_str, &cval);
1903 if (!t)
1904 break;
1905 if (t == '#') {
1906 /* stringize */
1907 t = tok_get(&macro_str, &cval);
1908 if (!t)
1909 break;
1910 s = sym_find2(args, t);
1911 if (s) {
1912 token_buf[0] = '\0';
1913 st = (int *)s->c;
1914 notfirst = 0;
1915 while (*st) {
1916 if (notfirst)
1917 pstrcat(token_buf, sizeof(token_buf), " ");
1918 t = tok_get(&st, &cval);
1919 pstrcat(token_buf, sizeof(token_buf), get_tok_str(t, &cval));
1920 notfirst = 1;
1922 #ifdef PP_DEBUG
1923 printf("stringize: %s\n", token_buf);
1924 #endif
1925 /* add string */
1926 ts = tok_alloc(token_buf, 0);
1927 cval.ts = ts;
1928 tok_add2(&str, &len, TOK_STR, &cval);
1929 } else {
1930 tok_add2(&str, &len, t, &cval);
1932 } else if (t >= TOK_IDENT) {
1933 s = sym_find2(args, t);
1934 if (s) {
1935 st = (int *)s->c;
1936 /* if '##' is present before or after , no arg substitution */
1937 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
1938 while (*st)
1939 tok_add(&str, &len, *st++);
1940 } else {
1941 macro_subst(&str, &len, nested_list, st);
1943 } else {
1944 tok_add(&str, &len, t);
1946 } else {
1947 tok_add2(&str, &len, t, &cval);
1949 last_tok = t;
1951 tok_add(&str, &len, 0);
1952 return str;
1955 /* handle the '##' operator */
1956 int *macro_twosharps(int *macro_str)
1958 TokenSym *ts;
1959 int *macro_str1, macro_str1_len, *macro_ptr1;
1960 int t;
1961 char *p;
1962 CValue cval;
1964 macro_str1 = NULL;
1965 macro_str1_len = 0;
1966 tok = 0;
1967 while (1) {
1968 next_nomacro();
1969 if (tok == 0)
1970 break;
1971 while (*macro_ptr == TOK_TWOSHARPS) {
1972 macro_ptr++;
1973 macro_ptr1 = macro_ptr;
1974 t = *macro_ptr;
1975 if (t) {
1976 t = tok_get(&macro_ptr, &cval);
1977 /* XXX: we handle only most common cases:
1978 ident + ident or ident + number */
1979 if (tok >= TOK_IDENT &&
1980 (t >= TOK_IDENT || t == TOK_CINT)) {
1981 p = get_tok_str(tok, &tokc);
1982 pstrcpy(token_buf, sizeof(token_buf), p);
1983 p = get_tok_str(t, &cval);
1984 pstrcat(token_buf, sizeof(token_buf), p);
1985 ts = tok_alloc(token_buf, 0);
1986 tok = ts->tok; /* modify current token */
1987 } else {
1988 /* cannot merge tokens: skip '##' */
1989 macro_ptr = macro_ptr1;
1990 break;
1994 tok_add2(&macro_str1, &macro_str1_len, tok, &tokc);
1996 tok_add(&macro_str1, &macro_str1_len, 0);
1997 return macro_str1;
2002 /* do macro substitution of macro_str and add result to
2003 (tok_str,tok_len). If macro_str is NULL, then input stream token is
2004 substituted. 'nested_list' is the list of all macros we got inside
2005 to avoid recursing. */
2006 void macro_subst(int **tok_str, int *tok_len,
2007 Sym **nested_list, int *macro_str)
2009 Sym *s, *args, *sa, *sa1;
2010 int *str, parlevel, len, *mstr, t, *saved_macro_ptr;
2011 int mstr_allocated, *macro_str1;
2012 CValue cval;
2014 saved_macro_ptr = macro_ptr;
2015 macro_ptr = macro_str;
2016 macro_str1 = NULL;
2017 if (macro_str) {
2018 /* first scan for '##' operator handling */
2019 macro_str1 = macro_twosharps(macro_str);
2020 macro_ptr = macro_str1;
2023 while (1) {
2024 next_nomacro();
2025 if (tok == 0)
2026 break;
2027 /* special macros */
2028 if (tok == TOK___LINE__) {
2029 cval.i = line_num;
2030 tok_add2(tok_str, tok_len, TOK_CINT, &cval);
2031 } else if (tok == TOK___FILE__) {
2032 cval.ts = tok_alloc(filename, 0);
2033 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2034 } else if (tok == TOK___DATE__) {
2035 cval.ts = tok_alloc("Jan 1 1970", 0);
2036 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2037 } else if (tok == TOK___TIME__) {
2038 cval.ts = tok_alloc("00:00:00", 0);
2039 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2040 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
2041 /* if symbol is a macro, prepare substitution */
2042 /* if nested substitution, do nothing */
2043 if (sym_find2(*nested_list, tok))
2044 goto no_subst;
2045 mstr = (int *)s->c;
2046 mstr_allocated = 0;
2047 if (s->t == MACRO_FUNC) {
2048 /* NOTE: we do not use next_nomacro to avoid eating the
2049 next token. XXX: find better solution */
2050 if (macro_ptr) {
2051 t = *macro_ptr;
2052 } else {
2053 while (ch == ' ' || ch == '\t' || ch == '\n')
2054 cinp();
2055 t = ch;
2057 if (t != '(') /* no macro subst */
2058 goto no_subst;
2060 /* argument macro */
2061 next_nomacro();
2062 next_nomacro();
2063 args = NULL;
2064 sa = s->next;
2065 while (tok != ')' && sa) {
2066 len = 0;
2067 str = NULL;
2068 parlevel = 0;
2069 while ((parlevel > 0 ||
2070 (tok != ')' &&
2071 (tok != ',' ||
2072 sa->v == (TOK___VA_ARGS__ | SYM_FIELD)))) &&
2073 tok != -1) {
2074 if (tok == '(')
2075 parlevel++;
2076 else if (tok == ')')
2077 parlevel--;
2078 tok_add2(&str, &len, tok, &tokc);
2079 next_nomacro();
2081 tok_add(&str, &len, 0);
2082 sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
2083 if (tok != ',')
2084 break;
2085 next_nomacro();
2086 sa = sa->next;
2088 if (tok != ')')
2089 expect(")");
2090 /* now subst each arg */
2091 mstr = macro_arg_subst(nested_list, mstr, args);
2092 /* free memory */
2093 sa = args;
2094 while (sa) {
2095 sa1 = sa->prev;
2096 free((int *)sa->c);
2097 free(sa);
2098 sa = sa1;
2100 mstr_allocated = 1;
2102 sym_push2(nested_list, s->v, 0, 0);
2103 macro_subst(tok_str, tok_len, nested_list, mstr);
2104 /* pop nested defined symbol */
2105 sa1 = *nested_list;
2106 *nested_list = sa1->prev;
2107 free(sa1);
2108 if (mstr_allocated)
2109 free(mstr);
2110 } else {
2111 no_subst:
2112 /* no need to add if reading input stream */
2113 if (!macro_str)
2114 return;
2115 tok_add2(tok_str, tok_len, tok, &tokc);
2117 /* only replace one macro while parsing input stream */
2118 if (!macro_str)
2119 return;
2121 macro_ptr = saved_macro_ptr;
2122 if (macro_str1)
2123 free(macro_str1);
2126 /* return next token with macro substitution */
2127 void next(void)
2129 int len, *ptr;
2130 Sym *nested_list;
2132 /* special 'ungettok' case for label parsing */
2133 if (tok1) {
2134 tok = tok1;
2135 tokc = tok1c;
2136 tok1 = 0;
2137 } else {
2138 redo:
2139 if (!macro_ptr) {
2140 /* if not reading from macro substuted string, then try to substitute */
2141 len = 0;
2142 ptr = NULL;
2143 nested_list = NULL;
2144 macro_subst(&ptr, &len, &nested_list, NULL);
2145 if (ptr) {
2146 tok_add(&ptr, &len, 0);
2147 macro_ptr = ptr;
2148 macro_ptr_allocated = ptr;
2149 goto redo;
2151 if (tok == 0)
2152 goto redo;
2153 } else {
2154 next_nomacro();
2155 if (tok == 0) {
2156 /* end of macro string: free it */
2157 free(macro_ptr_allocated);
2158 macro_ptr = NULL;
2159 goto redo;
2163 #if defined(DEBUG)
2164 printf("token = %s\n", get_tok_str(tok, tokc));
2165 #endif
2168 void swap(int *p, int *q)
2170 int t;
2171 t = *p;
2172 *p = *q;
2173 *q = t;
2176 void vsetc(int t, int r, CValue *vc)
2178 if (vtop >= vstack + VSTACK_SIZE)
2179 error("memory full");
2180 /* cannot let cpu flags if other instruction are generated */
2181 /* XXX: VT_JMP test too ? */
2182 if ((vtop->r & VT_VALMASK) == VT_CMP)
2183 gv(RC_INT);
2184 vtop++;
2185 vtop->t = t;
2186 vtop->r = r;
2187 vtop->r2 = VT_CONST;
2188 vtop->c = *vc;
2191 /* push integer constant */
2192 void vpushi(int v)
2194 CValue cval;
2195 cval.i = v;
2196 vsetc(VT_INT, VT_CONST, &cval);
2199 void vset(int t, int r, int v)
2201 CValue cval;
2203 cval.i = v;
2204 vsetc(t, r, &cval);
2207 void vswap(void)
2209 SValue tmp;
2211 tmp = vtop[0];
2212 vtop[0] = vtop[-1];
2213 vtop[-1] = tmp;
2216 void vpushv(SValue *v)
2218 if (vtop >= vstack + VSTACK_SIZE)
2219 error("memory full");
2220 vtop++;
2221 *vtop = *v;
2224 void vdup(void)
2226 vpushv(vtop);
2229 /* save r to the memory stack, and mark it as being free */
2230 void save_reg(int r)
2232 int l, i, saved, t, size, align;
2233 SValue *p, sv;
2235 /* modify all stack values */
2236 saved = 0;
2237 l = 0;
2238 for(p=vstack;p<=vtop;p++) {
2239 i = p->r & VT_VALMASK;
2240 if ((p->r & VT_VALMASK) == r ||
2241 (p->r2 & VT_VALMASK) == r) {
2242 /* must save value on stack if not already done */
2243 if (!saved) {
2244 /* store register in the stack */
2245 t = p->t;
2246 if (!is_float(t) && (t & VT_BTYPE) != VT_LLONG)
2247 t = VT_INT;
2248 size = type_size(t, &align);
2249 loc = (loc - size) & -align;
2250 sv.t = t;
2251 sv.r = VT_LOCAL | VT_LVAL;
2252 sv.c.ul = loc;
2253 store(r, &sv);
2254 /* XXX: x86 specific: need to pop fp register ST0 if saved */
2255 if (r == REG_ST0) {
2256 o(0xd9dd); /* fstp %st(1) */
2258 /* special long long case */
2259 if ((p->t & VT_BTYPE) == VT_LLONG) {
2260 sv.c.ul += 4;
2261 store(p->r2, &sv);
2263 l = loc;
2264 saved = 1;
2266 /* mark that stack entry as being saved on the stack */
2267 if (p->r & VT_LVAL)
2268 t = VT_LLOCAL;
2269 else
2270 t = VT_LOCAL;
2271 p->r = VT_LVAL | t;
2272 p->r2 = VT_CONST;
2273 p->c.ul = l;
2278 /* find a free register of class 'rc'. If none, save one register */
2279 int get_reg(int rc)
2281 int r;
2282 SValue *p;
2284 /* find a free register */
2285 for(r=0;r<NB_REGS;r++) {
2286 if (reg_classes[r] & rc) {
2287 for(p=vstack;p<=vtop;p++) {
2288 if ((p->r & VT_VALMASK) == r ||
2289 (p->r2 & VT_VALMASK) == r)
2290 goto notfound;
2292 return r;
2294 notfound: ;
2297 /* no register left : free the first one on the stack (VERY
2298 IMPORTANT to start from the bottom to ensure that we don't
2299 spill registers used in gen_opi()) */
2300 for(p=vstack;p<=vtop;p++) {
2301 r = p->r & VT_VALMASK;
2302 if (r < VT_CONST && (reg_classes[r] & rc)) {
2303 save_reg(r);
2304 break;
2307 return r;
2310 void save_regs(void)
2312 int r;
2313 SValue *p;
2315 for(p=vstack;p<=vtop;p++) {
2316 r = p->r & VT_VALMASK;
2317 if (r < VT_CONST) {
2318 save_reg(r);
2323 /* move register 's' to 'r', and flush previous value of r to memory
2324 if needed */
2325 void move_reg(int r, int s)
2327 SValue sv;
2329 if (r != s) {
2330 save_reg(r);
2331 sv.t = VT_INT;
2332 sv.r = s;
2333 sv.c.ul = 0;
2334 load(r, &sv);
2338 /* get address of vtop (vtop MUST BE an lvalue) */
2339 void gaddrof(void)
2341 vtop->r &= ~VT_LVAL;
2342 /* tricky: if saved lvalue, then we can go back to lvalue */
2343 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
2344 vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
2347 /* generate lvalue bound code */
2348 void gbound(void)
2350 vtop->r &= ~VT_MUSTBOUND;
2351 /* if lvalue, then use checking code before dereferencing */
2352 if (vtop->r & VT_LVAL) {
2353 gaddrof();
2354 vpushi(0);
2355 gen_bounded_ptr_add1();
2356 gen_bounded_ptr_add2(1);
2357 vtop->r |= VT_LVAL;
2361 /* store vtop a register belonging to class 'rc'. lvalues are
2362 converted to values. Cannot be used if cannot be converted to
2363 register value (such as structures). */
2364 int gv(int rc)
2366 int r, r2, rc2, bit_pos, bit_size, size, align, i, data_offset;
2367 unsigned long long ll;
2369 /* NOTE: get_reg can modify vstack[] */
2370 if (vtop->t & VT_BITFIELD) {
2371 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
2372 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2373 /* remove bit field info to avoid loops */
2374 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2375 /* generate shifts */
2376 vpushi(32 - (bit_pos + bit_size));
2377 gen_op(TOK_SHL);
2378 vpushi(32 - bit_size);
2379 /* NOTE: transformed to SHR if unsigned */
2380 gen_op(TOK_SAR);
2381 r = gv(rc);
2382 } else {
2383 if (is_float(vtop->t) &&
2384 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2385 /* CPUs usually cannot use float constants, so we store them
2386 generically in data segment */
2387 size = type_size(vtop->t, &align);
2388 data_offset = (int)data_section->data_ptr;
2389 data_offset = (data_offset + align - 1) & -align;
2390 /* XXX: not portable yet */
2391 size = size >> 2;
2392 for(i=0;i<size;i++)
2393 ((int *)data_offset)[i] = vtop->c.tab[i];
2394 vtop->r |= VT_LVAL;
2395 vtop->c.ul = data_offset;
2396 data_offset += size << 2;
2397 data_section->data_ptr = (unsigned char *)data_offset;
2399 if (vtop->r & VT_MUSTBOUND)
2400 gbound();
2402 r = vtop->r & VT_VALMASK;
2403 /* need to reload if:
2404 - constant
2405 - lvalue (need to dereference pointer)
2406 - already a register, but not in the right class */
2407 if (r >= VT_CONST ||
2408 (vtop->r & VT_LVAL) ||
2409 !(reg_classes[r] & rc) ||
2410 ((vtop->t & VT_BTYPE) == VT_LLONG &&
2411 !(reg_classes[vtop->r2] & rc))) {
2412 r = get_reg(rc);
2413 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
2414 /* two register type load : expand to two words
2415 temporarily */
2416 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2417 /* load constant */
2418 ll = vtop->c.ull;
2419 vtop->c.ui = ll; /* first word */
2420 load(r, vtop);
2421 vtop->r = r; /* save register value */
2422 vpushi(ll >> 32); /* second word */
2423 } else if (r >= VT_CONST ||
2424 (vtop->r & VT_LVAL)) {
2425 /* load from memory */
2426 load(r, vtop);
2427 vdup();
2428 vtop[-1].r = r; /* save register value */
2429 /* increment pointer to get second word */
2430 vtop->t = VT_INT;
2431 gaddrof();
2432 vpushi(4);
2433 gen_op('+');
2434 vtop->r |= VT_LVAL;
2435 } else {
2436 /* move registers */
2437 load(r, vtop);
2438 vdup();
2439 vtop[-1].r = r; /* save register value */
2440 vtop->r = vtop[-1].r2;
2442 /* allocate second register */
2443 rc2 = RC_INT;
2444 if (rc == RC_IRET)
2445 rc2 = RC_LRET;
2446 r2 = get_reg(rc2);
2447 load(r2, vtop);
2448 vpop();
2449 /* write second register */
2450 vtop->r2 = r2;
2451 } else {
2452 /* one register type load */
2453 load(r, vtop);
2456 vtop->r = r;
2458 return r;
2461 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
2462 void gv2(int rc1, int rc2)
2464 /* generate more generic register first */
2465 if (rc1 <= rc2) {
2466 vswap();
2467 gv(rc1);
2468 vswap();
2469 gv(rc2);
2470 /* test if reload is needed for first register */
2471 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
2472 vswap();
2473 gv(rc1);
2474 vswap();
2476 } else {
2477 gv(rc2);
2478 vswap();
2479 gv(rc1);
2480 vswap();
2481 /* test if reload is needed for first register */
2482 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
2483 gv(rc2);
2488 /* expand long long on stack in two int registers */
2489 void lexpand(void)
2491 int u;
2493 u = vtop->t & VT_UNSIGNED;
2494 gv(RC_INT);
2495 vdup();
2496 vtop[0].r = vtop[-1].r2;
2497 vtop[0].r2 = VT_CONST;
2498 vtop[-1].r2 = VT_CONST;
2499 vtop[0].t = VT_INT | u;
2500 vtop[-1].t = VT_INT | u;
2503 /* build a long long from two ints */
2504 void lbuild(int t)
2506 gv2(RC_INT, RC_INT);
2507 vtop[-1].r2 = vtop[0].r;
2508 vtop[-1].t = t;
2509 vpop();
2512 /* rotate n first stack elements to the bottom */
2513 void vrotb(int n)
2515 int i;
2516 SValue tmp;
2518 tmp = vtop[-n + 1];
2519 for(i=-n+1;i!=0;i++)
2520 vtop[i] = vtop[i+1];
2521 vtop[0] = tmp;
2524 /* pop stack value */
2525 void vpop(void)
2527 /* for x86, we need to pop the FP stack */
2528 if ((vtop->r & VT_VALMASK) == REG_ST0) {
2529 o(0xd9dd); /* fstp %st(1) */
2531 vtop--;
2534 /* convert stack entry to register and duplicate its value in another
2535 register */
2536 void gv_dup(void)
2538 int rc, t, r, r1;
2539 SValue sv;
2541 t = vtop->t;
2542 if ((t & VT_BTYPE) == VT_LLONG) {
2543 lexpand();
2544 gv_dup();
2545 vswap();
2546 vrotb(3);
2547 gv_dup();
2548 vrotb(4);
2549 /* stack: H L L1 H1 */
2550 lbuild(t);
2551 vrotb(3);
2552 vrotb(3);
2553 vswap();
2554 lbuild(t);
2555 vswap();
2556 } else {
2557 /* duplicate value */
2558 rc = RC_INT;
2559 sv.t = VT_INT;
2560 if (is_float(t)) {
2561 rc = RC_FLOAT;
2562 sv.t = t;
2564 r = gv(rc);
2565 r1 = get_reg(rc);
2566 sv.r = r;
2567 sv.c.ul = 0;
2568 load(r1, &sv); /* move r to r1 */
2569 vdup();
2570 /* duplicates value */
2571 vtop->r = r1;
2575 /* generate CPU independent (unsigned) long long operations */
2576 void gen_opl(int op)
2578 int t, a, b, op1, c, i;
2579 void *func;
2580 GFuncContext gf;
2581 SValue tmp;
2583 switch(op) {
2584 case '/':
2585 case TOK_PDIV:
2586 func = __divll;
2587 goto gen_func;
2588 case TOK_UDIV:
2589 func = __divull;
2590 goto gen_func;
2591 case '%':
2592 func = __modll;
2593 goto gen_func;
2594 case TOK_UMOD:
2595 func = __modull;
2596 gen_func:
2597 /* call generic long long function */
2598 gfunc_start(&gf);
2599 gfunc_param(&gf);
2600 gfunc_param(&gf);
2601 vpushi((int)func);
2602 gfunc_call(&gf);
2603 vpushi(0);
2604 vtop->r = REG_IRET;
2605 vtop->r2 = REG_LRET;
2606 break;
2607 case '^':
2608 case '&':
2609 case '|':
2610 case '*':
2611 case '+':
2612 case '-':
2613 t = vtop->t;
2614 vswap();
2615 lexpand();
2616 vrotb(3);
2617 lexpand();
2618 /* stack: L1 H1 L2 H2 */
2619 tmp = vtop[0];
2620 vtop[0] = vtop[-3];
2621 vtop[-3] = tmp;
2622 tmp = vtop[-2];
2623 vtop[-2] = vtop[-3];
2624 vtop[-3] = tmp;
2625 vswap();
2626 /* stack: H1 H2 L1 L2 */
2627 if (op == '*') {
2628 vpushv(vtop - 1);
2629 vpushv(vtop - 1);
2630 gen_op(TOK_UMULL);
2631 lexpand();
2632 /* stack: H1 H2 L1 L2 ML MH */
2633 for(i=0;i<4;i++)
2634 vrotb(6);
2635 /* stack: ML MH H1 H2 L1 L2 */
2636 tmp = vtop[0];
2637 vtop[0] = vtop[-2];
2638 vtop[-2] = tmp;
2639 /* stack: ML MH H1 L2 H2 L1 */
2640 gen_op('*');
2641 vrotb(3);
2642 vrotb(3);
2643 gen_op('*');
2644 /* stack: ML MH M1 M2 */
2645 gen_op('+');
2646 gen_op('+');
2647 } else if (op == '+' || op == '-') {
2648 /* XXX: add non carry method too (for MIPS ?) */
2649 if (op == '+')
2650 op1 = TOK_ADDC1;
2651 else
2652 op1 = TOK_SUBC1;
2653 gen_op(op1);
2654 /* stack: H1 H2 (L1 op L2) */
2655 vrotb(3);
2656 vrotb(3);
2657 gen_op(op1 + 1); /* TOK_xxxC2 */
2658 } else {
2659 gen_op(op);
2660 /* stack: H1 H2 (L1 op L2) */
2661 vrotb(3);
2662 vrotb(3);
2663 /* stack: (L1 op L2) H1 H2 */
2664 gen_op(op);
2665 /* stack: (L1 op L2) (H1 op H2) */
2667 /* stack: L H */
2668 lbuild(t);
2669 break;
2670 case TOK_SAR:
2671 case TOK_SHR:
2672 case TOK_SHL:
2673 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
2674 t = vtop[-1].t;
2675 vswap();
2676 lexpand();
2677 vrotb(3);
2678 /* stack: L H shift */
2679 c = (int)vtop->c.i;
2680 /* constant: simpler */
2681 /* NOTE: all comments are for SHL. the other cases are
2682 done by swaping words */
2683 vpop();
2684 if (op != TOK_SHL)
2685 vswap();
2686 if (c >= 32) {
2687 /* stack: L H */
2688 vpop();
2689 if (c > 32) {
2690 vpushi(c - 32);
2691 gen_op(op);
2693 if (op != TOK_SAR) {
2694 vpushi(0);
2695 } else {
2696 gv_dup();
2697 vpushi(31);
2698 gen_op(TOK_SAR);
2700 vswap();
2701 } else {
2702 vswap();
2703 gv_dup();
2704 /* stack: H L L */
2705 vpushi(c);
2706 gen_op(op);
2707 vswap();
2708 vpushi(32 - c);
2709 if (op == TOK_SHL)
2710 gen_op(TOK_SHR);
2711 else
2712 gen_op(TOK_SHL);
2713 vrotb(3);
2714 /* stack: L L H */
2715 vpushi(c);
2716 gen_op(op);
2717 gen_op('|');
2719 if (op != TOK_SHL)
2720 vswap();
2721 lbuild(t);
2722 } else {
2723 /* XXX: should provide a faster fallback on x86 ? */
2724 switch(op) {
2725 case TOK_SAR:
2726 func = __sardi3;
2727 goto gen_func;
2728 case TOK_SHR:
2729 func = __shrdi3;
2730 goto gen_func;
2731 case TOK_SHL:
2732 func = __shldi3;
2733 goto gen_func;
2736 break;
2737 default:
2738 /* compare operations */
2739 t = vtop->t;
2740 vswap();
2741 lexpand();
2742 vrotb(3);
2743 lexpand();
2744 /* stack: L1 H1 L2 H2 */
2745 tmp = vtop[-1];
2746 vtop[-1] = vtop[-2];
2747 vtop[-2] = tmp;
2748 /* stack: L1 L2 H1 H2 */
2749 /* compare high */
2750 op1 = op;
2751 /* when values are equal, we need to compare low words. since
2752 the jump is inverted, we invert the test too. */
2753 if (op1 == TOK_LT)
2754 op1 = TOK_LE;
2755 else if (op1 == TOK_GT)
2756 op1 = TOK_GE;
2757 else if (op1 == TOK_ULT)
2758 op1 = TOK_ULE;
2759 else if (op1 == TOK_UGT)
2760 op1 = TOK_UGE;
2761 a = 0;
2762 b = 0;
2763 gen_op(op1);
2764 if (op1 != TOK_NE) {
2765 a = gtst(1, 0);
2767 if (op != TOK_EQ) {
2768 /* generate non equal test */
2769 /* XXX: NOT PORTABLE yet */
2770 if (a == 0)
2771 b = gtst(0, 0);
2772 else
2773 b = psym(0x850f, 0);
2775 /* compare low */
2776 gen_op(op);
2777 a = gtst(1, a);
2778 gsym(b);
2779 vset(VT_INT, VT_JMPI, a);
2780 break;
2784 /* handle constant optimizations and various machine independant opt */
2785 void gen_opc(int op)
2787 int fc, c1, c2, n;
2788 SValue *v1, *v2;
2790 v1 = vtop - 1;
2791 v2 = vtop;
2792 /* currently, we cannot do computations with forward symbols */
2793 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2794 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2795 if (c1 && c2) {
2796 fc = v2->c.i;
2797 switch(op) {
2798 case '+': v1->c.i += fc; break;
2799 case '-': v1->c.i -= fc; break;
2800 case '&': v1->c.i &= fc; break;
2801 case '^': v1->c.i ^= fc; break;
2802 case '|': v1->c.i |= fc; break;
2803 case '*': v1->c.i *= fc; break;
2804 case TOK_PDIV:
2805 case '/': v1->c.i /= fc; break; /* XXX: zero case ? */
2806 case '%': v1->c.i %= fc; break; /* XXX: zero case ? */
2807 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break; /* XXX: zero case ? */
2808 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break; /* XXX: zero case ? */
2809 case TOK_SHL: v1->c.i <<= fc; break;
2810 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
2811 case TOK_SAR: v1->c.i >>= fc; break;
2812 /* tests */
2813 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
2814 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
2815 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
2816 case TOK_NE: v1->c.i = v1->c.i != fc; break;
2817 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
2818 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
2819 case TOK_LT: v1->c.i = v1->c.i < fc; break;
2820 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
2821 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
2822 case TOK_GT: v1->c.i = v1->c.i > fc; break;
2823 /* logical */
2824 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
2825 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
2826 default:
2827 goto general_case;
2829 vtop--;
2830 } else {
2831 /* if commutative ops, put c2 as constant */
2832 if (c1 && (op == '+' || op == '&' || op == '^' ||
2833 op == '|' || op == '*')) {
2834 vswap();
2835 swap(&c1, &c2);
2837 fc = vtop->c.i;
2838 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
2839 op == TOK_PDIV) &&
2840 fc == 1) ||
2841 ((op == '+' || op == '-' || op == '|' || op == '^' ||
2842 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
2843 fc == 0) ||
2844 (op == '&' &&
2845 fc == -1))) {
2846 /* nothing to do */
2847 vtop--;
2848 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
2849 /* try to use shifts instead of muls or divs */
2850 if (fc > 0 && (fc & (fc - 1)) == 0) {
2851 n = -1;
2852 while (fc) {
2853 fc >>= 1;
2854 n++;
2856 vtop->c.i = n;
2857 if (op == '*')
2858 op = TOK_SHL;
2859 else if (op == TOK_PDIV)
2860 op = TOK_SAR;
2861 else
2862 op = TOK_SHR;
2864 goto general_case;
2865 } else {
2866 general_case:
2867 /* call low level op generator */
2868 /* XXX: remove explicit registers */
2869 gen_opi(op);
2874 int pointed_size(int t)
2876 return type_size(pointed_type(t), &t);
2879 #if 0
2880 void check_pointer_types(SValue *p1, SValue *p2)
2882 char buf1[256], buf2[256];
2883 int t1, t2;
2884 t1 = p1->t;
2885 t2 = p2->t;
2886 if (!is_compatible_types(t1, t2)) {
2887 type_to_str(buf1, sizeof(buf1), t1, NULL);
2888 type_to_str(buf2, sizeof(buf2), t2, NULL);
2889 error("incompatible pointers '%s' and '%s'", buf1, buf2);
2892 #endif
2894 /* generic gen_op: handles types problems */
2895 void gen_op(int op)
2897 int u, t1, t2, bt1, bt2, t;
2899 t1 = vtop[-1].t;
2900 t2 = vtop[0].t;
2901 bt1 = t1 & VT_BTYPE;
2902 bt2 = t2 & VT_BTYPE;
2904 if (bt1 == VT_PTR || bt2 == VT_PTR) {
2905 /* at least one operand is a pointer */
2906 /* relationnal op: must be both pointers */
2907 if (op >= TOK_ULT && op <= TOK_GT) {
2908 // check_pointer_types(vtop, vtop - 1);
2909 /* pointers are handled are unsigned */
2910 t = VT_INT | VT_UNSIGNED;
2911 goto std_op;
2913 /* if both pointers, then it must be the '-' op */
2914 if ((t1 & VT_BTYPE) == VT_PTR &&
2915 (t2 & VT_BTYPE) == VT_PTR) {
2916 if (op != '-')
2917 error("cannot use pointers here");
2918 // check_pointer_types(vtop - 1, vtop);
2919 /* XXX: check that types are compatible */
2920 u = pointed_size(t1);
2921 gen_opc(op);
2922 /* set to integer type */
2923 vtop->t = VT_INT;
2924 vpushi(u);
2925 gen_op(TOK_PDIV);
2926 } else {
2927 /* exactly one pointer : must be '+' or '-'. */
2928 if (op != '-' && op != '+')
2929 error("cannot use pointers here");
2930 /* Put pointer as first operand */
2931 if ((t2 & VT_BTYPE) == VT_PTR) {
2932 vswap();
2933 swap(&t1, &t2);
2935 /* XXX: cast to int ? (long long case) */
2936 vpushi(pointed_size(vtop[-1].t));
2937 gen_op('*');
2938 if (do_bounds_check) {
2939 /* if bounded pointers, we generate a special code to
2940 test bounds */
2941 if (op == '-') {
2942 vpushi(0);
2943 vswap();
2944 gen_op('-');
2946 gen_bounded_ptr_add1();
2947 gen_bounded_ptr_add2(0);
2948 } else {
2949 gen_opc(op);
2951 /* put again type if gen_opc() swaped operands */
2952 vtop->t = t1;
2954 } else if (is_float(bt1) || is_float(bt2)) {
2955 /* compute bigger type and do implicit casts */
2956 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
2957 t = VT_LDOUBLE;
2958 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
2959 t = VT_DOUBLE;
2960 } else {
2961 t = VT_FLOAT;
2963 /* floats can only be used for a few operations */
2964 if (op != '+' && op != '-' && op != '*' && op != '/' &&
2965 (op < TOK_ULT || op > TOK_GT))
2966 error("invalid operands for binary operation");
2967 goto std_op;
2968 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
2969 /* cast to biggest op */
2970 t = VT_LLONG;
2971 /* convert to unsigned if it does not fit in a long long */
2972 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
2973 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
2974 t |= VT_UNSIGNED;
2975 goto std_op;
2976 } else {
2977 /* integer operations */
2978 t = VT_INT;
2979 /* convert to unsigned if it does not fit in an integer */
2980 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
2981 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
2982 t |= VT_UNSIGNED;
2983 std_op:
2984 /* XXX: currently, some unsigned operations are explicit, so
2985 we modify them here */
2986 if (t & VT_UNSIGNED) {
2987 if (op == TOK_SAR)
2988 op = TOK_SHR;
2989 else if (op == '/')
2990 op = TOK_UDIV;
2991 else if (op == '%')
2992 op = TOK_UMOD;
2993 else if (op == TOK_LT)
2994 op = TOK_ULT;
2995 else if (op == TOK_GT)
2996 op = TOK_UGT;
2997 else if (op == TOK_LE)
2998 op = TOK_ULE;
2999 else if (op == TOK_GE)
3000 op = TOK_UGE;
3002 vswap();
3003 gen_cast(t);
3004 vswap();
3005 /* special case for shifts and long long: we keep the shift as
3006 an integer */
3007 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
3008 gen_cast(VT_INT);
3009 else
3010 gen_cast(t);
3011 if (is_float(t))
3012 gen_opf(op);
3013 else if ((t & VT_BTYPE) == VT_LLONG)
3014 gen_opl(op);
3015 else
3016 gen_opc(op);
3017 if (op >= TOK_ULT && op <= TOK_GT) {
3018 /* relationnal op: the result is an int */
3019 vtop->t = VT_INT;
3020 } else {
3021 vtop->t = t;
3026 /* generic itof for unsigned long long case */
3027 void gen_cvt_itof1(int t)
3029 GFuncContext gf;
3031 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
3032 (VT_LLONG | VT_UNSIGNED)) {
3034 gfunc_start(&gf);
3035 gfunc_param(&gf);
3036 if (t == VT_FLOAT)
3037 vpushi((int)&__ulltof);
3038 else if (t == VT_DOUBLE)
3039 vpushi((int)&__ulltod);
3040 else
3041 vpushi((int)&__ulltold);
3042 gfunc_call(&gf);
3043 vpushi(0);
3044 vtop->r = REG_FRET;
3045 } else {
3046 gen_cvt_itof(t);
3050 /* generic ftoi for unsigned long long case */
3051 void gen_cvt_ftoi1(int t)
3053 GFuncContext gf;
3054 int st;
3056 if (t == (VT_LLONG | VT_UNSIGNED)) {
3057 /* not handled natively */
3058 gfunc_start(&gf);
3059 st = vtop->t & VT_BTYPE;
3060 gfunc_param(&gf);
3061 if (st == VT_FLOAT)
3062 vpushi((int)&__ftoull);
3063 else if (st == VT_DOUBLE)
3064 vpushi((int)&__dtoull);
3065 else
3066 vpushi((int)&__ldtoull);
3067 gfunc_call(&gf);
3068 vpushi(0);
3069 vtop->r = REG_IRET;
3070 vtop->r2 = REG_LRET;
3071 } else {
3072 gen_cvt_ftoi(t);
3076 /* force char or short cast */
3077 void force_charshort_cast(int t)
3079 int bits, dbt;
3080 dbt = t & VT_BTYPE;
3081 /* XXX: add optimization if lvalue : just change type and offset */
3082 if (dbt == VT_BYTE)
3083 bits = 8;
3084 else
3085 bits = 16;
3086 if (t & VT_UNSIGNED) {
3087 vpushi((1 << bits) - 1);
3088 gen_op('&');
3089 } else {
3090 bits = 32 - bits;
3091 vpushi(bits);
3092 gen_op(TOK_SHL);
3093 vpushi(bits);
3094 gen_op(TOK_SAR);
3098 /* cast 'vtop' to 't' type */
3099 void gen_cast(int t)
3101 int sbt, dbt, sf, df, c, st1, dt1;
3103 /* special delayed cast for char/short */
3104 /* XXX: in some cases (multiple cascaded casts), it may still
3105 be incorrect */
3106 if (vtop->r & VT_MUSTCAST) {
3107 vtop->r &= ~VT_MUSTCAST;
3108 force_charshort_cast(vtop->t);
3111 dbt = t & VT_BTYPE;
3112 sbt = vtop->t & VT_BTYPE;
3114 if (sbt != dbt) {
3115 sf = is_float(sbt);
3116 df = is_float(dbt);
3117 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3118 if (sf && df) {
3119 /* convert from fp to fp */
3120 if (c) {
3121 /* constant case: we can do it now */
3122 /* XXX: in ISOC, cannot do it if error in convert */
3123 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
3124 vtop->c.f = (float)vtop->c.d;
3125 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
3126 vtop->c.f = (float)vtop->c.ld;
3127 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
3128 vtop->c.d = (double)vtop->c.f;
3129 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
3130 vtop->c.d = (double)vtop->c.ld;
3131 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
3132 vtop->c.ld = (long double)vtop->c.f;
3133 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
3134 vtop->c.ld = (long double)vtop->c.d;
3135 } else {
3136 /* non constant case: generate code */
3137 gen_cvt_ftof(dbt);
3139 } else if (df) {
3140 /* convert int to fp */
3141 st1 = vtop->t & (VT_BTYPE | VT_UNSIGNED);
3142 if (c) {
3143 switch(st1) {
3144 case VT_LLONG | VT_UNSIGNED:
3145 case VT_LLONG:
3146 /* XXX: add const cases for long long */
3147 goto do_itof;
3148 case VT_INT | VT_UNSIGNED:
3149 switch(dbt) {
3150 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
3151 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
3152 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
3154 break;
3155 default:
3156 switch(dbt) {
3157 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
3158 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
3159 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
3161 break;
3163 } else {
3164 do_itof:
3165 gen_cvt_itof1(dbt);
3167 } else if (sf) {
3168 /* convert fp to int */
3169 dt1 = t & (VT_BTYPE | VT_UNSIGNED);
3170 /* we handle char/short/etc... with generic code */
3171 if (dt1 != (VT_INT | VT_UNSIGNED) &&
3172 dt1 != (VT_LLONG | VT_UNSIGNED) &&
3173 dt1 != VT_LLONG)
3174 dt1 = VT_INT;
3175 if (c) {
3176 switch(dt1) {
3177 case VT_LLONG | VT_UNSIGNED:
3178 case VT_LLONG:
3179 /* XXX: add const cases for long long */
3180 goto do_ftoi;
3181 case VT_INT | VT_UNSIGNED:
3182 switch(sbt) {
3183 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
3184 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3185 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3187 break;
3188 default:
3189 /* int case */
3190 switch(sbt) {
3191 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
3192 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
3193 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
3195 break;
3197 } else {
3198 do_ftoi:
3199 gen_cvt_ftoi1(dt1);
3201 if (dt1 == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dt1) {
3202 /* additionnal cast for char/short/bool... */
3203 vtop->t = dt1;
3204 gen_cast(t);
3206 } else if (dbt == VT_LLONG) {
3207 /* scalar to long long */
3208 if (c) {
3209 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3210 vtop->c.ll = vtop->c.ui;
3211 else
3212 vtop->c.ll = vtop->c.i;
3213 } else {
3214 /* machine independant conversion */
3215 gv(RC_INT);
3216 /* generate high word */
3217 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) {
3218 vpushi(0);
3219 gv(RC_INT);
3220 } else {
3221 gv_dup();
3222 vpushi(31);
3223 gen_op(TOK_SAR);
3225 /* patch second register */
3226 vtop[-1].r2 = vtop->r;
3227 vpop();
3229 } else if (dbt == VT_BOOL) {
3230 /* scalar to bool */
3231 vpushi(0);
3232 gen_op(TOK_NE);
3233 } else if (dbt == VT_BYTE || dbt == VT_SHORT) {
3234 force_charshort_cast(t);
3235 } else if (dbt == VT_INT) {
3236 /* scalar to int */
3237 if (sbt == VT_LLONG) {
3238 /* from long long: just take low order word */
3239 lexpand();
3240 vpop();
3241 } else if (vtop->r & VT_LVAL) {
3242 /* if lvalue and single word type, nothing to do (XXX:
3243 maybe incorrect for sizeof op) */
3244 goto no_cast;
3248 vtop->t = t;
3249 no_cast: ;
3252 /* return type size. Put alignment at 'a' */
3253 int type_size(int t, int *a)
3255 Sym *s;
3256 int bt;
3258 bt = t & VT_BTYPE;
3259 if (bt == VT_STRUCT) {
3260 /* struct/union */
3261 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3262 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
3263 return s->c;
3264 } else if (bt == VT_PTR) {
3265 if (t & VT_ARRAY) {
3266 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3267 return type_size(s->t, a) * s->c;
3268 } else {
3269 *a = PTR_SIZE;
3270 return PTR_SIZE;
3272 } else if (bt == VT_LDOUBLE) {
3273 *a = LDOUBLE_ALIGN;
3274 return LDOUBLE_SIZE;
3275 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
3276 *a = 8;
3277 return 8;
3278 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
3279 *a = 4;
3280 return 4;
3281 } else if (bt == VT_SHORT) {
3282 *a = 2;
3283 return 2;
3284 } else {
3285 /* char, void, function, _Bool */
3286 *a = 1;
3287 return 1;
3291 /* return the pointed type of t */
3292 int pointed_type(int t)
3294 Sym *s;
3295 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3296 return s->t | (t & ~VT_TYPE);
3299 int mk_pointer(int t)
3301 int p;
3302 p = anon_sym++;
3303 sym_push(p, t, 0, -1);
3304 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
3307 int is_compatible_types(int t1, int t2)
3309 Sym *s1, *s2;
3310 int bt1, bt2;
3312 t1 &= VT_TYPE;
3313 t2 &= VT_TYPE;
3314 bt1 = t1 & VT_BTYPE;
3315 bt2 = t2 & VT_BTYPE;
3316 if (bt1 == VT_PTR) {
3317 t1 = pointed_type(t1);
3318 /* if function, then convert implicitely to function pointer */
3319 if (bt2 != VT_FUNC) {
3320 if (bt2 != VT_PTR)
3321 return 0;
3322 t2 = pointed_type(t2);
3324 /* void matches everything */
3325 t1 &= VT_TYPE;
3326 t2 &= VT_TYPE;
3327 if (t1 == VT_VOID || t2 == VT_VOID)
3328 return 1;
3329 return is_compatible_types(t1, t2);
3330 } else if (bt1 == VT_STRUCT) {
3331 return (t2 == t1);
3332 } else if (bt1 == VT_FUNC) {
3333 if (bt2 != VT_FUNC)
3334 return 0;
3335 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
3336 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
3337 if (!is_compatible_types(s1->t, s2->t))
3338 return 0;
3339 /* XXX: not complete */
3340 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
3341 return 1;
3342 if (s1->c != s2->c)
3343 return 0;
3344 while (s1 != NULL) {
3345 if (s2 == NULL)
3346 return 0;
3347 if (!is_compatible_types(s1->t, s2->t))
3348 return 0;
3349 s1 = s1->next;
3350 s2 = s2->next;
3352 if (s2)
3353 return 0;
3354 return 1;
3355 } else {
3356 /* XXX: not complete */
3357 return 1;
3361 /* print a type. If 'varstr' is not NULL, then the variable is also
3362 printed in the type */
3363 /* XXX: union */
3364 /* XXX: add array and function pointers */
3365 void type_to_str(char *buf, int buf_size,
3366 int t, const char *varstr)
3368 int bt, v;
3369 Sym *s, *sa;
3370 char buf1[256];
3371 const char *tstr;
3373 t = t & VT_TYPE;
3374 bt = t & VT_BTYPE;
3375 buf[0] = '\0';
3376 if (t & VT_UNSIGNED)
3377 pstrcat(buf, buf_size, "unsigned ");
3378 switch(bt) {
3379 case VT_VOID:
3380 tstr = "void";
3381 goto add_tstr;
3382 case VT_BOOL:
3383 tstr = "_Bool";
3384 goto add_tstr;
3385 case VT_BYTE:
3386 tstr = "char";
3387 goto add_tstr;
3388 case VT_SHORT:
3389 tstr = "short";
3390 goto add_tstr;
3391 case VT_INT:
3392 tstr = "int";
3393 goto add_tstr;
3394 case VT_LONG:
3395 tstr = "long";
3396 goto add_tstr;
3397 case VT_LLONG:
3398 tstr = "long long";
3399 goto add_tstr;
3400 case VT_FLOAT:
3401 tstr = "float";
3402 goto add_tstr;
3403 case VT_DOUBLE:
3404 tstr = "double";
3405 goto add_tstr;
3406 case VT_LDOUBLE:
3407 tstr = "long double";
3408 add_tstr:
3409 pstrcat(buf, buf_size, tstr);
3410 break;
3411 case VT_ENUM:
3412 case VT_STRUCT:
3413 if (bt == VT_STRUCT)
3414 tstr = "struct ";
3415 else
3416 tstr = "enum ";
3417 pstrcat(buf, buf_size, tstr);
3418 v = (unsigned)t >> VT_STRUCT_SHIFT;
3419 if (v >= SYM_FIRST_ANOM)
3420 pstrcat(buf, buf_size, "<anonymous>");
3421 else
3422 pstrcat(buf, buf_size, get_tok_str(v, NULL));
3423 break;
3424 case VT_FUNC:
3425 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3426 type_to_str(buf, buf_size, s->t, varstr);
3427 pstrcat(buf, buf_size, "(");
3428 sa = s->next;
3429 while (sa != NULL) {
3430 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
3431 pstrcat(buf, buf_size, buf1);
3432 sa = sa->next;
3433 if (sa)
3434 pstrcat(buf, buf_size, ", ");
3436 pstrcat(buf, buf_size, ")");
3437 goto no_var;
3438 case VT_PTR:
3439 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3440 pstrcpy(buf1, sizeof(buf1), "*");
3441 if (varstr)
3442 pstrcat(buf1, sizeof(buf1), varstr);
3443 type_to_str(buf, buf_size, s->t, buf1);
3444 goto no_var;
3446 if (varstr) {
3447 pstrcat(buf, buf_size, " ");
3448 pstrcat(buf, buf_size, varstr);
3450 no_var: ;
3453 /* verify type compatibility to store vtop in 'dt' type, and generate
3454 casts if needed. */
3455 void gen_assign_cast(int dt)
3457 int st;
3458 char buf1[256], buf2[256];
3460 st = vtop->t; /* source type */
3461 if ((dt & VT_BTYPE) == VT_PTR) {
3462 /* special cases for pointers */
3463 /* a function is implicitely a function pointer */
3464 if ((st & VT_BTYPE) == VT_FUNC) {
3465 if (!is_compatible_types(pointed_type(dt), st))
3466 goto error;
3467 else
3468 goto type_ok;
3470 /* '0' can also be a pointer */
3471 if ((st & VT_BTYPE) == VT_INT &&
3472 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) &&
3473 vtop->c.i == 0)
3474 goto type_ok;
3476 if (!is_compatible_types(dt, st)) {
3477 error:
3478 type_to_str(buf1, sizeof(buf1), st, NULL);
3479 type_to_str(buf2, sizeof(buf2), dt, NULL);
3480 error("cannot cast '%s' to '%s'", buf1, buf2);
3482 type_ok:
3483 gen_cast(dt);
3486 /* store vtop in lvalue pushed on stack */
3487 void vstore(void)
3489 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
3490 GFuncContext gf;
3492 ft = vtop[-1].t;
3493 sbt = vtop->t & VT_BTYPE;
3494 dbt = ft & VT_BTYPE;
3495 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
3496 (sbt == VT_INT && dbt == VT_SHORT)) {
3497 /* optimize char/short casts */
3498 delayed_cast = VT_MUSTCAST;
3499 vtop->t = ft & VT_TYPE;
3500 } else {
3501 delayed_cast = 0;
3502 gen_assign_cast(ft & VT_TYPE);
3505 if (sbt == VT_STRUCT) {
3506 /* if structure, only generate pointer */
3507 /* structure assignment : generate memcpy */
3508 /* XXX: optimize if small size */
3510 vdup();
3511 gfunc_start(&gf);
3512 /* type size */
3513 size = type_size(vtop->t, &align);
3514 vpushi(size);
3515 gfunc_param(&gf);
3516 /* source */
3517 vtop->t = VT_INT;
3518 gaddrof();
3519 gfunc_param(&gf);
3520 /* destination */
3521 vswap();
3522 vtop->t = VT_INT;
3523 gaddrof();
3524 gfunc_param(&gf);
3526 save_regs();
3527 vpushi((int)&memcpy);
3528 gfunc_call(&gf);
3529 /* leave source on stack */
3530 } else if (ft & VT_BITFIELD) {
3531 /* bitfield store handling */
3532 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
3533 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3534 /* remove bit field info to avoid loops */
3535 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3537 /* duplicate destination */
3538 vdup();
3539 vtop[-1] = vtop[-2];
3541 /* mask and shift source */
3542 vpushi((1 << bit_size) - 1);
3543 gen_op('&');
3544 vpushi(bit_pos);
3545 gen_op(TOK_SHL);
3546 /* load destination, mask and or with source */
3547 vswap();
3548 vpushi(~(((1 << bit_size) - 1) << bit_pos));
3549 gen_op('&');
3550 gen_op('|');
3551 /* store result */
3552 vstore();
3553 } else {
3554 /* bound check case */
3555 if (vtop[-1].r & VT_MUSTBOUND) {
3556 vswap();
3557 gbound();
3558 vswap();
3560 rc = RC_INT;
3561 if (is_float(ft))
3562 rc = RC_FLOAT;
3563 r = gv(rc); /* generate value */
3564 /* if lvalue was saved on stack, must read it */
3565 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
3566 SValue sv;
3567 t = get_reg(RC_INT);
3568 sv.t = VT_INT;
3569 sv.r = VT_LOCAL | VT_LVAL;
3570 sv.c.ul = vtop[-1].c.ul;
3571 load(t, &sv);
3572 vtop[-1].r = t | VT_LVAL;
3574 store(r, vtop - 1);
3575 /* two word case handling : store second register at word + 4 */
3576 if ((ft & VT_BTYPE) == VT_LLONG) {
3577 vswap();
3578 /* convert to int to increment easily */
3579 vtop->t = VT_INT;
3580 gaddrof();
3581 vpushi(4);
3582 gen_op('+');
3583 vtop->r |= VT_LVAL;
3584 vswap();
3585 /* XXX: it works because r2 is spilled last ! */
3586 store(vtop->r2, vtop - 1);
3588 vswap();
3589 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
3590 vtop->r |= delayed_cast;
3594 /* post defines POST/PRE add. c is the token ++ or -- */
3595 void inc(int post, int c)
3597 test_lvalue();
3598 vdup(); /* save lvalue */
3599 if (post) {
3600 gv_dup(); /* duplicate value */
3601 vrotb(3);
3602 vrotb(3);
3604 /* add constant */
3605 vpushi(c - TOK_MID);
3606 gen_op('+');
3607 vstore(); /* store value */
3608 if (post)
3609 vpop(); /* if post op, return saved value */
3612 /* Parse GNUC __attribute__ extension. Currently, the following
3613 extensions are recognized:
3614 - aligned(n) : set data/function alignment.
3615 - section(x) : generate data/code in this section.
3616 - unused : currently ignored, but may be used someday.
3618 void parse_attribute(AttributeDef *ad)
3620 int t, n;
3622 next();
3623 skip('(');
3624 skip('(');
3625 while (tok != ')') {
3626 if (tok < TOK_IDENT)
3627 expect("attribute name");
3628 t = tok;
3629 next();
3630 switch(t) {
3631 case TOK_SECTION:
3632 case TOK___SECTION__:
3633 skip('(');
3634 if (tok != TOK_STR)
3635 expect("section name");
3636 ad->section = find_section(tokc.ts->str);
3637 next();
3638 skip(')');
3639 break;
3640 case TOK_ALIGNED:
3641 case TOK___ALIGNED__:
3642 skip('(');
3643 n = expr_const();
3644 if (n <= 0 || (n & (n - 1)) != 0)
3645 error("alignment must be a positive power of two");
3646 ad->aligned = n;
3647 skip(')');
3648 break;
3649 case TOK_UNUSED:
3650 case TOK___UNUSED__:
3651 /* currently, no need to handle it because tcc does not
3652 track unused objects */
3653 break;
3654 default:
3655 warning("'%s' attribute ignored", get_tok_str(t, NULL));
3656 /* skip parameters */
3657 /* XXX: skip parenthesis too */
3658 if (tok == '(') {
3659 next();
3660 while (tok != ')' && tok != -1)
3661 next();
3662 next();
3664 break;
3666 if (tok != ',')
3667 break;
3668 next();
3670 skip(')');
3671 skip(')');
3674 /* enum/struct/union declaration */
3675 int struct_decl(int u)
3677 int a, t, b, v, size, align, maxalign, c, offset;
3678 int bit_size, bit_pos, bsize, bt, lbit_pos;
3679 Sym *s, *ss, **ps;
3680 AttributeDef ad;
3682 a = tok; /* save decl type */
3683 next();
3684 if (tok != '{') {
3685 v = tok;
3686 next();
3687 /* struct already defined ? return it */
3688 /* XXX: check consistency */
3689 s = sym_find(v | SYM_STRUCT);
3690 if (s) {
3691 if (s->t != a)
3692 error("invalid type");
3693 goto do_decl;
3695 } else {
3696 v = anon_sym++;
3698 s = sym_push(v | SYM_STRUCT, a, 0, 0);
3699 /* put struct/union/enum name in type */
3700 do_decl:
3701 u = u | (v << VT_STRUCT_SHIFT);
3703 if (tok == '{') {
3704 next();
3705 if (s->c)
3706 error("struct/union/enum already defined");
3707 /* cannot be empty */
3708 c = 0;
3709 maxalign = 0;
3710 ps = &s->next;
3711 bit_pos = 0;
3712 offset = 0;
3713 while (1) {
3714 if (a == TOK_ENUM) {
3715 v = tok;
3716 next();
3717 if (tok == '=') {
3718 next();
3719 c = expr_const();
3721 /* enum symbols have static storage */
3722 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
3723 if (tok == ',')
3724 next();
3725 c++;
3726 } else {
3727 parse_btype(&b, &ad);
3728 while (1) {
3729 bit_size = -1;
3730 v = 0;
3731 if (tok != ':') {
3732 t = type_decl(&v, b, TYPE_DIRECT);
3733 if ((t & VT_BTYPE) == VT_FUNC ||
3734 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
3735 error("invalid type for '%s'",
3736 get_tok_str(v, NULL));
3737 } else {
3738 t = b;
3740 if (tok == ':') {
3741 next();
3742 bit_size = expr_const();
3743 /* XXX: handle v = 0 case for messages */
3744 if (bit_size < 0)
3745 error("negative width in bit-field '%s'",
3746 get_tok_str(v, NULL));
3747 if (v && bit_size == 0)
3748 error("zero width for bit-field '%s'",
3749 get_tok_str(v, NULL));
3751 size = type_size(t, &align);
3752 lbit_pos = 0;
3753 if (bit_size >= 0) {
3754 bt = t & VT_BTYPE;
3755 if (bt != VT_INT &&
3756 bt != VT_BYTE &&
3757 bt != VT_SHORT)
3758 error("bitfields must have scalar type");
3759 bsize = size * 8;
3760 if (bit_size > bsize) {
3761 error("width of '%s' exceeds its type",
3762 get_tok_str(v, NULL));
3763 } else if (bit_size == bsize) {
3764 /* no need for bit fields */
3765 bit_pos = 0;
3766 } else if (bit_size == 0) {
3767 /* XXX: what to do if only padding in a
3768 structure ? */
3769 /* zero size: means to pad */
3770 if (bit_pos > 0)
3771 bit_pos = bsize;
3772 } else {
3773 /* we do not have enough room ? */
3774 if ((bit_pos + bit_size) > bsize)
3775 bit_pos = 0;
3776 lbit_pos = bit_pos;
3777 /* XXX: handle LSB first */
3778 t |= VT_BITFIELD |
3779 (bit_pos << VT_STRUCT_SHIFT) |
3780 (bit_size << (VT_STRUCT_SHIFT + 6));
3781 bit_pos += bit_size;
3783 } else {
3784 bit_pos = 0;
3786 if (v) {
3787 /* add new memory data only if starting
3788 bit field */
3789 if (lbit_pos == 0) {
3790 if (a == TOK_STRUCT) {
3791 c = (c + align - 1) & -align;
3792 offset = c;
3793 c += size;
3794 } else {
3795 offset = 0;
3796 if (size > c)
3797 c = size;
3799 if (align > maxalign)
3800 maxalign = align;
3802 #if 0
3803 printf("add field %s offset=%d",
3804 get_tok_str(v, NULL), offset);
3805 if (t & VT_BITFIELD) {
3806 printf(" pos=%d size=%d",
3807 (t >> VT_STRUCT_SHIFT) & 0x3f,
3808 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
3810 printf("\n");
3811 #endif
3812 ss = sym_push(v | SYM_FIELD, t, 0, offset);
3813 *ps = ss;
3814 ps = &ss->next;
3816 if (tok == ';' || tok == -1)
3817 break;
3818 skip(',');
3820 skip(';');
3822 if (tok == '}')
3823 break;
3825 skip('}');
3826 /* size for struct/union, dummy for enum */
3827 s->c = (c + maxalign - 1) & -maxalign;
3829 return u;
3832 /* return 0 if no type declaration. otherwise, return the basic type
3833 and skip it.
3835 int parse_btype(int *type_ptr, AttributeDef *ad)
3837 int t, u, type_found;
3838 Sym *s;
3840 memset(ad, 0, sizeof(AttributeDef));
3841 type_found = 0;
3842 t = 0;
3843 while(1) {
3844 switch(tok) {
3845 /* basic types */
3846 case TOK_CHAR:
3847 u = VT_BYTE;
3848 basic_type:
3849 next();
3850 basic_type1:
3851 if ((t & VT_BTYPE) != 0)
3852 error("too many basic types");
3853 t |= u;
3854 break;
3855 case TOK_VOID:
3856 u = VT_VOID;
3857 goto basic_type;
3858 case TOK_SHORT:
3859 u = VT_SHORT;
3860 goto basic_type;
3861 case TOK_INT:
3862 next();
3863 break;
3864 case TOK_LONG:
3865 next();
3866 if ((t & VT_BTYPE) == VT_DOUBLE) {
3867 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
3868 } else if ((t & VT_BTYPE) == VT_LONG) {
3869 t = (t & ~VT_BTYPE) | VT_LLONG;
3870 } else {
3871 u = VT_LONG;
3872 goto basic_type1;
3874 break;
3875 case TOK_BOOL:
3876 u = VT_BOOL;
3877 goto basic_type;
3878 case TOK_FLOAT:
3879 u = VT_FLOAT;
3880 goto basic_type;
3881 case TOK_DOUBLE:
3882 next();
3883 if ((t & VT_BTYPE) == VT_LONG) {
3884 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
3885 } else {
3886 u = VT_DOUBLE;
3887 goto basic_type1;
3889 break;
3890 case TOK_ENUM:
3891 u = struct_decl(VT_ENUM);
3892 goto basic_type1;
3893 case TOK_STRUCT:
3894 case TOK_UNION:
3895 u = struct_decl(VT_STRUCT);
3896 goto basic_type1;
3898 /* type modifiers */
3899 case TOK_CONST:
3900 case TOK_VOLATILE:
3901 case TOK_REGISTER:
3902 case TOK_SIGNED:
3903 case TOK_AUTO:
3904 case TOK_INLINE:
3905 case TOK_RESTRICT:
3906 next();
3907 break;
3908 case TOK_UNSIGNED:
3909 t |= VT_UNSIGNED;
3910 next();
3911 break;
3913 /* storage */
3914 case TOK_EXTERN:
3915 t |= VT_EXTERN;
3916 next();
3917 break;
3918 case TOK_STATIC:
3919 t |= VT_STATIC;
3920 next();
3921 break;
3922 case TOK_TYPEDEF:
3923 t |= VT_TYPEDEF;
3924 next();
3925 break;
3926 /* GNUC attribute */
3927 case TOK___ATTRIBUTE__:
3928 parse_attribute(ad);
3929 break;
3930 default:
3931 s = sym_find(tok);
3932 if (!s || !(s->t & VT_TYPEDEF))
3933 goto the_end;
3934 t |= (s->t & ~VT_TYPEDEF);
3935 next();
3936 break;
3938 type_found = 1;
3940 the_end:
3941 /* long is never used as type */
3942 if ((t & VT_BTYPE) == VT_LONG)
3943 t = (t & ~VT_BTYPE) | VT_INT;
3944 *type_ptr = t;
3945 return type_found;
3948 int post_type(int t)
3950 int p, n, pt, l, t1;
3951 Sym **plast, *s, *first;
3952 AttributeDef ad;
3954 if (tok == '(') {
3955 /* function declaration */
3956 next();
3957 l = 0;
3958 first = NULL;
3959 plast = &first;
3960 while (tok != ')') {
3961 /* read param name and compute offset */
3962 if (l != FUNC_OLD) {
3963 if (!parse_btype(&pt, &ad)) {
3964 if (l) {
3965 error("invalid type");
3966 } else {
3967 l = FUNC_OLD;
3968 goto old_proto;
3971 l = FUNC_NEW;
3972 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
3973 break;
3974 pt = type_decl(&n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
3975 if ((pt & VT_BTYPE) == VT_VOID)
3976 error("parameter declared as void");
3977 } else {
3978 old_proto:
3979 n = tok;
3980 pt = VT_INT;
3981 next();
3983 /* array must be transformed to pointer according to ANSI C */
3984 pt &= ~VT_ARRAY;
3985 s = sym_push(n | SYM_FIELD, pt, 0, 0);
3986 *plast = s;
3987 plast = &s->next;
3988 if (tok == ',') {
3989 next();
3990 if (l == FUNC_NEW && tok == TOK_DOTS) {
3991 l = FUNC_ELLIPSIS;
3992 next();
3993 break;
3997 /* if no parameters, then old type prototype */
3998 if (l == 0)
3999 l = FUNC_OLD;
4000 skip(')');
4001 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4002 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
4003 /* we push a anonymous symbol which will contain the function prototype */
4004 p = anon_sym++;
4005 s = sym_push(p, t, 0, l);
4006 s->next = first;
4007 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
4008 } else if (tok == '[') {
4009 /* array definition */
4010 next();
4011 n = -1;
4012 if (tok != ']') {
4013 n = expr_const();
4014 if (n < 0)
4015 error("invalid array size");
4017 skip(']');
4018 /* parse next post type */
4019 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4020 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
4022 /* we push a anonymous symbol which will contain the array
4023 element type */
4024 p = anon_sym++;
4025 sym_push(p, t, 0, n);
4026 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
4028 return t;
4031 /* Read a type declaration (except basic type), and return the
4032 type. If v is true, then also put variable name in 'vtop->c' */
4033 int type_decl(int *v, int t, int td)
4035 int u, p;
4036 Sym *s;
4038 while (tok == '*') {
4039 next();
4040 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
4041 next();
4042 t = mk_pointer(t);
4045 /* recursive type */
4046 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4047 if (tok == '(') {
4048 next();
4049 u = type_decl(v, 0, td);
4050 skip(')');
4051 } else {
4052 u = 0;
4053 /* type identifier */
4054 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
4055 *v = tok;
4056 next();
4057 } else {
4058 if (!(td & TYPE_ABSTRACT))
4059 expect("identifier");
4060 *v = 0;
4063 /* append t at the end of u */
4064 t = post_type(t);
4065 if (!u)
4066 return t;
4067 p = u;
4068 while(1) {
4069 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
4070 p = s->t;
4071 if (!p) {
4072 s->t = t;
4073 break;
4076 return u;
4079 /* define a new external reference to a function 'v' of type 'u' */
4080 Sym *external_sym(int v, int u, int r)
4082 Sym *s;
4083 s = sym_find(v);
4084 if (!s) {
4085 /* push forward reference */
4086 s = sym_push1(&global_stack,
4087 v, u, 0);
4088 s->r = r | VT_CONST | VT_FORWARD;
4090 return s;
4093 void indir(void)
4095 if ((vtop->t & VT_BTYPE) != VT_PTR)
4096 expect("pointer");
4097 if (vtop->r & VT_LVAL)
4098 gv(RC_INT);
4099 vtop->t = pointed_type(vtop->t);
4100 /* an array is never an lvalue */
4101 if (!(vtop->t & VT_ARRAY)) {
4102 vtop->r |= VT_LVAL;
4103 /* if bound checking, the referenced pointer must be checked */
4104 if (do_bounds_check)
4105 vtop->r |= VT_MUSTBOUND;
4109 /* pass a parameter to a function and do type checking and casting */
4110 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
4112 int func_type;
4113 func_type = func->c;
4114 if (func_type == FUNC_OLD ||
4115 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
4116 /* default casting : only need to convert float to double */
4117 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
4118 gen_cast(VT_DOUBLE);
4119 } else if (arg == NULL) {
4120 error("too many arguments to function");
4121 } else {
4122 gen_assign_cast(arg->t);
4124 gfunc_param(gf);
4127 void unary(void)
4129 int n, t, ft, fc, p, align, size, r, data_offset;
4130 Sym *s;
4131 GFuncContext gf;
4132 AttributeDef ad;
4134 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
4135 vpushi(tokc.i);
4136 next();
4137 } else if (tok == TOK_CUINT) {
4138 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
4139 next();
4140 } else if (tok == TOK_CLLONG) {
4141 vsetc(VT_LLONG, VT_CONST, &tokc);
4142 next();
4143 } else if (tok == TOK_CULLONG) {
4144 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
4145 next();
4146 } else if (tok == TOK_CFLOAT) {
4147 vsetc(VT_FLOAT, VT_CONST, &tokc);
4148 next();
4149 } else if (tok == TOK_CDOUBLE) {
4150 vsetc(VT_DOUBLE, VT_CONST, &tokc);
4151 next();
4152 } else if (tok == TOK_CLDOUBLE) {
4153 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
4154 next();
4155 } else if (tok == TOK___FUNC__) {
4156 /* special function name identifier */
4157 /* generate (char *) type */
4158 data_offset = (int)data_section->data_ptr;
4159 vset(mk_pointer(VT_BYTE), VT_CONST, data_offset);
4160 strcpy((void *)data_offset, funcname);
4161 data_offset += strlen(funcname) + 1;
4162 data_section->data_ptr = (unsigned char *)data_offset;
4163 next();
4164 } else if (tok == TOK_LSTR) {
4165 t = VT_INT;
4166 goto str_init;
4167 } else if (tok == TOK_STR) {
4168 /* string parsing */
4169 t = VT_BYTE;
4170 str_init:
4171 type_size(t, &align);
4172 data_offset = (int)data_section->data_ptr;
4173 data_offset = (data_offset + align - 1) & -align;
4174 fc = data_offset;
4175 /* we must declare it as an array first to use initializer parser */
4176 t = VT_ARRAY | mk_pointer(t);
4177 decl_initializer(t, VT_CONST, data_offset, 1, 0);
4178 data_offset += type_size(t, &align);
4179 /* put it as pointer */
4180 vset(t & ~VT_ARRAY, VT_CONST, fc);
4181 data_section->data_ptr = (unsigned char *)data_offset;
4182 } else {
4183 t = tok;
4184 next();
4185 if (t == '(') {
4186 /* cast ? */
4187 if (parse_btype(&t, &ad)) {
4188 ft = type_decl(&n, t, TYPE_ABSTRACT);
4189 skip(')');
4190 /* check ISOC99 compound literal */
4191 if (tok == '{') {
4192 /* data is allocated locally by default */
4193 if (global_expr)
4194 r = VT_CONST;
4195 else
4196 r = VT_LOCAL;
4197 /* all except arrays are lvalues */
4198 if (!(ft & VT_ARRAY))
4199 r |= VT_LVAL;
4200 memset(&ad, 0, sizeof(AttributeDef));
4201 fc = decl_initializer_alloc(ft, &ad, r, 1);
4202 vset(ft, r, fc);
4203 } else {
4204 unary();
4205 gen_cast(ft);
4207 } else {
4208 gexpr();
4209 skip(')');
4211 } else if (t == '*') {
4212 unary();
4213 indir();
4214 } else if (t == '&') {
4215 unary();
4216 /* functions names must be treated as function pointers,
4217 except for unary '&' and sizeof. Since we consider that
4218 functions are not lvalues, we only have to handle it
4219 there and in function calls. */
4220 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4221 test_lvalue();
4222 vtop->t = mk_pointer(vtop->t);
4223 gaddrof();
4224 } else
4225 if (t == '!') {
4226 unary();
4227 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
4228 vtop->c.i = !vtop->c.i;
4229 else if ((vtop->r & VT_VALMASK) == VT_CMP)
4230 vtop->c.i = vtop->c.i ^ 1;
4231 else
4232 vset(VT_INT, VT_JMP, gtst(1, 0));
4233 } else
4234 if (t == '~') {
4235 unary();
4236 vpushi(-1);
4237 gen_op('^');
4238 } else
4239 if (t == '+') {
4240 unary();
4241 } else
4242 if (t == TOK_SIZEOF) {
4243 if (tok == '(') {
4244 next();
4245 if (parse_btype(&t, &ad)) {
4246 t = type_decl(&n, t, TYPE_ABSTRACT);
4247 } else {
4248 /* XXX: some code could be generated: add eval
4249 flag */
4250 gexpr();
4251 t = vtop->t;
4252 vpop();
4254 skip(')');
4255 } else {
4256 unary();
4257 t = vtop->t;
4258 vpop();
4260 vpushi(type_size(t, &t));
4261 } else
4262 if (t == TOK_INC || t == TOK_DEC) {
4263 unary();
4264 inc(0, t);
4265 } else if (t == '-') {
4266 vpushi(0);
4267 unary();
4268 gen_op('-');
4269 } else
4271 s = sym_find(t);
4272 if (!s) {
4273 if (tok != '(')
4274 error("'%s' undeclared", get_tok_str(t, NULL));
4275 /* for simple function calls, we tolerate undeclared
4276 external reference */
4277 p = anon_sym++;
4278 sym_push1(&global_stack, p, 0, FUNC_OLD);
4279 /* int() function */
4280 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT), 0);
4282 vset(s->t, s->r, s->c);
4283 /* if forward reference, we must point to s */
4284 if (vtop->r & VT_FORWARD)
4285 vtop->c.sym = s;
4289 /* post operations */
4290 while (1) {
4291 if (tok == TOK_INC || tok == TOK_DEC) {
4292 inc(1, tok);
4293 next();
4294 } else if (tok == '.' || tok == TOK_ARROW) {
4295 /* field */
4296 if (tok == TOK_ARROW)
4297 indir();
4298 test_lvalue();
4299 gaddrof();
4300 next();
4301 /* expect pointer on structure */
4302 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
4303 expect("struct or union");
4304 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4305 /* find field */
4306 tok |= SYM_FIELD;
4307 while ((s = s->next) != NULL) {
4308 if (s->v == tok)
4309 break;
4311 if (!s)
4312 error("field not found");
4313 /* add field offset to pointer */
4314 vtop->t = char_pointer_type; /* change type to 'char *' */
4315 vpushi(s->c);
4316 gen_op('+');
4317 /* change type to field type, and set to lvalue */
4318 vtop->t = s->t;
4319 /* an array is never an lvalue */
4320 if (!(vtop->t & VT_ARRAY))
4321 vtop->r |= VT_LVAL;
4322 next();
4323 } else if (tok == '[') {
4324 next();
4325 gexpr();
4326 gen_op('+');
4327 indir();
4328 skip(']');
4329 } else if (tok == '(') {
4330 SValue ret;
4331 Sym *sa;
4333 /* function call */
4334 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
4335 /* pointer test (no array accepted) */
4336 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
4337 vtop->t = pointed_type(vtop->t);
4338 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4339 goto error_func;
4340 } else {
4341 error_func:
4342 expect("function pointer");
4344 } else {
4345 vtop->r &= ~VT_LVAL; /* no lvalue */
4347 /* get return type */
4348 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
4349 save_regs(); /* save used temporary registers */
4350 gfunc_start(&gf);
4351 next();
4352 sa = s->next; /* first parameter */
4353 #ifdef INVERT_FUNC_PARAMS
4355 int *str, len, parlevel, *saved_macro_ptr;
4356 Sym *args, *s1;
4358 /* read each argument and store it on a stack */
4359 /* XXX: merge it with macro args ? */
4360 args = NULL;
4361 while (tok != ')') {
4362 len = 0;
4363 str = NULL;
4364 parlevel = 0;
4365 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
4366 tok != -1) {
4367 if (tok == '(')
4368 parlevel++;
4369 else if (tok == ')')
4370 parlevel--;
4371 tok_add2(&str, &len, tok, &tokc);
4372 next();
4374 tok_add(&str, &len, -1); /* end of file added */
4375 tok_add(&str, &len, 0);
4376 s1 = sym_push2(&args, 0, 0, (int)str);
4377 s1->next = sa; /* add reference to argument */
4378 if (sa)
4379 sa = sa->next;
4380 if (tok != ',')
4381 break;
4382 next();
4384 if (tok != ')')
4385 expect(")");
4387 /* now generate code in reverse order by reading the stack */
4388 saved_macro_ptr = macro_ptr;
4389 while (args) {
4390 macro_ptr = (int *)args->c;
4391 next();
4392 expr_eq();
4393 if (tok != -1)
4394 expect("',' or ')'");
4395 gfunc_param_typed(&gf, s, args->next);
4396 s1 = args->prev;
4397 free((int *)args->c);
4398 free(args);
4399 args = s1;
4401 macro_ptr = saved_macro_ptr;
4402 /* restore token */
4403 tok = ')';
4405 #endif
4406 /* compute first implicit argument if a structure is returned */
4407 if ((s->t & VT_BTYPE) == VT_STRUCT) {
4408 /* get some space for the returned structure */
4409 size = type_size(s->t, &align);
4410 loc = (loc - size) & -align;
4411 ret.t = s->t;
4412 ret.r = VT_LOCAL | VT_LVAL;
4413 /* pass it as 'int' to avoid structure arg passing
4414 problems */
4415 vset(VT_INT, VT_LOCAL, loc);
4416 ret.c = vtop->c;
4417 gfunc_param(&gf);
4418 } else {
4419 ret.t = s->t;
4420 ret.r2 = VT_CONST;
4421 /* return in register */
4422 if (is_float(ret.t)) {
4423 ret.r = REG_FRET;
4424 } else {
4425 if ((ret.t & VT_BTYPE) == VT_LLONG)
4426 ret.r2 = REG_LRET;
4427 ret.r = REG_IRET;
4429 ret.c.i = 0;
4431 #ifndef INVERT_FUNC_PARAMS
4432 while (tok != ')') {
4433 expr_eq();
4434 gfunc_param_typed(&gf, s, sa);
4435 if (sa)
4436 sa = sa->next;
4437 if (tok == ',')
4438 next();
4440 #endif
4441 if (sa)
4442 error("too few arguments to function");
4443 skip(')');
4444 gfunc_call(&gf);
4445 /* return value */
4446 vsetc(ret.t, ret.r, &ret.c);
4447 vtop->r2 = ret.r2;
4448 } else {
4449 break;
4454 void uneq(void)
4456 int t;
4458 unary();
4459 if (tok == '=' ||
4460 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
4461 tok == TOK_A_XOR || tok == TOK_A_OR ||
4462 tok == TOK_A_SHL || tok == TOK_A_SAR) {
4463 test_lvalue();
4464 t = tok;
4465 next();
4466 if (t == '=') {
4467 expr_eq();
4468 } else {
4469 vdup();
4470 expr_eq();
4471 gen_op(t & 0x7f);
4473 vstore();
4477 void sum(int l)
4479 int t;
4481 if (l == 0)
4482 uneq();
4483 else {
4484 sum(--l);
4485 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
4486 (l == 1 && (tok == '+' || tok == '-')) ||
4487 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
4488 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
4489 tok == TOK_ULT || tok == TOK_UGE)) ||
4490 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
4491 (l == 5 && tok == '&') ||
4492 (l == 6 && tok == '^') ||
4493 (l == 7 && tok == '|') ||
4494 (l == 8 && tok == TOK_LAND) ||
4495 (l == 9 && tok == TOK_LOR)) {
4496 t = tok;
4497 next();
4498 sum(l);
4499 gen_op(t);
4504 /* only used if non constant */
4505 void eand(void)
4507 int t;
4509 sum(8);
4510 t = 0;
4511 while (1) {
4512 if (tok != TOK_LAND) {
4513 if (t) {
4514 t = gtst(1, t);
4515 vset(VT_INT, VT_JMPI, t);
4517 break;
4519 t = gtst(1, t);
4520 next();
4521 sum(8);
4525 void eor(void)
4527 int t;
4529 eand();
4530 t = 0;
4531 while (1) {
4532 if (tok != TOK_LOR) {
4533 if (t) {
4534 t = gtst(0, t);
4535 vset(VT_INT, VT_JMP, t);
4537 break;
4539 t = gtst(0, t);
4540 next();
4541 eand();
4545 /* XXX: better constant handling */
4546 void expr_eq(void)
4548 int t, u, c, r1, r2, rc;
4550 if (const_wanted) {
4551 sum(10);
4552 if (tok == '?') {
4553 c = vtop->c.i;
4554 vpop();
4555 next();
4556 gexpr();
4557 t = vtop->c.i;
4558 vpop();
4559 skip(':');
4560 expr_eq();
4561 if (c)
4562 vtop->c.i = t;
4564 } else {
4565 eor();
4566 if (tok == '?') {
4567 next();
4568 t = gtst(1, 0);
4569 gexpr();
4570 /* XXX: long long handling ? */
4571 rc = RC_INT;
4572 if (is_float(vtop->t))
4573 rc = RC_FLOAT;
4574 r1 = gv(rc);
4575 vpop();
4576 skip(':');
4577 u = gjmp(0);
4579 gsym(t);
4580 expr_eq();
4581 r2 = gv(rc);
4582 move_reg(r1, r2);
4583 vtop->r = r1;
4584 gsym(u);
4589 void gexpr(void)
4591 while (1) {
4592 expr_eq();
4593 if (tok != ',')
4594 break;
4595 vpop();
4596 next();
4600 /* parse a constant expression and return value in vtop */
4601 void expr_const1(void)
4603 int a;
4604 a = const_wanted;
4605 const_wanted = 1;
4606 expr_eq();
4607 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
4608 expect("constant");
4609 const_wanted = a;
4612 /* parse an integer constant and return its value */
4613 int expr_const(void)
4615 int c;
4616 expr_const1();
4617 c = vtop->c.i;
4618 vpop();
4619 return c;
4622 /* return the label token if current token is a label, otherwise
4623 return zero */
4624 int is_label(void)
4626 int t;
4627 CValue c;
4629 /* fast test first */
4630 if (tok < TOK_UIDENT)
4631 return 0;
4632 /* no need to save tokc since we expect an identifier */
4633 t = tok;
4634 c = tokc;
4635 next();
4636 if (tok == ':') {
4637 next();
4638 return t;
4639 } else {
4640 /* XXX: may not work in all cases (macros ?) */
4641 tok1 = tok;
4642 tok1c = tokc;
4643 tok = t;
4644 tokc = c;
4645 return 0;
4649 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
4651 int a, b, c, d;
4652 Sym *s;
4654 /* generate line number info */
4655 if (do_debug &&
4656 (last_line_num != line_num || last_ind != ind)) {
4657 put_stabn(N_SLINE, 0, line_num, ind - func_ind);
4658 last_ind = ind;
4659 last_line_num = line_num;
4662 if (tok == TOK_IF) {
4663 /* if test */
4664 next();
4665 skip('(');
4666 gexpr();
4667 skip(')');
4668 a = gtst(1, 0);
4669 block(bsym, csym, case_sym, def_sym, case_reg);
4670 c = tok;
4671 if (c == TOK_ELSE) {
4672 next();
4673 d = gjmp(0);
4674 gsym(a);
4675 block(bsym, csym, case_sym, def_sym, case_reg);
4676 gsym(d); /* patch else jmp */
4677 } else
4678 gsym(a);
4679 } else if (tok == TOK_WHILE) {
4680 next();
4681 d = ind;
4682 skip('(');
4683 gexpr();
4684 skip(')');
4685 a = gtst(1, 0);
4686 b = 0;
4687 block(&a, &b, case_sym, def_sym, case_reg);
4688 oad(0xe9, d - ind - 5); /* jmp */
4689 gsym(a);
4690 gsym_addr(b, d);
4691 } else if (tok == '{') {
4692 next();
4693 /* declarations */
4694 s = local_stack.top;
4695 while (tok != '}') {
4696 decl(VT_LOCAL);
4697 if (tok != '}')
4698 block(bsym, csym, case_sym, def_sym, case_reg);
4700 /* pop locally defined symbols */
4701 sym_pop(&local_stack, s);
4702 next();
4703 } else if (tok == TOK_RETURN) {
4704 next();
4705 if (tok != ';') {
4706 gexpr();
4707 gen_assign_cast(func_vt);
4708 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
4709 /* if returning structure, must copy it to implicit
4710 first pointer arg location */
4711 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
4712 indir();
4713 vswap();
4714 /* copy structure value to pointer */
4715 vstore();
4716 } else if (is_float(func_vt)) {
4717 gv(RC_FRET);
4718 } else {
4719 gv(RC_IRET);
4721 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
4723 skip(';');
4724 rsym = gjmp(rsym); /* jmp */
4725 } else if (tok == TOK_BREAK) {
4726 /* compute jump */
4727 if (!bsym)
4728 error("cannot break");
4729 *bsym = gjmp(*bsym);
4730 next();
4731 skip(';');
4732 } else if (tok == TOK_CONTINUE) {
4733 /* compute jump */
4734 if (!csym)
4735 error("cannot continue");
4736 *csym = gjmp(*csym);
4737 next();
4738 skip(';');
4739 } else if (tok == TOK_FOR) {
4740 int e;
4741 next();
4742 skip('(');
4743 if (tok != ';') {
4744 gexpr();
4745 vpop();
4747 skip(';');
4748 d = ind;
4749 c = ind;
4750 a = 0;
4751 b = 0;
4752 if (tok != ';') {
4753 gexpr();
4754 a = gtst(1, 0);
4756 skip(';');
4757 if (tok != ')') {
4758 e = gjmp(0);
4759 c = ind;
4760 gexpr();
4761 vpop();
4762 oad(0xe9, d - ind - 5); /* jmp */
4763 gsym(e);
4765 skip(')');
4766 block(&a, &b, case_sym, def_sym, case_reg);
4767 oad(0xe9, c - ind - 5); /* jmp */
4768 gsym(a);
4769 gsym_addr(b, c);
4770 } else
4771 if (tok == TOK_DO) {
4772 next();
4773 a = 0;
4774 b = 0;
4775 d = ind;
4776 block(&a, &b, case_sym, def_sym, case_reg);
4777 skip(TOK_WHILE);
4778 skip('(');
4779 gsym(b);
4780 gexpr();
4781 c = gtst(0, 0);
4782 gsym_addr(c, d);
4783 skip(')');
4784 gsym(a);
4785 skip(';');
4786 } else
4787 if (tok == TOK_SWITCH) {
4788 next();
4789 skip('(');
4790 gexpr();
4791 /* XXX: other types than integer */
4792 case_reg = gv(RC_INT);
4793 vpop();
4794 skip(')');
4795 a = 0;
4796 b = gjmp(0); /* jump to first case */
4797 c = 0;
4798 block(&a, csym, &b, &c, case_reg);
4799 /* if no default, jmp after switch */
4800 if (c == 0)
4801 c = ind;
4802 /* default label */
4803 gsym_addr(b, c);
4804 /* break label */
4805 gsym(a);
4806 } else
4807 if (tok == TOK_CASE) {
4808 int v1, v2;
4809 if (!case_sym)
4810 expect("switch");
4811 next();
4812 v1 = expr_const();
4813 v2 = v1;
4814 if (gnu_ext && tok == TOK_DOTS) {
4815 next();
4816 v2 = expr_const();
4817 if (v2 < v1)
4818 warning("empty case range");
4820 /* since a case is like a label, we must skip it with a jmp */
4821 b = gjmp(0);
4822 gsym(*case_sym);
4823 vset(VT_INT, case_reg, 0);
4824 vpushi(v1);
4825 if (v1 == v2) {
4826 gen_op(TOK_EQ);
4827 *case_sym = gtst(1, 0);
4828 } else {
4829 gen_op(TOK_GE);
4830 *case_sym = gtst(1, 0);
4831 vset(VT_INT, case_reg, 0);
4832 vpushi(v2);
4833 gen_op(TOK_LE);
4834 *case_sym = gtst(1, *case_sym);
4836 gsym(b);
4837 skip(':');
4838 block(bsym, csym, case_sym, def_sym, case_reg);
4839 } else
4840 if (tok == TOK_DEFAULT) {
4841 next();
4842 skip(':');
4843 if (!def_sym)
4844 expect("switch");
4845 if (*def_sym)
4846 error("too many 'default'");
4847 *def_sym = ind;
4848 block(bsym, csym, case_sym, def_sym, case_reg);
4849 } else
4850 if (tok == TOK_GOTO) {
4851 next();
4852 s = sym_find1(&label_stack, tok);
4853 /* put forward definition if needed */
4854 if (!s)
4855 s = sym_push1(&label_stack, tok, VT_FORWARD, 0);
4856 /* label already defined */
4857 if (s->t & VT_FORWARD)
4858 s->c = gjmp(s->c); /* jmp xxx */
4859 else
4860 oad(0xe9, s->c - ind - 5); /* jmp xxx */
4861 next();
4862 skip(';');
4863 } else {
4864 b = is_label();
4865 if (b) {
4866 /* label case */
4867 s = sym_find1(&label_stack, b);
4868 if (s) {
4869 if (!(s->t & VT_FORWARD))
4870 error("multiple defined label");
4871 gsym(s->c);
4872 s->c = ind;
4873 s->t = 0;
4874 } else {
4875 sym_push1(&label_stack, b, 0, ind);
4877 /* we accept this, but it is a mistake */
4878 if (tok == '}')
4879 warning("deprecated use of label at end of compound statement");
4880 else
4881 block(bsym, csym, case_sym, def_sym, case_reg);
4882 } else {
4883 /* expression case */
4884 if (tok != ';') {
4885 gexpr();
4886 vpop();
4888 skip(';');
4893 /* t is the array or struct type. c is the array or struct
4894 address. cur_index/cur_field is the pointer to the current
4895 value. 'size_only' is true if only size info is needed (only used
4896 in arrays) */
4897 void decl_designator(int t, int r, int c,
4898 int *cur_index, Sym **cur_field,
4899 int size_only)
4901 Sym *s, *f;
4902 int notfirst, index, align, l;
4904 notfirst = 0;
4905 if (gnu_ext && (l = is_label()) != 0)
4906 goto struct_field;
4908 while (tok == '[' || tok == '.') {
4909 if (tok == '[') {
4910 if (!(t & VT_ARRAY))
4911 expect("array type");
4912 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
4913 next();
4914 index = expr_const();
4915 if (index < 0 || (s->c >= 0 && index >= s->c))
4916 expect("invalid index");
4917 skip(']');
4918 if (!notfirst)
4919 *cur_index = index;
4920 t = pointed_type(t);
4921 c += index * type_size(t, &align);
4922 } else {
4923 next();
4924 l = tok;
4925 next();
4926 struct_field:
4927 if ((t & VT_BTYPE) != VT_STRUCT)
4928 expect("struct/union type");
4929 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4930 l |= SYM_FIELD;
4931 f = s->next;
4932 while (f) {
4933 if (f->v == l)
4934 break;
4935 f = f->next;
4937 if (!f)
4938 expect("field");
4939 if (!notfirst)
4940 *cur_field = f;
4941 t = f->t | (t & ~VT_TYPE);
4942 c += f->c;
4944 notfirst = 1;
4946 if (notfirst) {
4947 if (tok == '=') {
4948 next();
4949 } else {
4950 if (!gnu_ext)
4951 expect("=");
4953 } else {
4954 if (t & VT_ARRAY) {
4955 index = *cur_index;
4956 t = pointed_type(t);
4957 c += index * type_size(t, &align);
4958 } else {
4959 f = *cur_field;
4960 if (!f)
4961 error("too many field init");
4962 t = f->t | (t & ~VT_TYPE);
4963 c += f->c;
4966 decl_initializer(t, r, c, 0, size_only);
4969 #define EXPR_VAL 0
4970 #define EXPR_CONST 1
4971 #define EXPR_ANY 2
4973 /* store a value or an expression directly in global data or in local array */
4974 void init_putv(int t, int r, int c,
4975 int v, int expr_type)
4977 int saved_global_expr, bt;
4979 switch(expr_type) {
4980 case EXPR_VAL:
4981 vpushi(v);
4982 break;
4983 case EXPR_CONST:
4984 /* compound literals must be allocated globally in this case */
4985 saved_global_expr = global_expr;
4986 global_expr = 1;
4987 expr_const1();
4988 global_expr = saved_global_expr;
4989 break;
4990 case EXPR_ANY:
4991 expr_eq();
4992 break;
4995 if ((r & VT_VALMASK) == VT_CONST) {
4996 /* XXX: do casting */
4997 /* XXX: not portable */
4998 bt = vtop->t & VT_BTYPE;
4999 switch(bt) {
5000 case VT_BYTE:
5001 *(char *)c = vtop->c.i;
5002 break;
5003 case VT_SHORT:
5004 *(short *)c = vtop->c.i;
5005 break;
5006 case VT_DOUBLE:
5007 *(double *)c = vtop->c.d;
5008 break;
5009 case VT_LDOUBLE:
5010 *(long double *)c = vtop->c.ld;
5011 break;
5012 #if 0
5013 case VT_LLONG:
5014 *(long long *)c = vtop->c.ll;
5015 break;
5016 #endif
5017 default:
5018 *(int *)c = vtop->c.i;
5019 break;
5021 vpop();
5022 } else {
5023 vset(t, r, c);
5024 vswap();
5025 vstore();
5026 vpop();
5030 /* put zeros for variable based init */
5031 void init_putz(int t, int r, int c, int size)
5033 GFuncContext gf;
5035 if ((r & VT_VALMASK) == VT_CONST) {
5036 /* nothing to do because global are already set to zero */
5037 } else {
5038 gfunc_start(&gf);
5039 vpushi(size);
5040 gfunc_param(&gf);
5041 vpushi(0);
5042 gfunc_param(&gf);
5043 vset(VT_INT, VT_LOCAL, c);
5044 gfunc_param(&gf);
5045 vpushi((int)&memset);
5046 gfunc_call(&gf);
5050 /* 't' contains the type and storage info. c is the address of the
5051 object. 'first' is true if array '{' must be read (multi dimension
5052 implicit array init handling). 'size_only' is true if size only
5053 evaluation is wanted (only for arrays). */
5054 void decl_initializer(int t, int r, int c, int first, int size_only)
5056 int index, array_length, n, no_oblock, nb, parlevel, i;
5057 int t1, size1, align1, expr_type;
5058 Sym *s, *f;
5059 TokenSym *ts;
5061 if (t & VT_ARRAY) {
5062 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5063 n = s->c;
5064 array_length = 0;
5065 t1 = pointed_type(t);
5066 size1 = type_size(t1, &align1);
5068 no_oblock = 1;
5069 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
5070 tok == '{') {
5071 skip('{');
5072 no_oblock = 0;
5075 /* only parse strings here if correct type (otherwise: handle
5076 them as ((w)char *) expressions */
5077 if ((tok == TOK_LSTR &&
5078 (t1 & VT_BTYPE) == VT_INT) ||
5079 (tok == TOK_STR &&
5080 (t1 & VT_BTYPE) == VT_BYTE)) {
5081 /* XXX: move multiple string parsing in parser ? */
5082 while (tok == TOK_STR || tok == TOK_LSTR) {
5083 ts = tokc.ts;
5084 /* compute maximum number of chars wanted */
5085 nb = ts->len;
5086 if (n >= 0 && nb > (n - array_length))
5087 nb = n - array_length;
5088 if (!size_only) {
5089 if (ts->len > nb)
5090 warning("initializer-string for array is too long");
5091 for(i=0;i<nb;i++) {
5092 init_putv(t1, r, c + (array_length + i) * size1,
5093 ts->str[i], EXPR_VAL);
5096 array_length += nb;
5097 next();
5099 /* only add trailing zero if enough storage (no
5100 warning in this case since it is standard) */
5101 if (n < 0 || array_length < n) {
5102 if (!size_only) {
5103 init_putv(t1, r, c + (array_length * size1), 0, EXPR_VAL);
5105 array_length++;
5107 } else {
5108 index = 0;
5109 while (tok != '}') {
5110 decl_designator(t, r, c, &index, NULL, size_only);
5111 if (n >= 0 && index >= n)
5112 error("index too large");
5113 /* must put zero in holes (note that doing it that way
5114 ensures that it even works with designators) */
5115 if (!size_only && array_length < index) {
5116 init_putz(t1, r, c + array_length * size1,
5117 (index - array_length) * size1);
5119 index++;
5120 if (index > array_length)
5121 array_length = index;
5122 /* special test for multi dimensional arrays (may not
5123 be strictly correct if designators are used at the
5124 same time) */
5125 if (index >= n && no_oblock)
5126 break;
5127 if (tok == '}')
5128 break;
5129 skip(',');
5132 if (!no_oblock)
5133 skip('}');
5134 /* put zeros at the end */
5135 if (!size_only && n >= 0 && array_length < n) {
5136 init_putz(t1, r, c + array_length * size1,
5137 (n - array_length) * size1);
5139 /* patch type size if needed */
5140 if (n < 0)
5141 s->c = array_length;
5142 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
5143 /* XXX: union needs only one init */
5144 next();
5145 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5146 f = s->next;
5147 array_length = 0;
5148 index = 0;
5149 n = s->c;
5150 while (tok != '}') {
5151 decl_designator(t, r, c, NULL, &f, size_only);
5152 /* fill with zero between fields */
5153 index = f->c;
5154 if (!size_only && array_length < index) {
5155 init_putz(t, r, c + array_length,
5156 index - array_length);
5158 index = index + type_size(f->t, &align1);
5159 if (index > array_length)
5160 array_length = index;
5161 if (tok == '}')
5162 break;
5163 skip(',');
5164 f = f->next;
5166 /* put zeros at the end */
5167 if (!size_only && array_length < n) {
5168 init_putz(t, r, c + array_length,
5169 n - array_length);
5171 skip('}');
5172 } else if (tok == '{') {
5173 next();
5174 decl_initializer(t, r, c, first, size_only);
5175 skip('}');
5176 } else if (size_only) {
5177 /* just skip expression */
5178 parlevel = 0;
5179 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
5180 tok != -1) {
5181 if (tok == '(')
5182 parlevel++;
5183 else if (tok == ')')
5184 parlevel--;
5185 next();
5187 } else {
5188 /* currently, we always use constant expression for globals
5189 (may change for scripting case) */
5190 expr_type = EXPR_CONST;
5191 if ((r & VT_VALMASK) == VT_LOCAL)
5192 expr_type = EXPR_ANY;
5193 init_putv(t, r, c, 0, expr_type);
5197 /* parse an initializer for type 't' if 'has_init' is true, and
5198 allocate space in local or global data space ('r' is either
5199 VT_LOCAL or VT_CONST). The allocated address in returned */
5200 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init)
5202 int size, align, addr, tok1, data_offset;
5203 int *init_str, init_len, level, *saved_macro_ptr;
5204 Section *sec;
5206 size = type_size(t, &align);
5207 /* If unknown size, we must evaluate it before
5208 evaluating initializers because
5209 initializers can generate global data too
5210 (e.g. string pointers or ISOC99 compound
5211 literals). It also simplifies local
5212 initializers handling */
5213 init_len = 0;
5214 init_str = NULL;
5215 saved_macro_ptr = NULL; /* avoid warning */
5216 tok1 = 0;
5217 if (size < 0) {
5218 if (!has_init)
5219 error("unknown type size");
5220 /* get all init string */
5221 level = 0;
5222 while (level > 0 || (tok != ',' && tok != ';')) {
5223 if (tok < 0)
5224 error("unexpected end of file in initializer");
5225 tok_add2(&init_str, &init_len, tok, &tokc);
5226 if (tok == '{')
5227 level++;
5228 else if (tok == '}') {
5229 if (level == 0)
5230 break;
5231 level--;
5233 next();
5235 tok1 = tok;
5236 tok_add(&init_str, &init_len, -1);
5237 tok_add(&init_str, &init_len, 0);
5239 /* compute size */
5240 saved_macro_ptr = macro_ptr;
5241 macro_ptr = init_str;
5242 next();
5243 decl_initializer(t, r, 0, 1, 1);
5244 /* prepare second initializer parsing */
5245 macro_ptr = init_str;
5246 next();
5248 /* if still unknown size, error */
5249 size = type_size(t, &align);
5250 if (size < 0)
5251 error("unknown type size");
5253 /* take into account specified alignment if bigger */
5254 if (ad->aligned > align)
5255 align = ad->aligned;
5256 if ((r & VT_VALMASK) == VT_LOCAL) {
5257 if (do_bounds_check && (t & VT_ARRAY))
5258 loc--;
5259 loc = (loc - size) & -align;
5260 addr = loc;
5261 /* handles bounds */
5262 /* XXX: currently, since we do only one pass, we cannot track
5263 '&' operators, so we add only arrays */
5264 if (do_bounds_check && (t & VT_ARRAY)) {
5265 int *bounds_ptr;
5266 /* add padding between regions */
5267 loc--;
5268 /* then add local bound info */
5269 bounds_ptr = (int *)lbounds_section->data_ptr;
5270 *bounds_ptr++ = addr;
5271 *bounds_ptr++ = size;
5272 lbounds_section->data_ptr = (unsigned char *)bounds_ptr;
5274 } else {
5275 /* compute section */
5276 sec = ad->section;
5277 if (!sec) {
5278 if (has_init)
5279 sec = data_section;
5280 else
5281 sec = bss_section;
5283 data_offset = (int)sec->data_ptr;
5284 data_offset = (data_offset + align - 1) & -align;
5285 addr = data_offset;
5286 /* very important to increment global
5287 pointer at this time because
5288 initializers themselves can create new
5289 initializers */
5290 data_offset += size;
5291 /* handles bounds */
5292 if (do_bounds_check) {
5293 int *bounds_ptr;
5294 /* first, we need to add at least one byte between each region */
5295 data_offset++;
5296 /* then add global bound info */
5297 bounds_ptr = (int *)bounds_section->data_ptr;
5298 *bounds_ptr++ = addr;
5299 *bounds_ptr++ = size;
5300 bounds_section->data_ptr = (unsigned char *)bounds_ptr;
5302 sec->data_ptr = (unsigned char *)data_offset;
5304 if (has_init) {
5305 decl_initializer(t, r, addr, 1, 0);
5306 /* restore parse state if needed */
5307 if (init_str) {
5308 free(init_str);
5309 macro_ptr = saved_macro_ptr;
5310 tok = tok1;
5313 return addr;
5316 void put_func_debug(int t)
5318 int bind;
5319 char buf[512];
5321 if (t & VT_STATIC)
5322 bind = STB_LOCAL;
5323 else
5324 bind = STB_GLOBAL;
5325 put_elf_sym(symtab_section, ind, 0,
5326 ELF32_ST_INFO(bind, STT_FUNC), 0,
5327 cur_text_section->sh_num, funcname);
5328 /* stabs info */
5329 /* XXX: we put here a dummy type */
5330 snprintf(buf, sizeof(buf), "%s:%c1",
5331 funcname, t & VT_STATIC ? 'f' : 'F');
5332 put_stabs(buf, N_FUN, 0, line_num, ind);
5333 func_ind = ind;
5334 last_ind = 0;
5335 last_line_num = 0;
5338 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5339 void decl(int l)
5341 int t, b, v, addr, has_init, r;
5342 Sym *sym;
5343 AttributeDef ad;
5345 while (1) {
5346 if (!parse_btype(&b, &ad)) {
5347 /* skip redundant ';' */
5348 /* XXX: find more elegant solution */
5349 if (tok == ';') {
5350 next();
5351 continue;
5353 /* special test for old K&R protos without explicit int
5354 type. Only accepted when defining global data */
5355 if (l == VT_LOCAL || tok < TOK_DEFINE)
5356 break;
5357 b = VT_INT;
5359 if (((b & VT_BTYPE) == VT_ENUM ||
5360 (b & VT_BTYPE) == VT_STRUCT) &&
5361 tok == ';') {
5362 /* we accept no variable after */
5363 next();
5364 continue;
5366 while (1) { /* iterate thru each declaration */
5367 t = type_decl(&v, b, TYPE_DIRECT);
5368 /* currently, we do not parse attribute in
5369 type_decl(). May change if needed */
5370 if (tok == TOK___ATTRIBUTE__)
5371 parse_attribute(&ad);
5372 #if 0
5374 char buf[500];
5375 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
5376 printf("type = '%s'\n", buf);
5378 #endif
5379 if (tok == '{') {
5380 if (l == VT_LOCAL)
5381 error("cannot use local functions");
5382 if (!(t & VT_FUNC))
5383 expect("function definition");
5384 /* compute text section */
5385 cur_text_section = ad.section;
5386 if (!cur_text_section)
5387 cur_text_section = text_section;
5388 ind = (int)cur_text_section->data_ptr;
5389 /* patch forward references */
5390 if ((sym = sym_find(v)) && (sym->r & VT_FORWARD)) {
5391 greloc_patch(sym, ind);
5392 sym->t = t;
5393 } else {
5394 /* put function address */
5395 sym = sym_push1(&global_stack, v, t, ind);
5397 sym->r = VT_CONST;
5398 funcname = get_tok_str(v, NULL);
5399 /* put debug symbol */
5400 if (do_debug)
5401 put_func_debug(t);
5402 /* push a dummy symbol to enable local sym storage */
5403 sym_push1(&local_stack, 0, 0, 0);
5404 gfunc_prolog(t);
5405 loc = 0;
5406 rsym = 0;
5407 block(NULL, NULL, NULL, NULL, 0);
5408 gsym(rsym);
5409 gfunc_epilog();
5410 cur_text_section->data_ptr = (unsigned char *)ind;
5411 sym_pop(&label_stack, NULL); /* reset label stack */
5412 sym_pop(&local_stack, NULL); /* reset local stack */
5413 /* end of function */
5414 if (do_debug) {
5415 put_stabn(N_FUN, 0, 0, ind - func_ind);
5417 funcname = ""; /* for safety */
5418 func_vt = VT_VOID; /* for safety */
5419 break;
5420 } else {
5421 if (b & VT_TYPEDEF) {
5422 /* save typedefed type */
5423 /* XXX: test storage specifiers ? */
5424 sym_push(v, t | VT_TYPEDEF, 0, 0);
5425 } else if ((t & VT_BTYPE) == VT_FUNC) {
5426 /* external function definition */
5427 external_sym(v, t, 0);
5428 } else {
5429 /* not lvalue if array */
5430 r = 0;
5431 if (!(t & VT_ARRAY))
5432 r |= VT_LVAL;
5433 if (b & VT_EXTERN) {
5434 /* external variable */
5435 external_sym(v, t, r);
5436 } else {
5437 if (t & VT_STATIC)
5438 r |= VT_CONST;
5439 else
5440 r |= l;
5441 has_init = (tok == '=');
5442 if (has_init)
5443 next();
5444 addr = decl_initializer_alloc(t, &ad, r,
5445 has_init);
5446 if (l == VT_CONST) {
5447 /* global scope: see if already defined */
5448 sym = sym_find(v);
5449 if (!sym)
5450 goto do_def;
5451 if (!is_compatible_types(sym->t, t))
5452 error("incompatible types for redefinition of '%s'",
5453 get_tok_str(v, NULL));
5454 if (!(sym->r & VT_FORWARD))
5455 error("redefinition of '%s'", get_tok_str(v, NULL));
5456 greloc_patch(sym, addr);
5457 } else {
5458 do_def:
5459 sym_push(v, t, r, addr);
5463 if (tok != ',') {
5464 skip(';');
5465 break;
5467 next();
5473 /* put all global symbols in the extern stack and do all the
5474 resolving which can be done without using external symbols from DLLs */
5475 /* XXX: could try to verify types, but would not to save them in
5476 extern_stack too */
5477 void resolve_global_syms(void)
5479 Sym *s, *s1, *ext_sym;
5480 Reloc **p;
5482 s = global_stack.top;
5483 while (s != NULL) {
5484 s1 = s->prev;
5485 /* do not save static or typedefed symbols or types */
5486 if (!(s->t & (VT_STATIC | VT_TYPEDEF)) &&
5487 !(s->v & (SYM_FIELD | SYM_STRUCT)) &&
5488 (s->v < SYM_FIRST_ANOM)) {
5489 ext_sym = sym_find1(&extern_stack, s->v);
5490 if (!ext_sym) {
5491 /* if the symbol do not exist, we simply save it */
5492 ext_sym = sym_push1(&extern_stack, s->v, s->t, s->c);
5493 ext_sym->r = s->r;
5494 } else if (ext_sym->r & VT_FORWARD) {
5495 /* external symbol already exists, but only as forward
5496 definition */
5497 if (!(s->r & VT_FORWARD)) {
5498 /* s is not forward, so we can relocate all symbols */
5499 greloc_patch(ext_sym, s->c);
5500 } else {
5501 /* the two symbols are forward: merge them */
5502 p = (Reloc **)&ext_sym->c;
5503 while (*p != NULL)
5504 p = &(*p)->next;
5505 *p = (Reloc *)s->c;
5507 } else {
5508 /* external symbol already exists and is defined :
5509 patch all references to it */
5510 if (!(s->r & VT_FORWARD))
5511 error("'%s' defined twice", get_tok_str(s->v, NULL));
5512 greloc_patch(s, ext_sym->c);
5515 s = s1;
5519 /* compile a C file. Return non zero if errors. */
5520 int tcc_compile_file(const char *filename1)
5522 Sym *define_start;
5523 char buf[512];
5525 line_num = 1;
5526 funcname = "";
5527 filename = (char *)filename1;
5529 file = fopen(filename, "r");
5530 if (!file)
5531 error("file '%s' not found", filename);
5532 include_stack_ptr = include_stack;
5533 ifdef_stack_ptr = ifdef_stack;
5535 vtop = vstack - 1;
5536 anon_sym = SYM_FIRST_ANOM;
5538 /* file info: full path + filename */
5539 if (do_debug) {
5540 getcwd(buf, sizeof(buf));
5541 pstrcat(buf, sizeof(buf), "/");
5542 put_stabs(buf, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5543 put_stabs(filename, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5545 /* define common 'char *' type because it is often used internally
5546 for arrays and struct dereference */
5547 char_pointer_type = mk_pointer(VT_BYTE);
5549 define_start = define_stack.top;
5550 inp();
5551 ch = '\n'; /* needed to parse correctly first preprocessor command */
5552 next();
5553 decl(VT_CONST);
5554 if (tok != -1)
5555 expect("declaration");
5556 fclose(file);
5558 /* end of translation unit info */
5559 if (do_debug) {
5560 put_stabn(N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5563 /* reset define stack, but leave -Dsymbols (may be incorrect if
5564 they are undefined) */
5565 sym_pop(&define_stack, define_start);
5567 resolve_global_syms();
5569 sym_pop(&global_stack, NULL);
5571 return 0;
5574 /* define a symbol. A value can also be provided with the '=' operator */
5575 /* XXX: currently only handles integers and string defines. should use
5576 tcc parser, but would need a custom 'FILE *' */
5577 void define_symbol(const char *sym)
5579 TokenSym *ts;
5580 int *str, len;
5581 CValue cval;
5582 const char *p;
5583 char buf[256];
5585 p = strchr(sym, '=');
5586 if (!p) {
5587 pstrcpy(buf, sizeof(buf), sym);
5588 p = "1";
5589 } else {
5590 len = p - sym;
5591 if (len > sizeof(buf) - 1)
5592 len = sizeof(buf) - 1;
5593 memcpy(buf, sym, len);
5594 buf[len] = '\0';
5595 p++;
5598 ts = tok_alloc(buf, 0);
5599 str = NULL;
5600 len = 0;
5601 if (isnum(*p)) {
5602 /* integer case */
5603 cval.i = atoi(p);
5604 tok_add2(&str, &len, TOK_CINT, &cval);
5605 } else {
5606 /* string case */
5607 cval.ts = tok_alloc(p, 0);
5608 tok_add2(&str, &len, TOK_STR, &cval);
5610 tok_add(&str, &len, 0);
5611 sym_push1(&define_stack, ts->tok, MACRO_OBJ, (int)str);
5614 void undef_symbol(const char *sym)
5616 TokenSym *ts;
5617 Sym *s;
5618 printf("undef %s\n", sym);
5619 ts = tok_alloc(sym, 0);
5620 s = sym_find1(&define_stack, tok);
5621 /* undefine symbol by putting an invalid name */
5622 if (s)
5623 sym_undef(&define_stack, s);
5626 /* open a dynamic library so that its symbol are available for
5627 compiled programs */
5628 void open_dll(char *libname)
5630 char buf[1024];
5631 void *h;
5633 snprintf(buf, sizeof(buf), "lib%s.so", libname);
5634 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
5635 if (!h)
5636 error((char *)dlerror());
5639 static void *resolve_sym(const char *sym)
5641 void *ptr;
5642 if (do_bounds_check) {
5643 ptr = bound_resolve_sym(sym);
5644 if (ptr)
5645 return ptr;
5647 return dlsym(NULL, sym);
5650 void resolve_extern_syms(void)
5652 Sym *s, *s1;
5653 char *str;
5654 int addr;
5656 s = extern_stack.top;
5657 while (s != NULL) {
5658 s1 = s->prev;
5659 if (s->r & VT_FORWARD) {
5660 /* if there is at least one relocation to do, then find it
5661 and patch it */
5662 if (s->c) {
5663 str = get_tok_str(s->v, NULL);
5664 addr = (int)resolve_sym(str);
5665 if (!addr)
5666 error("unresolved external reference '%s'", str);
5667 greloc_patch(s, addr);
5670 s = s1;
5674 static int put_elf_str(Section *s, const char *sym)
5676 int c, offset;
5677 offset = s->data_ptr - s->data;
5678 for(;;) {
5679 c = *sym++;
5680 *s->data_ptr++ = c;
5681 if (c == '\0')
5682 break;
5684 return offset;
5687 static void put_elf_sym(Section *s,
5688 unsigned long value, unsigned long size,
5689 int info, int other, int shndx, const char *name)
5691 int name_offset;
5692 Elf32_Sym *sym;
5694 sym = (Elf32_Sym *)s->data_ptr;
5695 if (name)
5696 name_offset = put_elf_str(s->link, name);
5697 else
5698 name_offset = 0;
5699 sym->st_name = name_offset;
5700 sym->st_value = value;
5701 sym->st_size = size;
5702 sym->st_info = info;
5703 sym->st_other = other;
5704 sym->st_shndx = shndx;
5705 s->data_ptr += sizeof(Elf32_Sym);
5708 /* put stab debug information */
5710 typedef struct {
5711 unsigned long n_strx; /* index into string table of name */
5712 unsigned char n_type; /* type of symbol */
5713 unsigned char n_other; /* misc info (usually empty) */
5714 unsigned short n_desc; /* description field */
5715 unsigned long n_value; /* value of symbol */
5716 } Stab_Sym;
5718 static void put_stabs(const char *str, int type, int other, int desc, int value)
5720 Stab_Sym *sym;
5722 sym = (Stab_Sym *)stab_section->data_ptr;
5723 if (str) {
5724 sym->n_strx = put_elf_str(stabstr_section, str);
5725 } else {
5726 sym->n_strx = 0;
5728 sym->n_type = type;
5729 sym->n_other = other;
5730 sym->n_desc = desc;
5731 sym->n_value = value;
5733 stab_section->data_ptr += sizeof(Stab_Sym);
5736 static void put_stabn(int type, int other, int desc, int value)
5738 put_stabs(NULL, type, other, desc, value);
5741 static void put_stabd(int type, int other, int desc)
5743 put_stabs(NULL, type, other, desc, 0);
5746 /* output an ELF file (currently, only for testing) */
5747 /* XXX: better program header generation */
5748 /* XXX: handle realloc'ed sections (instead of mmaping them) */
5749 /* XXX: generate dynamic reloc info + DLL tables */
5750 /* XXX: generate startup code */
5751 void build_exe(char *filename)
5753 Elf32_Ehdr ehdr;
5754 FILE *f;
5755 int shnum, i, phnum, file_offset, offset, size, j;
5756 Section *sec, *strsec;
5757 Elf32_Shdr *shdr, *sh;
5758 Elf32_Phdr *phdr, *ph;
5760 memset(&ehdr, 0, sizeof(ehdr));
5762 /* we add a section for symbols */
5763 strsec = new_section(".shstrtab", SHT_STRTAB, 0);
5764 put_elf_str(strsec, "");
5766 /* count number of sections and compute number of program segments */
5767 shnum = 1; /* section index zero is reserved */
5768 phnum = 0;
5769 for(sec = first_section; sec != NULL; sec = sec->next) {
5770 shnum++;
5771 if (sec->sh_flags & SHF_ALLOC)
5772 phnum++;
5774 /* allocate section headers */
5775 shdr = malloc(shnum * sizeof(Elf32_Shdr));
5776 if (!shdr)
5777 error("memory full");
5778 memset(shdr, 0, shnum * sizeof(Elf32_Shdr));
5779 /* allocate program segment headers */
5780 phdr = malloc(phnum * sizeof(Elf32_Phdr));
5781 if (!phdr)
5782 error("memory full");
5783 memset(phdr, 0, phnum * sizeof(Elf32_Phdr));
5785 /* XXX: find correct load order */
5786 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
5787 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
5788 sh = &shdr[i];
5789 sh->sh_name = put_elf_str(strsec, sec->name);
5790 sh->sh_type = sec->sh_type;
5791 sh->sh_flags = sec->sh_flags;
5792 sh->sh_entsize = sec->sh_entsize;
5793 if (sec->link)
5794 sh->sh_link = sec->link->sh_num;
5795 if (sh->sh_type == SHT_STRTAB) {
5796 sh->sh_addralign = 1;
5797 } else if (sh->sh_type == SHT_SYMTAB ||
5798 (sh->sh_flags & SHF_ALLOC) == 0) {
5799 sh->sh_addralign = 4;
5800 } else {
5801 sh->sh_addr = (Elf32_Word)sec->data;
5802 sh->sh_addralign = 4096;
5804 sh->sh_size = (Elf32_Word)sec->data_ptr - (Elf32_Word)sec->data;
5805 /* align to section start */
5806 file_offset = (file_offset + sh->sh_addralign - 1) &
5807 ~(sh->sh_addralign - 1);
5808 sh->sh_offset = file_offset;
5809 file_offset += sh->sh_size;
5811 /* build program headers (simplistic - not fully correct) */
5812 j = 0;
5813 for(i=1;i<shnum;i++) {
5814 sh = &shdr[i];
5815 if (sh->sh_type == SHT_PROGBITS &&
5816 (sh->sh_flags & SHF_ALLOC) != 0) {
5817 ph = &phdr[j++];
5818 ph->p_type = PT_LOAD;
5819 ph->p_offset = sh->sh_offset;
5820 ph->p_vaddr = sh->sh_addr;
5821 ph->p_paddr = ph->p_vaddr;
5822 ph->p_filesz = sh->sh_size;
5823 ph->p_memsz = sh->sh_size;
5824 ph->p_flags = PF_R;
5825 if (sh->sh_flags & SHF_WRITE)
5826 ph->p_flags |= PF_W;
5827 if (sh->sh_flags & SHF_EXECINSTR)
5828 ph->p_flags |= PF_X;
5829 ph->p_align = sh->sh_addralign;
5833 /* align to 4 */
5834 file_offset = (file_offset + 3) & -4;
5836 /* fill header */
5837 ehdr.e_ident[0] = ELFMAG0;
5838 ehdr.e_ident[1] = ELFMAG1;
5839 ehdr.e_ident[2] = ELFMAG2;
5840 ehdr.e_ident[3] = ELFMAG3;
5841 ehdr.e_ident[4] = ELFCLASS32;
5842 ehdr.e_ident[5] = ELFDATA2LSB;
5843 ehdr.e_ident[6] = EV_CURRENT;
5844 ehdr.e_type = ET_EXEC;
5845 ehdr.e_machine = EM_386;
5846 ehdr.e_version = EV_CURRENT;
5847 ehdr.e_entry = 0; /* XXX: patch it */
5848 ehdr.e_phoff = sizeof(Elf32_Ehdr);
5849 ehdr.e_shoff = file_offset;
5850 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
5851 ehdr.e_phentsize = sizeof(Elf32_Phdr);
5852 ehdr.e_phnum = phnum;
5853 ehdr.e_shentsize = sizeof(Elf32_Shdr);
5854 ehdr.e_shnum = shnum;
5855 ehdr.e_shstrndx = shnum - 1;
5857 /* write elf file */
5858 f = fopen(filename, "w");
5859 if (!f)
5860 error("could not write '%s'", filename);
5861 fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
5862 fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
5863 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
5864 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
5865 sh = &shdr[i];
5866 while (offset < sh->sh_offset) {
5867 fputc(0, f);
5868 offset++;
5870 size = sec->data_ptr - sec->data;
5871 fwrite(sec->data, 1, size, f);
5872 offset += size;
5874 while (offset < ehdr.e_shoff) {
5875 fputc(0, f);
5876 offset++;
5878 fwrite(shdr, 1, shnum * sizeof(Elf32_Shdr), f);
5879 fclose(f);
5882 /* print the position in the source file of PC value 'pc' by reading
5883 the stabs debug information */
5884 static void rt_printline(unsigned long wanted_pc)
5886 Stab_Sym *sym, *sym_end;
5887 char func_name[128];
5888 unsigned long func_addr, last_pc, pc;
5889 const char *incl_files[INCLUDE_STACK_SIZE];
5890 int incl_index, len, last_line_num, i;
5891 const char *str, *p;
5893 func_name[0] = '\0';
5894 func_addr = 0;
5895 incl_index = 0;
5896 last_pc = 0xffffffff;
5897 last_line_num = 1;
5898 sym = (Stab_Sym *)stab_section->data + 1;
5899 sym_end = (Stab_Sym *)stab_section->data_ptr;
5900 while (sym < sym_end) {
5901 switch(sym->n_type) {
5902 /* function start or end */
5903 case N_FUN:
5904 if (sym->n_strx == 0) {
5905 func_name[0] = '\0';
5906 func_addr = 0;
5907 } else {
5908 str = stabstr_section->data + sym->n_strx;
5909 p = strchr(str, ':');
5910 if (!p) {
5911 pstrcpy(func_name, sizeof(func_name), str);
5912 } else {
5913 len = p - str;
5914 if (len > sizeof(func_name) - 1)
5915 len = sizeof(func_name) - 1;
5916 memcpy(func_name, str, len);
5917 func_name[len] = '\0';
5919 func_addr = sym->n_value;
5921 break;
5922 /* line number info */
5923 case N_SLINE:
5924 pc = sym->n_value + func_addr;
5925 if (wanted_pc >= last_pc && wanted_pc < pc)
5926 goto found;
5927 last_pc = pc;
5928 last_line_num = sym->n_desc;
5929 break;
5930 /* include files */
5931 case N_BINCL:
5932 str = stabstr_section->data + sym->n_strx;
5933 add_incl:
5934 if (incl_index < INCLUDE_STACK_SIZE) {
5935 incl_files[incl_index++] = str;
5937 break;
5938 case N_EINCL:
5939 if (incl_index > 1)
5940 incl_index--;
5941 break;
5942 case N_SO:
5943 if (sym->n_strx == 0) {
5944 incl_index = 0; /* end of translation unit */
5945 } else {
5946 str = stabstr_section->data + sym->n_strx;
5947 /* do not add path */
5948 len = strlen(str);
5949 if (len > 0 && str[len - 1] != '/')
5950 goto add_incl;
5952 break;
5954 sym++;
5956 /* did not find line number info: */
5957 fprintf(stderr, "(no debug info, pc=0x%08lx): ", wanted_pc);
5958 return;
5959 found:
5960 for(i = 0; i < incl_index - 1; i++)
5961 fprintf(stderr, "In file included from %s\n",
5962 incl_files[i]);
5963 if (incl_index > 0) {
5964 fprintf(stderr, "%s:%d: ",
5965 incl_files[incl_index - 1], last_line_num);
5967 if (func_name[0] != '\0') {
5968 fprintf(stderr, "in function '%s()': ", func_name);
5973 /* signal handler for fatal errors */
5974 static void sig_error(int signum, siginfo_t *siginf, void *puc)
5976 struct ucontext *uc = puc;
5977 unsigned long pc;
5979 #ifdef __i386__
5980 pc = uc->uc_mcontext.gregs[14];
5981 #else
5982 #error please put the right sigcontext field
5983 #endif
5985 rt_printline(pc);
5987 switch(signum) {
5988 case SIGFPE:
5989 switch(siginf->si_code) {
5990 case FPE_INTDIV:
5991 case FPE_FLTDIV:
5992 fprintf(stderr, "division by zero\n");
5993 break;
5994 default:
5995 fprintf(stderr, "floating point exception\n");
5996 break;
5998 break;
5999 case SIGBUS:
6000 case SIGSEGV:
6001 fprintf(stderr, "dereferencing invalid pointer\n");
6002 break;
6003 case SIGILL:
6004 fprintf(stderr, "illegal instruction\n");
6005 break;
6006 case SIGABRT:
6007 fprintf(stderr, "abort() called\n");
6008 break;
6009 default:
6010 fprintf(stderr, "caught signal %d\n", signum);
6011 break;
6013 exit(255);
6016 /* launch the compiled program with the given arguments */
6017 int launch_exe(int argc, char **argv)
6019 Sym *s;
6020 int (*t)();
6021 struct sigaction sigact;
6023 s = sym_find1(&extern_stack, TOK_MAIN);
6024 if (!s || (s->r & VT_FORWARD))
6025 error("main() not defined");
6027 if (do_debug) {
6028 /* install TCC signal handlers to print debug info on fatal
6029 runtime errors */
6030 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
6031 sigact.sa_sigaction = sig_error;
6032 sigemptyset(&sigact.sa_mask);
6033 sigaction(SIGFPE, &sigact, NULL);
6034 sigaction(SIGILL, &sigact, NULL);
6035 sigaction(SIGSEGV, &sigact, NULL);
6036 sigaction(SIGBUS, &sigact, NULL);
6037 sigaction(SIGABRT, &sigact, NULL);
6040 if (do_bounds_check) {
6041 int *p, *p_end;
6042 __bound_init();
6043 /* add all known static regions */
6044 p = (int *)bounds_section->data;
6045 p_end = (int *)bounds_section->data_ptr;
6046 while (p < p_end) {
6047 __bound_new_region((void *)p[0], p[1]);
6048 p += 2;
6052 t = (int (*)())s->c;
6053 return (*t)(argc, argv);
6057 void help(void)
6059 printf("tcc version 0.9.3 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
6060 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
6061 " [-i infile] infile [infile_args...]\n"
6062 "\n"
6063 "-Idir : add include path 'dir'\n"
6064 "-Dsym[=val] : define 'sym' with value 'val'\n"
6065 "-Usym : undefine 'sym'\n"
6066 "-llib : link with dynamic library 'lib'\n"
6067 "-g : generate runtime debug info\n"
6068 "-b : compile with built-in memory and bounds checker (implies -g)\n"
6069 "-i infile : compile infile\n"
6073 int main(int argc, char **argv)
6075 char *p, *r, *outfile;
6076 int optind;
6078 include_paths[0] = "/usr/include";
6079 include_paths[1] = "/usr/lib/tcc";
6080 include_paths[2] = "/usr/local/lib/tcc";
6081 nb_include_paths = 3;
6083 /* add all tokens */
6084 tok_ident = TOK_IDENT;
6085 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";
6086 while (*p) {
6087 r = p;
6088 while (*r++);
6089 tok_alloc(p, r - p - 1);
6090 p = r;
6093 /* standard defines */
6094 define_symbol("__STDC__");
6095 #ifdef __i386__
6096 define_symbol("__i386__");
6097 #endif
6098 /* tiny C specific defines */
6099 define_symbol("__TINYC__");
6101 /* create standard sections */
6102 text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
6103 data_section = new_section(".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6104 /* XXX: should change type to SHT_NOBITS */
6105 bss_section = new_section(".bss", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6107 optind = 1;
6108 outfile = NULL;
6109 while (1) {
6110 if (optind >= argc) {
6111 show_help:
6112 help();
6113 return 1;
6115 r = argv[optind];
6116 if (r[0] != '-')
6117 break;
6118 optind++;
6119 if (r[1] == 'I') {
6120 if (nb_include_paths >= INCLUDE_PATHS_MAX)
6121 error("too many include paths");
6122 include_paths[nb_include_paths++] = r + 2;
6123 } else if (r[1] == 'D') {
6124 define_symbol(r + 2);
6125 } else if (r[1] == 'U') {
6126 undef_symbol(r + 2);
6127 } else if (r[1] == 'l') {
6128 open_dll(r + 2);
6129 } else if (r[1] == 'i') {
6130 if (optind >= argc)
6131 goto show_help;
6132 tcc_compile_file(argv[optind++]);
6133 } else if (r[1] == 'b') {
6134 if (!do_bounds_check) {
6135 do_bounds_check = 1;
6136 /* create bounds sections */
6137 bounds_section = new_section(".bounds",
6138 SHT_PROGBITS, SHF_ALLOC);
6139 lbounds_section = new_section(".lbounds",
6140 SHT_PROGBITS, SHF_ALLOC);
6141 /* debug is implied */
6142 goto debug_opt;
6144 } else if (r[1] == 'g') {
6145 debug_opt:
6146 if (!do_debug) {
6147 do_debug = 1;
6149 /* stab symbols */
6150 stab_section = new_section(".stab", SHT_PROGBITS, 0);
6151 stab_section->sh_entsize = sizeof(Stab_Sym);
6152 stabstr_section = new_section(".stabstr", SHT_STRTAB, 0);
6153 put_elf_str(stabstr_section, "");
6154 stab_section->link = stabstr_section;
6155 /* put first entry */
6156 put_stabs("", 0, 0, 0, 0);
6158 /* elf symbols */
6159 symtab_section = new_section(".symtab", SHT_SYMTAB, 0);
6160 symtab_section->sh_entsize = sizeof(Elf32_Sym);
6161 strtab_section = new_section(".strtab", SHT_STRTAB, 0);
6162 put_elf_str(strtab_section, "");
6163 symtab_section->link = strtab_section;
6164 put_elf_sym(symtab_section, 0, 0, 0, 0, 0, NULL);
6166 } else if (r[1] == 'o') {
6167 /* currently, only for testing, so not documented */
6168 if (optind >= argc)
6169 goto show_help;
6170 outfile = argv[optind++];
6171 } else {
6172 fprintf(stderr, "invalid option -- '%s'\n", r);
6173 exit(1);
6177 tcc_compile_file(argv[optind]);
6179 resolve_extern_syms();
6181 if (outfile) {
6182 build_exe(outfile);
6183 return 0;
6184 } else {
6185 return launch_exe(argc - optind, argv + optind);