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