new_region() fix - added bounded strlen and strcpy
[tinycc/miki.git] / tcc.c
blob520a62bc914fa5de6b4d10ca3b7dc1af33c31df2
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 <malloc.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #ifndef WIN32
32 #include <sys/ucontext.h>
33 #include <sys/mman.h>
34 #endif
35 #include "elf.h"
36 #include "stab.h"
37 #ifndef CONFIG_TCC_STATIC
38 #include <dlfcn.h>
39 #endif
41 //#define DEBUG
42 /* preprocessor debug */
43 //#define PP_DEBUG
45 /* amount of virtual memory associated to a section (currently, we do
46 not realloc them) */
47 #define SECTION_VSIZE (1024 * 1024)
49 #define INCLUDE_STACK_SIZE 32
50 #define IFDEF_STACK_SIZE 64
51 #define VSTACK_SIZE 64
52 #define STRING_MAX_SIZE 1024
53 #define INCLUDE_PATHS_MAX 32
55 #define TOK_HASH_SIZE 2048 /* must be a power of two */
56 #define TOK_ALLOC_INCR 512 /* must be a power of two */
57 #define SYM_HASH_SIZE 1031
59 /* token symbol management */
60 typedef struct TokenSym {
61 struct TokenSym *hash_next;
62 int tok; /* token number */
63 int len;
64 char str[1];
65 } TokenSym;
67 /* constant value */
68 typedef union CValue {
69 long double ld;
70 double d;
71 float f;
72 int i;
73 unsigned int ui;
74 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
75 long long ll;
76 unsigned long long ull;
77 struct TokenSym *ts;
78 struct Sym *sym;
79 int tab[1];
80 } CValue;
82 /* value on stack */
83 typedef struct SValue {
84 int t; /* type */
85 unsigned short r; /* register + flags */
86 unsigned short r2; /* second register, used for 'long long'
87 type. If not used, set to VT_CONST */
88 CValue c; /* constant */
89 } SValue;
91 /* symbol management */
92 typedef struct Sym {
93 int v; /* symbol token */
94 int t; /* associated type */
95 int r; /* associated register */
96 int c; /* associated number */
97 struct Sym *next; /* next related symbol */
98 struct Sym *prev; /* prev symbol in stack */
99 struct Sym *hash_next; /* next symbol in hash table */
100 } Sym;
102 typedef struct SymStack {
103 struct Sym *top;
104 struct Sym *hash[SYM_HASH_SIZE];
105 } SymStack;
107 /* relocation entry (currently only used for functions or variables */
108 typedef struct Reloc {
109 int type; /* type of relocation */
110 int addr; /* address of relocation */
111 struct Reloc *next; /* next relocation */
112 } Reloc;
114 #define RELOC_ADDR32 1 /* 32 bits relocation */
115 #define RELOC_REL32 2 /* 32 bits relative relocation */
117 /* section definition */
118 typedef struct Section {
119 char name[64]; /* section name */
120 unsigned char *data; /* section data */
121 unsigned char *data_ptr; /* current data pointer */
122 int sh_num; /* elf section number */
123 int sh_type; /* elf section type */
124 int sh_flags; /* elf section flags */
125 int sh_entsize; /* elf entry size */
126 struct Section *link; /* link to another section */
127 struct Section *next;
128 } Section;
130 /* GNUC attribute definition */
131 typedef struct AttributeDef {
132 int aligned;
133 Section *section;
134 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
135 } AttributeDef;
137 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
138 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
139 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
141 /* stored in 'Sym.c' field */
142 #define FUNC_NEW 1 /* ansi function prototype */
143 #define FUNC_OLD 2 /* old function prototype */
144 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
146 /* stored in 'Sym.r' field */
147 #define FUNC_CDECL 0 /* standard c call */
148 #define FUNC_STDCALL 1 /* pascal c call */
150 /* field 'Sym.t' for macros */
151 #define MACRO_OBJ 0 /* object like macro */
152 #define MACRO_FUNC 1 /* function like macro */
154 /* type_decl() types */
155 #define TYPE_ABSTRACT 1 /* type without variable */
156 #define TYPE_DIRECT 2 /* type with variable */
158 #define IO_BUF_SIZE 8192
160 typedef struct BufferedFile {
161 unsigned char *buf_ptr;
162 unsigned char *buf_end;
163 int fd;
164 int line_num; /* current line number - here to simply code */
165 char filename[1024]; /* current filename - here to simply code */
166 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
167 } BufferedFile;
169 #define CH_EOB 0 /* end of buffer or '\0' char in file */
170 #define CH_EOF (-1) /* end of file */
172 /* parser */
173 struct BufferedFile *file;
174 int ch, ch1, tok, tok1;
175 CValue tokc, tok1c;
177 /* sections */
178 Section *first_section;
179 int section_num;
180 Section *text_section, *data_section, *bss_section; /* predefined sections */
181 Section *cur_text_section; /* current section where function code is
182 generated */
183 /* bound check related sections */
184 Section *bounds_section; /* contains global data bound description */
185 Section *lbounds_section; /* contains local data bound description */
186 /* debug sections */
187 Section *stab_section, *stabstr_section, *symtab_section, *strtab_section;
189 /* loc : local variable index
190 ind : output code index
191 rsym: return symbol
192 anon_sym: anonymous symbol index
194 int rsym, anon_sym,
195 prog, ind, loc, const_wanted;
196 int global_expr; /* true if compound literals must be allocated
197 globally (used during initializers parsing */
198 int func_vt, func_vc; /* current function return type (used by
199 return instruction) */
200 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
201 int tok_ident;
202 TokenSym **table_ident;
203 TokenSym *hash_ident[TOK_HASH_SIZE];
204 char token_buf[STRING_MAX_SIZE + 1];
205 char *funcname;
206 /* contains global symbols which remain between each translation unit */
207 SymStack extern_stack;
208 SymStack define_stack, global_stack, local_stack, label_stack;
210 SValue vstack[VSTACK_SIZE], *vtop;
211 int *macro_ptr, *macro_ptr_allocated;
212 BufferedFile *include_stack[INCLUDE_STACK_SIZE], **include_stack_ptr;
213 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
214 char *include_paths[INCLUDE_PATHS_MAX];
215 int nb_include_paths;
216 int char_pointer_type;
218 /* compile with debug symbol (and use them if error during execution) */
219 int do_debug = 0;
221 /* compile with built-in memory and bounds checker */
222 int do_bounds_check = 0;
224 /* display benchmark infos */
225 int do_bench = 0;
226 int total_lines;
227 int total_bytes;
229 /* use GNU C extensions */
230 int gnu_ext = 1;
232 /* use Tiny C extensions */
233 int tcc_ext = 1;
235 /* The current value can be: */
236 #define VT_VALMASK 0x00ff
237 #define VT_CONST 0x00f0 /* constant in vc
238 (must be first non register value) */
239 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
240 #define VT_LOCAL 0x00f2 /* offset on stack */
241 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
242 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
243 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
244 #define VT_LVAL 0x0100 /* var is an lvalue */
245 #define VT_FORWARD 0x0200 /* value is forward reference */
246 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
247 char/short stored in integer registers) */
248 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
249 dereferencing value */
251 /* types */
252 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
254 #define VT_INT 0 /* integer type */
255 #define VT_BYTE 1 /* signed byte type */
256 #define VT_SHORT 2 /* short type */
257 #define VT_VOID 3 /* void type */
258 #define VT_PTR 4 /* pointer increment */
259 #define VT_ENUM 5 /* enum definition */
260 #define VT_FUNC 6 /* function type */
261 #define VT_STRUCT 7 /* struct/union definition */
262 #define VT_FLOAT 8 /* IEEE float */
263 #define VT_DOUBLE 9 /* IEEE double */
264 #define VT_LDOUBLE 10 /* IEEE long double */
265 #define VT_BOOL 11 /* ISOC99 boolean type */
266 #define VT_LLONG 12 /* 64 bit integer */
267 #define VT_LONG 13 /* long integer (NEVER USED as type, only
268 during parsing) */
269 #define VT_BTYPE 0x000f /* mask for basic type */
270 #define VT_UNSIGNED 0x0010 /* unsigned type */
271 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
272 #define VT_BITFIELD 0x0040 /* bitfield modifier */
274 /* storage */
275 #define VT_EXTERN 0x00000080 /* extern definition */
276 #define VT_STATIC 0x00000100 /* static variable */
277 #define VT_TYPEDEF 0x00000200 /* typedef definition */
279 /* type mask (except storage) */
280 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
282 /* token values */
284 /* warning: the following compare tokens depend on i386 asm code */
285 #define TOK_ULT 0x92
286 #define TOK_UGE 0x93
287 #define TOK_EQ 0x94
288 #define TOK_NE 0x95
289 #define TOK_ULE 0x96
290 #define TOK_UGT 0x97
291 #define TOK_LT 0x9c
292 #define TOK_GE 0x9d
293 #define TOK_LE 0x9e
294 #define TOK_GT 0x9f
296 #define TOK_LAND 0xa0
297 #define TOK_LOR 0xa1
299 #define TOK_DEC 0xa2
300 #define TOK_MID 0xa3 /* inc/dec, to void constant */
301 #define TOK_INC 0xa4
302 #define TOK_UDIV 0xb0 /* unsigned division */
303 #define TOK_UMOD 0xb1 /* unsigned modulo */
304 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
305 #define TOK_CINT 0xb3 /* number in tokc */
306 #define TOK_CCHAR 0xb4 /* char constant in tokc */
307 #define TOK_STR 0xb5 /* pointer to string in tokc */
308 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
309 #define TOK_LCHAR 0xb7
310 #define TOK_LSTR 0xb8
311 #define TOK_CFLOAT 0xb9 /* float constant */
312 #define TOK_CDOUBLE 0xc0 /* double constant */
313 #define TOK_CLDOUBLE 0xc1 /* long double constant */
314 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
315 #define TOK_ADDC1 0xc3 /* add with carry generation */
316 #define TOK_ADDC2 0xc4 /* add with carry use */
317 #define TOK_SUBC1 0xc5 /* add with carry generation */
318 #define TOK_SUBC2 0xc6 /* add with carry use */
319 #define TOK_CUINT 0xc8 /* unsigned int constant */
320 #define TOK_CLLONG 0xc9 /* long long constant */
321 #define TOK_CULLONG 0xca /* unsigned long long constant */
322 #define TOK_ARROW 0xcb
323 #define TOK_DOTS 0xcc /* three dots */
324 #define TOK_SHR 0xcd /* unsigned shift right */
326 #define TOK_SHL 0x01 /* shift left */
327 #define TOK_SAR 0x02 /* signed shift right */
329 /* assignement operators : normal operator or 0x80 */
330 #define TOK_A_MOD 0xa5
331 #define TOK_A_AND 0xa6
332 #define TOK_A_MUL 0xaa
333 #define TOK_A_ADD 0xab
334 #define TOK_A_SUB 0xad
335 #define TOK_A_DIV 0xaf
336 #define TOK_A_XOR 0xde
337 #define TOK_A_OR 0xfc
338 #define TOK_A_SHL 0x81
339 #define TOK_A_SAR 0x82
341 #define TOK_EOF (-1) /* end of file */
343 /* all identificators and strings have token above that */
344 #define TOK_IDENT 256
346 enum {
347 TOK_INT = TOK_IDENT,
348 TOK_VOID,
349 TOK_CHAR,
350 TOK_IF,
351 TOK_ELSE,
352 TOK_WHILE,
353 TOK_BREAK,
354 TOK_RETURN,
355 TOK_FOR,
356 TOK_EXTERN,
357 TOK_STATIC,
358 TOK_UNSIGNED,
359 TOK_GOTO,
360 TOK_DO,
361 TOK_CONTINUE,
362 TOK_SWITCH,
363 TOK_CASE,
365 /* ignored types Must have contiguous values */
366 TOK_CONST,
367 TOK_VOLATILE,
368 TOK_LONG,
369 TOK_REGISTER,
370 TOK_SIGNED,
371 TOK___SIGNED__, /* gcc keyword */
372 TOK_AUTO,
373 TOK_INLINE,
374 TOK___INLINE__, /* gcc keyword */
375 TOK_RESTRICT,
377 /* unsupported type */
378 TOK_FLOAT,
379 TOK_DOUBLE,
380 TOK_BOOL,
382 TOK_SHORT,
383 TOK_STRUCT,
384 TOK_UNION,
385 TOK_TYPEDEF,
386 TOK_DEFAULT,
387 TOK_ENUM,
388 TOK_SIZEOF,
389 TOK___ATTRIBUTE__,
391 /* preprocessor only */
392 TOK_UIDENT, /* first "user" ident (not keyword) */
393 TOK_DEFINE = TOK_UIDENT,
394 TOK_INCLUDE,
395 TOK_IFDEF,
396 TOK_IFNDEF,
397 TOK_ELIF,
398 TOK_ENDIF,
399 TOK_DEFINED,
400 TOK_UNDEF,
401 TOK_ERROR,
402 TOK_LINE,
403 TOK___LINE__,
404 TOK___FILE__,
405 TOK___DATE__,
406 TOK___TIME__,
407 TOK___VA_ARGS__,
409 /* special identifiers */
410 TOK___FUNC__,
411 TOK_MAIN,
412 /* attribute identifiers */
413 TOK_SECTION,
414 TOK___SECTION__,
415 TOK_ALIGNED,
416 TOK___ALIGNED__,
417 TOK_UNUSED,
418 TOK___UNUSED__,
419 TOK_CDECL,
420 TOK___CDECL,
421 TOK___CDECL__,
422 TOK_STDCALL,
423 TOK___STDCALL,
424 TOK___STDCALL__,
425 TOK_NORETURN,
426 TOK___NORETURN__,
429 char *tcc_keywords =
430 "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
431 "unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
432 "register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
433 "float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
434 "sizeof\0__attribute__\0"
435 /* the following are not keywords. They are included to ease parsing */
436 "define\0include\0ifdef\0ifndef\0elif\0endif\0"
437 "defined\0undef\0error\0line\0"
438 "__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0"
439 "__func__\0main\0"
440 /* attributes */
441 "section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0"
442 "cdecl\0__cdecl\0__cdecl__\0stdcall\0__stdcall\0__stdcall__\0"
443 "noreturn\0__noreturn__\0"
446 #ifdef WIN32
447 #define snprintf _snprintf
448 /* currently incorrect */
449 long double strtold(const char *nptr, char **endptr)
451 return (long double)strtod(nptr, endptr);
453 float strtof(const char *nptr, char **endptr)
455 return (float)strtod(nptr, endptr);
457 #else
458 /* XXX: need to define this to use them in non ISOC99 context */
459 extern float strtof (const char *__nptr, char **__endptr);
460 extern long double strtold (const char *__nptr, char **__endptr);
461 #endif
463 void sum(int l);
464 void next(void);
465 void next_nomacro(void);
466 int expr_const(void);
467 void expr_eq(void);
468 void gexpr(void);
469 void decl(int l);
470 void decl_initializer(int t, int r, int c, int first, int size_only);
471 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init);
472 int gv(int rc);
473 void gv2(int rc1, int rc2);
474 void move_reg(int r, int s);
475 void save_regs(void);
476 void save_reg(int r);
477 void vpop(void);
478 void vswap(void);
479 void vdup(void);
480 int get_reg(int rc);
482 void macro_subst(int **tok_str, int *tok_len,
483 Sym **nested_list, int *macro_str);
484 int save_reg_forced(int r);
485 void gen_op(int op);
486 void force_charshort_cast(int t);
487 void gen_cast(int t);
488 void vstore(void);
489 Sym *sym_find(int v);
490 Sym *sym_push(int v, int t, int r, int c);
492 /* type handling */
493 int type_size(int t, int *a);
494 int pointed_type(int t);
495 int pointed_size(int t);
496 int is_compatible_types(int t1, int t2);
497 int parse_btype(int *type_ptr, AttributeDef *ad);
498 int type_decl(AttributeDef *ad, int *v, int t, int td);
500 void error(const char *fmt, ...);
501 void rt_error(unsigned long pc, const char *fmt, ...);
502 void vpushi(int v);
503 void vset(int t, int r, int v);
504 void type_to_str(char *buf, int buf_size,
505 int t, const char *varstr);
507 /* section generation */
508 void greloc(Sym *s, int addr, int type);
509 static int put_elf_str(Section *s, const char *sym);
510 static void put_elf_sym(Section *s,
511 unsigned long value, unsigned long size,
512 int info, int other, int shndx, const char *name);
513 static void put_stabs(const char *str, int type, int other, int desc, int value);
514 static void put_stabn(int type, int other, int desc, int value);
515 static void put_stabd(int type, int other, int desc);
517 /* true if float/double/long double type */
518 static inline int is_float(int t)
520 int bt;
521 bt = t & VT_BTYPE;
522 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
525 #include "bcheck.c"
527 #include "i386-gen.c"
529 #ifdef CONFIG_TCC_STATIC
531 #define RTLD_LAZY 0x001
532 #define RTLD_NOW 0x002
533 #define RTLD_GLOBAL 0x100
535 /* dummy function for profiling */
536 void *dlopen(const char *filename, int flag)
538 return NULL;
541 const char *dlerror(void)
543 return "error";
546 typedef struct TCCSyms {
547 char *str;
548 void *ptr;
549 } TCCSyms;
551 #define TCCSYM(a) { #a, &a, },
553 /* add the symbol you want here if no dynamic linking is done */
554 static TCCSyms tcc_syms[] = {
555 TCCSYM(printf)
556 TCCSYM(fprintf)
557 TCCSYM(fopen)
558 TCCSYM(fclose)
559 { NULL, NULL },
562 void *dlsym(void *handle, const char *symbol)
564 TCCSyms *p;
565 p = tcc_syms;
566 while (p->str != NULL) {
567 if (!strcmp(p->str, symbol))
568 return p->ptr;
569 p++;
571 return NULL;
574 #endif
576 /********************************************************/
577 /* runtime library is there */
578 /* XXX: we suppose that the host compiler handles 'long long'. It
579 would not be difficult to suppress this assumption */
581 long long __divll(long long a, long long b)
583 return a / b;
586 long long __modll(long long a, long long b)
588 return a % b;
591 unsigned long long __divull(unsigned long long a, unsigned long long b)
593 return a / b;
596 unsigned long long __modull(unsigned long long a, unsigned long long b)
598 return a % b;
601 long long __sardi3(long long a, int b)
603 return a >> b;
606 unsigned long long __shrdi3(unsigned long long a, int b)
608 return a >> b;
611 long long __shldi3(long long a, int b)
613 return a << b;
616 float __ulltof(unsigned long long a)
618 return (float)a;
621 double __ulltod(unsigned long long a)
623 return (double)a;
626 long double __ulltold(unsigned long long a)
628 return (long double)a;
631 unsigned long long __ftoull(float a)
633 return (unsigned long long)a;
636 unsigned long long __dtoull(double a)
638 return (unsigned long long)a;
641 unsigned long long __ldtoull(long double a)
643 return (unsigned long long)a;
647 /********************************************************/
649 /* copy a string and truncate it. */
650 char *pstrcpy(char *buf, int buf_size, const char *s)
652 char *q, *q_end;
653 int c;
655 if (buf_size > 0) {
656 q = buf;
657 q_end = buf + buf_size - 1;
658 while (q < q_end) {
659 c = *s++;
660 if (c == '\0')
661 break;
662 *q++ = c;
664 *q = '\0';
666 return buf;
669 /* strcat and truncate. */
670 char *pstrcat(char *buf, int buf_size, const char *s)
672 int len;
673 len = strlen(buf);
674 if (len < buf_size)
675 pstrcpy(buf + len, buf_size - len, s);
676 return buf;
679 Section *new_section(const char *name, int sh_type, int sh_flags)
681 Section *sec, **psec;
682 void *data;
684 sec = malloc(sizeof(Section));
685 if (!sec)
686 error("memory full");
687 memset(sec, 0, sizeof(Section));
688 pstrcpy(sec->name, sizeof(sec->name), name);
689 sec->link = NULL;
690 sec->sh_num = ++section_num;
691 sec->sh_type = sh_type;
692 sec->sh_flags = sh_flags;
693 #ifdef WIN32
694 /* XXX: currently, a single malloc */
695 data = malloc(SECTION_VSIZE);
696 if (data == NULL)
697 error("could not alloc section '%s'", name);
698 #else
699 data = mmap(NULL, SECTION_VSIZE,
700 PROT_EXEC | PROT_READ | PROT_WRITE,
701 MAP_PRIVATE | MAP_ANONYMOUS,
702 -1, 0);
703 if (data == (void *)(-1))
704 error("could not mmap section '%s'", name);
705 #endif
706 sec->data = data;
707 sec->data_ptr = data;
708 psec = &first_section;
709 while (*psec != NULL)
710 psec = &(*psec)->next;
711 sec->next = NULL;
712 *psec = sec;
713 return sec;
716 /* return a reference to a section, and create it if it does not
717 exists */
718 Section *find_section(const char *name)
720 Section *sec;
722 for(sec = first_section; sec != NULL; sec = sec->next) {
723 if (!strcmp(name, sec->name))
724 return sec;
726 /* sections are created as PROGBITS */
727 return new_section(name, SHT_PROGBITS, SHF_ALLOC);
730 /* add a new relocation entry to symbol 's' */
731 void greloc(Sym *s, int addr, int type)
733 Reloc *p;
734 p = malloc(sizeof(Reloc));
735 if (!p)
736 error("memory full");
737 p->type = type;
738 p->addr = addr;
739 p->next = (Reloc *)s->c;
740 s->c = (int)p;
743 /* patch each relocation entry with value 'val' */
744 void greloc_patch(Sym *s, int val)
746 Reloc *p, *p1;
748 p = (Reloc *)s->c;
749 while (p != NULL) {
750 p1 = p->next;
751 greloc_patch1(p, val);
752 free(p);
753 p = p1;
755 s->c = val;
756 s->r &= ~VT_FORWARD;
760 static inline int isid(int c)
762 return (c >= 'a' && c <= 'z') ||
763 (c >= 'A' && c <= 'Z') ||
764 c == '_';
767 static inline int isnum(int c)
769 return c >= '0' && c <= '9';
772 static inline int toup(int c)
774 if (ch >= 'a' && ch <= 'z')
775 return ch - 'a' + 'A';
776 else
777 return ch;
780 void printline(void)
782 BufferedFile **f;
783 for(f = include_stack; f < include_stack_ptr; f++)
784 fprintf(stderr, "In file included from %s:%d:\n",
785 (*f)->filename, (*f)->line_num);
786 fprintf(stderr, "%s:%d: ", file->filename, file->line_num);
789 void error(const char *fmt, ...)
791 va_list ap;
792 va_start(ap, fmt);
793 printline();
794 vfprintf(stderr, fmt, ap);
795 fprintf(stderr, "\n");
796 exit(1);
797 va_end(ap);
800 void expect(const char *msg)
802 error("%s expected", msg);
805 void warning(const char *fmt, ...)
807 va_list ap;
809 va_start(ap, fmt);
810 printline();
811 fprintf(stderr, "warning: ");
812 vfprintf(stderr, fmt, ap);
813 fprintf(stderr, "\n");
814 va_end(ap);
817 void skip(int c)
819 if (tok != c)
820 error("'%c' expected", c);
821 next();
824 void test_lvalue(void)
826 if (!(vtop->r & VT_LVAL))
827 expect("lvalue");
830 TokenSym *tok_alloc(const char *str, int len)
832 TokenSym *ts, **pts, **ptable;
833 int h, i;
835 if (len <= 0)
836 len = strlen(str);
837 h = 1;
838 for(i=0;i<len;i++)
839 h = (h * 263 + ((unsigned char *)str)[i]) & (TOK_HASH_SIZE - 1);
841 pts = &hash_ident[h];
842 while (1) {
843 ts = *pts;
844 if (!ts)
845 break;
846 if (ts->len == len && !memcmp(ts->str, str, len))
847 return ts;
848 pts = &(ts->hash_next);
851 if (tok_ident >= SYM_FIRST_ANOM)
852 error("memory full");
854 /* expand token table if needed */
855 i = tok_ident - TOK_IDENT;
856 if ((i % TOK_ALLOC_INCR) == 0) {
857 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
858 if (!ptable)
859 error("memory full");
860 table_ident = ptable;
863 ts = malloc(sizeof(TokenSym) + len);
864 if (!ts)
865 error("memory full");
866 table_ident[i] = ts;
867 ts->tok = tok_ident++;
868 ts->len = len;
869 ts->hash_next = NULL;
870 memcpy(ts->str, str, len + 1);
871 *pts = ts;
872 return ts;
875 void add_char(char **pp, int c)
877 char *p;
878 p = *pp;
879 if (c == '\'' || c == '\"' || c == '\\') {
880 /* XXX: could be more precise if char or string */
881 *p++ = '\\';
883 if (c >= 32 && c <= 126) {
884 *p++ = c;
885 } else {
886 *p++ = '\\';
887 if (c == '\n') {
888 *p++ = 'n';
889 } else {
890 *p++ = '0' + ((c >> 6) & 7);
891 *p++ = '0' + ((c >> 3) & 7);
892 *p++ = '0' + (c & 7);
895 *pp = p;
898 /* XXX: buffer overflow */
899 char *get_tok_str(int v, CValue *cv)
901 static char buf[STRING_MAX_SIZE + 1];
902 TokenSym *ts;
903 char *p;
904 int i;
906 if (v == TOK_CINT || v == TOK_CUINT) {
907 sprintf(buf, "%u", cv->ui);
908 return buf;
909 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
910 p = buf;
911 *p++ = '\'';
912 add_char(&p, cv->i);
913 *p++ = '\'';
914 *p = '\0';
915 return buf;
916 } else if (v == TOK_STR || v == TOK_LSTR) {
917 ts = cv->ts;
918 p = buf;
919 *p++ = '\"';
920 for(i=0;i<ts->len;i++)
921 add_char(&p, ts->str[i]);
922 *p++ = '\"';
923 *p = '\0';
924 return buf;
925 } else if (v < TOK_IDENT) {
926 p = buf;
927 *p++ = v;
928 *p = '\0';
929 return buf;
930 } else if (v < tok_ident) {
931 return table_ident[v - TOK_IDENT]->str;
932 } else {
933 /* should never happen */
934 return NULL;
938 /* push, without hashing */
939 Sym *sym_push2(Sym **ps, int v, int t, int c)
941 Sym *s;
942 s = malloc(sizeof(Sym));
943 if (!s)
944 error("memory full");
945 s->v = v;
946 s->t = t;
947 s->c = c;
948 s->next = NULL;
949 /* add in stack */
950 s->prev = *ps;
951 *ps = s;
952 return s;
955 /* find a symbol and return its associated structure. 's' is the top
956 of the symbol stack */
957 Sym *sym_find2(Sym *s, int v)
959 while (s) {
960 if (s->v == v)
961 return s;
962 s = s->prev;
964 return NULL;
967 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
969 /* find a symbol and return its associated structure. 'st' is the
970 symbol stack */
971 Sym *sym_find1(SymStack *st, int v)
973 Sym *s;
975 s = st->hash[HASH_SYM(v)];
976 while (s) {
977 if (s->v == v)
978 return s;
979 s = s->hash_next;
981 return NULL;
984 Sym *sym_push1(SymStack *st, int v, int t, int c)
986 Sym *s, **ps;
987 s = sym_push2(&st->top, v, t, c);
988 /* add in hash table */
989 if (v) {
990 ps = &st->hash[HASH_SYM(v)];
991 s->hash_next = *ps;
992 *ps = s;
994 return s;
997 /* find a symbol in the right symbol space */
998 Sym *sym_find(int v)
1000 Sym *s;
1001 s = sym_find1(&local_stack, v);
1002 if (!s)
1003 s = sym_find1(&global_stack, v);
1004 return s;
1007 /* push a given symbol on the symbol stack */
1008 Sym *sym_push(int v, int t, int r, int c)
1010 Sym *s;
1011 if (local_stack.top)
1012 s = sym_push1(&local_stack, v, t, c);
1013 else
1014 s = sym_push1(&global_stack, v, t, c);
1015 s->r = r;
1016 return s;
1019 /* pop symbols until top reaches 'b' */
1020 void sym_pop(SymStack *st, Sym *b)
1022 Sym *s, *ss;
1024 s = st->top;
1025 while(s != b) {
1026 ss = s->prev;
1027 /* free hash table entry, except if symbol was freed (only
1028 used for #undef symbols) */
1029 if (s->v)
1030 st->hash[HASH_SYM(s->v)] = s->hash_next;
1031 free(s);
1032 s = ss;
1034 st->top = b;
1037 /* undefined a hashed symbol (used for #undef). Its name is set to
1038 zero */
1039 void sym_undef(SymStack *st, Sym *s)
1041 Sym **ss;
1042 ss = &st->hash[HASH_SYM(s->v)];
1043 while (*ss != NULL) {
1044 if (*ss == s)
1045 break;
1046 ss = &(*ss)->hash_next;
1048 *ss = s->hash_next;
1049 s->v = 0;
1052 /* I/O layer */
1054 BufferedFile *tcc_open(const char *filename)
1056 int fd;
1057 BufferedFile *bf;
1059 fd = open(filename, O_RDONLY);
1060 if (fd < 0)
1061 return NULL;
1062 bf = malloc(sizeof(BufferedFile));
1063 if (!bf) {
1064 close(fd);
1065 return NULL;
1067 bf->fd = fd;
1068 bf->buf_ptr = bf->buffer;
1069 bf->buf_end = bf->buffer;
1070 bf->buffer[0] = CH_EOB; /* put eob symbol */
1071 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1072 bf->line_num = 1;
1073 // printf("opening '%s'\n", filename);
1074 return bf;
1077 void tcc_close(BufferedFile *bf)
1079 total_lines += bf->line_num;
1080 close(bf->fd);
1081 free(bf);
1084 /* read one char. MUST call tcc_fillbuf if CH_EOB is read */
1085 #define TCC_GETC(bf) (*(bf)->buf_ptr++)
1087 /* fill input buffer and return next char */
1088 int tcc_getc_slow(BufferedFile *bf)
1090 int len;
1091 /* only tries to read if really end of buffer */
1092 if (bf->buf_ptr >= bf->buf_end) {
1093 if (bf->fd != -1) {
1094 len = read(bf->fd, bf->buffer, IO_BUF_SIZE);
1095 if (len < 0)
1096 len = 0;
1097 } else {
1098 len = 0;
1100 total_bytes += len;
1101 bf->buf_ptr = bf->buffer;
1102 bf->buf_end = bf->buffer + len;
1103 *bf->buf_end = CH_EOB;
1105 if (bf->buf_ptr < bf->buf_end) {
1106 return *bf->buf_ptr++;
1107 } else {
1108 bf->buf_ptr = bf->buf_end;
1109 return CH_EOF;
1113 /* no need to put that inline */
1114 void handle_eob(void)
1116 for(;;) {
1117 ch1 = tcc_getc_slow(file);
1118 if (ch1 != CH_EOF)
1119 return;
1121 if (include_stack_ptr == include_stack)
1122 return;
1123 /* add end of include file debug info */
1124 if (do_debug) {
1125 put_stabd(N_EINCL, 0, 0);
1127 /* pop include stack */
1128 tcc_close(file);
1129 include_stack_ptr--;
1130 file = *include_stack_ptr;
1134 /* read next char from current input file */
1135 static inline void inp(void)
1137 ch1 = TCC_GETC(file);
1138 /* end of buffer/file handling */
1139 if (ch1 == CH_EOB)
1140 handle_eob();
1141 if (ch1 == '\n')
1142 file->line_num++;
1143 // printf("ch1=%c 0x%x\n", ch1, ch1);
1146 /* input with '\\n' handling */
1147 static inline void minp(void)
1149 redo:
1150 ch = ch1;
1151 inp();
1152 if (ch == '\\' && ch1 == '\n') {
1153 inp();
1154 goto redo;
1156 //printf("ch=%c 0x%x\n", ch, ch);
1160 /* same as minp, but also skip comments */
1161 void cinp(void)
1163 int c;
1165 if (ch1 == '/') {
1166 inp();
1167 if (ch1 == '/') {
1168 /* single line C++ comments */
1169 inp();
1170 while (ch1 != '\n' && ch1 != -1)
1171 inp();
1172 inp();
1173 ch = ' '; /* return space */
1174 } else if (ch1 == '*') {
1175 /* C comments */
1176 inp();
1177 while (ch1 != -1) {
1178 c = ch1;
1179 inp();
1180 if (c == '*' && ch1 == '/') {
1181 inp();
1182 ch = ' '; /* return space */
1183 break;
1186 } else {
1187 ch = '/';
1189 } else {
1190 minp();
1194 void skip_spaces(void)
1196 while (ch == ' ' || ch == '\t')
1197 cinp();
1200 /* skip block of text until #else, #elif or #endif. skip also pairs of
1201 #if/#endif */
1202 void preprocess_skip(void)
1204 int a;
1205 a = 0;
1206 while (1) {
1207 while (ch != '\n') {
1208 if (ch == -1)
1209 expect("#endif");
1210 cinp();
1212 cinp();
1213 skip_spaces();
1214 if (ch == '#') {
1215 cinp();
1216 next_nomacro();
1217 if (a == 0 &&
1218 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1219 break;
1220 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1221 a++;
1222 else if (tok == TOK_ENDIF)
1223 a--;
1228 /* return the number of additionnal 'ints' necessary to store the
1229 token */
1230 static inline int tok_ext_size(int t)
1232 switch(t) {
1233 /* 4 bytes */
1234 case TOK_CINT:
1235 case TOK_CUINT:
1236 case TOK_CCHAR:
1237 case TOK_LCHAR:
1238 case TOK_STR:
1239 case TOK_LSTR:
1240 case TOK_CFLOAT:
1241 return 1;
1242 case TOK_CDOUBLE:
1243 case TOK_CLLONG:
1244 case TOK_CULLONG:
1245 return 2;
1246 case TOK_CLDOUBLE:
1247 return LDOUBLE_SIZE / 4;
1248 default:
1249 return 0;
1253 void tok_add(int **tok_str, int *tok_len, int t)
1255 int len, *str;
1256 len = *tok_len;
1257 str = *tok_str;
1258 if ((len & 63) == 0) {
1259 str = realloc(str, (len + 64) * sizeof(int));
1260 if (!str)
1261 return;
1262 *tok_str = str;
1264 str[len++] = t;
1265 *tok_len = len;
1268 void tok_add2(int **tok_str, int *tok_len, int t, CValue *cv)
1270 int n, i;
1272 tok_add(tok_str, tok_len, t);
1273 n = tok_ext_size(t);
1274 for(i=0;i<n;i++)
1275 tok_add(tok_str, tok_len, cv->tab[i]);
1278 /* get a token from an integer array and increment pointer accordingly */
1279 int tok_get(int **tok_str, CValue *cv)
1281 int *p, t, n, i;
1283 p = *tok_str;
1284 t = *p++;
1285 n = tok_ext_size(t);
1286 for(i=0;i<n;i++)
1287 cv->tab[i] = *p++;
1288 *tok_str = p;
1289 return t;
1292 /* eval an expression for #if/#elif */
1293 int expr_preprocess(void)
1295 int *str, len, c, t;
1297 str = NULL;
1298 len = 0;
1299 while (1) {
1300 skip_spaces();
1301 if (ch == '\n')
1302 break;
1303 next(); /* do macro subst */
1304 if (tok == TOK_DEFINED) {
1305 next_nomacro();
1306 t = tok;
1307 if (t == '(')
1308 next_nomacro();
1309 c = sym_find1(&define_stack, tok) != 0;
1310 if (t == '(')
1311 next_nomacro();
1312 tok = TOK_CINT;
1313 tokc.i = c;
1314 } else if (tok >= TOK_IDENT) {
1315 /* if undefined macro */
1316 tok = TOK_CINT;
1317 tokc.i = 0;
1319 tok_add2(&str, &len, tok, &tokc);
1321 tok_add(&str, &len, -1); /* simulate end of file */
1322 tok_add(&str, &len, 0);
1323 /* now evaluate C constant expression */
1324 macro_ptr = str;
1325 next();
1326 c = expr_const();
1327 macro_ptr = NULL;
1328 free(str);
1329 return c != 0;
1332 #if defined(DEBUG) || defined(PP_DEBUG)
1333 void tok_print(int *str)
1335 int t;
1336 CValue cval;
1338 while (1) {
1339 t = tok_get(&str, &cval);
1340 if (!t)
1341 break;
1342 printf(" %s", get_tok_str(t, &cval));
1344 printf("\n");
1346 #endif
1348 /* parse after #define */
1349 void parse_define(void)
1351 Sym *s, *first, **ps;
1352 int v, t, *str, len;
1354 v = tok;
1355 /* XXX: should check if same macro (ANSI) */
1356 first = NULL;
1357 t = MACRO_OBJ;
1358 /* '(' must be just after macro definition for MACRO_FUNC */
1359 if (ch == '(') {
1360 next_nomacro();
1361 next_nomacro();
1362 ps = &first;
1363 while (tok != ')') {
1364 if (tok == TOK_DOTS)
1365 tok = TOK___VA_ARGS__;
1366 s = sym_push1(&define_stack, tok | SYM_FIELD, 0, 0);
1367 *ps = s;
1368 ps = &s->next;
1369 next_nomacro();
1370 if (tok != ',')
1371 break;
1372 next_nomacro();
1374 t = MACRO_FUNC;
1376 str = NULL;
1377 len = 0;
1378 while (1) {
1379 skip_spaces();
1380 if (ch == '\n' || ch == -1)
1381 break;
1382 next_nomacro();
1383 tok_add2(&str, &len, tok, &tokc);
1385 tok_add(&str, &len, 0);
1386 #ifdef PP_DEBUG
1387 printf("define %s %d: ", get_tok_str(v, NULL), t);
1388 tok_print(str);
1389 #endif
1390 s = sym_push1(&define_stack, v, t, (int)str);
1391 s->next = first;
1394 void preprocess(void)
1396 int size, i, c;
1397 char buf[1024], *q, *p;
1398 char buf1[1024];
1399 BufferedFile *f;
1400 Sym *s;
1402 cinp();
1403 next_nomacro();
1404 redo:
1405 if (tok == TOK_DEFINE) {
1406 next_nomacro();
1407 parse_define();
1408 } else if (tok == TOK_UNDEF) {
1409 next_nomacro();
1410 s = sym_find1(&define_stack, tok);
1411 /* undefine symbol by putting an invalid name */
1412 if (s)
1413 sym_undef(&define_stack, s);
1414 } else if (tok == TOK_INCLUDE) {
1415 skip_spaces();
1416 if (ch == '<') {
1417 c = '>';
1418 goto read_name;
1419 } else if (ch == '\"') {
1420 c = ch;
1421 read_name:
1422 minp();
1423 q = buf;
1424 while (ch != c && ch != '\n' && ch != -1) {
1425 if ((q - buf) < sizeof(buf) - 1)
1426 *q++ = ch;
1427 minp();
1429 *q = '\0';
1430 } else {
1431 next();
1432 if (tok != TOK_STR)
1433 error("#include syntax error");
1434 pstrcpy(buf, sizeof(buf), get_tok_str(tok, &tokc));
1435 c = '\"';
1437 /* eat all spaces and comments after include */
1438 /* XXX: slightly incorrect */
1439 while (ch1 != '\n' && ch1 != -1)
1440 inp();
1442 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
1443 error("memory full");
1444 if (c == '\"') {
1445 /* first search in current dir if "header.h" */
1446 size = 0;
1447 p = strrchr(file->filename, '/');
1448 if (p)
1449 size = p + 1 - file->filename;
1450 if (size > sizeof(buf1) - 1)
1451 size = sizeof(buf1) - 1;
1452 memcpy(buf1, file->filename, size);
1453 buf1[size] = '\0';
1454 pstrcat(buf1, sizeof(buf1), buf);
1455 f = tcc_open(buf1);
1456 if (f)
1457 goto found;
1459 /* now search in standard include path */
1460 for(i=nb_include_paths - 1;i>=0;i--) {
1461 strcpy(buf1, include_paths[i]);
1462 strcat(buf1, "/");
1463 strcat(buf1, buf);
1464 f = tcc_open(buf1);
1465 if (f)
1466 goto found;
1468 error("include file '%s' not found", buf1);
1469 f = NULL;
1470 found:
1471 /* push current file in stack */
1472 /* XXX: fix current line init */
1473 *include_stack_ptr++ = file;
1474 file = f;
1475 /* add include file debug info */
1476 if (do_debug) {
1477 put_stabs(file->filename, N_BINCL, 0, 0, 0);
1479 } else if (tok == TOK_IFNDEF) {
1480 c = 1;
1481 goto do_ifdef;
1482 } else if (tok == TOK_IF) {
1483 c = expr_preprocess();
1484 goto do_if;
1485 } else if (tok == TOK_IFDEF) {
1486 c = 0;
1487 do_ifdef:
1488 next_nomacro();
1489 c = (sym_find1(&define_stack, tok) != 0) ^ c;
1490 do_if:
1491 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
1492 error("memory full");
1493 *ifdef_stack_ptr++ = c;
1494 goto test_skip;
1495 } else if (tok == TOK_ELSE) {
1496 if (ifdef_stack_ptr == ifdef_stack)
1497 error("#else without matching #if");
1498 if (ifdef_stack_ptr[-1] & 2)
1499 error("#else after #else");
1500 c = (ifdef_stack_ptr[-1] ^= 3);
1501 goto test_skip;
1502 } else if (tok == TOK_ELIF) {
1503 if (ifdef_stack_ptr == ifdef_stack)
1504 error("#elif without matching #if");
1505 c = ifdef_stack_ptr[-1];
1506 if (c > 1)
1507 error("#elif after #else");
1508 /* last #if/#elif expression was true: we skip */
1509 if (c == 1)
1510 goto skip;
1511 c = expr_preprocess();
1512 ifdef_stack_ptr[-1] = c;
1513 test_skip:
1514 if (!(c & 1)) {
1515 skip:
1516 preprocess_skip();
1517 goto redo;
1519 } else if (tok == TOK_ENDIF) {
1520 if (ifdef_stack_ptr == ifdef_stack)
1521 error("#endif without matching #if");
1522 ifdef_stack_ptr--;
1523 } else if (tok == TOK_LINE) {
1524 next();
1525 if (tok != TOK_CINT)
1526 error("#line");
1527 file->line_num = tokc.i;
1528 skip_spaces();
1529 if (ch != '\n') {
1530 next();
1531 if (tok != TOK_STR)
1532 error("#line");
1533 pstrcpy(file->filename, sizeof(file->filename),
1534 get_tok_str(tok, &tokc));
1536 } else if (tok == TOK_ERROR) {
1537 error("#error");
1539 /* ignore other preprocess commands or #! for C scripts */
1540 while (ch != '\n' && ch != -1)
1541 cinp();
1544 /* read a number in base b */
1545 int getn(b)
1547 int n, t;
1548 n = 0;
1549 while (1) {
1550 if (ch >= 'a' && ch <= 'f')
1551 t = ch - 'a' + 10;
1552 else if (ch >= 'A' && ch <= 'F')
1553 t = ch - 'A' + 10;
1554 else if (isnum(ch))
1555 t = ch - '0';
1556 else
1557 break;
1558 if (t < 0 || t >= b)
1559 break;
1560 n = n * b + t;
1561 cinp();
1563 return n;
1566 /* read a character for string or char constant and eval escape codes */
1567 int getq()
1569 int c;
1571 c = ch;
1572 minp();
1573 if (c == '\\') {
1574 if (isnum(ch)) {
1575 /* at most three octal digits */
1576 c = ch - '0';
1577 minp();
1578 if (isnum(ch)) {
1579 c = c * 8 + ch - '0';
1580 minp();
1581 if (isnum(ch)) {
1582 c = c * 8 + ch - '0';
1583 minp();
1586 return c;
1587 } else if (ch == 'x') {
1588 minp();
1589 return getn(16);
1590 } else {
1591 if (ch == 'a')
1592 c = '\a';
1593 else if (ch == 'b')
1594 c = '\b';
1595 else if (ch == 'f')
1596 c = '\f';
1597 else if (ch == 'n')
1598 c = '\n';
1599 else if (ch == 'r')
1600 c = '\r';
1601 else if (ch == 't')
1602 c = '\t';
1603 else if (ch == 'v')
1604 c = '\v';
1605 else if (ch == 'e' && gnu_ext)
1606 c = 27;
1607 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
1608 c = ch;
1609 else
1610 error("invalid escaped char");
1611 minp();
1614 return c;
1617 /* we use 64 bit numbers */
1618 #define BN_SIZE 2
1620 /* bn = (bn << shift) | or_val */
1621 void bn_lshift(unsigned int *bn, int shift, int or_val)
1623 int i;
1624 unsigned int v;
1625 for(i=0;i<BN_SIZE;i++) {
1626 v = bn[i];
1627 bn[i] = (v << shift) | or_val;
1628 or_val = v >> (32 - shift);
1632 void bn_zero(unsigned int *bn)
1634 int i;
1635 for(i=0;i<BN_SIZE;i++) {
1636 bn[i] = 0;
1640 void parse_number(void)
1642 int b, t, shift, frac_bits, s, exp_val;
1643 char *q;
1644 unsigned int bn[BN_SIZE];
1645 double d;
1647 /* number */
1648 q = token_buf;
1649 t = ch;
1650 cinp();
1651 *q++ = t;
1652 b = 10;
1653 if (t == '.') {
1654 /* special dot handling */
1655 if (ch >= '0' && ch <= '9') {
1656 goto float_frac_parse;
1657 } else if (ch == '.') {
1658 cinp();
1659 if (ch != '.')
1660 expect("'.'");
1661 cinp();
1662 tok = TOK_DOTS;
1663 } else {
1664 /* dots */
1665 tok = t;
1667 return;
1668 } else if (t == '0') {
1669 if (ch == 'x' || ch == 'X') {
1670 q--;
1671 cinp();
1672 b = 16;
1673 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1674 q--;
1675 cinp();
1676 b = 2;
1679 /* parse all digits. cannot check octal numbers at this stage
1680 because of floating point constants */
1681 while (1) {
1682 if (ch >= 'a' && ch <= 'f')
1683 t = ch - 'a' + 10;
1684 else if (ch >= 'A' && ch <= 'F')
1685 t = ch - 'A' + 10;
1686 else if (isnum(ch))
1687 t = ch - '0';
1688 else
1689 break;
1690 if (t >= b)
1691 break;
1692 if (q >= token_buf + STRING_MAX_SIZE) {
1693 num_too_long:
1694 error("number too long");
1696 *q++ = ch;
1697 cinp();
1699 if (ch == '.' ||
1700 ((ch == 'e' || ch == 'E') && b == 10) ||
1701 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1702 if (b != 10) {
1703 /* NOTE: strtox should support that for hexa numbers, but
1704 non ISOC99 libcs do not support it, so we prefer to do
1705 it by hand */
1706 /* hexadecimal or binary floats */
1707 /* XXX: handle overflows */
1708 *q = '\0';
1709 if (b == 16)
1710 shift = 4;
1711 else
1712 shift = 2;
1713 bn_zero(bn);
1714 q = token_buf;
1715 while (1) {
1716 t = *q++;
1717 if (t == '\0') {
1718 break;
1719 } else if (t >= 'a') {
1720 t = t - 'a' + 10;
1721 } else if (t >= 'A') {
1722 t = t - 'A' + 10;
1723 } else {
1724 t = t - '0';
1726 bn_lshift(bn, shift, t);
1728 frac_bits = 0;
1729 if (ch == '.') {
1730 cinp();
1731 while (1) {
1732 t = ch;
1733 if (t >= 'a' && t <= 'f') {
1734 t = t - 'a' + 10;
1735 } else if (t >= 'A' && t <= 'F') {
1736 t = t - 'A' + 10;
1737 } else if (t >= '0' && t <= '9') {
1738 t = t - '0';
1739 } else {
1740 break;
1742 if (t >= b)
1743 error("invalid digit");
1744 bn_lshift(bn, shift, t);
1745 frac_bits += shift;
1746 cinp();
1749 if (ch != 'p' && ch != 'P')
1750 error("exponent expected");
1751 cinp();
1752 s = 1;
1753 exp_val = 0;
1754 if (ch == '+') {
1755 cinp();
1756 } else if (ch == '-') {
1757 s = -1;
1758 cinp();
1760 if (ch < '0' || ch > '9')
1761 error("exponent digits expected");
1762 while (ch >= '0' && ch <= '9') {
1763 exp_val = exp_val * 10 + ch - '0';
1764 cinp();
1766 exp_val = exp_val * s;
1768 /* now we can generate the number */
1769 /* XXX: should patch directly float number */
1770 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1771 d = ldexp(d, exp_val - frac_bits);
1772 t = toup(ch);
1773 if (t == 'F') {
1774 cinp();
1775 tok = TOK_CFLOAT;
1776 /* float : should handle overflow */
1777 tokc.f = (float)d;
1778 } else if (t == 'L') {
1779 cinp();
1780 tok = TOK_CLDOUBLE;
1781 /* XXX: not large enough */
1782 tokc.ld = (long double)d;
1783 } else {
1784 tok = TOK_CDOUBLE;
1785 tokc.d = d;
1787 } else {
1788 /* decimal floats */
1789 if (ch == '.') {
1790 if (q >= token_buf + STRING_MAX_SIZE)
1791 goto num_too_long;
1792 *q++ = ch;
1793 cinp();
1794 float_frac_parse:
1795 while (ch >= '0' && ch <= '9') {
1796 if (q >= token_buf + STRING_MAX_SIZE)
1797 goto num_too_long;
1798 *q++ = ch;
1799 cinp();
1802 if (ch == 'e' || ch == 'E') {
1803 if (q >= token_buf + STRING_MAX_SIZE)
1804 goto num_too_long;
1805 *q++ = ch;
1806 cinp();
1807 if (ch == '-' || ch == '+') {
1808 if (q >= token_buf + STRING_MAX_SIZE)
1809 goto num_too_long;
1810 *q++ = ch;
1811 cinp();
1813 if (ch < '0' || ch > '9')
1814 error("exponent digits expected");
1815 while (ch >= '0' && ch <= '9') {
1816 if (q >= token_buf + STRING_MAX_SIZE)
1817 goto num_too_long;
1818 *q++ = ch;
1819 cinp();
1822 *q = '\0';
1823 t = toup(ch);
1824 errno = 0;
1825 if (t == 'F') {
1826 cinp();
1827 tok = TOK_CFLOAT;
1828 tokc.f = strtof(token_buf, NULL);
1829 } else if (t == 'L') {
1830 cinp();
1831 tok = TOK_CLDOUBLE;
1832 tokc.ld = strtold(token_buf, NULL);
1833 } else {
1834 tok = TOK_CDOUBLE;
1835 tokc.d = strtod(token_buf, NULL);
1838 } else {
1839 unsigned long long n, n1;
1840 int lcount;
1842 /* integer number */
1843 *q = '\0';
1844 q = token_buf;
1845 if (b == 10 && *q == '0') {
1846 b = 8;
1847 q++;
1849 n = 0;
1850 while(1) {
1851 t = *q++;
1852 /* no need for checks except for base 10 / 8 errors */
1853 if (t == '\0') {
1854 break;
1855 } else if (t >= 'a') {
1856 t = t - 'a' + 10;
1857 } else if (t >= 'A') {
1858 t = t - 'A' + 10;
1859 } else {
1860 t = t - '0';
1861 if (t >= b)
1862 error("invalid digit");
1864 n1 = n;
1865 n = n * b + t;
1866 /* detect overflow */
1867 if (n < n1)
1868 error("integer constant overflow");
1871 /* XXX: not exactly ANSI compliant */
1872 if ((n & 0xffffffff00000000LL) != 0) {
1873 if ((n >> 63) != 0)
1874 tok = TOK_CULLONG;
1875 else
1876 tok = TOK_CLLONG;
1877 } else if (n > 0x7fffffff) {
1878 tok = TOK_CUINT;
1879 } else {
1880 tok = TOK_CINT;
1882 lcount = 0;
1883 for(;;) {
1884 t = toup(ch);
1885 if (t == 'L') {
1886 if (lcount >= 2)
1887 error("three 'l' in integer constant");
1888 lcount++;
1889 if (lcount == 2) {
1890 if (tok == TOK_CINT)
1891 tok = TOK_CLLONG;
1892 else if (tok == TOK_CUINT)
1893 tok = TOK_CULLONG;
1895 cinp();
1896 } else if (t == 'U') {
1897 if (tok == TOK_CINT)
1898 tok = TOK_CUINT;
1899 else if (tok == TOK_CLLONG)
1900 tok = TOK_CULLONG;
1901 cinp();
1902 } else {
1903 break;
1906 if (tok == TOK_CINT || tok == TOK_CUINT)
1907 tokc.ui = n;
1908 else
1909 tokc.ull = n;
1914 /* return next token without macro substitution */
1915 void next_nomacro1(void)
1917 int b;
1918 char *q;
1919 TokenSym *ts;
1921 /* skip spaces */
1922 while(1) {
1923 while (ch == '\n') {
1924 cinp();
1925 while (ch == ' ' || ch == '\t')
1926 cinp();
1927 if (ch == '#') {
1928 /* preprocessor command if # at start of line after
1929 spaces */
1930 preprocess();
1933 if (ch != ' ' && ch != '\t' && ch != '\f')
1934 break;
1935 cinp();
1937 if (isid(ch)) {
1938 q = token_buf;
1939 *q++ = ch;
1940 cinp();
1941 if (q[-1] == 'L') {
1942 if (ch == '\'') {
1943 tok = TOK_LCHAR;
1944 goto char_const;
1946 if (ch == '\"') {
1947 tok = TOK_LSTR;
1948 goto str_const;
1951 while (isid(ch) || isnum(ch)) {
1952 if (q >= token_buf + STRING_MAX_SIZE)
1953 error("ident too long");
1954 *q++ = ch;
1955 cinp();
1957 *q = '\0';
1958 ts = tok_alloc(token_buf, q - token_buf);
1959 tok = ts->tok;
1960 } else if (isnum(ch) || ch == '.') {
1961 parse_number();
1962 } else if (ch == '\'') {
1963 tok = TOK_CCHAR;
1964 char_const:
1965 minp();
1966 tokc.i = getq();
1967 if (ch != '\'')
1968 expect("\'");
1969 minp();
1970 } else if (ch == '\"') {
1971 tok = TOK_STR;
1972 str_const:
1973 minp();
1974 q = token_buf;
1975 while (ch != '\"') {
1976 b = getq();
1977 if (ch == -1)
1978 error("unterminated string");
1979 if (q >= token_buf + STRING_MAX_SIZE)
1980 error("string too long");
1981 *q++ = b;
1983 *q = '\0';
1984 tokc.ts = tok_alloc(token_buf, q - token_buf);
1985 minp();
1986 } else {
1987 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
1988 /* two chars */
1989 tok = ch;
1990 cinp();
1991 while (*q) {
1992 if (*q == tok && q[1] == ch) {
1993 cinp();
1994 tok = q[2] & 0xff;
1995 /* three chars tests */
1996 if (tok == TOK_SHL || tok == TOK_SAR) {
1997 if (ch == '=') {
1998 tok = tok | 0x80;
1999 cinp();
2001 } else if (tok == TOK_DOTS) {
2002 if (ch != '.')
2003 error("parse error");
2004 cinp();
2006 return;
2008 q = q + 3;
2010 /* single char substitutions */
2011 if (tok == '<')
2012 tok = TOK_LT;
2013 else if (tok == '>')
2014 tok = TOK_GT;
2018 /* return next token without macro substitution. Can read input from
2019 macro_ptr buffer */
2020 void next_nomacro()
2022 if (macro_ptr) {
2023 tok = *macro_ptr;
2024 if (tok)
2025 tok = tok_get(&macro_ptr, &tokc);
2026 } else {
2027 next_nomacro1();
2031 /* substitute args in macro_str and return allocated string */
2032 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
2034 int *st, last_tok, t, notfirst, *str, len;
2035 Sym *s;
2036 TokenSym *ts;
2037 CValue cval;
2039 str = NULL;
2040 len = 0;
2041 last_tok = 0;
2042 while(1) {
2043 t = tok_get(&macro_str, &cval);
2044 if (!t)
2045 break;
2046 if (t == '#') {
2047 /* stringize */
2048 t = tok_get(&macro_str, &cval);
2049 if (!t)
2050 break;
2051 s = sym_find2(args, t);
2052 if (s) {
2053 token_buf[0] = '\0';
2054 st = (int *)s->c;
2055 notfirst = 0;
2056 while (*st) {
2057 if (notfirst)
2058 pstrcat(token_buf, sizeof(token_buf), " ");
2059 t = tok_get(&st, &cval);
2060 pstrcat(token_buf, sizeof(token_buf), get_tok_str(t, &cval));
2061 notfirst = 1;
2063 #ifdef PP_DEBUG
2064 printf("stringize: %s\n", token_buf);
2065 #endif
2066 /* add string */
2067 ts = tok_alloc(token_buf, 0);
2068 cval.ts = ts;
2069 tok_add2(&str, &len, TOK_STR, &cval);
2070 } else {
2071 tok_add2(&str, &len, t, &cval);
2073 } else if (t >= TOK_IDENT) {
2074 s = sym_find2(args, t);
2075 if (s) {
2076 st = (int *)s->c;
2077 /* if '##' is present before or after , no arg substitution */
2078 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
2079 while (*st)
2080 tok_add(&str, &len, *st++);
2081 } else {
2082 macro_subst(&str, &len, nested_list, st);
2084 } else {
2085 tok_add(&str, &len, t);
2087 } else {
2088 tok_add2(&str, &len, t, &cval);
2090 last_tok = t;
2092 tok_add(&str, &len, 0);
2093 return str;
2096 /* handle the '##' operator */
2097 int *macro_twosharps(int *macro_str)
2099 TokenSym *ts;
2100 int *macro_str1, macro_str1_len, *macro_ptr1;
2101 int t;
2102 char *p;
2103 CValue cval;
2105 macro_str1 = NULL;
2106 macro_str1_len = 0;
2107 tok = 0;
2108 while (1) {
2109 next_nomacro();
2110 if (tok == 0)
2111 break;
2112 while (*macro_ptr == TOK_TWOSHARPS) {
2113 macro_ptr++;
2114 macro_ptr1 = macro_ptr;
2115 t = *macro_ptr;
2116 if (t) {
2117 t = tok_get(&macro_ptr, &cval);
2118 /* XXX: we handle only most common cases:
2119 ident + ident or ident + number */
2120 if (tok >= TOK_IDENT &&
2121 (t >= TOK_IDENT || t == TOK_CINT)) {
2122 p = get_tok_str(tok, &tokc);
2123 pstrcpy(token_buf, sizeof(token_buf), p);
2124 p = get_tok_str(t, &cval);
2125 pstrcat(token_buf, sizeof(token_buf), p);
2126 ts = tok_alloc(token_buf, 0);
2127 tok = ts->tok; /* modify current token */
2128 } else {
2129 /* cannot merge tokens: skip '##' */
2130 macro_ptr = macro_ptr1;
2131 break;
2135 tok_add2(&macro_str1, &macro_str1_len, tok, &tokc);
2137 tok_add(&macro_str1, &macro_str1_len, 0);
2138 return macro_str1;
2143 /* do macro substitution of macro_str and add result to
2144 (tok_str,tok_len). If macro_str is NULL, then input stream token is
2145 substituted. 'nested_list' is the list of all macros we got inside
2146 to avoid recursing. */
2147 void macro_subst(int **tok_str, int *tok_len,
2148 Sym **nested_list, int *macro_str)
2150 Sym *s, *args, *sa, *sa1;
2151 int *str, parlevel, len, *mstr, t, *saved_macro_ptr;
2152 int mstr_allocated, *macro_str1;
2153 CValue cval;
2155 saved_macro_ptr = macro_ptr;
2156 macro_ptr = macro_str;
2157 macro_str1 = NULL;
2158 if (macro_str) {
2159 /* first scan for '##' operator handling */
2160 macro_str1 = macro_twosharps(macro_str);
2161 macro_ptr = macro_str1;
2164 while (1) {
2165 next_nomacro();
2166 if (tok == 0)
2167 break;
2168 /* special macros */
2169 if (tok == TOK___LINE__) {
2170 cval.i = file->line_num;
2171 tok_add2(tok_str, tok_len, TOK_CINT, &cval);
2172 } else if (tok == TOK___FILE__) {
2173 cval.ts = tok_alloc(file->filename, 0);
2174 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2175 } else if (tok == TOK___DATE__) {
2176 cval.ts = tok_alloc("Jan 1 1970", 0);
2177 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2178 } else if (tok == TOK___TIME__) {
2179 cval.ts = tok_alloc("00:00:00", 0);
2180 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2181 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
2182 /* if symbol is a macro, prepare substitution */
2183 /* if nested substitution, do nothing */
2184 if (sym_find2(*nested_list, tok))
2185 goto no_subst;
2186 mstr = (int *)s->c;
2187 mstr_allocated = 0;
2188 if (s->t == MACRO_FUNC) {
2189 /* NOTE: we do not use next_nomacro to avoid eating the
2190 next token. XXX: find better solution */
2191 if (macro_ptr) {
2192 t = *macro_ptr;
2193 } else {
2194 while (ch == ' ' || ch == '\t' || ch == '\n')
2195 cinp();
2196 t = ch;
2198 if (t != '(') /* no macro subst */
2199 goto no_subst;
2201 /* argument macro */
2202 next_nomacro();
2203 next_nomacro();
2204 args = NULL;
2205 sa = s->next;
2206 /* NOTE: empty args are allowed, except if no args */
2207 for(;;) {
2208 /* handle '()' case */
2209 if (!args && tok == ')')
2210 break;
2211 if (!sa)
2212 error("macro '%s' used with too many args",
2213 get_tok_str(s->v, 0));
2214 len = 0;
2215 str = NULL;
2216 parlevel = 0;
2217 while ((parlevel > 0 ||
2218 (tok != ')' &&
2219 (tok != ',' ||
2220 sa->v == (TOK___VA_ARGS__ | SYM_FIELD)))) &&
2221 tok != -1) {
2222 if (tok == '(')
2223 parlevel++;
2224 else if (tok == ')')
2225 parlevel--;
2226 tok_add2(&str, &len, tok, &tokc);
2227 next_nomacro();
2229 tok_add(&str, &len, 0);
2230 sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
2231 if (tok == ')')
2232 break;
2233 if (tok != ',')
2234 expect(",");
2235 next_nomacro();
2236 sa = sa->next;
2238 if (sa->next)
2239 error("macro '%s' used with too few args",
2240 get_tok_str(s->v, 0));
2242 /* now subst each arg */
2243 mstr = macro_arg_subst(nested_list, mstr, args);
2244 /* free memory */
2245 sa = args;
2246 while (sa) {
2247 sa1 = sa->prev;
2248 free((int *)sa->c);
2249 free(sa);
2250 sa = sa1;
2252 mstr_allocated = 1;
2254 sym_push2(nested_list, s->v, 0, 0);
2255 macro_subst(tok_str, tok_len, nested_list, mstr);
2256 /* pop nested defined symbol */
2257 sa1 = *nested_list;
2258 *nested_list = sa1->prev;
2259 free(sa1);
2260 if (mstr_allocated)
2261 free(mstr);
2262 } else {
2263 no_subst:
2264 /* no need to add if reading input stream */
2265 if (!macro_str)
2266 return;
2267 tok_add2(tok_str, tok_len, tok, &tokc);
2269 /* only replace one macro while parsing input stream */
2270 if (!macro_str)
2271 return;
2273 macro_ptr = saved_macro_ptr;
2274 if (macro_str1)
2275 free(macro_str1);
2278 /* return next token with macro substitution */
2279 void next(void)
2281 int len, *ptr;
2282 Sym *nested_list;
2284 /* special 'ungettok' case for label parsing */
2285 if (tok1) {
2286 tok = tok1;
2287 tokc = tok1c;
2288 tok1 = 0;
2289 } else {
2290 redo:
2291 if (!macro_ptr) {
2292 /* if not reading from macro substituted string, then try to substitute */
2293 len = 0;
2294 ptr = NULL;
2295 nested_list = NULL;
2296 macro_subst(&ptr, &len, &nested_list, NULL);
2297 if (ptr) {
2298 tok_add(&ptr, &len, 0);
2299 macro_ptr = ptr;
2300 macro_ptr_allocated = ptr;
2301 goto redo;
2303 if (tok == 0)
2304 goto redo;
2305 } else {
2306 next_nomacro();
2307 if (tok == 0) {
2308 /* end of macro string: free it */
2309 free(macro_ptr_allocated);
2310 macro_ptr = NULL;
2311 goto redo;
2315 #if defined(DEBUG)
2316 printf("token = %s\n", get_tok_str(tok, tokc));
2317 #endif
2320 void swap(int *p, int *q)
2322 int t;
2323 t = *p;
2324 *p = *q;
2325 *q = t;
2328 void vsetc(int t, int r, CValue *vc)
2330 if (vtop >= vstack + VSTACK_SIZE)
2331 error("memory full");
2332 /* cannot let cpu flags if other instruction are generated */
2333 /* XXX: VT_JMP test too ? */
2334 if ((vtop->r & VT_VALMASK) == VT_CMP)
2335 gv(RC_INT);
2336 vtop++;
2337 vtop->t = t;
2338 vtop->r = r;
2339 vtop->r2 = VT_CONST;
2340 vtop->c = *vc;
2343 /* push integer constant */
2344 void vpushi(int v)
2346 CValue cval;
2347 cval.i = v;
2348 vsetc(VT_INT, VT_CONST, &cval);
2351 void vset(int t, int r, int v)
2353 CValue cval;
2355 cval.i = v;
2356 vsetc(t, r, &cval);
2359 void vswap(void)
2361 SValue tmp;
2363 tmp = vtop[0];
2364 vtop[0] = vtop[-1];
2365 vtop[-1] = tmp;
2368 void vpushv(SValue *v)
2370 if (vtop >= vstack + VSTACK_SIZE)
2371 error("memory full");
2372 vtop++;
2373 *vtop = *v;
2376 void vdup(void)
2378 vpushv(vtop);
2381 /* save r to the memory stack, and mark it as being free */
2382 void save_reg(int r)
2384 int l, i, saved, t, size, align;
2385 SValue *p, sv;
2387 /* modify all stack values */
2388 saved = 0;
2389 l = 0;
2390 for(p=vstack;p<=vtop;p++) {
2391 i = p->r & VT_VALMASK;
2392 if ((p->r & VT_VALMASK) == r ||
2393 (p->r2 & VT_VALMASK) == r) {
2394 /* must save value on stack if not already done */
2395 if (!saved) {
2396 /* store register in the stack */
2397 t = p->t;
2398 if ((p->r & VT_LVAL) ||
2399 (!is_float(t) && (t & VT_BTYPE) != VT_LLONG))
2400 t = VT_INT;
2401 size = type_size(t, &align);
2402 loc = (loc - size) & -align;
2403 sv.t = t;
2404 sv.r = VT_LOCAL | VT_LVAL;
2405 sv.c.ul = loc;
2406 store(r, &sv);
2407 /* XXX: x86 specific: need to pop fp register ST0 if saved */
2408 if (r == REG_ST0) {
2409 o(0xd9dd); /* fstp %st(1) */
2411 /* special long long case */
2412 if ((p->t & VT_BTYPE) == VT_LLONG) {
2413 sv.c.ul += 4;
2414 store(p->r2, &sv);
2416 l = loc;
2417 saved = 1;
2419 /* mark that stack entry as being saved on the stack */
2420 if (p->r & VT_LVAL)
2421 t = VT_LLOCAL;
2422 else
2423 t = VT_LOCAL;
2424 p->r = VT_LVAL | t;
2425 p->r2 = VT_CONST;
2426 p->c.ul = l;
2431 /* find a free register of class 'rc'. If none, save one register */
2432 int get_reg(int rc)
2434 int r;
2435 SValue *p;
2437 /* find a free register */
2438 for(r=0;r<NB_REGS;r++) {
2439 if (reg_classes[r] & rc) {
2440 for(p=vstack;p<=vtop;p++) {
2441 if ((p->r & VT_VALMASK) == r ||
2442 (p->r2 & VT_VALMASK) == r)
2443 goto notfound;
2445 return r;
2447 notfound: ;
2450 /* no register left : free the first one on the stack (VERY
2451 IMPORTANT to start from the bottom to ensure that we don't
2452 spill registers used in gen_opi()) */
2453 for(p=vstack;p<=vtop;p++) {
2454 r = p->r & VT_VALMASK;
2455 if (r < VT_CONST && (reg_classes[r] & rc)) {
2456 save_reg(r);
2457 break;
2460 return r;
2463 void save_regs(void)
2465 int r;
2466 SValue *p;
2468 for(p=vstack;p<=vtop;p++) {
2469 r = p->r & VT_VALMASK;
2470 if (r < VT_CONST) {
2471 save_reg(r);
2476 /* move register 's' to 'r', and flush previous value of r to memory
2477 if needed */
2478 void move_reg(int r, int s)
2480 SValue sv;
2482 if (r != s) {
2483 save_reg(r);
2484 sv.t = VT_INT;
2485 sv.r = s;
2486 sv.c.ul = 0;
2487 load(r, &sv);
2491 /* get address of vtop (vtop MUST BE an lvalue) */
2492 void gaddrof(void)
2494 vtop->r &= ~VT_LVAL;
2495 /* tricky: if saved lvalue, then we can go back to lvalue */
2496 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
2497 vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
2500 /* generate lvalue bound code */
2501 void gbound(void)
2503 vtop->r &= ~VT_MUSTBOUND;
2504 /* if lvalue, then use checking code before dereferencing */
2505 if (vtop->r & VT_LVAL) {
2506 gaddrof();
2507 vpushi(0);
2508 gen_bounded_ptr_add1();
2509 gen_bounded_ptr_add2(1);
2510 vtop->r |= VT_LVAL;
2514 /* store vtop a register belonging to class 'rc'. lvalues are
2515 converted to values. Cannot be used if cannot be converted to
2516 register value (such as structures). */
2517 int gv(int rc)
2519 int r, r2, rc2, bit_pos, bit_size, size, align, i, data_offset;
2520 unsigned long long ll;
2522 /* NOTE: get_reg can modify vstack[] */
2523 if (vtop->t & VT_BITFIELD) {
2524 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
2525 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2526 /* remove bit field info to avoid loops */
2527 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2528 /* generate shifts */
2529 vpushi(32 - (bit_pos + bit_size));
2530 gen_op(TOK_SHL);
2531 vpushi(32 - bit_size);
2532 /* NOTE: transformed to SHR if unsigned */
2533 gen_op(TOK_SAR);
2534 r = gv(rc);
2535 } else {
2536 if (is_float(vtop->t) &&
2537 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2538 /* CPUs usually cannot use float constants, so we store them
2539 generically in data segment */
2540 size = type_size(vtop->t, &align);
2541 data_offset = (int)data_section->data_ptr;
2542 data_offset = (data_offset + align - 1) & -align;
2543 /* XXX: not portable yet */
2544 size = size >> 2;
2545 for(i=0;i<size;i++)
2546 ((int *)data_offset)[i] = vtop->c.tab[i];
2547 vtop->r |= VT_LVAL;
2548 vtop->c.ul = data_offset;
2549 data_offset += size << 2;
2550 data_section->data_ptr = (unsigned char *)data_offset;
2552 if (vtop->r & VT_MUSTBOUND)
2553 gbound();
2555 r = vtop->r & VT_VALMASK;
2556 /* need to reload if:
2557 - constant
2558 - lvalue (need to dereference pointer)
2559 - already a register, but not in the right class */
2560 if (r >= VT_CONST ||
2561 (vtop->r & VT_LVAL) ||
2562 !(reg_classes[r] & rc) ||
2563 ((vtop->t & VT_BTYPE) == VT_LLONG &&
2564 !(reg_classes[vtop->r2] & rc))) {
2565 r = get_reg(rc);
2566 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
2567 /* two register type load : expand to two words
2568 temporarily */
2569 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2570 /* load constant */
2571 ll = vtop->c.ull;
2572 vtop->c.ui = ll; /* first word */
2573 load(r, vtop);
2574 vtop->r = r; /* save register value */
2575 vpushi(ll >> 32); /* second word */
2576 } else if (r >= VT_CONST ||
2577 (vtop->r & VT_LVAL)) {
2578 /* load from memory */
2579 load(r, vtop);
2580 vdup();
2581 vtop[-1].r = r; /* save register value */
2582 /* increment pointer to get second word */
2583 vtop->t = VT_INT;
2584 gaddrof();
2585 vpushi(4);
2586 gen_op('+');
2587 vtop->r |= VT_LVAL;
2588 } else {
2589 /* move registers */
2590 load(r, vtop);
2591 vdup();
2592 vtop[-1].r = r; /* save register value */
2593 vtop->r = vtop[-1].r2;
2595 /* allocate second register */
2596 rc2 = RC_INT;
2597 if (rc == RC_IRET)
2598 rc2 = RC_LRET;
2599 r2 = get_reg(rc2);
2600 load(r2, vtop);
2601 vpop();
2602 /* write second register */
2603 vtop->r2 = r2;
2604 } else {
2605 /* one register type load */
2606 load(r, vtop);
2609 vtop->r = r;
2611 return r;
2614 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
2615 void gv2(int rc1, int rc2)
2617 /* generate more generic register first */
2618 if (rc1 <= rc2) {
2619 vswap();
2620 gv(rc1);
2621 vswap();
2622 gv(rc2);
2623 /* test if reload is needed for first register */
2624 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
2625 vswap();
2626 gv(rc1);
2627 vswap();
2629 } else {
2630 gv(rc2);
2631 vswap();
2632 gv(rc1);
2633 vswap();
2634 /* test if reload is needed for first register */
2635 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
2636 gv(rc2);
2641 /* expand long long on stack in two int registers */
2642 void lexpand(void)
2644 int u;
2646 u = vtop->t & VT_UNSIGNED;
2647 gv(RC_INT);
2648 vdup();
2649 vtop[0].r = vtop[-1].r2;
2650 vtop[0].r2 = VT_CONST;
2651 vtop[-1].r2 = VT_CONST;
2652 vtop[0].t = VT_INT | u;
2653 vtop[-1].t = VT_INT | u;
2656 /* build a long long from two ints */
2657 void lbuild(int t)
2659 gv2(RC_INT, RC_INT);
2660 vtop[-1].r2 = vtop[0].r;
2661 vtop[-1].t = t;
2662 vpop();
2665 /* rotate n first stack elements to the bottom */
2666 void vrotb(int n)
2668 int i;
2669 SValue tmp;
2671 tmp = vtop[-n + 1];
2672 for(i=-n+1;i!=0;i++)
2673 vtop[i] = vtop[i+1];
2674 vtop[0] = tmp;
2677 /* pop stack value */
2678 void vpop(void)
2680 /* for x86, we need to pop the FP stack */
2681 if ((vtop->r & VT_VALMASK) == REG_ST0) {
2682 o(0xd9dd); /* fstp %st(1) */
2684 vtop--;
2687 /* convert stack entry to register and duplicate its value in another
2688 register */
2689 void gv_dup(void)
2691 int rc, t, r, r1;
2692 SValue sv;
2694 t = vtop->t;
2695 if ((t & VT_BTYPE) == VT_LLONG) {
2696 lexpand();
2697 gv_dup();
2698 vswap();
2699 vrotb(3);
2700 gv_dup();
2701 vrotb(4);
2702 /* stack: H L L1 H1 */
2703 lbuild(t);
2704 vrotb(3);
2705 vrotb(3);
2706 vswap();
2707 lbuild(t);
2708 vswap();
2709 } else {
2710 /* duplicate value */
2711 rc = RC_INT;
2712 sv.t = VT_INT;
2713 if (is_float(t)) {
2714 rc = RC_FLOAT;
2715 sv.t = t;
2717 r = gv(rc);
2718 r1 = get_reg(rc);
2719 sv.r = r;
2720 sv.c.ul = 0;
2721 load(r1, &sv); /* move r to r1 */
2722 vdup();
2723 /* duplicates value */
2724 vtop->r = r1;
2728 /* generate CPU independent (unsigned) long long operations */
2729 void gen_opl(int op)
2731 int t, a, b, op1, c, i;
2732 void *func;
2733 GFuncContext gf;
2734 SValue tmp;
2736 switch(op) {
2737 case '/':
2738 case TOK_PDIV:
2739 func = __divll;
2740 goto gen_func;
2741 case TOK_UDIV:
2742 func = __divull;
2743 goto gen_func;
2744 case '%':
2745 func = __modll;
2746 goto gen_func;
2747 case TOK_UMOD:
2748 func = __modull;
2749 gen_func:
2750 /* call generic long long function */
2751 gfunc_start(&gf, FUNC_CDECL);
2752 gfunc_param(&gf);
2753 gfunc_param(&gf);
2754 vpushi((int)func);
2755 gfunc_call(&gf);
2756 vpushi(0);
2757 vtop->r = REG_IRET;
2758 vtop->r2 = REG_LRET;
2759 break;
2760 case '^':
2761 case '&':
2762 case '|':
2763 case '*':
2764 case '+':
2765 case '-':
2766 t = vtop->t;
2767 vswap();
2768 lexpand();
2769 vrotb(3);
2770 lexpand();
2771 /* stack: L1 H1 L2 H2 */
2772 tmp = vtop[0];
2773 vtop[0] = vtop[-3];
2774 vtop[-3] = tmp;
2775 tmp = vtop[-2];
2776 vtop[-2] = vtop[-3];
2777 vtop[-3] = tmp;
2778 vswap();
2779 /* stack: H1 H2 L1 L2 */
2780 if (op == '*') {
2781 vpushv(vtop - 1);
2782 vpushv(vtop - 1);
2783 gen_op(TOK_UMULL);
2784 lexpand();
2785 /* stack: H1 H2 L1 L2 ML MH */
2786 for(i=0;i<4;i++)
2787 vrotb(6);
2788 /* stack: ML MH H1 H2 L1 L2 */
2789 tmp = vtop[0];
2790 vtop[0] = vtop[-2];
2791 vtop[-2] = tmp;
2792 /* stack: ML MH H1 L2 H2 L1 */
2793 gen_op('*');
2794 vrotb(3);
2795 vrotb(3);
2796 gen_op('*');
2797 /* stack: ML MH M1 M2 */
2798 gen_op('+');
2799 gen_op('+');
2800 } else if (op == '+' || op == '-') {
2801 /* XXX: add non carry method too (for MIPS or alpha) */
2802 if (op == '+')
2803 op1 = TOK_ADDC1;
2804 else
2805 op1 = TOK_SUBC1;
2806 gen_op(op1);
2807 /* stack: H1 H2 (L1 op L2) */
2808 vrotb(3);
2809 vrotb(3);
2810 gen_op(op1 + 1); /* TOK_xxxC2 */
2811 } else {
2812 gen_op(op);
2813 /* stack: H1 H2 (L1 op L2) */
2814 vrotb(3);
2815 vrotb(3);
2816 /* stack: (L1 op L2) H1 H2 */
2817 gen_op(op);
2818 /* stack: (L1 op L2) (H1 op H2) */
2820 /* stack: L H */
2821 lbuild(t);
2822 break;
2823 case TOK_SAR:
2824 case TOK_SHR:
2825 case TOK_SHL:
2826 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
2827 t = vtop[-1].t;
2828 vswap();
2829 lexpand();
2830 vrotb(3);
2831 /* stack: L H shift */
2832 c = (int)vtop->c.i;
2833 /* constant: simpler */
2834 /* NOTE: all comments are for SHL. the other cases are
2835 done by swaping words */
2836 vpop();
2837 if (op != TOK_SHL)
2838 vswap();
2839 if (c >= 32) {
2840 /* stack: L H */
2841 vpop();
2842 if (c > 32) {
2843 vpushi(c - 32);
2844 gen_op(op);
2846 if (op != TOK_SAR) {
2847 vpushi(0);
2848 } else {
2849 gv_dup();
2850 vpushi(31);
2851 gen_op(TOK_SAR);
2853 vswap();
2854 } else {
2855 vswap();
2856 gv_dup();
2857 /* stack: H L L */
2858 vpushi(c);
2859 gen_op(op);
2860 vswap();
2861 vpushi(32 - c);
2862 if (op == TOK_SHL)
2863 gen_op(TOK_SHR);
2864 else
2865 gen_op(TOK_SHL);
2866 vrotb(3);
2867 /* stack: L L H */
2868 vpushi(c);
2869 gen_op(op);
2870 gen_op('|');
2872 if (op != TOK_SHL)
2873 vswap();
2874 lbuild(t);
2875 } else {
2876 /* XXX: should provide a faster fallback on x86 ? */
2877 switch(op) {
2878 case TOK_SAR:
2879 func = __sardi3;
2880 goto gen_func;
2881 case TOK_SHR:
2882 func = __shrdi3;
2883 goto gen_func;
2884 case TOK_SHL:
2885 func = __shldi3;
2886 goto gen_func;
2889 break;
2890 default:
2891 /* compare operations */
2892 t = vtop->t;
2893 vswap();
2894 lexpand();
2895 vrotb(3);
2896 lexpand();
2897 /* stack: L1 H1 L2 H2 */
2898 tmp = vtop[-1];
2899 vtop[-1] = vtop[-2];
2900 vtop[-2] = tmp;
2901 /* stack: L1 L2 H1 H2 */
2902 /* compare high */
2903 op1 = op;
2904 /* when values are equal, we need to compare low words. since
2905 the jump is inverted, we invert the test too. */
2906 if (op1 == TOK_LT)
2907 op1 = TOK_LE;
2908 else if (op1 == TOK_GT)
2909 op1 = TOK_GE;
2910 else if (op1 == TOK_ULT)
2911 op1 = TOK_ULE;
2912 else if (op1 == TOK_UGT)
2913 op1 = TOK_UGE;
2914 a = 0;
2915 b = 0;
2916 gen_op(op1);
2917 if (op1 != TOK_NE) {
2918 a = gtst(1, 0);
2920 if (op != TOK_EQ) {
2921 /* generate non equal test */
2922 /* XXX: NOT PORTABLE yet */
2923 if (a == 0)
2924 b = gtst(0, 0);
2925 else
2926 b = psym(0x850f, 0);
2928 /* compare low */
2929 gen_op(op);
2930 a = gtst(1, a);
2931 gsym(b);
2932 vset(VT_INT, VT_JMPI, a);
2933 break;
2937 /* handle constant optimizations and various machine independant opt */
2938 void gen_opc(int op)
2940 int fc, c1, c2, n;
2941 SValue *v1, *v2;
2943 v1 = vtop - 1;
2944 v2 = vtop;
2945 /* currently, we cannot do computations with forward symbols */
2946 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2947 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2948 if (c1 && c2) {
2949 fc = v2->c.i;
2950 switch(op) {
2951 case '+': v1->c.i += fc; break;
2952 case '-': v1->c.i -= fc; break;
2953 case '&': v1->c.i &= fc; break;
2954 case '^': v1->c.i ^= fc; break;
2955 case '|': v1->c.i |= fc; break;
2956 case '*': v1->c.i *= fc; break;
2958 case TOK_PDIV:
2959 case '/':
2960 case '%':
2961 case TOK_UDIV:
2962 case TOK_UMOD:
2963 /* if division by zero, generate explicit division */
2964 if (fc == 0) {
2965 if (const_wanted)
2966 error("division by zero in constant");
2967 goto general_case;
2969 switch(op) {
2970 default: v1->c.i /= fc; break;
2971 case '%': v1->c.i %= fc; break;
2972 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
2973 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
2975 break;
2976 case TOK_SHL: v1->c.i <<= fc; break;
2977 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
2978 case TOK_SAR: v1->c.i >>= fc; break;
2979 /* tests */
2980 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
2981 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
2982 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
2983 case TOK_NE: v1->c.i = v1->c.i != fc; break;
2984 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
2985 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
2986 case TOK_LT: v1->c.i = v1->c.i < fc; break;
2987 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
2988 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
2989 case TOK_GT: v1->c.i = v1->c.i > fc; break;
2990 /* logical */
2991 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
2992 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
2993 default:
2994 goto general_case;
2996 vtop--;
2997 } else {
2998 /* if commutative ops, put c2 as constant */
2999 if (c1 && (op == '+' || op == '&' || op == '^' ||
3000 op == '|' || op == '*')) {
3001 vswap();
3002 swap(&c1, &c2);
3004 fc = vtop->c.i;
3005 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
3006 op == TOK_PDIV) &&
3007 fc == 1) ||
3008 ((op == '+' || op == '-' || op == '|' || op == '^' ||
3009 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
3010 fc == 0) ||
3011 (op == '&' &&
3012 fc == -1))) {
3013 /* nothing to do */
3014 vtop--;
3015 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
3016 /* try to use shifts instead of muls or divs */
3017 if (fc > 0 && (fc & (fc - 1)) == 0) {
3018 n = -1;
3019 while (fc) {
3020 fc >>= 1;
3021 n++;
3023 vtop->c.i = n;
3024 if (op == '*')
3025 op = TOK_SHL;
3026 else if (op == TOK_PDIV)
3027 op = TOK_SAR;
3028 else
3029 op = TOK_SHR;
3031 goto general_case;
3032 } else {
3033 general_case:
3034 /* call low level op generator */
3035 gen_opi(op);
3040 int pointed_size(int t)
3042 return type_size(pointed_type(t), &t);
3045 #if 0
3046 void check_pointer_types(SValue *p1, SValue *p2)
3048 char buf1[256], buf2[256];
3049 int t1, t2;
3050 t1 = p1->t;
3051 t2 = p2->t;
3052 if (!is_compatible_types(t1, t2)) {
3053 type_to_str(buf1, sizeof(buf1), t1, NULL);
3054 type_to_str(buf2, sizeof(buf2), t2, NULL);
3055 error("incompatible pointers '%s' and '%s'", buf1, buf2);
3058 #endif
3060 /* generic gen_op: handles types problems */
3061 void gen_op(int op)
3063 int u, t1, t2, bt1, bt2, t;
3065 t1 = vtop[-1].t;
3066 t2 = vtop[0].t;
3067 bt1 = t1 & VT_BTYPE;
3068 bt2 = t2 & VT_BTYPE;
3070 if (bt1 == VT_PTR || bt2 == VT_PTR) {
3071 /* at least one operand is a pointer */
3072 /* relationnal op: must be both pointers */
3073 if (op >= TOK_ULT && op <= TOK_GT) {
3074 // check_pointer_types(vtop, vtop - 1);
3075 /* pointers are handled are unsigned */
3076 t = VT_INT | VT_UNSIGNED;
3077 goto std_op;
3079 /* if both pointers, then it must be the '-' op */
3080 if ((t1 & VT_BTYPE) == VT_PTR &&
3081 (t2 & VT_BTYPE) == VT_PTR) {
3082 if (op != '-')
3083 error("cannot use pointers here");
3084 // check_pointer_types(vtop - 1, vtop);
3085 /* XXX: check that types are compatible */
3086 u = pointed_size(t1);
3087 gen_opc(op);
3088 /* set to integer type */
3089 vtop->t = VT_INT;
3090 vpushi(u);
3091 gen_op(TOK_PDIV);
3092 } else {
3093 /* exactly one pointer : must be '+' or '-'. */
3094 if (op != '-' && op != '+')
3095 error("cannot use pointers here");
3096 /* Put pointer as first operand */
3097 if ((t2 & VT_BTYPE) == VT_PTR) {
3098 vswap();
3099 swap(&t1, &t2);
3101 /* XXX: cast to int ? (long long case) */
3102 vpushi(pointed_size(vtop[-1].t));
3103 gen_op('*');
3104 if (do_bounds_check) {
3105 /* if bounded pointers, we generate a special code to
3106 test bounds */
3107 if (op == '-') {
3108 vpushi(0);
3109 vswap();
3110 gen_op('-');
3112 gen_bounded_ptr_add1();
3113 gen_bounded_ptr_add2(0);
3114 } else {
3115 gen_opc(op);
3117 /* put again type if gen_opc() swaped operands */
3118 vtop->t = t1;
3120 } else if (is_float(bt1) || is_float(bt2)) {
3121 /* compute bigger type and do implicit casts */
3122 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
3123 t = VT_LDOUBLE;
3124 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
3125 t = VT_DOUBLE;
3126 } else {
3127 t = VT_FLOAT;
3129 /* floats can only be used for a few operations */
3130 if (op != '+' && op != '-' && op != '*' && op != '/' &&
3131 (op < TOK_ULT || op > TOK_GT))
3132 error("invalid operands for binary operation");
3133 goto std_op;
3134 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
3135 /* cast to biggest op */
3136 t = VT_LLONG;
3137 /* convert to unsigned if it does not fit in a long long */
3138 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
3139 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
3140 t |= VT_UNSIGNED;
3141 goto std_op;
3142 } else {
3143 /* integer operations */
3144 t = VT_INT;
3145 /* convert to unsigned if it does not fit in an integer */
3146 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
3147 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3148 t |= VT_UNSIGNED;
3149 std_op:
3150 /* XXX: currently, some unsigned operations are explicit, so
3151 we modify them here */
3152 if (t & VT_UNSIGNED) {
3153 if (op == TOK_SAR)
3154 op = TOK_SHR;
3155 else if (op == '/')
3156 op = TOK_UDIV;
3157 else if (op == '%')
3158 op = TOK_UMOD;
3159 else if (op == TOK_LT)
3160 op = TOK_ULT;
3161 else if (op == TOK_GT)
3162 op = TOK_UGT;
3163 else if (op == TOK_LE)
3164 op = TOK_ULE;
3165 else if (op == TOK_GE)
3166 op = TOK_UGE;
3168 vswap();
3169 gen_cast(t);
3170 vswap();
3171 /* special case for shifts and long long: we keep the shift as
3172 an integer */
3173 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
3174 gen_cast(VT_INT);
3175 else
3176 gen_cast(t);
3177 if (is_float(t))
3178 gen_opf(op);
3179 else if ((t & VT_BTYPE) == VT_LLONG)
3180 gen_opl(op);
3181 else
3182 gen_opc(op);
3183 if (op >= TOK_ULT && op <= TOK_GT) {
3184 /* relationnal op: the result is an int */
3185 vtop->t = VT_INT;
3186 } else {
3187 vtop->t = t;
3192 /* generic itof for unsigned long long case */
3193 void gen_cvt_itof1(int t)
3195 GFuncContext gf;
3197 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
3198 (VT_LLONG | VT_UNSIGNED)) {
3200 gfunc_start(&gf, FUNC_CDECL);
3201 gfunc_param(&gf);
3202 if (t == VT_FLOAT)
3203 vpushi((int)&__ulltof);
3204 else if (t == VT_DOUBLE)
3205 vpushi((int)&__ulltod);
3206 else
3207 vpushi((int)&__ulltold);
3208 gfunc_call(&gf);
3209 vpushi(0);
3210 vtop->r = REG_FRET;
3211 } else {
3212 gen_cvt_itof(t);
3216 /* generic ftoi for unsigned long long case */
3217 void gen_cvt_ftoi1(int t)
3219 GFuncContext gf;
3220 int st;
3222 if (t == (VT_LLONG | VT_UNSIGNED)) {
3223 /* not handled natively */
3224 gfunc_start(&gf, FUNC_CDECL);
3225 st = vtop->t & VT_BTYPE;
3226 gfunc_param(&gf);
3227 if (st == VT_FLOAT)
3228 vpushi((int)&__ftoull);
3229 else if (st == VT_DOUBLE)
3230 vpushi((int)&__dtoull);
3231 else
3232 vpushi((int)&__ldtoull);
3233 gfunc_call(&gf);
3234 vpushi(0);
3235 vtop->r = REG_IRET;
3236 vtop->r2 = REG_LRET;
3237 } else {
3238 gen_cvt_ftoi(t);
3242 /* force char or short cast */
3243 void force_charshort_cast(int t)
3245 int bits, dbt;
3246 dbt = t & VT_BTYPE;
3247 /* XXX: add optimization if lvalue : just change type and offset */
3248 if (dbt == VT_BYTE)
3249 bits = 8;
3250 else
3251 bits = 16;
3252 if (t & VT_UNSIGNED) {
3253 vpushi((1 << bits) - 1);
3254 gen_op('&');
3255 } else {
3256 bits = 32 - bits;
3257 vpushi(bits);
3258 gen_op(TOK_SHL);
3259 vpushi(bits);
3260 gen_op(TOK_SAR);
3264 /* cast 'vtop' to 't' type */
3265 void gen_cast(int t)
3267 int sbt, dbt, sf, df, c, st1, dt1;
3269 /* special delayed cast for char/short */
3270 /* XXX: in some cases (multiple cascaded casts), it may still
3271 be incorrect */
3272 if (vtop->r & VT_MUSTCAST) {
3273 vtop->r &= ~VT_MUSTCAST;
3274 force_charshort_cast(vtop->t);
3277 dbt = t & VT_BTYPE;
3278 sbt = vtop->t & VT_BTYPE;
3280 if (sbt != dbt) {
3281 sf = is_float(sbt);
3282 df = is_float(dbt);
3283 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3284 if (sf && df) {
3285 /* convert from fp to fp */
3286 if (c) {
3287 /* constant case: we can do it now */
3288 /* XXX: in ISOC, cannot do it if error in convert */
3289 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
3290 vtop->c.f = (float)vtop->c.d;
3291 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
3292 vtop->c.f = (float)vtop->c.ld;
3293 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
3294 vtop->c.d = (double)vtop->c.f;
3295 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
3296 vtop->c.d = (double)vtop->c.ld;
3297 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
3298 vtop->c.ld = (long double)vtop->c.f;
3299 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
3300 vtop->c.ld = (long double)vtop->c.d;
3301 } else {
3302 /* non constant case: generate code */
3303 gen_cvt_ftof(dbt);
3305 } else if (df) {
3306 /* convert int to fp */
3307 st1 = vtop->t & (VT_BTYPE | VT_UNSIGNED);
3308 if (c) {
3309 switch(st1) {
3310 case VT_LLONG | VT_UNSIGNED:
3311 case VT_LLONG:
3312 /* XXX: add const cases for long long */
3313 goto do_itof;
3314 case VT_INT | VT_UNSIGNED:
3315 switch(dbt) {
3316 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
3317 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
3318 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
3320 break;
3321 default:
3322 switch(dbt) {
3323 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
3324 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
3325 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
3327 break;
3329 } else {
3330 do_itof:
3331 gen_cvt_itof1(dbt);
3333 } else if (sf) {
3334 /* convert fp to int */
3335 dt1 = t & (VT_BTYPE | VT_UNSIGNED);
3336 /* we handle char/short/etc... with generic code */
3337 if (dt1 != (VT_INT | VT_UNSIGNED) &&
3338 dt1 != (VT_LLONG | VT_UNSIGNED) &&
3339 dt1 != VT_LLONG)
3340 dt1 = VT_INT;
3341 if (c) {
3342 switch(dt1) {
3343 case VT_LLONG | VT_UNSIGNED:
3344 case VT_LLONG:
3345 /* XXX: add const cases for long long */
3346 goto do_ftoi;
3347 case VT_INT | VT_UNSIGNED:
3348 switch(sbt) {
3349 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
3350 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3351 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3353 break;
3354 default:
3355 /* int case */
3356 switch(sbt) {
3357 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
3358 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
3359 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
3361 break;
3363 } else {
3364 do_ftoi:
3365 gen_cvt_ftoi1(dt1);
3367 if (dt1 == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dt1) {
3368 /* additionnal cast for char/short/bool... */
3369 vtop->t = dt1;
3370 gen_cast(t);
3372 } else if (dbt == VT_LLONG) {
3373 /* scalar to long long */
3374 if (c) {
3375 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3376 vtop->c.ll = vtop->c.ui;
3377 else
3378 vtop->c.ll = vtop->c.i;
3379 } else {
3380 /* machine independant conversion */
3381 gv(RC_INT);
3382 /* generate high word */
3383 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) {
3384 vpushi(0);
3385 gv(RC_INT);
3386 } else {
3387 gv_dup();
3388 vpushi(31);
3389 gen_op(TOK_SAR);
3391 /* patch second register */
3392 vtop[-1].r2 = vtop->r;
3393 vpop();
3395 } else if (dbt == VT_BOOL) {
3396 /* scalar to bool */
3397 vpushi(0);
3398 gen_op(TOK_NE);
3399 } else if (dbt == VT_BYTE || dbt == VT_SHORT) {
3400 force_charshort_cast(t);
3401 } else if (dbt == VT_INT) {
3402 /* scalar to int */
3403 if (sbt == VT_LLONG) {
3404 /* from long long: just take low order word */
3405 lexpand();
3406 vpop();
3407 } else if (sbt == VT_PTR) {
3408 /* ok to cast */
3409 } else if (vtop->r & VT_LVAL) {
3410 /* if lvalue and single word type, nothing to do (XXX:
3411 maybe incorrect for sizeof op) */
3412 goto no_cast;
3416 vtop->t = t;
3417 no_cast: ;
3420 /* return type size. Put alignment at 'a' */
3421 int type_size(int t, int *a)
3423 Sym *s;
3424 int bt;
3426 bt = t & VT_BTYPE;
3427 if (bt == VT_STRUCT) {
3428 /* struct/union */
3429 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3430 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
3431 return s->c;
3432 } else if (bt == VT_PTR) {
3433 if (t & VT_ARRAY) {
3434 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3435 return type_size(s->t, a) * s->c;
3436 } else {
3437 *a = PTR_SIZE;
3438 return PTR_SIZE;
3440 } else if (bt == VT_LDOUBLE) {
3441 *a = LDOUBLE_ALIGN;
3442 return LDOUBLE_SIZE;
3443 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
3444 *a = 8;
3445 return 8;
3446 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
3447 *a = 4;
3448 return 4;
3449 } else if (bt == VT_SHORT) {
3450 *a = 2;
3451 return 2;
3452 } else {
3453 /* char, void, function, _Bool */
3454 *a = 1;
3455 return 1;
3459 /* return the pointed type of t */
3460 int pointed_type(int t)
3462 Sym *s;
3463 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3464 return s->t | (t & ~VT_TYPE);
3467 int mk_pointer(int t)
3469 int p;
3470 p = anon_sym++;
3471 sym_push(p, t, 0, -1);
3472 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
3475 int is_compatible_types(int t1, int t2)
3477 Sym *s1, *s2;
3478 int bt1, bt2;
3480 t1 &= VT_TYPE;
3481 t2 &= VT_TYPE;
3482 bt1 = t1 & VT_BTYPE;
3483 bt2 = t2 & VT_BTYPE;
3484 if (bt1 == VT_PTR) {
3485 t1 = pointed_type(t1);
3486 /* if function, then convert implicitely to function pointer */
3487 if (bt2 != VT_FUNC) {
3488 if (bt2 != VT_PTR)
3489 return 0;
3490 t2 = pointed_type(t2);
3492 /* void matches everything */
3493 t1 &= VT_TYPE;
3494 t2 &= VT_TYPE;
3495 if (t1 == VT_VOID || t2 == VT_VOID)
3496 return 1;
3497 return is_compatible_types(t1, t2);
3498 } else if (bt1 == VT_STRUCT) {
3499 return (t2 == t1);
3500 } else if (bt1 == VT_FUNC) {
3501 if (bt2 != VT_FUNC)
3502 return 0;
3503 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
3504 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
3505 if (!is_compatible_types(s1->t, s2->t))
3506 return 0;
3507 /* XXX: not complete */
3508 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
3509 return 1;
3510 if (s1->c != s2->c)
3511 return 0;
3512 while (s1 != NULL) {
3513 if (s2 == NULL)
3514 return 0;
3515 if (!is_compatible_types(s1->t, s2->t))
3516 return 0;
3517 s1 = s1->next;
3518 s2 = s2->next;
3520 if (s2)
3521 return 0;
3522 return 1;
3523 } else {
3524 /* XXX: not complete */
3525 return 1;
3529 /* print a type. If 'varstr' is not NULL, then the variable is also
3530 printed in the type */
3531 /* XXX: union */
3532 /* XXX: add array and function pointers */
3533 void type_to_str(char *buf, int buf_size,
3534 int t, const char *varstr)
3536 int bt, v;
3537 Sym *s, *sa;
3538 char buf1[256];
3539 const char *tstr;
3541 t = t & VT_TYPE;
3542 bt = t & VT_BTYPE;
3543 buf[0] = '\0';
3544 if (t & VT_UNSIGNED)
3545 pstrcat(buf, buf_size, "unsigned ");
3546 switch(bt) {
3547 case VT_VOID:
3548 tstr = "void";
3549 goto add_tstr;
3550 case VT_BOOL:
3551 tstr = "_Bool";
3552 goto add_tstr;
3553 case VT_BYTE:
3554 tstr = "char";
3555 goto add_tstr;
3556 case VT_SHORT:
3557 tstr = "short";
3558 goto add_tstr;
3559 case VT_INT:
3560 tstr = "int";
3561 goto add_tstr;
3562 case VT_LONG:
3563 tstr = "long";
3564 goto add_tstr;
3565 case VT_LLONG:
3566 tstr = "long long";
3567 goto add_tstr;
3568 case VT_FLOAT:
3569 tstr = "float";
3570 goto add_tstr;
3571 case VT_DOUBLE:
3572 tstr = "double";
3573 goto add_tstr;
3574 case VT_LDOUBLE:
3575 tstr = "long double";
3576 add_tstr:
3577 pstrcat(buf, buf_size, tstr);
3578 break;
3579 case VT_ENUM:
3580 case VT_STRUCT:
3581 if (bt == VT_STRUCT)
3582 tstr = "struct ";
3583 else
3584 tstr = "enum ";
3585 pstrcat(buf, buf_size, tstr);
3586 v = (unsigned)t >> VT_STRUCT_SHIFT;
3587 if (v >= SYM_FIRST_ANOM)
3588 pstrcat(buf, buf_size, "<anonymous>");
3589 else
3590 pstrcat(buf, buf_size, get_tok_str(v, NULL));
3591 break;
3592 case VT_FUNC:
3593 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3594 type_to_str(buf, buf_size, s->t, varstr);
3595 pstrcat(buf, buf_size, "(");
3596 sa = s->next;
3597 while (sa != NULL) {
3598 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
3599 pstrcat(buf, buf_size, buf1);
3600 sa = sa->next;
3601 if (sa)
3602 pstrcat(buf, buf_size, ", ");
3604 pstrcat(buf, buf_size, ")");
3605 goto no_var;
3606 case VT_PTR:
3607 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3608 pstrcpy(buf1, sizeof(buf1), "*");
3609 if (varstr)
3610 pstrcat(buf1, sizeof(buf1), varstr);
3611 type_to_str(buf, buf_size, s->t, buf1);
3612 goto no_var;
3614 if (varstr) {
3615 pstrcat(buf, buf_size, " ");
3616 pstrcat(buf, buf_size, varstr);
3618 no_var: ;
3621 /* verify type compatibility to store vtop in 'dt' type, and generate
3622 casts if needed. */
3623 void gen_assign_cast(int dt)
3625 int st;
3626 char buf1[256], buf2[256];
3628 st = vtop->t; /* source type */
3629 if ((dt & VT_BTYPE) == VT_PTR) {
3630 /* special cases for pointers */
3631 /* a function is implicitely a function pointer */
3632 if ((st & VT_BTYPE) == VT_FUNC) {
3633 if (!is_compatible_types(pointed_type(dt), st))
3634 goto error;
3635 else
3636 goto type_ok;
3638 /* '0' can also be a pointer */
3639 if ((st & VT_BTYPE) == VT_INT &&
3640 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) &&
3641 vtop->c.i == 0)
3642 goto type_ok;
3644 if (!is_compatible_types(dt, st)) {
3645 error:
3646 type_to_str(buf1, sizeof(buf1), st, NULL);
3647 type_to_str(buf2, sizeof(buf2), dt, NULL);
3648 error("cannot cast '%s' to '%s'", buf1, buf2);
3650 type_ok:
3651 gen_cast(dt);
3654 /* store vtop in lvalue pushed on stack */
3655 void vstore(void)
3657 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
3658 GFuncContext gf;
3660 ft = vtop[-1].t;
3661 sbt = vtop->t & VT_BTYPE;
3662 dbt = ft & VT_BTYPE;
3663 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
3664 (sbt == VT_INT && dbt == VT_SHORT)) {
3665 /* optimize char/short casts */
3666 delayed_cast = VT_MUSTCAST;
3667 vtop->t = ft & VT_TYPE;
3668 } else {
3669 delayed_cast = 0;
3670 gen_assign_cast(ft & VT_TYPE);
3673 if (sbt == VT_STRUCT) {
3674 /* if structure, only generate pointer */
3675 /* structure assignment : generate memcpy */
3676 /* XXX: optimize if small size */
3678 vdup();
3679 gfunc_start(&gf, FUNC_CDECL);
3680 /* type size */
3681 size = type_size(vtop->t, &align);
3682 vpushi(size);
3683 gfunc_param(&gf);
3684 /* source */
3685 vtop->t = VT_INT;
3686 gaddrof();
3687 gfunc_param(&gf);
3688 /* destination */
3689 vswap();
3690 vtop->t = VT_INT;
3691 gaddrof();
3692 gfunc_param(&gf);
3694 save_regs();
3695 vpushi((int)&memcpy);
3696 gfunc_call(&gf);
3697 /* leave source on stack */
3698 } else if (ft & VT_BITFIELD) {
3699 /* bitfield store handling */
3700 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
3701 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3702 /* remove bit field info to avoid loops */
3703 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3705 /* duplicate destination */
3706 vdup();
3707 vtop[-1] = vtop[-2];
3709 /* mask and shift source */
3710 vpushi((1 << bit_size) - 1);
3711 gen_op('&');
3712 vpushi(bit_pos);
3713 gen_op(TOK_SHL);
3714 /* load destination, mask and or with source */
3715 vswap();
3716 vpushi(~(((1 << bit_size) - 1) << bit_pos));
3717 gen_op('&');
3718 gen_op('|');
3719 /* store result */
3720 vstore();
3721 } else {
3722 /* bound check case */
3723 if (vtop[-1].r & VT_MUSTBOUND) {
3724 vswap();
3725 gbound();
3726 vswap();
3728 rc = RC_INT;
3729 if (is_float(ft))
3730 rc = RC_FLOAT;
3731 r = gv(rc); /* generate value */
3732 /* if lvalue was saved on stack, must read it */
3733 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
3734 SValue sv;
3735 t = get_reg(RC_INT);
3736 sv.t = VT_INT;
3737 sv.r = VT_LOCAL | VT_LVAL;
3738 sv.c.ul = vtop[-1].c.ul;
3739 load(t, &sv);
3740 vtop[-1].r = t | VT_LVAL;
3742 store(r, vtop - 1);
3743 /* two word case handling : store second register at word + 4 */
3744 if ((ft & VT_BTYPE) == VT_LLONG) {
3745 vswap();
3746 /* convert to int to increment easily */
3747 vtop->t = VT_INT;
3748 gaddrof();
3749 vpushi(4);
3750 gen_op('+');
3751 vtop->r |= VT_LVAL;
3752 vswap();
3753 /* XXX: it works because r2 is spilled last ! */
3754 store(vtop->r2, vtop - 1);
3756 vswap();
3757 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
3758 vtop->r |= delayed_cast;
3762 /* post defines POST/PRE add. c is the token ++ or -- */
3763 void inc(int post, int c)
3765 test_lvalue();
3766 vdup(); /* save lvalue */
3767 if (post) {
3768 gv_dup(); /* duplicate value */
3769 vrotb(3);
3770 vrotb(3);
3772 /* add constant */
3773 vpushi(c - TOK_MID);
3774 gen_op('+');
3775 vstore(); /* store value */
3776 if (post)
3777 vpop(); /* if post op, return saved value */
3780 /* Parse GNUC __attribute__ extension. Currently, the following
3781 extensions are recognized:
3782 - aligned(n) : set data/function alignment.
3783 - section(x) : generate data/code in this section.
3784 - unused : currently ignored, but may be used someday.
3786 void parse_attribute(AttributeDef *ad)
3788 int t, n;
3790 next();
3791 skip('(');
3792 skip('(');
3793 while (tok != ')') {
3794 if (tok < TOK_IDENT)
3795 expect("attribute name");
3796 t = tok;
3797 next();
3798 switch(t) {
3799 case TOK_SECTION:
3800 case TOK___SECTION__:
3801 skip('(');
3802 if (tok != TOK_STR)
3803 expect("section name");
3804 ad->section = find_section(tokc.ts->str);
3805 next();
3806 skip(')');
3807 break;
3808 case TOK_ALIGNED:
3809 case TOK___ALIGNED__:
3810 skip('(');
3811 n = expr_const();
3812 if (n <= 0 || (n & (n - 1)) != 0)
3813 error("alignment must be a positive power of two");
3814 ad->aligned = n;
3815 skip(')');
3816 break;
3817 case TOK_UNUSED:
3818 case TOK___UNUSED__:
3819 /* currently, no need to handle it because tcc does not
3820 track unused objects */
3821 break;
3822 case TOK_NORETURN:
3823 case TOK___NORETURN__:
3824 /* currently, no need to handle it because tcc does not
3825 track unused objects */
3826 break;
3827 case TOK_CDECL:
3828 case TOK___CDECL:
3829 case TOK___CDECL__:
3830 ad->func_call = FUNC_CDECL;
3831 break;
3832 case TOK_STDCALL:
3833 case TOK___STDCALL:
3834 case TOK___STDCALL__:
3835 ad->func_call = FUNC_STDCALL;
3836 break;
3837 default:
3838 warning("'%s' attribute ignored", get_tok_str(t, NULL));
3839 /* skip parameters */
3840 /* XXX: skip parenthesis too */
3841 if (tok == '(') {
3842 next();
3843 while (tok != ')' && tok != -1)
3844 next();
3845 next();
3847 break;
3849 if (tok != ',')
3850 break;
3851 next();
3853 skip(')');
3854 skip(')');
3857 /* enum/struct/union declaration */
3858 int struct_decl(int u)
3860 int a, t, b, v, size, align, maxalign, c, offset;
3861 int bit_size, bit_pos, bsize, bt, lbit_pos;
3862 Sym *s, *ss, **ps;
3863 AttributeDef ad;
3865 a = tok; /* save decl type */
3866 next();
3867 if (tok != '{') {
3868 v = tok;
3869 next();
3870 /* struct already defined ? return it */
3871 /* XXX: check consistency */
3872 s = sym_find(v | SYM_STRUCT);
3873 if (s) {
3874 if (s->t != a)
3875 error("invalid type");
3876 goto do_decl;
3878 } else {
3879 v = anon_sym++;
3881 s = sym_push(v | SYM_STRUCT, a, 0, 0);
3882 /* put struct/union/enum name in type */
3883 do_decl:
3884 u = u | (v << VT_STRUCT_SHIFT);
3886 if (tok == '{') {
3887 next();
3888 if (s->c)
3889 error("struct/union/enum already defined");
3890 /* cannot be empty */
3891 c = 0;
3892 maxalign = 0;
3893 ps = &s->next;
3894 bit_pos = 0;
3895 offset = 0;
3896 while (1) {
3897 if (a == TOK_ENUM) {
3898 v = tok;
3899 next();
3900 if (tok == '=') {
3901 next();
3902 c = expr_const();
3904 /* enum symbols have static storage */
3905 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
3906 if (tok == ',')
3907 next();
3908 c++;
3909 } else {
3910 parse_btype(&b, &ad);
3911 while (1) {
3912 bit_size = -1;
3913 v = 0;
3914 if (tok != ':') {
3915 t = type_decl(&ad, &v, b, TYPE_DIRECT);
3916 if ((t & VT_BTYPE) == VT_FUNC ||
3917 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
3918 error("invalid type for '%s'",
3919 get_tok_str(v, NULL));
3920 } else {
3921 t = b;
3923 if (tok == ':') {
3924 next();
3925 bit_size = expr_const();
3926 /* XXX: handle v = 0 case for messages */
3927 if (bit_size < 0)
3928 error("negative width in bit-field '%s'",
3929 get_tok_str(v, NULL));
3930 if (v && bit_size == 0)
3931 error("zero width for bit-field '%s'",
3932 get_tok_str(v, NULL));
3934 size = type_size(t, &align);
3935 lbit_pos = 0;
3936 if (bit_size >= 0) {
3937 bt = t & VT_BTYPE;
3938 if (bt != VT_INT &&
3939 bt != VT_BYTE &&
3940 bt != VT_SHORT)
3941 error("bitfields must have scalar type");
3942 bsize = size * 8;
3943 if (bit_size > bsize) {
3944 error("width of '%s' exceeds its type",
3945 get_tok_str(v, NULL));
3946 } else if (bit_size == bsize) {
3947 /* no need for bit fields */
3948 bit_pos = 0;
3949 } else if (bit_size == 0) {
3950 /* XXX: what to do if only padding in a
3951 structure ? */
3952 /* zero size: means to pad */
3953 if (bit_pos > 0)
3954 bit_pos = bsize;
3955 } else {
3956 /* we do not have enough room ? */
3957 if ((bit_pos + bit_size) > bsize)
3958 bit_pos = 0;
3959 lbit_pos = bit_pos;
3960 /* XXX: handle LSB first */
3961 t |= VT_BITFIELD |
3962 (bit_pos << VT_STRUCT_SHIFT) |
3963 (bit_size << (VT_STRUCT_SHIFT + 6));
3964 bit_pos += bit_size;
3966 } else {
3967 bit_pos = 0;
3969 if (v) {
3970 /* add new memory data only if starting
3971 bit field */
3972 if (lbit_pos == 0) {
3973 if (a == TOK_STRUCT) {
3974 c = (c + align - 1) & -align;
3975 offset = c;
3976 c += size;
3977 } else {
3978 offset = 0;
3979 if (size > c)
3980 c = size;
3982 if (align > maxalign)
3983 maxalign = align;
3985 #if 0
3986 printf("add field %s offset=%d",
3987 get_tok_str(v, NULL), offset);
3988 if (t & VT_BITFIELD) {
3989 printf(" pos=%d size=%d",
3990 (t >> VT_STRUCT_SHIFT) & 0x3f,
3991 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
3993 printf("\n");
3994 #endif
3995 ss = sym_push(v | SYM_FIELD, t, 0, offset);
3996 *ps = ss;
3997 ps = &ss->next;
3999 if (tok == ';' || tok == -1)
4000 break;
4001 skip(',');
4003 skip(';');
4005 if (tok == '}')
4006 break;
4008 skip('}');
4009 /* size for struct/union, dummy for enum */
4010 s->c = (c + maxalign - 1) & -maxalign;
4012 return u;
4015 /* return 0 if no type declaration. otherwise, return the basic type
4016 and skip it.
4018 int parse_btype(int *type_ptr, AttributeDef *ad)
4020 int t, u, type_found;
4021 Sym *s;
4023 memset(ad, 0, sizeof(AttributeDef));
4024 type_found = 0;
4025 t = 0;
4026 while(1) {
4027 switch(tok) {
4028 /* basic types */
4029 case TOK_CHAR:
4030 u = VT_BYTE;
4031 basic_type:
4032 next();
4033 basic_type1:
4034 if ((t & VT_BTYPE) != 0)
4035 error("too many basic types");
4036 t |= u;
4037 break;
4038 case TOK_VOID:
4039 u = VT_VOID;
4040 goto basic_type;
4041 case TOK_SHORT:
4042 u = VT_SHORT;
4043 goto basic_type;
4044 case TOK_INT:
4045 next();
4046 break;
4047 case TOK_LONG:
4048 next();
4049 if ((t & VT_BTYPE) == VT_DOUBLE) {
4050 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4051 } else if ((t & VT_BTYPE) == VT_LONG) {
4052 t = (t & ~VT_BTYPE) | VT_LLONG;
4053 } else {
4054 u = VT_LONG;
4055 goto basic_type1;
4057 break;
4058 case TOK_BOOL:
4059 u = VT_BOOL;
4060 goto basic_type;
4061 case TOK_FLOAT:
4062 u = VT_FLOAT;
4063 goto basic_type;
4064 case TOK_DOUBLE:
4065 next();
4066 if ((t & VT_BTYPE) == VT_LONG) {
4067 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4068 } else {
4069 u = VT_DOUBLE;
4070 goto basic_type1;
4072 break;
4073 case TOK_ENUM:
4074 u = struct_decl(VT_ENUM);
4075 goto basic_type1;
4076 case TOK_STRUCT:
4077 case TOK_UNION:
4078 u = struct_decl(VT_STRUCT);
4079 goto basic_type1;
4081 /* type modifiers */
4082 case TOK_CONST:
4083 case TOK_VOLATILE:
4084 case TOK_REGISTER:
4085 case TOK_SIGNED:
4086 case TOK___SIGNED__:
4087 case TOK_AUTO:
4088 case TOK_INLINE:
4089 case TOK___INLINE__:
4090 case TOK_RESTRICT:
4091 next();
4092 break;
4093 case TOK_UNSIGNED:
4094 t |= VT_UNSIGNED;
4095 next();
4096 break;
4098 /* storage */
4099 case TOK_EXTERN:
4100 t |= VT_EXTERN;
4101 next();
4102 break;
4103 case TOK_STATIC:
4104 t |= VT_STATIC;
4105 next();
4106 break;
4107 case TOK_TYPEDEF:
4108 t |= VT_TYPEDEF;
4109 next();
4110 break;
4111 /* GNUC attribute */
4112 case TOK___ATTRIBUTE__:
4113 parse_attribute(ad);
4114 break;
4115 default:
4116 s = sym_find(tok);
4117 if (!s || !(s->t & VT_TYPEDEF))
4118 goto the_end;
4119 t |= (s->t & ~VT_TYPEDEF);
4120 next();
4121 break;
4123 type_found = 1;
4125 the_end:
4126 /* long is never used as type */
4127 if ((t & VT_BTYPE) == VT_LONG)
4128 t = (t & ~VT_BTYPE) | VT_INT;
4129 *type_ptr = t;
4130 return type_found;
4133 int post_type(int t, AttributeDef *ad)
4135 int p, n, pt, l, t1;
4136 Sym **plast, *s, *first;
4137 AttributeDef ad1;
4139 if (tok == '(') {
4140 /* function declaration */
4141 next();
4142 l = 0;
4143 first = NULL;
4144 plast = &first;
4145 while (tok != ')') {
4146 /* read param name and compute offset */
4147 if (l != FUNC_OLD) {
4148 if (!parse_btype(&pt, &ad1)) {
4149 if (l) {
4150 error("invalid type");
4151 } else {
4152 l = FUNC_OLD;
4153 goto old_proto;
4156 l = FUNC_NEW;
4157 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
4158 break;
4159 pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
4160 if ((pt & VT_BTYPE) == VT_VOID)
4161 error("parameter declared as void");
4162 } else {
4163 old_proto:
4164 n = tok;
4165 pt = VT_INT;
4166 next();
4168 /* array must be transformed to pointer according to ANSI C */
4169 pt &= ~VT_ARRAY;
4170 s = sym_push(n | SYM_FIELD, pt, 0, 0);
4171 *plast = s;
4172 plast = &s->next;
4173 if (tok == ',') {
4174 next();
4175 if (l == FUNC_NEW && tok == TOK_DOTS) {
4176 l = FUNC_ELLIPSIS;
4177 next();
4178 break;
4182 /* if no parameters, then old type prototype */
4183 if (l == 0)
4184 l = FUNC_OLD;
4185 skip(')');
4186 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4187 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4188 /* we push a anonymous symbol which will contain the function prototype */
4189 p = anon_sym++;
4190 s = sym_push(p, t, ad->func_call, l);
4191 s->next = first;
4192 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
4193 } else if (tok == '[') {
4194 /* array definition */
4195 next();
4196 n = -1;
4197 if (tok != ']') {
4198 n = expr_const();
4199 if (n < 0)
4200 error("invalid array size");
4202 skip(']');
4203 /* parse next post type */
4204 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4205 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4207 /* we push a anonymous symbol which will contain the array
4208 element type */
4209 p = anon_sym++;
4210 sym_push(p, t, 0, n);
4211 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
4213 return t;
4216 /* Read a type declaration (except basic type), and return the
4217 type. 'td' is a bitmask indicating which kind of type decl is
4218 expected. 't' should contain the basic type. 'ad' is the attribute
4219 definition of the basic type. It can be modified by type_decl(). */
4220 int type_decl(AttributeDef *ad, int *v, int t, int td)
4222 int u, p;
4223 Sym *s;
4225 while (tok == '*') {
4226 next();
4227 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
4228 next();
4229 t = mk_pointer(t);
4232 /* recursive type */
4233 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4234 if (tok == '(') {
4235 next();
4236 /* XXX: this is not correct to modify 'ad' at this point, but
4237 the syntax is not clear */
4238 if (tok == TOK___ATTRIBUTE__)
4239 parse_attribute(ad);
4240 u = type_decl(ad, v, 0, td);
4241 skip(')');
4242 } else {
4243 u = 0;
4244 /* type identifier */
4245 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
4246 *v = tok;
4247 next();
4248 } else {
4249 if (!(td & TYPE_ABSTRACT))
4250 expect("identifier");
4251 *v = 0;
4254 /* append t at the end of u */
4255 t = post_type(t, ad);
4256 if (tok == TOK___ATTRIBUTE__)
4257 parse_attribute(ad);
4258 if (!u)
4259 return t;
4260 p = u;
4261 while(1) {
4262 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
4263 p = s->t;
4264 if (!p) {
4265 s->t = t;
4266 break;
4269 return u;
4272 /* define a new external reference to a function 'v' of type 'u' */
4273 Sym *external_sym(int v, int u, int r)
4275 Sym *s;
4276 s = sym_find(v);
4277 if (!s) {
4278 /* push forward reference */
4279 s = sym_push1(&global_stack,
4280 v, u, 0);
4281 s->r = r | VT_CONST | VT_FORWARD;
4283 return s;
4286 void indir(void)
4288 if ((vtop->t & VT_BTYPE) != VT_PTR)
4289 expect("pointer");
4290 if (vtop->r & VT_LVAL)
4291 gv(RC_INT);
4292 vtop->t = pointed_type(vtop->t);
4293 /* an array is never an lvalue */
4294 if (!(vtop->t & VT_ARRAY)) {
4295 vtop->r |= VT_LVAL;
4296 /* if bound checking, the referenced pointer must be checked */
4297 if (do_bounds_check)
4298 vtop->r |= VT_MUSTBOUND;
4302 /* pass a parameter to a function and do type checking and casting */
4303 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
4305 int func_type;
4306 func_type = func->c;
4307 if (func_type == FUNC_OLD ||
4308 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
4309 /* default casting : only need to convert float to double */
4310 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
4311 gen_cast(VT_DOUBLE);
4312 } else if (arg == NULL) {
4313 error("too many arguments to function");
4314 } else {
4315 gen_assign_cast(arg->t);
4317 gfunc_param(gf);
4320 void unary(void)
4322 int n, t, ft, fc, p, align, size, r, data_offset;
4323 Sym *s;
4324 GFuncContext gf;
4325 AttributeDef ad;
4327 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
4328 vpushi(tokc.i);
4329 next();
4330 } else if (tok == TOK_CUINT) {
4331 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
4332 next();
4333 } else if (tok == TOK_CLLONG) {
4334 vsetc(VT_LLONG, VT_CONST, &tokc);
4335 next();
4336 } else if (tok == TOK_CULLONG) {
4337 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
4338 next();
4339 } else if (tok == TOK_CFLOAT) {
4340 vsetc(VT_FLOAT, VT_CONST, &tokc);
4341 next();
4342 } else if (tok == TOK_CDOUBLE) {
4343 vsetc(VT_DOUBLE, VT_CONST, &tokc);
4344 next();
4345 } else if (tok == TOK_CLDOUBLE) {
4346 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
4347 next();
4348 } else if (tok == TOK___FUNC__) {
4349 /* special function name identifier */
4350 /* generate (char *) type */
4351 data_offset = (int)data_section->data_ptr;
4352 vset(mk_pointer(VT_BYTE), VT_CONST, data_offset);
4353 strcpy((void *)data_offset, funcname);
4354 data_offset += strlen(funcname) + 1;
4355 data_section->data_ptr = (unsigned char *)data_offset;
4356 next();
4357 } else if (tok == TOK_LSTR) {
4358 t = VT_INT;
4359 goto str_init;
4360 } else if (tok == TOK_STR) {
4361 /* string parsing */
4362 t = VT_BYTE;
4363 str_init:
4364 type_size(t, &align);
4365 data_offset = (int)data_section->data_ptr;
4366 data_offset = (data_offset + align - 1) & -align;
4367 fc = data_offset;
4368 /* we must declare it as an array first to use initializer parser */
4369 t = VT_ARRAY | mk_pointer(t);
4370 decl_initializer(t, VT_CONST, data_offset, 1, 0);
4371 data_offset += type_size(t, &align);
4372 /* put it as pointer */
4373 vset(t & ~VT_ARRAY, VT_CONST, fc);
4374 data_section->data_ptr = (unsigned char *)data_offset;
4375 } else {
4376 t = tok;
4377 next();
4378 if (t == '(') {
4379 /* cast ? */
4380 if (parse_btype(&t, &ad)) {
4381 ft = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4382 skip(')');
4383 /* check ISOC99 compound literal */
4384 if (tok == '{') {
4385 /* data is allocated locally by default */
4386 if (global_expr)
4387 r = VT_CONST;
4388 else
4389 r = VT_LOCAL;
4390 /* all except arrays are lvalues */
4391 if (!(ft & VT_ARRAY))
4392 r |= VT_LVAL;
4393 memset(&ad, 0, sizeof(AttributeDef));
4394 fc = decl_initializer_alloc(ft, &ad, r, 1);
4395 vset(ft, r, fc);
4396 } else {
4397 unary();
4398 gen_cast(ft);
4400 } else {
4401 gexpr();
4402 skip(')');
4404 } else if (t == '*') {
4405 unary();
4406 indir();
4407 } else if (t == '&') {
4408 unary();
4409 /* functions names must be treated as function pointers,
4410 except for unary '&' and sizeof. Since we consider that
4411 functions are not lvalues, we only have to handle it
4412 there and in function calls. */
4413 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4414 test_lvalue();
4415 vtop->t = mk_pointer(vtop->t);
4416 gaddrof();
4417 } else
4418 if (t == '!') {
4419 unary();
4420 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
4421 vtop->c.i = !vtop->c.i;
4422 else if ((vtop->r & VT_VALMASK) == VT_CMP)
4423 vtop->c.i = vtop->c.i ^ 1;
4424 else
4425 vset(VT_INT, VT_JMP, gtst(1, 0));
4426 } else
4427 if (t == '~') {
4428 unary();
4429 vpushi(-1);
4430 gen_op('^');
4431 } else
4432 if (t == '+') {
4433 unary();
4434 } else
4435 if (t == TOK_SIZEOF) {
4436 if (tok == '(') {
4437 next();
4438 if (parse_btype(&t, &ad)) {
4439 t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4440 } else {
4441 /* XXX: some code could be generated: add eval
4442 flag */
4443 gexpr();
4444 t = vtop->t;
4445 vpop();
4447 skip(')');
4448 } else {
4449 unary();
4450 t = vtop->t;
4451 vpop();
4453 vpushi(type_size(t, &t));
4454 } else
4455 if (t == TOK_INC || t == TOK_DEC) {
4456 unary();
4457 inc(0, t);
4458 } else if (t == '-') {
4459 vpushi(0);
4460 unary();
4461 gen_op('-');
4462 } else
4464 s = sym_find(t);
4465 if (!s) {
4466 if (tok != '(')
4467 error("'%s' undeclared", get_tok_str(t, NULL));
4468 /* for simple function calls, we tolerate undeclared
4469 external reference */
4470 p = anon_sym++;
4471 sym_push1(&global_stack, p, 0, FUNC_OLD);
4472 /* int() function */
4473 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT), 0);
4475 vset(s->t, s->r, s->c);
4476 /* if forward reference, we must point to s */
4477 if (vtop->r & VT_FORWARD)
4478 vtop->c.sym = s;
4482 /* post operations */
4483 while (1) {
4484 if (tok == TOK_INC || tok == TOK_DEC) {
4485 inc(1, tok);
4486 next();
4487 } else if (tok == '.' || tok == TOK_ARROW) {
4488 /* field */
4489 if (tok == TOK_ARROW)
4490 indir();
4491 test_lvalue();
4492 gaddrof();
4493 next();
4494 /* expect pointer on structure */
4495 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
4496 expect("struct or union");
4497 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4498 /* find field */
4499 tok |= SYM_FIELD;
4500 while ((s = s->next) != NULL) {
4501 if (s->v == tok)
4502 break;
4504 if (!s)
4505 error("field not found");
4506 /* add field offset to pointer */
4507 vtop->t = char_pointer_type; /* change type to 'char *' */
4508 vpushi(s->c);
4509 gen_op('+');
4510 /* change type to field type, and set to lvalue */
4511 vtop->t = s->t;
4512 /* an array is never an lvalue */
4513 if (!(vtop->t & VT_ARRAY))
4514 vtop->r |= VT_LVAL;
4515 next();
4516 } else if (tok == '[') {
4517 next();
4518 gexpr();
4519 gen_op('+');
4520 indir();
4521 skip(']');
4522 } else if (tok == '(') {
4523 SValue ret;
4524 Sym *sa;
4526 /* function call */
4527 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
4528 /* pointer test (no array accepted) */
4529 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
4530 vtop->t = pointed_type(vtop->t);
4531 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4532 goto error_func;
4533 } else {
4534 error_func:
4535 expect("function pointer");
4537 } else {
4538 vtop->r &= ~VT_LVAL; /* no lvalue */
4540 /* get return type */
4541 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
4542 save_regs(); /* save used temporary registers */
4543 gfunc_start(&gf, s->r);
4544 next();
4545 sa = s->next; /* first parameter */
4546 #ifdef INVERT_FUNC_PARAMS
4548 int *str, len, parlevel, *saved_macro_ptr;
4549 Sym *args, *s1;
4551 /* read each argument and store it on a stack */
4552 /* XXX: merge it with macro args ? */
4553 args = NULL;
4554 while (tok != ')') {
4555 len = 0;
4556 str = NULL;
4557 parlevel = 0;
4558 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
4559 tok != -1) {
4560 if (tok == '(')
4561 parlevel++;
4562 else if (tok == ')')
4563 parlevel--;
4564 tok_add2(&str, &len, tok, &tokc);
4565 next();
4567 tok_add(&str, &len, -1); /* end of file added */
4568 tok_add(&str, &len, 0);
4569 s1 = sym_push2(&args, 0, 0, (int)str);
4570 s1->next = sa; /* add reference to argument */
4571 if (sa)
4572 sa = sa->next;
4573 if (tok != ',')
4574 break;
4575 next();
4577 if (tok != ')')
4578 expect(")");
4580 /* now generate code in reverse order by reading the stack */
4581 saved_macro_ptr = macro_ptr;
4582 while (args) {
4583 macro_ptr = (int *)args->c;
4584 next();
4585 expr_eq();
4586 if (tok != -1)
4587 expect("',' or ')'");
4588 gfunc_param_typed(&gf, s, args->next);
4589 s1 = args->prev;
4590 free((int *)args->c);
4591 free(args);
4592 args = s1;
4594 macro_ptr = saved_macro_ptr;
4595 /* restore token */
4596 tok = ')';
4598 #endif
4599 /* compute first implicit argument if a structure is returned */
4600 if ((s->t & VT_BTYPE) == VT_STRUCT) {
4601 /* get some space for the returned structure */
4602 size = type_size(s->t, &align);
4603 loc = (loc - size) & -align;
4604 ret.t = s->t;
4605 ret.r = VT_LOCAL | VT_LVAL;
4606 /* pass it as 'int' to avoid structure arg passing
4607 problems */
4608 vset(VT_INT, VT_LOCAL, loc);
4609 ret.c = vtop->c;
4610 gfunc_param(&gf);
4611 } else {
4612 ret.t = s->t;
4613 ret.r2 = VT_CONST;
4614 /* return in register */
4615 if (is_float(ret.t)) {
4616 ret.r = REG_FRET;
4617 } else {
4618 if ((ret.t & VT_BTYPE) == VT_LLONG)
4619 ret.r2 = REG_LRET;
4620 ret.r = REG_IRET;
4622 ret.c.i = 0;
4624 #ifndef INVERT_FUNC_PARAMS
4625 while (tok != ')') {
4626 expr_eq();
4627 gfunc_param_typed(&gf, s, sa);
4628 if (sa)
4629 sa = sa->next;
4630 if (tok == ',')
4631 next();
4633 #endif
4634 if (sa)
4635 error("too few arguments to function");
4636 skip(')');
4637 gfunc_call(&gf);
4638 /* return value */
4639 vsetc(ret.t, ret.r, &ret.c);
4640 vtop->r2 = ret.r2;
4641 } else {
4642 break;
4647 void uneq(void)
4649 int t;
4651 unary();
4652 if (tok == '=' ||
4653 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
4654 tok == TOK_A_XOR || tok == TOK_A_OR ||
4655 tok == TOK_A_SHL || tok == TOK_A_SAR) {
4656 test_lvalue();
4657 t = tok;
4658 next();
4659 if (t == '=') {
4660 expr_eq();
4661 } else {
4662 vdup();
4663 expr_eq();
4664 gen_op(t & 0x7f);
4666 vstore();
4670 void sum(int l)
4672 int t;
4674 if (l == 0)
4675 uneq();
4676 else {
4677 sum(--l);
4678 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
4679 (l == 1 && (tok == '+' || tok == '-')) ||
4680 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
4681 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
4682 tok == TOK_ULT || tok == TOK_UGE)) ||
4683 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
4684 (l == 5 && tok == '&') ||
4685 (l == 6 && tok == '^') ||
4686 (l == 7 && tok == '|') ||
4687 (l == 8 && tok == TOK_LAND) ||
4688 (l == 9 && tok == TOK_LOR)) {
4689 t = tok;
4690 next();
4691 sum(l);
4692 gen_op(t);
4697 /* only used if non constant */
4698 void eand(void)
4700 int t;
4702 sum(8);
4703 t = 0;
4704 while (1) {
4705 if (tok != TOK_LAND) {
4706 if (t) {
4707 t = gtst(1, t);
4708 vset(VT_INT, VT_JMPI, t);
4710 break;
4712 t = gtst(1, t);
4713 next();
4714 sum(8);
4718 void eor(void)
4720 int t;
4722 eand();
4723 t = 0;
4724 while (1) {
4725 if (tok != TOK_LOR) {
4726 if (t) {
4727 t = gtst(0, t);
4728 vset(VT_INT, VT_JMP, t);
4730 break;
4732 t = gtst(0, t);
4733 next();
4734 eand();
4738 /* XXX: better constant handling */
4739 void expr_eq(void)
4741 int t, u, c, r1, r2, rc;
4743 if (const_wanted) {
4744 sum(10);
4745 if (tok == '?') {
4746 c = vtop->c.i;
4747 vpop();
4748 next();
4749 gexpr();
4750 t = vtop->c.i;
4751 vpop();
4752 skip(':');
4753 expr_eq();
4754 if (c)
4755 vtop->c.i = t;
4757 } else {
4758 eor();
4759 if (tok == '?') {
4760 next();
4761 t = gtst(1, 0);
4762 gexpr();
4763 /* XXX: long long handling ? */
4764 rc = RC_INT;
4765 if (is_float(vtop->t))
4766 rc = RC_FLOAT;
4767 r1 = gv(rc);
4768 vtop--; /* no vpop so that FP stack is not flushed */
4769 skip(':');
4770 u = gjmp(0);
4772 gsym(t);
4773 expr_eq();
4774 r2 = gv(rc);
4775 move_reg(r1, r2);
4776 vtop->r = r1;
4777 gsym(u);
4782 void gexpr(void)
4784 while (1) {
4785 expr_eq();
4786 if (tok != ',')
4787 break;
4788 vpop();
4789 next();
4793 /* parse a constant expression and return value in vtop */
4794 void expr_const1(void)
4796 int a;
4797 a = const_wanted;
4798 const_wanted = 1;
4799 expr_eq();
4800 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
4801 expect("constant");
4802 const_wanted = a;
4805 /* parse an integer constant and return its value */
4806 int expr_const(void)
4808 int c;
4809 expr_const1();
4810 c = vtop->c.i;
4811 vpop();
4812 return c;
4815 /* return the label token if current token is a label, otherwise
4816 return zero */
4817 int is_label(void)
4819 int t;
4820 CValue c;
4822 /* fast test first */
4823 if (tok < TOK_UIDENT)
4824 return 0;
4825 /* no need to save tokc since we expect an identifier */
4826 t = tok;
4827 c = tokc;
4828 next();
4829 if (tok == ':') {
4830 next();
4831 return t;
4832 } else {
4833 /* XXX: may not work in all cases (macros ?) */
4834 tok1 = tok;
4835 tok1c = tokc;
4836 tok = t;
4837 tokc = c;
4838 return 0;
4842 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
4844 int a, b, c, d;
4845 Sym *s;
4847 /* generate line number info */
4848 if (do_debug &&
4849 (last_line_num != file->line_num || last_ind != ind)) {
4850 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
4851 last_ind = ind;
4852 last_line_num = file->line_num;
4855 if (tok == TOK_IF) {
4856 /* if test */
4857 next();
4858 skip('(');
4859 gexpr();
4860 skip(')');
4861 a = gtst(1, 0);
4862 block(bsym, csym, case_sym, def_sym, case_reg);
4863 c = tok;
4864 if (c == TOK_ELSE) {
4865 next();
4866 d = gjmp(0);
4867 gsym(a);
4868 block(bsym, csym, case_sym, def_sym, case_reg);
4869 gsym(d); /* patch else jmp */
4870 } else
4871 gsym(a);
4872 } else if (tok == TOK_WHILE) {
4873 next();
4874 d = ind;
4875 skip('(');
4876 gexpr();
4877 skip(')');
4878 a = gtst(1, 0);
4879 b = 0;
4880 block(&a, &b, case_sym, def_sym, case_reg);
4881 oad(0xe9, d - ind - 5); /* jmp */
4882 gsym(a);
4883 gsym_addr(b, d);
4884 } else if (tok == '{') {
4885 next();
4886 /* declarations */
4887 s = local_stack.top;
4888 while (tok != '}') {
4889 decl(VT_LOCAL);
4890 if (tok != '}')
4891 block(bsym, csym, case_sym, def_sym, case_reg);
4893 /* pop locally defined symbols */
4894 sym_pop(&local_stack, s);
4895 next();
4896 } else if (tok == TOK_RETURN) {
4897 next();
4898 if (tok != ';') {
4899 gexpr();
4900 gen_assign_cast(func_vt);
4901 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
4902 /* if returning structure, must copy it to implicit
4903 first pointer arg location */
4904 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
4905 indir();
4906 vswap();
4907 /* copy structure value to pointer */
4908 vstore();
4909 } else if (is_float(func_vt)) {
4910 gv(RC_FRET);
4911 } else {
4912 gv(RC_IRET);
4914 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
4916 skip(';');
4917 rsym = gjmp(rsym); /* jmp */
4918 } else if (tok == TOK_BREAK) {
4919 /* compute jump */
4920 if (!bsym)
4921 error("cannot break");
4922 *bsym = gjmp(*bsym);
4923 next();
4924 skip(';');
4925 } else if (tok == TOK_CONTINUE) {
4926 /* compute jump */
4927 if (!csym)
4928 error("cannot continue");
4929 *csym = gjmp(*csym);
4930 next();
4931 skip(';');
4932 } else if (tok == TOK_FOR) {
4933 int e;
4934 next();
4935 skip('(');
4936 if (tok != ';') {
4937 gexpr();
4938 vpop();
4940 skip(';');
4941 d = ind;
4942 c = ind;
4943 a = 0;
4944 b = 0;
4945 if (tok != ';') {
4946 gexpr();
4947 a = gtst(1, 0);
4949 skip(';');
4950 if (tok != ')') {
4951 e = gjmp(0);
4952 c = ind;
4953 gexpr();
4954 vpop();
4955 oad(0xe9, d - ind - 5); /* jmp */
4956 gsym(e);
4958 skip(')');
4959 block(&a, &b, case_sym, def_sym, case_reg);
4960 oad(0xe9, c - ind - 5); /* jmp */
4961 gsym(a);
4962 gsym_addr(b, c);
4963 } else
4964 if (tok == TOK_DO) {
4965 next();
4966 a = 0;
4967 b = 0;
4968 d = ind;
4969 block(&a, &b, case_sym, def_sym, case_reg);
4970 skip(TOK_WHILE);
4971 skip('(');
4972 gsym(b);
4973 gexpr();
4974 c = gtst(0, 0);
4975 gsym_addr(c, d);
4976 skip(')');
4977 gsym(a);
4978 skip(';');
4979 } else
4980 if (tok == TOK_SWITCH) {
4981 next();
4982 skip('(');
4983 gexpr();
4984 /* XXX: other types than integer */
4985 case_reg = gv(RC_INT);
4986 vpop();
4987 skip(')');
4988 a = 0;
4989 b = gjmp(0); /* jump to first case */
4990 c = 0;
4991 block(&a, csym, &b, &c, case_reg);
4992 /* if no default, jmp after switch */
4993 if (c == 0)
4994 c = ind;
4995 /* default label */
4996 gsym_addr(b, c);
4997 /* break label */
4998 gsym(a);
4999 } else
5000 if (tok == TOK_CASE) {
5001 int v1, v2;
5002 if (!case_sym)
5003 expect("switch");
5004 next();
5005 v1 = expr_const();
5006 v2 = v1;
5007 if (gnu_ext && tok == TOK_DOTS) {
5008 next();
5009 v2 = expr_const();
5010 if (v2 < v1)
5011 warning("empty case range");
5013 /* since a case is like a label, we must skip it with a jmp */
5014 b = gjmp(0);
5015 gsym(*case_sym);
5016 vset(VT_INT, case_reg, 0);
5017 vpushi(v1);
5018 if (v1 == v2) {
5019 gen_op(TOK_EQ);
5020 *case_sym = gtst(1, 0);
5021 } else {
5022 gen_op(TOK_GE);
5023 *case_sym = gtst(1, 0);
5024 vset(VT_INT, case_reg, 0);
5025 vpushi(v2);
5026 gen_op(TOK_LE);
5027 *case_sym = gtst(1, *case_sym);
5029 gsym(b);
5030 skip(':');
5031 block(bsym, csym, case_sym, def_sym, case_reg);
5032 } else
5033 if (tok == TOK_DEFAULT) {
5034 next();
5035 skip(':');
5036 if (!def_sym)
5037 expect("switch");
5038 if (*def_sym)
5039 error("too many 'default'");
5040 *def_sym = ind;
5041 block(bsym, csym, case_sym, def_sym, case_reg);
5042 } else
5043 if (tok == TOK_GOTO) {
5044 next();
5045 s = sym_find1(&label_stack, tok);
5046 /* put forward definition if needed */
5047 if (!s)
5048 s = sym_push1(&label_stack, tok, VT_FORWARD, 0);
5049 /* label already defined */
5050 if (s->t & VT_FORWARD)
5051 s->c = gjmp(s->c); /* jmp xxx */
5052 else
5053 oad(0xe9, s->c - ind - 5); /* jmp xxx */
5054 next();
5055 skip(';');
5056 } else {
5057 b = is_label();
5058 if (b) {
5059 /* label case */
5060 s = sym_find1(&label_stack, b);
5061 if (s) {
5062 if (!(s->t & VT_FORWARD))
5063 error("multiple defined label");
5064 gsym(s->c);
5065 s->c = ind;
5066 s->t = 0;
5067 } else {
5068 sym_push1(&label_stack, b, 0, ind);
5070 /* we accept this, but it is a mistake */
5071 if (tok == '}')
5072 warning("deprecated use of label at end of compound statement");
5073 else
5074 block(bsym, csym, case_sym, def_sym, case_reg);
5075 } else {
5076 /* expression case */
5077 if (tok != ';') {
5078 gexpr();
5079 vpop();
5081 skip(';');
5086 /* t is the array or struct type. c is the array or struct
5087 address. cur_index/cur_field is the pointer to the current
5088 value. 'size_only' is true if only size info is needed (only used
5089 in arrays) */
5090 void decl_designator(int t, int r, int c,
5091 int *cur_index, Sym **cur_field,
5092 int size_only)
5094 Sym *s, *f;
5095 int notfirst, index, align, l;
5097 notfirst = 0;
5098 if (gnu_ext && (l = is_label()) != 0)
5099 goto struct_field;
5101 while (tok == '[' || tok == '.') {
5102 if (tok == '[') {
5103 if (!(t & VT_ARRAY))
5104 expect("array type");
5105 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5106 next();
5107 index = expr_const();
5108 if (index < 0 || (s->c >= 0 && index >= s->c))
5109 expect("invalid index");
5110 skip(']');
5111 if (!notfirst)
5112 *cur_index = index;
5113 t = pointed_type(t);
5114 c += index * type_size(t, &align);
5115 } else {
5116 next();
5117 l = tok;
5118 next();
5119 struct_field:
5120 if ((t & VT_BTYPE) != VT_STRUCT)
5121 expect("struct/union type");
5122 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5123 l |= SYM_FIELD;
5124 f = s->next;
5125 while (f) {
5126 if (f->v == l)
5127 break;
5128 f = f->next;
5130 if (!f)
5131 expect("field");
5132 if (!notfirst)
5133 *cur_field = f;
5134 t = f->t | (t & ~VT_TYPE);
5135 c += f->c;
5137 notfirst = 1;
5139 if (notfirst) {
5140 if (tok == '=') {
5141 next();
5142 } else {
5143 if (!gnu_ext)
5144 expect("=");
5146 } else {
5147 if (t & VT_ARRAY) {
5148 index = *cur_index;
5149 t = pointed_type(t);
5150 c += index * type_size(t, &align);
5151 } else {
5152 f = *cur_field;
5153 if (!f)
5154 error("too many field init");
5155 t = f->t | (t & ~VT_TYPE);
5156 c += f->c;
5159 decl_initializer(t, r, c, 0, size_only);
5162 #define EXPR_VAL 0
5163 #define EXPR_CONST 1
5164 #define EXPR_ANY 2
5166 /* store a value or an expression directly in global data or in local array */
5167 void init_putv(int t, int r, int c,
5168 int v, int expr_type)
5170 int saved_global_expr, bt;
5172 switch(expr_type) {
5173 case EXPR_VAL:
5174 vpushi(v);
5175 break;
5176 case EXPR_CONST:
5177 /* compound literals must be allocated globally in this case */
5178 saved_global_expr = global_expr;
5179 global_expr = 1;
5180 expr_const1();
5181 global_expr = saved_global_expr;
5182 break;
5183 case EXPR_ANY:
5184 expr_eq();
5185 break;
5188 if ((r & VT_VALMASK) == VT_CONST) {
5189 /* XXX: not portable */
5190 gen_assign_cast(t);
5191 bt = t & VT_BTYPE;
5192 switch(bt) {
5193 case VT_BYTE:
5194 *(char *)c = vtop->c.i;
5195 break;
5196 case VT_SHORT:
5197 *(short *)c = vtop->c.i;
5198 break;
5199 case VT_DOUBLE:
5200 *(double *)c = vtop->c.d;
5201 break;
5202 case VT_LDOUBLE:
5203 *(long double *)c = vtop->c.ld;
5204 break;
5205 case VT_LLONG:
5206 *(long long *)c = vtop->c.ll;
5207 break;
5208 default:
5209 *(int *)c = vtop->c.i;
5210 break;
5212 vtop--;
5213 } else {
5214 vset(t, r, c);
5215 vswap();
5216 vstore();
5217 vpop();
5221 /* put zeros for variable based init */
5222 void init_putz(int t, int r, int c, int size)
5224 GFuncContext gf;
5226 if ((r & VT_VALMASK) == VT_CONST) {
5227 /* nothing to do because globals are already set to zero */
5228 } else {
5229 gfunc_start(&gf, FUNC_CDECL);
5230 vpushi(size);
5231 gfunc_param(&gf);
5232 vpushi(0);
5233 gfunc_param(&gf);
5234 vset(VT_INT, VT_LOCAL, c);
5235 gfunc_param(&gf);
5236 vpushi((int)&memset);
5237 gfunc_call(&gf);
5241 /* 't' contains the type and storage info. c is the address of the
5242 object. 'first' is true if array '{' must be read (multi dimension
5243 implicit array init handling). 'size_only' is true if size only
5244 evaluation is wanted (only for arrays). */
5245 void decl_initializer(int t, int r, int c, int first, int size_only)
5247 int index, array_length, n, no_oblock, nb, parlevel, i;
5248 int t1, size1, align1, expr_type;
5249 Sym *s, *f;
5250 TokenSym *ts;
5252 if (t & VT_ARRAY) {
5253 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5254 n = s->c;
5255 array_length = 0;
5256 t1 = pointed_type(t);
5257 size1 = type_size(t1, &align1);
5259 no_oblock = 1;
5260 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
5261 tok == '{') {
5262 skip('{');
5263 no_oblock = 0;
5266 /* only parse strings here if correct type (otherwise: handle
5267 them as ((w)char *) expressions */
5268 if ((tok == TOK_LSTR &&
5269 (t1 & VT_BTYPE) == VT_INT) ||
5270 (tok == TOK_STR &&
5271 (t1 & VT_BTYPE) == VT_BYTE)) {
5272 /* XXX: move multiple string parsing in parser ? */
5273 while (tok == TOK_STR || tok == TOK_LSTR) {
5274 ts = tokc.ts;
5275 /* compute maximum number of chars wanted */
5276 nb = ts->len;
5277 if (n >= 0 && nb > (n - array_length))
5278 nb = n - array_length;
5279 if (!size_only) {
5280 if (ts->len > nb)
5281 warning("initializer-string for array is too long");
5282 for(i=0;i<nb;i++) {
5283 init_putv(t1, r, c + (array_length + i) * size1,
5284 ts->str[i], EXPR_VAL);
5287 array_length += nb;
5288 next();
5290 /* only add trailing zero if enough storage (no
5291 warning in this case since it is standard) */
5292 if (n < 0 || array_length < n) {
5293 if (!size_only) {
5294 init_putv(t1, r, c + (array_length * size1), 0, EXPR_VAL);
5296 array_length++;
5298 } else {
5299 index = 0;
5300 while (tok != '}') {
5301 decl_designator(t, r, c, &index, NULL, size_only);
5302 if (n >= 0 && index >= n)
5303 error("index too large");
5304 /* must put zero in holes (note that doing it that way
5305 ensures that it even works with designators) */
5306 if (!size_only && array_length < index) {
5307 init_putz(t1, r, c + array_length * size1,
5308 (index - array_length) * size1);
5310 index++;
5311 if (index > array_length)
5312 array_length = index;
5313 /* special test for multi dimensional arrays (may not
5314 be strictly correct if designators are used at the
5315 same time) */
5316 if (index >= n && no_oblock)
5317 break;
5318 if (tok == '}')
5319 break;
5320 skip(',');
5323 if (!no_oblock)
5324 skip('}');
5325 /* put zeros at the end */
5326 if (!size_only && n >= 0 && array_length < n) {
5327 init_putz(t1, r, c + array_length * size1,
5328 (n - array_length) * size1);
5330 /* patch type size if needed */
5331 if (n < 0)
5332 s->c = array_length;
5333 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
5334 /* XXX: union needs only one init */
5335 next();
5336 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5337 f = s->next;
5338 array_length = 0;
5339 index = 0;
5340 n = s->c;
5341 while (tok != '}') {
5342 decl_designator(t, r, c, NULL, &f, size_only);
5343 /* fill with zero between fields */
5344 index = f->c;
5345 if (!size_only && array_length < index) {
5346 init_putz(t, r, c + array_length,
5347 index - array_length);
5349 index = index + type_size(f->t, &align1);
5350 if (index > array_length)
5351 array_length = index;
5352 if (tok == '}')
5353 break;
5354 skip(',');
5355 f = f->next;
5357 /* put zeros at the end */
5358 if (!size_only && array_length < n) {
5359 init_putz(t, r, c + array_length,
5360 n - array_length);
5362 skip('}');
5363 } else if (tok == '{') {
5364 next();
5365 decl_initializer(t, r, c, first, size_only);
5366 skip('}');
5367 } else if (size_only) {
5368 /* just skip expression */
5369 parlevel = 0;
5370 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
5371 tok != -1) {
5372 if (tok == '(')
5373 parlevel++;
5374 else if (tok == ')')
5375 parlevel--;
5376 next();
5378 } else {
5379 /* currently, we always use constant expression for globals
5380 (may change for scripting case) */
5381 expr_type = EXPR_CONST;
5382 if ((r & VT_VALMASK) == VT_LOCAL)
5383 expr_type = EXPR_ANY;
5384 init_putv(t, r, c, 0, expr_type);
5388 /* parse an initializer for type 't' if 'has_init' is true, and
5389 allocate space in local or global data space ('r' is either
5390 VT_LOCAL or VT_CONST). The allocated address in returned */
5391 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init)
5393 int size, align, addr, tok1, data_offset;
5394 int *init_str, init_len, level, *saved_macro_ptr;
5395 Section *sec;
5397 size = type_size(t, &align);
5398 /* If unknown size, we must evaluate it before
5399 evaluating initializers because
5400 initializers can generate global data too
5401 (e.g. string pointers or ISOC99 compound
5402 literals). It also simplifies local
5403 initializers handling */
5404 init_len = 0;
5405 init_str = NULL;
5406 saved_macro_ptr = NULL; /* avoid warning */
5407 tok1 = 0;
5408 if (size < 0) {
5409 if (!has_init)
5410 error("unknown type size");
5411 /* get all init string */
5412 level = 0;
5413 while (level > 0 || (tok != ',' && tok != ';')) {
5414 if (tok < 0)
5415 error("unexpected end of file in initializer");
5416 tok_add2(&init_str, &init_len, tok, &tokc);
5417 if (tok == '{')
5418 level++;
5419 else if (tok == '}') {
5420 if (level == 0)
5421 break;
5422 level--;
5424 next();
5426 tok1 = tok;
5427 tok_add(&init_str, &init_len, -1);
5428 tok_add(&init_str, &init_len, 0);
5430 /* compute size */
5431 saved_macro_ptr = macro_ptr;
5432 macro_ptr = init_str;
5433 next();
5434 decl_initializer(t, r, 0, 1, 1);
5435 /* prepare second initializer parsing */
5436 macro_ptr = init_str;
5437 next();
5439 /* if still unknown size, error */
5440 size = type_size(t, &align);
5441 if (size < 0)
5442 error("unknown type size");
5444 /* take into account specified alignment if bigger */
5445 if (ad->aligned > align)
5446 align = ad->aligned;
5447 if ((r & VT_VALMASK) == VT_LOCAL) {
5448 if (do_bounds_check && (t & VT_ARRAY))
5449 loc--;
5450 loc = (loc - size) & -align;
5451 addr = loc;
5452 /* handles bounds */
5453 /* XXX: currently, since we do only one pass, we cannot track
5454 '&' operators, so we add only arrays */
5455 if (do_bounds_check && (t & VT_ARRAY)) {
5456 int *bounds_ptr;
5457 /* add padding between regions */
5458 loc--;
5459 /* then add local bound info */
5460 bounds_ptr = (int *)lbounds_section->data_ptr;
5461 *bounds_ptr++ = addr;
5462 *bounds_ptr++ = size;
5463 lbounds_section->data_ptr = (unsigned char *)bounds_ptr;
5465 } else {
5466 /* compute section */
5467 sec = ad->section;
5468 if (!sec) {
5469 if (has_init)
5470 sec = data_section;
5471 else
5472 sec = bss_section;
5474 data_offset = (int)sec->data_ptr;
5475 data_offset = (data_offset + align - 1) & -align;
5476 addr = data_offset;
5477 /* very important to increment global
5478 pointer at this time because
5479 initializers themselves can create new
5480 initializers */
5481 data_offset += size;
5482 /* handles bounds */
5483 if (do_bounds_check) {
5484 int *bounds_ptr;
5485 /* first, we need to add at least one byte between each region */
5486 data_offset++;
5487 /* then add global bound info */
5488 bounds_ptr = (int *)bounds_section->data_ptr;
5489 *bounds_ptr++ = addr;
5490 *bounds_ptr++ = size;
5491 bounds_section->data_ptr = (unsigned char *)bounds_ptr;
5493 sec->data_ptr = (unsigned char *)data_offset;
5495 if (has_init) {
5496 decl_initializer(t, r, addr, 1, 0);
5497 /* restore parse state if needed */
5498 if (init_str) {
5499 free(init_str);
5500 macro_ptr = saved_macro_ptr;
5501 tok = tok1;
5504 return addr;
5507 void put_func_debug(int t)
5509 int bind;
5510 char buf[512];
5512 if (t & VT_STATIC)
5513 bind = STB_LOCAL;
5514 else
5515 bind = STB_GLOBAL;
5516 put_elf_sym(symtab_section, ind, 0,
5517 ELF32_ST_INFO(bind, STT_FUNC), 0,
5518 cur_text_section->sh_num, funcname);
5519 /* stabs info */
5520 /* XXX: we put here a dummy type */
5521 snprintf(buf, sizeof(buf), "%s:%c1",
5522 funcname, t & VT_STATIC ? 'f' : 'F');
5523 put_stabs(buf, N_FUN, 0, file->line_num, ind);
5524 func_ind = ind;
5525 last_ind = 0;
5526 last_line_num = 0;
5529 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5530 void decl(int l)
5532 int t, b, v, addr, has_init, r;
5533 Sym *sym;
5534 AttributeDef ad;
5536 while (1) {
5537 if (!parse_btype(&b, &ad)) {
5538 /* skip redundant ';' */
5539 /* XXX: find more elegant solution */
5540 if (tok == ';') {
5541 next();
5542 continue;
5544 /* special test for old K&R protos without explicit int
5545 type. Only accepted when defining global data */
5546 if (l == VT_LOCAL || tok < TOK_DEFINE)
5547 break;
5548 b = VT_INT;
5550 if (((b & VT_BTYPE) == VT_ENUM ||
5551 (b & VT_BTYPE) == VT_STRUCT) &&
5552 tok == ';') {
5553 /* we accept no variable after */
5554 next();
5555 continue;
5557 while (1) { /* iterate thru each declaration */
5558 t = type_decl(&ad, &v, b, TYPE_DIRECT);
5559 #if 0
5561 char buf[500];
5562 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
5563 printf("type = '%s'\n", buf);
5565 #endif
5566 if (tok == '{') {
5567 if (l == VT_LOCAL)
5568 error("cannot use local functions");
5569 if (!(t & VT_FUNC))
5570 expect("function definition");
5571 /* compute text section */
5572 cur_text_section = ad.section;
5573 if (!cur_text_section)
5574 cur_text_section = text_section;
5575 ind = (int)cur_text_section->data_ptr;
5576 /* patch forward references */
5577 if ((sym = sym_find(v)) && (sym->r & VT_FORWARD)) {
5578 greloc_patch(sym, ind);
5579 sym->t = t;
5580 } else {
5581 /* put function address */
5582 sym = sym_push1(&global_stack, v, t, ind);
5584 sym->r = VT_CONST;
5585 funcname = get_tok_str(v, NULL);
5586 /* put debug symbol */
5587 if (do_debug)
5588 put_func_debug(t);
5589 /* push a dummy symbol to enable local sym storage */
5590 sym_push1(&local_stack, 0, 0, 0);
5591 gfunc_prolog(t);
5592 loc = 0;
5593 rsym = 0;
5594 block(NULL, NULL, NULL, NULL, 0);
5595 gsym(rsym);
5596 gfunc_epilog();
5597 cur_text_section->data_ptr = (unsigned char *)ind;
5598 sym_pop(&label_stack, NULL); /* reset label stack */
5599 sym_pop(&local_stack, NULL); /* reset local stack */
5600 /* end of function */
5601 if (do_debug) {
5602 put_stabn(N_FUN, 0, 0, ind - func_ind);
5604 funcname = ""; /* for safety */
5605 func_vt = VT_VOID; /* for safety */
5606 ind = 0; /* for safety */
5607 break;
5608 } else {
5609 if (b & VT_TYPEDEF) {
5610 /* save typedefed type */
5611 /* XXX: test storage specifiers ? */
5612 sym_push(v, t | VT_TYPEDEF, 0, 0);
5613 } else if ((t & VT_BTYPE) == VT_FUNC) {
5614 /* external function definition */
5615 external_sym(v, t, 0);
5616 } else {
5617 /* not lvalue if array */
5618 r = 0;
5619 if (!(t & VT_ARRAY))
5620 r |= VT_LVAL;
5621 if (b & VT_EXTERN) {
5622 /* external variable */
5623 external_sym(v, t, r);
5624 } else {
5625 if (t & VT_STATIC)
5626 r |= VT_CONST;
5627 else
5628 r |= l;
5629 has_init = (tok == '=');
5630 if (has_init)
5631 next();
5632 addr = decl_initializer_alloc(t, &ad, r,
5633 has_init);
5634 if (l == VT_CONST) {
5635 /* global scope: see if already defined */
5636 sym = sym_find(v);
5637 if (!sym)
5638 goto do_def;
5639 if (!is_compatible_types(sym->t, t))
5640 error("incompatible types for redefinition of '%s'",
5641 get_tok_str(v, NULL));
5642 if (!(sym->r & VT_FORWARD))
5643 error("redefinition of '%s'", get_tok_str(v, NULL));
5644 greloc_patch(sym, addr);
5645 } else {
5646 do_def:
5647 sym_push(v, t, r, addr);
5651 if (tok != ',') {
5652 skip(';');
5653 break;
5655 next();
5661 /* put all global symbols in the extern stack and do all the
5662 resolving which can be done without using external symbols from DLLs */
5663 /* XXX: could try to verify types, but would not to save them in
5664 extern_stack too */
5665 void resolve_global_syms(void)
5667 Sym *s, *s1, *ext_sym;
5668 Reloc **p;
5670 s = global_stack.top;
5671 while (s != NULL) {
5672 s1 = s->prev;
5673 /* do not save static or typedefed symbols or types */
5674 if (!(s->t & (VT_STATIC | VT_TYPEDEF)) &&
5675 !(s->v & (SYM_FIELD | SYM_STRUCT)) &&
5676 (s->v < SYM_FIRST_ANOM)) {
5677 ext_sym = sym_find1(&extern_stack, s->v);
5678 if (!ext_sym) {
5679 /* if the symbol do not exist, we simply save it */
5680 ext_sym = sym_push1(&extern_stack, s->v, s->t, s->c);
5681 ext_sym->r = s->r;
5682 } else if (ext_sym->r & VT_FORWARD) {
5683 /* external symbol already exists, but only as forward
5684 definition */
5685 if (!(s->r & VT_FORWARD)) {
5686 /* s is not forward, so we can relocate all symbols */
5687 greloc_patch(ext_sym, s->c);
5688 } else {
5689 /* the two symbols are forward: merge them */
5690 p = (Reloc **)&ext_sym->c;
5691 while (*p != NULL)
5692 p = &(*p)->next;
5693 *p = (Reloc *)s->c;
5695 } else {
5696 /* external symbol already exists and is defined :
5697 patch all references to it */
5698 if (!(s->r & VT_FORWARD))
5699 error("'%s' defined twice", get_tok_str(s->v, NULL));
5700 greloc_patch(s, ext_sym->c);
5703 s = s1;
5707 /* compile a C file. Return non zero if errors. */
5708 int tcc_compile_file(const char *filename1)
5710 Sym *define_start;
5711 char buf[512];
5713 funcname = "";
5715 file = tcc_open(filename1);
5716 if (!file)
5717 error("file '%s' not found", filename1);
5718 include_stack_ptr = include_stack;
5719 ifdef_stack_ptr = ifdef_stack;
5721 vtop = vstack - 1;
5722 anon_sym = SYM_FIRST_ANOM;
5724 /* file info: full path + filename */
5725 if (do_debug) {
5726 getcwd(buf, sizeof(buf));
5727 pstrcat(buf, sizeof(buf), "/");
5728 put_stabs(buf, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5729 put_stabs(file->filename, N_SO, 0, 0,
5730 (unsigned long)text_section->data_ptr);
5732 /* define common 'char *' type because it is often used internally
5733 for arrays and struct dereference */
5734 char_pointer_type = mk_pointer(VT_BYTE);
5736 define_start = define_stack.top;
5737 inp();
5738 ch = '\n'; /* needed to parse correctly first preprocessor command */
5739 next();
5740 decl(VT_CONST);
5741 if (tok != -1)
5742 expect("declaration");
5743 tcc_close(file);
5745 /* end of translation unit info */
5746 if (do_debug) {
5747 put_stabn(N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5750 /* reset define stack, but leave -Dsymbols (may be incorrect if
5751 they are undefined) */
5752 sym_pop(&define_stack, define_start);
5754 resolve_global_syms();
5756 sym_pop(&global_stack, NULL);
5758 return 0;
5761 /* define a symbol. A value can also be provided with the '=' operator */
5762 /* XXX: currently only handles integers and string defines. should use
5763 tcc parser, but would need a custom 'FILE *' */
5764 void define_symbol(const char *sym)
5766 char *p;
5767 BufferedFile bf1, *bf = &bf1;
5769 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
5770 p = strchr(bf->buffer, '=');
5771 if (!p) {
5772 /* default value */
5773 pstrcat(bf->buffer, IO_BUF_SIZE, " 1");
5774 } else {
5775 *p = ' ';
5778 /* init file structure */
5779 bf->fd = -1;
5780 bf->buf_ptr = bf->buffer;
5781 bf->buf_end = bf->buffer + strlen(bf->buffer);
5782 bf->filename[0] = '\0';
5783 bf->line_num = 1;
5784 file = bf;
5786 include_stack_ptr = include_stack;
5788 /* parse with define parser */
5789 inp();
5790 ch = '\n'; /* needed to parse correctly first preprocessor command */
5791 next_nomacro();
5792 parse_define();
5793 file = NULL;
5796 void undef_symbol(const char *sym)
5798 TokenSym *ts;
5799 Sym *s;
5800 ts = tok_alloc(sym, 0);
5801 s = sym_find1(&define_stack, tok);
5802 /* undefine symbol by putting an invalid name */
5803 if (s)
5804 sym_undef(&define_stack, s);
5807 /* open a dynamic library so that its symbol are available for
5808 compiled programs */
5809 void open_dll(char *libname)
5811 char buf[1024];
5812 void *h;
5814 snprintf(buf, sizeof(buf), "lib%s.so", libname);
5815 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
5816 if (!h)
5817 error((char *)dlerror());
5820 static void *resolve_sym(const char *sym)
5822 void *ptr;
5823 if (do_bounds_check) {
5824 ptr = bound_resolve_sym(sym);
5825 if (ptr)
5826 return ptr;
5828 return dlsym(NULL, sym);
5831 void resolve_extern_syms(void)
5833 Sym *s, *s1;
5834 char *str;
5835 int addr;
5837 s = extern_stack.top;
5838 while (s != NULL) {
5839 s1 = s->prev;
5840 if (s->r & VT_FORWARD) {
5841 /* if there is at least one relocation to do, then find it
5842 and patch it */
5843 if (s->c) {
5844 str = get_tok_str(s->v, NULL);
5845 addr = (int)resolve_sym(str);
5846 if (!addr)
5847 error("unresolved external reference '%s'", str);
5848 greloc_patch(s, addr);
5851 s = s1;
5855 static int put_elf_str(Section *s, const char *sym)
5857 int c, offset;
5858 offset = s->data_ptr - s->data;
5859 for(;;) {
5860 c = *sym++;
5861 *s->data_ptr++ = c;
5862 if (c == '\0')
5863 break;
5865 return offset;
5868 static void put_elf_sym(Section *s,
5869 unsigned long value, unsigned long size,
5870 int info, int other, int shndx, const char *name)
5872 int name_offset;
5873 Elf32_Sym *sym;
5875 sym = (Elf32_Sym *)s->data_ptr;
5876 if (name)
5877 name_offset = put_elf_str(s->link, name);
5878 else
5879 name_offset = 0;
5880 sym->st_name = name_offset;
5881 sym->st_value = value;
5882 sym->st_size = size;
5883 sym->st_info = info;
5884 sym->st_other = other;
5885 sym->st_shndx = shndx;
5886 s->data_ptr += sizeof(Elf32_Sym);
5889 /* put stab debug information */
5891 typedef struct {
5892 unsigned long n_strx; /* index into string table of name */
5893 unsigned char n_type; /* type of symbol */
5894 unsigned char n_other; /* misc info (usually empty) */
5895 unsigned short n_desc; /* description field */
5896 unsigned long n_value; /* value of symbol */
5897 } Stab_Sym;
5899 static void put_stabs(const char *str, int type, int other, int desc, int value)
5901 Stab_Sym *sym;
5903 sym = (Stab_Sym *)stab_section->data_ptr;
5904 if (str) {
5905 sym->n_strx = put_elf_str(stabstr_section, str);
5906 } else {
5907 sym->n_strx = 0;
5909 sym->n_type = type;
5910 sym->n_other = other;
5911 sym->n_desc = desc;
5912 sym->n_value = value;
5914 stab_section->data_ptr += sizeof(Stab_Sym);
5917 static void put_stabn(int type, int other, int desc, int value)
5919 put_stabs(NULL, type, other, desc, value);
5922 static void put_stabd(int type, int other, int desc)
5924 put_stabs(NULL, type, other, desc, 0);
5927 /* output an ELF file (currently, only for testing) */
5928 /* XXX: generate dynamic reloc info + DLL tables */
5929 /* XXX: generate startup code */
5930 /* XXX: better program header generation */
5931 /* XXX: handle realloc'ed sections (instead of mmaping them) */
5932 void build_exe(char *filename)
5934 Elf32_Ehdr ehdr;
5935 FILE *f;
5936 int shnum, i, phnum, file_offset, offset, size, j;
5937 Section *sec, *strsec;
5938 Elf32_Shdr *shdr, *sh;
5939 Elf32_Phdr *phdr, *ph;
5941 memset(&ehdr, 0, sizeof(ehdr));
5943 /* we add a section for symbols */
5944 strsec = new_section(".shstrtab", SHT_STRTAB, 0);
5945 put_elf_str(strsec, "");
5947 /* count number of sections and compute number of program segments */
5948 shnum = 1; /* section index zero is reserved */
5949 phnum = 0;
5950 for(sec = first_section; sec != NULL; sec = sec->next) {
5951 shnum++;
5952 if (sec->sh_flags & SHF_ALLOC)
5953 phnum++;
5955 /* allocate section headers */
5956 shdr = malloc(shnum * sizeof(Elf32_Shdr));
5957 if (!shdr)
5958 error("memory full");
5959 memset(shdr, 0, shnum * sizeof(Elf32_Shdr));
5960 /* allocate program segment headers */
5961 phdr = malloc(phnum * sizeof(Elf32_Phdr));
5962 if (!phdr)
5963 error("memory full");
5964 memset(phdr, 0, phnum * sizeof(Elf32_Phdr));
5966 /* XXX: find correct load order */
5967 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
5968 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
5969 sh = &shdr[i];
5970 sh->sh_name = put_elf_str(strsec, sec->name);
5971 sh->sh_type = sec->sh_type;
5972 sh->sh_flags = sec->sh_flags;
5973 sh->sh_entsize = sec->sh_entsize;
5974 if (sec->link)
5975 sh->sh_link = sec->link->sh_num;
5976 if (sh->sh_type == SHT_STRTAB) {
5977 sh->sh_addralign = 1;
5978 } else if (sh->sh_type == SHT_SYMTAB ||
5979 (sh->sh_flags & SHF_ALLOC) == 0) {
5980 sh->sh_addralign = 4;
5981 } else {
5982 sh->sh_addr = (Elf32_Word)sec->data;
5983 sh->sh_addralign = 4096;
5985 sh->sh_size = (Elf32_Word)sec->data_ptr - (Elf32_Word)sec->data;
5986 /* align to section start */
5987 file_offset = (file_offset + sh->sh_addralign - 1) &
5988 ~(sh->sh_addralign - 1);
5989 sh->sh_offset = file_offset;
5990 file_offset += sh->sh_size;
5992 /* build program headers (simplistic - not fully correct) */
5993 j = 0;
5994 for(i=1;i<shnum;i++) {
5995 sh = &shdr[i];
5996 if (sh->sh_type == SHT_PROGBITS &&
5997 (sh->sh_flags & SHF_ALLOC) != 0) {
5998 ph = &phdr[j++];
5999 ph->p_type = PT_LOAD;
6000 ph->p_offset = sh->sh_offset;
6001 ph->p_vaddr = sh->sh_addr;
6002 ph->p_paddr = ph->p_vaddr;
6003 ph->p_filesz = sh->sh_size;
6004 ph->p_memsz = sh->sh_size;
6005 ph->p_flags = PF_R;
6006 if (sh->sh_flags & SHF_WRITE)
6007 ph->p_flags |= PF_W;
6008 if (sh->sh_flags & SHF_EXECINSTR)
6009 ph->p_flags |= PF_X;
6010 ph->p_align = sh->sh_addralign;
6014 /* align to 4 */
6015 file_offset = (file_offset + 3) & -4;
6017 /* fill header */
6018 ehdr.e_ident[0] = ELFMAG0;
6019 ehdr.e_ident[1] = ELFMAG1;
6020 ehdr.e_ident[2] = ELFMAG2;
6021 ehdr.e_ident[3] = ELFMAG3;
6022 ehdr.e_ident[4] = ELFCLASS32;
6023 ehdr.e_ident[5] = ELFDATA2LSB;
6024 ehdr.e_ident[6] = EV_CURRENT;
6025 ehdr.e_type = ET_EXEC;
6026 ehdr.e_machine = EM_386;
6027 ehdr.e_version = EV_CURRENT;
6028 ehdr.e_entry = 0; /* XXX: patch it */
6029 ehdr.e_phoff = sizeof(Elf32_Ehdr);
6030 ehdr.e_shoff = file_offset;
6031 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
6032 ehdr.e_phentsize = sizeof(Elf32_Phdr);
6033 ehdr.e_phnum = phnum;
6034 ehdr.e_shentsize = sizeof(Elf32_Shdr);
6035 ehdr.e_shnum = shnum;
6036 ehdr.e_shstrndx = shnum - 1;
6038 /* write elf file */
6039 f = fopen(filename, "w");
6040 if (!f)
6041 error("could not write '%s'", filename);
6042 fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
6043 fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
6044 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
6045 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
6046 sh = &shdr[i];
6047 while (offset < sh->sh_offset) {
6048 fputc(0, f);
6049 offset++;
6051 size = sec->data_ptr - sec->data;
6052 fwrite(sec->data, 1, size, f);
6053 offset += size;
6055 while (offset < ehdr.e_shoff) {
6056 fputc(0, f);
6057 offset++;
6059 fwrite(shdr, 1, shnum * sizeof(Elf32_Shdr), f);
6060 fclose(f);
6063 /* print the position in the source file of PC value 'pc' by reading
6064 the stabs debug information */
6065 static void rt_printline(unsigned long wanted_pc)
6067 Stab_Sym *sym, *sym_end;
6068 char func_name[128];
6069 unsigned long func_addr, last_pc, pc;
6070 const char *incl_files[INCLUDE_STACK_SIZE];
6071 int incl_index, len, last_line_num, i;
6072 const char *str, *p;
6074 func_name[0] = '\0';
6075 func_addr = 0;
6076 incl_index = 0;
6077 last_pc = 0xffffffff;
6078 last_line_num = 1;
6079 sym = (Stab_Sym *)stab_section->data + 1;
6080 sym_end = (Stab_Sym *)stab_section->data_ptr;
6081 while (sym < sym_end) {
6082 switch(sym->n_type) {
6083 /* function start or end */
6084 case N_FUN:
6085 if (sym->n_strx == 0) {
6086 func_name[0] = '\0';
6087 func_addr = 0;
6088 } else {
6089 str = stabstr_section->data + sym->n_strx;
6090 p = strchr(str, ':');
6091 if (!p) {
6092 pstrcpy(func_name, sizeof(func_name), str);
6093 } else {
6094 len = p - str;
6095 if (len > sizeof(func_name) - 1)
6096 len = sizeof(func_name) - 1;
6097 memcpy(func_name, str, len);
6098 func_name[len] = '\0';
6100 func_addr = sym->n_value;
6102 break;
6103 /* line number info */
6104 case N_SLINE:
6105 pc = sym->n_value + func_addr;
6106 if (wanted_pc >= last_pc && wanted_pc < pc)
6107 goto found;
6108 last_pc = pc;
6109 last_line_num = sym->n_desc;
6110 break;
6111 /* include files */
6112 case N_BINCL:
6113 str = stabstr_section->data + sym->n_strx;
6114 add_incl:
6115 if (incl_index < INCLUDE_STACK_SIZE) {
6116 incl_files[incl_index++] = str;
6118 break;
6119 case N_EINCL:
6120 if (incl_index > 1)
6121 incl_index--;
6122 break;
6123 case N_SO:
6124 if (sym->n_strx == 0) {
6125 incl_index = 0; /* end of translation unit */
6126 } else {
6127 str = stabstr_section->data + sym->n_strx;
6128 /* do not add path */
6129 len = strlen(str);
6130 if (len > 0 && str[len - 1] != '/')
6131 goto add_incl;
6133 break;
6135 sym++;
6137 /* did not find line number info: */
6138 fprintf(stderr, "(no debug info, pc=0x%08lx): ", wanted_pc);
6139 return;
6140 found:
6141 for(i = 0; i < incl_index - 1; i++)
6142 fprintf(stderr, "In file included from %s\n",
6143 incl_files[i]);
6144 if (incl_index > 0) {
6145 fprintf(stderr, "%s:%d: ",
6146 incl_files[incl_index - 1], last_line_num);
6148 if (func_name[0] != '\0') {
6149 fprintf(stderr, "in function '%s()': ", func_name);
6153 /* emit a run time error at position 'pc' */
6154 void rt_error(unsigned long pc, const char *fmt, ...)
6156 va_list ap;
6157 va_start(ap, fmt);
6159 rt_printline(pc);
6160 vfprintf(stderr, fmt, ap);
6161 fprintf(stderr, "\n");
6162 exit(255);
6163 va_end(ap);
6166 #ifndef WIN32
6167 /* signal handler for fatal errors */
6168 static void sig_error(int signum, siginfo_t *siginf, void *puc)
6170 struct ucontext *uc = puc;
6171 unsigned long pc;
6173 #ifdef __i386__
6174 pc = uc->uc_mcontext.gregs[14];
6175 #else
6176 #error please put the right sigcontext field
6177 #endif
6179 switch(signum) {
6180 case SIGFPE:
6181 switch(siginf->si_code) {
6182 case FPE_INTDIV:
6183 case FPE_FLTDIV:
6184 rt_error(pc, "division by zero");
6185 break;
6186 default:
6187 rt_error(pc, "floating point exception");
6188 break;
6190 break;
6191 case SIGBUS:
6192 case SIGSEGV:
6193 rt_error(pc, "dereferencing invalid pointer");
6194 break;
6195 case SIGILL:
6196 rt_error(pc, "illegal instruction");
6197 break;
6198 case SIGABRT:
6199 rt_error(pc, "abort() called");
6200 break;
6201 default:
6202 rt_error(pc, "caught signal %d", signum);
6203 break;
6205 exit(255);
6207 #endif
6209 /* launch the compiled program with the given arguments */
6210 int launch_exe(int argc, char **argv)
6212 Sym *s;
6213 int (*t)();
6215 s = sym_find1(&extern_stack, TOK_MAIN);
6216 if (!s || (s->r & VT_FORWARD))
6217 error("main() not defined");
6219 if (do_debug) {
6220 #ifdef WIN32
6221 error("debug mode currently not available for Windows");
6222 #else
6223 struct sigaction sigact;
6224 /* install TCC signal handlers to print debug info on fatal
6225 runtime errors */
6226 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
6227 sigact.sa_sigaction = sig_error;
6228 sigemptyset(&sigact.sa_mask);
6229 sigaction(SIGFPE, &sigact, NULL);
6230 sigaction(SIGILL, &sigact, NULL);
6231 sigaction(SIGSEGV, &sigact, NULL);
6232 sigaction(SIGBUS, &sigact, NULL);
6233 sigaction(SIGABRT, &sigact, NULL);
6234 #endif
6237 if (do_bounds_check) {
6238 #ifdef WIN32
6239 error("bound checking currently not available for Windows");
6240 #else
6241 int *p, *p_end;
6242 __bound_init();
6243 /* add all known static regions */
6244 p = (int *)bounds_section->data;
6245 p_end = (int *)bounds_section->data_ptr;
6246 while (p < p_end) {
6247 __bound_new_region((void *)p[0], p[1]);
6248 p += 2;
6250 #endif
6253 t = (int (*)())s->c;
6254 return (*t)(argc, argv);
6258 void help(void)
6260 printf("tcc version 0.9.4 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
6261 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
6262 " [-i infile] infile [infile_args...]\n"
6263 "\n"
6264 "-Idir : add include path 'dir'\n"
6265 "-Dsym[=val] : define 'sym' with value 'val'\n"
6266 "-Usym : undefine 'sym'\n"
6267 "-llib : link with dynamic library 'lib'\n"
6268 "-g : generate runtime debug info\n"
6269 "-b : compile with built-in memory and bounds checker (implies -g)\n"
6270 "-i infile : compile infile\n"
6274 int main(int argc, char **argv)
6276 char *p, *r, *outfile;
6277 int optind;
6279 include_paths[0] = "/usr/include";
6280 include_paths[1] = "/usr/lib/tcc";
6281 include_paths[2] = "/usr/local/lib/tcc";
6282 nb_include_paths = 3;
6284 /* add all tokens */
6285 tok_ident = TOK_IDENT;
6286 p = tcc_keywords;
6287 while (*p) {
6288 r = p;
6289 while (*r++);
6290 tok_alloc(p, r - p - 1);
6291 p = r;
6294 /* standard defines */
6295 define_symbol("__STDC__");
6296 #ifdef __i386__
6297 define_symbol("__i386__");
6298 #endif
6299 /* tiny C specific defines */
6300 define_symbol("__TINYC__");
6302 /* create standard sections */
6303 text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
6304 data_section = new_section(".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6305 /* XXX: should change type to SHT_NOBITS */
6306 bss_section = new_section(".bss", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6308 optind = 1;
6309 outfile = NULL;
6310 while (1) {
6311 if (optind >= argc) {
6312 show_help:
6313 help();
6314 return 1;
6316 r = argv[optind];
6317 if (r[0] != '-')
6318 break;
6319 optind++;
6320 if (r[1] == 'I') {
6321 if (nb_include_paths >= INCLUDE_PATHS_MAX)
6322 error("too many include paths");
6323 include_paths[nb_include_paths++] = r + 2;
6324 } else if (r[1] == 'D') {
6325 define_symbol(r + 2);
6326 } else if (r[1] == 'U') {
6327 undef_symbol(r + 2);
6328 } else if (r[1] == 'l') {
6329 open_dll(r + 2);
6330 } else if (r[1] == 'i') {
6331 if (optind >= argc)
6332 goto show_help;
6333 tcc_compile_file(argv[optind++]);
6334 } else if (!strcmp(r + 1, "bench")) {
6335 do_bench = 1;
6336 } else if (r[1] == 'b') {
6337 if (!do_bounds_check) {
6338 do_bounds_check = 1;
6339 /* define symbol */
6340 define_symbol("__BOUNDS_CHECKING_ON");
6341 /* create bounds sections */
6342 bounds_section = new_section(".bounds",
6343 SHT_PROGBITS, SHF_ALLOC);
6344 lbounds_section = new_section(".lbounds",
6345 SHT_PROGBITS, SHF_ALLOC);
6346 /* debug is implied */
6347 goto debug_opt;
6349 } else if (r[1] == 'g') {
6350 debug_opt:
6351 if (!do_debug) {
6352 do_debug = 1;
6354 /* stab symbols */
6355 stab_section = new_section(".stab", SHT_PROGBITS, 0);
6356 stab_section->sh_entsize = sizeof(Stab_Sym);
6357 stabstr_section = new_section(".stabstr", SHT_STRTAB, 0);
6358 put_elf_str(stabstr_section, "");
6359 stab_section->link = stabstr_section;
6360 /* put first entry */
6361 put_stabs("", 0, 0, 0, 0);
6363 /* elf symbols */
6364 symtab_section = new_section(".symtab", SHT_SYMTAB, 0);
6365 symtab_section->sh_entsize = sizeof(Elf32_Sym);
6366 strtab_section = new_section(".strtab", SHT_STRTAB, 0);
6367 put_elf_str(strtab_section, "");
6368 symtab_section->link = strtab_section;
6369 put_elf_sym(symtab_section, 0, 0, 0, 0, 0, NULL);
6371 } else if (r[1] == 'o') {
6372 /* currently, only for testing, so not documented */
6373 if (optind >= argc)
6374 goto show_help;
6375 outfile = argv[optind++];
6376 } else {
6377 fprintf(stderr, "invalid option -- '%s'\n", r);
6378 exit(1);
6382 tcc_compile_file(argv[optind]);
6384 if (do_bench) {
6385 printf("total: %d idents, %d lines, %d bytes\n",
6386 tok_ident - TOK_IDENT, total_lines, total_bytes);
6389 resolve_extern_syms();
6391 if (outfile) {
6392 build_exe(outfile);
6393 return 0;
6394 } else {
6395 return launch_exe(argc - optind, argv + optind);