added minimal debug info support
[tinycc.git] / tcc.c
blob166c00a940f578c739b54b71c8ef074b617a92b3
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 #ifndef CONFIG_TCC_STATIC
33 #include <dlfcn.h>
34 #endif
36 //#define DEBUG
37 /* preprocessor debug */
38 //#define PP_DEBUG
40 /* amount of virtual memory associate to a section (currently, we do
41 not realloc them) */
42 #define SECTION_VSIZE (1024 * 1024)
44 #define INCLUDE_STACK_SIZE 32
45 #define IFDEF_STACK_SIZE 64
46 #define VSTACK_SIZE 64
47 #define STRING_MAX_SIZE 1024
48 #define INCLUDE_PATHS_MAX 32
50 #define TOK_HASH_SIZE 521
51 #define TOK_ALLOC_INCR 256 /* must be a power of two */
52 #define SYM_HASH_SIZE 263
54 /* token symbol management */
55 typedef struct TokenSym {
56 struct TokenSym *hash_next;
57 int tok; /* token number */
58 int len;
59 char str[1];
60 } TokenSym;
62 /* constant value */
63 typedef union CValue {
64 long double ld;
65 double d;
66 float f;
67 int i;
68 unsigned int ui;
69 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
70 long long ll;
71 unsigned long long ull;
72 struct TokenSym *ts;
73 struct Sym *sym;
74 int tab[1];
75 } CValue;
77 /* value on stack */
78 typedef struct SValue {
79 int t; /* type */
80 unsigned short r; /* register + flags */
81 unsigned short r2; /* second register, used for 'long long'
82 type. If not used, set to VT_CONST */
83 CValue c; /* constant */
84 } SValue;
86 /* symbol management */
87 typedef struct Sym {
88 int v; /* symbol token */
89 int t; /* associated type */
90 int r; /* associated register */
91 int c; /* associated number */
92 struct Sym *next; /* next related symbol */
93 struct Sym *prev; /* prev symbol in stack */
94 struct Sym *hash_next; /* next symbol in hash table */
95 } Sym;
97 typedef struct SymStack {
98 struct Sym *top;
99 struct Sym *hash[SYM_HASH_SIZE];
100 } SymStack;
102 /* relocation entry (currently only used for functions or variables */
103 typedef struct Reloc {
104 int type; /* type of relocation */
105 int addr; /* address of relocation */
106 struct Reloc *next; /* next relocation */
107 } Reloc;
109 #define RELOC_ADDR32 1 /* 32 bits relocation */
110 #define RELOC_REL32 2 /* 32 bits relative relocation */
112 /* section definition */
113 typedef struct Section {
114 char name[64]; /* section name */
115 unsigned char *data; /* section data */
116 unsigned char *data_ptr; /* current data pointer */
117 int sh_num; /* elf section number */
118 int sh_type; /* elf section type */
119 int sh_flags; /* elf section flags */
120 int sh_entsize; /* elf entry size */
121 struct Section *link; /* link to another section */
122 struct Section *next;
123 } Section;
125 /* GNUC attribute definition */
126 typedef struct AttributeDef {
127 int aligned;
128 Section *section;
129 } AttributeDef;
131 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
132 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
133 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
135 #define FUNC_NEW 1 /* ansi function prototype */
136 #define FUNC_OLD 2 /* old function prototype */
137 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
139 /* field 'Sym.t' for macros */
140 #define MACRO_OBJ 0 /* object like macro */
141 #define MACRO_FUNC 1 /* function like macro */
143 /* type_decl() types */
144 #define TYPE_ABSTRACT 1 /* type without variable */
145 #define TYPE_DIRECT 2 /* type with variable */
147 typedef struct {
148 FILE *file;
149 char *filename;
150 int line_num;
151 } IncludeFile;
153 /* parser */
154 FILE *file;
155 int line_num;
156 int ch, ch1, tok, tok1;
157 CValue tokc, tok1c;
159 /* sections */
160 Section *first_section;
161 int section_num;
162 Section *text_section, *data_section, *bss_section; /* predefined sections */
163 Section *cur_text_section; /* current section where function code is
164 generated */
165 Section *bounds_section; /* contains global data bound description */
166 /* debug sections */
167 Section *stab_section, *stabstr_section, *symtab_section, *strtab_section;
169 /* loc : local variable index
170 ind : output code index
171 rsym: return symbol
172 anon_sym: anonymous symbol index
174 int rsym, anon_sym,
175 prog, ind, loc, const_wanted;
176 int global_expr; /* true if compound literals must be allocated
177 globally (used during initializers parsing */
178 int func_vt, func_vc; /* current function return type (used by
179 return instruction) */
180 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
181 int tok_ident;
182 TokenSym **table_ident;
183 TokenSym *hash_ident[TOK_HASH_SIZE];
184 char token_buf[STRING_MAX_SIZE + 1];
185 char *filename, *funcname;
186 /* contains global symbols which remain between each translation unit */
187 SymStack extern_stack;
188 SymStack define_stack, global_stack, local_stack, label_stack;
190 SValue vstack[VSTACK_SIZE], *vtop;
191 int *macro_ptr, *macro_ptr_allocated;
192 IncludeFile include_stack[INCLUDE_STACK_SIZE], *include_stack_ptr;
193 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
194 char *include_paths[INCLUDE_PATHS_MAX];
195 int nb_include_paths;
196 int char_pointer_type;
198 /* compile with debug symbol (and use them if error during execution) */
199 int do_debug = 0;
201 /* compile with built-in memory and bounds checker */
202 int do_bounds_check = 0;
204 /* use GNU C extensions */
205 int gnu_ext = 1;
207 /* use Tiny C extensions */
208 int tcc_ext = 1;
210 /* The current value can be: */
211 #define VT_VALMASK 0x00ff
212 #define VT_CONST 0x00f0 /* constant in vc
213 (must be first non register value) */
214 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
215 #define VT_LOCAL 0x00f2 /* offset on stack */
216 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
217 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
218 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
219 #define VT_LVAL 0x0100 /* var is an lvalue */
220 #define VT_FORWARD 0x0200 /* value is forward reference */
221 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (user for
222 bool/char/short stored in int registers) */
224 /* types */
225 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
227 #define VT_INT 0 /* integer type */
228 #define VT_BYTE 1 /* signed byte type */
229 #define VT_SHORT 2 /* short type */
230 #define VT_VOID 3 /* void type */
231 #define VT_PTR 4 /* pointer increment */
232 #define VT_ENUM 5 /* enum definition */
233 #define VT_FUNC 6 /* function type */
234 #define VT_STRUCT 7 /* struct/union definition */
235 #define VT_FLOAT 8 /* IEEE float */
236 #define VT_DOUBLE 9 /* IEEE double */
237 #define VT_LDOUBLE 10 /* IEEE long double */
238 #define VT_BOOL 11 /* ISOC99 boolean type */
239 #define VT_LLONG 12 /* 64 bit integer */
240 #define VT_LONG 13 /* long integer (NEVER USED as type, only
241 during parsing) */
242 #define VT_BTYPE 0x000f /* mask for basic type */
243 #define VT_UNSIGNED 0x0010 /* unsigned type */
244 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
245 #define VT_BITFIELD 0x0040 /* bitfield modifier */
247 /* storage */
248 #define VT_EXTERN 0x00000080 /* extern definition */
249 #define VT_STATIC 0x00000100 /* static variable */
250 #define VT_TYPEDEF 0x00000200 /* typedef definition */
252 /* type mask (except storage) */
253 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
255 /* token values */
257 /* warning: the following compare tokens depend on i386 asm code */
258 #define TOK_ULT 0x92
259 #define TOK_UGE 0x93
260 #define TOK_EQ 0x94
261 #define TOK_NE 0x95
262 #define TOK_ULE 0x96
263 #define TOK_UGT 0x97
264 #define TOK_LT 0x9c
265 #define TOK_GE 0x9d
266 #define TOK_LE 0x9e
267 #define TOK_GT 0x9f
269 #define TOK_LAND 0xa0
270 #define TOK_LOR 0xa1
272 #define TOK_DEC 0xa2
273 #define TOK_MID 0xa3 /* inc/dec, to void constant */
274 #define TOK_INC 0xa4
275 #define TOK_UDIV 0xb0 /* unsigned division */
276 #define TOK_UMOD 0xb1 /* unsigned modulo */
277 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
278 #define TOK_CINT 0xb3 /* number in tokc */
279 #define TOK_CCHAR 0xb4 /* char constant in tokc */
280 #define TOK_STR 0xb5 /* pointer to string in tokc */
281 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
282 #define TOK_LCHAR 0xb7
283 #define TOK_LSTR 0xb8
284 #define TOK_CFLOAT 0xb9 /* float constant */
285 #define TOK_CDOUBLE 0xc0 /* double constant */
286 #define TOK_CLDOUBLE 0xc1 /* long double constant */
287 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
288 #define TOK_ADDC1 0xc3 /* add with carry generation */
289 #define TOK_ADDC2 0xc4 /* add with carry use */
290 #define TOK_SUBC1 0xc5 /* add with carry generation */
291 #define TOK_SUBC2 0xc6 /* add with carry use */
292 #define TOK_CUINT 0xc8 /* unsigned int constant */
293 #define TOK_CLLONG 0xc9 /* long long constant */
294 #define TOK_CULLONG 0xca /* unsigned long long constant */
295 #define TOK_ARROW 0xcb
296 #define TOK_DOTS 0xcc /* three dots */
297 #define TOK_SHR 0xcd /* unsigned shift right */
299 #define TOK_SHL 0x01 /* shift left */
300 #define TOK_SAR 0x02 /* signed shift right */
302 /* assignement operators : normal operator or 0x80 */
303 #define TOK_A_MOD 0xa5
304 #define TOK_A_AND 0xa6
305 #define TOK_A_MUL 0xaa
306 #define TOK_A_ADD 0xab
307 #define TOK_A_SUB 0xad
308 #define TOK_A_DIV 0xaf
309 #define TOK_A_XOR 0xde
310 #define TOK_A_OR 0xfc
311 #define TOK_A_SHL 0x81
312 #define TOK_A_SAR 0x82
314 /* all identificators and strings have token above that */
315 #define TOK_IDENT 256
317 enum {
318 TOK_INT = TOK_IDENT,
319 TOK_VOID,
320 TOK_CHAR,
321 TOK_IF,
322 TOK_ELSE,
323 TOK_WHILE,
324 TOK_BREAK,
325 TOK_RETURN,
326 TOK_FOR,
327 TOK_EXTERN,
328 TOK_STATIC,
329 TOK_UNSIGNED,
330 TOK_GOTO,
331 TOK_DO,
332 TOK_CONTINUE,
333 TOK_SWITCH,
334 TOK_CASE,
336 /* ignored types Must have contiguous values */
337 TOK_CONST,
338 TOK_VOLATILE,
339 TOK_LONG,
340 TOK_REGISTER,
341 TOK_SIGNED,
342 TOK_AUTO,
343 TOK_INLINE,
344 TOK_RESTRICT,
346 /* unsupported type */
347 TOK_FLOAT,
348 TOK_DOUBLE,
349 TOK_BOOL,
351 TOK_SHORT,
352 TOK_STRUCT,
353 TOK_UNION,
354 TOK_TYPEDEF,
355 TOK_DEFAULT,
356 TOK_ENUM,
357 TOK_SIZEOF,
358 TOK___ATTRIBUTE__,
360 /* preprocessor only */
361 TOK_UIDENT, /* first "user" ident (not keyword) */
362 TOK_DEFINE = TOK_UIDENT,
363 TOK_INCLUDE,
364 TOK_IFDEF,
365 TOK_IFNDEF,
366 TOK_ELIF,
367 TOK_ENDIF,
368 TOK_DEFINED,
369 TOK_UNDEF,
370 TOK_ERROR,
371 TOK_LINE,
372 TOK___LINE__,
373 TOK___FILE__,
374 TOK___DATE__,
375 TOK___TIME__,
376 TOK___VA_ARGS__,
378 /* special identifiers */
379 TOK___FUNC__,
380 TOK_MAIN,
381 /* attribute identifiers */
382 TOK_SECTION,
383 TOK___SECTION__,
384 TOK_ALIGNED,
385 TOK___ALIGNED__,
386 TOK_UNUSED,
387 TOK___UNUSED__,
390 /* XXX: need to define this to use them in non ISOC99 context */
391 extern float strtof (const char *__nptr, char **__endptr);
392 extern long double strtold (const char *__nptr, char **__endptr);
394 void sum(int l);
395 void next(void);
396 void next_nomacro(void);
397 int expr_const(void);
398 void expr_eq(void);
399 void gexpr(void);
400 void decl(int l);
401 void decl_initializer(int t, int r, int c, int first, int size_only);
402 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init);
403 int gv(int rc);
404 void move_reg(int r, int s);
405 void save_regs(void);
406 void save_reg(int r);
407 void vpop(void);
408 void vswap(void);
409 void vdup(void);
410 int get_reg(int rc);
412 void macro_subst(int **tok_str, int *tok_len,
413 Sym **nested_list, int *macro_str);
414 int save_reg_forced(int r);
415 void gen_op(int op);
416 void force_charshort_cast(int t);
417 void gen_cast(int t);
418 void vstore(void);
419 Sym *sym_find(int v);
420 Sym *sym_push(int v, int t, int r, int c);
422 /* type handling */
423 int type_size(int t, int *a);
424 int pointed_type(int t);
425 int pointed_size(int t);
426 int is_compatible_types(int t1, int t2);
427 int parse_btype(int *type_ptr, AttributeDef *ad);
428 int type_decl(int *v, int t, int td);
430 void error(const char *fmt, ...);
431 void vpushi(int v);
432 void vset(int t, int r, int v);
433 void type_to_str(char *buf, int buf_size,
434 int t, const char *varstr);
436 /* section generation */
437 void greloc(Sym *s, int addr, int type);
438 static int put_elf_str(Section *s, const char *sym);
439 static void put_elf_sym(Section *s,
440 unsigned long value, unsigned long size,
441 int info, int other, int shndx, const char *name);
442 static void put_stabs(const char *str, int type, int other, int desc, int value);
443 static void put_stabn(int type, int other, int desc, int value);
444 static void put_stabd(int type, int other, int desc);
446 /* true if float/double/long double type */
447 static inline int is_float(int t)
449 int bt;
450 bt = t & VT_BTYPE;
451 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
454 #include "bcheck.c"
456 #include "i386-gen.c"
458 #ifdef CONFIG_TCC_STATIC
460 #define RTLD_LAZY 0x001
461 #define RTLD_NOW 0x002
462 #define RTLD_GLOBAL 0x100
464 /* dummy function for profiling */
465 void *dlopen(const char *filename, int flag)
467 return NULL;
470 const char *dlerror(void)
472 return "error";
475 typedef struct TCCSyms {
476 char *str;
477 void *ptr;
478 } TCCSyms;
480 #define TCCSYM(a) { #a, &a, },
482 /* add the symbol you want here if no dynamic linking is done */
483 static TCCSyms tcc_syms[] = {
484 TCCSYM(printf)
485 TCCSYM(fprintf)
486 TCCSYM(fopen)
487 TCCSYM(fclose)
488 { NULL, NULL },
491 void *dlsym(void *handle, char *symbol)
493 TCCSyms *p;
494 p = tcc_syms;
495 while (p->str != NULL) {
496 if (!strcmp(p->str, symbol))
497 return p->ptr;
498 p++;
500 return NULL;
503 #endif
505 /********************************************************/
506 /* runtime library is there */
507 /* XXX: we suppose that the host compiler handles 'long long'. It
508 would not be difficult to suppress this assumption */
510 /* XXX: these functions are defined in libgcc. Should provide a
511 portable code too. */
512 long long __divll(long long a, long long b)
514 return a / b;
517 long long __modll(long long a, long long b)
519 return a % b;
522 unsigned long long __divull(unsigned long long a, unsigned long long b)
524 return a / b;
527 unsigned long long __modull(unsigned long long a, unsigned long long b)
529 return a % b;
532 long long __sardi3(long long a, int b)
534 return a >> b;
537 unsigned long long __shrdi3(unsigned long long a, int b)
539 return a >> b;
542 long long __shldi3(long long a, int b)
544 return a << b;
547 float __ulltof(unsigned long long a)
549 return (float)a;
552 double __ulltod(unsigned long long a)
554 return (double)a;
557 long double __ulltold(unsigned long long a)
559 return (long double)a;
562 unsigned long long __ftoull(float a)
564 return (unsigned long long)a;
567 unsigned long long __dtoull(double a)
569 return (unsigned long long)a;
572 unsigned long long __ldtoull(long double a)
574 return (unsigned long long)a;
578 /********************************************************/
580 /* copy a string and truncate it */
581 char *pstrcpy(char *buf, int buf_size, const char *s)
583 char *q, *q_end;
584 int c;
586 q = buf;
587 q_end = buf + buf_size - 1;
588 while (q < q_end) {
589 c = *s++;
590 if (c == '\0')
591 break;
592 *q++ = c;
594 *q = '\0';
595 return buf;
598 /* strcat and truncate */
599 char *pstrcat(char *buf, int buf_size, const char *s)
601 int len;
602 len = strlen(buf);
603 if (len < buf_size)
604 pstrcpy(buf + len, buf_size - len, s);
605 return buf;
608 Section *new_section(const char *name, int sh_type, int sh_flags)
610 Section *sec, **psec;
611 void *data;
613 sec = malloc(sizeof(Section));
614 if (!sec)
615 error("memory full");
616 memset(sec, 0, sizeof(Section));
617 pstrcpy(sec->name, sizeof(sec->name), name);
618 sec->link = NULL;
619 sec->sh_num = ++section_num;
620 sec->sh_type = sh_type;
621 sec->sh_flags = sh_flags;
622 data = mmap(NULL, SECTION_VSIZE,
623 PROT_EXEC | PROT_READ | PROT_WRITE,
624 MAP_PRIVATE | MAP_ANONYMOUS,
625 -1, 0);
626 if (data == (void *)(-1))
627 error("could not mmap section '%s'", name);
628 sec->data = data;
629 sec->data_ptr = data;
630 psec = &first_section;
631 while (*psec != NULL)
632 psec = &(*psec)->next;
633 sec->next = NULL;
634 *psec = sec;
635 return sec;
638 /* return a reference to a section, and create it if it does not
639 exists */
640 Section *find_section(const char *name)
642 Section *sec;
644 for(sec = first_section; sec != NULL; sec = sec->next) {
645 if (!strcmp(name, sec->name))
646 return sec;
648 /* sections are created as PROGBITS */
649 return new_section(name, SHT_PROGBITS, SHF_ALLOC);
652 /* add a new relocation entry to symbol 's' */
653 void greloc(Sym *s, int addr, int type)
655 Reloc *p;
656 p = malloc(sizeof(Reloc));
657 if (!p)
658 error("memory full");
659 p->type = type;
660 p->addr = addr;
661 p->next = (Reloc *)s->c;
662 s->c = (int)p;
665 /* patch each relocation entry with value 'val' */
666 void greloc_patch(Sym *s, int val)
668 Reloc *p, *p1;
670 p = (Reloc *)s->c;
671 while (p != NULL) {
672 p1 = p->next;
673 greloc_patch1(p, val);
674 free(p);
675 p = p1;
677 s->c = val;
678 s->r &= ~VT_FORWARD;
682 static inline int isid(int c)
684 return (c >= 'a' && c <= 'z') ||
685 (c >= 'A' && c <= 'Z') ||
686 c == '_';
689 static inline int isnum(int c)
691 return c >= '0' && c <= '9';
694 static inline int toup(int c)
696 if (ch >= 'a' && ch <= 'z')
697 return ch - 'a' + 'A';
698 else
699 return ch;
702 void printline(void)
704 IncludeFile *f;
705 for(f = include_stack; f < include_stack_ptr; f++)
706 fprintf(stderr, "In file included from %s:%d:\n",
707 f->filename, f->line_num);
708 fprintf(stderr, "%s:%d: ", filename, line_num);
711 void error(const char *fmt, ...)
713 va_list ap;
714 va_start(ap, fmt);
715 printline();
716 vfprintf(stderr, fmt, ap);
717 fprintf(stderr, "\n");
718 exit(1);
719 va_end(ap);
722 void expect(const char *msg)
724 error("%s expected", msg);
727 void warning(const char *fmt, ...)
729 va_list ap;
731 va_start(ap, fmt);
732 printline();
733 fprintf(stderr, "warning: ");
734 vfprintf(stderr, fmt, ap);
735 fprintf(stderr, "\n");
736 va_end(ap);
739 void skip(int c)
741 if (tok != c)
742 error("'%c' expected", c);
743 next();
746 void test_lvalue(void)
748 if (!(vtop->r & VT_LVAL))
749 expect("lvalue");
752 TokenSym *tok_alloc(const char *str, int len)
754 TokenSym *ts, **pts, **ptable;
755 int h, i;
757 if (len <= 0)
758 len = strlen(str);
759 h = 1;
760 for(i=0;i<len;i++)
761 h = ((h << 8) | (str[i] & 0xff)) % TOK_HASH_SIZE;
763 pts = &hash_ident[h];
764 while (1) {
765 ts = *pts;
766 if (!ts)
767 break;
768 if (ts->len == len && !memcmp(ts->str, str, len))
769 return ts;
770 pts = &(ts->hash_next);
773 if (tok_ident >= SYM_FIRST_ANOM)
774 error("memory full");
776 /* expand token table if needed */
777 i = tok_ident - TOK_IDENT;
778 if ((i % TOK_ALLOC_INCR) == 0) {
779 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
780 if (!ptable)
781 error("memory full");
782 table_ident = ptable;
785 ts = malloc(sizeof(TokenSym) + len);
786 if (!ts)
787 error("memory full");
788 table_ident[i] = ts;
789 ts->tok = tok_ident++;
790 ts->len = len;
791 ts->hash_next = NULL;
792 memcpy(ts->str, str, len + 1);
793 *pts = ts;
794 return ts;
797 void add_char(char **pp, int c)
799 char *p;
800 p = *pp;
801 if (c == '\'' || c == '\"' || c == '\\') {
802 /* XXX: could be more precise if char or string */
803 *p++ = '\\';
805 if (c >= 32 && c <= 126) {
806 *p++ = c;
807 } else {
808 *p++ = '\\';
809 if (c == '\n') {
810 *p++ = 'n';
811 } else {
812 *p++ = '0' + ((c >> 6) & 7);
813 *p++ = '0' + ((c >> 3) & 7);
814 *p++ = '0' + (c & 7);
817 *pp = p;
820 /* XXX: buffer overflow */
821 char *get_tok_str(int v, CValue *cv)
823 static char buf[STRING_MAX_SIZE + 1];
824 TokenSym *ts;
825 char *p;
826 int i;
828 if (v == TOK_CINT || v == TOK_CUINT) {
829 sprintf(buf, "%u", cv->ui);
830 return buf;
831 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
832 p = buf;
833 *p++ = '\'';
834 add_char(&p, cv->i);
835 *p++ = '\'';
836 *p = '\0';
837 return buf;
838 } else if (v == TOK_STR || v == TOK_LSTR) {
839 ts = cv->ts;
840 p = buf;
841 *p++ = '\"';
842 for(i=0;i<ts->len;i++)
843 add_char(&p, ts->str[i]);
844 *p++ = '\"';
845 *p = '\0';
846 return buf;
847 } else if (v < TOK_IDENT) {
848 p = buf;
849 *p++ = v;
850 *p = '\0';
851 return buf;
852 } else if (v < tok_ident) {
853 return table_ident[v - TOK_IDENT]->str;
854 } else {
855 /* should never happen */
856 return NULL;
860 /* push, without hashing */
861 Sym *sym_push2(Sym **ps, int v, int t, int c)
863 Sym *s;
864 s = malloc(sizeof(Sym));
865 if (!s)
866 error("memory full");
867 s->v = v;
868 s->t = t;
869 s->c = c;
870 s->next = NULL;
871 /* add in stack */
872 s->prev = *ps;
873 *ps = s;
874 return s;
877 /* find a symbol and return its associated structure. 's' is the top
878 of the symbol stack */
879 Sym *sym_find2(Sym *s, int v)
881 while (s) {
882 if (s->v == v)
883 return s;
884 s = s->prev;
886 return NULL;
889 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
891 /* find a symbol and return its associated structure. 'st' is the
892 symbol stack */
893 Sym *sym_find1(SymStack *st, int v)
895 Sym *s;
897 s = st->hash[HASH_SYM(v)];
898 while (s) {
899 if (s->v == v)
900 return s;
901 s = s->hash_next;
903 return NULL;
906 Sym *sym_push1(SymStack *st, int v, int t, int c)
908 Sym *s, **ps;
909 s = sym_push2(&st->top, v, t, c);
910 /* add in hash table */
911 if (v) {
912 ps = &st->hash[HASH_SYM(v)];
913 s->hash_next = *ps;
914 *ps = s;
916 return s;
919 /* find a symbol in the right symbol space */
920 Sym *sym_find(int v)
922 Sym *s;
923 s = sym_find1(&local_stack, v);
924 if (!s)
925 s = sym_find1(&global_stack, v);
926 return s;
929 /* push a given symbol on the symbol stack */
930 Sym *sym_push(int v, int t, int r, int c)
932 Sym *s;
933 if (local_stack.top)
934 s = sym_push1(&local_stack, v, t, c);
935 else
936 s = sym_push1(&global_stack, v, t, c);
937 s->r = r;
938 return s;
941 /* pop symbols until top reaches 'b' */
942 void sym_pop(SymStack *st, Sym *b)
944 Sym *s, *ss;
946 s = st->top;
947 while(s != b) {
948 ss = s->prev;
949 /* free hash table entry, except if symbol was freed (only
950 used for #undef symbols) */
951 if (s->v)
952 st->hash[HASH_SYM(s->v)] = s->hash_next;
953 free(s);
954 s = ss;
956 st->top = b;
959 /* undefined a hashed symbol (used for #undef). Its name is set to
960 zero */
961 void sym_undef(SymStack *st, Sym *s)
963 Sym **ss;
964 ss = &st->hash[HASH_SYM(s->v)];
965 while (*ss != NULL) {
966 if (*ss == s)
967 break;
968 ss = &(*ss)->hash_next;
970 *ss = s->hash_next;
971 s->v = 0;
974 /* no need to put that inline */
975 int handle_eof(void)
977 if (include_stack_ptr == include_stack)
978 return -1;
979 /* add end of include file debug info */
980 if (do_debug) {
981 put_stabd(N_EINCL, 0, 0);
983 /* pop include stack */
984 fclose(file);
985 free(filename);
986 include_stack_ptr--;
987 file = include_stack_ptr->file;
988 filename = include_stack_ptr->filename;
989 line_num = include_stack_ptr->line_num;
990 return 0;
993 /* read next char from current input file */
994 static inline void inp(void)
996 redo:
997 /* faster than fgetc */
998 ch1 = getc_unlocked(file);
999 if (ch1 == -1) {
1000 if (handle_eof() < 0)
1001 return;
1002 else
1003 goto redo;
1005 if (ch1 == '\n')
1006 line_num++;
1007 // printf("ch1=%c 0x%x\n", ch1, ch1);
1010 /* input with '\\n' handling */
1011 static inline void minp(void)
1013 redo:
1014 ch = ch1;
1015 inp();
1016 if (ch == '\\' && ch1 == '\n') {
1017 inp();
1018 goto redo;
1020 //printf("ch=%c 0x%x\n", ch, ch);
1024 /* same as minp, but also skip comments */
1025 void cinp(void)
1027 int c;
1029 if (ch1 == '/') {
1030 inp();
1031 if (ch1 == '/') {
1032 /* single line C++ comments */
1033 inp();
1034 while (ch1 != '\n' && ch1 != -1)
1035 inp();
1036 inp();
1037 ch = ' '; /* return space */
1038 } else if (ch1 == '*') {
1039 /* C comments */
1040 inp();
1041 while (ch1 != -1) {
1042 c = ch1;
1043 inp();
1044 if (c == '*' && ch1 == '/') {
1045 inp();
1046 ch = ' '; /* return space */
1047 break;
1050 } else {
1051 ch = '/';
1053 } else {
1054 minp();
1058 void skip_spaces(void)
1060 while (ch == ' ' || ch == '\t')
1061 cinp();
1064 /* skip block of text until #else, #elif or #endif. skip also pairs of
1065 #if/#endif */
1066 void preprocess_skip()
1068 int a;
1069 a = 0;
1070 while (1) {
1071 while (ch != '\n') {
1072 if (ch == -1)
1073 expect("#endif");
1074 cinp();
1076 cinp();
1077 skip_spaces();
1078 if (ch == '#') {
1079 cinp();
1080 next_nomacro();
1081 if (a == 0 &&
1082 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1083 break;
1084 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1085 a++;
1086 else if (tok == TOK_ENDIF)
1087 a--;
1092 /* return the number of additionnal 'ints' necessary to store the
1093 token */
1094 static inline int tok_ext_size(int t)
1096 switch(t) {
1097 /* 4 bytes */
1098 case TOK_CINT:
1099 case TOK_CUINT:
1100 case TOK_CCHAR:
1101 case TOK_LCHAR:
1102 case TOK_STR:
1103 case TOK_LSTR:
1104 case TOK_CFLOAT:
1105 return 1;
1106 case TOK_CDOUBLE:
1107 case TOK_CLLONG:
1108 case TOK_CULLONG:
1109 return 2;
1110 case TOK_CLDOUBLE:
1111 return LDOUBLE_SIZE / 4;
1112 default:
1113 return 0;
1117 void tok_add(int **tok_str, int *tok_len, int t)
1119 int len, *str;
1120 len = *tok_len;
1121 str = *tok_str;
1122 if ((len & 63) == 0) {
1123 str = realloc(str, (len + 64) * sizeof(int));
1124 if (!str)
1125 return;
1126 *tok_str = str;
1128 str[len++] = t;
1129 *tok_len = len;
1132 void tok_add2(int **tok_str, int *tok_len, int t, CValue *cv)
1134 int n, i;
1136 tok_add(tok_str, tok_len, t);
1137 n = tok_ext_size(t);
1138 for(i=0;i<n;i++)
1139 tok_add(tok_str, tok_len, cv->tab[i]);
1142 /* get a token from an integer array and increment pointer accordingly */
1143 int tok_get(int **tok_str, CValue *cv)
1145 int *p, t, n, i;
1147 p = *tok_str;
1148 t = *p++;
1149 n = tok_ext_size(t);
1150 for(i=0;i<n;i++)
1151 cv->tab[i] = *p++;
1152 *tok_str = p;
1153 return t;
1156 /* eval an expression for #if/#elif */
1157 int expr_preprocess(void)
1159 int *str, len, c, t;
1161 str = NULL;
1162 len = 0;
1163 while (1) {
1164 skip_spaces();
1165 if (ch == '\n')
1166 break;
1167 next(); /* do macro subst */
1168 if (tok == TOK_DEFINED) {
1169 next_nomacro();
1170 t = tok;
1171 if (t == '(')
1172 next_nomacro();
1173 c = sym_find1(&define_stack, tok) != 0;
1174 if (t == '(')
1175 next_nomacro();
1176 tok = TOK_CINT;
1177 tokc.i = c;
1178 } else if (tok >= TOK_IDENT) {
1179 /* if undefined macro */
1180 tok = TOK_CINT;
1181 tokc.i = 0;
1183 tok_add2(&str, &len, tok, &tokc);
1185 tok_add(&str, &len, -1); /* simulate end of file */
1186 tok_add(&str, &len, 0);
1187 /* now evaluate C constant expression */
1188 macro_ptr = str;
1189 next();
1190 c = expr_const();
1191 macro_ptr = NULL;
1192 free(str);
1193 return c != 0;
1196 #if defined(DEBUG)
1197 void tok_print(int *str)
1199 int t;
1200 CValue cval;
1202 while (1) {
1203 t = tok_get(&str, &cval);
1204 if (!t)
1205 break;
1206 printf(" %s", get_tok_str(t, &cval));
1208 printf("\n");
1210 #endif
1212 void preprocess(void)
1214 int size, i, c, v, t, *str, len;
1215 char buf[1024], *q, *p;
1216 char buf1[1024];
1217 FILE *f;
1218 Sym **ps, *first, *s;
1220 cinp();
1221 next_nomacro();
1222 redo:
1223 if (tok == TOK_DEFINE) {
1224 next_nomacro();
1225 v = tok;
1226 /* XXX: should check if same macro (ANSI) */
1227 first = NULL;
1228 t = MACRO_OBJ;
1229 /* '(' must be just after macro definition for MACRO_FUNC */
1230 if (ch == '(') {
1231 next_nomacro();
1232 next_nomacro();
1233 ps = &first;
1234 while (tok != ')') {
1235 if (tok == TOK_DOTS)
1236 tok = TOK___VA_ARGS__;
1237 s = sym_push1(&define_stack, tok | SYM_FIELD, 0, 0);
1238 *ps = s;
1239 ps = &s->next;
1240 next_nomacro();
1241 if (tok != ',')
1242 break;
1243 next_nomacro();
1245 t = MACRO_FUNC;
1247 str = NULL;
1248 len = 0;
1249 while (1) {
1250 skip_spaces();
1251 if (ch == '\n' || ch == -1)
1252 break;
1253 next_nomacro();
1254 tok_add2(&str, &len, tok, &tokc);
1256 tok_add(&str, &len, 0);
1257 #ifdef PP_DEBUG
1258 printf("define %s %d: ", get_tok_str(v, NULL), t);
1259 tok_print(str);
1260 #endif
1261 s = sym_push1(&define_stack, v, t, (int)str);
1262 s->next = first;
1263 } else if (tok == TOK_UNDEF) {
1264 next_nomacro();
1265 s = sym_find1(&define_stack, tok);
1266 /* undefine symbol by putting an invalid name */
1267 if (s)
1268 sym_undef(&define_stack, s);
1269 } else if (tok == TOK_INCLUDE) {
1270 skip_spaces();
1271 if (ch == '<') {
1272 c = '>';
1273 goto read_name;
1274 } else if (ch == '\"') {
1275 c = ch;
1276 read_name:
1277 minp();
1278 q = buf;
1279 while (ch != c && ch != '\n' && ch != -1) {
1280 if ((q - buf) < sizeof(buf) - 1)
1281 *q++ = ch;
1282 minp();
1284 *q = '\0';
1285 } else {
1286 next();
1287 if (tok != TOK_STR)
1288 error("#include syntax error");
1289 pstrcpy(buf, sizeof(buf), get_tok_str(tok, &tokc));
1290 c = '\"';
1292 /* eat all spaces and comments after include */
1293 /* XXX: slightly incorrect */
1294 while (ch1 != '\n' && ch1 != -1)
1295 inp();
1297 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
1298 error("memory full");
1299 if (c == '\"') {
1300 /* first search in current dir if "header.h" */
1301 size = 0;
1302 p = strrchr(filename, '/');
1303 if (p)
1304 size = p + 1 - filename;
1305 if (size > sizeof(buf1) - 1)
1306 size = sizeof(buf1) - 1;
1307 memcpy(buf1, filename, size);
1308 buf1[size] = '\0';
1309 pstrcat(buf1, sizeof(buf1), buf);
1310 f = fopen(buf1, "r");
1311 if (f)
1312 goto found;
1314 /* now search in standard include path */
1315 for(i=nb_include_paths - 1;i>=0;i--) {
1316 strcpy(buf1, include_paths[i]);
1317 strcat(buf1, "/");
1318 strcat(buf1, buf);
1319 f = fopen(buf1, "r");
1320 if (f)
1321 goto found;
1323 error("include file '%s' not found", buf1);
1324 f = NULL;
1325 found:
1326 /* push current file in stack */
1327 /* XXX: fix current line init */
1328 include_stack_ptr->file = file;
1329 include_stack_ptr->filename = filename;
1330 include_stack_ptr->line_num = line_num;
1331 include_stack_ptr++;
1332 file = f;
1333 filename = strdup(buf1);
1334 line_num = 1;
1335 /* add include file debug info */
1336 if (do_debug) {
1337 put_stabs(filename, N_BINCL, 0, 0, 0);
1339 } else if (tok == TOK_IFNDEF) {
1340 c = 1;
1341 goto do_ifdef;
1342 } else if (tok == TOK_IF) {
1343 c = expr_preprocess();
1344 goto do_if;
1345 } else if (tok == TOK_IFDEF) {
1346 c = 0;
1347 do_ifdef:
1348 next_nomacro();
1349 c = (sym_find1(&define_stack, tok) != 0) ^ c;
1350 do_if:
1351 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
1352 error("memory full");
1353 *ifdef_stack_ptr++ = c;
1354 goto test_skip;
1355 } else if (tok == TOK_ELSE) {
1356 if (ifdef_stack_ptr == ifdef_stack ||
1357 (ifdef_stack_ptr[-1] & 2))
1358 error("#else after #else");
1359 c = (ifdef_stack_ptr[-1] ^= 3);
1360 goto test_skip;
1361 } else if (tok == TOK_ELIF) {
1362 if (ifdef_stack_ptr == ifdef_stack ||
1363 ifdef_stack_ptr[-1] > 1)
1364 error("#elif after #else");
1365 c = expr_preprocess();
1366 ifdef_stack_ptr[-1] = c;
1367 test_skip:
1368 if (!(c & 1)) {
1369 preprocess_skip();
1370 goto redo;
1372 } else if (tok == TOK_ENDIF) {
1373 if (ifdef_stack_ptr == ifdef_stack)
1374 expect("#if");
1375 ifdef_stack_ptr--;
1376 } else if (tok == TOK_LINE) {
1377 next();
1378 if (tok != TOK_CINT)
1379 error("#line");
1380 line_num = tokc.i;
1381 skip_spaces();
1382 if (ch != '\n') {
1383 next();
1384 if (tok != TOK_STR)
1385 error("#line");
1386 /* XXX: potential memory leak */
1387 filename = strdup(get_tok_str(tok, &tokc));
1389 } else if (tok == TOK_ERROR) {
1390 error("#error");
1392 /* ignore other preprocess commands or #! for C scripts */
1393 while (ch != '\n' && ch != -1)
1394 cinp();
1397 /* read a number in base b */
1398 int getn(b)
1400 int n, t;
1401 n = 0;
1402 while (1) {
1403 if (ch >= 'a' && ch <= 'f')
1404 t = ch - 'a' + 10;
1405 else if (ch >= 'A' && ch <= 'F')
1406 t = ch - 'A' + 10;
1407 else if (isnum(ch))
1408 t = ch - '0';
1409 else
1410 break;
1411 if (t < 0 || t >= b)
1412 break;
1413 n = n * b + t;
1414 cinp();
1416 return n;
1419 /* read a character for string or char constant and eval escape codes */
1420 int getq()
1422 int c;
1424 c = ch;
1425 minp();
1426 if (c == '\\') {
1427 if (isnum(ch)) {
1428 /* at most three octal digits */
1429 c = ch - '0';
1430 minp();
1431 if (isnum(ch)) {
1432 c = c * 8 + ch - '0';
1433 minp();
1434 if (isnum(ch)) {
1435 c = c * 8 + ch - '0';
1436 minp();
1439 return c;
1440 } else if (ch == 'x') {
1441 minp();
1442 return getn(16);
1443 } else {
1444 if (ch == 'a')
1445 c = '\a';
1446 else if (ch == 'b')
1447 c = '\b';
1448 else if (ch == 'f')
1449 c = '\f';
1450 else if (ch == 'n')
1451 c = '\n';
1452 else if (ch == 'r')
1453 c = '\r';
1454 else if (ch == 't')
1455 c = '\t';
1456 else if (ch == 'v')
1457 c = '\v';
1458 else if (ch == 'e' && gnu_ext)
1459 c = 27;
1460 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
1461 c = ch;
1462 else
1463 error("invalid escaped char");
1464 minp();
1467 return c;
1470 /* we use 64 bit numbers */
1471 #define BN_SIZE 2
1473 /* bn = (bn << shift) | or_val */
1474 void bn_lshift(unsigned int *bn, int shift, int or_val)
1476 int i;
1477 unsigned int v;
1478 for(i=0;i<BN_SIZE;i++) {
1479 v = bn[i];
1480 bn[i] = (v << shift) | or_val;
1481 or_val = v >> (32 - shift);
1485 void bn_zero(unsigned int *bn)
1487 int i;
1488 for(i=0;i<BN_SIZE;i++) {
1489 bn[i] = 0;
1493 void parse_number(void)
1495 int b, t, shift, frac_bits, s, exp_val;
1496 char *q;
1497 unsigned int bn[BN_SIZE];
1498 double d;
1500 /* number */
1501 q = token_buf;
1502 t = ch;
1503 cinp();
1504 *q++ = t;
1505 b = 10;
1506 if (t == '.') {
1507 /* special dot handling */
1508 if (ch >= '0' && ch <= '9') {
1509 goto float_frac_parse;
1510 } else if (ch == '.') {
1511 cinp();
1512 if (ch != '.')
1513 expect("'.'");
1514 cinp();
1515 tok = TOK_DOTS;
1516 } else {
1517 /* dots */
1518 tok = t;
1520 return;
1521 } else if (t == '0') {
1522 if (ch == 'x' || ch == 'X') {
1523 q--;
1524 cinp();
1525 b = 16;
1526 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1527 q--;
1528 cinp();
1529 b = 2;
1532 /* parse all digits. cannot check octal numbers at this stage
1533 because of floating point constants */
1534 while (1) {
1535 if (ch >= 'a' && ch <= 'f')
1536 t = ch - 'a' + 10;
1537 else if (ch >= 'A' && ch <= 'F')
1538 t = ch - 'A' + 10;
1539 else if (isnum(ch))
1540 t = ch - '0';
1541 else
1542 break;
1543 if (t >= b)
1544 break;
1545 if (q >= token_buf + STRING_MAX_SIZE) {
1546 num_too_long:
1547 error("number too long");
1549 *q++ = ch;
1550 cinp();
1552 if (ch == '.' ||
1553 ((ch == 'e' || ch == 'E') && b == 10) ||
1554 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1555 if (b != 10) {
1556 /* NOTE: strtox should support that for hexa numbers, but
1557 non ISOC99 libcs do not support it, so we prefer to do
1558 it by hand */
1559 /* hexadecimal or binary floats */
1560 /* XXX: handle overflows */
1561 *q = '\0';
1562 if (b == 16)
1563 shift = 4;
1564 else
1565 shift = 2;
1566 bn_zero(bn);
1567 q = token_buf;
1568 while (1) {
1569 t = *q++;
1570 if (t == '\0') {
1571 break;
1572 } else if (t >= 'a') {
1573 t = t - 'a' + 10;
1574 } else if (t >= 'A') {
1575 t = t - 'A' + 10;
1576 } else {
1577 t = t - '0';
1579 bn_lshift(bn, shift, t);
1581 frac_bits = 0;
1582 if (ch == '.') {
1583 cinp();
1584 while (1) {
1585 t = ch;
1586 if (t >= 'a' && t <= 'f') {
1587 t = t - 'a' + 10;
1588 } else if (t >= 'A' && t <= 'F') {
1589 t = t - 'A' + 10;
1590 } else if (t >= '0' && t <= '9') {
1591 t = t - '0';
1592 } else {
1593 break;
1595 if (t >= b)
1596 error("invalid digit");
1597 bn_lshift(bn, shift, t);
1598 frac_bits += shift;
1599 cinp();
1602 if (ch != 'p' && ch != 'P')
1603 error("exponent expected");
1604 cinp();
1605 s = 1;
1606 exp_val = 0;
1607 if (ch == '+') {
1608 cinp();
1609 } else if (ch == '-') {
1610 s = -1;
1611 cinp();
1613 if (ch < '0' || ch > '9')
1614 error("exponent digits expected");
1615 while (ch >= '0' && ch <= '9') {
1616 exp_val = exp_val * 10 + ch - '0';
1617 cinp();
1619 exp_val = exp_val * s;
1621 /* now we can generate the number */
1622 /* XXX: should patch directly float number */
1623 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1624 d = ldexp(d, exp_val - frac_bits);
1625 t = toup(ch);
1626 if (t == 'F') {
1627 cinp();
1628 tok = TOK_CFLOAT;
1629 /* float : should handle overflow */
1630 tokc.f = (float)d;
1631 } else if (t == 'L') {
1632 cinp();
1633 tok = TOK_CLDOUBLE;
1634 /* XXX: not large enough */
1635 tokc.ld = (long double)d;
1636 } else {
1637 tok = TOK_CDOUBLE;
1638 tokc.d = d;
1640 } else {
1641 /* decimal floats */
1642 if (ch == '.') {
1643 if (q >= token_buf + STRING_MAX_SIZE)
1644 goto num_too_long;
1645 *q++ = ch;
1646 cinp();
1647 float_frac_parse:
1648 while (ch >= '0' && ch <= '9') {
1649 if (q >= token_buf + STRING_MAX_SIZE)
1650 goto num_too_long;
1651 *q++ = ch;
1652 cinp();
1655 if (ch == 'e' || ch == 'E') {
1656 if (q >= token_buf + STRING_MAX_SIZE)
1657 goto num_too_long;
1658 *q++ = ch;
1659 cinp();
1660 if (ch == '-' || ch == '+') {
1661 if (q >= token_buf + STRING_MAX_SIZE)
1662 goto num_too_long;
1663 *q++ = ch;
1664 cinp();
1666 if (ch < '0' || ch > '9')
1667 error("exponent digits expected");
1668 while (ch >= '0' && ch <= '9') {
1669 if (q >= token_buf + STRING_MAX_SIZE)
1670 goto num_too_long;
1671 *q++ = ch;
1672 cinp();
1675 *q = '\0';
1676 t = toup(ch);
1677 errno = 0;
1678 if (t == 'F') {
1679 cinp();
1680 tok = TOK_CFLOAT;
1681 tokc.f = strtof(token_buf, NULL);
1682 } else if (t == 'L') {
1683 cinp();
1684 tok = TOK_CLDOUBLE;
1685 tokc.ld = strtold(token_buf, NULL);
1686 } else {
1687 tok = TOK_CDOUBLE;
1688 tokc.d = strtod(token_buf, NULL);
1691 } else {
1692 unsigned long long n, n1;
1693 int lcount;
1695 /* integer number */
1696 *q = '\0';
1697 q = token_buf;
1698 if (b == 10 && *q == '0') {
1699 b = 8;
1700 q++;
1702 n = 0;
1703 while(1) {
1704 t = *q++;
1705 /* no need for checks except for base 10 / 8 errors */
1706 if (t == '\0') {
1707 break;
1708 } else if (t >= 'a') {
1709 t = t - 'a' + 10;
1710 } else if (t >= 'A') {
1711 t = t - 'A' + 10;
1712 } else {
1713 t = t - '0';
1714 if (t >= b)
1715 error("invalid digit");
1717 n1 = n;
1718 n = n * b + t;
1719 /* detect overflow */
1720 if (n < n1)
1721 error("integer constant overflow");
1724 /* XXX: not exactly ANSI compliant */
1725 if ((n & 0xffffffff00000000LL) != 0) {
1726 if ((n >> 63) != 0)
1727 tok = TOK_CULLONG;
1728 else
1729 tok = TOK_CLLONG;
1730 } else if (n > 0x7fffffff) {
1731 tok = TOK_CUINT;
1732 } else {
1733 tok = TOK_CINT;
1735 lcount = 0;
1736 for(;;) {
1737 t = toup(ch);
1738 if (t == 'L') {
1739 if (lcount >= 2)
1740 error("three 'l' in integer constant");
1741 lcount++;
1742 if (lcount == 2) {
1743 if (tok == TOK_CINT)
1744 tok = TOK_CLLONG;
1745 else if (tok == TOK_CUINT)
1746 tok = TOK_CULLONG;
1748 cinp();
1749 } else if (t == 'U') {
1750 if (tok == TOK_CINT)
1751 tok = TOK_CUINT;
1752 else if (tok == TOK_CLLONG)
1753 tok = TOK_CULLONG;
1754 cinp();
1755 } else {
1756 break;
1759 if (tok == TOK_CINT || tok == TOK_CUINT)
1760 tokc.ui = n;
1761 else
1762 tokc.ull = n;
1767 /* return next token without macro substitution */
1768 void next_nomacro1(void)
1770 int b;
1771 char *q;
1772 TokenSym *ts;
1774 /* skip spaces */
1775 while(1) {
1776 while (ch == '\n') {
1777 cinp();
1778 while (ch == ' ' || ch == 9)
1779 cinp();
1780 if (ch == '#') {
1781 /* preprocessor command if # at start of line after
1782 spaces */
1783 preprocess();
1786 if (ch != ' ' && ch != '\t' && ch != '\f')
1787 break;
1788 cinp();
1790 if (isid(ch)) {
1791 q = token_buf;
1792 *q++ = ch;
1793 cinp();
1794 if (q[-1] == 'L') {
1795 if (ch == '\'') {
1796 tok = TOK_LCHAR;
1797 goto char_const;
1799 if (ch == '\"') {
1800 tok = TOK_LSTR;
1801 goto str_const;
1804 while (isid(ch) || isnum(ch)) {
1805 if (q >= token_buf + STRING_MAX_SIZE)
1806 error("ident too long");
1807 *q++ = ch;
1808 cinp();
1810 *q = '\0';
1811 ts = tok_alloc(token_buf, q - token_buf);
1812 tok = ts->tok;
1813 } else if (isnum(ch) || ch == '.') {
1814 parse_number();
1815 } else if (ch == '\'') {
1816 tok = TOK_CCHAR;
1817 char_const:
1818 minp();
1819 tokc.i = getq();
1820 if (ch != '\'')
1821 expect("\'");
1822 minp();
1823 } else if (ch == '\"') {
1824 tok = TOK_STR;
1825 str_const:
1826 minp();
1827 q = token_buf;
1828 while (ch != '\"') {
1829 b = getq();
1830 if (ch == -1)
1831 error("unterminated string");
1832 if (q >= token_buf + STRING_MAX_SIZE)
1833 error("string too long");
1834 *q++ = b;
1836 *q = '\0';
1837 tokc.ts = tok_alloc(token_buf, q - token_buf);
1838 minp();
1839 } else {
1840 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
1841 /* two chars */
1842 tok = ch;
1843 cinp();
1844 while (*q) {
1845 if (*q == tok && q[1] == ch) {
1846 cinp();
1847 tok = q[2] & 0xff;
1848 /* three chars tests */
1849 if (tok == TOK_SHL || tok == TOK_SAR) {
1850 if (ch == '=') {
1851 tok = tok | 0x80;
1852 cinp();
1854 } else if (tok == TOK_DOTS) {
1855 if (ch != '.')
1856 error("parse error");
1857 cinp();
1859 return;
1861 q = q + 3;
1863 /* single char substitutions */
1864 if (tok == '<')
1865 tok = TOK_LT;
1866 else if (tok == '>')
1867 tok = TOK_GT;
1871 /* return next token without macro substitution. Can read input from
1872 macro_ptr buffer */
1873 void next_nomacro()
1875 if (macro_ptr) {
1876 tok = *macro_ptr;
1877 if (tok)
1878 tok = tok_get(&macro_ptr, &tokc);
1879 } else {
1880 next_nomacro1();
1884 /* substitute args in macro_str and return allocated string */
1885 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
1887 int *st, last_tok, t, notfirst, *str, len;
1888 Sym *s;
1889 TokenSym *ts;
1890 CValue cval;
1892 str = NULL;
1893 len = 0;
1894 last_tok = 0;
1895 while(1) {
1896 t = tok_get(&macro_str, &cval);
1897 if (!t)
1898 break;
1899 if (t == '#') {
1900 /* stringize */
1901 t = tok_get(&macro_str, &cval);
1902 if (!t)
1903 break;
1904 s = sym_find2(args, t);
1905 if (s) {
1906 token_buf[0] = '\0';
1907 st = (int *)s->c;
1908 notfirst = 0;
1909 while (*st) {
1910 if (notfirst)
1911 pstrcat(token_buf, sizeof(token_buf), " ");
1912 t = tok_get(&st, &cval);
1913 pstrcat(token_buf, sizeof(token_buf), get_tok_str(t, &cval));
1914 notfirst = 1;
1916 #ifdef PP_DEBUG
1917 printf("stringize: %s\n", token_buf);
1918 #endif
1919 /* add string */
1920 ts = tok_alloc(token_buf, 0);
1921 cval.ts = ts;
1922 tok_add2(&str, &len, TOK_STR, &cval);
1923 } else {
1924 tok_add2(&str, &len, t, &cval);
1926 } else if (t >= TOK_IDENT) {
1927 s = sym_find2(args, t);
1928 if (s) {
1929 st = (int *)s->c;
1930 /* if '##' is present before or after , no arg substitution */
1931 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
1932 while (*st)
1933 tok_add(&str, &len, *st++);
1934 } else {
1935 macro_subst(&str, &len, nested_list, st);
1937 } else {
1938 tok_add(&str, &len, t);
1940 } else {
1941 tok_add2(&str, &len, t, &cval);
1943 last_tok = t;
1945 tok_add(&str, &len, 0);
1946 return str;
1949 /* handle the '##' operator */
1950 int *macro_twosharps(int *macro_str)
1952 TokenSym *ts;
1953 int *macro_str1, macro_str1_len, *macro_ptr1;
1954 int t;
1955 char *p;
1956 CValue cval;
1958 macro_str1 = NULL;
1959 macro_str1_len = 0;
1960 tok = 0;
1961 while (1) {
1962 next_nomacro();
1963 if (tok == 0)
1964 break;
1965 while (*macro_ptr == TOK_TWOSHARPS) {
1966 macro_ptr++;
1967 macro_ptr1 = macro_ptr;
1968 t = *macro_ptr;
1969 if (t) {
1970 t = tok_get(&macro_ptr, &cval);
1971 /* XXX: we handle only most common cases:
1972 ident + ident or ident + number */
1973 if (tok >= TOK_IDENT &&
1974 (t >= TOK_IDENT || t == TOK_CINT)) {
1975 p = get_tok_str(tok, &tokc);
1976 pstrcpy(token_buf, sizeof(token_buf), p);
1977 p = get_tok_str(t, &cval);
1978 pstrcat(token_buf, sizeof(token_buf), p);
1979 ts = tok_alloc(token_buf, 0);
1980 tok = ts->tok; /* modify current token */
1981 } else {
1982 /* cannot merge tokens: skip '##' */
1983 macro_ptr = macro_ptr1;
1984 break;
1988 tok_add2(&macro_str1, &macro_str1_len, tok, &tokc);
1990 tok_add(&macro_str1, &macro_str1_len, 0);
1991 return macro_str1;
1996 /* do macro substitution of macro_str and add result to
1997 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1998 substituted. 'nested_list' is the list of all macros we got inside
1999 to avoid recursing. */
2000 void macro_subst(int **tok_str, int *tok_len,
2001 Sym **nested_list, int *macro_str)
2003 Sym *s, *args, *sa, *sa1;
2004 int *str, parlevel, len, *mstr, t, *saved_macro_ptr;
2005 int mstr_allocated, *macro_str1;
2006 CValue cval;
2008 saved_macro_ptr = macro_ptr;
2009 macro_ptr = macro_str;
2010 macro_str1 = NULL;
2011 if (macro_str) {
2012 /* first scan for '##' operator handling */
2013 macro_str1 = macro_twosharps(macro_str);
2014 macro_ptr = macro_str1;
2017 while (1) {
2018 next_nomacro();
2019 if (tok == 0)
2020 break;
2021 /* special macros */
2022 if (tok == TOK___LINE__) {
2023 cval.i = line_num;
2024 tok_add2(tok_str, tok_len, TOK_CINT, &cval);
2025 } else if (tok == TOK___FILE__) {
2026 cval.ts = tok_alloc(filename, 0);
2027 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2028 } else if (tok == TOK___DATE__) {
2029 cval.ts = tok_alloc("Jan 1 1970", 0);
2030 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2031 } else if (tok == TOK___TIME__) {
2032 cval.ts = tok_alloc("00:00:00", 0);
2033 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2034 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
2035 /* if symbol is a macro, prepare substitution */
2036 /* if nested substitution, do nothing */
2037 if (sym_find2(*nested_list, tok))
2038 goto no_subst;
2039 mstr = (int *)s->c;
2040 mstr_allocated = 0;
2041 if (s->t == MACRO_FUNC) {
2042 /* NOTE: we do not use next_nomacro to avoid eating the
2043 next token. XXX: find better solution */
2044 if (macro_ptr) {
2045 t = *macro_ptr;
2046 } else {
2047 while (ch == ' ' || ch == '\t' || ch == '\n')
2048 cinp();
2049 t = ch;
2051 if (t != '(') /* no macro subst */
2052 goto no_subst;
2054 /* argument macro */
2055 next_nomacro();
2056 next_nomacro();
2057 args = NULL;
2058 sa = s->next;
2059 while (tok != ')' && sa) {
2060 len = 0;
2061 str = NULL;
2062 parlevel = 0;
2063 while ((parlevel > 0 ||
2064 (tok != ')' &&
2065 (tok != ',' ||
2066 sa->v == (TOK___VA_ARGS__ | SYM_FIELD)))) &&
2067 tok != -1) {
2068 if (tok == '(')
2069 parlevel++;
2070 else if (tok == ')')
2071 parlevel--;
2072 tok_add2(&str, &len, tok, &tokc);
2073 next_nomacro();
2075 tok_add(&str, &len, 0);
2076 sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
2077 if (tok != ',')
2078 break;
2079 next_nomacro();
2080 sa = sa->next;
2082 if (tok != ')')
2083 expect(")");
2084 /* now subst each arg */
2085 mstr = macro_arg_subst(nested_list, mstr, args);
2086 /* free memory */
2087 sa = args;
2088 while (sa) {
2089 sa1 = sa->prev;
2090 free((int *)sa->c);
2091 free(sa);
2092 sa = sa1;
2094 mstr_allocated = 1;
2096 sym_push2(nested_list, s->v, 0, 0);
2097 macro_subst(tok_str, tok_len, nested_list, mstr);
2098 /* pop nested defined symbol */
2099 sa1 = *nested_list;
2100 *nested_list = sa1->prev;
2101 free(sa1);
2102 if (mstr_allocated)
2103 free(mstr);
2104 } else {
2105 no_subst:
2106 /* no need to add if reading input stream */
2107 if (!macro_str)
2108 return;
2109 tok_add2(tok_str, tok_len, tok, &tokc);
2111 /* only replace one macro while parsing input stream */
2112 if (!macro_str)
2113 return;
2115 macro_ptr = saved_macro_ptr;
2116 if (macro_str1)
2117 free(macro_str1);
2120 /* return next token with macro substitution */
2121 void next(void)
2123 int len, *ptr;
2124 Sym *nested_list;
2126 /* special 'ungettok' case for label parsing */
2127 if (tok1) {
2128 tok = tok1;
2129 tokc = tok1c;
2130 tok1 = 0;
2131 } else {
2132 redo:
2133 if (!macro_ptr) {
2134 /* if not reading from macro substuted string, then try to substitute */
2135 len = 0;
2136 ptr = NULL;
2137 nested_list = NULL;
2138 macro_subst(&ptr, &len, &nested_list, NULL);
2139 if (ptr) {
2140 tok_add(&ptr, &len, 0);
2141 macro_ptr = ptr;
2142 macro_ptr_allocated = ptr;
2143 goto redo;
2145 if (tok == 0)
2146 goto redo;
2147 } else {
2148 next_nomacro();
2149 if (tok == 0) {
2150 /* end of macro string: free it */
2151 free(macro_ptr_allocated);
2152 macro_ptr = NULL;
2153 goto redo;
2157 #if defined(DEBUG)
2158 printf("token = %s\n", get_tok_str(tok, tokc));
2159 #endif
2162 void swap(int *p, int *q)
2164 int t;
2165 t = *p;
2166 *p = *q;
2167 *q = t;
2170 void vsetc(int t, int r, CValue *vc)
2172 if (vtop >= vstack + VSTACK_SIZE)
2173 error("memory full");
2174 /* cannot let cpu flags if other instruction are generated */
2175 /* XXX: VT_JMP test too ? */
2176 if ((vtop->r & VT_VALMASK) == VT_CMP)
2177 gv(RC_INT);
2178 vtop++;
2179 vtop->t = t;
2180 vtop->r = r;
2181 vtop->r2 = VT_CONST;
2182 vtop->c = *vc;
2185 /* push integer constant */
2186 void vpushi(int v)
2188 CValue cval;
2189 cval.i = v;
2190 vsetc(VT_INT, VT_CONST, &cval);
2193 void vset(int t, int r, int v)
2195 CValue cval;
2197 cval.i = v;
2198 vsetc(t, r, &cval);
2201 void vswap(void)
2203 SValue tmp;
2205 tmp = vtop[0];
2206 vtop[0] = vtop[-1];
2207 vtop[-1] = tmp;
2210 void vpushv(SValue *v)
2212 if (vtop >= vstack + VSTACK_SIZE)
2213 error("memory full");
2214 vtop++;
2215 *vtop = *v;
2218 void vdup(void)
2220 vpushv(vtop);
2223 /* save r to the memory stack, and mark it as being free */
2224 void save_reg(int r)
2226 int l, i, saved, t, size, align;
2227 SValue *p, sv;
2229 /* modify all stack values */
2230 saved = 0;
2231 l = 0;
2232 for(p=vstack;p<=vtop;p++) {
2233 i = p->r & VT_VALMASK;
2234 if ((p->r & VT_VALMASK) == r ||
2235 (p->r2 & VT_VALMASK) == r) {
2236 /* must save value on stack if not already done */
2237 if (!saved) {
2238 /* store register in the stack */
2239 t = p->t;
2240 if (!is_float(t) && (t & VT_BTYPE) != VT_LLONG)
2241 t = VT_INT;
2242 size = type_size(t, &align);
2243 loc = (loc - size) & -align;
2244 sv.t = t;
2245 sv.r = VT_LOCAL | VT_LVAL;
2246 sv.c.ul = loc;
2247 store(r, &sv);
2248 /* XXX: x86 specific: need to pop fp register ST0 if saved */
2249 if (r == REG_ST0) {
2250 o(0xd9dd); /* fstp %st(1) */
2252 /* special long long case */
2253 if ((p->t & VT_BTYPE) == VT_LLONG) {
2254 sv.c.ul += 4;
2255 store(p->r2, &sv);
2257 l = loc;
2258 saved = 1;
2260 /* mark that stack entry as being saved on the stack */
2261 if (p->r & VT_LVAL)
2262 t = VT_LLOCAL;
2263 else
2264 t = VT_LOCAL;
2265 p->r = VT_LVAL | t;
2266 p->r2 = VT_CONST;
2267 p->c.ul = l;
2272 /* find a free register of class 'rc'. If none, save one register */
2273 int get_reg(int rc)
2275 int r;
2276 SValue *p;
2278 /* find a free register */
2279 for(r=0;r<NB_REGS;r++) {
2280 if (reg_classes[r] & rc) {
2281 for(p=vstack;p<=vtop;p++) {
2282 if ((p->r & VT_VALMASK) == r ||
2283 (p->r2 & VT_VALMASK) == r)
2284 goto notfound;
2286 return r;
2288 notfound: ;
2291 /* no register left : free the first one on the stack (VERY
2292 IMPORTANT to start from the bottom to ensure that we don't
2293 spill registers used in gen_opi()) */
2294 for(p=vstack;p<=vtop;p++) {
2295 r = p->r & VT_VALMASK;
2296 if (r < VT_CONST && (reg_classes[r] & rc)) {
2297 save_reg(r);
2298 break;
2301 return r;
2304 void save_regs(void)
2306 int r;
2307 SValue *p;
2309 for(p=vstack;p<=vtop;p++) {
2310 r = p->r & VT_VALMASK;
2311 if (r < VT_CONST) {
2312 save_reg(r);
2317 /* move register 's' to 'r', and flush previous value of r to memory
2318 if needed */
2319 void move_reg(int r, int s)
2321 SValue sv;
2323 if (r != s) {
2324 save_reg(r);
2325 sv.t = VT_INT;
2326 sv.r = s;
2327 sv.c.ul = 0;
2328 load(r, &sv);
2332 /* store vtop a register belonging to class 'rc'. lvalues are
2333 converted to values. Cannot be used if cannot be converted to
2334 register value (such as structures). */
2335 int gv(int rc)
2337 int r, r2, rc2, bit_pos, bit_size, size, align, i, data_offset;
2338 unsigned long long ll;
2340 /* NOTE: get_reg can modify vstack[] */
2341 if (vtop->t & VT_BITFIELD) {
2342 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
2343 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2344 /* remove bit field info to avoid loops */
2345 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2346 /* generate shifts */
2347 vpushi(32 - (bit_pos + bit_size));
2348 gen_op(TOK_SHL);
2349 vpushi(32 - bit_size);
2350 /* NOTE: transformed to SHR if unsigned */
2351 gen_op(TOK_SAR);
2352 r = gv(rc);
2353 } else {
2354 if (is_float(vtop->t) &&
2355 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2356 /* CPUs usually cannot use float constants, so we store them
2357 generically in data segment */
2358 size = type_size(vtop->t, &align);
2359 data_offset = (int)data_section->data_ptr;
2360 data_offset = (data_offset + align - 1) & -align;
2361 /* XXX: not portable yet */
2362 size = size >> 2;
2363 for(i=0;i<size;i++)
2364 ((int *)data_offset)[i] = vtop->c.tab[i];
2365 vtop->r |= VT_LVAL;
2366 vtop->c.ul = data_offset;
2367 data_offset += size << 2;
2368 data_section->data_ptr = (unsigned char *)data_offset;
2370 r = vtop->r & VT_VALMASK;
2371 /* need to reload if:
2372 - constant
2373 - lvalue (need to dereference pointer)
2374 - already a register, but not in the right class */
2375 if (r >= VT_CONST ||
2376 (vtop->r & VT_LVAL) ||
2377 !(reg_classes[r] & rc) ||
2378 ((vtop->t & VT_BTYPE) == VT_LLONG &&
2379 !(reg_classes[vtop->r2] & rc))) {
2380 r = get_reg(rc);
2381 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
2382 /* two register type load : expand to two words
2383 temporarily */
2384 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2385 /* load constant */
2386 ll = vtop->c.ull;
2387 vtop->c.ui = ll; /* first word */
2388 load(r, vtop);
2389 vtop->r = r; /* save register value */
2390 vpushi(ll >> 32); /* second word */
2391 } else if (r >= VT_CONST ||
2392 (vtop->r & VT_LVAL)) {
2393 /* load from memory */
2394 load(r, vtop);
2395 vdup();
2396 vtop[-1].r = r; /* save register value */
2397 /* increment pointer to get second word */
2398 vtop->t = VT_INT;
2399 vtop->r &= ~VT_LVAL;
2400 vpushi(4);
2401 gen_op('+');
2402 vtop->r |= VT_LVAL;
2403 } else {
2404 /* move registers */
2405 load(r, vtop);
2406 vdup();
2407 vtop[-1].r = r; /* save register value */
2408 vtop->r = vtop[-1].r2;
2410 /* allocate second register */
2411 rc2 = RC_INT;
2412 if (rc == RC_IRET)
2413 rc2 = RC_LRET;
2414 r2 = get_reg(rc2);
2415 load(r2, vtop);
2416 vpop();
2417 /* write second register */
2418 vtop->r2 = r2;
2419 } else {
2420 /* one register type load */
2421 load(r, vtop);
2424 vtop->r = r;
2426 return r;
2429 /* expand long long on stack in two int registers */
2430 void lexpand(void)
2432 int u;
2434 u = vtop->t & VT_UNSIGNED;
2435 gv(RC_INT);
2436 vdup();
2437 vtop[0].r = vtop[-1].r2;
2438 vtop[0].r2 = VT_CONST;
2439 vtop[-1].r2 = VT_CONST;
2440 vtop[0].t = VT_INT | u;
2441 vtop[-1].t = VT_INT | u;
2444 /* build a long long from two ints */
2445 void lbuild(int t)
2447 vswap();
2448 gv(RC_INT);
2449 vswap();
2450 gv(RC_INT);
2451 vtop[-1].r2 = vtop[0].r;
2452 vtop[-1].t = t;
2453 vpop();
2456 /* rotate n first stack elements to the bottom */
2457 void vrotb(int n)
2459 int i;
2460 SValue tmp;
2462 tmp = vtop[-n + 1];
2463 for(i=-n+1;i!=0;i++)
2464 vtop[i] = vtop[i+1];
2465 vtop[0] = tmp;
2468 /* pop stack value */
2469 void vpop(void)
2471 /* for x86, we need to pop the FP stack */
2472 if ((vtop->r & VT_VALMASK) == REG_ST0) {
2473 o(0xd9dd); /* fstp %st(1) */
2475 vtop--;
2478 /* convert stack entry to register and duplicate its value in another
2479 register */
2480 void gv_dup(void)
2482 int rc, t, r, r1;
2483 SValue sv;
2485 t = vtop->t;
2486 if ((t & VT_BTYPE) == VT_LLONG) {
2487 lexpand();
2488 gv_dup();
2489 vswap();
2490 vrotb(3);
2491 gv_dup();
2492 vrotb(4);
2493 /* stack: H L L1 H1 */
2494 lbuild(t);
2495 vrotb(3);
2496 vrotb(3);
2497 vswap();
2498 lbuild(t);
2499 vswap();
2500 } else {
2501 /* duplicate value */
2502 rc = RC_INT;
2503 sv.t = VT_INT;
2504 if (is_float(t)) {
2505 rc = RC_FLOAT;
2506 sv.t = t;
2508 r = gv(rc);
2509 r1 = get_reg(rc);
2510 sv.r = r;
2511 sv.c.ul = 0;
2512 load(r1, &sv); /* move r to r1 */
2513 vdup();
2514 /* duplicates value */
2515 vtop->r = r1;
2519 /* generate CPU independent (unsigned) long long operations */
2520 void gen_opl(int op)
2522 int t, a, b, op1, c, i;
2523 void *func;
2524 GFuncContext gf;
2525 SValue tmp;
2527 switch(op) {
2528 case '/':
2529 case TOK_PDIV:
2530 func = __divll;
2531 goto gen_func;
2532 case TOK_UDIV:
2533 func = __divull;
2534 goto gen_func;
2535 case '%':
2536 func = __modll;
2537 goto gen_func;
2538 case TOK_UMOD:
2539 func = __modull;
2540 gen_func:
2541 /* call generic long long function */
2542 gfunc_start(&gf);
2543 gfunc_param(&gf);
2544 gfunc_param(&gf);
2545 vpushi((int)func);
2546 gfunc_call(&gf);
2547 vpushi(0);
2548 vtop->r = REG_IRET;
2549 vtop->r2 = REG_LRET;
2550 break;
2551 case '^':
2552 case '&':
2553 case '|':
2554 case '*':
2555 case '+':
2556 case '-':
2557 t = vtop->t;
2558 vswap();
2559 lexpand();
2560 vrotb(3);
2561 lexpand();
2562 /* stack: L1 H1 L2 H2 */
2563 tmp = vtop[0];
2564 vtop[0] = vtop[-3];
2565 vtop[-3] = tmp;
2566 tmp = vtop[-2];
2567 vtop[-2] = vtop[-3];
2568 vtop[-3] = tmp;
2569 vswap();
2570 /* stack: H1 H2 L1 L2 */
2571 if (op == '*') {
2572 vpushv(vtop - 1);
2573 vpushv(vtop - 1);
2574 gen_op(TOK_UMULL);
2575 lexpand();
2576 /* stack: H1 H2 L1 L2 ML MH */
2577 for(i=0;i<4;i++)
2578 vrotb(6);
2579 /* stack: ML MH H1 H2 L1 L2 */
2580 tmp = vtop[0];
2581 vtop[0] = vtop[-2];
2582 vtop[-2] = tmp;
2583 /* stack: ML MH H1 L2 H2 L1 */
2584 gen_op('*');
2585 vrotb(3);
2586 vrotb(3);
2587 gen_op('*');
2588 /* stack: ML MH M1 M2 */
2589 gen_op('+');
2590 gen_op('+');
2591 } else if (op == '+' || op == '-') {
2592 /* XXX: add non carry method too (for MIPS ?) */
2593 if (op == '+')
2594 op1 = TOK_ADDC1;
2595 else
2596 op1 = TOK_SUBC1;
2597 gen_op(op1);
2598 /* stack: H1 H2 (L1 op L2) */
2599 vrotb(3);
2600 vrotb(3);
2601 gen_op(op1 + 1); /* TOK_xxxC2 */
2602 } else {
2603 gen_op(op);
2604 /* stack: H1 H2 (L1 op L2) */
2605 vrotb(3);
2606 vrotb(3);
2607 /* stack: (L1 op L2) H1 H2 */
2608 gen_op(op);
2609 /* stack: (L1 op L2) (H1 op H2) */
2611 /* stack: L H */
2612 lbuild(t);
2613 break;
2614 case TOK_SAR:
2615 case TOK_SHR:
2616 case TOK_SHL:
2617 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
2618 t = vtop[-1].t;
2619 vswap();
2620 lexpand();
2621 vrotb(3);
2622 /* stack: L H shift */
2623 c = (int)vtop->c.i;
2624 /* constant: simpler */
2625 /* NOTE: all comments are for SHL. the other cases are
2626 done by swaping words */
2627 vpop();
2628 if (op != TOK_SHL)
2629 vswap();
2630 if (c >= 32) {
2631 /* stack: L H */
2632 vpop();
2633 if (c > 32) {
2634 vpushi(c - 32);
2635 gen_op(op);
2637 if (op != TOK_SAR) {
2638 vpushi(0);
2639 } else {
2640 gv_dup();
2641 vpushi(31);
2642 gen_op(TOK_SAR);
2644 vswap();
2645 } else {
2646 vswap();
2647 gv_dup();
2648 /* stack: H L L */
2649 vpushi(c);
2650 gen_op(op);
2651 vswap();
2652 vpushi(32 - c);
2653 if (op == TOK_SHL)
2654 gen_op(TOK_SHR);
2655 else
2656 gen_op(TOK_SHL);
2657 vrotb(3);
2658 /* stack: L L H */
2659 vpushi(c);
2660 gen_op(op);
2661 gen_op('|');
2663 if (op != TOK_SHL)
2664 vswap();
2665 lbuild(t);
2666 } else {
2667 /* XXX: should provide a faster fallback on x86 ? */
2668 switch(op) {
2669 case TOK_SAR:
2670 func = __sardi3;
2671 goto gen_func;
2672 case TOK_SHR:
2673 func = __shrdi3;
2674 goto gen_func;
2675 case TOK_SHL:
2676 func = __shldi3;
2677 goto gen_func;
2680 break;
2681 default:
2682 /* compare operations */
2683 t = vtop->t;
2684 vswap();
2685 lexpand();
2686 vrotb(3);
2687 lexpand();
2688 /* stack: L1 H1 L2 H2 */
2689 tmp = vtop[-1];
2690 vtop[-1] = vtop[-2];
2691 vtop[-2] = tmp;
2692 /* stack: L1 L2 H1 H2 */
2693 /* compare high */
2694 op1 = op;
2695 /* when values are equal, we need to compare low words. since
2696 the jump is inverted, we invert the test too. */
2697 if (op1 == TOK_LT)
2698 op1 = TOK_LE;
2699 else if (op1 == TOK_GT)
2700 op1 = TOK_GE;
2701 else if (op1 == TOK_ULT)
2702 op1 = TOK_ULE;
2703 else if (op1 == TOK_UGT)
2704 op1 = TOK_UGE;
2705 a = 0;
2706 b = 0;
2707 gen_op(op1);
2708 if (op1 != TOK_NE) {
2709 a = gtst(1, 0);
2711 if (op != TOK_EQ) {
2712 /* generate non equal test */
2713 /* XXX: NOT PORTABLE yet */
2714 if (a == 0)
2715 b = gtst(0, 0);
2716 else
2717 b = psym(0x850f, 0);
2719 /* compare low */
2720 gen_op(op);
2721 a = gtst(1, a);
2722 gsym(b);
2723 vset(VT_INT, VT_JMPI, a);
2724 break;
2728 /* handle constant optimizations and various machine independant opt */
2729 void gen_opc(int op)
2731 int fc, c1, c2, n;
2732 SValue *v1, *v2;
2734 v1 = vtop - 1;
2735 v2 = vtop;
2736 /* currently, we cannot do computations with forward symbols */
2737 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2738 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2739 if (c1 && c2) {
2740 fc = v2->c.i;
2741 switch(op) {
2742 case '+': v1->c.i += fc; break;
2743 case '-': v1->c.i -= fc; break;
2744 case '&': v1->c.i &= fc; break;
2745 case '^': v1->c.i ^= fc; break;
2746 case '|': v1->c.i |= fc; break;
2747 case '*': v1->c.i *= fc; break;
2748 case TOK_PDIV:
2749 case '/': v1->c.i /= fc; break; /* XXX: zero case ? */
2750 case '%': v1->c.i %= fc; break; /* XXX: zero case ? */
2751 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break; /* XXX: zero case ? */
2752 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break; /* XXX: zero case ? */
2753 case TOK_SHL: v1->c.i <<= fc; break;
2754 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
2755 case TOK_SAR: v1->c.i >>= fc; break;
2756 /* tests */
2757 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
2758 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
2759 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
2760 case TOK_NE: v1->c.i = v1->c.i != fc; break;
2761 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
2762 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
2763 case TOK_LT: v1->c.i = v1->c.i < fc; break;
2764 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
2765 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
2766 case TOK_GT: v1->c.i = v1->c.i > fc; break;
2767 /* logical */
2768 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
2769 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
2770 default:
2771 goto general_case;
2773 vtop--;
2774 } else {
2775 /* if commutative ops, put c2 as constant */
2776 if (c1 && (op == '+' || op == '&' || op == '^' ||
2777 op == '|' || op == '*')) {
2778 vswap();
2779 swap(&c1, &c2);
2781 fc = vtop->c.i;
2782 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
2783 op == TOK_PDIV) &&
2784 fc == 1) ||
2785 ((op == '+' || op == '-' || op == '|' || op == '^' ||
2786 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
2787 fc == 0) ||
2788 (op == '&' &&
2789 fc == -1))) {
2790 /* nothing to do */
2791 vtop--;
2792 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
2793 /* try to use shifts instead of muls or divs */
2794 if (fc > 0 && (fc & (fc - 1)) == 0) {
2795 n = -1;
2796 while (fc) {
2797 fc >>= 1;
2798 n++;
2800 vtop->c.i = n;
2801 if (op == '*')
2802 op = TOK_SHL;
2803 else if (op == TOK_PDIV)
2804 op = TOK_SAR;
2805 else
2806 op = TOK_SHR;
2808 goto general_case;
2809 } else {
2810 general_case:
2811 /* call low level op generator */
2812 /* XXX: remove explicit registers */
2813 gen_opi(op);
2818 int pointed_size(int t)
2820 return type_size(pointed_type(t), &t);
2823 #if 0
2824 void check_pointer_types(SValue *p1, SValue *p2)
2826 char buf1[256], buf2[256];
2827 int t1, t2;
2828 t1 = p1->t;
2829 t2 = p2->t;
2830 if (!is_compatible_types(t1, t2)) {
2831 type_to_str(buf1, sizeof(buf1), t1, NULL);
2832 type_to_str(buf2, sizeof(buf2), t2, NULL);
2833 error("incompatible pointers '%s' and '%s'", buf1, buf2);
2836 #endif
2838 /* generic gen_op: handles types problems */
2839 void gen_op(int op)
2841 int u, t1, t2, bt1, bt2, t;
2843 t1 = vtop[-1].t;
2844 t2 = vtop[0].t;
2845 bt1 = t1 & VT_BTYPE;
2846 bt2 = t2 & VT_BTYPE;
2848 if (bt1 == VT_PTR || bt2 == VT_PTR) {
2849 /* at least one operand is a pointer */
2850 /* relationnal op: must be both pointers */
2851 if (op >= TOK_ULT && op <= TOK_GT) {
2852 // check_pointer_types(vtop, vtop - 1);
2853 /* pointers are handled are unsigned */
2854 t = VT_INT | VT_UNSIGNED;
2855 goto std_op;
2857 /* if both pointers, then it must be the '-' op */
2858 if ((t1 & VT_BTYPE) == VT_PTR &&
2859 (t2 & VT_BTYPE) == VT_PTR) {
2860 if (op != '-')
2861 error("cannot use pointers here");
2862 // check_pointer_types(vtop - 1, vtop);
2863 /* XXX: check that types are compatible */
2864 u = pointed_size(t1);
2865 gen_opc(op);
2866 /* set to integer type */
2867 vtop->t = VT_INT;
2868 vpushi(u);
2869 gen_op(TOK_PDIV);
2870 } else {
2871 /* exactly one pointer : must be '+' or '-'. */
2872 if (op != '-' && op != '+')
2873 error("cannot use pointers here");
2874 /* Put pointer as first operand */
2875 if ((t2 & VT_BTYPE) == VT_PTR) {
2876 vswap();
2877 swap(&t1, &t2);
2879 /* XXX: cast to int ? (long long case) */
2880 vpushi(pointed_size(vtop[-1].t));
2881 gen_op('*');
2882 if (do_bounds_check) {
2883 /* if bounded pointers, we generate a special code to test bounds */
2884 if (op == '-') {
2885 vpushi(0);
2886 vswap();
2887 gen_op('-');
2889 gen_bounded_ptr_add();
2890 } else {
2891 gen_opc(op);
2893 /* put again type if gen_opc() swaped operands */
2894 vtop->t = t1;
2896 } else if (is_float(bt1) || is_float(bt2)) {
2897 /* compute bigger type and do implicit casts */
2898 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
2899 t = VT_LDOUBLE;
2900 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
2901 t = VT_DOUBLE;
2902 } else {
2903 t = VT_FLOAT;
2905 /* floats can only be used for a few operations */
2906 if (op != '+' && op != '-' && op != '*' && op != '/' &&
2907 (op < TOK_ULT || op > TOK_GT))
2908 error("invalid operands for binary operation");
2909 goto std_op;
2910 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
2911 /* cast to biggest op */
2912 t = VT_LLONG;
2913 /* convert to unsigned if it does not fit in a long long */
2914 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
2915 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
2916 t |= VT_UNSIGNED;
2917 goto std_op;
2918 } else {
2919 /* integer operations */
2920 t = VT_INT;
2921 /* convert to unsigned if it does not fit in an integer */
2922 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
2923 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
2924 t |= VT_UNSIGNED;
2925 std_op:
2926 /* XXX: currently, some unsigned operations are explicit, so
2927 we modify them here */
2928 if (t & VT_UNSIGNED) {
2929 if (op == TOK_SAR)
2930 op = TOK_SHR;
2931 else if (op == '/')
2932 op = TOK_UDIV;
2933 else if (op == '%')
2934 op = TOK_UMOD;
2935 else if (op == TOK_LT)
2936 op = TOK_ULT;
2937 else if (op == TOK_GT)
2938 op = TOK_UGT;
2939 else if (op == TOK_LE)
2940 op = TOK_ULE;
2941 else if (op == TOK_GE)
2942 op = TOK_UGE;
2944 vswap();
2945 gen_cast(t);
2946 vswap();
2947 /* special case for shifts and long long: we keep the shift as
2948 an integer */
2949 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
2950 gen_cast(VT_INT);
2951 else
2952 gen_cast(t);
2953 if (is_float(t))
2954 gen_opf(op);
2955 else if ((t & VT_BTYPE) == VT_LLONG)
2956 gen_opl(op);
2957 else
2958 gen_opc(op);
2959 if (op >= TOK_ULT && op <= TOK_GT) {
2960 /* relationnal op: the result is an int */
2961 vtop->t = VT_INT;
2962 } else {
2963 vtop->t = t;
2968 /* generic itof for unsigned long long case */
2969 void gen_cvt_itof1(int t)
2971 GFuncContext gf;
2973 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
2974 (VT_LLONG | VT_UNSIGNED)) {
2976 gfunc_start(&gf);
2977 gfunc_param(&gf);
2978 if (t == VT_FLOAT)
2979 vpushi((int)&__ulltof);
2980 else if (t == VT_DOUBLE)
2981 vpushi((int)&__ulltod);
2982 else
2983 vpushi((int)&__ulltold);
2984 gfunc_call(&gf);
2985 vpushi(0);
2986 vtop->r = REG_FRET;
2987 } else {
2988 gen_cvt_itof(t);
2992 /* generic ftoi for unsigned long long case */
2993 void gen_cvt_ftoi1(int t)
2995 GFuncContext gf;
2996 int st;
2998 if (t == (VT_LLONG | VT_UNSIGNED)) {
2999 /* not handled natively */
3000 gfunc_start(&gf);
3001 st = vtop->t & VT_BTYPE;
3002 gfunc_param(&gf);
3003 if (st == VT_FLOAT)
3004 vpushi((int)&__ftoull);
3005 else if (st == VT_DOUBLE)
3006 vpushi((int)&__dtoull);
3007 else
3008 vpushi((int)&__ldtoull);
3009 gfunc_call(&gf);
3010 vpushi(0);
3011 vtop->r = REG_IRET;
3012 vtop->r2 = REG_LRET;
3013 } else {
3014 gen_cvt_ftoi(t);
3018 /* force char or short cast */
3019 void force_charshort_cast(int t)
3021 int bits, dbt;
3022 dbt = t & VT_BTYPE;
3023 /* XXX: add optimization if lvalue : just change type and offset */
3024 if (dbt == VT_BYTE)
3025 bits = 8;
3026 else
3027 bits = 16;
3028 if (t & VT_UNSIGNED) {
3029 vpushi((1 << bits) - 1);
3030 gen_op('&');
3031 } else {
3032 bits = 32 - bits;
3033 vpushi(bits);
3034 gen_op(TOK_SHL);
3035 vpushi(bits);
3036 gen_op(TOK_SAR);
3040 /* cast 'vtop' to 't' type */
3041 void gen_cast(int t)
3043 int sbt, dbt, sf, df, c, st1, dt1;
3045 /* special delayed cast for char/short */
3046 /* XXX: in some cases (multiple cascaded casts), it may still
3047 be incorrect */
3048 if (vtop->r & VT_MUSTCAST) {
3049 vtop->r &= ~VT_MUSTCAST;
3050 force_charshort_cast(vtop->t);
3053 dbt = t & VT_BTYPE;
3054 sbt = vtop->t & VT_BTYPE;
3056 if (sbt != dbt) {
3057 sf = is_float(sbt);
3058 df = is_float(dbt);
3059 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3060 if (sf && df) {
3061 /* convert from fp to fp */
3062 if (c) {
3063 /* constant case: we can do it now */
3064 /* XXX: in ISOC, cannot do it if error in convert */
3065 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
3066 vtop->c.f = (float)vtop->c.d;
3067 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
3068 vtop->c.f = (float)vtop->c.ld;
3069 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
3070 vtop->c.d = (double)vtop->c.f;
3071 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
3072 vtop->c.d = (double)vtop->c.ld;
3073 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
3074 vtop->c.ld = (long double)vtop->c.f;
3075 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
3076 vtop->c.ld = (long double)vtop->c.d;
3077 } else {
3078 /* non constant case: generate code */
3079 gen_cvt_ftof(dbt);
3081 } else if (df) {
3082 /* convert int to fp */
3083 st1 = vtop->t & (VT_BTYPE | VT_UNSIGNED);
3084 if (c) {
3085 switch(st1) {
3086 case VT_LLONG | VT_UNSIGNED:
3087 case VT_LLONG:
3088 /* XXX: add const cases for long long */
3089 goto do_itof;
3090 case VT_INT | VT_UNSIGNED:
3091 switch(dbt) {
3092 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
3093 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
3094 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
3096 break;
3097 default:
3098 switch(dbt) {
3099 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
3100 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
3101 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
3103 break;
3105 } else {
3106 do_itof:
3107 gen_cvt_itof1(dbt);
3109 } else if (sf) {
3110 /* convert fp to int */
3111 dt1 = t & (VT_BTYPE | VT_UNSIGNED);
3112 /* we handle char/short/etc... with generic code */
3113 if (dt1 != (VT_INT | VT_UNSIGNED) &&
3114 dt1 != (VT_LLONG | VT_UNSIGNED) &&
3115 dt1 != VT_LLONG)
3116 dt1 = VT_INT;
3117 if (c) {
3118 switch(dt1) {
3119 case VT_LLONG | VT_UNSIGNED:
3120 case VT_LLONG:
3121 /* XXX: add const cases for long long */
3122 goto do_ftoi;
3123 case VT_INT | VT_UNSIGNED:
3124 switch(sbt) {
3125 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
3126 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3127 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3129 break;
3130 default:
3131 /* int case */
3132 switch(sbt) {
3133 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
3134 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
3135 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
3137 break;
3139 } else {
3140 do_ftoi:
3141 gen_cvt_ftoi1(dt1);
3143 if (dt1 == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dt1) {
3144 /* additionnal cast for char/short/bool... */
3145 vtop->t = dt1;
3146 gen_cast(t);
3148 } else if (dbt == VT_LLONG) {
3149 /* scalar to long long */
3150 if (c) {
3151 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3152 vtop->c.ll = vtop->c.ui;
3153 else
3154 vtop->c.ll = vtop->c.i;
3155 } else {
3156 /* machine independant conversion */
3157 gv(RC_INT);
3158 /* generate high word */
3159 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) {
3160 vpushi(0);
3161 gv(RC_INT);
3162 } else {
3163 gv_dup();
3164 vpushi(31);
3165 gen_op(TOK_SAR);
3167 /* patch second register */
3168 vtop[-1].r2 = vtop->r;
3169 vpop();
3171 } else if (dbt == VT_BOOL) {
3172 /* scalar to bool */
3173 vpushi(0);
3174 gen_op(TOK_NE);
3175 } else if (dbt == VT_BYTE || dbt == VT_SHORT) {
3176 force_charshort_cast(t);
3177 } else if (dbt == VT_INT) {
3178 /* scalar to int */
3179 if (sbt == VT_LLONG) {
3180 /* from long long: just take low order word */
3181 lexpand();
3182 vpop();
3183 } else if (vtop->r & VT_LVAL) {
3184 /* if lvalue and single word type, nothing to do (XXX:
3185 maybe incorrect for sizeof op) */
3186 goto no_cast;
3190 vtop->t = t;
3191 no_cast: ;
3194 /* return type size. Put alignment at 'a' */
3195 int type_size(int t, int *a)
3197 Sym *s;
3198 int bt;
3200 bt = t & VT_BTYPE;
3201 if (bt == VT_STRUCT) {
3202 /* struct/union */
3203 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3204 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
3205 return s->c;
3206 } else if (bt == VT_PTR) {
3207 if (t & VT_ARRAY) {
3208 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3209 return type_size(s->t, a) * s->c;
3210 } else {
3211 *a = PTR_SIZE;
3212 return PTR_SIZE;
3214 } else if (bt == VT_LDOUBLE) {
3215 *a = LDOUBLE_ALIGN;
3216 return LDOUBLE_SIZE;
3217 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
3218 *a = 8;
3219 return 8;
3220 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
3221 *a = 4;
3222 return 4;
3223 } else if (bt == VT_SHORT) {
3224 *a = 2;
3225 return 2;
3226 } else {
3227 /* char, void, function, _Bool */
3228 *a = 1;
3229 return 1;
3233 /* return the pointed type of t */
3234 int pointed_type(int t)
3236 Sym *s;
3237 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3238 return s->t | (t & ~VT_TYPE);
3241 int mk_pointer(int t)
3243 int p;
3244 p = anon_sym++;
3245 sym_push(p, t, 0, -1);
3246 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
3249 int is_compatible_types(int t1, int t2)
3251 Sym *s1, *s2;
3252 int bt1, bt2;
3254 t1 &= VT_TYPE;
3255 t2 &= VT_TYPE;
3256 bt1 = t1 & VT_BTYPE;
3257 bt2 = t2 & VT_BTYPE;
3258 if (bt1 == VT_PTR) {
3259 t1 = pointed_type(t1);
3260 /* if function, then convert implicitely to function pointer */
3261 if (bt2 != VT_FUNC) {
3262 if (bt2 != VT_PTR)
3263 return 0;
3264 t2 = pointed_type(t2);
3266 /* void matches everything */
3267 t1 &= VT_TYPE;
3268 t2 &= VT_TYPE;
3269 if (t1 == VT_VOID || t2 == VT_VOID)
3270 return 1;
3271 return is_compatible_types(t1, t2);
3272 } else if (bt1 == VT_STRUCT) {
3273 return (t2 == t1);
3274 } else if (bt1 == VT_FUNC) {
3275 if (bt2 != VT_FUNC)
3276 return 0;
3277 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
3278 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
3279 if (!is_compatible_types(s1->t, s2->t))
3280 return 0;
3281 /* XXX: not complete */
3282 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
3283 return 1;
3284 if (s1->c != s2->c)
3285 return 0;
3286 while (s1 != NULL) {
3287 if (s2 == NULL)
3288 return 0;
3289 if (!is_compatible_types(s1->t, s2->t))
3290 return 0;
3291 s1 = s1->next;
3292 s2 = s2->next;
3294 if (s2)
3295 return 0;
3296 return 1;
3297 } else {
3298 /* XXX: not complete */
3299 return 1;
3303 /* print a type. If 'varstr' is not NULL, then the variable is also
3304 printed in the type */
3305 /* XXX: union */
3306 /* XXX: add array and function pointers */
3307 void type_to_str(char *buf, int buf_size,
3308 int t, const char *varstr)
3310 int bt, v;
3311 Sym *s, *sa;
3312 char buf1[256];
3313 const char *tstr;
3315 t = t & VT_TYPE;
3316 bt = t & VT_BTYPE;
3317 buf[0] = '\0';
3318 if (t & VT_UNSIGNED)
3319 pstrcat(buf, buf_size, "unsigned ");
3320 switch(bt) {
3321 case VT_VOID:
3322 tstr = "void";
3323 goto add_tstr;
3324 case VT_BOOL:
3325 tstr = "_Bool";
3326 goto add_tstr;
3327 case VT_BYTE:
3328 tstr = "char";
3329 goto add_tstr;
3330 case VT_SHORT:
3331 tstr = "short";
3332 goto add_tstr;
3333 case VT_INT:
3334 tstr = "int";
3335 goto add_tstr;
3336 case VT_LONG:
3337 tstr = "long";
3338 goto add_tstr;
3339 case VT_LLONG:
3340 tstr = "long long";
3341 goto add_tstr;
3342 case VT_FLOAT:
3343 tstr = "float";
3344 goto add_tstr;
3345 case VT_DOUBLE:
3346 tstr = "double";
3347 goto add_tstr;
3348 case VT_LDOUBLE:
3349 tstr = "long double";
3350 add_tstr:
3351 pstrcat(buf, buf_size, tstr);
3352 break;
3353 case VT_ENUM:
3354 case VT_STRUCT:
3355 if (bt == VT_STRUCT)
3356 tstr = "struct ";
3357 else
3358 tstr = "enum ";
3359 pstrcat(buf, buf_size, tstr);
3360 v = (unsigned)t >> VT_STRUCT_SHIFT;
3361 if (v >= SYM_FIRST_ANOM)
3362 pstrcat(buf, buf_size, "<anonymous>");
3363 else
3364 pstrcat(buf, buf_size, get_tok_str(v, NULL));
3365 break;
3366 case VT_FUNC:
3367 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3368 type_to_str(buf, buf_size, s->t, varstr);
3369 pstrcat(buf, buf_size, "(");
3370 sa = s->next;
3371 while (sa != NULL) {
3372 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
3373 pstrcat(buf, buf_size, buf1);
3374 sa = sa->next;
3375 if (sa)
3376 pstrcat(buf, buf_size, ", ");
3378 pstrcat(buf, buf_size, ")");
3379 goto no_var;
3380 case VT_PTR:
3381 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3382 pstrcpy(buf1, sizeof(buf1), "*");
3383 if (varstr)
3384 pstrcat(buf1, sizeof(buf1), varstr);
3385 type_to_str(buf, buf_size, s->t, buf1);
3386 goto no_var;
3388 if (varstr) {
3389 pstrcat(buf, buf_size, " ");
3390 pstrcat(buf, buf_size, varstr);
3392 no_var: ;
3395 /* verify type compatibility to store vtop in 'dt' type, and generate
3396 casts if needed. */
3397 void gen_assign_cast(int dt)
3399 int st;
3400 char buf1[256], buf2[256];
3402 st = vtop->t; /* source type */
3403 if ((dt & VT_BTYPE) == VT_PTR) {
3404 /* special cases for pointers */
3405 /* a function is implicitely a function pointer */
3406 if ((st & VT_BTYPE) == VT_FUNC) {
3407 if (!is_compatible_types(pointed_type(dt), st))
3408 goto error;
3409 else
3410 goto type_ok;
3412 /* '0' can also be a pointer */
3413 if ((st & VT_BTYPE) == VT_INT &&
3414 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) &&
3415 vtop->c.i == 0)
3416 goto type_ok;
3418 if (!is_compatible_types(dt, st)) {
3419 error:
3420 type_to_str(buf1, sizeof(buf1), st, NULL);
3421 type_to_str(buf2, sizeof(buf2), dt, NULL);
3422 error("cannot cast '%s' to '%s'", buf1, buf2);
3424 type_ok:
3425 gen_cast(dt);
3428 /* store vtop in lvalue pushed on stack */
3429 void vstore(void)
3431 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
3432 GFuncContext gf;
3434 ft = vtop[-1].t;
3435 sbt = vtop->t & VT_BTYPE;
3436 dbt = ft & VT_BTYPE;
3437 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
3438 (sbt == VT_INT && dbt == VT_SHORT)) {
3439 /* optimize char/short casts */
3440 delayed_cast = VT_MUSTCAST;
3441 vtop->t = ft & VT_TYPE;
3442 } else {
3443 delayed_cast = 0;
3444 gen_assign_cast(ft & VT_TYPE);
3447 if (sbt == VT_STRUCT) {
3448 /* if structure, only generate pointer */
3449 /* structure assignment : generate memcpy */
3450 /* XXX: optimize if small size */
3452 vdup();
3453 gfunc_start(&gf);
3454 /* type size */
3455 size = type_size(vtop->t, &align);
3456 vpushi(size);
3457 gfunc_param(&gf);
3458 /* source */
3459 vtop->t = VT_INT;
3460 vtop->r &= ~VT_LVAL;
3461 gfunc_param(&gf);
3462 /* destination */
3463 vswap();
3464 vtop->t = VT_INT;
3465 vtop->r &= ~VT_LVAL;
3466 gfunc_param(&gf);
3468 save_regs();
3469 vpushi((int)&memcpy);
3470 gfunc_call(&gf);
3471 /* leave source on stack */
3472 } else if (ft & VT_BITFIELD) {
3473 /* bitfield store handling */
3474 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
3475 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3476 /* remove bit field info to avoid loops */
3477 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3479 /* duplicate destination */
3480 vdup();
3481 vtop[-1] = vtop[-2];
3483 /* mask and shift source */
3484 vpushi((1 << bit_size) - 1);
3485 gen_op('&');
3486 vpushi(bit_pos);
3487 gen_op(TOK_SHL);
3488 /* load destination, mask and or with source */
3489 vswap();
3490 vpushi(~(((1 << bit_size) - 1) << bit_pos));
3491 gen_op('&');
3492 gen_op('|');
3493 /* store result */
3494 vstore();
3495 } else {
3496 rc = RC_INT;
3497 if (is_float(ft))
3498 rc = RC_FLOAT;
3499 r = gv(rc); /* generate value (XXX: move that to store code) */
3500 /* if lvalue was saved on stack, must read it */
3501 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
3502 SValue sv;
3503 t = get_reg(RC_INT);
3504 sv.t = VT_INT;
3505 sv.r = VT_LOCAL | VT_LVAL;
3506 sv.c.ul = vtop[-1].c.ul;
3507 load(t, &sv);
3508 vtop[-1].r = t | VT_LVAL;
3510 store(r, vtop - 1);
3511 /* two word case handling : store second register at word + 4 */
3512 if ((ft & VT_BTYPE) == VT_LLONG) {
3513 vswap();
3514 /* convert to int to increment easily */
3515 vtop->t = VT_INT;
3516 vtop->r &= ~VT_LVAL;
3517 vpushi(4);
3518 gen_op('+');
3519 vtop->r |= VT_LVAL;
3520 vswap();
3521 /* XXX: it works because r2 is spilled last ! */
3522 store(vtop->r2, vtop - 1);
3524 vswap();
3525 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
3526 vtop->r |= delayed_cast;
3530 /* post defines POST/PRE add. c is the token ++ or -- */
3531 void inc(int post, int c)
3533 test_lvalue();
3534 vdup(); /* save lvalue */
3535 if (post) {
3536 gv_dup(); /* duplicate value */
3537 vrotb(3);
3538 vrotb(3);
3540 /* add constant */
3541 vpushi(c - TOK_MID);
3542 gen_op('+');
3543 vstore(); /* store value */
3544 if (post)
3545 vpop(); /* if post op, return saved value */
3548 /* Parse GNUC __attribute__ extension. Currently, the following
3549 extensions are recognized:
3550 - aligned(n) : set data/function alignment.
3551 - section(x) : generate data/code in this section.
3552 - unused : currently ignored, but may be used someday.
3554 void parse_attribute(AttributeDef *ad)
3556 int t, n;
3558 next();
3559 skip('(');
3560 skip('(');
3561 while (tok != ')') {
3562 if (tok < TOK_IDENT)
3563 expect("attribute name");
3564 t = tok;
3565 next();
3566 switch(t) {
3567 case TOK_SECTION:
3568 case TOK___SECTION__:
3569 skip('(');
3570 if (tok != TOK_STR)
3571 expect("section name");
3572 ad->section = find_section(tokc.ts->str);
3573 next();
3574 skip(')');
3575 break;
3576 case TOK_ALIGNED:
3577 case TOK___ALIGNED__:
3578 skip('(');
3579 n = expr_const();
3580 if (n <= 0 || (n & (n - 1)) != 0)
3581 error("alignment must be a positive power of two");
3582 ad->aligned = n;
3583 skip(')');
3584 break;
3585 case TOK_UNUSED:
3586 case TOK___UNUSED__:
3587 /* currently, no need to handle it because tcc does not
3588 track unused objects */
3589 break;
3590 default:
3591 warning("'%s' attribute ignored", get_tok_str(t, NULL));
3592 /* skip parameters */
3593 /* XXX: skip parenthesis too */
3594 if (tok == '(') {
3595 next();
3596 while (tok != ')' && tok != -1)
3597 next();
3598 next();
3600 break;
3602 if (tok != ',')
3603 break;
3604 next();
3606 skip(')');
3607 skip(')');
3610 /* enum/struct/union declaration */
3611 int struct_decl(int u)
3613 int a, t, b, v, size, align, maxalign, c, offset;
3614 int bit_size, bit_pos, bsize, bt, lbit_pos;
3615 Sym *s, *ss, **ps;
3616 AttributeDef ad;
3618 a = tok; /* save decl type */
3619 next();
3620 if (tok != '{') {
3621 v = tok;
3622 next();
3623 /* struct already defined ? return it */
3624 /* XXX: check consistency */
3625 s = sym_find(v | SYM_STRUCT);
3626 if (s) {
3627 if (s->t != a)
3628 error("invalid type");
3629 goto do_decl;
3631 } else {
3632 v = anon_sym++;
3634 s = sym_push(v | SYM_STRUCT, a, 0, 0);
3635 /* put struct/union/enum name in type */
3636 do_decl:
3637 u = u | (v << VT_STRUCT_SHIFT);
3639 if (tok == '{') {
3640 next();
3641 if (s->c)
3642 error("struct/union/enum already defined");
3643 /* cannot be empty */
3644 c = 0;
3645 maxalign = 0;
3646 ps = &s->next;
3647 bit_pos = 0;
3648 offset = 0;
3649 while (1) {
3650 if (a == TOK_ENUM) {
3651 v = tok;
3652 next();
3653 if (tok == '=') {
3654 next();
3655 c = expr_const();
3657 /* enum symbols have static storage */
3658 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
3659 if (tok == ',')
3660 next();
3661 c++;
3662 } else {
3663 parse_btype(&b, &ad);
3664 while (1) {
3665 bit_size = -1;
3666 v = 0;
3667 if (tok != ':') {
3668 t = type_decl(&v, b, TYPE_DIRECT);
3669 if ((t & VT_BTYPE) == VT_FUNC ||
3670 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
3671 error("invalid type for '%s'",
3672 get_tok_str(v, NULL));
3673 } else {
3674 t = b;
3676 if (tok == ':') {
3677 next();
3678 bit_size = expr_const();
3679 /* XXX: handle v = 0 case for messages */
3680 if (bit_size < 0)
3681 error("negative width in bit-field '%s'",
3682 get_tok_str(v, NULL));
3683 if (v && bit_size == 0)
3684 error("zero width for bit-field '%s'",
3685 get_tok_str(v, NULL));
3687 size = type_size(t, &align);
3688 lbit_pos = 0;
3689 if (bit_size >= 0) {
3690 bt = t & VT_BTYPE;
3691 if (bt != VT_INT &&
3692 bt != VT_BYTE &&
3693 bt != VT_SHORT)
3694 error("bitfields must have scalar type");
3695 bsize = size * 8;
3696 if (bit_size > bsize) {
3697 error("width of '%s' exceeds its type",
3698 get_tok_str(v, NULL));
3699 } else if (bit_size == bsize) {
3700 /* no need for bit fields */
3701 bit_pos = 0;
3702 } else if (bit_size == 0) {
3703 /* XXX: what to do if only padding in a
3704 structure ? */
3705 /* zero size: means to pad */
3706 if (bit_pos > 0)
3707 bit_pos = bsize;
3708 } else {
3709 /* we do not have enough room ? */
3710 if ((bit_pos + bit_size) > bsize)
3711 bit_pos = 0;
3712 lbit_pos = bit_pos;
3713 /* XXX: handle LSB first */
3714 t |= VT_BITFIELD |
3715 (bit_pos << VT_STRUCT_SHIFT) |
3716 (bit_size << (VT_STRUCT_SHIFT + 6));
3717 bit_pos += bit_size;
3719 } else {
3720 bit_pos = 0;
3722 if (v) {
3723 /* add new memory data only if starting
3724 bit field */
3725 if (lbit_pos == 0) {
3726 if (a == TOK_STRUCT) {
3727 c = (c + align - 1) & -align;
3728 offset = c;
3729 c += size;
3730 } else {
3731 offset = 0;
3732 if (size > c)
3733 c = size;
3735 if (align > maxalign)
3736 maxalign = align;
3738 #if 0
3739 printf("add field %s offset=%d",
3740 get_tok_str(v, NULL), offset);
3741 if (t & VT_BITFIELD) {
3742 printf(" pos=%d size=%d",
3743 (t >> VT_STRUCT_SHIFT) & 0x3f,
3744 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
3746 printf("\n");
3747 #endif
3748 ss = sym_push(v | SYM_FIELD, t, 0, offset);
3749 *ps = ss;
3750 ps = &ss->next;
3752 if (tok == ';' || tok == -1)
3753 break;
3754 skip(',');
3756 skip(';');
3758 if (tok == '}')
3759 break;
3761 skip('}');
3762 /* size for struct/union, dummy for enum */
3763 s->c = (c + maxalign - 1) & -maxalign;
3765 return u;
3768 /* return 0 if no type declaration. otherwise, return the basic type
3769 and skip it.
3771 int parse_btype(int *type_ptr, AttributeDef *ad)
3773 int t, u, type_found;
3774 Sym *s;
3776 memset(ad, 0, sizeof(AttributeDef));
3777 type_found = 0;
3778 t = 0;
3779 while(1) {
3780 switch(tok) {
3781 /* basic types */
3782 case TOK_CHAR:
3783 u = VT_BYTE;
3784 basic_type:
3785 next();
3786 basic_type1:
3787 if ((t & VT_BTYPE) != 0)
3788 error("too many basic types");
3789 t |= u;
3790 break;
3791 case TOK_VOID:
3792 u = VT_VOID;
3793 goto basic_type;
3794 case TOK_SHORT:
3795 u = VT_SHORT;
3796 goto basic_type;
3797 case TOK_INT:
3798 next();
3799 break;
3800 case TOK_LONG:
3801 next();
3802 if ((t & VT_BTYPE) == VT_DOUBLE) {
3803 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
3804 } else if ((t & VT_BTYPE) == VT_LONG) {
3805 t = (t & ~VT_BTYPE) | VT_LLONG;
3806 } else {
3807 u = VT_LONG;
3808 goto basic_type1;
3810 break;
3811 case TOK_BOOL:
3812 u = VT_BOOL;
3813 goto basic_type;
3814 case TOK_FLOAT:
3815 u = VT_FLOAT;
3816 goto basic_type;
3817 case TOK_DOUBLE:
3818 next();
3819 if ((t & VT_BTYPE) == VT_LONG) {
3820 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
3821 } else {
3822 u = VT_DOUBLE;
3823 goto basic_type1;
3825 break;
3826 case TOK_ENUM:
3827 u = struct_decl(VT_ENUM);
3828 goto basic_type1;
3829 case TOK_STRUCT:
3830 case TOK_UNION:
3831 u = struct_decl(VT_STRUCT);
3832 goto basic_type1;
3834 /* type modifiers */
3835 case TOK_CONST:
3836 case TOK_VOLATILE:
3837 case TOK_REGISTER:
3838 case TOK_SIGNED:
3839 case TOK_AUTO:
3840 case TOK_INLINE:
3841 case TOK_RESTRICT:
3842 next();
3843 break;
3844 case TOK_UNSIGNED:
3845 t |= VT_UNSIGNED;
3846 next();
3847 break;
3849 /* storage */
3850 case TOK_EXTERN:
3851 t |= VT_EXTERN;
3852 next();
3853 break;
3854 case TOK_STATIC:
3855 t |= VT_STATIC;
3856 next();
3857 break;
3858 case TOK_TYPEDEF:
3859 t |= VT_TYPEDEF;
3860 next();
3861 break;
3862 /* GNUC attribute */
3863 case TOK___ATTRIBUTE__:
3864 parse_attribute(ad);
3865 break;
3866 default:
3867 s = sym_find(tok);
3868 if (!s || !(s->t & VT_TYPEDEF))
3869 goto the_end;
3870 t |= (s->t & ~VT_TYPEDEF);
3871 next();
3872 break;
3874 type_found = 1;
3876 the_end:
3877 /* long is never used as type */
3878 if ((t & VT_BTYPE) == VT_LONG)
3879 t = (t & ~VT_BTYPE) | VT_INT;
3880 *type_ptr = t;
3881 return type_found;
3884 int post_type(int t)
3886 int p, n, pt, l, t1;
3887 Sym **plast, *s, *first;
3888 AttributeDef ad;
3890 if (tok == '(') {
3891 /* function declaration */
3892 next();
3893 l = 0;
3894 first = NULL;
3895 plast = &first;
3896 while (tok != ')') {
3897 /* read param name and compute offset */
3898 if (l != FUNC_OLD) {
3899 if (!parse_btype(&pt, &ad)) {
3900 if (l) {
3901 error("invalid type");
3902 } else {
3903 l = FUNC_OLD;
3904 goto old_proto;
3907 l = FUNC_NEW;
3908 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
3909 break;
3910 pt = type_decl(&n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
3911 if ((pt & VT_BTYPE) == VT_VOID)
3912 error("parameter declared as void");
3913 } else {
3914 old_proto:
3915 n = tok;
3916 pt = VT_INT;
3917 next();
3919 /* array must be transformed to pointer according to ANSI C */
3920 pt &= ~VT_ARRAY;
3921 s = sym_push(n | SYM_FIELD, pt, 0, 0);
3922 *plast = s;
3923 plast = &s->next;
3924 if (tok == ',') {
3925 next();
3926 if (l == FUNC_NEW && tok == TOK_DOTS) {
3927 l = FUNC_ELLIPSIS;
3928 next();
3929 break;
3933 /* if no parameters, then old type prototype */
3934 if (l == 0)
3935 l = FUNC_OLD;
3936 skip(')');
3937 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
3938 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
3939 /* we push a anonymous symbol which will contain the function prototype */
3940 p = anon_sym++;
3941 s = sym_push(p, t, 0, l);
3942 s->next = first;
3943 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
3944 } else if (tok == '[') {
3945 /* array definition */
3946 next();
3947 n = -1;
3948 if (tok != ']') {
3949 n = expr_const();
3950 if (n < 0)
3951 error("invalid array size");
3953 skip(']');
3954 /* parse next post type */
3955 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
3956 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
3958 /* we push a anonymous symbol which will contain the array
3959 element type */
3960 p = anon_sym++;
3961 sym_push(p, t, 0, n);
3962 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
3964 return t;
3967 /* Read a type declaration (except basic type), and return the
3968 type. If v is true, then also put variable name in 'vtop->c' */
3969 int type_decl(int *v, int t, int td)
3971 int u, p;
3972 Sym *s;
3974 while (tok == '*') {
3975 next();
3976 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
3977 next();
3978 t = mk_pointer(t);
3981 /* recursive type */
3982 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
3983 if (tok == '(') {
3984 next();
3985 u = type_decl(v, 0, td);
3986 skip(')');
3987 } else {
3988 u = 0;
3989 /* type identifier */
3990 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
3991 *v = tok;
3992 next();
3993 } else {
3994 if (!(td & TYPE_ABSTRACT))
3995 expect("identifier");
3996 *v = 0;
3999 /* append t at the end of u */
4000 t = post_type(t);
4001 if (!u)
4002 return t;
4003 p = u;
4004 while(1) {
4005 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
4006 p = s->t;
4007 if (!p) {
4008 s->t = t;
4009 break;
4012 return u;
4015 /* define a new external reference to a function 'v' of type 'u' */
4016 Sym *external_sym(int v, int u, int r)
4018 Sym *s;
4019 s = sym_find(v);
4020 if (!s) {
4021 /* push forward reference */
4022 s = sym_push1(&global_stack,
4023 v, u, 0);
4024 s->r = r | VT_CONST | VT_FORWARD;
4026 return s;
4029 void indir(void)
4031 if ((vtop->t & VT_BTYPE) != VT_PTR)
4032 expect("pointer");
4033 if (vtop->r & VT_LVAL)
4034 gv(RC_INT);
4035 vtop->t = pointed_type(vtop->t);
4036 if (!(vtop->t & VT_ARRAY)) /* an array is never an lvalue */
4037 vtop->r |= VT_LVAL;
4040 /* pass a parameter to a function and do type checking and casting */
4041 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
4043 int func_type;
4044 func_type = func->c;
4045 if (func_type == FUNC_OLD ||
4046 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
4047 /* default casting : only need to convert float to double */
4048 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
4049 gen_cast(VT_DOUBLE);
4050 } else if (arg == NULL) {
4051 error("too many arguments to function");
4052 } else {
4053 gen_assign_cast(arg->t);
4055 gfunc_param(gf);
4058 void unary(void)
4060 int n, t, ft, fc, p, align, size, r, data_offset;
4061 Sym *s;
4062 GFuncContext gf;
4063 AttributeDef ad;
4065 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
4066 vpushi(tokc.i);
4067 next();
4068 } else if (tok == TOK_CUINT) {
4069 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
4070 next();
4071 } else if (tok == TOK_CLLONG) {
4072 vsetc(VT_LLONG, VT_CONST, &tokc);
4073 next();
4074 } else if (tok == TOK_CULLONG) {
4075 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
4076 next();
4077 } else if (tok == TOK_CFLOAT) {
4078 vsetc(VT_FLOAT, VT_CONST, &tokc);
4079 next();
4080 } else if (tok == TOK_CDOUBLE) {
4081 vsetc(VT_DOUBLE, VT_CONST, &tokc);
4082 next();
4083 } else if (tok == TOK_CLDOUBLE) {
4084 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
4085 next();
4086 } else if (tok == TOK___FUNC__) {
4087 /* special function name identifier */
4088 /* generate (char *) type */
4089 data_offset = (int)data_section->data_ptr;
4090 vset(mk_pointer(VT_BYTE), VT_CONST, data_offset);
4091 strcpy((void *)data_offset, funcname);
4092 data_offset += strlen(funcname) + 1;
4093 data_section->data_ptr = (unsigned char *)data_offset;
4094 next();
4095 } else if (tok == TOK_LSTR) {
4096 t = VT_INT;
4097 goto str_init;
4098 } else if (tok == TOK_STR) {
4099 /* string parsing */
4100 t = VT_BYTE;
4101 str_init:
4102 type_size(t, &align);
4103 data_offset = (int)data_section->data_ptr;
4104 data_offset = (data_offset + align - 1) & -align;
4105 fc = data_offset;
4106 /* we must declare it as an array first to use initializer parser */
4107 t = VT_ARRAY | mk_pointer(t);
4108 decl_initializer(t, VT_CONST, data_offset, 1, 0);
4109 data_offset += type_size(t, &align);
4110 /* put it as pointer */
4111 vset(t & ~VT_ARRAY, VT_CONST, fc);
4112 data_section->data_ptr = (unsigned char *)data_offset;
4113 } else {
4114 t = tok;
4115 next();
4116 if (t == '(') {
4117 /* cast ? */
4118 if (parse_btype(&t, &ad)) {
4119 ft = type_decl(&n, t, TYPE_ABSTRACT);
4120 skip(')');
4121 /* check ISOC99 compound literal */
4122 if (tok == '{') {
4123 /* data is allocated locally by default */
4124 if (global_expr)
4125 r = VT_CONST;
4126 else
4127 r = VT_LOCAL;
4128 /* all except arrays are lvalues */
4129 if (!(ft & VT_ARRAY))
4130 r |= VT_LVAL;
4131 memset(&ad, 0, sizeof(AttributeDef));
4132 fc = decl_initializer_alloc(ft, &ad, r, 1);
4133 vset(ft, r, fc);
4134 } else {
4135 unary();
4136 gen_cast(ft);
4138 } else {
4139 gexpr();
4140 skip(')');
4142 } else if (t == '*') {
4143 unary();
4144 indir();
4145 } else if (t == '&') {
4146 unary();
4147 /* functions names must be treated as function pointers,
4148 except for unary '&' and sizeof. Since we consider that
4149 functions are not lvalues, we only have to handle it
4150 there and in function calls. */
4151 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4152 test_lvalue();
4153 vtop->t = mk_pointer(vtop->t);
4154 vtop->r &= ~VT_LVAL;
4155 } else
4156 if (t == '!') {
4157 unary();
4158 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
4159 vtop->c.i = !vtop->c.i;
4160 else if ((vtop->r & VT_VALMASK) == VT_CMP)
4161 vtop->c.i = vtop->c.i ^ 1;
4162 else
4163 vset(VT_INT, VT_JMP, gtst(1, 0));
4164 } else
4165 if (t == '~') {
4166 unary();
4167 vpushi(-1);
4168 gen_op('^');
4169 } else
4170 if (t == '+') {
4171 unary();
4172 } else
4173 if (t == TOK_SIZEOF) {
4174 if (tok == '(') {
4175 next();
4176 if (parse_btype(&t, &ad)) {
4177 t = type_decl(&n, t, TYPE_ABSTRACT);
4178 } else {
4179 /* XXX: some code could be generated: add eval
4180 flag */
4181 gexpr();
4182 t = vtop->t;
4183 vpop();
4185 skip(')');
4186 } else {
4187 unary();
4188 t = vtop->t;
4189 vpop();
4191 vpushi(type_size(t, &t));
4192 } else
4193 if (t == TOK_INC || t == TOK_DEC) {
4194 unary();
4195 inc(0, t);
4196 } else if (t == '-') {
4197 vpushi(0);
4198 unary();
4199 gen_op('-');
4200 } else
4202 s = sym_find(t);
4203 if (!s) {
4204 if (tok != '(')
4205 error("'%s' undeclared", get_tok_str(t, NULL));
4206 /* for simple function calls, we tolerate undeclared
4207 external reference */
4208 p = anon_sym++;
4209 sym_push1(&global_stack, p, 0, FUNC_OLD);
4210 /* int() function */
4211 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT), 0);
4213 vset(s->t, s->r, s->c);
4214 /* if forward reference, we must point to s */
4215 if (vtop->r & VT_FORWARD)
4216 vtop->c.sym = s;
4220 /* post operations */
4221 while (1) {
4222 if (tok == TOK_INC || tok == TOK_DEC) {
4223 inc(1, tok);
4224 next();
4225 } else if (tok == '.' || tok == TOK_ARROW) {
4226 /* field */
4227 if (tok == TOK_ARROW)
4228 indir();
4229 test_lvalue();
4230 vtop->r &= ~VT_LVAL;
4231 next();
4232 /* expect pointer on structure */
4233 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
4234 expect("struct or union");
4235 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4236 /* find field */
4237 tok |= SYM_FIELD;
4238 while ((s = s->next) != NULL) {
4239 if (s->v == tok)
4240 break;
4242 if (!s)
4243 error("field not found");
4244 /* add field offset to pointer */
4245 vtop->t = char_pointer_type; /* change type to 'char *' */
4246 vpushi(s->c);
4247 gen_op('+');
4248 /* change type to field type, and set to lvalue */
4249 vtop->t = s->t;
4250 /* an array is never an lvalue */
4251 if (!(vtop->t & VT_ARRAY))
4252 vtop->r |= VT_LVAL;
4253 next();
4254 } else if (tok == '[') {
4255 next();
4256 gexpr();
4257 gen_op('+');
4258 indir();
4259 skip(']');
4260 } else if (tok == '(') {
4261 SValue ret;
4262 Sym *sa;
4264 /* function call */
4265 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
4266 /* pointer test (no array accepted) */
4267 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
4268 vtop->t = pointed_type(vtop->t);
4269 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4270 goto error_func;
4271 } else {
4272 error_func:
4273 expect("function pointer");
4275 } else {
4276 vtop->r &= ~VT_LVAL; /* no lvalue */
4278 /* get return type */
4279 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
4280 save_regs(); /* save used temporary registers */
4281 gfunc_start(&gf);
4282 next();
4283 sa = s->next; /* first parameter */
4284 #ifdef INVERT_FUNC_PARAMS
4286 int *str, len, parlevel, *saved_macro_ptr;
4287 Sym *args, *s1;
4289 /* read each argument and store it on a stack */
4290 /* XXX: merge it with macro args ? */
4291 args = NULL;
4292 while (tok != ')') {
4293 len = 0;
4294 str = NULL;
4295 parlevel = 0;
4296 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
4297 tok != -1) {
4298 if (tok == '(')
4299 parlevel++;
4300 else if (tok == ')')
4301 parlevel--;
4302 tok_add2(&str, &len, tok, &tokc);
4303 next();
4305 tok_add(&str, &len, -1); /* end of file added */
4306 tok_add(&str, &len, 0);
4307 s1 = sym_push2(&args, 0, 0, (int)str);
4308 s1->next = sa; /* add reference to argument */
4309 if (sa)
4310 sa = sa->next;
4311 if (tok != ',')
4312 break;
4313 next();
4315 if (tok != ')')
4316 expect(")");
4318 /* now generate code in reverse order by reading the stack */
4319 saved_macro_ptr = macro_ptr;
4320 while (args) {
4321 macro_ptr = (int *)args->c;
4322 next();
4323 expr_eq();
4324 if (tok != -1)
4325 expect("',' or ')'");
4326 gfunc_param_typed(&gf, s, args->next);
4327 s1 = args->prev;
4328 free((int *)args->c);
4329 free(args);
4330 args = s1;
4332 macro_ptr = saved_macro_ptr;
4333 /* restore token */
4334 tok = ')';
4336 #endif
4337 /* compute first implicit argument if a structure is returned */
4338 if ((s->t & VT_BTYPE) == VT_STRUCT) {
4339 /* get some space for the returned structure */
4340 size = type_size(s->t, &align);
4341 loc = (loc - size) & -align;
4342 ret.t = s->t;
4343 ret.r = VT_LOCAL | VT_LVAL;
4344 /* pass it as 'int' to avoid structure arg passing
4345 problems */
4346 vset(VT_INT, VT_LOCAL, loc);
4347 ret.c = vtop->c;
4348 gfunc_param(&gf);
4349 } else {
4350 ret.t = s->t;
4351 ret.r2 = VT_CONST;
4352 /* return in register */
4353 if (is_float(ret.t)) {
4354 ret.r = REG_FRET;
4355 } else {
4356 if ((ret.t & VT_BTYPE) == VT_LLONG)
4357 ret.r2 = REG_LRET;
4358 ret.r = REG_IRET;
4360 ret.c.i = 0;
4362 #ifndef INVERT_FUNC_PARAMS
4363 while (tok != ')') {
4364 expr_eq();
4365 gfunc_param_typed(&gf, s, sa);
4366 if (sa)
4367 sa = sa->next;
4368 if (tok == ',')
4369 next();
4371 #endif
4372 if (sa)
4373 error("too few arguments to function");
4374 skip(')');
4375 gfunc_call(&gf);
4376 /* return value */
4377 vsetc(ret.t, ret.r, &ret.c);
4378 vtop->r2 = ret.r2;
4379 } else {
4380 break;
4385 void uneq(void)
4387 int t;
4389 unary();
4390 if (tok == '=' ||
4391 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
4392 tok == TOK_A_XOR || tok == TOK_A_OR ||
4393 tok == TOK_A_SHL || tok == TOK_A_SAR) {
4394 test_lvalue();
4395 t = tok;
4396 next();
4397 if (t == '=') {
4398 expr_eq();
4399 } else {
4400 vdup();
4401 expr_eq();
4402 gen_op(t & 0x7f);
4404 vstore();
4408 void sum(int l)
4410 int t;
4412 if (l == 0)
4413 uneq();
4414 else {
4415 sum(--l);
4416 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
4417 (l == 1 && (tok == '+' || tok == '-')) ||
4418 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
4419 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
4420 tok == TOK_ULT || tok == TOK_UGE)) ||
4421 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
4422 (l == 5 && tok == '&') ||
4423 (l == 6 && tok == '^') ||
4424 (l == 7 && tok == '|') ||
4425 (l == 8 && tok == TOK_LAND) ||
4426 (l == 9 && tok == TOK_LOR)) {
4427 t = tok;
4428 next();
4429 sum(l);
4430 gen_op(t);
4435 /* only used if non constant */
4436 void eand(void)
4438 int t;
4440 sum(8);
4441 t = 0;
4442 while (1) {
4443 if (tok != TOK_LAND) {
4444 if (t) {
4445 t = gtst(1, t);
4446 vset(VT_INT, VT_JMPI, t);
4448 break;
4450 t = gtst(1, t);
4451 next();
4452 sum(8);
4456 void eor(void)
4458 int t;
4460 eand();
4461 t = 0;
4462 while (1) {
4463 if (tok != TOK_LOR) {
4464 if (t) {
4465 t = gtst(0, t);
4466 vset(VT_INT, VT_JMP, t);
4468 break;
4470 t = gtst(0, t);
4471 next();
4472 eand();
4476 /* XXX: better constant handling */
4477 void expr_eq(void)
4479 int t, u, c, r1, r2, rc;
4481 if (const_wanted) {
4482 sum(10);
4483 if (tok == '?') {
4484 c = vtop->c.i;
4485 vpop();
4486 next();
4487 gexpr();
4488 t = vtop->c.i;
4489 vpop();
4490 skip(':');
4491 expr_eq();
4492 if (c)
4493 vtop->c.i = t;
4495 } else {
4496 eor();
4497 if (tok == '?') {
4498 next();
4499 t = gtst(1, 0);
4500 gexpr();
4501 /* XXX: long long handling ? */
4502 rc = RC_INT;
4503 if (is_float(vtop->t))
4504 rc = RC_FLOAT;
4505 r1 = gv(rc);
4506 vpop();
4507 skip(':');
4508 u = gjmp(0);
4510 gsym(t);
4511 expr_eq();
4512 r2 = gv(rc);
4513 move_reg(r1, r2);
4514 vtop->r = r1;
4515 gsym(u);
4520 void gexpr(void)
4522 while (1) {
4523 expr_eq();
4524 if (tok != ',')
4525 break;
4526 vpop();
4527 next();
4531 /* parse a constant expression and return value in vtop */
4532 void expr_const1(void)
4534 int a;
4535 a = const_wanted;
4536 const_wanted = 1;
4537 expr_eq();
4538 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
4539 expect("constant");
4540 const_wanted = a;
4543 /* parse an integer constant and return its value */
4544 int expr_const(void)
4546 int c;
4547 expr_const1();
4548 c = vtop->c.i;
4549 vpop();
4550 return c;
4553 /* return the label token if current token is a label, otherwise
4554 return zero */
4555 int is_label(void)
4557 int t;
4558 CValue c;
4560 /* fast test first */
4561 if (tok < TOK_UIDENT)
4562 return 0;
4563 /* no need to save tokc since we expect an identifier */
4564 t = tok;
4565 c = tokc;
4566 next();
4567 if (tok == ':') {
4568 next();
4569 return t;
4570 } else {
4571 /* XXX: may not work in all cases (macros ?) */
4572 tok1 = tok;
4573 tok1c = tokc;
4574 tok = t;
4575 tokc = c;
4576 return 0;
4580 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
4582 int a, b, c, d;
4583 Sym *s;
4585 /* generate line number info */
4586 if (do_debug &&
4587 (last_line_num != line_num || last_ind != ind)) {
4588 put_stabn(N_SLINE, 0, line_num, ind - func_ind);
4589 last_ind = ind;
4590 last_line_num = line_num;
4593 if (tok == TOK_IF) {
4594 /* if test */
4595 next();
4596 skip('(');
4597 gexpr();
4598 skip(')');
4599 a = gtst(1, 0);
4600 block(bsym, csym, case_sym, def_sym, case_reg);
4601 c = tok;
4602 if (c == TOK_ELSE) {
4603 next();
4604 d = gjmp(0);
4605 gsym(a);
4606 block(bsym, csym, case_sym, def_sym, case_reg);
4607 gsym(d); /* patch else jmp */
4608 } else
4609 gsym(a);
4610 } else if (tok == TOK_WHILE) {
4611 next();
4612 d = ind;
4613 skip('(');
4614 gexpr();
4615 skip(')');
4616 a = gtst(1, 0);
4617 b = 0;
4618 block(&a, &b, case_sym, def_sym, case_reg);
4619 oad(0xe9, d - ind - 5); /* jmp */
4620 gsym(a);
4621 gsym_addr(b, d);
4622 } else if (tok == '{') {
4623 next();
4624 /* declarations */
4625 s = local_stack.top;
4626 while (tok != '}') {
4627 decl(VT_LOCAL);
4628 if (tok != '}')
4629 block(bsym, csym, case_sym, def_sym, case_reg);
4631 /* pop locally defined symbols */
4632 sym_pop(&local_stack, s);
4633 next();
4634 } else if (tok == TOK_RETURN) {
4635 next();
4636 if (tok != ';') {
4637 gexpr();
4638 gen_assign_cast(func_vt);
4639 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
4640 /* if returning structure, must copy it to implicit
4641 first pointer arg location */
4642 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
4643 indir();
4644 vswap();
4645 /* copy structure value to pointer */
4646 vstore();
4647 } else if (is_float(func_vt)) {
4648 gv(RC_FRET);
4649 } else {
4650 gv(RC_IRET);
4652 vpop();
4654 skip(';');
4655 rsym = gjmp(rsym); /* jmp */
4656 } else if (tok == TOK_BREAK) {
4657 /* compute jump */
4658 if (!bsym)
4659 error("cannot break");
4660 *bsym = gjmp(*bsym);
4661 next();
4662 skip(';');
4663 } else if (tok == TOK_CONTINUE) {
4664 /* compute jump */
4665 if (!csym)
4666 error("cannot continue");
4667 *csym = gjmp(*csym);
4668 next();
4669 skip(';');
4670 } else if (tok == TOK_FOR) {
4671 int e;
4672 next();
4673 skip('(');
4674 if (tok != ';') {
4675 gexpr();
4676 vpop();
4678 skip(';');
4679 d = ind;
4680 c = ind;
4681 a = 0;
4682 b = 0;
4683 if (tok != ';') {
4684 gexpr();
4685 a = gtst(1, 0);
4687 skip(';');
4688 if (tok != ')') {
4689 e = gjmp(0);
4690 c = ind;
4691 gexpr();
4692 vpop();
4693 oad(0xe9, d - ind - 5); /* jmp */
4694 gsym(e);
4696 skip(')');
4697 block(&a, &b, case_sym, def_sym, case_reg);
4698 oad(0xe9, c - ind - 5); /* jmp */
4699 gsym(a);
4700 gsym_addr(b, c);
4701 } else
4702 if (tok == TOK_DO) {
4703 next();
4704 a = 0;
4705 b = 0;
4706 d = ind;
4707 block(&a, &b, case_sym, def_sym, case_reg);
4708 skip(TOK_WHILE);
4709 skip('(');
4710 gsym(b);
4711 gexpr();
4712 c = gtst(0, 0);
4713 gsym_addr(c, d);
4714 skip(')');
4715 gsym(a);
4716 skip(';');
4717 } else
4718 if (tok == TOK_SWITCH) {
4719 next();
4720 skip('(');
4721 gexpr();
4722 /* XXX: other types than integer */
4723 case_reg = gv(RC_INT);
4724 vpop();
4725 skip(')');
4726 a = 0;
4727 b = gjmp(0); /* jump to first case */
4728 c = 0;
4729 block(&a, csym, &b, &c, case_reg);
4730 /* if no default, jmp after switch */
4731 if (c == 0)
4732 c = ind;
4733 /* default label */
4734 gsym_addr(b, c);
4735 /* break label */
4736 gsym(a);
4737 } else
4738 if (tok == TOK_CASE) {
4739 int v1, v2;
4740 if (!case_sym)
4741 expect("switch");
4742 next();
4743 v1 = expr_const();
4744 v2 = v1;
4745 if (gnu_ext && tok == TOK_DOTS) {
4746 next();
4747 v2 = expr_const();
4748 if (v2 < v1)
4749 warning("empty case range");
4751 /* since a case is like a label, we must skip it with a jmp */
4752 b = gjmp(0);
4753 gsym(*case_sym);
4754 vset(VT_INT, case_reg, 0);
4755 vpushi(v1);
4756 if (v1 == v2) {
4757 gen_op(TOK_EQ);
4758 *case_sym = gtst(1, 0);
4759 } else {
4760 gen_op(TOK_GE);
4761 *case_sym = gtst(1, 0);
4762 vset(VT_INT, case_reg, 0);
4763 vpushi(v2);
4764 gen_op(TOK_LE);
4765 *case_sym = gtst(1, *case_sym);
4767 gsym(b);
4768 skip(':');
4769 block(bsym, csym, case_sym, def_sym, case_reg);
4770 } else
4771 if (tok == TOK_DEFAULT) {
4772 next();
4773 skip(':');
4774 if (!def_sym)
4775 expect("switch");
4776 if (*def_sym)
4777 error("too many 'default'");
4778 *def_sym = ind;
4779 block(bsym, csym, case_sym, def_sym, case_reg);
4780 } else
4781 if (tok == TOK_GOTO) {
4782 next();
4783 s = sym_find1(&label_stack, tok);
4784 /* put forward definition if needed */
4785 if (!s)
4786 s = sym_push1(&label_stack, tok, VT_FORWARD, 0);
4787 /* label already defined */
4788 if (s->t & VT_FORWARD)
4789 s->c = gjmp(s->c); /* jmp xxx */
4790 else
4791 oad(0xe9, s->c - ind - 5); /* jmp xxx */
4792 next();
4793 skip(';');
4794 } else {
4795 b = is_label();
4796 if (b) {
4797 /* label case */
4798 s = sym_find1(&label_stack, b);
4799 if (s) {
4800 if (!(s->t & VT_FORWARD))
4801 error("multiple defined label");
4802 gsym(s->c);
4803 s->c = ind;
4804 s->t = 0;
4805 } else {
4806 sym_push1(&label_stack, b, 0, ind);
4808 /* we accept this, but it is a mistake */
4809 if (tok == '}')
4810 warning("deprecated use of label at end of compound statement");
4811 else
4812 block(bsym, csym, case_sym, def_sym, case_reg);
4813 } else {
4814 /* expression case */
4815 if (tok != ';') {
4816 gexpr();
4817 vpop();
4819 skip(';');
4824 /* t is the array or struct type. c is the array or struct
4825 address. cur_index/cur_field is the pointer to the current
4826 value. 'size_only' is true if only size info is needed (only used
4827 in arrays) */
4828 void decl_designator(int t, int r, int c,
4829 int *cur_index, Sym **cur_field,
4830 int size_only)
4832 Sym *s, *f;
4833 int notfirst, index, align, l;
4835 notfirst = 0;
4836 if (gnu_ext && (l = is_label()) != 0)
4837 goto struct_field;
4839 while (tok == '[' || tok == '.') {
4840 if (tok == '[') {
4841 if (!(t & VT_ARRAY))
4842 expect("array type");
4843 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
4844 next();
4845 index = expr_const();
4846 if (index < 0 || (s->c >= 0 && index >= s->c))
4847 expect("invalid index");
4848 skip(']');
4849 if (!notfirst)
4850 *cur_index = index;
4851 t = pointed_type(t);
4852 c += index * type_size(t, &align);
4853 } else {
4854 next();
4855 l = tok;
4856 next();
4857 struct_field:
4858 if ((t & VT_BTYPE) != VT_STRUCT)
4859 expect("struct/union type");
4860 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4861 l |= SYM_FIELD;
4862 f = s->next;
4863 while (f) {
4864 if (f->v == l)
4865 break;
4866 f = f->next;
4868 if (!f)
4869 expect("field");
4870 if (!notfirst)
4871 *cur_field = f;
4872 t = f->t | (t & ~VT_TYPE);
4873 c += f->c;
4875 notfirst = 1;
4877 if (notfirst) {
4878 if (tok == '=') {
4879 next();
4880 } else {
4881 if (!gnu_ext)
4882 expect("=");
4884 } else {
4885 if (t & VT_ARRAY) {
4886 index = *cur_index;
4887 t = pointed_type(t);
4888 c += index * type_size(t, &align);
4889 } else {
4890 f = *cur_field;
4891 if (!f)
4892 error("too many field init");
4893 t = f->t | (t & ~VT_TYPE);
4894 c += f->c;
4897 decl_initializer(t, r, c, 0, size_only);
4900 #define EXPR_VAL 0
4901 #define EXPR_CONST 1
4902 #define EXPR_ANY 2
4904 /* store a value or an expression directly in global data or in local array */
4905 void init_putv(int t, int r, int c,
4906 int v, int expr_type)
4908 int saved_global_expr, bt;
4910 switch(expr_type) {
4911 case EXPR_VAL:
4912 vpushi(v);
4913 break;
4914 case EXPR_CONST:
4915 /* compound literals must be allocated globally in this case */
4916 saved_global_expr = global_expr;
4917 global_expr = 1;
4918 expr_const1();
4919 global_expr = saved_global_expr;
4920 break;
4921 case EXPR_ANY:
4922 expr_eq();
4923 break;
4926 if ((r & VT_VALMASK) == VT_CONST) {
4927 /* XXX: do casting */
4928 /* XXX: not portable */
4929 bt = vtop->t & VT_BTYPE;
4930 switch(bt) {
4931 case VT_BYTE:
4932 *(char *)c = vtop->c.i;
4933 break;
4934 case VT_SHORT:
4935 *(short *)c = vtop->c.i;
4936 break;
4937 case VT_DOUBLE:
4938 *(double *)c = vtop->c.d;
4939 break;
4940 case VT_LDOUBLE:
4941 *(long double *)c = vtop->c.ld;
4942 break;
4943 #if 0
4944 case VT_LLONG:
4945 *(long long *)c = vtop->c.ll;
4946 break;
4947 #endif
4948 default:
4949 *(int *)c = vtop->c.i;
4950 break;
4952 vpop();
4953 } else {
4954 vset(t, r, c);
4955 vswap();
4956 vstore();
4957 vpop();
4961 /* put zeros for variable based init */
4962 void init_putz(int t, int r, int c, int size)
4964 GFuncContext gf;
4966 if ((r & VT_VALMASK) == VT_CONST) {
4967 /* nothing to do because global are already set to zero */
4968 } else {
4969 gfunc_start(&gf);
4970 vpushi(size);
4971 gfunc_param(&gf);
4972 vpushi(0);
4973 gfunc_param(&gf);
4974 vset(VT_INT, VT_LOCAL, c);
4975 gfunc_param(&gf);
4976 vpushi((int)&memset);
4977 gfunc_call(&gf);
4981 /* 't' contains the type and storage info. c is the address of the
4982 object. 'first' is true if array '{' must be read (multi dimension
4983 implicit array init handling). 'size_only' is true if size only
4984 evaluation is wanted (only for arrays). */
4985 void decl_initializer(int t, int r, int c, int first, int size_only)
4987 int index, array_length, n, no_oblock, nb, parlevel, i;
4988 int t1, size1, align1, expr_type;
4989 Sym *s, *f;
4990 TokenSym *ts;
4992 if (t & VT_ARRAY) {
4993 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
4994 n = s->c;
4995 array_length = 0;
4996 t1 = pointed_type(t);
4997 size1 = type_size(t1, &align1);
4999 no_oblock = 1;
5000 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
5001 tok == '{') {
5002 skip('{');
5003 no_oblock = 0;
5006 /* only parse strings here if correct type (otherwise: handle
5007 them as ((w)char *) expressions */
5008 if ((tok == TOK_LSTR &&
5009 (t1 & VT_BTYPE) == VT_INT) ||
5010 (tok == TOK_STR &&
5011 (t1 & VT_BTYPE) == VT_BYTE)) {
5012 /* XXX: move multiple string parsing in parser ? */
5013 while (tok == TOK_STR || tok == TOK_LSTR) {
5014 ts = tokc.ts;
5015 /* compute maximum number of chars wanted */
5016 nb = ts->len;
5017 if (n >= 0 && nb > (n - array_length))
5018 nb = n - array_length;
5019 if (!size_only) {
5020 if (ts->len > nb)
5021 warning("initializer-string for array is too long");
5022 for(i=0;i<nb;i++) {
5023 init_putv(t1, r, c + (array_length + i) * size1,
5024 ts->str[i], EXPR_VAL);
5027 array_length += nb;
5028 next();
5030 /* only add trailing zero if enough storage (no
5031 warning in this case since it is standard) */
5032 if (n < 0 || array_length < n) {
5033 if (!size_only) {
5034 init_putv(t1, r, c + (array_length * size1), 0, EXPR_VAL);
5036 array_length++;
5038 } else {
5039 index = 0;
5040 while (tok != '}') {
5041 decl_designator(t, r, c, &index, NULL, size_only);
5042 if (n >= 0 && index >= n)
5043 error("index too large");
5044 /* must put zero in holes (note that doing it that way
5045 ensures that it even works with designators) */
5046 if (!size_only && array_length < index) {
5047 init_putz(t1, r, c + array_length * size1,
5048 (index - array_length) * size1);
5050 index++;
5051 if (index > array_length)
5052 array_length = index;
5053 /* special test for multi dimensional arrays (may not
5054 be strictly correct if designators are used at the
5055 same time) */
5056 if (index >= n && no_oblock)
5057 break;
5058 if (tok == '}')
5059 break;
5060 skip(',');
5063 if (!no_oblock)
5064 skip('}');
5065 /* put zeros at the end */
5066 if (!size_only && n >= 0 && array_length < n) {
5067 init_putz(t1, r, c + array_length * size1,
5068 (n - array_length) * size1);
5070 /* patch type size if needed */
5071 if (n < 0)
5072 s->c = array_length;
5073 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
5074 /* XXX: union needs only one init */
5075 next();
5076 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5077 f = s->next;
5078 array_length = 0;
5079 index = 0;
5080 n = s->c;
5081 while (tok != '}') {
5082 decl_designator(t, r, c, NULL, &f, size_only);
5083 /* fill with zero between fields */
5084 index = f->c;
5085 if (!size_only && array_length < index) {
5086 init_putz(t, r, c + array_length,
5087 index - array_length);
5089 index = index + type_size(f->t, &align1);
5090 if (index > array_length)
5091 array_length = index;
5092 if (tok == '}')
5093 break;
5094 skip(',');
5095 f = f->next;
5097 /* put zeros at the end */
5098 if (!size_only && array_length < n) {
5099 init_putz(t, r, c + array_length,
5100 n - array_length);
5102 skip('}');
5103 } else if (tok == '{') {
5104 next();
5105 decl_initializer(t, r, c, first, size_only);
5106 skip('}');
5107 } else if (size_only) {
5108 /* just skip expression */
5109 parlevel = 0;
5110 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
5111 tok != -1) {
5112 if (tok == '(')
5113 parlevel++;
5114 else if (tok == ')')
5115 parlevel--;
5116 next();
5118 } else {
5119 /* currently, we always use constant expression for globals
5120 (may change for scripting case) */
5121 expr_type = EXPR_CONST;
5122 if ((r & VT_VALMASK) == VT_LOCAL)
5123 expr_type = EXPR_ANY;
5124 init_putv(t, r, c, 0, expr_type);
5128 /* parse an initializer for type 't' if 'has_init' is true, and
5129 allocate space in local or global data space ('r' is either
5130 VT_LOCAL or VT_CONST). The allocated address in returned */
5131 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init)
5133 int size, align, addr, tok1, data_offset;
5134 int *init_str, init_len, level, *saved_macro_ptr;
5135 Section *sec;
5137 size = type_size(t, &align);
5138 /* If unknown size, we must evaluate it before
5139 evaluating initializers because
5140 initializers can generate global data too
5141 (e.g. string pointers or ISOC99 compound
5142 literals). It also simplifies local
5143 initializers handling */
5144 init_len = 0;
5145 init_str = NULL;
5146 saved_macro_ptr = NULL; /* avoid warning */
5147 tok1 = 0;
5148 if (size < 0) {
5149 if (!has_init)
5150 error("unknown type size");
5151 /* get all init string */
5152 level = 0;
5153 while (level > 0 || (tok != ',' && tok != ';')) {
5154 if (tok < 0)
5155 error("unexpected end of file in initializer");
5156 tok_add2(&init_str, &init_len, tok, &tokc);
5157 if (tok == '{')
5158 level++;
5159 else if (tok == '}') {
5160 if (level == 0)
5161 break;
5162 level--;
5164 next();
5166 tok1 = tok;
5167 tok_add(&init_str, &init_len, -1);
5168 tok_add(&init_str, &init_len, 0);
5170 /* compute size */
5171 saved_macro_ptr = macro_ptr;
5172 macro_ptr = init_str;
5173 next();
5174 decl_initializer(t, r, 0, 1, 1);
5175 /* prepare second initializer parsing */
5176 macro_ptr = init_str;
5177 next();
5179 /* if still unknown size, error */
5180 size = type_size(t, &align);
5181 if (size < 0)
5182 error("unknown type size");
5184 /* take into account specified alignment if bigger */
5185 if (ad->aligned > align)
5186 align = ad->aligned;
5187 if ((r & VT_VALMASK) == VT_LOCAL) {
5188 loc = (loc - size) & -align;
5189 addr = loc;
5190 } else {
5191 /* compute section */
5192 sec = ad->section;
5193 if (!sec) {
5194 if (has_init)
5195 sec = data_section;
5196 else
5197 sec = bss_section;
5199 data_offset = (int)sec->data_ptr;
5200 data_offset = (data_offset + align - 1) & -align;
5201 addr = data_offset;
5202 /* very important to increment global
5203 pointer at this time because
5204 initializers themselves can create new
5205 initializers */
5206 data_offset += size;
5207 /* handles bounds */
5208 if (do_bounds_check) {
5209 int *bounds_ptr;
5210 /* first, we need to add at least one byte between each region */
5211 data_offset++;
5212 /* then add global data info */
5213 bounds_ptr = (int *)bounds_section->data_ptr;
5214 *bounds_ptr++ = addr;
5215 *bounds_ptr++ = size;
5216 bounds_section->data_ptr = (unsigned char *)bounds_ptr;
5218 sec->data_ptr = (unsigned char *)data_offset;
5220 if (has_init) {
5221 decl_initializer(t, r, addr, 1, 0);
5222 /* restore parse state if needed */
5223 if (init_str) {
5224 free(init_str);
5225 macro_ptr = saved_macro_ptr;
5226 tok = tok1;
5229 return addr;
5232 void put_func_debug(int t)
5234 int bind;
5235 char buf[512];
5237 if (t & VT_STATIC)
5238 bind = STB_LOCAL;
5239 else
5240 bind = STB_GLOBAL;
5241 put_elf_sym(symtab_section, ind, 0,
5242 ELF32_ST_INFO(bind, STT_FUNC), 0,
5243 cur_text_section->sh_num, funcname);
5244 /* stabs info */
5245 /* XXX: we put here a dummy type */
5246 snprintf(buf, sizeof(buf), "%s:%c1",
5247 funcname, t & VT_STATIC ? 'f' : 'F');
5248 put_stabs(buf, N_FUN, 0, line_num, ind);
5249 func_ind = ind;
5250 last_ind = 0;
5251 last_line_num = 0;
5254 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5255 void decl(int l)
5257 int t, b, v, addr, has_init, r;
5258 Sym *sym;
5259 AttributeDef ad;
5261 while (1) {
5262 if (!parse_btype(&b, &ad)) {
5263 /* skip redundant ';' */
5264 /* XXX: find more elegant solution */
5265 if (tok == ';') {
5266 next();
5267 continue;
5269 /* special test for old K&R protos without explicit int
5270 type. Only accepted when defining global data */
5271 if (l == VT_LOCAL || tok < TOK_DEFINE)
5272 break;
5273 b = VT_INT;
5275 if (((b & VT_BTYPE) == VT_ENUM ||
5276 (b & VT_BTYPE) == VT_STRUCT) &&
5277 tok == ';') {
5278 /* we accept no variable after */
5279 next();
5280 continue;
5282 while (1) { /* iterate thru each declaration */
5283 t = type_decl(&v, b, TYPE_DIRECT);
5284 /* currently, we do not parse attribute in
5285 type_decl(). May change if needed */
5286 if (tok == TOK___ATTRIBUTE__)
5287 parse_attribute(&ad);
5288 #if 0
5290 char buf[500];
5291 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
5292 printf("type = '%s'\n", buf);
5294 #endif
5295 if (tok == '{') {
5296 if (l == VT_LOCAL)
5297 error("cannot use local functions");
5298 if (!(t & VT_FUNC))
5299 expect("function definition");
5300 /* compute text section */
5301 cur_text_section = ad.section;
5302 if (!cur_text_section)
5303 cur_text_section = text_section;
5304 ind = (int)cur_text_section->data_ptr;
5305 /* patch forward references */
5306 if ((sym = sym_find(v)) && (sym->r & VT_FORWARD)) {
5307 greloc_patch(sym, ind);
5308 sym->t = t;
5309 } else {
5310 /* put function address */
5311 sym = sym_push1(&global_stack, v, t, ind);
5313 sym->r = VT_CONST;
5314 funcname = get_tok_str(v, NULL);
5315 /* put debug symbol */
5316 if (do_debug)
5317 put_func_debug(t);
5318 /* push a dummy symbol to enable local sym storage */
5319 sym_push1(&local_stack, 0, 0, 0);
5320 gfunc_prolog(t);
5321 loc = 0;
5322 rsym = 0;
5323 block(NULL, NULL, NULL, NULL, 0);
5324 gsym(rsym);
5325 gfunc_epilog();
5326 cur_text_section->data_ptr = (unsigned char *)ind;
5327 sym_pop(&label_stack, NULL); /* reset label stack */
5328 sym_pop(&local_stack, NULL); /* reset local stack */
5329 /* end of function */
5330 if (do_debug) {
5331 put_stabn(N_FUN, 0, 0, ind - func_ind);
5333 funcname = ""; /* for safety */
5334 func_vt = VT_VOID; /* for safety */
5335 break;
5336 } else {
5337 if (b & VT_TYPEDEF) {
5338 /* save typedefed type */
5339 /* XXX: test storage specifiers ? */
5340 sym_push(v, t | VT_TYPEDEF, 0, 0);
5341 } else if ((t & VT_BTYPE) == VT_FUNC) {
5342 /* external function definition */
5343 external_sym(v, t, 0);
5344 } else {
5345 /* not lvalue if array */
5346 r = 0;
5347 if (!(t & VT_ARRAY))
5348 r |= VT_LVAL;
5349 if (b & VT_EXTERN) {
5350 /* external variable */
5351 external_sym(v, t, r);
5352 } else {
5353 if (t & VT_STATIC)
5354 r |= VT_CONST;
5355 else
5356 r |= l;
5357 has_init = (tok == '=');
5358 if (has_init)
5359 next();
5360 addr = decl_initializer_alloc(t, &ad, r,
5361 has_init);
5362 if (l == VT_CONST) {
5363 /* global scope: see if already defined */
5364 sym = sym_find(v);
5365 if (!sym)
5366 goto do_def;
5367 if (!is_compatible_types(sym->t, t))
5368 error("incompatible types for redefinition of '%s'",
5369 get_tok_str(v, NULL));
5370 if (!(sym->r & VT_FORWARD))
5371 error("redefinition of '%s'", get_tok_str(v, NULL));
5372 greloc_patch(sym, addr);
5373 } else {
5374 do_def:
5375 sym_push(v, t, r, addr);
5379 if (tok != ',') {
5380 skip(';');
5381 break;
5383 next();
5389 /* put all global symbols in the extern stack and do all the
5390 resolving which can be done without using external symbols from DLLs */
5391 /* XXX: could try to verify types, but would not to save them in
5392 extern_stack too */
5393 void resolve_global_syms(void)
5395 Sym *s, *s1, *ext_sym;
5396 Reloc **p;
5398 s = global_stack.top;
5399 while (s != NULL) {
5400 s1 = s->prev;
5401 /* do not save static or typedefed symbols or types */
5402 if (!(s->t & (VT_STATIC | VT_TYPEDEF)) &&
5403 !(s->v & (SYM_FIELD | SYM_STRUCT)) &&
5404 (s->v < SYM_FIRST_ANOM)) {
5405 ext_sym = sym_find1(&extern_stack, s->v);
5406 if (!ext_sym) {
5407 /* if the symbol do not exist, we simply save it */
5408 ext_sym = sym_push1(&extern_stack, s->v, s->t, s->c);
5409 ext_sym->r = s->r;
5410 } else if (ext_sym->r & VT_FORWARD) {
5411 /* external symbol already exists, but only as forward
5412 definition */
5413 if (!(s->r & VT_FORWARD)) {
5414 /* s is not forward, so we can relocate all symbols */
5415 greloc_patch(ext_sym, s->c);
5416 } else {
5417 /* the two symbols are forward: merge them */
5418 p = (Reloc **)&ext_sym->c;
5419 while (*p != NULL)
5420 p = &(*p)->next;
5421 *p = (Reloc *)s->c;
5423 } else {
5424 /* external symbol already exists and is defined :
5425 patch all references to it */
5426 if (!(s->r & VT_FORWARD))
5427 error("'%s' defined twice", get_tok_str(s->v, NULL));
5428 greloc_patch(s, ext_sym->c);
5431 s = s1;
5435 /* compile a C file. Return non zero if errors. */
5436 int tcc_compile_file(const char *filename1)
5438 Sym *define_start;
5439 char buf[512];
5441 line_num = 1;
5442 funcname = "";
5443 filename = (char *)filename1;
5445 file = fopen(filename, "r");
5446 if (!file)
5447 error("file '%s' not found", filename);
5448 include_stack_ptr = include_stack;
5449 ifdef_stack_ptr = ifdef_stack;
5451 vtop = vstack - 1;
5452 anon_sym = SYM_FIRST_ANOM;
5454 /* file info: full path + filename */
5455 if (do_debug) {
5456 getcwd(buf, sizeof(buf));
5457 pstrcat(buf, sizeof(buf), "/");
5458 put_stabs(buf, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5459 put_stabs(filename, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5461 /* define common 'char *' type because it is often used internally
5462 for arrays and struct dereference */
5463 char_pointer_type = mk_pointer(VT_BYTE);
5465 define_start = define_stack.top;
5466 inp();
5467 ch = '\n'; /* needed to parse correctly first preprocessor command */
5468 next();
5469 decl(VT_CONST);
5470 if (tok != -1)
5471 expect("declaration");
5472 fclose(file);
5474 /* end of translation unit info */
5475 if (do_debug) {
5476 put_stabn(N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5479 /* reset define stack, but leave -Dsymbols (may be incorrect if
5480 they are undefined) */
5481 sym_pop(&define_stack, define_start);
5483 resolve_global_syms();
5485 sym_pop(&global_stack, NULL);
5487 return 0;
5490 /* define a symbol. A value can also be provided with the '=' operator */
5491 /* XXX: currently only handles integers and string defines. should use
5492 tcc parser, but would need a custom 'FILE *' */
5493 void define_symbol(const char *sym)
5495 TokenSym *ts;
5496 int *str, len;
5497 CValue cval;
5498 const char *p;
5499 char buf[256];
5501 p = strchr(sym, '=');
5502 if (!p) {
5503 pstrcpy(buf, sizeof(buf), sym);
5504 p = "1";
5505 } else {
5506 len = p - sym;
5507 if (len > sizeof(buf) - 1)
5508 len = sizeof(buf) - 1;
5509 memcpy(buf, sym, len);
5510 buf[len] = '\0';
5511 p++;
5514 ts = tok_alloc(buf, 0);
5515 str = NULL;
5516 len = 0;
5517 if (isnum(*p)) {
5518 /* integer case */
5519 cval.i = atoi(p);
5520 tok_add2(&str, &len, TOK_CINT, &cval);
5521 } else {
5522 /* string case */
5523 cval.ts = tok_alloc(p, 0);
5524 tok_add2(&str, &len, TOK_STR, &cval);
5526 tok_add(&str, &len, 0);
5527 sym_push1(&define_stack, ts->tok, MACRO_OBJ, (int)str);
5530 void undef_symbol(const char *sym)
5532 TokenSym *ts;
5533 Sym *s;
5534 printf("undef %s\n", sym);
5535 ts = tok_alloc(sym, 0);
5536 s = sym_find1(&define_stack, tok);
5537 /* undefine symbol by putting an invalid name */
5538 if (s)
5539 sym_undef(&define_stack, s);
5542 /* open a dynamic library so that its symbol are available for
5543 compiled programs */
5544 void open_dll(char *libname)
5546 char buf[1024];
5547 void *h;
5549 snprintf(buf, sizeof(buf), "lib%s.so", libname);
5550 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
5551 if (!h)
5552 error((char *)dlerror());
5555 static void *resolve_sym(const char *sym)
5557 void *ptr;
5558 if (do_bounds_check) {
5559 ptr = bound_resolve_sym(sym);
5560 if (ptr)
5561 return ptr;
5563 return dlsym(NULL, sym);
5566 void resolve_extern_syms(void)
5568 Sym *s, *s1;
5569 char *str;
5570 int addr;
5572 s = extern_stack.top;
5573 while (s != NULL) {
5574 s1 = s->prev;
5575 if (s->r & VT_FORWARD) {
5576 /* if there is at least one relocation to do, then find it
5577 and patch it */
5578 if (s->c) {
5579 str = get_tok_str(s->v, NULL);
5580 addr = (int)resolve_sym(str);
5581 if (!addr)
5582 error("unresolved external reference '%s'", str);
5583 greloc_patch(s, addr);
5586 s = s1;
5590 static int put_elf_str(Section *s, const char *sym)
5592 int c, offset;
5593 offset = s->data_ptr - s->data;
5594 for(;;) {
5595 c = *sym++;
5596 *s->data_ptr++ = c;
5597 if (c == '\0')
5598 break;
5600 return offset;
5603 static void put_elf_sym(Section *s,
5604 unsigned long value, unsigned long size,
5605 int info, int other, int shndx, const char *name)
5607 int name_offset;
5608 Elf32_Sym *sym;
5610 sym = (Elf32_Sym *)s->data_ptr;
5611 if (name)
5612 name_offset = put_elf_str(s->link, name);
5613 else
5614 name_offset = 0;
5615 sym->st_name = name_offset;
5616 sym->st_value = value;
5617 sym->st_size = size;
5618 sym->st_info = info;
5619 sym->st_other = other;
5620 sym->st_shndx = shndx;
5621 s->data_ptr += sizeof(Elf32_Sym);
5624 /* put stab debug information */
5626 typedef struct {
5627 unsigned long n_strx; /* index into string table of name */
5628 unsigned char n_type; /* type of symbol */
5629 unsigned char n_other; /* misc info (usually empty) */
5630 unsigned short n_desc; /* description field */
5631 unsigned long n_value; /* value of symbol */
5632 } Stab_Sym;
5634 static void put_stabs(const char *str, int type, int other, int desc, int value)
5636 Stab_Sym *sym;
5638 sym = (Stab_Sym *)stab_section->data_ptr;
5639 if (str) {
5640 sym->n_strx = put_elf_str(stabstr_section, str);
5641 } else {
5642 sym->n_strx = 0;
5644 sym->n_type = type;
5645 sym->n_other = other;
5646 sym->n_desc = desc;
5647 sym->n_value = value;
5649 stab_section->data_ptr += sizeof(Stab_Sym);
5652 static void put_stabn(int type, int other, int desc, int value)
5654 put_stabs(NULL, type, other, desc, value);
5657 static void put_stabd(int type, int other, int desc)
5659 put_stabs(NULL, type, other, desc, 0);
5662 /* output an ELF file (currently, only for testing) */
5663 void build_exe(char *filename)
5665 Elf32_Ehdr ehdr;
5666 FILE *f;
5667 int shnum, i, phnum, file_offset, offset, size, j;
5668 Section *sec, *strsec;
5669 Elf32_Shdr *shdr, *sh;
5670 Elf32_Phdr *phdr, *ph;
5672 memset(&ehdr, 0, sizeof(ehdr));
5674 /* we add a section for symbols */
5675 strsec = new_section(".shstrtab", SHT_STRTAB, 0);
5676 put_elf_str(strsec, "");
5678 /* count number of sections and compute number of program segments */
5679 shnum = 1; /* section index zero is reserved */
5680 phnum = 0;
5681 for(sec = first_section; sec != NULL; sec = sec->next) {
5682 shnum++;
5683 if (sec->sh_flags & SHF_ALLOC)
5684 phnum++;
5686 /* allocate section headers */
5687 shdr = malloc(shnum * sizeof(Elf32_Shdr));
5688 if (!shdr)
5689 error("memory full");
5690 memset(shdr, 0, shnum * sizeof(Elf32_Shdr));
5691 /* allocate program segment headers */
5692 phdr = malloc(phnum * sizeof(Elf32_Phdr));
5693 if (!phdr)
5694 error("memory full");
5695 memset(phdr, 0, phnum * sizeof(Elf32_Phdr));
5697 /* XXX: find correct load order */
5698 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
5699 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
5700 sh = &shdr[i];
5701 sh->sh_name = put_elf_str(strsec, sec->name);
5702 sh->sh_type = sec->sh_type;
5703 sh->sh_flags = sec->sh_flags;
5704 sh->sh_entsize = sec->sh_entsize;
5705 if (sec->link)
5706 sh->sh_link = sec->link->sh_num;
5707 if (sh->sh_type == SHT_STRTAB) {
5708 sh->sh_addralign = 1;
5709 } else if (sh->sh_type == SHT_SYMTAB ||
5710 (sh->sh_flags & SHF_ALLOC) == 0) {
5711 sh->sh_addralign = 4;
5712 } else {
5713 sh->sh_addr = (Elf32_Word)sec->data;
5714 sh->sh_addralign = 4096;
5716 sh->sh_size = (Elf32_Word)sec->data_ptr - (Elf32_Word)sec->data;
5717 /* align to section start */
5718 file_offset = (file_offset + sh->sh_addralign - 1) &
5719 ~(sh->sh_addralign - 1);
5720 sh->sh_offset = file_offset;
5721 file_offset += sh->sh_size;
5723 /* build program headers (simplistic - not fully correct) */
5724 j = 0;
5725 for(i=1;i<shnum;i++) {
5726 sh = &shdr[i];
5727 if (sh->sh_type == SHT_PROGBITS &&
5728 (sh->sh_flags & SHF_ALLOC) != 0) {
5729 ph = &phdr[j++];
5730 ph->p_type = PT_LOAD;
5731 ph->p_offset = sh->sh_offset;
5732 ph->p_vaddr = sh->sh_addr;
5733 ph->p_paddr = ph->p_vaddr;
5734 ph->p_filesz = sh->sh_size;
5735 ph->p_memsz = sh->sh_size;
5736 ph->p_flags = PF_R;
5737 if (sh->sh_flags & SHF_WRITE)
5738 ph->p_flags |= PF_W;
5739 if (sh->sh_flags & SHF_EXECINSTR)
5740 ph->p_flags |= PF_X;
5741 ph->p_align = sh->sh_addralign;
5745 /* align to 4 */
5746 file_offset = (file_offset + 3) & -4;
5748 /* fill header */
5749 ehdr.e_ident[0] = ELFMAG0;
5750 ehdr.e_ident[1] = ELFMAG1;
5751 ehdr.e_ident[2] = ELFMAG2;
5752 ehdr.e_ident[3] = ELFMAG3;
5753 ehdr.e_ident[4] = ELFCLASS32;
5754 ehdr.e_ident[5] = ELFDATA2LSB;
5755 ehdr.e_ident[6] = EV_CURRENT;
5756 ehdr.e_type = ET_EXEC;
5757 ehdr.e_machine = EM_386;
5758 ehdr.e_version = EV_CURRENT;
5759 ehdr.e_entry = 0; /* XXX: patch it */
5760 ehdr.e_phoff = sizeof(Elf32_Ehdr);
5761 ehdr.e_shoff = file_offset;
5762 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
5763 ehdr.e_phentsize = sizeof(Elf32_Phdr);
5764 ehdr.e_phnum = phnum;
5765 ehdr.e_shentsize = sizeof(Elf32_Shdr);
5766 ehdr.e_shnum = shnum;
5767 ehdr.e_shstrndx = shnum - 1;
5769 /* write elf file */
5770 f = fopen(filename, "w");
5771 if (!f)
5772 error("could not write '%s'", filename);
5773 fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
5774 fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
5775 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
5776 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
5777 sh = &shdr[i];
5778 while (offset < sh->sh_offset) {
5779 fputc(0, f);
5780 offset++;
5782 size = sec->data_ptr - sec->data;
5783 fwrite(sec->data, 1, size, f);
5784 offset += size;
5786 while (offset < ehdr.e_shoff) {
5787 fputc(0, f);
5788 offset++;
5790 fwrite(shdr, 1, shnum * sizeof(Elf32_Shdr), f);
5791 fclose(f);
5794 /* print the position in the source file of PC value 'pc' by reading
5795 the stabs debug information */
5796 static void rt_printline(unsigned long wanted_pc)
5798 Stab_Sym *sym, *sym_end;
5799 char func_name[128];
5800 unsigned long func_addr, last_pc, pc;
5801 const char *incl_files[INCLUDE_STACK_SIZE];
5802 int incl_index, len, last_line_num, i;
5803 const char *str, *p;
5805 func_name[0] = '\0';
5806 func_addr = 0;
5807 incl_index = 0;
5808 last_pc = 0xffffffff;
5809 last_line_num = 1;
5810 sym = (Stab_Sym *)stab_section->data + 1;
5811 sym_end = (Stab_Sym *)stab_section->data_ptr;
5812 while (sym < sym_end) {
5813 switch(sym->n_type) {
5814 /* function start or end */
5815 case N_FUN:
5816 if (sym->n_strx == 0) {
5817 func_name[0] = '\0';
5818 func_addr = 0;
5819 } else {
5820 str = stabstr_section->data + sym->n_strx;
5821 p = strchr(str, ':');
5822 if (!p) {
5823 pstrcpy(func_name, sizeof(func_name), str);
5824 } else {
5825 len = p - str;
5826 if (len > sizeof(func_name) - 1)
5827 len = sizeof(func_name) - 1;
5828 memcpy(func_name, str, len);
5829 func_name[len] = '\0';
5831 func_addr = sym->n_value;
5833 break;
5834 /* line number info */
5835 case N_SLINE:
5836 pc = sym->n_value + func_addr;
5837 if (wanted_pc >= last_pc && wanted_pc < pc)
5838 goto found;
5839 last_pc = pc;
5840 last_line_num = sym->n_desc;
5841 break;
5842 /* include files */
5843 case N_BINCL:
5844 str = stabstr_section->data + sym->n_strx;
5845 add_incl:
5846 if (incl_index < INCLUDE_STACK_SIZE) {
5847 incl_files[incl_index++] = str;
5849 break;
5850 case N_EINCL:
5851 if (incl_index > 1)
5852 incl_index--;
5853 break;
5854 case N_SO:
5855 if (sym->n_strx == 0) {
5856 incl_index = 0; /* end of translation unit */
5857 } else {
5858 str = stabstr_section->data + sym->n_strx;
5859 /* do not add path */
5860 len = strlen(str);
5861 if (len > 0 && str[len - 1] != '/')
5862 goto add_incl;
5864 break;
5866 sym++;
5868 /* did not find line number info: */
5869 fprintf(stderr, "(no debug info, pc=0x%08lx) ", wanted_pc);
5870 return;
5871 found:
5872 for(i = 0; i < incl_index - 1; i++)
5873 fprintf(stderr, "In file included from %s\n",
5874 incl_files[i]);
5875 if (incl_index > 0) {
5876 fprintf(stderr, "%s:%d: ",
5877 incl_files[incl_index - 1], last_line_num);
5879 if (func_name[0] != '\0') {
5880 fprintf(stderr, "in function '%s()': ", func_name);
5885 /* signal handler for fatal errors */
5886 static void sig_error(int signum, siginfo_t *siginf, void *puc)
5888 struct ucontext *uc = puc;
5889 unsigned long pc;
5891 #ifdef __i386__
5892 pc = uc->uc_mcontext.gregs[14];
5893 #else
5894 #error please put the right sigcontext field
5895 #endif
5897 rt_printline(pc);
5899 switch(signum) {
5900 case SIGFPE:
5901 switch(siginf->si_code) {
5902 case FPE_INTDIV:
5903 case FPE_FLTDIV:
5904 fprintf(stderr, "division by zero\n");
5905 break;
5906 default:
5907 fprintf(stderr, "floating point exception\n");
5908 break;
5910 break;
5911 case SIGBUS:
5912 case SIGSEGV:
5913 fprintf(stderr, "dereferencing invalid pointer\n");
5914 break;
5915 case SIGILL:
5916 fprintf(stderr, "illegal instruction\n");
5917 break;
5918 case SIGABRT:
5919 fprintf(stderr, "abort() called\n");
5920 break;
5921 default:
5922 fprintf(stderr, "signal %d\n", signum);
5923 break;
5925 exit(255);
5928 /* launch the compiled program with the given arguments */
5929 int launch_exe(int argc, char **argv)
5931 Sym *s;
5932 int (*t)();
5933 struct sigaction sigact;
5935 s = sym_find1(&extern_stack, TOK_MAIN);
5936 if (!s || (s->r & VT_FORWARD))
5937 error("main() not defined");
5939 if (do_debug) {
5940 /* install TCC signal handlers to print debug info on fatal
5941 runtime errors */
5942 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
5943 sigact.sa_sigaction = sig_error;
5944 sigemptyset(&sigact.sa_mask);
5945 sigaction(SIGFPE, &sigact, NULL);
5946 sigaction(SIGILL, &sigact, NULL);
5947 sigaction(SIGSEGV, &sigact, NULL);
5948 sigaction(SIGBUS, &sigact, NULL);
5949 sigaction(SIGABRT, &sigact, NULL);
5952 if (do_bounds_check) {
5953 int *p, *p_end;
5954 __bound_init();
5955 /* add all known static regions */
5956 p = (int *)bounds_section->data;
5957 p_end = (int *)bounds_section->data_ptr;
5958 while (p < p_end) {
5959 __bound_new_region((void *)p[0], p[1]);
5960 p += 2;
5964 t = (int (*)())s->c;
5965 return (*t)(argc, argv);
5969 void help(void)
5971 printf("tcc version 0.9.3 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
5972 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
5973 " [-i infile] infile [infile_args...]\n"
5974 "\n"
5975 "-Idir : add include path 'dir'\n"
5976 "-Dsym[=val] : define 'sym' with value 'val'\n"
5977 "-Usym : undefine 'sym'\n"
5978 "-llib : link with dynamic library 'lib'\n"
5979 "-g : generate debug info\n"
5980 "-b : compile with built-in memory and bounds checker (implies -g)\n"
5981 "-i infile : compile infile\n"
5985 int main(int argc, char **argv)
5987 char *p, *r, *outfile;
5988 int optind;
5990 include_paths[0] = "/usr/include";
5991 include_paths[1] = "/usr/lib/tcc";
5992 include_paths[2] = "/usr/local/lib/tcc";
5993 nb_include_paths = 3;
5995 /* add all tokens */
5996 tok_ident = TOK_IDENT;
5997 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";
5998 while (*p) {
5999 r = p;
6000 while (*r++);
6001 tok_alloc(p, r - p - 1);
6002 p = r;
6005 /* standard defines */
6006 define_symbol("__STDC__");
6007 #ifdef __i386__
6008 define_symbol("__i386__");
6009 #endif
6010 /* tiny C specific defines */
6011 define_symbol("__TINYC__");
6013 /* create standard sections */
6014 text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
6015 data_section = new_section(".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6016 /* XXX: should change type to SHT_NOBITS */
6017 bss_section = new_section(".bss", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6019 optind = 1;
6020 outfile = NULL;
6021 while (1) {
6022 if (optind >= argc) {
6023 show_help:
6024 help();
6025 return 1;
6027 r = argv[optind];
6028 if (r[0] != '-')
6029 break;
6030 optind++;
6031 if (r[1] == 'I') {
6032 if (nb_include_paths >= INCLUDE_PATHS_MAX)
6033 error("too many include paths");
6034 include_paths[nb_include_paths++] = r + 2;
6035 } else if (r[1] == 'D') {
6036 define_symbol(r + 2);
6037 } else if (r[1] == 'U') {
6038 undef_symbol(r + 2);
6039 } else if (r[1] == 'l') {
6040 open_dll(r + 2);
6041 } else if (r[1] == 'i') {
6042 if (optind >= argc)
6043 goto show_help;
6044 tcc_compile_file(argv[optind++]);
6045 } else if (r[1] == 'b') {
6046 if (!do_bounds_check) {
6047 do_bounds_check = 1;
6048 /* create bounds section for global data */
6049 bounds_section = new_section(".bounds",
6050 SHT_PROGBITS, SHF_ALLOC);
6051 /* debug is implied */
6052 goto debug_opt;
6054 } else if (r[1] == 'g') {
6055 debug_opt:
6056 if (!do_debug) {
6057 do_debug = 1;
6059 /* stab symbols */
6060 stab_section = new_section(".stab", SHT_PROGBITS, 0);
6061 stab_section->sh_entsize = sizeof(Stab_Sym);
6062 stabstr_section = new_section(".stabstr", SHT_STRTAB, 0);
6063 put_elf_str(stabstr_section, "");
6064 stab_section->link = stabstr_section;
6065 /* put first entry */
6066 put_stabs("", 0, 0, 0, 0);
6068 /* elf symbols */
6069 symtab_section = new_section(".symtab", SHT_SYMTAB, 0);
6070 symtab_section->sh_entsize = sizeof(Elf32_Sym);
6071 strtab_section = new_section(".strtab", SHT_STRTAB, 0);
6072 put_elf_str(strtab_section, "");
6073 symtab_section->link = strtab_section;
6074 put_elf_sym(symtab_section, 0, 0, 0, 0, 0, NULL);
6076 } else if (r[1] == 'o') {
6077 /* currently, only for testing, so not documented */
6078 if (optind >= argc)
6079 goto show_help;
6080 outfile = argv[optind++];
6081 } else {
6082 fprintf(stderr, "invalid option -- '%s'\n", r);
6083 exit(1);
6087 tcc_compile_file(argv[optind]);
6089 resolve_extern_syms();
6091 if (outfile) {
6092 build_exe(outfile);
6093 return 0;
6094 } else {
6095 return launch_exe(argc - optind, argv + optind);