fixed VT_LLOCAL dereferencing
[tinycc.git] / tcc.c
blob5d9623e036cb9da2d3de9b1262bcc99da5285ef1
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <math.h>
26 #include <unistd.h>
27 #include <signal.h>
28 #include <sys/ucontext.h>
29 #include <sys/mman.h>
30 #include <elf.h>
31 #include <stab.h>
32 #include <malloc.h>
33 #ifndef CONFIG_TCC_STATIC
34 #include <dlfcn.h>
35 #endif
37 //#define DEBUG
38 /* preprocessor debug */
39 //#define PP_DEBUG
41 /* amount of virtual memory associate to a section (currently, we do
42 not realloc them) */
43 #define SECTION_VSIZE (1024 * 1024)
45 #define INCLUDE_STACK_SIZE 32
46 #define IFDEF_STACK_SIZE 64
47 #define VSTACK_SIZE 64
48 #define STRING_MAX_SIZE 1024
49 #define INCLUDE_PATHS_MAX 32
51 #define TOK_HASH_SIZE 521
52 #define TOK_ALLOC_INCR 256 /* must be a power of two */
53 #define SYM_HASH_SIZE 263
55 /* token symbol management */
56 typedef struct TokenSym {
57 struct TokenSym *hash_next;
58 int tok; /* token number */
59 int len;
60 char str[1];
61 } TokenSym;
63 /* constant value */
64 typedef union CValue {
65 long double ld;
66 double d;
67 float f;
68 int i;
69 unsigned int ui;
70 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
71 long long ll;
72 unsigned long long ull;
73 struct TokenSym *ts;
74 struct Sym *sym;
75 int tab[1];
76 } CValue;
78 /* value on stack */
79 typedef struct SValue {
80 int t; /* type */
81 unsigned short r; /* register + flags */
82 unsigned short r2; /* second register, used for 'long long'
83 type. If not used, set to VT_CONST */
84 CValue c; /* constant */
85 } SValue;
87 /* symbol management */
88 typedef struct Sym {
89 int v; /* symbol token */
90 int t; /* associated type */
91 int r; /* associated register */
92 int c; /* associated number */
93 struct Sym *next; /* next related symbol */
94 struct Sym *prev; /* prev symbol in stack */
95 struct Sym *hash_next; /* next symbol in hash table */
96 } Sym;
98 typedef struct SymStack {
99 struct Sym *top;
100 struct Sym *hash[SYM_HASH_SIZE];
101 } SymStack;
103 /* relocation entry (currently only used for functions or variables */
104 typedef struct Reloc {
105 int type; /* type of relocation */
106 int addr; /* address of relocation */
107 struct Reloc *next; /* next relocation */
108 } Reloc;
110 #define RELOC_ADDR32 1 /* 32 bits relocation */
111 #define RELOC_REL32 2 /* 32 bits relative relocation */
113 /* section definition */
114 typedef struct Section {
115 char name[64]; /* section name */
116 unsigned char *data; /* section data */
117 unsigned char *data_ptr; /* current data pointer */
118 int sh_num; /* elf section number */
119 int sh_type; /* elf section type */
120 int sh_flags; /* elf section flags */
121 int sh_entsize; /* elf entry size */
122 struct Section *link; /* link to another section */
123 struct Section *next;
124 } Section;
126 /* GNUC attribute definition */
127 typedef struct AttributeDef {
128 int aligned;
129 Section *section;
130 } AttributeDef;
132 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
133 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
134 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
136 #define FUNC_NEW 1 /* ansi function prototype */
137 #define FUNC_OLD 2 /* old function prototype */
138 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
140 /* field 'Sym.t' for macros */
141 #define MACRO_OBJ 0 /* object like macro */
142 #define MACRO_FUNC 1 /* function like macro */
144 /* type_decl() types */
145 #define TYPE_ABSTRACT 1 /* type without variable */
146 #define TYPE_DIRECT 2 /* type with variable */
148 typedef struct {
149 FILE *file;
150 char *filename;
151 int line_num;
152 } IncludeFile;
154 /* parser */
155 FILE *file;
156 int line_num;
157 int ch, ch1, tok, tok1;
158 CValue tokc, tok1c;
160 /* sections */
161 Section *first_section;
162 int section_num;
163 Section *text_section, *data_section, *bss_section; /* predefined sections */
164 Section *cur_text_section; /* current section where function code is
165 generated */
166 Section *bounds_section; /* contains global data bound description */
167 /* debug sections */
168 Section *stab_section, *stabstr_section, *symtab_section, *strtab_section;
170 /* loc : local variable index
171 ind : output code index
172 rsym: return symbol
173 anon_sym: anonymous symbol index
175 int rsym, anon_sym,
176 prog, ind, loc, const_wanted;
177 int global_expr; /* true if compound literals must be allocated
178 globally (used during initializers parsing */
179 int func_vt, func_vc; /* current function return type (used by
180 return instruction) */
181 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
182 int tok_ident;
183 TokenSym **table_ident;
184 TokenSym *hash_ident[TOK_HASH_SIZE];
185 char token_buf[STRING_MAX_SIZE + 1];
186 char *filename, *funcname;
187 /* contains global symbols which remain between each translation unit */
188 SymStack extern_stack;
189 SymStack define_stack, global_stack, local_stack, label_stack;
191 SValue vstack[VSTACK_SIZE], *vtop;
192 int *macro_ptr, *macro_ptr_allocated;
193 IncludeFile include_stack[INCLUDE_STACK_SIZE], *include_stack_ptr;
194 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
195 char *include_paths[INCLUDE_PATHS_MAX];
196 int nb_include_paths;
197 int char_pointer_type;
199 /* compile with debug symbol (and use them if error during execution) */
200 int do_debug = 0;
202 /* compile with built-in memory and bounds checker */
203 int do_bounds_check = 0;
205 /* use GNU C extensions */
206 int gnu_ext = 1;
208 /* use Tiny C extensions */
209 int tcc_ext = 1;
211 /* The current value can be: */
212 #define VT_VALMASK 0x00ff
213 #define VT_CONST 0x00f0 /* constant in vc
214 (must be first non register value) */
215 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
216 #define VT_LOCAL 0x00f2 /* offset on stack */
217 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
218 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
219 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
220 #define VT_LVAL 0x0100 /* var is an lvalue */
221 #define VT_FORWARD 0x0200 /* value is forward reference */
222 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
223 char/short stored in integer registers) */
225 /* types */
226 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
228 #define VT_INT 0 /* integer type */
229 #define VT_BYTE 1 /* signed byte type */
230 #define VT_SHORT 2 /* short type */
231 #define VT_VOID 3 /* void type */
232 #define VT_PTR 4 /* pointer increment */
233 #define VT_ENUM 5 /* enum definition */
234 #define VT_FUNC 6 /* function type */
235 #define VT_STRUCT 7 /* struct/union definition */
236 #define VT_FLOAT 8 /* IEEE float */
237 #define VT_DOUBLE 9 /* IEEE double */
238 #define VT_LDOUBLE 10 /* IEEE long double */
239 #define VT_BOOL 11 /* ISOC99 boolean type */
240 #define VT_LLONG 12 /* 64 bit integer */
241 #define VT_LONG 13 /* long integer (NEVER USED as type, only
242 during parsing) */
243 #define VT_BTYPE 0x000f /* mask for basic type */
244 #define VT_UNSIGNED 0x0010 /* unsigned type */
245 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
246 #define VT_BITFIELD 0x0040 /* bitfield modifier */
248 /* storage */
249 #define VT_EXTERN 0x00000080 /* extern definition */
250 #define VT_STATIC 0x00000100 /* static variable */
251 #define VT_TYPEDEF 0x00000200 /* typedef definition */
253 /* type mask (except storage) */
254 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
256 /* token values */
258 /* warning: the following compare tokens depend on i386 asm code */
259 #define TOK_ULT 0x92
260 #define TOK_UGE 0x93
261 #define TOK_EQ 0x94
262 #define TOK_NE 0x95
263 #define TOK_ULE 0x96
264 #define TOK_UGT 0x97
265 #define TOK_LT 0x9c
266 #define TOK_GE 0x9d
267 #define TOK_LE 0x9e
268 #define TOK_GT 0x9f
270 #define TOK_LAND 0xa0
271 #define TOK_LOR 0xa1
273 #define TOK_DEC 0xa2
274 #define TOK_MID 0xa3 /* inc/dec, to void constant */
275 #define TOK_INC 0xa4
276 #define TOK_UDIV 0xb0 /* unsigned division */
277 #define TOK_UMOD 0xb1 /* unsigned modulo */
278 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
279 #define TOK_CINT 0xb3 /* number in tokc */
280 #define TOK_CCHAR 0xb4 /* char constant in tokc */
281 #define TOK_STR 0xb5 /* pointer to string in tokc */
282 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
283 #define TOK_LCHAR 0xb7
284 #define TOK_LSTR 0xb8
285 #define TOK_CFLOAT 0xb9 /* float constant */
286 #define TOK_CDOUBLE 0xc0 /* double constant */
287 #define TOK_CLDOUBLE 0xc1 /* long double constant */
288 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
289 #define TOK_ADDC1 0xc3 /* add with carry generation */
290 #define TOK_ADDC2 0xc4 /* add with carry use */
291 #define TOK_SUBC1 0xc5 /* add with carry generation */
292 #define TOK_SUBC2 0xc6 /* add with carry use */
293 #define TOK_CUINT 0xc8 /* unsigned int constant */
294 #define TOK_CLLONG 0xc9 /* long long constant */
295 #define TOK_CULLONG 0xca /* unsigned long long constant */
296 #define TOK_ARROW 0xcb
297 #define TOK_DOTS 0xcc /* three dots */
298 #define TOK_SHR 0xcd /* unsigned shift right */
300 #define TOK_SHL 0x01 /* shift left */
301 #define TOK_SAR 0x02 /* signed shift right */
303 /* assignement operators : normal operator or 0x80 */
304 #define TOK_A_MOD 0xa5
305 #define TOK_A_AND 0xa6
306 #define TOK_A_MUL 0xaa
307 #define TOK_A_ADD 0xab
308 #define TOK_A_SUB 0xad
309 #define TOK_A_DIV 0xaf
310 #define TOK_A_XOR 0xde
311 #define TOK_A_OR 0xfc
312 #define TOK_A_SHL 0x81
313 #define TOK_A_SAR 0x82
315 /* all identificators and strings have token above that */
316 #define TOK_IDENT 256
318 enum {
319 TOK_INT = TOK_IDENT,
320 TOK_VOID,
321 TOK_CHAR,
322 TOK_IF,
323 TOK_ELSE,
324 TOK_WHILE,
325 TOK_BREAK,
326 TOK_RETURN,
327 TOK_FOR,
328 TOK_EXTERN,
329 TOK_STATIC,
330 TOK_UNSIGNED,
331 TOK_GOTO,
332 TOK_DO,
333 TOK_CONTINUE,
334 TOK_SWITCH,
335 TOK_CASE,
337 /* ignored types Must have contiguous values */
338 TOK_CONST,
339 TOK_VOLATILE,
340 TOK_LONG,
341 TOK_REGISTER,
342 TOK_SIGNED,
343 TOK_AUTO,
344 TOK_INLINE,
345 TOK_RESTRICT,
347 /* unsupported type */
348 TOK_FLOAT,
349 TOK_DOUBLE,
350 TOK_BOOL,
352 TOK_SHORT,
353 TOK_STRUCT,
354 TOK_UNION,
355 TOK_TYPEDEF,
356 TOK_DEFAULT,
357 TOK_ENUM,
358 TOK_SIZEOF,
359 TOK___ATTRIBUTE__,
361 /* preprocessor only */
362 TOK_UIDENT, /* first "user" ident (not keyword) */
363 TOK_DEFINE = TOK_UIDENT,
364 TOK_INCLUDE,
365 TOK_IFDEF,
366 TOK_IFNDEF,
367 TOK_ELIF,
368 TOK_ENDIF,
369 TOK_DEFINED,
370 TOK_UNDEF,
371 TOK_ERROR,
372 TOK_LINE,
373 TOK___LINE__,
374 TOK___FILE__,
375 TOK___DATE__,
376 TOK___TIME__,
377 TOK___VA_ARGS__,
379 /* special identifiers */
380 TOK___FUNC__,
381 TOK_MAIN,
382 /* attribute identifiers */
383 TOK_SECTION,
384 TOK___SECTION__,
385 TOK_ALIGNED,
386 TOK___ALIGNED__,
387 TOK_UNUSED,
388 TOK___UNUSED__,
391 /* XXX: need to define this to use them in non ISOC99 context */
392 extern float strtof (const char *__nptr, char **__endptr);
393 extern long double strtold (const char *__nptr, char **__endptr);
395 void sum(int l);
396 void next(void);
397 void next_nomacro(void);
398 int expr_const(void);
399 void expr_eq(void);
400 void gexpr(void);
401 void decl(int l);
402 void decl_initializer(int t, int r, int c, int first, int size_only);
403 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init);
404 int gv(int rc);
405 void move_reg(int r, int s);
406 void save_regs(void);
407 void save_reg(int r);
408 void vpop(void);
409 void vswap(void);
410 void vdup(void);
411 int get_reg(int rc);
413 void macro_subst(int **tok_str, int *tok_len,
414 Sym **nested_list, int *macro_str);
415 int save_reg_forced(int r);
416 void gen_op(int op);
417 void force_charshort_cast(int t);
418 void gen_cast(int t);
419 void vstore(void);
420 Sym *sym_find(int v);
421 Sym *sym_push(int v, int t, int r, int c);
423 /* type handling */
424 int type_size(int t, int *a);
425 int pointed_type(int t);
426 int pointed_size(int t);
427 int is_compatible_types(int t1, int t2);
428 int parse_btype(int *type_ptr, AttributeDef *ad);
429 int type_decl(int *v, int t, int td);
431 void error(const char *fmt, ...);
432 void vpushi(int v);
433 void vset(int t, int r, int v);
434 void type_to_str(char *buf, int buf_size,
435 int t, const char *varstr);
437 /* section generation */
438 void greloc(Sym *s, int addr, int type);
439 static int put_elf_str(Section *s, const char *sym);
440 static void put_elf_sym(Section *s,
441 unsigned long value, unsigned long size,
442 int info, int other, int shndx, const char *name);
443 static void put_stabs(const char *str, int type, int other, int desc, int value);
444 static void put_stabn(int type, int other, int desc, int value);
445 static void put_stabd(int type, int other, int desc);
447 /* true if float/double/long double type */
448 static inline int is_float(int t)
450 int bt;
451 bt = t & VT_BTYPE;
452 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
455 #include "bcheck.c"
457 #include "i386-gen.c"
459 #ifdef CONFIG_TCC_STATIC
461 #define RTLD_LAZY 0x001
462 #define RTLD_NOW 0x002
463 #define RTLD_GLOBAL 0x100
465 /* dummy function for profiling */
466 void *dlopen(const char *filename, int flag)
468 return NULL;
471 const char *dlerror(void)
473 return "error";
476 typedef struct TCCSyms {
477 char *str;
478 void *ptr;
479 } TCCSyms;
481 #define TCCSYM(a) { #a, &a, },
483 /* add the symbol you want here if no dynamic linking is done */
484 static TCCSyms tcc_syms[] = {
485 TCCSYM(printf)
486 TCCSYM(fprintf)
487 TCCSYM(fopen)
488 TCCSYM(fclose)
489 { NULL, NULL },
492 void *dlsym(void *handle, char *symbol)
494 TCCSyms *p;
495 p = tcc_syms;
496 while (p->str != NULL) {
497 if (!strcmp(p->str, symbol))
498 return p->ptr;
499 p++;
501 return NULL;
504 #endif
506 /********************************************************/
507 /* runtime library is there */
508 /* XXX: we suppose that the host compiler handles 'long long'. It
509 would not be difficult to suppress this assumption */
511 /* XXX: these functions are defined in libgcc. Should provide a
512 portable code too. */
513 long long __divll(long long a, long long b)
515 return a / b;
518 long long __modll(long long a, long long b)
520 return a % b;
523 unsigned long long __divull(unsigned long long a, unsigned long long b)
525 return a / b;
528 unsigned long long __modull(unsigned long long a, unsigned long long b)
530 return a % b;
533 long long __sardi3(long long a, int b)
535 return a >> b;
538 unsigned long long __shrdi3(unsigned long long a, int b)
540 return a >> b;
543 long long __shldi3(long long a, int b)
545 return a << b;
548 float __ulltof(unsigned long long a)
550 return (float)a;
553 double __ulltod(unsigned long long a)
555 return (double)a;
558 long double __ulltold(unsigned long long a)
560 return (long double)a;
563 unsigned long long __ftoull(float a)
565 return (unsigned long long)a;
568 unsigned long long __dtoull(double a)
570 return (unsigned long long)a;
573 unsigned long long __ldtoull(long double a)
575 return (unsigned long long)a;
579 /********************************************************/
581 /* copy a string and truncate it */
582 char *pstrcpy(char *buf, int buf_size, const char *s)
584 char *q, *q_end;
585 int c;
587 q = buf;
588 q_end = buf + buf_size - 1;
589 while (q < q_end) {
590 c = *s++;
591 if (c == '\0')
592 break;
593 *q++ = c;
595 *q = '\0';
596 return buf;
599 /* strcat and truncate */
600 char *pstrcat(char *buf, int buf_size, const char *s)
602 int len;
603 len = strlen(buf);
604 if (len < buf_size)
605 pstrcpy(buf + len, buf_size - len, s);
606 return buf;
609 Section *new_section(const char *name, int sh_type, int sh_flags)
611 Section *sec, **psec;
612 void *data;
614 sec = malloc(sizeof(Section));
615 if (!sec)
616 error("memory full");
617 memset(sec, 0, sizeof(Section));
618 pstrcpy(sec->name, sizeof(sec->name), name);
619 sec->link = NULL;
620 sec->sh_num = ++section_num;
621 sec->sh_type = sh_type;
622 sec->sh_flags = sh_flags;
623 data = mmap(NULL, SECTION_VSIZE,
624 PROT_EXEC | PROT_READ | PROT_WRITE,
625 MAP_PRIVATE | MAP_ANONYMOUS,
626 -1, 0);
627 if (data == (void *)(-1))
628 error("could not mmap section '%s'", name);
629 sec->data = data;
630 sec->data_ptr = data;
631 psec = &first_section;
632 while (*psec != NULL)
633 psec = &(*psec)->next;
634 sec->next = NULL;
635 *psec = sec;
636 return sec;
639 /* return a reference to a section, and create it if it does not
640 exists */
641 Section *find_section(const char *name)
643 Section *sec;
645 for(sec = first_section; sec != NULL; sec = sec->next) {
646 if (!strcmp(name, sec->name))
647 return sec;
649 /* sections are created as PROGBITS */
650 return new_section(name, SHT_PROGBITS, SHF_ALLOC);
653 /* add a new relocation entry to symbol 's' */
654 void greloc(Sym *s, int addr, int type)
656 Reloc *p;
657 p = malloc(sizeof(Reloc));
658 if (!p)
659 error("memory full");
660 p->type = type;
661 p->addr = addr;
662 p->next = (Reloc *)s->c;
663 s->c = (int)p;
666 /* patch each relocation entry with value 'val' */
667 void greloc_patch(Sym *s, int val)
669 Reloc *p, *p1;
671 p = (Reloc *)s->c;
672 while (p != NULL) {
673 p1 = p->next;
674 greloc_patch1(p, val);
675 free(p);
676 p = p1;
678 s->c = val;
679 s->r &= ~VT_FORWARD;
683 static inline int isid(int c)
685 return (c >= 'a' && c <= 'z') ||
686 (c >= 'A' && c <= 'Z') ||
687 c == '_';
690 static inline int isnum(int c)
692 return c >= '0' && c <= '9';
695 static inline int toup(int c)
697 if (ch >= 'a' && ch <= 'z')
698 return ch - 'a' + 'A';
699 else
700 return ch;
703 void printline(void)
705 IncludeFile *f;
706 for(f = include_stack; f < include_stack_ptr; f++)
707 fprintf(stderr, "In file included from %s:%d:\n",
708 f->filename, f->line_num);
709 fprintf(stderr, "%s:%d: ", filename, line_num);
712 void error(const char *fmt, ...)
714 va_list ap;
715 va_start(ap, fmt);
716 printline();
717 vfprintf(stderr, fmt, ap);
718 fprintf(stderr, "\n");
719 exit(1);
720 va_end(ap);
723 void expect(const char *msg)
725 error("%s expected", msg);
728 void warning(const char *fmt, ...)
730 va_list ap;
732 va_start(ap, fmt);
733 printline();
734 fprintf(stderr, "warning: ");
735 vfprintf(stderr, fmt, ap);
736 fprintf(stderr, "\n");
737 va_end(ap);
740 void skip(int c)
742 if (tok != c)
743 error("'%c' expected", c);
744 next();
747 void test_lvalue(void)
749 if (!(vtop->r & VT_LVAL))
750 expect("lvalue");
753 TokenSym *tok_alloc(const char *str, int len)
755 TokenSym *ts, **pts, **ptable;
756 int h, i;
758 if (len <= 0)
759 len = strlen(str);
760 h = 1;
761 for(i=0;i<len;i++)
762 h = ((h << 8) | (str[i] & 0xff)) % TOK_HASH_SIZE;
764 pts = &hash_ident[h];
765 while (1) {
766 ts = *pts;
767 if (!ts)
768 break;
769 if (ts->len == len && !memcmp(ts->str, str, len))
770 return ts;
771 pts = &(ts->hash_next);
774 if (tok_ident >= SYM_FIRST_ANOM)
775 error("memory full");
777 /* expand token table if needed */
778 i = tok_ident - TOK_IDENT;
779 if ((i % TOK_ALLOC_INCR) == 0) {
780 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
781 if (!ptable)
782 error("memory full");
783 table_ident = ptable;
786 ts = malloc(sizeof(TokenSym) + len);
787 if (!ts)
788 error("memory full");
789 table_ident[i] = ts;
790 ts->tok = tok_ident++;
791 ts->len = len;
792 ts->hash_next = NULL;
793 memcpy(ts->str, str, len + 1);
794 *pts = ts;
795 return ts;
798 void add_char(char **pp, int c)
800 char *p;
801 p = *pp;
802 if (c == '\'' || c == '\"' || c == '\\') {
803 /* XXX: could be more precise if char or string */
804 *p++ = '\\';
806 if (c >= 32 && c <= 126) {
807 *p++ = c;
808 } else {
809 *p++ = '\\';
810 if (c == '\n') {
811 *p++ = 'n';
812 } else {
813 *p++ = '0' + ((c >> 6) & 7);
814 *p++ = '0' + ((c >> 3) & 7);
815 *p++ = '0' + (c & 7);
818 *pp = p;
821 /* XXX: buffer overflow */
822 char *get_tok_str(int v, CValue *cv)
824 static char buf[STRING_MAX_SIZE + 1];
825 TokenSym *ts;
826 char *p;
827 int i;
829 if (v == TOK_CINT || v == TOK_CUINT) {
830 sprintf(buf, "%u", cv->ui);
831 return buf;
832 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
833 p = buf;
834 *p++ = '\'';
835 add_char(&p, cv->i);
836 *p++ = '\'';
837 *p = '\0';
838 return buf;
839 } else if (v == TOK_STR || v == TOK_LSTR) {
840 ts = cv->ts;
841 p = buf;
842 *p++ = '\"';
843 for(i=0;i<ts->len;i++)
844 add_char(&p, ts->str[i]);
845 *p++ = '\"';
846 *p = '\0';
847 return buf;
848 } else if (v < TOK_IDENT) {
849 p = buf;
850 *p++ = v;
851 *p = '\0';
852 return buf;
853 } else if (v < tok_ident) {
854 return table_ident[v - TOK_IDENT]->str;
855 } else {
856 /* should never happen */
857 return NULL;
861 /* push, without hashing */
862 Sym *sym_push2(Sym **ps, int v, int t, int c)
864 Sym *s;
865 s = malloc(sizeof(Sym));
866 if (!s)
867 error("memory full");
868 s->v = v;
869 s->t = t;
870 s->c = c;
871 s->next = NULL;
872 /* add in stack */
873 s->prev = *ps;
874 *ps = s;
875 return s;
878 /* find a symbol and return its associated structure. 's' is the top
879 of the symbol stack */
880 Sym *sym_find2(Sym *s, int v)
882 while (s) {
883 if (s->v == v)
884 return s;
885 s = s->prev;
887 return NULL;
890 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
892 /* find a symbol and return its associated structure. 'st' is the
893 symbol stack */
894 Sym *sym_find1(SymStack *st, int v)
896 Sym *s;
898 s = st->hash[HASH_SYM(v)];
899 while (s) {
900 if (s->v == v)
901 return s;
902 s = s->hash_next;
904 return NULL;
907 Sym *sym_push1(SymStack *st, int v, int t, int c)
909 Sym *s, **ps;
910 s = sym_push2(&st->top, v, t, c);
911 /* add in hash table */
912 if (v) {
913 ps = &st->hash[HASH_SYM(v)];
914 s->hash_next = *ps;
915 *ps = s;
917 return s;
920 /* find a symbol in the right symbol space */
921 Sym *sym_find(int v)
923 Sym *s;
924 s = sym_find1(&local_stack, v);
925 if (!s)
926 s = sym_find1(&global_stack, v);
927 return s;
930 /* push a given symbol on the symbol stack */
931 Sym *sym_push(int v, int t, int r, int c)
933 Sym *s;
934 if (local_stack.top)
935 s = sym_push1(&local_stack, v, t, c);
936 else
937 s = sym_push1(&global_stack, v, t, c);
938 s->r = r;
939 return s;
942 /* pop symbols until top reaches 'b' */
943 void sym_pop(SymStack *st, Sym *b)
945 Sym *s, *ss;
947 s = st->top;
948 while(s != b) {
949 ss = s->prev;
950 /* free hash table entry, except if symbol was freed (only
951 used for #undef symbols) */
952 if (s->v)
953 st->hash[HASH_SYM(s->v)] = s->hash_next;
954 free(s);
955 s = ss;
957 st->top = b;
960 /* undefined a hashed symbol (used for #undef). Its name is set to
961 zero */
962 void sym_undef(SymStack *st, Sym *s)
964 Sym **ss;
965 ss = &st->hash[HASH_SYM(s->v)];
966 while (*ss != NULL) {
967 if (*ss == s)
968 break;
969 ss = &(*ss)->hash_next;
971 *ss = s->hash_next;
972 s->v = 0;
975 /* no need to put that inline */
976 int handle_eof(void)
978 if (include_stack_ptr == include_stack)
979 return -1;
980 /* add end of include file debug info */
981 if (do_debug) {
982 put_stabd(N_EINCL, 0, 0);
984 /* pop include stack */
985 fclose(file);
986 free(filename);
987 include_stack_ptr--;
988 file = include_stack_ptr->file;
989 filename = include_stack_ptr->filename;
990 line_num = include_stack_ptr->line_num;
991 return 0;
994 /* read next char from current input file */
995 static inline void inp(void)
997 redo:
998 /* faster than fgetc */
999 ch1 = getc_unlocked(file);
1000 if (ch1 == -1) {
1001 if (handle_eof() < 0)
1002 return;
1003 else
1004 goto redo;
1006 if (ch1 == '\n')
1007 line_num++;
1008 // printf("ch1=%c 0x%x\n", ch1, ch1);
1011 /* input with '\\n' handling */
1012 static inline void minp(void)
1014 redo:
1015 ch = ch1;
1016 inp();
1017 if (ch == '\\' && ch1 == '\n') {
1018 inp();
1019 goto redo;
1021 //printf("ch=%c 0x%x\n", ch, ch);
1025 /* same as minp, but also skip comments */
1026 void cinp(void)
1028 int c;
1030 if (ch1 == '/') {
1031 inp();
1032 if (ch1 == '/') {
1033 /* single line C++ comments */
1034 inp();
1035 while (ch1 != '\n' && ch1 != -1)
1036 inp();
1037 inp();
1038 ch = ' '; /* return space */
1039 } else if (ch1 == '*') {
1040 /* C comments */
1041 inp();
1042 while (ch1 != -1) {
1043 c = ch1;
1044 inp();
1045 if (c == '*' && ch1 == '/') {
1046 inp();
1047 ch = ' '; /* return space */
1048 break;
1051 } else {
1052 ch = '/';
1054 } else {
1055 minp();
1059 void skip_spaces(void)
1061 while (ch == ' ' || ch == '\t')
1062 cinp();
1065 /* skip block of text until #else, #elif or #endif. skip also pairs of
1066 #if/#endif */
1067 void preprocess_skip()
1069 int a;
1070 a = 0;
1071 while (1) {
1072 while (ch != '\n') {
1073 if (ch == -1)
1074 expect("#endif");
1075 cinp();
1077 cinp();
1078 skip_spaces();
1079 if (ch == '#') {
1080 cinp();
1081 next_nomacro();
1082 if (a == 0 &&
1083 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1084 break;
1085 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1086 a++;
1087 else if (tok == TOK_ENDIF)
1088 a--;
1093 /* return the number of additionnal 'ints' necessary to store the
1094 token */
1095 static inline int tok_ext_size(int t)
1097 switch(t) {
1098 /* 4 bytes */
1099 case TOK_CINT:
1100 case TOK_CUINT:
1101 case TOK_CCHAR:
1102 case TOK_LCHAR:
1103 case TOK_STR:
1104 case TOK_LSTR:
1105 case TOK_CFLOAT:
1106 return 1;
1107 case TOK_CDOUBLE:
1108 case TOK_CLLONG:
1109 case TOK_CULLONG:
1110 return 2;
1111 case TOK_CLDOUBLE:
1112 return LDOUBLE_SIZE / 4;
1113 default:
1114 return 0;
1118 void tok_add(int **tok_str, int *tok_len, int t)
1120 int len, *str;
1121 len = *tok_len;
1122 str = *tok_str;
1123 if ((len & 63) == 0) {
1124 str = realloc(str, (len + 64) * sizeof(int));
1125 if (!str)
1126 return;
1127 *tok_str = str;
1129 str[len++] = t;
1130 *tok_len = len;
1133 void tok_add2(int **tok_str, int *tok_len, int t, CValue *cv)
1135 int n, i;
1137 tok_add(tok_str, tok_len, t);
1138 n = tok_ext_size(t);
1139 for(i=0;i<n;i++)
1140 tok_add(tok_str, tok_len, cv->tab[i]);
1143 /* get a token from an integer array and increment pointer accordingly */
1144 int tok_get(int **tok_str, CValue *cv)
1146 int *p, t, n, i;
1148 p = *tok_str;
1149 t = *p++;
1150 n = tok_ext_size(t);
1151 for(i=0;i<n;i++)
1152 cv->tab[i] = *p++;
1153 *tok_str = p;
1154 return t;
1157 /* eval an expression for #if/#elif */
1158 int expr_preprocess(void)
1160 int *str, len, c, t;
1162 str = NULL;
1163 len = 0;
1164 while (1) {
1165 skip_spaces();
1166 if (ch == '\n')
1167 break;
1168 next(); /* do macro subst */
1169 if (tok == TOK_DEFINED) {
1170 next_nomacro();
1171 t = tok;
1172 if (t == '(')
1173 next_nomacro();
1174 c = sym_find1(&define_stack, tok) != 0;
1175 if (t == '(')
1176 next_nomacro();
1177 tok = TOK_CINT;
1178 tokc.i = c;
1179 } else if (tok >= TOK_IDENT) {
1180 /* if undefined macro */
1181 tok = TOK_CINT;
1182 tokc.i = 0;
1184 tok_add2(&str, &len, tok, &tokc);
1186 tok_add(&str, &len, -1); /* simulate end of file */
1187 tok_add(&str, &len, 0);
1188 /* now evaluate C constant expression */
1189 macro_ptr = str;
1190 next();
1191 c = expr_const();
1192 macro_ptr = NULL;
1193 free(str);
1194 return c != 0;
1197 #if defined(DEBUG)
1198 void tok_print(int *str)
1200 int t;
1201 CValue cval;
1203 while (1) {
1204 t = tok_get(&str, &cval);
1205 if (!t)
1206 break;
1207 printf(" %s", get_tok_str(t, &cval));
1209 printf("\n");
1211 #endif
1213 void preprocess(void)
1215 int size, i, c, v, t, *str, len;
1216 char buf[1024], *q, *p;
1217 char buf1[1024];
1218 FILE *f;
1219 Sym **ps, *first, *s;
1221 cinp();
1222 next_nomacro();
1223 redo:
1224 if (tok == TOK_DEFINE) {
1225 next_nomacro();
1226 v = tok;
1227 /* XXX: should check if same macro (ANSI) */
1228 first = NULL;
1229 t = MACRO_OBJ;
1230 /* '(' must be just after macro definition for MACRO_FUNC */
1231 if (ch == '(') {
1232 next_nomacro();
1233 next_nomacro();
1234 ps = &first;
1235 while (tok != ')') {
1236 if (tok == TOK_DOTS)
1237 tok = TOK___VA_ARGS__;
1238 s = sym_push1(&define_stack, tok | SYM_FIELD, 0, 0);
1239 *ps = s;
1240 ps = &s->next;
1241 next_nomacro();
1242 if (tok != ',')
1243 break;
1244 next_nomacro();
1246 t = MACRO_FUNC;
1248 str = NULL;
1249 len = 0;
1250 while (1) {
1251 skip_spaces();
1252 if (ch == '\n' || ch == -1)
1253 break;
1254 next_nomacro();
1255 tok_add2(&str, &len, tok, &tokc);
1257 tok_add(&str, &len, 0);
1258 #ifdef PP_DEBUG
1259 printf("define %s %d: ", get_tok_str(v, NULL), t);
1260 tok_print(str);
1261 #endif
1262 s = sym_push1(&define_stack, v, t, (int)str);
1263 s->next = first;
1264 } else if (tok == TOK_UNDEF) {
1265 next_nomacro();
1266 s = sym_find1(&define_stack, tok);
1267 /* undefine symbol by putting an invalid name */
1268 if (s)
1269 sym_undef(&define_stack, s);
1270 } else if (tok == TOK_INCLUDE) {
1271 skip_spaces();
1272 if (ch == '<') {
1273 c = '>';
1274 goto read_name;
1275 } else if (ch == '\"') {
1276 c = ch;
1277 read_name:
1278 minp();
1279 q = buf;
1280 while (ch != c && ch != '\n' && ch != -1) {
1281 if ((q - buf) < sizeof(buf) - 1)
1282 *q++ = ch;
1283 minp();
1285 *q = '\0';
1286 } else {
1287 next();
1288 if (tok != TOK_STR)
1289 error("#include syntax error");
1290 pstrcpy(buf, sizeof(buf), get_tok_str(tok, &tokc));
1291 c = '\"';
1293 /* eat all spaces and comments after include */
1294 /* XXX: slightly incorrect */
1295 while (ch1 != '\n' && ch1 != -1)
1296 inp();
1298 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
1299 error("memory full");
1300 if (c == '\"') {
1301 /* first search in current dir if "header.h" */
1302 size = 0;
1303 p = strrchr(filename, '/');
1304 if (p)
1305 size = p + 1 - filename;
1306 if (size > sizeof(buf1) - 1)
1307 size = sizeof(buf1) - 1;
1308 memcpy(buf1, filename, size);
1309 buf1[size] = '\0';
1310 pstrcat(buf1, sizeof(buf1), buf);
1311 f = fopen(buf1, "r");
1312 if (f)
1313 goto found;
1315 /* now search in standard include path */
1316 for(i=nb_include_paths - 1;i>=0;i--) {
1317 strcpy(buf1, include_paths[i]);
1318 strcat(buf1, "/");
1319 strcat(buf1, buf);
1320 f = fopen(buf1, "r");
1321 if (f)
1322 goto found;
1324 error("include file '%s' not found", buf1);
1325 f = NULL;
1326 found:
1327 /* push current file in stack */
1328 /* XXX: fix current line init */
1329 include_stack_ptr->file = file;
1330 include_stack_ptr->filename = filename;
1331 include_stack_ptr->line_num = line_num;
1332 include_stack_ptr++;
1333 file = f;
1334 filename = strdup(buf1);
1335 line_num = 1;
1336 /* add include file debug info */
1337 if (do_debug) {
1338 put_stabs(filename, N_BINCL, 0, 0, 0);
1340 } else if (tok == TOK_IFNDEF) {
1341 c = 1;
1342 goto do_ifdef;
1343 } else if (tok == TOK_IF) {
1344 c = expr_preprocess();
1345 goto do_if;
1346 } else if (tok == TOK_IFDEF) {
1347 c = 0;
1348 do_ifdef:
1349 next_nomacro();
1350 c = (sym_find1(&define_stack, tok) != 0) ^ c;
1351 do_if:
1352 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
1353 error("memory full");
1354 *ifdef_stack_ptr++ = c;
1355 goto test_skip;
1356 } else if (tok == TOK_ELSE) {
1357 if (ifdef_stack_ptr == ifdef_stack ||
1358 (ifdef_stack_ptr[-1] & 2))
1359 error("#else after #else");
1360 c = (ifdef_stack_ptr[-1] ^= 3);
1361 goto test_skip;
1362 } else if (tok == TOK_ELIF) {
1363 if (ifdef_stack_ptr == ifdef_stack ||
1364 ifdef_stack_ptr[-1] > 1)
1365 error("#elif after #else");
1366 c = expr_preprocess();
1367 ifdef_stack_ptr[-1] = c;
1368 test_skip:
1369 if (!(c & 1)) {
1370 preprocess_skip();
1371 goto redo;
1373 } else if (tok == TOK_ENDIF) {
1374 if (ifdef_stack_ptr == ifdef_stack)
1375 expect("#if");
1376 ifdef_stack_ptr--;
1377 } else if (tok == TOK_LINE) {
1378 next();
1379 if (tok != TOK_CINT)
1380 error("#line");
1381 line_num = tokc.i;
1382 skip_spaces();
1383 if (ch != '\n') {
1384 next();
1385 if (tok != TOK_STR)
1386 error("#line");
1387 /* XXX: potential memory leak */
1388 filename = strdup(get_tok_str(tok, &tokc));
1390 } else if (tok == TOK_ERROR) {
1391 error("#error");
1393 /* ignore other preprocess commands or #! for C scripts */
1394 while (ch != '\n' && ch != -1)
1395 cinp();
1398 /* read a number in base b */
1399 int getn(b)
1401 int n, t;
1402 n = 0;
1403 while (1) {
1404 if (ch >= 'a' && ch <= 'f')
1405 t = ch - 'a' + 10;
1406 else if (ch >= 'A' && ch <= 'F')
1407 t = ch - 'A' + 10;
1408 else if (isnum(ch))
1409 t = ch - '0';
1410 else
1411 break;
1412 if (t < 0 || t >= b)
1413 break;
1414 n = n * b + t;
1415 cinp();
1417 return n;
1420 /* read a character for string or char constant and eval escape codes */
1421 int getq()
1423 int c;
1425 c = ch;
1426 minp();
1427 if (c == '\\') {
1428 if (isnum(ch)) {
1429 /* at most three octal digits */
1430 c = ch - '0';
1431 minp();
1432 if (isnum(ch)) {
1433 c = c * 8 + ch - '0';
1434 minp();
1435 if (isnum(ch)) {
1436 c = c * 8 + ch - '0';
1437 minp();
1440 return c;
1441 } else if (ch == 'x') {
1442 minp();
1443 return getn(16);
1444 } else {
1445 if (ch == 'a')
1446 c = '\a';
1447 else if (ch == 'b')
1448 c = '\b';
1449 else if (ch == 'f')
1450 c = '\f';
1451 else if (ch == 'n')
1452 c = '\n';
1453 else if (ch == 'r')
1454 c = '\r';
1455 else if (ch == 't')
1456 c = '\t';
1457 else if (ch == 'v')
1458 c = '\v';
1459 else if (ch == 'e' && gnu_ext)
1460 c = 27;
1461 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
1462 c = ch;
1463 else
1464 error("invalid escaped char");
1465 minp();
1468 return c;
1471 /* we use 64 bit numbers */
1472 #define BN_SIZE 2
1474 /* bn = (bn << shift) | or_val */
1475 void bn_lshift(unsigned int *bn, int shift, int or_val)
1477 int i;
1478 unsigned int v;
1479 for(i=0;i<BN_SIZE;i++) {
1480 v = bn[i];
1481 bn[i] = (v << shift) | or_val;
1482 or_val = v >> (32 - shift);
1486 void bn_zero(unsigned int *bn)
1488 int i;
1489 for(i=0;i<BN_SIZE;i++) {
1490 bn[i] = 0;
1494 void parse_number(void)
1496 int b, t, shift, frac_bits, s, exp_val;
1497 char *q;
1498 unsigned int bn[BN_SIZE];
1499 double d;
1501 /* number */
1502 q = token_buf;
1503 t = ch;
1504 cinp();
1505 *q++ = t;
1506 b = 10;
1507 if (t == '.') {
1508 /* special dot handling */
1509 if (ch >= '0' && ch <= '9') {
1510 goto float_frac_parse;
1511 } else if (ch == '.') {
1512 cinp();
1513 if (ch != '.')
1514 expect("'.'");
1515 cinp();
1516 tok = TOK_DOTS;
1517 } else {
1518 /* dots */
1519 tok = t;
1521 return;
1522 } else if (t == '0') {
1523 if (ch == 'x' || ch == 'X') {
1524 q--;
1525 cinp();
1526 b = 16;
1527 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1528 q--;
1529 cinp();
1530 b = 2;
1533 /* parse all digits. cannot check octal numbers at this stage
1534 because of floating point constants */
1535 while (1) {
1536 if (ch >= 'a' && ch <= 'f')
1537 t = ch - 'a' + 10;
1538 else if (ch >= 'A' && ch <= 'F')
1539 t = ch - 'A' + 10;
1540 else if (isnum(ch))
1541 t = ch - '0';
1542 else
1543 break;
1544 if (t >= b)
1545 break;
1546 if (q >= token_buf + STRING_MAX_SIZE) {
1547 num_too_long:
1548 error("number too long");
1550 *q++ = ch;
1551 cinp();
1553 if (ch == '.' ||
1554 ((ch == 'e' || ch == 'E') && b == 10) ||
1555 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1556 if (b != 10) {
1557 /* NOTE: strtox should support that for hexa numbers, but
1558 non ISOC99 libcs do not support it, so we prefer to do
1559 it by hand */
1560 /* hexadecimal or binary floats */
1561 /* XXX: handle overflows */
1562 *q = '\0';
1563 if (b == 16)
1564 shift = 4;
1565 else
1566 shift = 2;
1567 bn_zero(bn);
1568 q = token_buf;
1569 while (1) {
1570 t = *q++;
1571 if (t == '\0') {
1572 break;
1573 } else if (t >= 'a') {
1574 t = t - 'a' + 10;
1575 } else if (t >= 'A') {
1576 t = t - 'A' + 10;
1577 } else {
1578 t = t - '0';
1580 bn_lshift(bn, shift, t);
1582 frac_bits = 0;
1583 if (ch == '.') {
1584 cinp();
1585 while (1) {
1586 t = ch;
1587 if (t >= 'a' && t <= 'f') {
1588 t = t - 'a' + 10;
1589 } else if (t >= 'A' && t <= 'F') {
1590 t = t - 'A' + 10;
1591 } else if (t >= '0' && t <= '9') {
1592 t = t - '0';
1593 } else {
1594 break;
1596 if (t >= b)
1597 error("invalid digit");
1598 bn_lshift(bn, shift, t);
1599 frac_bits += shift;
1600 cinp();
1603 if (ch != 'p' && ch != 'P')
1604 error("exponent expected");
1605 cinp();
1606 s = 1;
1607 exp_val = 0;
1608 if (ch == '+') {
1609 cinp();
1610 } else if (ch == '-') {
1611 s = -1;
1612 cinp();
1614 if (ch < '0' || ch > '9')
1615 error("exponent digits expected");
1616 while (ch >= '0' && ch <= '9') {
1617 exp_val = exp_val * 10 + ch - '0';
1618 cinp();
1620 exp_val = exp_val * s;
1622 /* now we can generate the number */
1623 /* XXX: should patch directly float number */
1624 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1625 d = ldexp(d, exp_val - frac_bits);
1626 t = toup(ch);
1627 if (t == 'F') {
1628 cinp();
1629 tok = TOK_CFLOAT;
1630 /* float : should handle overflow */
1631 tokc.f = (float)d;
1632 } else if (t == 'L') {
1633 cinp();
1634 tok = TOK_CLDOUBLE;
1635 /* XXX: not large enough */
1636 tokc.ld = (long double)d;
1637 } else {
1638 tok = TOK_CDOUBLE;
1639 tokc.d = d;
1641 } else {
1642 /* decimal floats */
1643 if (ch == '.') {
1644 if (q >= token_buf + STRING_MAX_SIZE)
1645 goto num_too_long;
1646 *q++ = ch;
1647 cinp();
1648 float_frac_parse:
1649 while (ch >= '0' && ch <= '9') {
1650 if (q >= token_buf + STRING_MAX_SIZE)
1651 goto num_too_long;
1652 *q++ = ch;
1653 cinp();
1656 if (ch == 'e' || ch == 'E') {
1657 if (q >= token_buf + STRING_MAX_SIZE)
1658 goto num_too_long;
1659 *q++ = ch;
1660 cinp();
1661 if (ch == '-' || ch == '+') {
1662 if (q >= token_buf + STRING_MAX_SIZE)
1663 goto num_too_long;
1664 *q++ = ch;
1665 cinp();
1667 if (ch < '0' || ch > '9')
1668 error("exponent digits expected");
1669 while (ch >= '0' && ch <= '9') {
1670 if (q >= token_buf + STRING_MAX_SIZE)
1671 goto num_too_long;
1672 *q++ = ch;
1673 cinp();
1676 *q = '\0';
1677 t = toup(ch);
1678 errno = 0;
1679 if (t == 'F') {
1680 cinp();
1681 tok = TOK_CFLOAT;
1682 tokc.f = strtof(token_buf, NULL);
1683 } else if (t == 'L') {
1684 cinp();
1685 tok = TOK_CLDOUBLE;
1686 tokc.ld = strtold(token_buf, NULL);
1687 } else {
1688 tok = TOK_CDOUBLE;
1689 tokc.d = strtod(token_buf, NULL);
1692 } else {
1693 unsigned long long n, n1;
1694 int lcount;
1696 /* integer number */
1697 *q = '\0';
1698 q = token_buf;
1699 if (b == 10 && *q == '0') {
1700 b = 8;
1701 q++;
1703 n = 0;
1704 while(1) {
1705 t = *q++;
1706 /* no need for checks except for base 10 / 8 errors */
1707 if (t == '\0') {
1708 break;
1709 } else if (t >= 'a') {
1710 t = t - 'a' + 10;
1711 } else if (t >= 'A') {
1712 t = t - 'A' + 10;
1713 } else {
1714 t = t - '0';
1715 if (t >= b)
1716 error("invalid digit");
1718 n1 = n;
1719 n = n * b + t;
1720 /* detect overflow */
1721 if (n < n1)
1722 error("integer constant overflow");
1725 /* XXX: not exactly ANSI compliant */
1726 if ((n & 0xffffffff00000000LL) != 0) {
1727 if ((n >> 63) != 0)
1728 tok = TOK_CULLONG;
1729 else
1730 tok = TOK_CLLONG;
1731 } else if (n > 0x7fffffff) {
1732 tok = TOK_CUINT;
1733 } else {
1734 tok = TOK_CINT;
1736 lcount = 0;
1737 for(;;) {
1738 t = toup(ch);
1739 if (t == 'L') {
1740 if (lcount >= 2)
1741 error("three 'l' in integer constant");
1742 lcount++;
1743 if (lcount == 2) {
1744 if (tok == TOK_CINT)
1745 tok = TOK_CLLONG;
1746 else if (tok == TOK_CUINT)
1747 tok = TOK_CULLONG;
1749 cinp();
1750 } else if (t == 'U') {
1751 if (tok == TOK_CINT)
1752 tok = TOK_CUINT;
1753 else if (tok == TOK_CLLONG)
1754 tok = TOK_CULLONG;
1755 cinp();
1756 } else {
1757 break;
1760 if (tok == TOK_CINT || tok == TOK_CUINT)
1761 tokc.ui = n;
1762 else
1763 tokc.ull = n;
1768 /* return next token without macro substitution */
1769 void next_nomacro1(void)
1771 int b;
1772 char *q;
1773 TokenSym *ts;
1775 /* skip spaces */
1776 while(1) {
1777 while (ch == '\n') {
1778 cinp();
1779 while (ch == ' ' || ch == 9)
1780 cinp();
1781 if (ch == '#') {
1782 /* preprocessor command if # at start of line after
1783 spaces */
1784 preprocess();
1787 if (ch != ' ' && ch != '\t' && ch != '\f')
1788 break;
1789 cinp();
1791 if (isid(ch)) {
1792 q = token_buf;
1793 *q++ = ch;
1794 cinp();
1795 if (q[-1] == 'L') {
1796 if (ch == '\'') {
1797 tok = TOK_LCHAR;
1798 goto char_const;
1800 if (ch == '\"') {
1801 tok = TOK_LSTR;
1802 goto str_const;
1805 while (isid(ch) || isnum(ch)) {
1806 if (q >= token_buf + STRING_MAX_SIZE)
1807 error("ident too long");
1808 *q++ = ch;
1809 cinp();
1811 *q = '\0';
1812 ts = tok_alloc(token_buf, q - token_buf);
1813 tok = ts->tok;
1814 } else if (isnum(ch) || ch == '.') {
1815 parse_number();
1816 } else if (ch == '\'') {
1817 tok = TOK_CCHAR;
1818 char_const:
1819 minp();
1820 tokc.i = getq();
1821 if (ch != '\'')
1822 expect("\'");
1823 minp();
1824 } else if (ch == '\"') {
1825 tok = TOK_STR;
1826 str_const:
1827 minp();
1828 q = token_buf;
1829 while (ch != '\"') {
1830 b = getq();
1831 if (ch == -1)
1832 error("unterminated string");
1833 if (q >= token_buf + STRING_MAX_SIZE)
1834 error("string too long");
1835 *q++ = b;
1837 *q = '\0';
1838 tokc.ts = tok_alloc(token_buf, q - token_buf);
1839 minp();
1840 } else {
1841 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
1842 /* two chars */
1843 tok = ch;
1844 cinp();
1845 while (*q) {
1846 if (*q == tok && q[1] == ch) {
1847 cinp();
1848 tok = q[2] & 0xff;
1849 /* three chars tests */
1850 if (tok == TOK_SHL || tok == TOK_SAR) {
1851 if (ch == '=') {
1852 tok = tok | 0x80;
1853 cinp();
1855 } else if (tok == TOK_DOTS) {
1856 if (ch != '.')
1857 error("parse error");
1858 cinp();
1860 return;
1862 q = q + 3;
1864 /* single char substitutions */
1865 if (tok == '<')
1866 tok = TOK_LT;
1867 else if (tok == '>')
1868 tok = TOK_GT;
1872 /* return next token without macro substitution. Can read input from
1873 macro_ptr buffer */
1874 void next_nomacro()
1876 if (macro_ptr) {
1877 tok = *macro_ptr;
1878 if (tok)
1879 tok = tok_get(&macro_ptr, &tokc);
1880 } else {
1881 next_nomacro1();
1885 /* substitute args in macro_str and return allocated string */
1886 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
1888 int *st, last_tok, t, notfirst, *str, len;
1889 Sym *s;
1890 TokenSym *ts;
1891 CValue cval;
1893 str = NULL;
1894 len = 0;
1895 last_tok = 0;
1896 while(1) {
1897 t = tok_get(&macro_str, &cval);
1898 if (!t)
1899 break;
1900 if (t == '#') {
1901 /* stringize */
1902 t = tok_get(&macro_str, &cval);
1903 if (!t)
1904 break;
1905 s = sym_find2(args, t);
1906 if (s) {
1907 token_buf[0] = '\0';
1908 st = (int *)s->c;
1909 notfirst = 0;
1910 while (*st) {
1911 if (notfirst)
1912 pstrcat(token_buf, sizeof(token_buf), " ");
1913 t = tok_get(&st, &cval);
1914 pstrcat(token_buf, sizeof(token_buf), get_tok_str(t, &cval));
1915 notfirst = 1;
1917 #ifdef PP_DEBUG
1918 printf("stringize: %s\n", token_buf);
1919 #endif
1920 /* add string */
1921 ts = tok_alloc(token_buf, 0);
1922 cval.ts = ts;
1923 tok_add2(&str, &len, TOK_STR, &cval);
1924 } else {
1925 tok_add2(&str, &len, t, &cval);
1927 } else if (t >= TOK_IDENT) {
1928 s = sym_find2(args, t);
1929 if (s) {
1930 st = (int *)s->c;
1931 /* if '##' is present before or after , no arg substitution */
1932 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
1933 while (*st)
1934 tok_add(&str, &len, *st++);
1935 } else {
1936 macro_subst(&str, &len, nested_list, st);
1938 } else {
1939 tok_add(&str, &len, t);
1941 } else {
1942 tok_add2(&str, &len, t, &cval);
1944 last_tok = t;
1946 tok_add(&str, &len, 0);
1947 return str;
1950 /* handle the '##' operator */
1951 int *macro_twosharps(int *macro_str)
1953 TokenSym *ts;
1954 int *macro_str1, macro_str1_len, *macro_ptr1;
1955 int t;
1956 char *p;
1957 CValue cval;
1959 macro_str1 = NULL;
1960 macro_str1_len = 0;
1961 tok = 0;
1962 while (1) {
1963 next_nomacro();
1964 if (tok == 0)
1965 break;
1966 while (*macro_ptr == TOK_TWOSHARPS) {
1967 macro_ptr++;
1968 macro_ptr1 = macro_ptr;
1969 t = *macro_ptr;
1970 if (t) {
1971 t = tok_get(&macro_ptr, &cval);
1972 /* XXX: we handle only most common cases:
1973 ident + ident or ident + number */
1974 if (tok >= TOK_IDENT &&
1975 (t >= TOK_IDENT || t == TOK_CINT)) {
1976 p = get_tok_str(tok, &tokc);
1977 pstrcpy(token_buf, sizeof(token_buf), p);
1978 p = get_tok_str(t, &cval);
1979 pstrcat(token_buf, sizeof(token_buf), p);
1980 ts = tok_alloc(token_buf, 0);
1981 tok = ts->tok; /* modify current token */
1982 } else {
1983 /* cannot merge tokens: skip '##' */
1984 macro_ptr = macro_ptr1;
1985 break;
1989 tok_add2(&macro_str1, &macro_str1_len, tok, &tokc);
1991 tok_add(&macro_str1, &macro_str1_len, 0);
1992 return macro_str1;
1997 /* do macro substitution of macro_str and add result to
1998 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1999 substituted. 'nested_list' is the list of all macros we got inside
2000 to avoid recursing. */
2001 void macro_subst(int **tok_str, int *tok_len,
2002 Sym **nested_list, int *macro_str)
2004 Sym *s, *args, *sa, *sa1;
2005 int *str, parlevel, len, *mstr, t, *saved_macro_ptr;
2006 int mstr_allocated, *macro_str1;
2007 CValue cval;
2009 saved_macro_ptr = macro_ptr;
2010 macro_ptr = macro_str;
2011 macro_str1 = NULL;
2012 if (macro_str) {
2013 /* first scan for '##' operator handling */
2014 macro_str1 = macro_twosharps(macro_str);
2015 macro_ptr = macro_str1;
2018 while (1) {
2019 next_nomacro();
2020 if (tok == 0)
2021 break;
2022 /* special macros */
2023 if (tok == TOK___LINE__) {
2024 cval.i = line_num;
2025 tok_add2(tok_str, tok_len, TOK_CINT, &cval);
2026 } else if (tok == TOK___FILE__) {
2027 cval.ts = tok_alloc(filename, 0);
2028 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2029 } else if (tok == TOK___DATE__) {
2030 cval.ts = tok_alloc("Jan 1 1970", 0);
2031 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2032 } else if (tok == TOK___TIME__) {
2033 cval.ts = tok_alloc("00:00:00", 0);
2034 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2035 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
2036 /* if symbol is a macro, prepare substitution */
2037 /* if nested substitution, do nothing */
2038 if (sym_find2(*nested_list, tok))
2039 goto no_subst;
2040 mstr = (int *)s->c;
2041 mstr_allocated = 0;
2042 if (s->t == MACRO_FUNC) {
2043 /* NOTE: we do not use next_nomacro to avoid eating the
2044 next token. XXX: find better solution */
2045 if (macro_ptr) {
2046 t = *macro_ptr;
2047 } else {
2048 while (ch == ' ' || ch == '\t' || ch == '\n')
2049 cinp();
2050 t = ch;
2052 if (t != '(') /* no macro subst */
2053 goto no_subst;
2055 /* argument macro */
2056 next_nomacro();
2057 next_nomacro();
2058 args = NULL;
2059 sa = s->next;
2060 while (tok != ')' && sa) {
2061 len = 0;
2062 str = NULL;
2063 parlevel = 0;
2064 while ((parlevel > 0 ||
2065 (tok != ')' &&
2066 (tok != ',' ||
2067 sa->v == (TOK___VA_ARGS__ | SYM_FIELD)))) &&
2068 tok != -1) {
2069 if (tok == '(')
2070 parlevel++;
2071 else if (tok == ')')
2072 parlevel--;
2073 tok_add2(&str, &len, tok, &tokc);
2074 next_nomacro();
2076 tok_add(&str, &len, 0);
2077 sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
2078 if (tok != ',')
2079 break;
2080 next_nomacro();
2081 sa = sa->next;
2083 if (tok != ')')
2084 expect(")");
2085 /* now subst each arg */
2086 mstr = macro_arg_subst(nested_list, mstr, args);
2087 /* free memory */
2088 sa = args;
2089 while (sa) {
2090 sa1 = sa->prev;
2091 free((int *)sa->c);
2092 free(sa);
2093 sa = sa1;
2095 mstr_allocated = 1;
2097 sym_push2(nested_list, s->v, 0, 0);
2098 macro_subst(tok_str, tok_len, nested_list, mstr);
2099 /* pop nested defined symbol */
2100 sa1 = *nested_list;
2101 *nested_list = sa1->prev;
2102 free(sa1);
2103 if (mstr_allocated)
2104 free(mstr);
2105 } else {
2106 no_subst:
2107 /* no need to add if reading input stream */
2108 if (!macro_str)
2109 return;
2110 tok_add2(tok_str, tok_len, tok, &tokc);
2112 /* only replace one macro while parsing input stream */
2113 if (!macro_str)
2114 return;
2116 macro_ptr = saved_macro_ptr;
2117 if (macro_str1)
2118 free(macro_str1);
2121 /* return next token with macro substitution */
2122 void next(void)
2124 int len, *ptr;
2125 Sym *nested_list;
2127 /* special 'ungettok' case for label parsing */
2128 if (tok1) {
2129 tok = tok1;
2130 tokc = tok1c;
2131 tok1 = 0;
2132 } else {
2133 redo:
2134 if (!macro_ptr) {
2135 /* if not reading from macro substuted string, then try to substitute */
2136 len = 0;
2137 ptr = NULL;
2138 nested_list = NULL;
2139 macro_subst(&ptr, &len, &nested_list, NULL);
2140 if (ptr) {
2141 tok_add(&ptr, &len, 0);
2142 macro_ptr = ptr;
2143 macro_ptr_allocated = ptr;
2144 goto redo;
2146 if (tok == 0)
2147 goto redo;
2148 } else {
2149 next_nomacro();
2150 if (tok == 0) {
2151 /* end of macro string: free it */
2152 free(macro_ptr_allocated);
2153 macro_ptr = NULL;
2154 goto redo;
2158 #if defined(DEBUG)
2159 printf("token = %s\n", get_tok_str(tok, tokc));
2160 #endif
2163 void swap(int *p, int *q)
2165 int t;
2166 t = *p;
2167 *p = *q;
2168 *q = t;
2171 void vsetc(int t, int r, CValue *vc)
2173 if (vtop >= vstack + VSTACK_SIZE)
2174 error("memory full");
2175 /* cannot let cpu flags if other instruction are generated */
2176 /* XXX: VT_JMP test too ? */
2177 if ((vtop->r & VT_VALMASK) == VT_CMP)
2178 gv(RC_INT);
2179 vtop++;
2180 vtop->t = t;
2181 vtop->r = r;
2182 vtop->r2 = VT_CONST;
2183 vtop->c = *vc;
2186 /* push integer constant */
2187 void vpushi(int v)
2189 CValue cval;
2190 cval.i = v;
2191 vsetc(VT_INT, VT_CONST, &cval);
2194 void vset(int t, int r, int v)
2196 CValue cval;
2198 cval.i = v;
2199 vsetc(t, r, &cval);
2202 void vswap(void)
2204 SValue tmp;
2206 tmp = vtop[0];
2207 vtop[0] = vtop[-1];
2208 vtop[-1] = tmp;
2211 void vpushv(SValue *v)
2213 if (vtop >= vstack + VSTACK_SIZE)
2214 error("memory full");
2215 vtop++;
2216 *vtop = *v;
2219 void vdup(void)
2221 vpushv(vtop);
2224 /* save r to the memory stack, and mark it as being free */
2225 void save_reg(int r)
2227 int l, i, saved, t, size, align;
2228 SValue *p, sv;
2230 /* modify all stack values */
2231 saved = 0;
2232 l = 0;
2233 for(p=vstack;p<=vtop;p++) {
2234 i = p->r & VT_VALMASK;
2235 if ((p->r & VT_VALMASK) == r ||
2236 (p->r2 & VT_VALMASK) == r) {
2237 /* must save value on stack if not already done */
2238 if (!saved) {
2239 /* store register in the stack */
2240 t = p->t;
2241 if (!is_float(t) && (t & VT_BTYPE) != VT_LLONG)
2242 t = VT_INT;
2243 size = type_size(t, &align);
2244 loc = (loc - size) & -align;
2245 sv.t = t;
2246 sv.r = VT_LOCAL | VT_LVAL;
2247 sv.c.ul = loc;
2248 store(r, &sv);
2249 /* XXX: x86 specific: need to pop fp register ST0 if saved */
2250 if (r == REG_ST0) {
2251 o(0xd9dd); /* fstp %st(1) */
2253 /* special long long case */
2254 if ((p->t & VT_BTYPE) == VT_LLONG) {
2255 sv.c.ul += 4;
2256 store(p->r2, &sv);
2258 l = loc;
2259 saved = 1;
2261 /* mark that stack entry as being saved on the stack */
2262 if (p->r & VT_LVAL)
2263 t = VT_LLOCAL;
2264 else
2265 t = VT_LOCAL;
2266 p->r = VT_LVAL | t;
2267 p->r2 = VT_CONST;
2268 p->c.ul = l;
2273 /* find a free register of class 'rc'. If none, save one register */
2274 int get_reg(int rc)
2276 int r;
2277 SValue *p;
2279 /* find a free register */
2280 for(r=0;r<NB_REGS;r++) {
2281 if (reg_classes[r] & rc) {
2282 for(p=vstack;p<=vtop;p++) {
2283 if ((p->r & VT_VALMASK) == r ||
2284 (p->r2 & VT_VALMASK) == r)
2285 goto notfound;
2287 return r;
2289 notfound: ;
2292 /* no register left : free the first one on the stack (VERY
2293 IMPORTANT to start from the bottom to ensure that we don't
2294 spill registers used in gen_opi()) */
2295 for(p=vstack;p<=vtop;p++) {
2296 r = p->r & VT_VALMASK;
2297 if (r < VT_CONST && (reg_classes[r] & rc)) {
2298 save_reg(r);
2299 break;
2302 return r;
2305 void save_regs(void)
2307 int r;
2308 SValue *p;
2310 for(p=vstack;p<=vtop;p++) {
2311 r = p->r & VT_VALMASK;
2312 if (r < VT_CONST) {
2313 save_reg(r);
2318 /* move register 's' to 'r', and flush previous value of r to memory
2319 if needed */
2320 void move_reg(int r, int s)
2322 SValue sv;
2324 if (r != s) {
2325 save_reg(r);
2326 sv.t = VT_INT;
2327 sv.r = s;
2328 sv.c.ul = 0;
2329 load(r, &sv);
2333 /* get address of vtop (vtop MUST BE an lvalue) */
2334 void gaddrof(void)
2336 vtop->r &= ~VT_LVAL;
2337 /* tricky: if saved lvalue, then we can go back to lvalue */
2338 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
2339 vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
2342 /* store vtop a register belonging to class 'rc'. lvalues are
2343 converted to values. Cannot be used if cannot be converted to
2344 register value (such as structures). */
2345 int gv(int rc)
2347 int r, r2, rc2, bit_pos, bit_size, size, align, i, data_offset;
2348 unsigned long long ll;
2350 /* NOTE: get_reg can modify vstack[] */
2351 if (vtop->t & VT_BITFIELD) {
2352 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
2353 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2354 /* remove bit field info to avoid loops */
2355 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2356 /* generate shifts */
2357 vpushi(32 - (bit_pos + bit_size));
2358 gen_op(TOK_SHL);
2359 vpushi(32 - bit_size);
2360 /* NOTE: transformed to SHR if unsigned */
2361 gen_op(TOK_SAR);
2362 r = gv(rc);
2363 } else {
2364 if (is_float(vtop->t) &&
2365 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2366 /* CPUs usually cannot use float constants, so we store them
2367 generically in data segment */
2368 size = type_size(vtop->t, &align);
2369 data_offset = (int)data_section->data_ptr;
2370 data_offset = (data_offset + align - 1) & -align;
2371 /* XXX: not portable yet */
2372 size = size >> 2;
2373 for(i=0;i<size;i++)
2374 ((int *)data_offset)[i] = vtop->c.tab[i];
2375 vtop->r |= VT_LVAL;
2376 vtop->c.ul = data_offset;
2377 data_offset += size << 2;
2378 data_section->data_ptr = (unsigned char *)data_offset;
2380 r = vtop->r & VT_VALMASK;
2381 /* need to reload if:
2382 - constant
2383 - lvalue (need to dereference pointer)
2384 - already a register, but not in the right class */
2385 if (r >= VT_CONST ||
2386 (vtop->r & VT_LVAL) ||
2387 !(reg_classes[r] & rc) ||
2388 ((vtop->t & VT_BTYPE) == VT_LLONG &&
2389 !(reg_classes[vtop->r2] & rc))) {
2390 r = get_reg(rc);
2391 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
2392 /* two register type load : expand to two words
2393 temporarily */
2394 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2395 /* load constant */
2396 ll = vtop->c.ull;
2397 vtop->c.ui = ll; /* first word */
2398 load(r, vtop);
2399 vtop->r = r; /* save register value */
2400 vpushi(ll >> 32); /* second word */
2401 } else if (r >= VT_CONST ||
2402 (vtop->r & VT_LVAL)) {
2403 /* load from memory */
2404 load(r, vtop);
2405 vdup();
2406 vtop[-1].r = r; /* save register value */
2407 /* increment pointer to get second word */
2408 vtop->t = VT_INT;
2409 gaddrof();
2410 vpushi(4);
2411 gen_op('+');
2412 vtop->r |= VT_LVAL;
2413 } else {
2414 /* move registers */
2415 load(r, vtop);
2416 vdup();
2417 vtop[-1].r = r; /* save register value */
2418 vtop->r = vtop[-1].r2;
2420 /* allocate second register */
2421 rc2 = RC_INT;
2422 if (rc == RC_IRET)
2423 rc2 = RC_LRET;
2424 r2 = get_reg(rc2);
2425 load(r2, vtop);
2426 vpop();
2427 /* write second register */
2428 vtop->r2 = r2;
2429 } else {
2430 /* one register type load */
2431 load(r, vtop);
2434 vtop->r = r;
2436 return r;
2439 /* expand long long on stack in two int registers */
2440 void lexpand(void)
2442 int u;
2444 u = vtop->t & VT_UNSIGNED;
2445 gv(RC_INT);
2446 vdup();
2447 vtop[0].r = vtop[-1].r2;
2448 vtop[0].r2 = VT_CONST;
2449 vtop[-1].r2 = VT_CONST;
2450 vtop[0].t = VT_INT | u;
2451 vtop[-1].t = VT_INT | u;
2454 /* build a long long from two ints */
2455 void lbuild(int t)
2457 vswap();
2458 gv(RC_INT);
2459 vswap();
2460 gv(RC_INT);
2461 vtop[-1].r2 = vtop[0].r;
2462 vtop[-1].t = t;
2463 vpop();
2466 /* rotate n first stack elements to the bottom */
2467 void vrotb(int n)
2469 int i;
2470 SValue tmp;
2472 tmp = vtop[-n + 1];
2473 for(i=-n+1;i!=0;i++)
2474 vtop[i] = vtop[i+1];
2475 vtop[0] = tmp;
2478 /* pop stack value */
2479 void vpop(void)
2481 /* for x86, we need to pop the FP stack */
2482 if ((vtop->r & VT_VALMASK) == REG_ST0) {
2483 o(0xd9dd); /* fstp %st(1) */
2485 vtop--;
2488 /* convert stack entry to register and duplicate its value in another
2489 register */
2490 void gv_dup(void)
2492 int rc, t, r, r1;
2493 SValue sv;
2495 t = vtop->t;
2496 if ((t & VT_BTYPE) == VT_LLONG) {
2497 lexpand();
2498 gv_dup();
2499 vswap();
2500 vrotb(3);
2501 gv_dup();
2502 vrotb(4);
2503 /* stack: H L L1 H1 */
2504 lbuild(t);
2505 vrotb(3);
2506 vrotb(3);
2507 vswap();
2508 lbuild(t);
2509 vswap();
2510 } else {
2511 /* duplicate value */
2512 rc = RC_INT;
2513 sv.t = VT_INT;
2514 if (is_float(t)) {
2515 rc = RC_FLOAT;
2516 sv.t = t;
2518 r = gv(rc);
2519 r1 = get_reg(rc);
2520 sv.r = r;
2521 sv.c.ul = 0;
2522 load(r1, &sv); /* move r to r1 */
2523 vdup();
2524 /* duplicates value */
2525 vtop->r = r1;
2529 /* generate CPU independent (unsigned) long long operations */
2530 void gen_opl(int op)
2532 int t, a, b, op1, c, i;
2533 void *func;
2534 GFuncContext gf;
2535 SValue tmp;
2537 switch(op) {
2538 case '/':
2539 case TOK_PDIV:
2540 func = __divll;
2541 goto gen_func;
2542 case TOK_UDIV:
2543 func = __divull;
2544 goto gen_func;
2545 case '%':
2546 func = __modll;
2547 goto gen_func;
2548 case TOK_UMOD:
2549 func = __modull;
2550 gen_func:
2551 /* call generic long long function */
2552 gfunc_start(&gf);
2553 gfunc_param(&gf);
2554 gfunc_param(&gf);
2555 vpushi((int)func);
2556 gfunc_call(&gf);
2557 vpushi(0);
2558 vtop->r = REG_IRET;
2559 vtop->r2 = REG_LRET;
2560 break;
2561 case '^':
2562 case '&':
2563 case '|':
2564 case '*':
2565 case '+':
2566 case '-':
2567 t = vtop->t;
2568 vswap();
2569 lexpand();
2570 vrotb(3);
2571 lexpand();
2572 /* stack: L1 H1 L2 H2 */
2573 tmp = vtop[0];
2574 vtop[0] = vtop[-3];
2575 vtop[-3] = tmp;
2576 tmp = vtop[-2];
2577 vtop[-2] = vtop[-3];
2578 vtop[-3] = tmp;
2579 vswap();
2580 /* stack: H1 H2 L1 L2 */
2581 if (op == '*') {
2582 vpushv(vtop - 1);
2583 vpushv(vtop - 1);
2584 gen_op(TOK_UMULL);
2585 lexpand();
2586 /* stack: H1 H2 L1 L2 ML MH */
2587 for(i=0;i<4;i++)
2588 vrotb(6);
2589 /* stack: ML MH H1 H2 L1 L2 */
2590 tmp = vtop[0];
2591 vtop[0] = vtop[-2];
2592 vtop[-2] = tmp;
2593 /* stack: ML MH H1 L2 H2 L1 */
2594 gen_op('*');
2595 vrotb(3);
2596 vrotb(3);
2597 gen_op('*');
2598 /* stack: ML MH M1 M2 */
2599 gen_op('+');
2600 gen_op('+');
2601 } else if (op == '+' || op == '-') {
2602 /* XXX: add non carry method too (for MIPS ?) */
2603 if (op == '+')
2604 op1 = TOK_ADDC1;
2605 else
2606 op1 = TOK_SUBC1;
2607 gen_op(op1);
2608 /* stack: H1 H2 (L1 op L2) */
2609 vrotb(3);
2610 vrotb(3);
2611 gen_op(op1 + 1); /* TOK_xxxC2 */
2612 } else {
2613 gen_op(op);
2614 /* stack: H1 H2 (L1 op L2) */
2615 vrotb(3);
2616 vrotb(3);
2617 /* stack: (L1 op L2) H1 H2 */
2618 gen_op(op);
2619 /* stack: (L1 op L2) (H1 op H2) */
2621 /* stack: L H */
2622 lbuild(t);
2623 break;
2624 case TOK_SAR:
2625 case TOK_SHR:
2626 case TOK_SHL:
2627 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
2628 t = vtop[-1].t;
2629 vswap();
2630 lexpand();
2631 vrotb(3);
2632 /* stack: L H shift */
2633 c = (int)vtop->c.i;
2634 /* constant: simpler */
2635 /* NOTE: all comments are for SHL. the other cases are
2636 done by swaping words */
2637 vpop();
2638 if (op != TOK_SHL)
2639 vswap();
2640 if (c >= 32) {
2641 /* stack: L H */
2642 vpop();
2643 if (c > 32) {
2644 vpushi(c - 32);
2645 gen_op(op);
2647 if (op != TOK_SAR) {
2648 vpushi(0);
2649 } else {
2650 gv_dup();
2651 vpushi(31);
2652 gen_op(TOK_SAR);
2654 vswap();
2655 } else {
2656 vswap();
2657 gv_dup();
2658 /* stack: H L L */
2659 vpushi(c);
2660 gen_op(op);
2661 vswap();
2662 vpushi(32 - c);
2663 if (op == TOK_SHL)
2664 gen_op(TOK_SHR);
2665 else
2666 gen_op(TOK_SHL);
2667 vrotb(3);
2668 /* stack: L L H */
2669 vpushi(c);
2670 gen_op(op);
2671 gen_op('|');
2673 if (op != TOK_SHL)
2674 vswap();
2675 lbuild(t);
2676 } else {
2677 /* XXX: should provide a faster fallback on x86 ? */
2678 switch(op) {
2679 case TOK_SAR:
2680 func = __sardi3;
2681 goto gen_func;
2682 case TOK_SHR:
2683 func = __shrdi3;
2684 goto gen_func;
2685 case TOK_SHL:
2686 func = __shldi3;
2687 goto gen_func;
2690 break;
2691 default:
2692 /* compare operations */
2693 t = vtop->t;
2694 vswap();
2695 lexpand();
2696 vrotb(3);
2697 lexpand();
2698 /* stack: L1 H1 L2 H2 */
2699 tmp = vtop[-1];
2700 vtop[-1] = vtop[-2];
2701 vtop[-2] = tmp;
2702 /* stack: L1 L2 H1 H2 */
2703 /* compare high */
2704 op1 = op;
2705 /* when values are equal, we need to compare low words. since
2706 the jump is inverted, we invert the test too. */
2707 if (op1 == TOK_LT)
2708 op1 = TOK_LE;
2709 else if (op1 == TOK_GT)
2710 op1 = TOK_GE;
2711 else if (op1 == TOK_ULT)
2712 op1 = TOK_ULE;
2713 else if (op1 == TOK_UGT)
2714 op1 = TOK_UGE;
2715 a = 0;
2716 b = 0;
2717 gen_op(op1);
2718 if (op1 != TOK_NE) {
2719 a = gtst(1, 0);
2721 if (op != TOK_EQ) {
2722 /* generate non equal test */
2723 /* XXX: NOT PORTABLE yet */
2724 if (a == 0)
2725 b = gtst(0, 0);
2726 else
2727 b = psym(0x850f, 0);
2729 /* compare low */
2730 gen_op(op);
2731 a = gtst(1, a);
2732 gsym(b);
2733 vset(VT_INT, VT_JMPI, a);
2734 break;
2738 /* handle constant optimizations and various machine independant opt */
2739 void gen_opc(int op)
2741 int fc, c1, c2, n;
2742 SValue *v1, *v2;
2744 v1 = vtop - 1;
2745 v2 = vtop;
2746 /* currently, we cannot do computations with forward symbols */
2747 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2748 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2749 if (c1 && c2) {
2750 fc = v2->c.i;
2751 switch(op) {
2752 case '+': v1->c.i += fc; break;
2753 case '-': v1->c.i -= fc; break;
2754 case '&': v1->c.i &= fc; break;
2755 case '^': v1->c.i ^= fc; break;
2756 case '|': v1->c.i |= fc; break;
2757 case '*': v1->c.i *= fc; break;
2758 case TOK_PDIV:
2759 case '/': v1->c.i /= fc; break; /* XXX: zero case ? */
2760 case '%': v1->c.i %= fc; break; /* XXX: zero case ? */
2761 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break; /* XXX: zero case ? */
2762 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break; /* XXX: zero case ? */
2763 case TOK_SHL: v1->c.i <<= fc; break;
2764 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
2765 case TOK_SAR: v1->c.i >>= fc; break;
2766 /* tests */
2767 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
2768 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
2769 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
2770 case TOK_NE: v1->c.i = v1->c.i != fc; break;
2771 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
2772 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
2773 case TOK_LT: v1->c.i = v1->c.i < fc; break;
2774 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
2775 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
2776 case TOK_GT: v1->c.i = v1->c.i > fc; break;
2777 /* logical */
2778 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
2779 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
2780 default:
2781 goto general_case;
2783 vtop--;
2784 } else {
2785 /* if commutative ops, put c2 as constant */
2786 if (c1 && (op == '+' || op == '&' || op == '^' ||
2787 op == '|' || op == '*')) {
2788 vswap();
2789 swap(&c1, &c2);
2791 fc = vtop->c.i;
2792 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
2793 op == TOK_PDIV) &&
2794 fc == 1) ||
2795 ((op == '+' || op == '-' || op == '|' || op == '^' ||
2796 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
2797 fc == 0) ||
2798 (op == '&' &&
2799 fc == -1))) {
2800 /* nothing to do */
2801 vtop--;
2802 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
2803 /* try to use shifts instead of muls or divs */
2804 if (fc > 0 && (fc & (fc - 1)) == 0) {
2805 n = -1;
2806 while (fc) {
2807 fc >>= 1;
2808 n++;
2810 vtop->c.i = n;
2811 if (op == '*')
2812 op = TOK_SHL;
2813 else if (op == TOK_PDIV)
2814 op = TOK_SAR;
2815 else
2816 op = TOK_SHR;
2818 goto general_case;
2819 } else {
2820 general_case:
2821 /* call low level op generator */
2822 /* XXX: remove explicit registers */
2823 gen_opi(op);
2828 int pointed_size(int t)
2830 return type_size(pointed_type(t), &t);
2833 #if 0
2834 void check_pointer_types(SValue *p1, SValue *p2)
2836 char buf1[256], buf2[256];
2837 int t1, t2;
2838 t1 = p1->t;
2839 t2 = p2->t;
2840 if (!is_compatible_types(t1, t2)) {
2841 type_to_str(buf1, sizeof(buf1), t1, NULL);
2842 type_to_str(buf2, sizeof(buf2), t2, NULL);
2843 error("incompatible pointers '%s' and '%s'", buf1, buf2);
2846 #endif
2848 /* generic gen_op: handles types problems */
2849 void gen_op(int op)
2851 int u, t1, t2, bt1, bt2, t;
2853 t1 = vtop[-1].t;
2854 t2 = vtop[0].t;
2855 bt1 = t1 & VT_BTYPE;
2856 bt2 = t2 & VT_BTYPE;
2858 if (bt1 == VT_PTR || bt2 == VT_PTR) {
2859 /* at least one operand is a pointer */
2860 /* relationnal op: must be both pointers */
2861 if (op >= TOK_ULT && op <= TOK_GT) {
2862 // check_pointer_types(vtop, vtop - 1);
2863 /* pointers are handled are unsigned */
2864 t = VT_INT | VT_UNSIGNED;
2865 goto std_op;
2867 /* if both pointers, then it must be the '-' op */
2868 if ((t1 & VT_BTYPE) == VT_PTR &&
2869 (t2 & VT_BTYPE) == VT_PTR) {
2870 if (op != '-')
2871 error("cannot use pointers here");
2872 // check_pointer_types(vtop - 1, vtop);
2873 /* XXX: check that types are compatible */
2874 u = pointed_size(t1);
2875 gen_opc(op);
2876 /* set to integer type */
2877 vtop->t = VT_INT;
2878 vpushi(u);
2879 gen_op(TOK_PDIV);
2880 } else {
2881 /* exactly one pointer : must be '+' or '-'. */
2882 if (op != '-' && op != '+')
2883 error("cannot use pointers here");
2884 /* Put pointer as first operand */
2885 if ((t2 & VT_BTYPE) == VT_PTR) {
2886 vswap();
2887 swap(&t1, &t2);
2889 /* XXX: cast to int ? (long long case) */
2890 vpushi(pointed_size(vtop[-1].t));
2891 gen_op('*');
2892 if (do_bounds_check) {
2893 /* if bounded pointers, we generate a special code to test bounds */
2894 if (op == '-') {
2895 vpushi(0);
2896 vswap();
2897 gen_op('-');
2899 gen_bounded_ptr_add();
2900 } else {
2901 gen_opc(op);
2903 /* put again type if gen_opc() swaped operands */
2904 vtop->t = t1;
2906 } else if (is_float(bt1) || is_float(bt2)) {
2907 /* compute bigger type and do implicit casts */
2908 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
2909 t = VT_LDOUBLE;
2910 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
2911 t = VT_DOUBLE;
2912 } else {
2913 t = VT_FLOAT;
2915 /* floats can only be used for a few operations */
2916 if (op != '+' && op != '-' && op != '*' && op != '/' &&
2917 (op < TOK_ULT || op > TOK_GT))
2918 error("invalid operands for binary operation");
2919 goto std_op;
2920 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
2921 /* cast to biggest op */
2922 t = VT_LLONG;
2923 /* convert to unsigned if it does not fit in a long long */
2924 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
2925 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
2926 t |= VT_UNSIGNED;
2927 goto std_op;
2928 } else {
2929 /* integer operations */
2930 t = VT_INT;
2931 /* convert to unsigned if it does not fit in an integer */
2932 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
2933 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
2934 t |= VT_UNSIGNED;
2935 std_op:
2936 /* XXX: currently, some unsigned operations are explicit, so
2937 we modify them here */
2938 if (t & VT_UNSIGNED) {
2939 if (op == TOK_SAR)
2940 op = TOK_SHR;
2941 else if (op == '/')
2942 op = TOK_UDIV;
2943 else if (op == '%')
2944 op = TOK_UMOD;
2945 else if (op == TOK_LT)
2946 op = TOK_ULT;
2947 else if (op == TOK_GT)
2948 op = TOK_UGT;
2949 else if (op == TOK_LE)
2950 op = TOK_ULE;
2951 else if (op == TOK_GE)
2952 op = TOK_UGE;
2954 vswap();
2955 gen_cast(t);
2956 vswap();
2957 /* special case for shifts and long long: we keep the shift as
2958 an integer */
2959 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
2960 gen_cast(VT_INT);
2961 else
2962 gen_cast(t);
2963 if (is_float(t))
2964 gen_opf(op);
2965 else if ((t & VT_BTYPE) == VT_LLONG)
2966 gen_opl(op);
2967 else
2968 gen_opc(op);
2969 if (op >= TOK_ULT && op <= TOK_GT) {
2970 /* relationnal op: the result is an int */
2971 vtop->t = VT_INT;
2972 } else {
2973 vtop->t = t;
2978 /* generic itof for unsigned long long case */
2979 void gen_cvt_itof1(int t)
2981 GFuncContext gf;
2983 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
2984 (VT_LLONG | VT_UNSIGNED)) {
2986 gfunc_start(&gf);
2987 gfunc_param(&gf);
2988 if (t == VT_FLOAT)
2989 vpushi((int)&__ulltof);
2990 else if (t == VT_DOUBLE)
2991 vpushi((int)&__ulltod);
2992 else
2993 vpushi((int)&__ulltold);
2994 gfunc_call(&gf);
2995 vpushi(0);
2996 vtop->r = REG_FRET;
2997 } else {
2998 gen_cvt_itof(t);
3002 /* generic ftoi for unsigned long long case */
3003 void gen_cvt_ftoi1(int t)
3005 GFuncContext gf;
3006 int st;
3008 if (t == (VT_LLONG | VT_UNSIGNED)) {
3009 /* not handled natively */
3010 gfunc_start(&gf);
3011 st = vtop->t & VT_BTYPE;
3012 gfunc_param(&gf);
3013 if (st == VT_FLOAT)
3014 vpushi((int)&__ftoull);
3015 else if (st == VT_DOUBLE)
3016 vpushi((int)&__dtoull);
3017 else
3018 vpushi((int)&__ldtoull);
3019 gfunc_call(&gf);
3020 vpushi(0);
3021 vtop->r = REG_IRET;
3022 vtop->r2 = REG_LRET;
3023 } else {
3024 gen_cvt_ftoi(t);
3028 /* force char or short cast */
3029 void force_charshort_cast(int t)
3031 int bits, dbt;
3032 dbt = t & VT_BTYPE;
3033 /* XXX: add optimization if lvalue : just change type and offset */
3034 if (dbt == VT_BYTE)
3035 bits = 8;
3036 else
3037 bits = 16;
3038 if (t & VT_UNSIGNED) {
3039 vpushi((1 << bits) - 1);
3040 gen_op('&');
3041 } else {
3042 bits = 32 - bits;
3043 vpushi(bits);
3044 gen_op(TOK_SHL);
3045 vpushi(bits);
3046 gen_op(TOK_SAR);
3050 /* cast 'vtop' to 't' type */
3051 void gen_cast(int t)
3053 int sbt, dbt, sf, df, c, st1, dt1;
3055 /* special delayed cast for char/short */
3056 /* XXX: in some cases (multiple cascaded casts), it may still
3057 be incorrect */
3058 if (vtop->r & VT_MUSTCAST) {
3059 vtop->r &= ~VT_MUSTCAST;
3060 force_charshort_cast(vtop->t);
3063 dbt = t & VT_BTYPE;
3064 sbt = vtop->t & VT_BTYPE;
3066 if (sbt != dbt) {
3067 sf = is_float(sbt);
3068 df = is_float(dbt);
3069 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3070 if (sf && df) {
3071 /* convert from fp to fp */
3072 if (c) {
3073 /* constant case: we can do it now */
3074 /* XXX: in ISOC, cannot do it if error in convert */
3075 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
3076 vtop->c.f = (float)vtop->c.d;
3077 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
3078 vtop->c.f = (float)vtop->c.ld;
3079 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
3080 vtop->c.d = (double)vtop->c.f;
3081 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
3082 vtop->c.d = (double)vtop->c.ld;
3083 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
3084 vtop->c.ld = (long double)vtop->c.f;
3085 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
3086 vtop->c.ld = (long double)vtop->c.d;
3087 } else {
3088 /* non constant case: generate code */
3089 gen_cvt_ftof(dbt);
3091 } else if (df) {
3092 /* convert int to fp */
3093 st1 = vtop->t & (VT_BTYPE | VT_UNSIGNED);
3094 if (c) {
3095 switch(st1) {
3096 case VT_LLONG | VT_UNSIGNED:
3097 case VT_LLONG:
3098 /* XXX: add const cases for long long */
3099 goto do_itof;
3100 case VT_INT | VT_UNSIGNED:
3101 switch(dbt) {
3102 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
3103 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
3104 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
3106 break;
3107 default:
3108 switch(dbt) {
3109 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
3110 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
3111 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
3113 break;
3115 } else {
3116 do_itof:
3117 gen_cvt_itof1(dbt);
3119 } else if (sf) {
3120 /* convert fp to int */
3121 dt1 = t & (VT_BTYPE | VT_UNSIGNED);
3122 /* we handle char/short/etc... with generic code */
3123 if (dt1 != (VT_INT | VT_UNSIGNED) &&
3124 dt1 != (VT_LLONG | VT_UNSIGNED) &&
3125 dt1 != VT_LLONG)
3126 dt1 = VT_INT;
3127 if (c) {
3128 switch(dt1) {
3129 case VT_LLONG | VT_UNSIGNED:
3130 case VT_LLONG:
3131 /* XXX: add const cases for long long */
3132 goto do_ftoi;
3133 case VT_INT | VT_UNSIGNED:
3134 switch(sbt) {
3135 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
3136 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3137 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3139 break;
3140 default:
3141 /* int case */
3142 switch(sbt) {
3143 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
3144 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
3145 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
3147 break;
3149 } else {
3150 do_ftoi:
3151 gen_cvt_ftoi1(dt1);
3153 if (dt1 == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dt1) {
3154 /* additionnal cast for char/short/bool... */
3155 vtop->t = dt1;
3156 gen_cast(t);
3158 } else if (dbt == VT_LLONG) {
3159 /* scalar to long long */
3160 if (c) {
3161 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3162 vtop->c.ll = vtop->c.ui;
3163 else
3164 vtop->c.ll = vtop->c.i;
3165 } else {
3166 /* machine independant conversion */
3167 gv(RC_INT);
3168 /* generate high word */
3169 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) {
3170 vpushi(0);
3171 gv(RC_INT);
3172 } else {
3173 gv_dup();
3174 vpushi(31);
3175 gen_op(TOK_SAR);
3177 /* patch second register */
3178 vtop[-1].r2 = vtop->r;
3179 vpop();
3181 } else if (dbt == VT_BOOL) {
3182 /* scalar to bool */
3183 vpushi(0);
3184 gen_op(TOK_NE);
3185 } else if (dbt == VT_BYTE || dbt == VT_SHORT) {
3186 force_charshort_cast(t);
3187 } else if (dbt == VT_INT) {
3188 /* scalar to int */
3189 if (sbt == VT_LLONG) {
3190 /* from long long: just take low order word */
3191 lexpand();
3192 vpop();
3193 } else if (vtop->r & VT_LVAL) {
3194 /* if lvalue and single word type, nothing to do (XXX:
3195 maybe incorrect for sizeof op) */
3196 goto no_cast;
3200 vtop->t = t;
3201 no_cast: ;
3204 /* return type size. Put alignment at 'a' */
3205 int type_size(int t, int *a)
3207 Sym *s;
3208 int bt;
3210 bt = t & VT_BTYPE;
3211 if (bt == VT_STRUCT) {
3212 /* struct/union */
3213 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3214 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
3215 return s->c;
3216 } else if (bt == VT_PTR) {
3217 if (t & VT_ARRAY) {
3218 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3219 return type_size(s->t, a) * s->c;
3220 } else {
3221 *a = PTR_SIZE;
3222 return PTR_SIZE;
3224 } else if (bt == VT_LDOUBLE) {
3225 *a = LDOUBLE_ALIGN;
3226 return LDOUBLE_SIZE;
3227 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
3228 *a = 8;
3229 return 8;
3230 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
3231 *a = 4;
3232 return 4;
3233 } else if (bt == VT_SHORT) {
3234 *a = 2;
3235 return 2;
3236 } else {
3237 /* char, void, function, _Bool */
3238 *a = 1;
3239 return 1;
3243 /* return the pointed type of t */
3244 int pointed_type(int t)
3246 Sym *s;
3247 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3248 return s->t | (t & ~VT_TYPE);
3251 int mk_pointer(int t)
3253 int p;
3254 p = anon_sym++;
3255 sym_push(p, t, 0, -1);
3256 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
3259 int is_compatible_types(int t1, int t2)
3261 Sym *s1, *s2;
3262 int bt1, bt2;
3264 t1 &= VT_TYPE;
3265 t2 &= VT_TYPE;
3266 bt1 = t1 & VT_BTYPE;
3267 bt2 = t2 & VT_BTYPE;
3268 if (bt1 == VT_PTR) {
3269 t1 = pointed_type(t1);
3270 /* if function, then convert implicitely to function pointer */
3271 if (bt2 != VT_FUNC) {
3272 if (bt2 != VT_PTR)
3273 return 0;
3274 t2 = pointed_type(t2);
3276 /* void matches everything */
3277 t1 &= VT_TYPE;
3278 t2 &= VT_TYPE;
3279 if (t1 == VT_VOID || t2 == VT_VOID)
3280 return 1;
3281 return is_compatible_types(t1, t2);
3282 } else if (bt1 == VT_STRUCT) {
3283 return (t2 == t1);
3284 } else if (bt1 == VT_FUNC) {
3285 if (bt2 != VT_FUNC)
3286 return 0;
3287 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
3288 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
3289 if (!is_compatible_types(s1->t, s2->t))
3290 return 0;
3291 /* XXX: not complete */
3292 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
3293 return 1;
3294 if (s1->c != s2->c)
3295 return 0;
3296 while (s1 != NULL) {
3297 if (s2 == NULL)
3298 return 0;
3299 if (!is_compatible_types(s1->t, s2->t))
3300 return 0;
3301 s1 = s1->next;
3302 s2 = s2->next;
3304 if (s2)
3305 return 0;
3306 return 1;
3307 } else {
3308 /* XXX: not complete */
3309 return 1;
3313 /* print a type. If 'varstr' is not NULL, then the variable is also
3314 printed in the type */
3315 /* XXX: union */
3316 /* XXX: add array and function pointers */
3317 void type_to_str(char *buf, int buf_size,
3318 int t, const char *varstr)
3320 int bt, v;
3321 Sym *s, *sa;
3322 char buf1[256];
3323 const char *tstr;
3325 t = t & VT_TYPE;
3326 bt = t & VT_BTYPE;
3327 buf[0] = '\0';
3328 if (t & VT_UNSIGNED)
3329 pstrcat(buf, buf_size, "unsigned ");
3330 switch(bt) {
3331 case VT_VOID:
3332 tstr = "void";
3333 goto add_tstr;
3334 case VT_BOOL:
3335 tstr = "_Bool";
3336 goto add_tstr;
3337 case VT_BYTE:
3338 tstr = "char";
3339 goto add_tstr;
3340 case VT_SHORT:
3341 tstr = "short";
3342 goto add_tstr;
3343 case VT_INT:
3344 tstr = "int";
3345 goto add_tstr;
3346 case VT_LONG:
3347 tstr = "long";
3348 goto add_tstr;
3349 case VT_LLONG:
3350 tstr = "long long";
3351 goto add_tstr;
3352 case VT_FLOAT:
3353 tstr = "float";
3354 goto add_tstr;
3355 case VT_DOUBLE:
3356 tstr = "double";
3357 goto add_tstr;
3358 case VT_LDOUBLE:
3359 tstr = "long double";
3360 add_tstr:
3361 pstrcat(buf, buf_size, tstr);
3362 break;
3363 case VT_ENUM:
3364 case VT_STRUCT:
3365 if (bt == VT_STRUCT)
3366 tstr = "struct ";
3367 else
3368 tstr = "enum ";
3369 pstrcat(buf, buf_size, tstr);
3370 v = (unsigned)t >> VT_STRUCT_SHIFT;
3371 if (v >= SYM_FIRST_ANOM)
3372 pstrcat(buf, buf_size, "<anonymous>");
3373 else
3374 pstrcat(buf, buf_size, get_tok_str(v, NULL));
3375 break;
3376 case VT_FUNC:
3377 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3378 type_to_str(buf, buf_size, s->t, varstr);
3379 pstrcat(buf, buf_size, "(");
3380 sa = s->next;
3381 while (sa != NULL) {
3382 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
3383 pstrcat(buf, buf_size, buf1);
3384 sa = sa->next;
3385 if (sa)
3386 pstrcat(buf, buf_size, ", ");
3388 pstrcat(buf, buf_size, ")");
3389 goto no_var;
3390 case VT_PTR:
3391 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3392 pstrcpy(buf1, sizeof(buf1), "*");
3393 if (varstr)
3394 pstrcat(buf1, sizeof(buf1), varstr);
3395 type_to_str(buf, buf_size, s->t, buf1);
3396 goto no_var;
3398 if (varstr) {
3399 pstrcat(buf, buf_size, " ");
3400 pstrcat(buf, buf_size, varstr);
3402 no_var: ;
3405 /* verify type compatibility to store vtop in 'dt' type, and generate
3406 casts if needed. */
3407 void gen_assign_cast(int dt)
3409 int st;
3410 char buf1[256], buf2[256];
3412 st = vtop->t; /* source type */
3413 if ((dt & VT_BTYPE) == VT_PTR) {
3414 /* special cases for pointers */
3415 /* a function is implicitely a function pointer */
3416 if ((st & VT_BTYPE) == VT_FUNC) {
3417 if (!is_compatible_types(pointed_type(dt), st))
3418 goto error;
3419 else
3420 goto type_ok;
3422 /* '0' can also be a pointer */
3423 if ((st & VT_BTYPE) == VT_INT &&
3424 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) &&
3425 vtop->c.i == 0)
3426 goto type_ok;
3428 if (!is_compatible_types(dt, st)) {
3429 error:
3430 type_to_str(buf1, sizeof(buf1), st, NULL);
3431 type_to_str(buf2, sizeof(buf2), dt, NULL);
3432 error("cannot cast '%s' to '%s'", buf1, buf2);
3434 type_ok:
3435 gen_cast(dt);
3438 /* store vtop in lvalue pushed on stack */
3439 void vstore(void)
3441 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
3442 GFuncContext gf;
3444 ft = vtop[-1].t;
3445 sbt = vtop->t & VT_BTYPE;
3446 dbt = ft & VT_BTYPE;
3447 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
3448 (sbt == VT_INT && dbt == VT_SHORT)) {
3449 /* optimize char/short casts */
3450 delayed_cast = VT_MUSTCAST;
3451 vtop->t = ft & VT_TYPE;
3452 } else {
3453 delayed_cast = 0;
3454 gen_assign_cast(ft & VT_TYPE);
3457 if (sbt == VT_STRUCT) {
3458 /* if structure, only generate pointer */
3459 /* structure assignment : generate memcpy */
3460 /* XXX: optimize if small size */
3462 vdup();
3463 gfunc_start(&gf);
3464 /* type size */
3465 size = type_size(vtop->t, &align);
3466 vpushi(size);
3467 gfunc_param(&gf);
3468 /* source */
3469 vtop->t = VT_INT;
3470 gaddrof();
3471 gfunc_param(&gf);
3472 /* destination */
3473 vswap();
3474 vtop->t = VT_INT;
3475 gaddrof();
3476 gfunc_param(&gf);
3478 save_regs();
3479 vpushi((int)&memcpy);
3480 gfunc_call(&gf);
3481 /* leave source on stack */
3482 } else if (ft & VT_BITFIELD) {
3483 /* bitfield store handling */
3484 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
3485 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3486 /* remove bit field info to avoid loops */
3487 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3489 /* duplicate destination */
3490 vdup();
3491 vtop[-1] = vtop[-2];
3493 /* mask and shift source */
3494 vpushi((1 << bit_size) - 1);
3495 gen_op('&');
3496 vpushi(bit_pos);
3497 gen_op(TOK_SHL);
3498 /* load destination, mask and or with source */
3499 vswap();
3500 vpushi(~(((1 << bit_size) - 1) << bit_pos));
3501 gen_op('&');
3502 gen_op('|');
3503 /* store result */
3504 vstore();
3505 } else {
3506 rc = RC_INT;
3507 if (is_float(ft))
3508 rc = RC_FLOAT;
3509 r = gv(rc); /* generate value (XXX: move that to store code) */
3510 /* if lvalue was saved on stack, must read it */
3511 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
3512 SValue sv;
3513 t = get_reg(RC_INT);
3514 sv.t = VT_INT;
3515 sv.r = VT_LOCAL | VT_LVAL;
3516 sv.c.ul = vtop[-1].c.ul;
3517 load(t, &sv);
3518 vtop[-1].r = t | VT_LVAL;
3520 store(r, vtop - 1);
3521 /* two word case handling : store second register at word + 4 */
3522 if ((ft & VT_BTYPE) == VT_LLONG) {
3523 vswap();
3524 /* convert to int to increment easily */
3525 vtop->t = VT_INT;
3526 gaddrof();
3527 vpushi(4);
3528 gen_op('+');
3529 vtop->r |= VT_LVAL;
3530 vswap();
3531 /* XXX: it works because r2 is spilled last ! */
3532 store(vtop->r2, vtop - 1);
3534 vswap();
3535 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
3536 vtop->r |= delayed_cast;
3540 /* post defines POST/PRE add. c is the token ++ or -- */
3541 void inc(int post, int c)
3543 test_lvalue();
3544 vdup(); /* save lvalue */
3545 if (post) {
3546 gv_dup(); /* duplicate value */
3547 vrotb(3);
3548 vrotb(3);
3550 /* add constant */
3551 vpushi(c - TOK_MID);
3552 gen_op('+');
3553 vstore(); /* store value */
3554 if (post)
3555 vpop(); /* if post op, return saved value */
3558 /* Parse GNUC __attribute__ extension. Currently, the following
3559 extensions are recognized:
3560 - aligned(n) : set data/function alignment.
3561 - section(x) : generate data/code in this section.
3562 - unused : currently ignored, but may be used someday.
3564 void parse_attribute(AttributeDef *ad)
3566 int t, n;
3568 next();
3569 skip('(');
3570 skip('(');
3571 while (tok != ')') {
3572 if (tok < TOK_IDENT)
3573 expect("attribute name");
3574 t = tok;
3575 next();
3576 switch(t) {
3577 case TOK_SECTION:
3578 case TOK___SECTION__:
3579 skip('(');
3580 if (tok != TOK_STR)
3581 expect("section name");
3582 ad->section = find_section(tokc.ts->str);
3583 next();
3584 skip(')');
3585 break;
3586 case TOK_ALIGNED:
3587 case TOK___ALIGNED__:
3588 skip('(');
3589 n = expr_const();
3590 if (n <= 0 || (n & (n - 1)) != 0)
3591 error("alignment must be a positive power of two");
3592 ad->aligned = n;
3593 skip(')');
3594 break;
3595 case TOK_UNUSED:
3596 case TOK___UNUSED__:
3597 /* currently, no need to handle it because tcc does not
3598 track unused objects */
3599 break;
3600 default:
3601 warning("'%s' attribute ignored", get_tok_str(t, NULL));
3602 /* skip parameters */
3603 /* XXX: skip parenthesis too */
3604 if (tok == '(') {
3605 next();
3606 while (tok != ')' && tok != -1)
3607 next();
3608 next();
3610 break;
3612 if (tok != ',')
3613 break;
3614 next();
3616 skip(')');
3617 skip(')');
3620 /* enum/struct/union declaration */
3621 int struct_decl(int u)
3623 int a, t, b, v, size, align, maxalign, c, offset;
3624 int bit_size, bit_pos, bsize, bt, lbit_pos;
3625 Sym *s, *ss, **ps;
3626 AttributeDef ad;
3628 a = tok; /* save decl type */
3629 next();
3630 if (tok != '{') {
3631 v = tok;
3632 next();
3633 /* struct already defined ? return it */
3634 /* XXX: check consistency */
3635 s = sym_find(v | SYM_STRUCT);
3636 if (s) {
3637 if (s->t != a)
3638 error("invalid type");
3639 goto do_decl;
3641 } else {
3642 v = anon_sym++;
3644 s = sym_push(v | SYM_STRUCT, a, 0, 0);
3645 /* put struct/union/enum name in type */
3646 do_decl:
3647 u = u | (v << VT_STRUCT_SHIFT);
3649 if (tok == '{') {
3650 next();
3651 if (s->c)
3652 error("struct/union/enum already defined");
3653 /* cannot be empty */
3654 c = 0;
3655 maxalign = 0;
3656 ps = &s->next;
3657 bit_pos = 0;
3658 offset = 0;
3659 while (1) {
3660 if (a == TOK_ENUM) {
3661 v = tok;
3662 next();
3663 if (tok == '=') {
3664 next();
3665 c = expr_const();
3667 /* enum symbols have static storage */
3668 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
3669 if (tok == ',')
3670 next();
3671 c++;
3672 } else {
3673 parse_btype(&b, &ad);
3674 while (1) {
3675 bit_size = -1;
3676 v = 0;
3677 if (tok != ':') {
3678 t = type_decl(&v, b, TYPE_DIRECT);
3679 if ((t & VT_BTYPE) == VT_FUNC ||
3680 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
3681 error("invalid type for '%s'",
3682 get_tok_str(v, NULL));
3683 } else {
3684 t = b;
3686 if (tok == ':') {
3687 next();
3688 bit_size = expr_const();
3689 /* XXX: handle v = 0 case for messages */
3690 if (bit_size < 0)
3691 error("negative width in bit-field '%s'",
3692 get_tok_str(v, NULL));
3693 if (v && bit_size == 0)
3694 error("zero width for bit-field '%s'",
3695 get_tok_str(v, NULL));
3697 size = type_size(t, &align);
3698 lbit_pos = 0;
3699 if (bit_size >= 0) {
3700 bt = t & VT_BTYPE;
3701 if (bt != VT_INT &&
3702 bt != VT_BYTE &&
3703 bt != VT_SHORT)
3704 error("bitfields must have scalar type");
3705 bsize = size * 8;
3706 if (bit_size > bsize) {
3707 error("width of '%s' exceeds its type",
3708 get_tok_str(v, NULL));
3709 } else if (bit_size == bsize) {
3710 /* no need for bit fields */
3711 bit_pos = 0;
3712 } else if (bit_size == 0) {
3713 /* XXX: what to do if only padding in a
3714 structure ? */
3715 /* zero size: means to pad */
3716 if (bit_pos > 0)
3717 bit_pos = bsize;
3718 } else {
3719 /* we do not have enough room ? */
3720 if ((bit_pos + bit_size) > bsize)
3721 bit_pos = 0;
3722 lbit_pos = bit_pos;
3723 /* XXX: handle LSB first */
3724 t |= VT_BITFIELD |
3725 (bit_pos << VT_STRUCT_SHIFT) |
3726 (bit_size << (VT_STRUCT_SHIFT + 6));
3727 bit_pos += bit_size;
3729 } else {
3730 bit_pos = 0;
3732 if (v) {
3733 /* add new memory data only if starting
3734 bit field */
3735 if (lbit_pos == 0) {
3736 if (a == TOK_STRUCT) {
3737 c = (c + align - 1) & -align;
3738 offset = c;
3739 c += size;
3740 } else {
3741 offset = 0;
3742 if (size > c)
3743 c = size;
3745 if (align > maxalign)
3746 maxalign = align;
3748 #if 0
3749 printf("add field %s offset=%d",
3750 get_tok_str(v, NULL), offset);
3751 if (t & VT_BITFIELD) {
3752 printf(" pos=%d size=%d",
3753 (t >> VT_STRUCT_SHIFT) & 0x3f,
3754 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
3756 printf("\n");
3757 #endif
3758 ss = sym_push(v | SYM_FIELD, t, 0, offset);
3759 *ps = ss;
3760 ps = &ss->next;
3762 if (tok == ';' || tok == -1)
3763 break;
3764 skip(',');
3766 skip(';');
3768 if (tok == '}')
3769 break;
3771 skip('}');
3772 /* size for struct/union, dummy for enum */
3773 s->c = (c + maxalign - 1) & -maxalign;
3775 return u;
3778 /* return 0 if no type declaration. otherwise, return the basic type
3779 and skip it.
3781 int parse_btype(int *type_ptr, AttributeDef *ad)
3783 int t, u, type_found;
3784 Sym *s;
3786 memset(ad, 0, sizeof(AttributeDef));
3787 type_found = 0;
3788 t = 0;
3789 while(1) {
3790 switch(tok) {
3791 /* basic types */
3792 case TOK_CHAR:
3793 u = VT_BYTE;
3794 basic_type:
3795 next();
3796 basic_type1:
3797 if ((t & VT_BTYPE) != 0)
3798 error("too many basic types");
3799 t |= u;
3800 break;
3801 case TOK_VOID:
3802 u = VT_VOID;
3803 goto basic_type;
3804 case TOK_SHORT:
3805 u = VT_SHORT;
3806 goto basic_type;
3807 case TOK_INT:
3808 next();
3809 break;
3810 case TOK_LONG:
3811 next();
3812 if ((t & VT_BTYPE) == VT_DOUBLE) {
3813 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
3814 } else if ((t & VT_BTYPE) == VT_LONG) {
3815 t = (t & ~VT_BTYPE) | VT_LLONG;
3816 } else {
3817 u = VT_LONG;
3818 goto basic_type1;
3820 break;
3821 case TOK_BOOL:
3822 u = VT_BOOL;
3823 goto basic_type;
3824 case TOK_FLOAT:
3825 u = VT_FLOAT;
3826 goto basic_type;
3827 case TOK_DOUBLE:
3828 next();
3829 if ((t & VT_BTYPE) == VT_LONG) {
3830 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
3831 } else {
3832 u = VT_DOUBLE;
3833 goto basic_type1;
3835 break;
3836 case TOK_ENUM:
3837 u = struct_decl(VT_ENUM);
3838 goto basic_type1;
3839 case TOK_STRUCT:
3840 case TOK_UNION:
3841 u = struct_decl(VT_STRUCT);
3842 goto basic_type1;
3844 /* type modifiers */
3845 case TOK_CONST:
3846 case TOK_VOLATILE:
3847 case TOK_REGISTER:
3848 case TOK_SIGNED:
3849 case TOK_AUTO:
3850 case TOK_INLINE:
3851 case TOK_RESTRICT:
3852 next();
3853 break;
3854 case TOK_UNSIGNED:
3855 t |= VT_UNSIGNED;
3856 next();
3857 break;
3859 /* storage */
3860 case TOK_EXTERN:
3861 t |= VT_EXTERN;
3862 next();
3863 break;
3864 case TOK_STATIC:
3865 t |= VT_STATIC;
3866 next();
3867 break;
3868 case TOK_TYPEDEF:
3869 t |= VT_TYPEDEF;
3870 next();
3871 break;
3872 /* GNUC attribute */
3873 case TOK___ATTRIBUTE__:
3874 parse_attribute(ad);
3875 break;
3876 default:
3877 s = sym_find(tok);
3878 if (!s || !(s->t & VT_TYPEDEF))
3879 goto the_end;
3880 t |= (s->t & ~VT_TYPEDEF);
3881 next();
3882 break;
3884 type_found = 1;
3886 the_end:
3887 /* long is never used as type */
3888 if ((t & VT_BTYPE) == VT_LONG)
3889 t = (t & ~VT_BTYPE) | VT_INT;
3890 *type_ptr = t;
3891 return type_found;
3894 int post_type(int t)
3896 int p, n, pt, l, t1;
3897 Sym **plast, *s, *first;
3898 AttributeDef ad;
3900 if (tok == '(') {
3901 /* function declaration */
3902 next();
3903 l = 0;
3904 first = NULL;
3905 plast = &first;
3906 while (tok != ')') {
3907 /* read param name and compute offset */
3908 if (l != FUNC_OLD) {
3909 if (!parse_btype(&pt, &ad)) {
3910 if (l) {
3911 error("invalid type");
3912 } else {
3913 l = FUNC_OLD;
3914 goto old_proto;
3917 l = FUNC_NEW;
3918 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
3919 break;
3920 pt = type_decl(&n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
3921 if ((pt & VT_BTYPE) == VT_VOID)
3922 error("parameter declared as void");
3923 } else {
3924 old_proto:
3925 n = tok;
3926 pt = VT_INT;
3927 next();
3929 /* array must be transformed to pointer according to ANSI C */
3930 pt &= ~VT_ARRAY;
3931 s = sym_push(n | SYM_FIELD, pt, 0, 0);
3932 *plast = s;
3933 plast = &s->next;
3934 if (tok == ',') {
3935 next();
3936 if (l == FUNC_NEW && tok == TOK_DOTS) {
3937 l = FUNC_ELLIPSIS;
3938 next();
3939 break;
3943 /* if no parameters, then old type prototype */
3944 if (l == 0)
3945 l = FUNC_OLD;
3946 skip(')');
3947 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
3948 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
3949 /* we push a anonymous symbol which will contain the function prototype */
3950 p = anon_sym++;
3951 s = sym_push(p, t, 0, l);
3952 s->next = first;
3953 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
3954 } else if (tok == '[') {
3955 /* array definition */
3956 next();
3957 n = -1;
3958 if (tok != ']') {
3959 n = expr_const();
3960 if (n < 0)
3961 error("invalid array size");
3963 skip(']');
3964 /* parse next post type */
3965 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
3966 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
3968 /* we push a anonymous symbol which will contain the array
3969 element type */
3970 p = anon_sym++;
3971 sym_push(p, t, 0, n);
3972 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
3974 return t;
3977 /* Read a type declaration (except basic type), and return the
3978 type. If v is true, then also put variable name in 'vtop->c' */
3979 int type_decl(int *v, int t, int td)
3981 int u, p;
3982 Sym *s;
3984 while (tok == '*') {
3985 next();
3986 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
3987 next();
3988 t = mk_pointer(t);
3991 /* recursive type */
3992 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
3993 if (tok == '(') {
3994 next();
3995 u = type_decl(v, 0, td);
3996 skip(')');
3997 } else {
3998 u = 0;
3999 /* type identifier */
4000 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
4001 *v = tok;
4002 next();
4003 } else {
4004 if (!(td & TYPE_ABSTRACT))
4005 expect("identifier");
4006 *v = 0;
4009 /* append t at the end of u */
4010 t = post_type(t);
4011 if (!u)
4012 return t;
4013 p = u;
4014 while(1) {
4015 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
4016 p = s->t;
4017 if (!p) {
4018 s->t = t;
4019 break;
4022 return u;
4025 /* define a new external reference to a function 'v' of type 'u' */
4026 Sym *external_sym(int v, int u, int r)
4028 Sym *s;
4029 s = sym_find(v);
4030 if (!s) {
4031 /* push forward reference */
4032 s = sym_push1(&global_stack,
4033 v, u, 0);
4034 s->r = r | VT_CONST | VT_FORWARD;
4036 return s;
4039 void indir(void)
4041 if ((vtop->t & VT_BTYPE) != VT_PTR)
4042 expect("pointer");
4043 if (vtop->r & VT_LVAL)
4044 gv(RC_INT);
4045 vtop->t = pointed_type(vtop->t);
4046 if (!(vtop->t & VT_ARRAY)) /* an array is never an lvalue */
4047 vtop->r |= VT_LVAL;
4050 /* pass a parameter to a function and do type checking and casting */
4051 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
4053 int func_type;
4054 func_type = func->c;
4055 if (func_type == FUNC_OLD ||
4056 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
4057 /* default casting : only need to convert float to double */
4058 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
4059 gen_cast(VT_DOUBLE);
4060 } else if (arg == NULL) {
4061 error("too many arguments to function");
4062 } else {
4063 gen_assign_cast(arg->t);
4065 gfunc_param(gf);
4068 void unary(void)
4070 int n, t, ft, fc, p, align, size, r, data_offset;
4071 Sym *s;
4072 GFuncContext gf;
4073 AttributeDef ad;
4075 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
4076 vpushi(tokc.i);
4077 next();
4078 } else if (tok == TOK_CUINT) {
4079 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
4080 next();
4081 } else if (tok == TOK_CLLONG) {
4082 vsetc(VT_LLONG, VT_CONST, &tokc);
4083 next();
4084 } else if (tok == TOK_CULLONG) {
4085 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
4086 next();
4087 } else if (tok == TOK_CFLOAT) {
4088 vsetc(VT_FLOAT, VT_CONST, &tokc);
4089 next();
4090 } else if (tok == TOK_CDOUBLE) {
4091 vsetc(VT_DOUBLE, VT_CONST, &tokc);
4092 next();
4093 } else if (tok == TOK_CLDOUBLE) {
4094 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
4095 next();
4096 } else if (tok == TOK___FUNC__) {
4097 /* special function name identifier */
4098 /* generate (char *) type */
4099 data_offset = (int)data_section->data_ptr;
4100 vset(mk_pointer(VT_BYTE), VT_CONST, data_offset);
4101 strcpy((void *)data_offset, funcname);
4102 data_offset += strlen(funcname) + 1;
4103 data_section->data_ptr = (unsigned char *)data_offset;
4104 next();
4105 } else if (tok == TOK_LSTR) {
4106 t = VT_INT;
4107 goto str_init;
4108 } else if (tok == TOK_STR) {
4109 /* string parsing */
4110 t = VT_BYTE;
4111 str_init:
4112 type_size(t, &align);
4113 data_offset = (int)data_section->data_ptr;
4114 data_offset = (data_offset + align - 1) & -align;
4115 fc = data_offset;
4116 /* we must declare it as an array first to use initializer parser */
4117 t = VT_ARRAY | mk_pointer(t);
4118 decl_initializer(t, VT_CONST, data_offset, 1, 0);
4119 data_offset += type_size(t, &align);
4120 /* put it as pointer */
4121 vset(t & ~VT_ARRAY, VT_CONST, fc);
4122 data_section->data_ptr = (unsigned char *)data_offset;
4123 } else {
4124 t = tok;
4125 next();
4126 if (t == '(') {
4127 /* cast ? */
4128 if (parse_btype(&t, &ad)) {
4129 ft = type_decl(&n, t, TYPE_ABSTRACT);
4130 skip(')');
4131 /* check ISOC99 compound literal */
4132 if (tok == '{') {
4133 /* data is allocated locally by default */
4134 if (global_expr)
4135 r = VT_CONST;
4136 else
4137 r = VT_LOCAL;
4138 /* all except arrays are lvalues */
4139 if (!(ft & VT_ARRAY))
4140 r |= VT_LVAL;
4141 memset(&ad, 0, sizeof(AttributeDef));
4142 fc = decl_initializer_alloc(ft, &ad, r, 1);
4143 vset(ft, r, fc);
4144 } else {
4145 unary();
4146 gen_cast(ft);
4148 } else {
4149 gexpr();
4150 skip(')');
4152 } else if (t == '*') {
4153 unary();
4154 indir();
4155 } else if (t == '&') {
4156 unary();
4157 /* functions names must be treated as function pointers,
4158 except for unary '&' and sizeof. Since we consider that
4159 functions are not lvalues, we only have to handle it
4160 there and in function calls. */
4161 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4162 test_lvalue();
4163 vtop->t = mk_pointer(vtop->t);
4164 gaddrof();
4165 } else
4166 if (t == '!') {
4167 unary();
4168 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
4169 vtop->c.i = !vtop->c.i;
4170 else if ((vtop->r & VT_VALMASK) == VT_CMP)
4171 vtop->c.i = vtop->c.i ^ 1;
4172 else
4173 vset(VT_INT, VT_JMP, gtst(1, 0));
4174 } else
4175 if (t == '~') {
4176 unary();
4177 vpushi(-1);
4178 gen_op('^');
4179 } else
4180 if (t == '+') {
4181 unary();
4182 } else
4183 if (t == TOK_SIZEOF) {
4184 if (tok == '(') {
4185 next();
4186 if (parse_btype(&t, &ad)) {
4187 t = type_decl(&n, t, TYPE_ABSTRACT);
4188 } else {
4189 /* XXX: some code could be generated: add eval
4190 flag */
4191 gexpr();
4192 t = vtop->t;
4193 vpop();
4195 skip(')');
4196 } else {
4197 unary();
4198 t = vtop->t;
4199 vpop();
4201 vpushi(type_size(t, &t));
4202 } else
4203 if (t == TOK_INC || t == TOK_DEC) {
4204 unary();
4205 inc(0, t);
4206 } else if (t == '-') {
4207 vpushi(0);
4208 unary();
4209 gen_op('-');
4210 } else
4212 s = sym_find(t);
4213 if (!s) {
4214 if (tok != '(')
4215 error("'%s' undeclared", get_tok_str(t, NULL));
4216 /* for simple function calls, we tolerate undeclared
4217 external reference */
4218 p = anon_sym++;
4219 sym_push1(&global_stack, p, 0, FUNC_OLD);
4220 /* int() function */
4221 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT), 0);
4223 vset(s->t, s->r, s->c);
4224 /* if forward reference, we must point to s */
4225 if (vtop->r & VT_FORWARD)
4226 vtop->c.sym = s;
4230 /* post operations */
4231 while (1) {
4232 if (tok == TOK_INC || tok == TOK_DEC) {
4233 inc(1, tok);
4234 next();
4235 } else if (tok == '.' || tok == TOK_ARROW) {
4236 /* field */
4237 if (tok == TOK_ARROW)
4238 indir();
4239 test_lvalue();
4240 gaddrof();
4241 next();
4242 /* expect pointer on structure */
4243 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
4244 expect("struct or union");
4245 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4246 /* find field */
4247 tok |= SYM_FIELD;
4248 while ((s = s->next) != NULL) {
4249 if (s->v == tok)
4250 break;
4252 if (!s)
4253 error("field not found");
4254 /* add field offset to pointer */
4255 vtop->t = char_pointer_type; /* change type to 'char *' */
4256 vpushi(s->c);
4257 gen_op('+');
4258 /* change type to field type, and set to lvalue */
4259 vtop->t = s->t;
4260 /* an array is never an lvalue */
4261 if (!(vtop->t & VT_ARRAY))
4262 vtop->r |= VT_LVAL;
4263 next();
4264 } else if (tok == '[') {
4265 next();
4266 gexpr();
4267 gen_op('+');
4268 indir();
4269 skip(']');
4270 } else if (tok == '(') {
4271 SValue ret;
4272 Sym *sa;
4274 /* function call */
4275 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
4276 /* pointer test (no array accepted) */
4277 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
4278 vtop->t = pointed_type(vtop->t);
4279 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4280 goto error_func;
4281 } else {
4282 error_func:
4283 expect("function pointer");
4285 } else {
4286 vtop->r &= ~VT_LVAL; /* no lvalue */
4288 /* get return type */
4289 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
4290 save_regs(); /* save used temporary registers */
4291 gfunc_start(&gf);
4292 next();
4293 sa = s->next; /* first parameter */
4294 #ifdef INVERT_FUNC_PARAMS
4296 int *str, len, parlevel, *saved_macro_ptr;
4297 Sym *args, *s1;
4299 /* read each argument and store it on a stack */
4300 /* XXX: merge it with macro args ? */
4301 args = NULL;
4302 while (tok != ')') {
4303 len = 0;
4304 str = NULL;
4305 parlevel = 0;
4306 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
4307 tok != -1) {
4308 if (tok == '(')
4309 parlevel++;
4310 else if (tok == ')')
4311 parlevel--;
4312 tok_add2(&str, &len, tok, &tokc);
4313 next();
4315 tok_add(&str, &len, -1); /* end of file added */
4316 tok_add(&str, &len, 0);
4317 s1 = sym_push2(&args, 0, 0, (int)str);
4318 s1->next = sa; /* add reference to argument */
4319 if (sa)
4320 sa = sa->next;
4321 if (tok != ',')
4322 break;
4323 next();
4325 if (tok != ')')
4326 expect(")");
4328 /* now generate code in reverse order by reading the stack */
4329 saved_macro_ptr = macro_ptr;
4330 while (args) {
4331 macro_ptr = (int *)args->c;
4332 next();
4333 expr_eq();
4334 if (tok != -1)
4335 expect("',' or ')'");
4336 gfunc_param_typed(&gf, s, args->next);
4337 s1 = args->prev;
4338 free((int *)args->c);
4339 free(args);
4340 args = s1;
4342 macro_ptr = saved_macro_ptr;
4343 /* restore token */
4344 tok = ')';
4346 #endif
4347 /* compute first implicit argument if a structure is returned */
4348 if ((s->t & VT_BTYPE) == VT_STRUCT) {
4349 /* get some space for the returned structure */
4350 size = type_size(s->t, &align);
4351 loc = (loc - size) & -align;
4352 ret.t = s->t;
4353 ret.r = VT_LOCAL | VT_LVAL;
4354 /* pass it as 'int' to avoid structure arg passing
4355 problems */
4356 vset(VT_INT, VT_LOCAL, loc);
4357 ret.c = vtop->c;
4358 gfunc_param(&gf);
4359 } else {
4360 ret.t = s->t;
4361 ret.r2 = VT_CONST;
4362 /* return in register */
4363 if (is_float(ret.t)) {
4364 ret.r = REG_FRET;
4365 } else {
4366 if ((ret.t & VT_BTYPE) == VT_LLONG)
4367 ret.r2 = REG_LRET;
4368 ret.r = REG_IRET;
4370 ret.c.i = 0;
4372 #ifndef INVERT_FUNC_PARAMS
4373 while (tok != ')') {
4374 expr_eq();
4375 gfunc_param_typed(&gf, s, sa);
4376 if (sa)
4377 sa = sa->next;
4378 if (tok == ',')
4379 next();
4381 #endif
4382 if (sa)
4383 error("too few arguments to function");
4384 skip(')');
4385 gfunc_call(&gf);
4386 /* return value */
4387 vsetc(ret.t, ret.r, &ret.c);
4388 vtop->r2 = ret.r2;
4389 } else {
4390 break;
4395 void uneq(void)
4397 int t;
4399 unary();
4400 if (tok == '=' ||
4401 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
4402 tok == TOK_A_XOR || tok == TOK_A_OR ||
4403 tok == TOK_A_SHL || tok == TOK_A_SAR) {
4404 test_lvalue();
4405 t = tok;
4406 next();
4407 if (t == '=') {
4408 expr_eq();
4409 } else {
4410 vdup();
4411 expr_eq();
4412 gen_op(t & 0x7f);
4414 vstore();
4418 void sum(int l)
4420 int t;
4422 if (l == 0)
4423 uneq();
4424 else {
4425 sum(--l);
4426 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
4427 (l == 1 && (tok == '+' || tok == '-')) ||
4428 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
4429 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
4430 tok == TOK_ULT || tok == TOK_UGE)) ||
4431 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
4432 (l == 5 && tok == '&') ||
4433 (l == 6 && tok == '^') ||
4434 (l == 7 && tok == '|') ||
4435 (l == 8 && tok == TOK_LAND) ||
4436 (l == 9 && tok == TOK_LOR)) {
4437 t = tok;
4438 next();
4439 sum(l);
4440 gen_op(t);
4445 /* only used if non constant */
4446 void eand(void)
4448 int t;
4450 sum(8);
4451 t = 0;
4452 while (1) {
4453 if (tok != TOK_LAND) {
4454 if (t) {
4455 t = gtst(1, t);
4456 vset(VT_INT, VT_JMPI, t);
4458 break;
4460 t = gtst(1, t);
4461 next();
4462 sum(8);
4466 void eor(void)
4468 int t;
4470 eand();
4471 t = 0;
4472 while (1) {
4473 if (tok != TOK_LOR) {
4474 if (t) {
4475 t = gtst(0, t);
4476 vset(VT_INT, VT_JMP, t);
4478 break;
4480 t = gtst(0, t);
4481 next();
4482 eand();
4486 /* XXX: better constant handling */
4487 void expr_eq(void)
4489 int t, u, c, r1, r2, rc;
4491 if (const_wanted) {
4492 sum(10);
4493 if (tok == '?') {
4494 c = vtop->c.i;
4495 vpop();
4496 next();
4497 gexpr();
4498 t = vtop->c.i;
4499 vpop();
4500 skip(':');
4501 expr_eq();
4502 if (c)
4503 vtop->c.i = t;
4505 } else {
4506 eor();
4507 if (tok == '?') {
4508 next();
4509 t = gtst(1, 0);
4510 gexpr();
4511 /* XXX: long long handling ? */
4512 rc = RC_INT;
4513 if (is_float(vtop->t))
4514 rc = RC_FLOAT;
4515 r1 = gv(rc);
4516 vpop();
4517 skip(':');
4518 u = gjmp(0);
4520 gsym(t);
4521 expr_eq();
4522 r2 = gv(rc);
4523 move_reg(r1, r2);
4524 vtop->r = r1;
4525 gsym(u);
4530 void gexpr(void)
4532 while (1) {
4533 expr_eq();
4534 if (tok != ',')
4535 break;
4536 vpop();
4537 next();
4541 /* parse a constant expression and return value in vtop */
4542 void expr_const1(void)
4544 int a;
4545 a = const_wanted;
4546 const_wanted = 1;
4547 expr_eq();
4548 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
4549 expect("constant");
4550 const_wanted = a;
4553 /* parse an integer constant and return its value */
4554 int expr_const(void)
4556 int c;
4557 expr_const1();
4558 c = vtop->c.i;
4559 vpop();
4560 return c;
4563 /* return the label token if current token is a label, otherwise
4564 return zero */
4565 int is_label(void)
4567 int t;
4568 CValue c;
4570 /* fast test first */
4571 if (tok < TOK_UIDENT)
4572 return 0;
4573 /* no need to save tokc since we expect an identifier */
4574 t = tok;
4575 c = tokc;
4576 next();
4577 if (tok == ':') {
4578 next();
4579 return t;
4580 } else {
4581 /* XXX: may not work in all cases (macros ?) */
4582 tok1 = tok;
4583 tok1c = tokc;
4584 tok = t;
4585 tokc = c;
4586 return 0;
4590 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
4592 int a, b, c, d;
4593 Sym *s;
4595 /* generate line number info */
4596 if (do_debug &&
4597 (last_line_num != line_num || last_ind != ind)) {
4598 put_stabn(N_SLINE, 0, line_num, ind - func_ind);
4599 last_ind = ind;
4600 last_line_num = line_num;
4603 if (tok == TOK_IF) {
4604 /* if test */
4605 next();
4606 skip('(');
4607 gexpr();
4608 skip(')');
4609 a = gtst(1, 0);
4610 block(bsym, csym, case_sym, def_sym, case_reg);
4611 c = tok;
4612 if (c == TOK_ELSE) {
4613 next();
4614 d = gjmp(0);
4615 gsym(a);
4616 block(bsym, csym, case_sym, def_sym, case_reg);
4617 gsym(d); /* patch else jmp */
4618 } else
4619 gsym(a);
4620 } else if (tok == TOK_WHILE) {
4621 next();
4622 d = ind;
4623 skip('(');
4624 gexpr();
4625 skip(')');
4626 a = gtst(1, 0);
4627 b = 0;
4628 block(&a, &b, case_sym, def_sym, case_reg);
4629 oad(0xe9, d - ind - 5); /* jmp */
4630 gsym(a);
4631 gsym_addr(b, d);
4632 } else if (tok == '{') {
4633 next();
4634 /* declarations */
4635 s = local_stack.top;
4636 while (tok != '}') {
4637 decl(VT_LOCAL);
4638 if (tok != '}')
4639 block(bsym, csym, case_sym, def_sym, case_reg);
4641 /* pop locally defined symbols */
4642 sym_pop(&local_stack, s);
4643 next();
4644 } else if (tok == TOK_RETURN) {
4645 next();
4646 if (tok != ';') {
4647 gexpr();
4648 gen_assign_cast(func_vt);
4649 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
4650 /* if returning structure, must copy it to implicit
4651 first pointer arg location */
4652 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
4653 indir();
4654 vswap();
4655 /* copy structure value to pointer */
4656 vstore();
4657 } else if (is_float(func_vt)) {
4658 gv(RC_FRET);
4659 } else {
4660 gv(RC_IRET);
4662 vpop();
4664 skip(';');
4665 rsym = gjmp(rsym); /* jmp */
4666 } else if (tok == TOK_BREAK) {
4667 /* compute jump */
4668 if (!bsym)
4669 error("cannot break");
4670 *bsym = gjmp(*bsym);
4671 next();
4672 skip(';');
4673 } else if (tok == TOK_CONTINUE) {
4674 /* compute jump */
4675 if (!csym)
4676 error("cannot continue");
4677 *csym = gjmp(*csym);
4678 next();
4679 skip(';');
4680 } else if (tok == TOK_FOR) {
4681 int e;
4682 next();
4683 skip('(');
4684 if (tok != ';') {
4685 gexpr();
4686 vpop();
4688 skip(';');
4689 d = ind;
4690 c = ind;
4691 a = 0;
4692 b = 0;
4693 if (tok != ';') {
4694 gexpr();
4695 a = gtst(1, 0);
4697 skip(';');
4698 if (tok != ')') {
4699 e = gjmp(0);
4700 c = ind;
4701 gexpr();
4702 vpop();
4703 oad(0xe9, d - ind - 5); /* jmp */
4704 gsym(e);
4706 skip(')');
4707 block(&a, &b, case_sym, def_sym, case_reg);
4708 oad(0xe9, c - ind - 5); /* jmp */
4709 gsym(a);
4710 gsym_addr(b, c);
4711 } else
4712 if (tok == TOK_DO) {
4713 next();
4714 a = 0;
4715 b = 0;
4716 d = ind;
4717 block(&a, &b, case_sym, def_sym, case_reg);
4718 skip(TOK_WHILE);
4719 skip('(');
4720 gsym(b);
4721 gexpr();
4722 c = gtst(0, 0);
4723 gsym_addr(c, d);
4724 skip(')');
4725 gsym(a);
4726 skip(';');
4727 } else
4728 if (tok == TOK_SWITCH) {
4729 next();
4730 skip('(');
4731 gexpr();
4732 /* XXX: other types than integer */
4733 case_reg = gv(RC_INT);
4734 vpop();
4735 skip(')');
4736 a = 0;
4737 b = gjmp(0); /* jump to first case */
4738 c = 0;
4739 block(&a, csym, &b, &c, case_reg);
4740 /* if no default, jmp after switch */
4741 if (c == 0)
4742 c = ind;
4743 /* default label */
4744 gsym_addr(b, c);
4745 /* break label */
4746 gsym(a);
4747 } else
4748 if (tok == TOK_CASE) {
4749 int v1, v2;
4750 if (!case_sym)
4751 expect("switch");
4752 next();
4753 v1 = expr_const();
4754 v2 = v1;
4755 if (gnu_ext && tok == TOK_DOTS) {
4756 next();
4757 v2 = expr_const();
4758 if (v2 < v1)
4759 warning("empty case range");
4761 /* since a case is like a label, we must skip it with a jmp */
4762 b = gjmp(0);
4763 gsym(*case_sym);
4764 vset(VT_INT, case_reg, 0);
4765 vpushi(v1);
4766 if (v1 == v2) {
4767 gen_op(TOK_EQ);
4768 *case_sym = gtst(1, 0);
4769 } else {
4770 gen_op(TOK_GE);
4771 *case_sym = gtst(1, 0);
4772 vset(VT_INT, case_reg, 0);
4773 vpushi(v2);
4774 gen_op(TOK_LE);
4775 *case_sym = gtst(1, *case_sym);
4777 gsym(b);
4778 skip(':');
4779 block(bsym, csym, case_sym, def_sym, case_reg);
4780 } else
4781 if (tok == TOK_DEFAULT) {
4782 next();
4783 skip(':');
4784 if (!def_sym)
4785 expect("switch");
4786 if (*def_sym)
4787 error("too many 'default'");
4788 *def_sym = ind;
4789 block(bsym, csym, case_sym, def_sym, case_reg);
4790 } else
4791 if (tok == TOK_GOTO) {
4792 next();
4793 s = sym_find1(&label_stack, tok);
4794 /* put forward definition if needed */
4795 if (!s)
4796 s = sym_push1(&label_stack, tok, VT_FORWARD, 0);
4797 /* label already defined */
4798 if (s->t & VT_FORWARD)
4799 s->c = gjmp(s->c); /* jmp xxx */
4800 else
4801 oad(0xe9, s->c - ind - 5); /* jmp xxx */
4802 next();
4803 skip(';');
4804 } else {
4805 b = is_label();
4806 if (b) {
4807 /* label case */
4808 s = sym_find1(&label_stack, b);
4809 if (s) {
4810 if (!(s->t & VT_FORWARD))
4811 error("multiple defined label");
4812 gsym(s->c);
4813 s->c = ind;
4814 s->t = 0;
4815 } else {
4816 sym_push1(&label_stack, b, 0, ind);
4818 /* we accept this, but it is a mistake */
4819 if (tok == '}')
4820 warning("deprecated use of label at end of compound statement");
4821 else
4822 block(bsym, csym, case_sym, def_sym, case_reg);
4823 } else {
4824 /* expression case */
4825 if (tok != ';') {
4826 gexpr();
4827 vpop();
4829 skip(';');
4834 /* t is the array or struct type. c is the array or struct
4835 address. cur_index/cur_field is the pointer to the current
4836 value. 'size_only' is true if only size info is needed (only used
4837 in arrays) */
4838 void decl_designator(int t, int r, int c,
4839 int *cur_index, Sym **cur_field,
4840 int size_only)
4842 Sym *s, *f;
4843 int notfirst, index, align, l;
4845 notfirst = 0;
4846 if (gnu_ext && (l = is_label()) != 0)
4847 goto struct_field;
4849 while (tok == '[' || tok == '.') {
4850 if (tok == '[') {
4851 if (!(t & VT_ARRAY))
4852 expect("array type");
4853 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
4854 next();
4855 index = expr_const();
4856 if (index < 0 || (s->c >= 0 && index >= s->c))
4857 expect("invalid index");
4858 skip(']');
4859 if (!notfirst)
4860 *cur_index = index;
4861 t = pointed_type(t);
4862 c += index * type_size(t, &align);
4863 } else {
4864 next();
4865 l = tok;
4866 next();
4867 struct_field:
4868 if ((t & VT_BTYPE) != VT_STRUCT)
4869 expect("struct/union type");
4870 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4871 l |= SYM_FIELD;
4872 f = s->next;
4873 while (f) {
4874 if (f->v == l)
4875 break;
4876 f = f->next;
4878 if (!f)
4879 expect("field");
4880 if (!notfirst)
4881 *cur_field = f;
4882 t = f->t | (t & ~VT_TYPE);
4883 c += f->c;
4885 notfirst = 1;
4887 if (notfirst) {
4888 if (tok == '=') {
4889 next();
4890 } else {
4891 if (!gnu_ext)
4892 expect("=");
4894 } else {
4895 if (t & VT_ARRAY) {
4896 index = *cur_index;
4897 t = pointed_type(t);
4898 c += index * type_size(t, &align);
4899 } else {
4900 f = *cur_field;
4901 if (!f)
4902 error("too many field init");
4903 t = f->t | (t & ~VT_TYPE);
4904 c += f->c;
4907 decl_initializer(t, r, c, 0, size_only);
4910 #define EXPR_VAL 0
4911 #define EXPR_CONST 1
4912 #define EXPR_ANY 2
4914 /* store a value or an expression directly in global data or in local array */
4915 void init_putv(int t, int r, int c,
4916 int v, int expr_type)
4918 int saved_global_expr, bt;
4920 switch(expr_type) {
4921 case EXPR_VAL:
4922 vpushi(v);
4923 break;
4924 case EXPR_CONST:
4925 /* compound literals must be allocated globally in this case */
4926 saved_global_expr = global_expr;
4927 global_expr = 1;
4928 expr_const1();
4929 global_expr = saved_global_expr;
4930 break;
4931 case EXPR_ANY:
4932 expr_eq();
4933 break;
4936 if ((r & VT_VALMASK) == VT_CONST) {
4937 /* XXX: do casting */
4938 /* XXX: not portable */
4939 bt = vtop->t & VT_BTYPE;
4940 switch(bt) {
4941 case VT_BYTE:
4942 *(char *)c = vtop->c.i;
4943 break;
4944 case VT_SHORT:
4945 *(short *)c = vtop->c.i;
4946 break;
4947 case VT_DOUBLE:
4948 *(double *)c = vtop->c.d;
4949 break;
4950 case VT_LDOUBLE:
4951 *(long double *)c = vtop->c.ld;
4952 break;
4953 #if 0
4954 case VT_LLONG:
4955 *(long long *)c = vtop->c.ll;
4956 break;
4957 #endif
4958 default:
4959 *(int *)c = vtop->c.i;
4960 break;
4962 vpop();
4963 } else {
4964 vset(t, r, c);
4965 vswap();
4966 vstore();
4967 vpop();
4971 /* put zeros for variable based init */
4972 void init_putz(int t, int r, int c, int size)
4974 GFuncContext gf;
4976 if ((r & VT_VALMASK) == VT_CONST) {
4977 /* nothing to do because global are already set to zero */
4978 } else {
4979 gfunc_start(&gf);
4980 vpushi(size);
4981 gfunc_param(&gf);
4982 vpushi(0);
4983 gfunc_param(&gf);
4984 vset(VT_INT, VT_LOCAL, c);
4985 gfunc_param(&gf);
4986 vpushi((int)&memset);
4987 gfunc_call(&gf);
4991 /* 't' contains the type and storage info. c is the address of the
4992 object. 'first' is true if array '{' must be read (multi dimension
4993 implicit array init handling). 'size_only' is true if size only
4994 evaluation is wanted (only for arrays). */
4995 void decl_initializer(int t, int r, int c, int first, int size_only)
4997 int index, array_length, n, no_oblock, nb, parlevel, i;
4998 int t1, size1, align1, expr_type;
4999 Sym *s, *f;
5000 TokenSym *ts;
5002 if (t & VT_ARRAY) {
5003 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5004 n = s->c;
5005 array_length = 0;
5006 t1 = pointed_type(t);
5007 size1 = type_size(t1, &align1);
5009 no_oblock = 1;
5010 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
5011 tok == '{') {
5012 skip('{');
5013 no_oblock = 0;
5016 /* only parse strings here if correct type (otherwise: handle
5017 them as ((w)char *) expressions */
5018 if ((tok == TOK_LSTR &&
5019 (t1 & VT_BTYPE) == VT_INT) ||
5020 (tok == TOK_STR &&
5021 (t1 & VT_BTYPE) == VT_BYTE)) {
5022 /* XXX: move multiple string parsing in parser ? */
5023 while (tok == TOK_STR || tok == TOK_LSTR) {
5024 ts = tokc.ts;
5025 /* compute maximum number of chars wanted */
5026 nb = ts->len;
5027 if (n >= 0 && nb > (n - array_length))
5028 nb = n - array_length;
5029 if (!size_only) {
5030 if (ts->len > nb)
5031 warning("initializer-string for array is too long");
5032 for(i=0;i<nb;i++) {
5033 init_putv(t1, r, c + (array_length + i) * size1,
5034 ts->str[i], EXPR_VAL);
5037 array_length += nb;
5038 next();
5040 /* only add trailing zero if enough storage (no
5041 warning in this case since it is standard) */
5042 if (n < 0 || array_length < n) {
5043 if (!size_only) {
5044 init_putv(t1, r, c + (array_length * size1), 0, EXPR_VAL);
5046 array_length++;
5048 } else {
5049 index = 0;
5050 while (tok != '}') {
5051 decl_designator(t, r, c, &index, NULL, size_only);
5052 if (n >= 0 && index >= n)
5053 error("index too large");
5054 /* must put zero in holes (note that doing it that way
5055 ensures that it even works with designators) */
5056 if (!size_only && array_length < index) {
5057 init_putz(t1, r, c + array_length * size1,
5058 (index - array_length) * size1);
5060 index++;
5061 if (index > array_length)
5062 array_length = index;
5063 /* special test for multi dimensional arrays (may not
5064 be strictly correct if designators are used at the
5065 same time) */
5066 if (index >= n && no_oblock)
5067 break;
5068 if (tok == '}')
5069 break;
5070 skip(',');
5073 if (!no_oblock)
5074 skip('}');
5075 /* put zeros at the end */
5076 if (!size_only && n >= 0 && array_length < n) {
5077 init_putz(t1, r, c + array_length * size1,
5078 (n - array_length) * size1);
5080 /* patch type size if needed */
5081 if (n < 0)
5082 s->c = array_length;
5083 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
5084 /* XXX: union needs only one init */
5085 next();
5086 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5087 f = s->next;
5088 array_length = 0;
5089 index = 0;
5090 n = s->c;
5091 while (tok != '}') {
5092 decl_designator(t, r, c, NULL, &f, size_only);
5093 /* fill with zero between fields */
5094 index = f->c;
5095 if (!size_only && array_length < index) {
5096 init_putz(t, r, c + array_length,
5097 index - array_length);
5099 index = index + type_size(f->t, &align1);
5100 if (index > array_length)
5101 array_length = index;
5102 if (tok == '}')
5103 break;
5104 skip(',');
5105 f = f->next;
5107 /* put zeros at the end */
5108 if (!size_only && array_length < n) {
5109 init_putz(t, r, c + array_length,
5110 n - array_length);
5112 skip('}');
5113 } else if (tok == '{') {
5114 next();
5115 decl_initializer(t, r, c, first, size_only);
5116 skip('}');
5117 } else if (size_only) {
5118 /* just skip expression */
5119 parlevel = 0;
5120 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
5121 tok != -1) {
5122 if (tok == '(')
5123 parlevel++;
5124 else if (tok == ')')
5125 parlevel--;
5126 next();
5128 } else {
5129 /* currently, we always use constant expression for globals
5130 (may change for scripting case) */
5131 expr_type = EXPR_CONST;
5132 if ((r & VT_VALMASK) == VT_LOCAL)
5133 expr_type = EXPR_ANY;
5134 init_putv(t, r, c, 0, expr_type);
5138 /* parse an initializer for type 't' if 'has_init' is true, and
5139 allocate space in local or global data space ('r' is either
5140 VT_LOCAL or VT_CONST). The allocated address in returned */
5141 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init)
5143 int size, align, addr, tok1, data_offset;
5144 int *init_str, init_len, level, *saved_macro_ptr;
5145 Section *sec;
5147 size = type_size(t, &align);
5148 /* If unknown size, we must evaluate it before
5149 evaluating initializers because
5150 initializers can generate global data too
5151 (e.g. string pointers or ISOC99 compound
5152 literals). It also simplifies local
5153 initializers handling */
5154 init_len = 0;
5155 init_str = NULL;
5156 saved_macro_ptr = NULL; /* avoid warning */
5157 tok1 = 0;
5158 if (size < 0) {
5159 if (!has_init)
5160 error("unknown type size");
5161 /* get all init string */
5162 level = 0;
5163 while (level > 0 || (tok != ',' && tok != ';')) {
5164 if (tok < 0)
5165 error("unexpected end of file in initializer");
5166 tok_add2(&init_str, &init_len, tok, &tokc);
5167 if (tok == '{')
5168 level++;
5169 else if (tok == '}') {
5170 if (level == 0)
5171 break;
5172 level--;
5174 next();
5176 tok1 = tok;
5177 tok_add(&init_str, &init_len, -1);
5178 tok_add(&init_str, &init_len, 0);
5180 /* compute size */
5181 saved_macro_ptr = macro_ptr;
5182 macro_ptr = init_str;
5183 next();
5184 decl_initializer(t, r, 0, 1, 1);
5185 /* prepare second initializer parsing */
5186 macro_ptr = init_str;
5187 next();
5189 /* if still unknown size, error */
5190 size = type_size(t, &align);
5191 if (size < 0)
5192 error("unknown type size");
5194 /* take into account specified alignment if bigger */
5195 if (ad->aligned > align)
5196 align = ad->aligned;
5197 if ((r & VT_VALMASK) == VT_LOCAL) {
5198 loc = (loc - size) & -align;
5199 addr = loc;
5200 } else {
5201 /* compute section */
5202 sec = ad->section;
5203 if (!sec) {
5204 if (has_init)
5205 sec = data_section;
5206 else
5207 sec = bss_section;
5209 data_offset = (int)sec->data_ptr;
5210 data_offset = (data_offset + align - 1) & -align;
5211 addr = data_offset;
5212 /* very important to increment global
5213 pointer at this time because
5214 initializers themselves can create new
5215 initializers */
5216 data_offset += size;
5217 /* handles bounds */
5218 if (do_bounds_check) {
5219 int *bounds_ptr;
5220 /* first, we need to add at least one byte between each region */
5221 data_offset++;
5222 /* then add global data info */
5223 bounds_ptr = (int *)bounds_section->data_ptr;
5224 *bounds_ptr++ = addr;
5225 *bounds_ptr++ = size;
5226 bounds_section->data_ptr = (unsigned char *)bounds_ptr;
5228 sec->data_ptr = (unsigned char *)data_offset;
5230 if (has_init) {
5231 decl_initializer(t, r, addr, 1, 0);
5232 /* restore parse state if needed */
5233 if (init_str) {
5234 free(init_str);
5235 macro_ptr = saved_macro_ptr;
5236 tok = tok1;
5239 return addr;
5242 void put_func_debug(int t)
5244 int bind;
5245 char buf[512];
5247 if (t & VT_STATIC)
5248 bind = STB_LOCAL;
5249 else
5250 bind = STB_GLOBAL;
5251 put_elf_sym(symtab_section, ind, 0,
5252 ELF32_ST_INFO(bind, STT_FUNC), 0,
5253 cur_text_section->sh_num, funcname);
5254 /* stabs info */
5255 /* XXX: we put here a dummy type */
5256 snprintf(buf, sizeof(buf), "%s:%c1",
5257 funcname, t & VT_STATIC ? 'f' : 'F');
5258 put_stabs(buf, N_FUN, 0, line_num, ind);
5259 func_ind = ind;
5260 last_ind = 0;
5261 last_line_num = 0;
5264 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5265 void decl(int l)
5267 int t, b, v, addr, has_init, r;
5268 Sym *sym;
5269 AttributeDef ad;
5271 while (1) {
5272 if (!parse_btype(&b, &ad)) {
5273 /* skip redundant ';' */
5274 /* XXX: find more elegant solution */
5275 if (tok == ';') {
5276 next();
5277 continue;
5279 /* special test for old K&R protos without explicit int
5280 type. Only accepted when defining global data */
5281 if (l == VT_LOCAL || tok < TOK_DEFINE)
5282 break;
5283 b = VT_INT;
5285 if (((b & VT_BTYPE) == VT_ENUM ||
5286 (b & VT_BTYPE) == VT_STRUCT) &&
5287 tok == ';') {
5288 /* we accept no variable after */
5289 next();
5290 continue;
5292 while (1) { /* iterate thru each declaration */
5293 t = type_decl(&v, b, TYPE_DIRECT);
5294 /* currently, we do not parse attribute in
5295 type_decl(). May change if needed */
5296 if (tok == TOK___ATTRIBUTE__)
5297 parse_attribute(&ad);
5298 #if 0
5300 char buf[500];
5301 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
5302 printf("type = '%s'\n", buf);
5304 #endif
5305 if (tok == '{') {
5306 if (l == VT_LOCAL)
5307 error("cannot use local functions");
5308 if (!(t & VT_FUNC))
5309 expect("function definition");
5310 /* compute text section */
5311 cur_text_section = ad.section;
5312 if (!cur_text_section)
5313 cur_text_section = text_section;
5314 ind = (int)cur_text_section->data_ptr;
5315 /* patch forward references */
5316 if ((sym = sym_find(v)) && (sym->r & VT_FORWARD)) {
5317 greloc_patch(sym, ind);
5318 sym->t = t;
5319 } else {
5320 /* put function address */
5321 sym = sym_push1(&global_stack, v, t, ind);
5323 sym->r = VT_CONST;
5324 funcname = get_tok_str(v, NULL);
5325 /* put debug symbol */
5326 if (do_debug)
5327 put_func_debug(t);
5328 /* push a dummy symbol to enable local sym storage */
5329 sym_push1(&local_stack, 0, 0, 0);
5330 gfunc_prolog(t);
5331 loc = 0;
5332 rsym = 0;
5333 block(NULL, NULL, NULL, NULL, 0);
5334 gsym(rsym);
5335 gfunc_epilog();
5336 cur_text_section->data_ptr = (unsigned char *)ind;
5337 sym_pop(&label_stack, NULL); /* reset label stack */
5338 sym_pop(&local_stack, NULL); /* reset local stack */
5339 /* end of function */
5340 if (do_debug) {
5341 put_stabn(N_FUN, 0, 0, ind - func_ind);
5343 funcname = ""; /* for safety */
5344 func_vt = VT_VOID; /* for safety */
5345 break;
5346 } else {
5347 if (b & VT_TYPEDEF) {
5348 /* save typedefed type */
5349 /* XXX: test storage specifiers ? */
5350 sym_push(v, t | VT_TYPEDEF, 0, 0);
5351 } else if ((t & VT_BTYPE) == VT_FUNC) {
5352 /* external function definition */
5353 external_sym(v, t, 0);
5354 } else {
5355 /* not lvalue if array */
5356 r = 0;
5357 if (!(t & VT_ARRAY))
5358 r |= VT_LVAL;
5359 if (b & VT_EXTERN) {
5360 /* external variable */
5361 external_sym(v, t, r);
5362 } else {
5363 if (t & VT_STATIC)
5364 r |= VT_CONST;
5365 else
5366 r |= l;
5367 has_init = (tok == '=');
5368 if (has_init)
5369 next();
5370 addr = decl_initializer_alloc(t, &ad, r,
5371 has_init);
5372 if (l == VT_CONST) {
5373 /* global scope: see if already defined */
5374 sym = sym_find(v);
5375 if (!sym)
5376 goto do_def;
5377 if (!is_compatible_types(sym->t, t))
5378 error("incompatible types for redefinition of '%s'",
5379 get_tok_str(v, NULL));
5380 if (!(sym->r & VT_FORWARD))
5381 error("redefinition of '%s'", get_tok_str(v, NULL));
5382 greloc_patch(sym, addr);
5383 } else {
5384 do_def:
5385 sym_push(v, t, r, addr);
5389 if (tok != ',') {
5390 skip(';');
5391 break;
5393 next();
5399 /* put all global symbols in the extern stack and do all the
5400 resolving which can be done without using external symbols from DLLs */
5401 /* XXX: could try to verify types, but would not to save them in
5402 extern_stack too */
5403 void resolve_global_syms(void)
5405 Sym *s, *s1, *ext_sym;
5406 Reloc **p;
5408 s = global_stack.top;
5409 while (s != NULL) {
5410 s1 = s->prev;
5411 /* do not save static or typedefed symbols or types */
5412 if (!(s->t & (VT_STATIC | VT_TYPEDEF)) &&
5413 !(s->v & (SYM_FIELD | SYM_STRUCT)) &&
5414 (s->v < SYM_FIRST_ANOM)) {
5415 ext_sym = sym_find1(&extern_stack, s->v);
5416 if (!ext_sym) {
5417 /* if the symbol do not exist, we simply save it */
5418 ext_sym = sym_push1(&extern_stack, s->v, s->t, s->c);
5419 ext_sym->r = s->r;
5420 } else if (ext_sym->r & VT_FORWARD) {
5421 /* external symbol already exists, but only as forward
5422 definition */
5423 if (!(s->r & VT_FORWARD)) {
5424 /* s is not forward, so we can relocate all symbols */
5425 greloc_patch(ext_sym, s->c);
5426 } else {
5427 /* the two symbols are forward: merge them */
5428 p = (Reloc **)&ext_sym->c;
5429 while (*p != NULL)
5430 p = &(*p)->next;
5431 *p = (Reloc *)s->c;
5433 } else {
5434 /* external symbol already exists and is defined :
5435 patch all references to it */
5436 if (!(s->r & VT_FORWARD))
5437 error("'%s' defined twice", get_tok_str(s->v, NULL));
5438 greloc_patch(s, ext_sym->c);
5441 s = s1;
5445 /* compile a C file. Return non zero if errors. */
5446 int tcc_compile_file(const char *filename1)
5448 Sym *define_start;
5449 char buf[512];
5451 line_num = 1;
5452 funcname = "";
5453 filename = (char *)filename1;
5455 file = fopen(filename, "r");
5456 if (!file)
5457 error("file '%s' not found", filename);
5458 include_stack_ptr = include_stack;
5459 ifdef_stack_ptr = ifdef_stack;
5461 vtop = vstack - 1;
5462 anon_sym = SYM_FIRST_ANOM;
5464 /* file info: full path + filename */
5465 if (do_debug) {
5466 getcwd(buf, sizeof(buf));
5467 pstrcat(buf, sizeof(buf), "/");
5468 put_stabs(buf, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5469 put_stabs(filename, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5471 /* define common 'char *' type because it is often used internally
5472 for arrays and struct dereference */
5473 char_pointer_type = mk_pointer(VT_BYTE);
5475 define_start = define_stack.top;
5476 inp();
5477 ch = '\n'; /* needed to parse correctly first preprocessor command */
5478 next();
5479 decl(VT_CONST);
5480 if (tok != -1)
5481 expect("declaration");
5482 fclose(file);
5484 /* end of translation unit info */
5485 if (do_debug) {
5486 put_stabn(N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5489 /* reset define stack, but leave -Dsymbols (may be incorrect if
5490 they are undefined) */
5491 sym_pop(&define_stack, define_start);
5493 resolve_global_syms();
5495 sym_pop(&global_stack, NULL);
5497 return 0;
5500 /* define a symbol. A value can also be provided with the '=' operator */
5501 /* XXX: currently only handles integers and string defines. should use
5502 tcc parser, but would need a custom 'FILE *' */
5503 void define_symbol(const char *sym)
5505 TokenSym *ts;
5506 int *str, len;
5507 CValue cval;
5508 const char *p;
5509 char buf[256];
5511 p = strchr(sym, '=');
5512 if (!p) {
5513 pstrcpy(buf, sizeof(buf), sym);
5514 p = "1";
5515 } else {
5516 len = p - sym;
5517 if (len > sizeof(buf) - 1)
5518 len = sizeof(buf) - 1;
5519 memcpy(buf, sym, len);
5520 buf[len] = '\0';
5521 p++;
5524 ts = tok_alloc(buf, 0);
5525 str = NULL;
5526 len = 0;
5527 if (isnum(*p)) {
5528 /* integer case */
5529 cval.i = atoi(p);
5530 tok_add2(&str, &len, TOK_CINT, &cval);
5531 } else {
5532 /* string case */
5533 cval.ts = tok_alloc(p, 0);
5534 tok_add2(&str, &len, TOK_STR, &cval);
5536 tok_add(&str, &len, 0);
5537 sym_push1(&define_stack, ts->tok, MACRO_OBJ, (int)str);
5540 void undef_symbol(const char *sym)
5542 TokenSym *ts;
5543 Sym *s;
5544 printf("undef %s\n", sym);
5545 ts = tok_alloc(sym, 0);
5546 s = sym_find1(&define_stack, tok);
5547 /* undefine symbol by putting an invalid name */
5548 if (s)
5549 sym_undef(&define_stack, s);
5552 /* open a dynamic library so that its symbol are available for
5553 compiled programs */
5554 void open_dll(char *libname)
5556 char buf[1024];
5557 void *h;
5559 snprintf(buf, sizeof(buf), "lib%s.so", libname);
5560 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
5561 if (!h)
5562 error((char *)dlerror());
5565 static void *resolve_sym(const char *sym)
5567 void *ptr;
5568 if (do_bounds_check) {
5569 ptr = bound_resolve_sym(sym);
5570 if (ptr)
5571 return ptr;
5573 return dlsym(NULL, sym);
5576 void resolve_extern_syms(void)
5578 Sym *s, *s1;
5579 char *str;
5580 int addr;
5582 s = extern_stack.top;
5583 while (s != NULL) {
5584 s1 = s->prev;
5585 if (s->r & VT_FORWARD) {
5586 /* if there is at least one relocation to do, then find it
5587 and patch it */
5588 if (s->c) {
5589 str = get_tok_str(s->v, NULL);
5590 addr = (int)resolve_sym(str);
5591 if (!addr)
5592 error("unresolved external reference '%s'", str);
5593 greloc_patch(s, addr);
5596 s = s1;
5600 static int put_elf_str(Section *s, const char *sym)
5602 int c, offset;
5603 offset = s->data_ptr - s->data;
5604 for(;;) {
5605 c = *sym++;
5606 *s->data_ptr++ = c;
5607 if (c == '\0')
5608 break;
5610 return offset;
5613 static void put_elf_sym(Section *s,
5614 unsigned long value, unsigned long size,
5615 int info, int other, int shndx, const char *name)
5617 int name_offset;
5618 Elf32_Sym *sym;
5620 sym = (Elf32_Sym *)s->data_ptr;
5621 if (name)
5622 name_offset = put_elf_str(s->link, name);
5623 else
5624 name_offset = 0;
5625 sym->st_name = name_offset;
5626 sym->st_value = value;
5627 sym->st_size = size;
5628 sym->st_info = info;
5629 sym->st_other = other;
5630 sym->st_shndx = shndx;
5631 s->data_ptr += sizeof(Elf32_Sym);
5634 /* put stab debug information */
5636 typedef struct {
5637 unsigned long n_strx; /* index into string table of name */
5638 unsigned char n_type; /* type of symbol */
5639 unsigned char n_other; /* misc info (usually empty) */
5640 unsigned short n_desc; /* description field */
5641 unsigned long n_value; /* value of symbol */
5642 } Stab_Sym;
5644 static void put_stabs(const char *str, int type, int other, int desc, int value)
5646 Stab_Sym *sym;
5648 sym = (Stab_Sym *)stab_section->data_ptr;
5649 if (str) {
5650 sym->n_strx = put_elf_str(stabstr_section, str);
5651 } else {
5652 sym->n_strx = 0;
5654 sym->n_type = type;
5655 sym->n_other = other;
5656 sym->n_desc = desc;
5657 sym->n_value = value;
5659 stab_section->data_ptr += sizeof(Stab_Sym);
5662 static void put_stabn(int type, int other, int desc, int value)
5664 put_stabs(NULL, type, other, desc, value);
5667 static void put_stabd(int type, int other, int desc)
5669 put_stabs(NULL, type, other, desc, 0);
5672 /* output an ELF file (currently, only for testing) */
5673 /* XXX: better program header generation */
5674 /* XXX: handle realloc'ed sections (instead of mmaping them) */
5675 /* XXX: generate dynamic reloc info + DLL tables */
5676 /* XXX: generate startup code */
5677 void build_exe(char *filename)
5679 Elf32_Ehdr ehdr;
5680 FILE *f;
5681 int shnum, i, phnum, file_offset, offset, size, j;
5682 Section *sec, *strsec;
5683 Elf32_Shdr *shdr, *sh;
5684 Elf32_Phdr *phdr, *ph;
5686 memset(&ehdr, 0, sizeof(ehdr));
5688 /* we add a section for symbols */
5689 strsec = new_section(".shstrtab", SHT_STRTAB, 0);
5690 put_elf_str(strsec, "");
5692 /* count number of sections and compute number of program segments */
5693 shnum = 1; /* section index zero is reserved */
5694 phnum = 0;
5695 for(sec = first_section; sec != NULL; sec = sec->next) {
5696 shnum++;
5697 if (sec->sh_flags & SHF_ALLOC)
5698 phnum++;
5700 /* allocate section headers */
5701 shdr = malloc(shnum * sizeof(Elf32_Shdr));
5702 if (!shdr)
5703 error("memory full");
5704 memset(shdr, 0, shnum * sizeof(Elf32_Shdr));
5705 /* allocate program segment headers */
5706 phdr = malloc(phnum * sizeof(Elf32_Phdr));
5707 if (!phdr)
5708 error("memory full");
5709 memset(phdr, 0, phnum * sizeof(Elf32_Phdr));
5711 /* XXX: find correct load order */
5712 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
5713 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
5714 sh = &shdr[i];
5715 sh->sh_name = put_elf_str(strsec, sec->name);
5716 sh->sh_type = sec->sh_type;
5717 sh->sh_flags = sec->sh_flags;
5718 sh->sh_entsize = sec->sh_entsize;
5719 if (sec->link)
5720 sh->sh_link = sec->link->sh_num;
5721 if (sh->sh_type == SHT_STRTAB) {
5722 sh->sh_addralign = 1;
5723 } else if (sh->sh_type == SHT_SYMTAB ||
5724 (sh->sh_flags & SHF_ALLOC) == 0) {
5725 sh->sh_addralign = 4;
5726 } else {
5727 sh->sh_addr = (Elf32_Word)sec->data;
5728 sh->sh_addralign = 4096;
5730 sh->sh_size = (Elf32_Word)sec->data_ptr - (Elf32_Word)sec->data;
5731 /* align to section start */
5732 file_offset = (file_offset + sh->sh_addralign - 1) &
5733 ~(sh->sh_addralign - 1);
5734 sh->sh_offset = file_offset;
5735 file_offset += sh->sh_size;
5737 /* build program headers (simplistic - not fully correct) */
5738 j = 0;
5739 for(i=1;i<shnum;i++) {
5740 sh = &shdr[i];
5741 if (sh->sh_type == SHT_PROGBITS &&
5742 (sh->sh_flags & SHF_ALLOC) != 0) {
5743 ph = &phdr[j++];
5744 ph->p_type = PT_LOAD;
5745 ph->p_offset = sh->sh_offset;
5746 ph->p_vaddr = sh->sh_addr;
5747 ph->p_paddr = ph->p_vaddr;
5748 ph->p_filesz = sh->sh_size;
5749 ph->p_memsz = sh->sh_size;
5750 ph->p_flags = PF_R;
5751 if (sh->sh_flags & SHF_WRITE)
5752 ph->p_flags |= PF_W;
5753 if (sh->sh_flags & SHF_EXECINSTR)
5754 ph->p_flags |= PF_X;
5755 ph->p_align = sh->sh_addralign;
5759 /* align to 4 */
5760 file_offset = (file_offset + 3) & -4;
5762 /* fill header */
5763 ehdr.e_ident[0] = ELFMAG0;
5764 ehdr.e_ident[1] = ELFMAG1;
5765 ehdr.e_ident[2] = ELFMAG2;
5766 ehdr.e_ident[3] = ELFMAG3;
5767 ehdr.e_ident[4] = ELFCLASS32;
5768 ehdr.e_ident[5] = ELFDATA2LSB;
5769 ehdr.e_ident[6] = EV_CURRENT;
5770 ehdr.e_type = ET_EXEC;
5771 ehdr.e_machine = EM_386;
5772 ehdr.e_version = EV_CURRENT;
5773 ehdr.e_entry = 0; /* XXX: patch it */
5774 ehdr.e_phoff = sizeof(Elf32_Ehdr);
5775 ehdr.e_shoff = file_offset;
5776 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
5777 ehdr.e_phentsize = sizeof(Elf32_Phdr);
5778 ehdr.e_phnum = phnum;
5779 ehdr.e_shentsize = sizeof(Elf32_Shdr);
5780 ehdr.e_shnum = shnum;
5781 ehdr.e_shstrndx = shnum - 1;
5783 /* write elf file */
5784 f = fopen(filename, "w");
5785 if (!f)
5786 error("could not write '%s'", filename);
5787 fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
5788 fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
5789 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
5790 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
5791 sh = &shdr[i];
5792 while (offset < sh->sh_offset) {
5793 fputc(0, f);
5794 offset++;
5796 size = sec->data_ptr - sec->data;
5797 fwrite(sec->data, 1, size, f);
5798 offset += size;
5800 while (offset < ehdr.e_shoff) {
5801 fputc(0, f);
5802 offset++;
5804 fwrite(shdr, 1, shnum * sizeof(Elf32_Shdr), f);
5805 fclose(f);
5808 /* print the position in the source file of PC value 'pc' by reading
5809 the stabs debug information */
5810 static void rt_printline(unsigned long wanted_pc)
5812 Stab_Sym *sym, *sym_end;
5813 char func_name[128];
5814 unsigned long func_addr, last_pc, pc;
5815 const char *incl_files[INCLUDE_STACK_SIZE];
5816 int incl_index, len, last_line_num, i;
5817 const char *str, *p;
5819 func_name[0] = '\0';
5820 func_addr = 0;
5821 incl_index = 0;
5822 last_pc = 0xffffffff;
5823 last_line_num = 1;
5824 sym = (Stab_Sym *)stab_section->data + 1;
5825 sym_end = (Stab_Sym *)stab_section->data_ptr;
5826 while (sym < sym_end) {
5827 switch(sym->n_type) {
5828 /* function start or end */
5829 case N_FUN:
5830 if (sym->n_strx == 0) {
5831 func_name[0] = '\0';
5832 func_addr = 0;
5833 } else {
5834 str = stabstr_section->data + sym->n_strx;
5835 p = strchr(str, ':');
5836 if (!p) {
5837 pstrcpy(func_name, sizeof(func_name), str);
5838 } else {
5839 len = p - str;
5840 if (len > sizeof(func_name) - 1)
5841 len = sizeof(func_name) - 1;
5842 memcpy(func_name, str, len);
5843 func_name[len] = '\0';
5845 func_addr = sym->n_value;
5847 break;
5848 /* line number info */
5849 case N_SLINE:
5850 pc = sym->n_value + func_addr;
5851 if (wanted_pc >= last_pc && wanted_pc < pc)
5852 goto found;
5853 last_pc = pc;
5854 last_line_num = sym->n_desc;
5855 break;
5856 /* include files */
5857 case N_BINCL:
5858 str = stabstr_section->data + sym->n_strx;
5859 add_incl:
5860 if (incl_index < INCLUDE_STACK_SIZE) {
5861 incl_files[incl_index++] = str;
5863 break;
5864 case N_EINCL:
5865 if (incl_index > 1)
5866 incl_index--;
5867 break;
5868 case N_SO:
5869 if (sym->n_strx == 0) {
5870 incl_index = 0; /* end of translation unit */
5871 } else {
5872 str = stabstr_section->data + sym->n_strx;
5873 /* do not add path */
5874 len = strlen(str);
5875 if (len > 0 && str[len - 1] != '/')
5876 goto add_incl;
5878 break;
5880 sym++;
5882 /* did not find line number info: */
5883 fprintf(stderr, "(no debug info, pc=0x%08lx): ", wanted_pc);
5884 return;
5885 found:
5886 for(i = 0; i < incl_index - 1; i++)
5887 fprintf(stderr, "In file included from %s\n",
5888 incl_files[i]);
5889 if (incl_index > 0) {
5890 fprintf(stderr, "%s:%d: ",
5891 incl_files[incl_index - 1], last_line_num);
5893 if (func_name[0] != '\0') {
5894 fprintf(stderr, "in function '%s()': ", func_name);
5899 /* signal handler for fatal errors */
5900 static void sig_error(int signum, siginfo_t *siginf, void *puc)
5902 struct ucontext *uc = puc;
5903 unsigned long pc;
5905 #ifdef __i386__
5906 pc = uc->uc_mcontext.gregs[14];
5907 #else
5908 #error please put the right sigcontext field
5909 #endif
5911 rt_printline(pc);
5913 switch(signum) {
5914 case SIGFPE:
5915 switch(siginf->si_code) {
5916 case FPE_INTDIV:
5917 case FPE_FLTDIV:
5918 fprintf(stderr, "division by zero\n");
5919 break;
5920 default:
5921 fprintf(stderr, "floating point exception\n");
5922 break;
5924 break;
5925 case SIGBUS:
5926 case SIGSEGV:
5927 fprintf(stderr, "dereferencing invalid pointer\n");
5928 break;
5929 case SIGILL:
5930 fprintf(stderr, "illegal instruction\n");
5931 break;
5932 case SIGABRT:
5933 fprintf(stderr, "abort() called\n");
5934 break;
5935 default:
5936 fprintf(stderr, "caught signal %d\n", signum);
5937 break;
5939 exit(255);
5942 /* launch the compiled program with the given arguments */
5943 int launch_exe(int argc, char **argv)
5945 Sym *s;
5946 int (*t)();
5947 struct sigaction sigact;
5949 s = sym_find1(&extern_stack, TOK_MAIN);
5950 if (!s || (s->r & VT_FORWARD))
5951 error("main() not defined");
5953 if (do_debug) {
5954 /* install TCC signal handlers to print debug info on fatal
5955 runtime errors */
5956 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
5957 sigact.sa_sigaction = sig_error;
5958 sigemptyset(&sigact.sa_mask);
5959 sigaction(SIGFPE, &sigact, NULL);
5960 sigaction(SIGILL, &sigact, NULL);
5961 sigaction(SIGSEGV, &sigact, NULL);
5962 sigaction(SIGBUS, &sigact, NULL);
5963 sigaction(SIGABRT, &sigact, NULL);
5966 if (do_bounds_check) {
5967 int *p, *p_end;
5968 __bound_init();
5969 /* add all known static regions */
5970 p = (int *)bounds_section->data;
5971 p_end = (int *)bounds_section->data_ptr;
5972 while (p < p_end) {
5973 __bound_new_region((void *)p[0], p[1]);
5974 p += 2;
5978 t = (int (*)())s->c;
5979 return (*t)(argc, argv);
5983 void help(void)
5985 printf("tcc version 0.9.3 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
5986 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
5987 " [-i infile] infile [infile_args...]\n"
5988 "\n"
5989 "-Idir : add include path 'dir'\n"
5990 "-Dsym[=val] : define 'sym' with value 'val'\n"
5991 "-Usym : undefine 'sym'\n"
5992 "-llib : link with dynamic library 'lib'\n"
5993 "-g : generate runtime debug info\n"
5994 "-b : compile with built-in memory and bounds checker (implies -g)\n"
5995 "-i infile : compile infile\n"
5999 int main(int argc, char **argv)
6001 char *p, *r, *outfile;
6002 int optind;
6004 include_paths[0] = "/usr/include";
6005 include_paths[1] = "/usr/lib/tcc";
6006 include_paths[2] = "/usr/local/lib/tcc";
6007 nb_include_paths = 3;
6009 /* add all tokens */
6010 tok_ident = TOK_IDENT;
6011 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";
6012 while (*p) {
6013 r = p;
6014 while (*r++);
6015 tok_alloc(p, r - p - 1);
6016 p = r;
6019 /* standard defines */
6020 define_symbol("__STDC__");
6021 #ifdef __i386__
6022 define_symbol("__i386__");
6023 #endif
6024 /* tiny C specific defines */
6025 define_symbol("__TINYC__");
6027 /* create standard sections */
6028 text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
6029 data_section = new_section(".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6030 /* XXX: should change type to SHT_NOBITS */
6031 bss_section = new_section(".bss", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6033 optind = 1;
6034 outfile = NULL;
6035 while (1) {
6036 if (optind >= argc) {
6037 show_help:
6038 help();
6039 return 1;
6041 r = argv[optind];
6042 if (r[0] != '-')
6043 break;
6044 optind++;
6045 if (r[1] == 'I') {
6046 if (nb_include_paths >= INCLUDE_PATHS_MAX)
6047 error("too many include paths");
6048 include_paths[nb_include_paths++] = r + 2;
6049 } else if (r[1] == 'D') {
6050 define_symbol(r + 2);
6051 } else if (r[1] == 'U') {
6052 undef_symbol(r + 2);
6053 } else if (r[1] == 'l') {
6054 open_dll(r + 2);
6055 } else if (r[1] == 'i') {
6056 if (optind >= argc)
6057 goto show_help;
6058 tcc_compile_file(argv[optind++]);
6059 } else if (r[1] == 'b') {
6060 if (!do_bounds_check) {
6061 do_bounds_check = 1;
6062 /* create bounds section for global data */
6063 bounds_section = new_section(".bounds",
6064 SHT_PROGBITS, SHF_ALLOC);
6065 /* debug is implied */
6066 goto debug_opt;
6068 } else if (r[1] == 'g') {
6069 debug_opt:
6070 if (!do_debug) {
6071 do_debug = 1;
6073 /* stab symbols */
6074 stab_section = new_section(".stab", SHT_PROGBITS, 0);
6075 stab_section->sh_entsize = sizeof(Stab_Sym);
6076 stabstr_section = new_section(".stabstr", SHT_STRTAB, 0);
6077 put_elf_str(stabstr_section, "");
6078 stab_section->link = stabstr_section;
6079 /* put first entry */
6080 put_stabs("", 0, 0, 0, 0);
6082 /* elf symbols */
6083 symtab_section = new_section(".symtab", SHT_SYMTAB, 0);
6084 symtab_section->sh_entsize = sizeof(Elf32_Sym);
6085 strtab_section = new_section(".strtab", SHT_STRTAB, 0);
6086 put_elf_str(strtab_section, "");
6087 symtab_section->link = strtab_section;
6088 put_elf_sym(symtab_section, 0, 0, 0, 0, 0, NULL);
6090 } else if (r[1] == 'o') {
6091 /* currently, only for testing, so not documented */
6092 if (optind >= argc)
6093 goto show_help;
6094 outfile = argv[optind++];
6095 } else {
6096 fprintf(stderr, "invalid option -- '%s'\n", r);
6097 exit(1);
6101 tcc_compile_file(argv[optind]);
6103 resolve_extern_syms();
6105 if (outfile) {
6106 build_exe(outfile);
6107 return 0;
6108 } else {
6109 return launch_exe(argc - optind, argv + optind);