update
[tinycc.git] / tcc.c
blobf2c9d077ec5b8ffb6326308e8a5031d40d6c11fc
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 /* target selection */
46 //#define TCC_TARGET_I386 /* i386 code generator */
47 //#define TCC_TARGET_IL /* .NET CLI generator */
49 /* default target is I386 */
50 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_IL)
51 #define TCC_TARGET_I386
52 #endif
54 /* amount of virtual memory associated to a section (currently, we do
55 not realloc them) */
56 #define SECTION_VSIZE (1024 * 1024)
58 #define INCLUDE_STACK_SIZE 32
59 #define IFDEF_STACK_SIZE 64
60 #define VSTACK_SIZE 64
61 #define STRING_MAX_SIZE 1024
62 #define INCLUDE_PATHS_MAX 32
64 #define TOK_HASH_SIZE 2048 /* must be a power of two */
65 #define TOK_ALLOC_INCR 512 /* must be a power of two */
66 #define SYM_HASH_SIZE 1031
68 /* token symbol management */
69 typedef struct TokenSym {
70 struct TokenSym *hash_next;
71 int tok; /* token number */
72 int len;
73 char str[1];
74 } TokenSym;
76 /* constant value */
77 typedef union CValue {
78 long double ld;
79 double d;
80 float f;
81 int i;
82 unsigned int ui;
83 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
84 long long ll;
85 unsigned long long ull;
86 struct TokenSym *ts;
87 struct Sym *sym;
88 int tab[1];
89 } CValue;
91 /* value on stack */
92 typedef struct SValue {
93 int t; /* type */
94 unsigned short r; /* register + flags */
95 unsigned short r2; /* second register, used for 'long long'
96 type. If not used, set to VT_CONST */
97 CValue c; /* constant */
98 } SValue;
100 /* symbol management */
101 typedef struct Sym {
102 int v; /* symbol token */
103 int t; /* associated type */
104 int r; /* associated register */
105 int c; /* associated number */
106 struct Sym *next; /* next related symbol */
107 struct Sym *prev; /* prev symbol in stack */
108 struct Sym *hash_next; /* next symbol in hash table */
109 } Sym;
111 typedef struct SymStack {
112 struct Sym *top;
113 struct Sym *hash[SYM_HASH_SIZE];
114 } SymStack;
116 /* relocation entry (currently only used for functions or variables */
117 typedef struct Reloc {
118 int type; /* type of relocation */
119 int addr; /* address of relocation */
120 struct Reloc *next; /* next relocation */
121 } Reloc;
123 #define RELOC_ADDR32 1 /* 32 bits relocation */
124 #define RELOC_REL32 2 /* 32 bits relative relocation */
126 /* section definition */
127 typedef struct Section {
128 char name[64]; /* section name */
129 unsigned char *data; /* section data */
130 unsigned char *data_ptr; /* current data pointer */
131 int sh_num; /* elf section number */
132 int sh_type; /* elf section type */
133 int sh_flags; /* elf section flags */
134 int sh_entsize; /* elf entry size */
135 struct Section *link; /* link to another section */
136 struct Section *next;
137 } Section;
139 /* GNUC attribute definition */
140 typedef struct AttributeDef {
141 int aligned;
142 Section *section;
143 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
144 } AttributeDef;
146 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
147 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
148 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
150 /* stored in 'Sym.c' field */
151 #define FUNC_NEW 1 /* ansi function prototype */
152 #define FUNC_OLD 2 /* old function prototype */
153 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
155 /* stored in 'Sym.r' field */
156 #define FUNC_CDECL 0 /* standard c call */
157 #define FUNC_STDCALL 1 /* pascal c call */
159 /* field 'Sym.t' for macros */
160 #define MACRO_OBJ 0 /* object like macro */
161 #define MACRO_FUNC 1 /* function like macro */
163 /* type_decl() types */
164 #define TYPE_ABSTRACT 1 /* type without variable */
165 #define TYPE_DIRECT 2 /* type with variable */
167 #define IO_BUF_SIZE 8192
169 typedef struct BufferedFile {
170 unsigned char *buf_ptr;
171 unsigned char *buf_end;
172 int fd;
173 int line_num; /* current line number - here to simply code */
174 char filename[1024]; /* current filename - here to simply code */
175 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
176 } BufferedFile;
178 #define CH_EOB 0 /* end of buffer or '\0' char in file */
179 #define CH_EOF (-1) /* end of file */
181 /* parser */
182 struct BufferedFile *file;
183 int ch, ch1, tok, tok1;
184 CValue tokc, tok1c;
186 /* sections */
187 Section *first_section;
188 int section_num;
189 Section *text_section, *data_section, *bss_section; /* predefined sections */
190 Section *cur_text_section; /* current section where function code is
191 generated */
192 /* bound check related sections */
193 Section *bounds_section; /* contains global data bound description */
194 Section *lbounds_section; /* contains local data bound description */
195 /* debug sections */
196 Section *stab_section, *stabstr_section, *symtab_section, *strtab_section;
198 /* loc : local variable index
199 ind : output code index
200 rsym: return symbol
201 anon_sym: anonymous symbol index
203 int rsym, anon_sym,
204 prog, ind, loc, const_wanted;
205 int global_expr; /* true if compound literals must be allocated
206 globally (used during initializers parsing */
207 int func_vt, func_vc; /* current function return type (used by
208 return instruction) */
209 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
210 int tok_ident;
211 TokenSym **table_ident;
212 TokenSym *hash_ident[TOK_HASH_SIZE];
213 char token_buf[STRING_MAX_SIZE + 1];
214 char *funcname;
215 /* contains global symbols which remain between each translation unit */
216 SymStack extern_stack;
217 SymStack define_stack, global_stack, local_stack, label_stack;
219 SValue vstack[VSTACK_SIZE], *vtop;
220 int *macro_ptr, *macro_ptr_allocated;
221 BufferedFile *include_stack[INCLUDE_STACK_SIZE], **include_stack_ptr;
222 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
223 char *include_paths[INCLUDE_PATHS_MAX];
224 int nb_include_paths;
225 int char_pointer_type;
227 /* compile with debug symbol (and use them if error during execution) */
228 int do_debug = 0;
230 /* compile with built-in memory and bounds checker */
231 int do_bounds_check = 0;
233 /* display benchmark infos */
234 int do_bench = 0;
235 int total_lines;
236 int total_bytes;
238 /* use GNU C extensions */
239 int gnu_ext = 1;
241 /* use Tiny C extensions */
242 int tcc_ext = 1;
244 /* The current value can be: */
245 #define VT_VALMASK 0x00ff
246 #define VT_CONST 0x00f0 /* constant in vc
247 (must be first non register value) */
248 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
249 #define VT_LOCAL 0x00f2 /* offset on stack */
250 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
251 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
252 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
253 #define VT_LVAL 0x0100 /* var is an lvalue */
254 #define VT_FORWARD 0x0200 /* value is forward reference */
255 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
256 char/short stored in integer registers) */
257 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
258 dereferencing value */
260 /* types */
261 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
263 #define VT_INT 0 /* integer type */
264 #define VT_BYTE 1 /* signed byte type */
265 #define VT_SHORT 2 /* short type */
266 #define VT_VOID 3 /* void type */
267 #define VT_PTR 4 /* pointer increment */
268 #define VT_ENUM 5 /* enum definition */
269 #define VT_FUNC 6 /* function type */
270 #define VT_STRUCT 7 /* struct/union definition */
271 #define VT_FLOAT 8 /* IEEE float */
272 #define VT_DOUBLE 9 /* IEEE double */
273 #define VT_LDOUBLE 10 /* IEEE long double */
274 #define VT_BOOL 11 /* ISOC99 boolean type */
275 #define VT_LLONG 12 /* 64 bit integer */
276 #define VT_LONG 13 /* long integer (NEVER USED as type, only
277 during parsing) */
278 #define VT_BTYPE 0x000f /* mask for basic type */
279 #define VT_UNSIGNED 0x0010 /* unsigned type */
280 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
281 #define VT_BITFIELD 0x0040 /* bitfield modifier */
283 /* storage */
284 #define VT_EXTERN 0x00000080 /* extern definition */
285 #define VT_STATIC 0x00000100 /* static variable */
286 #define VT_TYPEDEF 0x00000200 /* typedef definition */
288 /* type mask (except storage) */
289 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
291 /* token values */
293 /* warning: the following compare tokens depend on i386 asm code */
294 #define TOK_ULT 0x92
295 #define TOK_UGE 0x93
296 #define TOK_EQ 0x94
297 #define TOK_NE 0x95
298 #define TOK_ULE 0x96
299 #define TOK_UGT 0x97
300 #define TOK_LT 0x9c
301 #define TOK_GE 0x9d
302 #define TOK_LE 0x9e
303 #define TOK_GT 0x9f
305 #define TOK_LAND 0xa0
306 #define TOK_LOR 0xa1
308 #define TOK_DEC 0xa2
309 #define TOK_MID 0xa3 /* inc/dec, to void constant */
310 #define TOK_INC 0xa4
311 #define TOK_UDIV 0xb0 /* unsigned division */
312 #define TOK_UMOD 0xb1 /* unsigned modulo */
313 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
314 #define TOK_CINT 0xb3 /* number in tokc */
315 #define TOK_CCHAR 0xb4 /* char constant in tokc */
316 #define TOK_STR 0xb5 /* pointer to string in tokc */
317 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
318 #define TOK_LCHAR 0xb7
319 #define TOK_LSTR 0xb8
320 #define TOK_CFLOAT 0xb9 /* float constant */
321 #define TOK_CDOUBLE 0xc0 /* double constant */
322 #define TOK_CLDOUBLE 0xc1 /* long double constant */
323 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
324 #define TOK_ADDC1 0xc3 /* add with carry generation */
325 #define TOK_ADDC2 0xc4 /* add with carry use */
326 #define TOK_SUBC1 0xc5 /* add with carry generation */
327 #define TOK_SUBC2 0xc6 /* add with carry use */
328 #define TOK_CUINT 0xc8 /* unsigned int constant */
329 #define TOK_CLLONG 0xc9 /* long long constant */
330 #define TOK_CULLONG 0xca /* unsigned long long constant */
331 #define TOK_ARROW 0xcb
332 #define TOK_DOTS 0xcc /* three dots */
333 #define TOK_SHR 0xcd /* unsigned shift right */
335 #define TOK_SHL 0x01 /* shift left */
336 #define TOK_SAR 0x02 /* signed shift right */
338 /* assignement operators : normal operator or 0x80 */
339 #define TOK_A_MOD 0xa5
340 #define TOK_A_AND 0xa6
341 #define TOK_A_MUL 0xaa
342 #define TOK_A_ADD 0xab
343 #define TOK_A_SUB 0xad
344 #define TOK_A_DIV 0xaf
345 #define TOK_A_XOR 0xde
346 #define TOK_A_OR 0xfc
347 #define TOK_A_SHL 0x81
348 #define TOK_A_SAR 0x82
350 #define TOK_EOF (-1) /* end of file */
352 /* all identificators and strings have token above that */
353 #define TOK_IDENT 256
355 enum {
356 TOK_INT = TOK_IDENT,
357 TOK_VOID,
358 TOK_CHAR,
359 TOK_IF,
360 TOK_ELSE,
361 TOK_WHILE,
362 TOK_BREAK,
363 TOK_RETURN,
364 TOK_FOR,
365 TOK_EXTERN,
366 TOK_STATIC,
367 TOK_UNSIGNED,
368 TOK_GOTO,
369 TOK_DO,
370 TOK_CONTINUE,
371 TOK_SWITCH,
372 TOK_CASE,
374 /* ignored types Must have contiguous values */
375 TOK_CONST,
376 TOK_VOLATILE,
377 TOK_LONG,
378 TOK_REGISTER,
379 TOK_SIGNED,
380 TOK___SIGNED__, /* gcc keyword */
381 TOK_AUTO,
382 TOK_INLINE,
383 TOK___INLINE__, /* gcc keyword */
384 TOK_RESTRICT,
386 /* unsupported type */
387 TOK_FLOAT,
388 TOK_DOUBLE,
389 TOK_BOOL,
391 TOK_SHORT,
392 TOK_STRUCT,
393 TOK_UNION,
394 TOK_TYPEDEF,
395 TOK_DEFAULT,
396 TOK_ENUM,
397 TOK_SIZEOF,
398 TOK___ATTRIBUTE__,
400 /* preprocessor only */
401 TOK_UIDENT, /* first "user" ident (not keyword) */
402 TOK_DEFINE = TOK_UIDENT,
403 TOK_INCLUDE,
404 TOK_IFDEF,
405 TOK_IFNDEF,
406 TOK_ELIF,
407 TOK_ENDIF,
408 TOK_DEFINED,
409 TOK_UNDEF,
410 TOK_ERROR,
411 TOK_LINE,
412 TOK___LINE__,
413 TOK___FILE__,
414 TOK___DATE__,
415 TOK___TIME__,
416 TOK___VA_ARGS__,
418 /* special identifiers */
419 TOK___FUNC__,
420 TOK_MAIN,
421 /* attribute identifiers */
422 TOK_SECTION,
423 TOK___SECTION__,
424 TOK_ALIGNED,
425 TOK___ALIGNED__,
426 TOK_UNUSED,
427 TOK___UNUSED__,
428 TOK_CDECL,
429 TOK___CDECL,
430 TOK___CDECL__,
431 TOK_STDCALL,
432 TOK___STDCALL,
433 TOK___STDCALL__,
434 TOK_NORETURN,
435 TOK___NORETURN__,
438 char *tcc_keywords =
439 "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
440 "unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
441 "register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
442 "float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
443 "sizeof\0__attribute__\0"
444 /* the following are not keywords. They are included to ease parsing */
445 "define\0include\0ifdef\0ifndef\0elif\0endif\0"
446 "defined\0undef\0error\0line\0"
447 "__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0"
448 "__func__\0main\0"
449 /* attributes */
450 "section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0"
451 "cdecl\0__cdecl\0__cdecl__\0stdcall\0__stdcall\0__stdcall__\0"
452 "noreturn\0__noreturn__\0"
455 #ifdef WIN32
456 #define snprintf _snprintf
457 /* currently incorrect */
458 long double strtold(const char *nptr, char **endptr)
460 return (long double)strtod(nptr, endptr);
462 float strtof(const char *nptr, char **endptr)
464 return (float)strtod(nptr, endptr);
466 #else
467 /* XXX: need to define this to use them in non ISOC99 context */
468 extern float strtof (const char *__nptr, char **__endptr);
469 extern long double strtold (const char *__nptr, char **__endptr);
470 #endif
472 char *pstrcpy(char *buf, int buf_size, const char *s);
473 char *pstrcat(char *buf, int buf_size, const char *s);
475 void sum(int l);
476 void next(void);
477 void next_nomacro(void);
478 int expr_const(void);
479 void expr_eq(void);
480 void gexpr(void);
481 void decl(int l);
482 void decl_initializer(int t, int r, int c, int first, int size_only);
483 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init);
484 int gv(int rc);
485 void gv2(int rc1, int rc2);
486 void move_reg(int r, int s);
487 void save_regs(void);
488 void save_reg(int r);
489 void vpop(void);
490 void vswap(void);
491 void vdup(void);
492 int get_reg(int rc);
494 void macro_subst(int **tok_str, int *tok_len,
495 Sym **nested_list, int *macro_str);
496 int save_reg_forced(int r);
497 void gen_op(int op);
498 void force_charshort_cast(int t);
499 void gen_cast(int t);
500 void vstore(void);
501 Sym *sym_find(int v);
502 Sym *sym_push(int v, int t, int r, int c);
504 /* type handling */
505 int type_size(int t, int *a);
506 int pointed_type(int t);
507 int pointed_size(int t);
508 int is_compatible_types(int t1, int t2);
509 int parse_btype(int *type_ptr, AttributeDef *ad);
510 int type_decl(AttributeDef *ad, int *v, int t, int td);
512 void error(const char *fmt, ...);
513 void rt_error(unsigned long pc, const char *fmt, ...);
514 void vpushi(int v);
515 void vset(int t, int r, int v);
516 void type_to_str(char *buf, int buf_size,
517 int t, const char *varstr);
519 /* section generation */
520 void greloc(Sym *s, int addr, int type);
521 static int put_elf_str(Section *s, const char *sym);
522 static void put_elf_sym(Section *s,
523 unsigned long value, unsigned long size,
524 int info, int other, int shndx, const char *name);
525 static void put_stabs(const char *str, int type, int other, int desc, int value);
526 static void put_stabn(int type, int other, int desc, int value);
527 static void put_stabd(int type, int other, int desc);
529 /* true if float/double/long double type */
530 static inline int is_float(int t)
532 int bt;
533 bt = t & VT_BTYPE;
534 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
537 #include "bcheck.c"
539 #ifdef TCC_TARGET_I386
540 #include "i386-gen.c"
541 #endif
542 #ifdef TCC_TARGET_IL
543 #include "il-gen.c"
544 #endif
546 #ifdef CONFIG_TCC_STATIC
548 #define RTLD_LAZY 0x001
549 #define RTLD_NOW 0x002
550 #define RTLD_GLOBAL 0x100
552 /* dummy function for profiling */
553 void *dlopen(const char *filename, int flag)
555 return NULL;
558 const char *dlerror(void)
560 return "error";
563 typedef struct TCCSyms {
564 char *str;
565 void *ptr;
566 } TCCSyms;
568 #define TCCSYM(a) { #a, &a, },
570 /* add the symbol you want here if no dynamic linking is done */
571 static TCCSyms tcc_syms[] = {
572 TCCSYM(printf)
573 TCCSYM(fprintf)
574 TCCSYM(fopen)
575 TCCSYM(fclose)
576 { NULL, NULL },
579 void *dlsym(void *handle, const char *symbol)
581 TCCSyms *p;
582 p = tcc_syms;
583 while (p->str != NULL) {
584 if (!strcmp(p->str, symbol))
585 return p->ptr;
586 p++;
588 return NULL;
591 #endif
593 /********************************************************/
594 /* runtime library is there */
595 /* XXX: we suppose that the host compiler handles 'long long'. It
596 would not be difficult to suppress this assumption */
598 long long __divll(long long a, long long b)
600 return a / b;
603 long long __modll(long long a, long long b)
605 return a % b;
608 unsigned long long __divull(unsigned long long a, unsigned long long b)
610 return a / b;
613 unsigned long long __modull(unsigned long long a, unsigned long long b)
615 return a % b;
618 long long __sardi3(long long a, int b)
620 return a >> b;
623 unsigned long long __shrdi3(unsigned long long a, int b)
625 return a >> b;
628 long long __shldi3(long long a, int b)
630 return a << b;
633 float __ulltof(unsigned long long a)
635 return (float)a;
638 double __ulltod(unsigned long long a)
640 return (double)a;
643 long double __ulltold(unsigned long long a)
645 return (long double)a;
648 unsigned long long __ftoull(float a)
650 return (unsigned long long)a;
653 unsigned long long __dtoull(double a)
655 return (unsigned long long)a;
658 unsigned long long __ldtoull(long double a)
660 return (unsigned long long)a;
664 /********************************************************/
666 /* copy a string and truncate it. */
667 char *pstrcpy(char *buf, int buf_size, const char *s)
669 char *q, *q_end;
670 int c;
672 if (buf_size > 0) {
673 q = buf;
674 q_end = buf + buf_size - 1;
675 while (q < q_end) {
676 c = *s++;
677 if (c == '\0')
678 break;
679 *q++ = c;
681 *q = '\0';
683 return buf;
686 /* strcat and truncate. */
687 char *pstrcat(char *buf, int buf_size, const char *s)
689 int len;
690 len = strlen(buf);
691 if (len < buf_size)
692 pstrcpy(buf + len, buf_size - len, s);
693 return buf;
696 Section *new_section(const char *name, int sh_type, int sh_flags)
698 Section *sec, **psec;
699 void *data;
701 sec = malloc(sizeof(Section));
702 if (!sec)
703 error("memory full");
704 memset(sec, 0, sizeof(Section));
705 pstrcpy(sec->name, sizeof(sec->name), name);
706 sec->link = NULL;
707 sec->sh_num = ++section_num;
708 sec->sh_type = sh_type;
709 sec->sh_flags = sh_flags;
710 #ifdef WIN32
711 /* XXX: currently, a single malloc */
712 data = malloc(SECTION_VSIZE);
713 if (data == NULL)
714 error("could not alloc section '%s'", name);
715 #else
716 data = mmap(NULL, SECTION_VSIZE,
717 PROT_EXEC | PROT_READ | PROT_WRITE,
718 MAP_PRIVATE | MAP_ANONYMOUS,
719 -1, 0);
720 if (data == (void *)(-1))
721 error("could not mmap section '%s'", name);
722 #endif
723 sec->data = data;
724 sec->data_ptr = data;
725 psec = &first_section;
726 while (*psec != NULL)
727 psec = &(*psec)->next;
728 sec->next = NULL;
729 *psec = sec;
730 return sec;
733 /* return a reference to a section, and create it if it does not
734 exists */
735 Section *find_section(const char *name)
737 Section *sec;
739 for(sec = first_section; sec != NULL; sec = sec->next) {
740 if (!strcmp(name, sec->name))
741 return sec;
743 /* sections are created as PROGBITS */
744 return new_section(name, SHT_PROGBITS, SHF_ALLOC);
747 /* add a new relocation entry to symbol 's' */
748 void greloc(Sym *s, int addr, int type)
750 Reloc *p;
751 p = malloc(sizeof(Reloc));
752 if (!p)
753 error("memory full");
754 p->type = type;
755 p->addr = addr;
756 p->next = (Reloc *)s->c;
757 s->c = (int)p;
760 /* patch each relocation entry with value 'val' */
761 void greloc_patch(Sym *s, int val)
763 Reloc *p, *p1;
765 p = (Reloc *)s->c;
766 while (p != NULL) {
767 p1 = p->next;
768 greloc_patch1(p, val);
769 free(p);
770 p = p1;
772 s->c = val;
773 s->r &= ~VT_FORWARD;
777 static inline int isid(int c)
779 return (c >= 'a' && c <= 'z') ||
780 (c >= 'A' && c <= 'Z') ||
781 c == '_';
784 static inline int isnum(int c)
786 return c >= '0' && c <= '9';
789 static inline int toup(int c)
791 if (ch >= 'a' && ch <= 'z')
792 return ch - 'a' + 'A';
793 else
794 return ch;
797 void printline(void)
799 BufferedFile **f;
800 for(f = include_stack; f < include_stack_ptr; f++)
801 fprintf(stderr, "In file included from %s:%d:\n",
802 (*f)->filename, (*f)->line_num);
803 fprintf(stderr, "%s:%d: ", file->filename, file->line_num);
806 void error(const char *fmt, ...)
808 va_list ap;
809 va_start(ap, fmt);
810 printline();
811 vfprintf(stderr, fmt, ap);
812 fprintf(stderr, "\n");
813 exit(1);
814 va_end(ap);
817 void expect(const char *msg)
819 error("%s expected", msg);
822 void warning(const char *fmt, ...)
824 va_list ap;
826 va_start(ap, fmt);
827 printline();
828 fprintf(stderr, "warning: ");
829 vfprintf(stderr, fmt, ap);
830 fprintf(stderr, "\n");
831 va_end(ap);
834 void skip(int c)
836 if (tok != c)
837 error("'%c' expected", c);
838 next();
841 void test_lvalue(void)
843 if (!(vtop->r & VT_LVAL))
844 expect("lvalue");
847 TokenSym *tok_alloc(const char *str, int len)
849 TokenSym *ts, **pts, **ptable;
850 int h, i;
852 if (len <= 0)
853 len = strlen(str);
854 h = 1;
855 for(i=0;i<len;i++)
856 h = (h * 263 + ((unsigned char *)str)[i]) & (TOK_HASH_SIZE - 1);
858 pts = &hash_ident[h];
859 while (1) {
860 ts = *pts;
861 if (!ts)
862 break;
863 if (ts->len == len && !memcmp(ts->str, str, len))
864 return ts;
865 pts = &(ts->hash_next);
868 if (tok_ident >= SYM_FIRST_ANOM)
869 error("memory full");
871 /* expand token table if needed */
872 i = tok_ident - TOK_IDENT;
873 if ((i % TOK_ALLOC_INCR) == 0) {
874 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
875 if (!ptable)
876 error("memory full");
877 table_ident = ptable;
880 ts = malloc(sizeof(TokenSym) + len);
881 if (!ts)
882 error("memory full");
883 table_ident[i] = ts;
884 ts->tok = tok_ident++;
885 ts->len = len;
886 ts->hash_next = NULL;
887 memcpy(ts->str, str, len + 1);
888 *pts = ts;
889 return ts;
892 void add_char(char **pp, int c)
894 char *p;
895 p = *pp;
896 if (c == '\'' || c == '\"' || c == '\\') {
897 /* XXX: could be more precise if char or string */
898 *p++ = '\\';
900 if (c >= 32 && c <= 126) {
901 *p++ = c;
902 } else {
903 *p++ = '\\';
904 if (c == '\n') {
905 *p++ = 'n';
906 } else {
907 *p++ = '0' + ((c >> 6) & 7);
908 *p++ = '0' + ((c >> 3) & 7);
909 *p++ = '0' + (c & 7);
912 *pp = p;
915 /* XXX: buffer overflow */
916 char *get_tok_str(int v, CValue *cv)
918 static char buf[STRING_MAX_SIZE + 1];
919 TokenSym *ts;
920 char *p;
921 int i;
923 if (v == TOK_CINT || v == TOK_CUINT) {
924 sprintf(buf, "%u", cv->ui);
925 return buf;
926 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
927 p = buf;
928 *p++ = '\'';
929 add_char(&p, cv->i);
930 *p++ = '\'';
931 *p = '\0';
932 return buf;
933 } else if (v == TOK_STR || v == TOK_LSTR) {
934 ts = cv->ts;
935 p = buf;
936 *p++ = '\"';
937 for(i=0;i<ts->len;i++)
938 add_char(&p, ts->str[i]);
939 *p++ = '\"';
940 *p = '\0';
941 return buf;
942 } else if (v < TOK_IDENT) {
943 p = buf;
944 *p++ = v;
945 *p = '\0';
946 return buf;
947 } else if (v < tok_ident) {
948 return table_ident[v - TOK_IDENT]->str;
949 } else {
950 /* should never happen */
951 return NULL;
955 /* push, without hashing */
956 Sym *sym_push2(Sym **ps, int v, int t, int c)
958 Sym *s;
959 s = malloc(sizeof(Sym));
960 if (!s)
961 error("memory full");
962 s->v = v;
963 s->t = t;
964 s->c = c;
965 s->next = NULL;
966 /* add in stack */
967 s->prev = *ps;
968 *ps = s;
969 return s;
972 /* find a symbol and return its associated structure. 's' is the top
973 of the symbol stack */
974 Sym *sym_find2(Sym *s, int v)
976 while (s) {
977 if (s->v == v)
978 return s;
979 s = s->prev;
981 return NULL;
984 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
986 /* find a symbol and return its associated structure. 'st' is the
987 symbol stack */
988 Sym *sym_find1(SymStack *st, int v)
990 Sym *s;
992 s = st->hash[HASH_SYM(v)];
993 while (s) {
994 if (s->v == v)
995 return s;
996 s = s->hash_next;
998 return NULL;
1001 Sym *sym_push1(SymStack *st, int v, int t, int c)
1003 Sym *s, **ps;
1004 s = sym_push2(&st->top, v, t, c);
1005 /* add in hash table */
1006 if (v) {
1007 ps = &st->hash[HASH_SYM(v)];
1008 s->hash_next = *ps;
1009 *ps = s;
1011 return s;
1014 /* find a symbol in the right symbol space */
1015 Sym *sym_find(int v)
1017 Sym *s;
1018 s = sym_find1(&local_stack, v);
1019 if (!s)
1020 s = sym_find1(&global_stack, v);
1021 return s;
1024 /* push a given symbol on the symbol stack */
1025 Sym *sym_push(int v, int t, int r, int c)
1027 Sym *s;
1028 if (local_stack.top)
1029 s = sym_push1(&local_stack, v, t, c);
1030 else
1031 s = sym_push1(&global_stack, v, t, c);
1032 s->r = r;
1033 return s;
1036 /* pop symbols until top reaches 'b' */
1037 void sym_pop(SymStack *st, Sym *b)
1039 Sym *s, *ss;
1041 s = st->top;
1042 while(s != b) {
1043 ss = s->prev;
1044 /* free hash table entry, except if symbol was freed (only
1045 used for #undef symbols) */
1046 if (s->v)
1047 st->hash[HASH_SYM(s->v)] = s->hash_next;
1048 free(s);
1049 s = ss;
1051 st->top = b;
1054 /* undefined a hashed symbol (used for #undef). Its name is set to
1055 zero */
1056 void sym_undef(SymStack *st, Sym *s)
1058 Sym **ss;
1059 ss = &st->hash[HASH_SYM(s->v)];
1060 while (*ss != NULL) {
1061 if (*ss == s)
1062 break;
1063 ss = &(*ss)->hash_next;
1065 *ss = s->hash_next;
1066 s->v = 0;
1069 /* I/O layer */
1071 BufferedFile *tcc_open(const char *filename)
1073 int fd;
1074 BufferedFile *bf;
1076 fd = open(filename, O_RDONLY);
1077 if (fd < 0)
1078 return NULL;
1079 bf = malloc(sizeof(BufferedFile));
1080 if (!bf) {
1081 close(fd);
1082 return NULL;
1084 bf->fd = fd;
1085 bf->buf_ptr = bf->buffer;
1086 bf->buf_end = bf->buffer;
1087 bf->buffer[0] = CH_EOB; /* put eob symbol */
1088 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1089 bf->line_num = 1;
1090 // printf("opening '%s'\n", filename);
1091 return bf;
1094 void tcc_close(BufferedFile *bf)
1096 total_lines += bf->line_num;
1097 close(bf->fd);
1098 free(bf);
1101 /* read one char. MUST call tcc_fillbuf if CH_EOB is read */
1102 #define TCC_GETC(bf) (*(bf)->buf_ptr++)
1104 /* fill input buffer and return next char */
1105 int tcc_getc_slow(BufferedFile *bf)
1107 int len;
1108 /* only tries to read if really end of buffer */
1109 if (bf->buf_ptr >= bf->buf_end) {
1110 if (bf->fd != -1) {
1111 len = read(bf->fd, bf->buffer, IO_BUF_SIZE);
1112 if (len < 0)
1113 len = 0;
1114 } else {
1115 len = 0;
1117 total_bytes += len;
1118 bf->buf_ptr = bf->buffer;
1119 bf->buf_end = bf->buffer + len;
1120 *bf->buf_end = CH_EOB;
1122 if (bf->buf_ptr < bf->buf_end) {
1123 return *bf->buf_ptr++;
1124 } else {
1125 bf->buf_ptr = bf->buf_end;
1126 return CH_EOF;
1130 /* no need to put that inline */
1131 void handle_eob(void)
1133 for(;;) {
1134 ch1 = tcc_getc_slow(file);
1135 if (ch1 != CH_EOF)
1136 return;
1138 if (include_stack_ptr == include_stack)
1139 return;
1140 /* add end of include file debug info */
1141 if (do_debug) {
1142 put_stabd(N_EINCL, 0, 0);
1144 /* pop include stack */
1145 tcc_close(file);
1146 include_stack_ptr--;
1147 file = *include_stack_ptr;
1151 /* read next char from current input file */
1152 static inline void inp(void)
1154 ch1 = TCC_GETC(file);
1155 /* end of buffer/file handling */
1156 if (ch1 == CH_EOB)
1157 handle_eob();
1158 if (ch1 == '\n')
1159 file->line_num++;
1160 // printf("ch1=%c 0x%x\n", ch1, ch1);
1163 /* input with '\\n' handling */
1164 static inline void minp(void)
1166 redo:
1167 ch = ch1;
1168 inp();
1169 if (ch == '\\' && ch1 == '\n') {
1170 inp();
1171 goto redo;
1173 //printf("ch=%c 0x%x\n", ch, ch);
1177 /* same as minp, but also skip comments */
1178 void cinp(void)
1180 int c;
1182 if (ch1 == '/') {
1183 inp();
1184 if (ch1 == '/') {
1185 /* single line C++ comments */
1186 inp();
1187 while (ch1 != '\n' && ch1 != -1)
1188 inp();
1189 inp();
1190 ch = ' '; /* return space */
1191 } else if (ch1 == '*') {
1192 /* C comments */
1193 inp();
1194 while (ch1 != -1) {
1195 c = ch1;
1196 inp();
1197 if (c == '*' && ch1 == '/') {
1198 inp();
1199 ch = ' '; /* return space */
1200 break;
1203 } else {
1204 ch = '/';
1206 } else {
1207 minp();
1211 void skip_spaces(void)
1213 while (ch == ' ' || ch == '\t')
1214 cinp();
1217 /* skip block of text until #else, #elif or #endif. skip also pairs of
1218 #if/#endif */
1219 void preprocess_skip(void)
1221 int a;
1222 a = 0;
1223 while (1) {
1224 while (ch != '\n') {
1225 if (ch == -1)
1226 expect("#endif");
1227 cinp();
1229 cinp();
1230 skip_spaces();
1231 if (ch == '#') {
1232 cinp();
1233 next_nomacro();
1234 if (a == 0 &&
1235 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1236 break;
1237 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1238 a++;
1239 else if (tok == TOK_ENDIF)
1240 a--;
1245 /* return the number of additionnal 'ints' necessary to store the
1246 token */
1247 static inline int tok_ext_size(int t)
1249 switch(t) {
1250 /* 4 bytes */
1251 case TOK_CINT:
1252 case TOK_CUINT:
1253 case TOK_CCHAR:
1254 case TOK_LCHAR:
1255 case TOK_STR:
1256 case TOK_LSTR:
1257 case TOK_CFLOAT:
1258 return 1;
1259 case TOK_CDOUBLE:
1260 case TOK_CLLONG:
1261 case TOK_CULLONG:
1262 return 2;
1263 case TOK_CLDOUBLE:
1264 return LDOUBLE_SIZE / 4;
1265 default:
1266 return 0;
1270 void tok_add(int **tok_str, int *tok_len, int t)
1272 int len, *str;
1273 len = *tok_len;
1274 str = *tok_str;
1275 if ((len & 63) == 0) {
1276 str = realloc(str, (len + 64) * sizeof(int));
1277 if (!str)
1278 return;
1279 *tok_str = str;
1281 str[len++] = t;
1282 *tok_len = len;
1285 void tok_add2(int **tok_str, int *tok_len, int t, CValue *cv)
1287 int n, i;
1289 tok_add(tok_str, tok_len, t);
1290 n = tok_ext_size(t);
1291 for(i=0;i<n;i++)
1292 tok_add(tok_str, tok_len, cv->tab[i]);
1295 /* get a token from an integer array and increment pointer accordingly */
1296 int tok_get(int **tok_str, CValue *cv)
1298 int *p, t, n, i;
1300 p = *tok_str;
1301 t = *p++;
1302 n = tok_ext_size(t);
1303 for(i=0;i<n;i++)
1304 cv->tab[i] = *p++;
1305 *tok_str = p;
1306 return t;
1309 /* eval an expression for #if/#elif */
1310 int expr_preprocess(void)
1312 int *str, len, c, t;
1314 str = NULL;
1315 len = 0;
1316 while (1) {
1317 skip_spaces();
1318 if (ch == '\n')
1319 break;
1320 next(); /* do macro subst */
1321 if (tok == TOK_DEFINED) {
1322 next_nomacro();
1323 t = tok;
1324 if (t == '(')
1325 next_nomacro();
1326 c = sym_find1(&define_stack, tok) != 0;
1327 if (t == '(')
1328 next_nomacro();
1329 tok = TOK_CINT;
1330 tokc.i = c;
1331 } else if (tok >= TOK_IDENT) {
1332 /* if undefined macro */
1333 tok = TOK_CINT;
1334 tokc.i = 0;
1336 tok_add2(&str, &len, tok, &tokc);
1338 tok_add(&str, &len, -1); /* simulate end of file */
1339 tok_add(&str, &len, 0);
1340 /* now evaluate C constant expression */
1341 macro_ptr = str;
1342 next();
1343 c = expr_const();
1344 macro_ptr = NULL;
1345 free(str);
1346 return c != 0;
1349 #if defined(DEBUG) || defined(PP_DEBUG)
1350 void tok_print(int *str)
1352 int t;
1353 CValue cval;
1355 while (1) {
1356 t = tok_get(&str, &cval);
1357 if (!t)
1358 break;
1359 printf(" %s", get_tok_str(t, &cval));
1361 printf("\n");
1363 #endif
1365 /* parse after #define */
1366 void parse_define(void)
1368 Sym *s, *first, **ps;
1369 int v, t, *str, len;
1371 v = tok;
1372 /* XXX: should check if same macro (ANSI) */
1373 first = NULL;
1374 t = MACRO_OBJ;
1375 /* '(' must be just after macro definition for MACRO_FUNC */
1376 if (ch == '(') {
1377 next_nomacro();
1378 next_nomacro();
1379 ps = &first;
1380 while (tok != ')') {
1381 if (tok == TOK_DOTS)
1382 tok = TOK___VA_ARGS__;
1383 s = sym_push1(&define_stack, tok | SYM_FIELD, 0, 0);
1384 *ps = s;
1385 ps = &s->next;
1386 next_nomacro();
1387 if (tok != ',')
1388 break;
1389 next_nomacro();
1391 t = MACRO_FUNC;
1393 str = NULL;
1394 len = 0;
1395 while (1) {
1396 skip_spaces();
1397 if (ch == '\n' || ch == -1)
1398 break;
1399 next_nomacro();
1400 tok_add2(&str, &len, tok, &tokc);
1402 tok_add(&str, &len, 0);
1403 #ifdef PP_DEBUG
1404 printf("define %s %d: ", get_tok_str(v, NULL), t);
1405 tok_print(str);
1406 #endif
1407 s = sym_push1(&define_stack, v, t, (int)str);
1408 s->next = first;
1411 void preprocess(void)
1413 int size, i, c;
1414 char buf[1024], *q, *p;
1415 char buf1[1024];
1416 BufferedFile *f;
1417 Sym *s;
1419 cinp();
1420 next_nomacro();
1421 redo:
1422 if (tok == TOK_DEFINE) {
1423 next_nomacro();
1424 parse_define();
1425 } else if (tok == TOK_UNDEF) {
1426 next_nomacro();
1427 s = sym_find1(&define_stack, tok);
1428 /* undefine symbol by putting an invalid name */
1429 if (s)
1430 sym_undef(&define_stack, s);
1431 } else if (tok == TOK_INCLUDE) {
1432 skip_spaces();
1433 if (ch == '<') {
1434 c = '>';
1435 goto read_name;
1436 } else if (ch == '\"') {
1437 c = ch;
1438 read_name:
1439 minp();
1440 q = buf;
1441 while (ch != c && ch != '\n' && ch != -1) {
1442 if ((q - buf) < sizeof(buf) - 1)
1443 *q++ = ch;
1444 minp();
1446 *q = '\0';
1447 } else {
1448 next();
1449 if (tok != TOK_STR)
1450 error("#include syntax error");
1451 pstrcpy(buf, sizeof(buf), get_tok_str(tok, &tokc));
1452 c = '\"';
1454 /* eat all spaces and comments after include */
1455 /* XXX: slightly incorrect */
1456 while (ch1 != '\n' && ch1 != -1)
1457 inp();
1459 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
1460 error("memory full");
1461 if (c == '\"') {
1462 /* first search in current dir if "header.h" */
1463 size = 0;
1464 p = strrchr(file->filename, '/');
1465 if (p)
1466 size = p + 1 - file->filename;
1467 if (size > sizeof(buf1) - 1)
1468 size = sizeof(buf1) - 1;
1469 memcpy(buf1, file->filename, size);
1470 buf1[size] = '\0';
1471 pstrcat(buf1, sizeof(buf1), buf);
1472 f = tcc_open(buf1);
1473 if (f)
1474 goto found;
1476 /* now search in standard include path */
1477 for(i=nb_include_paths - 1;i>=0;i--) {
1478 strcpy(buf1, include_paths[i]);
1479 strcat(buf1, "/");
1480 strcat(buf1, buf);
1481 f = tcc_open(buf1);
1482 if (f)
1483 goto found;
1485 error("include file '%s' not found", buf1);
1486 f = NULL;
1487 found:
1488 /* push current file in stack */
1489 /* XXX: fix current line init */
1490 *include_stack_ptr++ = file;
1491 file = f;
1492 /* add include file debug info */
1493 if (do_debug) {
1494 put_stabs(file->filename, N_BINCL, 0, 0, 0);
1496 } else if (tok == TOK_IFNDEF) {
1497 c = 1;
1498 goto do_ifdef;
1499 } else if (tok == TOK_IF) {
1500 c = expr_preprocess();
1501 goto do_if;
1502 } else if (tok == TOK_IFDEF) {
1503 c = 0;
1504 do_ifdef:
1505 next_nomacro();
1506 c = (sym_find1(&define_stack, tok) != 0) ^ c;
1507 do_if:
1508 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
1509 error("memory full");
1510 *ifdef_stack_ptr++ = c;
1511 goto test_skip;
1512 } else if (tok == TOK_ELSE) {
1513 if (ifdef_stack_ptr == ifdef_stack)
1514 error("#else without matching #if");
1515 if (ifdef_stack_ptr[-1] & 2)
1516 error("#else after #else");
1517 c = (ifdef_stack_ptr[-1] ^= 3);
1518 goto test_skip;
1519 } else if (tok == TOK_ELIF) {
1520 if (ifdef_stack_ptr == ifdef_stack)
1521 error("#elif without matching #if");
1522 c = ifdef_stack_ptr[-1];
1523 if (c > 1)
1524 error("#elif after #else");
1525 /* last #if/#elif expression was true: we skip */
1526 if (c == 1)
1527 goto skip;
1528 c = expr_preprocess();
1529 ifdef_stack_ptr[-1] = c;
1530 test_skip:
1531 if (!(c & 1)) {
1532 skip:
1533 preprocess_skip();
1534 goto redo;
1536 } else if (tok == TOK_ENDIF) {
1537 if (ifdef_stack_ptr == ifdef_stack)
1538 error("#endif without matching #if");
1539 ifdef_stack_ptr--;
1540 } else if (tok == TOK_LINE) {
1541 next();
1542 if (tok != TOK_CINT)
1543 error("#line");
1544 file->line_num = tokc.i;
1545 skip_spaces();
1546 if (ch != '\n') {
1547 next();
1548 if (tok != TOK_STR)
1549 error("#line");
1550 pstrcpy(file->filename, sizeof(file->filename),
1551 get_tok_str(tok, &tokc));
1553 } else if (tok == TOK_ERROR) {
1554 error("#error");
1556 /* ignore other preprocess commands or #! for C scripts */
1557 while (ch != '\n' && ch != -1)
1558 cinp();
1561 /* read a number in base b */
1562 int getn(b)
1564 int n, t;
1565 n = 0;
1566 while (1) {
1567 if (ch >= 'a' && ch <= 'f')
1568 t = ch - 'a' + 10;
1569 else if (ch >= 'A' && ch <= 'F')
1570 t = ch - 'A' + 10;
1571 else if (isnum(ch))
1572 t = ch - '0';
1573 else
1574 break;
1575 if (t < 0 || t >= b)
1576 break;
1577 n = n * b + t;
1578 cinp();
1580 return n;
1583 /* read a character for string or char constant and eval escape codes */
1584 int getq()
1586 int c;
1588 c = ch;
1589 minp();
1590 if (c == '\\') {
1591 if (isnum(ch)) {
1592 /* at most three octal digits */
1593 c = ch - '0';
1594 minp();
1595 if (isnum(ch)) {
1596 c = c * 8 + ch - '0';
1597 minp();
1598 if (isnum(ch)) {
1599 c = c * 8 + ch - '0';
1600 minp();
1603 return c;
1604 } else if (ch == 'x') {
1605 minp();
1606 return getn(16);
1607 } else {
1608 if (ch == 'a')
1609 c = '\a';
1610 else if (ch == 'b')
1611 c = '\b';
1612 else if (ch == 'f')
1613 c = '\f';
1614 else if (ch == 'n')
1615 c = '\n';
1616 else if (ch == 'r')
1617 c = '\r';
1618 else if (ch == 't')
1619 c = '\t';
1620 else if (ch == 'v')
1621 c = '\v';
1622 else if (ch == 'e' && gnu_ext)
1623 c = 27;
1624 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
1625 c = ch;
1626 else
1627 error("invalid escaped char");
1628 minp();
1631 return c;
1634 /* we use 64 bit numbers */
1635 #define BN_SIZE 2
1637 /* bn = (bn << shift) | or_val */
1638 void bn_lshift(unsigned int *bn, int shift, int or_val)
1640 int i;
1641 unsigned int v;
1642 for(i=0;i<BN_SIZE;i++) {
1643 v = bn[i];
1644 bn[i] = (v << shift) | or_val;
1645 or_val = v >> (32 - shift);
1649 void bn_zero(unsigned int *bn)
1651 int i;
1652 for(i=0;i<BN_SIZE;i++) {
1653 bn[i] = 0;
1657 void parse_number(void)
1659 int b, t, shift, frac_bits, s, exp_val;
1660 char *q;
1661 unsigned int bn[BN_SIZE];
1662 double d;
1664 /* number */
1665 q = token_buf;
1666 t = ch;
1667 cinp();
1668 *q++ = t;
1669 b = 10;
1670 if (t == '.') {
1671 /* special dot handling */
1672 if (ch >= '0' && ch <= '9') {
1673 goto float_frac_parse;
1674 } else if (ch == '.') {
1675 cinp();
1676 if (ch != '.')
1677 expect("'.'");
1678 cinp();
1679 tok = TOK_DOTS;
1680 } else {
1681 /* dots */
1682 tok = t;
1684 return;
1685 } else if (t == '0') {
1686 if (ch == 'x' || ch == 'X') {
1687 q--;
1688 cinp();
1689 b = 16;
1690 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1691 q--;
1692 cinp();
1693 b = 2;
1696 /* parse all digits. cannot check octal numbers at this stage
1697 because of floating point constants */
1698 while (1) {
1699 if (ch >= 'a' && ch <= 'f')
1700 t = ch - 'a' + 10;
1701 else if (ch >= 'A' && ch <= 'F')
1702 t = ch - 'A' + 10;
1703 else if (isnum(ch))
1704 t = ch - '0';
1705 else
1706 break;
1707 if (t >= b)
1708 break;
1709 if (q >= token_buf + STRING_MAX_SIZE) {
1710 num_too_long:
1711 error("number too long");
1713 *q++ = ch;
1714 cinp();
1716 if (ch == '.' ||
1717 ((ch == 'e' || ch == 'E') && b == 10) ||
1718 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1719 if (b != 10) {
1720 /* NOTE: strtox should support that for hexa numbers, but
1721 non ISOC99 libcs do not support it, so we prefer to do
1722 it by hand */
1723 /* hexadecimal or binary floats */
1724 /* XXX: handle overflows */
1725 *q = '\0';
1726 if (b == 16)
1727 shift = 4;
1728 else
1729 shift = 2;
1730 bn_zero(bn);
1731 q = token_buf;
1732 while (1) {
1733 t = *q++;
1734 if (t == '\0') {
1735 break;
1736 } else if (t >= 'a') {
1737 t = t - 'a' + 10;
1738 } else if (t >= 'A') {
1739 t = t - 'A' + 10;
1740 } else {
1741 t = t - '0';
1743 bn_lshift(bn, shift, t);
1745 frac_bits = 0;
1746 if (ch == '.') {
1747 cinp();
1748 while (1) {
1749 t = ch;
1750 if (t >= 'a' && t <= 'f') {
1751 t = t - 'a' + 10;
1752 } else if (t >= 'A' && t <= 'F') {
1753 t = t - 'A' + 10;
1754 } else if (t >= '0' && t <= '9') {
1755 t = t - '0';
1756 } else {
1757 break;
1759 if (t >= b)
1760 error("invalid digit");
1761 bn_lshift(bn, shift, t);
1762 frac_bits += shift;
1763 cinp();
1766 if (ch != 'p' && ch != 'P')
1767 error("exponent expected");
1768 cinp();
1769 s = 1;
1770 exp_val = 0;
1771 if (ch == '+') {
1772 cinp();
1773 } else if (ch == '-') {
1774 s = -1;
1775 cinp();
1777 if (ch < '0' || ch > '9')
1778 error("exponent digits expected");
1779 while (ch >= '0' && ch <= '9') {
1780 exp_val = exp_val * 10 + ch - '0';
1781 cinp();
1783 exp_val = exp_val * s;
1785 /* now we can generate the number */
1786 /* XXX: should patch directly float number */
1787 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1788 d = ldexp(d, exp_val - frac_bits);
1789 t = toup(ch);
1790 if (t == 'F') {
1791 cinp();
1792 tok = TOK_CFLOAT;
1793 /* float : should handle overflow */
1794 tokc.f = (float)d;
1795 } else if (t == 'L') {
1796 cinp();
1797 tok = TOK_CLDOUBLE;
1798 /* XXX: not large enough */
1799 tokc.ld = (long double)d;
1800 } else {
1801 tok = TOK_CDOUBLE;
1802 tokc.d = d;
1804 } else {
1805 /* decimal floats */
1806 if (ch == '.') {
1807 if (q >= token_buf + STRING_MAX_SIZE)
1808 goto num_too_long;
1809 *q++ = ch;
1810 cinp();
1811 float_frac_parse:
1812 while (ch >= '0' && ch <= '9') {
1813 if (q >= token_buf + STRING_MAX_SIZE)
1814 goto num_too_long;
1815 *q++ = ch;
1816 cinp();
1819 if (ch == 'e' || ch == 'E') {
1820 if (q >= token_buf + STRING_MAX_SIZE)
1821 goto num_too_long;
1822 *q++ = ch;
1823 cinp();
1824 if (ch == '-' || ch == '+') {
1825 if (q >= token_buf + STRING_MAX_SIZE)
1826 goto num_too_long;
1827 *q++ = ch;
1828 cinp();
1830 if (ch < '0' || ch > '9')
1831 error("exponent digits expected");
1832 while (ch >= '0' && ch <= '9') {
1833 if (q >= token_buf + STRING_MAX_SIZE)
1834 goto num_too_long;
1835 *q++ = ch;
1836 cinp();
1839 *q = '\0';
1840 t = toup(ch);
1841 errno = 0;
1842 if (t == 'F') {
1843 cinp();
1844 tok = TOK_CFLOAT;
1845 tokc.f = strtof(token_buf, NULL);
1846 } else if (t == 'L') {
1847 cinp();
1848 tok = TOK_CLDOUBLE;
1849 tokc.ld = strtold(token_buf, NULL);
1850 } else {
1851 tok = TOK_CDOUBLE;
1852 tokc.d = strtod(token_buf, NULL);
1855 } else {
1856 unsigned long long n, n1;
1857 int lcount;
1859 /* integer number */
1860 *q = '\0';
1861 q = token_buf;
1862 if (b == 10 && *q == '0') {
1863 b = 8;
1864 q++;
1866 n = 0;
1867 while(1) {
1868 t = *q++;
1869 /* no need for checks except for base 10 / 8 errors */
1870 if (t == '\0') {
1871 break;
1872 } else if (t >= 'a') {
1873 t = t - 'a' + 10;
1874 } else if (t >= 'A') {
1875 t = t - 'A' + 10;
1876 } else {
1877 t = t - '0';
1878 if (t >= b)
1879 error("invalid digit");
1881 n1 = n;
1882 n = n * b + t;
1883 /* detect overflow */
1884 if (n < n1)
1885 error("integer constant overflow");
1888 /* XXX: not exactly ANSI compliant */
1889 if ((n & 0xffffffff00000000LL) != 0) {
1890 if ((n >> 63) != 0)
1891 tok = TOK_CULLONG;
1892 else
1893 tok = TOK_CLLONG;
1894 } else if (n > 0x7fffffff) {
1895 tok = TOK_CUINT;
1896 } else {
1897 tok = TOK_CINT;
1899 lcount = 0;
1900 for(;;) {
1901 t = toup(ch);
1902 if (t == 'L') {
1903 if (lcount >= 2)
1904 error("three 'l' in integer constant");
1905 lcount++;
1906 if (lcount == 2) {
1907 if (tok == TOK_CINT)
1908 tok = TOK_CLLONG;
1909 else if (tok == TOK_CUINT)
1910 tok = TOK_CULLONG;
1912 cinp();
1913 } else if (t == 'U') {
1914 if (tok == TOK_CINT)
1915 tok = TOK_CUINT;
1916 else if (tok == TOK_CLLONG)
1917 tok = TOK_CULLONG;
1918 cinp();
1919 } else {
1920 break;
1923 if (tok == TOK_CINT || tok == TOK_CUINT)
1924 tokc.ui = n;
1925 else
1926 tokc.ull = n;
1931 /* return next token without macro substitution */
1932 void next_nomacro1(void)
1934 int b;
1935 char *q;
1936 TokenSym *ts;
1938 /* skip spaces */
1939 while(1) {
1940 while (ch == '\n') {
1941 cinp();
1942 while (ch == ' ' || ch == '\t')
1943 cinp();
1944 if (ch == '#') {
1945 /* preprocessor command if # at start of line after
1946 spaces */
1947 preprocess();
1950 if (ch != ' ' && ch != '\t' && ch != '\f')
1951 break;
1952 cinp();
1954 if (isid(ch)) {
1955 q = token_buf;
1956 *q++ = ch;
1957 cinp();
1958 if (q[-1] == 'L') {
1959 if (ch == '\'') {
1960 tok = TOK_LCHAR;
1961 goto char_const;
1963 if (ch == '\"') {
1964 tok = TOK_LSTR;
1965 goto str_const;
1968 while (isid(ch) || isnum(ch)) {
1969 if (q >= token_buf + STRING_MAX_SIZE)
1970 error("ident too long");
1971 *q++ = ch;
1972 cinp();
1974 *q = '\0';
1975 ts = tok_alloc(token_buf, q - token_buf);
1976 tok = ts->tok;
1977 } else if (isnum(ch) || ch == '.') {
1978 parse_number();
1979 } else if (ch == '\'') {
1980 tok = TOK_CCHAR;
1981 char_const:
1982 minp();
1983 tokc.i = getq();
1984 if (ch != '\'')
1985 expect("\'");
1986 minp();
1987 } else if (ch == '\"') {
1988 tok = TOK_STR;
1989 str_const:
1990 minp();
1991 q = token_buf;
1992 while (ch != '\"') {
1993 b = getq();
1994 if (ch == -1)
1995 error("unterminated string");
1996 if (q >= token_buf + STRING_MAX_SIZE)
1997 error("string too long");
1998 *q++ = b;
2000 *q = '\0';
2001 tokc.ts = tok_alloc(token_buf, q - token_buf);
2002 minp();
2003 } else {
2004 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
2005 /* two chars */
2006 tok = ch;
2007 cinp();
2008 while (*q) {
2009 if (*q == tok && q[1] == ch) {
2010 cinp();
2011 tok = q[2] & 0xff;
2012 /* three chars tests */
2013 if (tok == TOK_SHL || tok == TOK_SAR) {
2014 if (ch == '=') {
2015 tok = tok | 0x80;
2016 cinp();
2018 } else if (tok == TOK_DOTS) {
2019 if (ch != '.')
2020 error("parse error");
2021 cinp();
2023 return;
2025 q = q + 3;
2027 /* single char substitutions */
2028 if (tok == '<')
2029 tok = TOK_LT;
2030 else if (tok == '>')
2031 tok = TOK_GT;
2035 /* return next token without macro substitution. Can read input from
2036 macro_ptr buffer */
2037 void next_nomacro()
2039 if (macro_ptr) {
2040 tok = *macro_ptr;
2041 if (tok)
2042 tok = tok_get(&macro_ptr, &tokc);
2043 } else {
2044 next_nomacro1();
2048 /* substitute args in macro_str and return allocated string */
2049 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
2051 int *st, last_tok, t, notfirst, *str, len;
2052 Sym *s;
2053 TokenSym *ts;
2054 CValue cval;
2056 str = NULL;
2057 len = 0;
2058 last_tok = 0;
2059 while(1) {
2060 t = tok_get(&macro_str, &cval);
2061 if (!t)
2062 break;
2063 if (t == '#') {
2064 /* stringize */
2065 t = tok_get(&macro_str, &cval);
2066 if (!t)
2067 break;
2068 s = sym_find2(args, t);
2069 if (s) {
2070 token_buf[0] = '\0';
2071 st = (int *)s->c;
2072 notfirst = 0;
2073 while (*st) {
2074 if (notfirst)
2075 pstrcat(token_buf, sizeof(token_buf), " ");
2076 t = tok_get(&st, &cval);
2077 pstrcat(token_buf, sizeof(token_buf), get_tok_str(t, &cval));
2078 notfirst = 1;
2080 #ifdef PP_DEBUG
2081 printf("stringize: %s\n", token_buf);
2082 #endif
2083 /* add string */
2084 ts = tok_alloc(token_buf, 0);
2085 cval.ts = ts;
2086 tok_add2(&str, &len, TOK_STR, &cval);
2087 } else {
2088 tok_add2(&str, &len, t, &cval);
2090 } else if (t >= TOK_IDENT) {
2091 s = sym_find2(args, t);
2092 if (s) {
2093 st = (int *)s->c;
2094 /* if '##' is present before or after , no arg substitution */
2095 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
2096 while (*st)
2097 tok_add(&str, &len, *st++);
2098 } else {
2099 macro_subst(&str, &len, nested_list, st);
2101 } else {
2102 tok_add(&str, &len, t);
2104 } else {
2105 tok_add2(&str, &len, t, &cval);
2107 last_tok = t;
2109 tok_add(&str, &len, 0);
2110 return str;
2113 /* handle the '##' operator */
2114 int *macro_twosharps(int *macro_str)
2116 TokenSym *ts;
2117 int *macro_str1, macro_str1_len, *macro_ptr1;
2118 int t;
2119 char *p;
2120 CValue cval;
2122 macro_str1 = NULL;
2123 macro_str1_len = 0;
2124 tok = 0;
2125 while (1) {
2126 next_nomacro();
2127 if (tok == 0)
2128 break;
2129 while (*macro_ptr == TOK_TWOSHARPS) {
2130 macro_ptr++;
2131 macro_ptr1 = macro_ptr;
2132 t = *macro_ptr;
2133 if (t) {
2134 t = tok_get(&macro_ptr, &cval);
2135 /* XXX: we handle only most common cases:
2136 ident + ident or ident + number */
2137 if (tok >= TOK_IDENT &&
2138 (t >= TOK_IDENT || t == TOK_CINT)) {
2139 p = get_tok_str(tok, &tokc);
2140 pstrcpy(token_buf, sizeof(token_buf), p);
2141 p = get_tok_str(t, &cval);
2142 pstrcat(token_buf, sizeof(token_buf), p);
2143 ts = tok_alloc(token_buf, 0);
2144 tok = ts->tok; /* modify current token */
2145 } else {
2146 /* cannot merge tokens: skip '##' */
2147 macro_ptr = macro_ptr1;
2148 break;
2152 tok_add2(&macro_str1, &macro_str1_len, tok, &tokc);
2154 tok_add(&macro_str1, &macro_str1_len, 0);
2155 return macro_str1;
2160 /* do macro substitution of macro_str and add result to
2161 (tok_str,tok_len). If macro_str is NULL, then input stream token is
2162 substituted. 'nested_list' is the list of all macros we got inside
2163 to avoid recursing. */
2164 void macro_subst(int **tok_str, int *tok_len,
2165 Sym **nested_list, int *macro_str)
2167 Sym *s, *args, *sa, *sa1;
2168 int *str, parlevel, len, *mstr, t, *saved_macro_ptr;
2169 int mstr_allocated, *macro_str1;
2170 CValue cval;
2172 saved_macro_ptr = macro_ptr;
2173 macro_ptr = macro_str;
2174 macro_str1 = NULL;
2175 if (macro_str) {
2176 /* first scan for '##' operator handling */
2177 macro_str1 = macro_twosharps(macro_str);
2178 macro_ptr = macro_str1;
2181 while (1) {
2182 next_nomacro();
2183 if (tok == 0)
2184 break;
2185 /* special macros */
2186 if (tok == TOK___LINE__) {
2187 cval.i = file->line_num;
2188 tok_add2(tok_str, tok_len, TOK_CINT, &cval);
2189 } else if (tok == TOK___FILE__) {
2190 cval.ts = tok_alloc(file->filename, 0);
2191 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2192 } else if (tok == TOK___DATE__) {
2193 cval.ts = tok_alloc("Jan 1 1970", 0);
2194 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2195 } else if (tok == TOK___TIME__) {
2196 cval.ts = tok_alloc("00:00:00", 0);
2197 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2198 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
2199 /* if symbol is a macro, prepare substitution */
2200 /* if nested substitution, do nothing */
2201 if (sym_find2(*nested_list, tok))
2202 goto no_subst;
2203 mstr = (int *)s->c;
2204 mstr_allocated = 0;
2205 if (s->t == MACRO_FUNC) {
2206 /* NOTE: we do not use next_nomacro to avoid eating the
2207 next token. XXX: find better solution */
2208 if (macro_ptr) {
2209 t = *macro_ptr;
2210 } else {
2211 while (ch == ' ' || ch == '\t' || ch == '\n')
2212 cinp();
2213 t = ch;
2215 if (t != '(') /* no macro subst */
2216 goto no_subst;
2218 /* argument macro */
2219 next_nomacro();
2220 next_nomacro();
2221 args = NULL;
2222 sa = s->next;
2223 /* NOTE: empty args are allowed, except if no args */
2224 for(;;) {
2225 /* handle '()' case */
2226 if (!args && tok == ')')
2227 break;
2228 if (!sa)
2229 error("macro '%s' used with too many args",
2230 get_tok_str(s->v, 0));
2231 len = 0;
2232 str = NULL;
2233 parlevel = 0;
2234 while ((parlevel > 0 ||
2235 (tok != ')' &&
2236 (tok != ',' ||
2237 sa->v == (TOK___VA_ARGS__ | SYM_FIELD)))) &&
2238 tok != -1) {
2239 if (tok == '(')
2240 parlevel++;
2241 else if (tok == ')')
2242 parlevel--;
2243 tok_add2(&str, &len, tok, &tokc);
2244 next_nomacro();
2246 tok_add(&str, &len, 0);
2247 sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
2248 if (tok == ')')
2249 break;
2250 if (tok != ',')
2251 expect(",");
2252 next_nomacro();
2253 sa = sa->next;
2255 if (sa->next)
2256 error("macro '%s' used with too few args",
2257 get_tok_str(s->v, 0));
2259 /* now subst each arg */
2260 mstr = macro_arg_subst(nested_list, mstr, args);
2261 /* free memory */
2262 sa = args;
2263 while (sa) {
2264 sa1 = sa->prev;
2265 free((int *)sa->c);
2266 free(sa);
2267 sa = sa1;
2269 mstr_allocated = 1;
2271 sym_push2(nested_list, s->v, 0, 0);
2272 macro_subst(tok_str, tok_len, nested_list, mstr);
2273 /* pop nested defined symbol */
2274 sa1 = *nested_list;
2275 *nested_list = sa1->prev;
2276 free(sa1);
2277 if (mstr_allocated)
2278 free(mstr);
2279 } else {
2280 no_subst:
2281 /* no need to add if reading input stream */
2282 if (!macro_str)
2283 return;
2284 tok_add2(tok_str, tok_len, tok, &tokc);
2286 /* only replace one macro while parsing input stream */
2287 if (!macro_str)
2288 return;
2290 macro_ptr = saved_macro_ptr;
2291 if (macro_str1)
2292 free(macro_str1);
2295 /* return next token with macro substitution */
2296 void next(void)
2298 int len, *ptr;
2299 Sym *nested_list;
2301 /* special 'ungettok' case for label parsing */
2302 if (tok1) {
2303 tok = tok1;
2304 tokc = tok1c;
2305 tok1 = 0;
2306 } else {
2307 redo:
2308 if (!macro_ptr) {
2309 /* if not reading from macro substituted string, then try to substitute */
2310 len = 0;
2311 ptr = NULL;
2312 nested_list = NULL;
2313 macro_subst(&ptr, &len, &nested_list, NULL);
2314 if (ptr) {
2315 tok_add(&ptr, &len, 0);
2316 macro_ptr = ptr;
2317 macro_ptr_allocated = ptr;
2318 goto redo;
2320 if (tok == 0)
2321 goto redo;
2322 } else {
2323 next_nomacro();
2324 if (tok == 0) {
2325 /* end of macro string: free it */
2326 free(macro_ptr_allocated);
2327 macro_ptr = NULL;
2328 goto redo;
2332 #if defined(DEBUG)
2333 printf("token = %s\n", get_tok_str(tok, tokc));
2334 #endif
2337 void swap(int *p, int *q)
2339 int t;
2340 t = *p;
2341 *p = *q;
2342 *q = t;
2345 void vsetc(int t, int r, CValue *vc)
2347 if (vtop >= vstack + VSTACK_SIZE)
2348 error("memory full");
2349 /* cannot let cpu flags if other instruction are generated */
2350 /* XXX: VT_JMP test too ? */
2351 if ((vtop->r & VT_VALMASK) == VT_CMP)
2352 gv(RC_INT);
2353 vtop++;
2354 vtop->t = t;
2355 vtop->r = r;
2356 vtop->r2 = VT_CONST;
2357 vtop->c = *vc;
2360 /* push integer constant */
2361 void vpushi(int v)
2363 CValue cval;
2364 cval.i = v;
2365 vsetc(VT_INT, VT_CONST, &cval);
2368 void vset(int t, int r, int v)
2370 CValue cval;
2372 cval.i = v;
2373 vsetc(t, r, &cval);
2376 void vswap(void)
2378 SValue tmp;
2380 tmp = vtop[0];
2381 vtop[0] = vtop[-1];
2382 vtop[-1] = tmp;
2385 void vpushv(SValue *v)
2387 if (vtop >= vstack + VSTACK_SIZE)
2388 error("memory full");
2389 vtop++;
2390 *vtop = *v;
2393 void vdup(void)
2395 vpushv(vtop);
2398 /* save r to the memory stack, and mark it as being free */
2399 void save_reg(int r)
2401 int l, i, saved, t, size, align;
2402 SValue *p, sv;
2404 /* modify all stack values */
2405 saved = 0;
2406 l = 0;
2407 for(p=vstack;p<=vtop;p++) {
2408 i = p->r & VT_VALMASK;
2409 if ((p->r & VT_VALMASK) == r ||
2410 (p->r2 & VT_VALMASK) == r) {
2411 /* must save value on stack if not already done */
2412 if (!saved) {
2413 /* store register in the stack */
2414 t = p->t;
2415 if ((p->r & VT_LVAL) ||
2416 (!is_float(t) && (t & VT_BTYPE) != VT_LLONG))
2417 t = VT_INT;
2418 size = type_size(t, &align);
2419 loc = (loc - size) & -align;
2420 sv.t = t;
2421 sv.r = VT_LOCAL | VT_LVAL;
2422 sv.c.ul = loc;
2423 store(r, &sv);
2424 #ifdef TCC_TARGET_I386
2425 /* x86 specific: need to pop fp register ST0 if saved */
2426 if (r == REG_ST0) {
2427 o(0xd9dd); /* fstp %st(1) */
2429 #endif
2430 /* special long long case */
2431 if ((p->t & VT_BTYPE) == VT_LLONG) {
2432 sv.c.ul += 4;
2433 store(p->r2, &sv);
2435 l = loc;
2436 saved = 1;
2438 /* mark that stack entry as being saved on the stack */
2439 if (p->r & VT_LVAL)
2440 t = VT_LLOCAL;
2441 else
2442 t = VT_LOCAL;
2443 p->r = VT_LVAL | t;
2444 p->r2 = VT_CONST;
2445 p->c.ul = l;
2450 /* find a free register of class 'rc'. If none, save one register */
2451 int get_reg(int rc)
2453 int r;
2454 SValue *p;
2456 /* find a free register */
2457 for(r=0;r<NB_REGS;r++) {
2458 if (reg_classes[r] & rc) {
2459 for(p=vstack;p<=vtop;p++) {
2460 if ((p->r & VT_VALMASK) == r ||
2461 (p->r2 & VT_VALMASK) == r)
2462 goto notfound;
2464 return r;
2466 notfound: ;
2469 /* no register left : free the first one on the stack (VERY
2470 IMPORTANT to start from the bottom to ensure that we don't
2471 spill registers used in gen_opi()) */
2472 for(p=vstack;p<=vtop;p++) {
2473 r = p->r & VT_VALMASK;
2474 if (r < VT_CONST && (reg_classes[r] & rc)) {
2475 save_reg(r);
2476 break;
2479 return r;
2482 void save_regs(void)
2484 int r;
2485 SValue *p;
2487 for(p=vstack;p<=vtop;p++) {
2488 r = p->r & VT_VALMASK;
2489 if (r < VT_CONST) {
2490 save_reg(r);
2495 /* move register 's' to 'r', and flush previous value of r to memory
2496 if needed */
2497 void move_reg(int r, int s)
2499 SValue sv;
2501 if (r != s) {
2502 save_reg(r);
2503 sv.t = VT_INT;
2504 sv.r = s;
2505 sv.c.ul = 0;
2506 load(r, &sv);
2510 /* get address of vtop (vtop MUST BE an lvalue) */
2511 void gaddrof(void)
2513 vtop->r &= ~VT_LVAL;
2514 /* tricky: if saved lvalue, then we can go back to lvalue */
2515 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
2516 vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
2519 /* generate lvalue bound code */
2520 void gbound(void)
2522 vtop->r &= ~VT_MUSTBOUND;
2523 /* if lvalue, then use checking code before dereferencing */
2524 if (vtop->r & VT_LVAL) {
2525 gaddrof();
2526 vpushi(0);
2527 gen_bounded_ptr_add1();
2528 gen_bounded_ptr_add2(1);
2529 vtop->r |= VT_LVAL;
2533 /* store vtop a register belonging to class 'rc'. lvalues are
2534 converted to values. Cannot be used if cannot be converted to
2535 register value (such as structures). */
2536 int gv(int rc)
2538 int r, r2, rc2, bit_pos, bit_size, size, align, i, data_offset;
2539 unsigned long long ll;
2541 /* NOTE: get_reg can modify vstack[] */
2542 if (vtop->t & VT_BITFIELD) {
2543 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
2544 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2545 /* remove bit field info to avoid loops */
2546 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2547 /* generate shifts */
2548 vpushi(32 - (bit_pos + bit_size));
2549 gen_op(TOK_SHL);
2550 vpushi(32 - bit_size);
2551 /* NOTE: transformed to SHR if unsigned */
2552 gen_op(TOK_SAR);
2553 r = gv(rc);
2554 } else {
2555 if (is_float(vtop->t) &&
2556 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2557 /* CPUs usually cannot use float constants, so we store them
2558 generically in data segment */
2559 size = type_size(vtop->t, &align);
2560 data_offset = (int)data_section->data_ptr;
2561 data_offset = (data_offset + align - 1) & -align;
2562 /* XXX: not portable yet */
2563 size = size >> 2;
2564 for(i=0;i<size;i++)
2565 ((int *)data_offset)[i] = vtop->c.tab[i];
2566 vtop->r |= VT_LVAL;
2567 vtop->c.ul = data_offset;
2568 data_offset += size << 2;
2569 data_section->data_ptr = (unsigned char *)data_offset;
2571 if (vtop->r & VT_MUSTBOUND)
2572 gbound();
2574 r = vtop->r & VT_VALMASK;
2575 /* need to reload if:
2576 - constant
2577 - lvalue (need to dereference pointer)
2578 - already a register, but not in the right class */
2579 if (r >= VT_CONST ||
2580 (vtop->r & VT_LVAL) ||
2581 !(reg_classes[r] & rc) ||
2582 ((vtop->t & VT_BTYPE) == VT_LLONG &&
2583 !(reg_classes[vtop->r2] & rc))) {
2584 r = get_reg(rc);
2585 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
2586 /* two register type load : expand to two words
2587 temporarily */
2588 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2589 /* load constant */
2590 ll = vtop->c.ull;
2591 vtop->c.ui = ll; /* first word */
2592 load(r, vtop);
2593 vtop->r = r; /* save register value */
2594 vpushi(ll >> 32); /* second word */
2595 } else if (r >= VT_CONST ||
2596 (vtop->r & VT_LVAL)) {
2597 /* load from memory */
2598 load(r, vtop);
2599 vdup();
2600 vtop[-1].r = r; /* save register value */
2601 /* increment pointer to get second word */
2602 vtop->t = VT_INT;
2603 gaddrof();
2604 vpushi(4);
2605 gen_op('+');
2606 vtop->r |= VT_LVAL;
2607 } else {
2608 /* move registers */
2609 load(r, vtop);
2610 vdup();
2611 vtop[-1].r = r; /* save register value */
2612 vtop->r = vtop[-1].r2;
2614 /* allocate second register */
2615 rc2 = RC_INT;
2616 if (rc == RC_IRET)
2617 rc2 = RC_LRET;
2618 r2 = get_reg(rc2);
2619 load(r2, vtop);
2620 vpop();
2621 /* write second register */
2622 vtop->r2 = r2;
2623 } else {
2624 /* one register type load */
2625 load(r, vtop);
2628 vtop->r = r;
2630 return r;
2633 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
2634 void gv2(int rc1, int rc2)
2636 /* generate more generic register first */
2637 if (rc1 <= rc2) {
2638 vswap();
2639 gv(rc1);
2640 vswap();
2641 gv(rc2);
2642 /* test if reload is needed for first register */
2643 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
2644 vswap();
2645 gv(rc1);
2646 vswap();
2648 } else {
2649 gv(rc2);
2650 vswap();
2651 gv(rc1);
2652 vswap();
2653 /* test if reload is needed for first register */
2654 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
2655 gv(rc2);
2660 /* expand long long on stack in two int registers */
2661 void lexpand(void)
2663 int u;
2665 u = vtop->t & VT_UNSIGNED;
2666 gv(RC_INT);
2667 vdup();
2668 vtop[0].r = vtop[-1].r2;
2669 vtop[0].r2 = VT_CONST;
2670 vtop[-1].r2 = VT_CONST;
2671 vtop[0].t = VT_INT | u;
2672 vtop[-1].t = VT_INT | u;
2675 /* build a long long from two ints */
2676 void lbuild(int t)
2678 gv2(RC_INT, RC_INT);
2679 vtop[-1].r2 = vtop[0].r;
2680 vtop[-1].t = t;
2681 vpop();
2684 /* rotate n first stack elements to the bottom */
2685 void vrotb(int n)
2687 int i;
2688 SValue tmp;
2690 tmp = vtop[-n + 1];
2691 for(i=-n+1;i!=0;i++)
2692 vtop[i] = vtop[i+1];
2693 vtop[0] = tmp;
2696 /* pop stack value */
2697 void vpop(void)
2699 #ifdef TCC_TARGET_I386
2700 /* for x86, we need to pop the FP stack */
2701 if ((vtop->r & VT_VALMASK) == REG_ST0) {
2702 o(0xd9dd); /* fstp %st(1) */
2704 #endif
2705 vtop--;
2708 /* convert stack entry to register and duplicate its value in another
2709 register */
2710 void gv_dup(void)
2712 int rc, t, r, r1;
2713 SValue sv;
2715 t = vtop->t;
2716 if ((t & VT_BTYPE) == VT_LLONG) {
2717 lexpand();
2718 gv_dup();
2719 vswap();
2720 vrotb(3);
2721 gv_dup();
2722 vrotb(4);
2723 /* stack: H L L1 H1 */
2724 lbuild(t);
2725 vrotb(3);
2726 vrotb(3);
2727 vswap();
2728 lbuild(t);
2729 vswap();
2730 } else {
2731 /* duplicate value */
2732 rc = RC_INT;
2733 sv.t = VT_INT;
2734 if (is_float(t)) {
2735 rc = RC_FLOAT;
2736 sv.t = t;
2738 r = gv(rc);
2739 r1 = get_reg(rc);
2740 sv.r = r;
2741 sv.c.ul = 0;
2742 load(r1, &sv); /* move r to r1 */
2743 vdup();
2744 /* duplicates value */
2745 vtop->r = r1;
2749 /* generate CPU independent (unsigned) long long operations */
2750 void gen_opl(int op)
2752 int t, a, b, op1, c, i;
2753 void *func;
2754 GFuncContext gf;
2755 SValue tmp;
2757 switch(op) {
2758 case '/':
2759 case TOK_PDIV:
2760 func = __divll;
2761 goto gen_func;
2762 case TOK_UDIV:
2763 func = __divull;
2764 goto gen_func;
2765 case '%':
2766 func = __modll;
2767 goto gen_func;
2768 case TOK_UMOD:
2769 func = __modull;
2770 gen_func:
2771 /* call generic long long function */
2772 gfunc_start(&gf, FUNC_CDECL);
2773 gfunc_param(&gf);
2774 gfunc_param(&gf);
2775 vpushi((int)func);
2776 gfunc_call(&gf);
2777 vpushi(0);
2778 vtop->r = REG_IRET;
2779 vtop->r2 = REG_LRET;
2780 break;
2781 case '^':
2782 case '&':
2783 case '|':
2784 case '*':
2785 case '+':
2786 case '-':
2787 t = vtop->t;
2788 vswap();
2789 lexpand();
2790 vrotb(3);
2791 lexpand();
2792 /* stack: L1 H1 L2 H2 */
2793 tmp = vtop[0];
2794 vtop[0] = vtop[-3];
2795 vtop[-3] = tmp;
2796 tmp = vtop[-2];
2797 vtop[-2] = vtop[-3];
2798 vtop[-3] = tmp;
2799 vswap();
2800 /* stack: H1 H2 L1 L2 */
2801 if (op == '*') {
2802 vpushv(vtop - 1);
2803 vpushv(vtop - 1);
2804 gen_op(TOK_UMULL);
2805 lexpand();
2806 /* stack: H1 H2 L1 L2 ML MH */
2807 for(i=0;i<4;i++)
2808 vrotb(6);
2809 /* stack: ML MH H1 H2 L1 L2 */
2810 tmp = vtop[0];
2811 vtop[0] = vtop[-2];
2812 vtop[-2] = tmp;
2813 /* stack: ML MH H1 L2 H2 L1 */
2814 gen_op('*');
2815 vrotb(3);
2816 vrotb(3);
2817 gen_op('*');
2818 /* stack: ML MH M1 M2 */
2819 gen_op('+');
2820 gen_op('+');
2821 } else if (op == '+' || op == '-') {
2822 /* XXX: add non carry method too (for MIPS or alpha) */
2823 if (op == '+')
2824 op1 = TOK_ADDC1;
2825 else
2826 op1 = TOK_SUBC1;
2827 gen_op(op1);
2828 /* stack: H1 H2 (L1 op L2) */
2829 vrotb(3);
2830 vrotb(3);
2831 gen_op(op1 + 1); /* TOK_xxxC2 */
2832 } else {
2833 gen_op(op);
2834 /* stack: H1 H2 (L1 op L2) */
2835 vrotb(3);
2836 vrotb(3);
2837 /* stack: (L1 op L2) H1 H2 */
2838 gen_op(op);
2839 /* stack: (L1 op L2) (H1 op H2) */
2841 /* stack: L H */
2842 lbuild(t);
2843 break;
2844 case TOK_SAR:
2845 case TOK_SHR:
2846 case TOK_SHL:
2847 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
2848 t = vtop[-1].t;
2849 vswap();
2850 lexpand();
2851 vrotb(3);
2852 /* stack: L H shift */
2853 c = (int)vtop->c.i;
2854 /* constant: simpler */
2855 /* NOTE: all comments are for SHL. the other cases are
2856 done by swaping words */
2857 vpop();
2858 if (op != TOK_SHL)
2859 vswap();
2860 if (c >= 32) {
2861 /* stack: L H */
2862 vpop();
2863 if (c > 32) {
2864 vpushi(c - 32);
2865 gen_op(op);
2867 if (op != TOK_SAR) {
2868 vpushi(0);
2869 } else {
2870 gv_dup();
2871 vpushi(31);
2872 gen_op(TOK_SAR);
2874 vswap();
2875 } else {
2876 vswap();
2877 gv_dup();
2878 /* stack: H L L */
2879 vpushi(c);
2880 gen_op(op);
2881 vswap();
2882 vpushi(32 - c);
2883 if (op == TOK_SHL)
2884 gen_op(TOK_SHR);
2885 else
2886 gen_op(TOK_SHL);
2887 vrotb(3);
2888 /* stack: L L H */
2889 vpushi(c);
2890 gen_op(op);
2891 gen_op('|');
2893 if (op != TOK_SHL)
2894 vswap();
2895 lbuild(t);
2896 } else {
2897 /* XXX: should provide a faster fallback on x86 ? */
2898 switch(op) {
2899 case TOK_SAR:
2900 func = __sardi3;
2901 goto gen_func;
2902 case TOK_SHR:
2903 func = __shrdi3;
2904 goto gen_func;
2905 case TOK_SHL:
2906 func = __shldi3;
2907 goto gen_func;
2910 break;
2911 default:
2912 /* compare operations */
2913 t = vtop->t;
2914 vswap();
2915 lexpand();
2916 vrotb(3);
2917 lexpand();
2918 /* stack: L1 H1 L2 H2 */
2919 tmp = vtop[-1];
2920 vtop[-1] = vtop[-2];
2921 vtop[-2] = tmp;
2922 /* stack: L1 L2 H1 H2 */
2923 /* compare high */
2924 op1 = op;
2925 /* when values are equal, we need to compare low words. since
2926 the jump is inverted, we invert the test too. */
2927 if (op1 == TOK_LT)
2928 op1 = TOK_LE;
2929 else if (op1 == TOK_GT)
2930 op1 = TOK_GE;
2931 else if (op1 == TOK_ULT)
2932 op1 = TOK_ULE;
2933 else if (op1 == TOK_UGT)
2934 op1 = TOK_UGE;
2935 a = 0;
2936 b = 0;
2937 gen_op(op1);
2938 if (op1 != TOK_NE) {
2939 a = gtst(1, 0);
2941 if (op != TOK_EQ) {
2942 /* generate non equal test */
2943 /* XXX: NOT PORTABLE yet */
2944 if (a == 0) {
2945 b = gtst(0, 0);
2946 } else {
2947 #ifdef TCC_TARGET_I386
2948 b = psym(0x850f, 0);
2949 #else
2950 error("not implemented");
2951 #endif
2954 /* compare low */
2955 gen_op(op);
2956 a = gtst(1, a);
2957 gsym(b);
2958 vset(VT_INT, VT_JMPI, a);
2959 break;
2963 /* handle constant optimizations and various machine independant opt */
2964 void gen_opc(int op)
2966 int fc, c1, c2, n;
2967 SValue *v1, *v2;
2969 v1 = vtop - 1;
2970 v2 = vtop;
2971 /* currently, we cannot do computations with forward symbols */
2972 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2973 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
2974 if (c1 && c2) {
2975 fc = v2->c.i;
2976 switch(op) {
2977 case '+': v1->c.i += fc; break;
2978 case '-': v1->c.i -= fc; break;
2979 case '&': v1->c.i &= fc; break;
2980 case '^': v1->c.i ^= fc; break;
2981 case '|': v1->c.i |= fc; break;
2982 case '*': v1->c.i *= fc; break;
2984 case TOK_PDIV:
2985 case '/':
2986 case '%':
2987 case TOK_UDIV:
2988 case TOK_UMOD:
2989 /* if division by zero, generate explicit division */
2990 if (fc == 0) {
2991 if (const_wanted)
2992 error("division by zero in constant");
2993 goto general_case;
2995 switch(op) {
2996 default: v1->c.i /= fc; break;
2997 case '%': v1->c.i %= fc; break;
2998 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
2999 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
3001 break;
3002 case TOK_SHL: v1->c.i <<= fc; break;
3003 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
3004 case TOK_SAR: v1->c.i >>= fc; break;
3005 /* tests */
3006 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
3007 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
3008 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
3009 case TOK_NE: v1->c.i = v1->c.i != fc; break;
3010 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
3011 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
3012 case TOK_LT: v1->c.i = v1->c.i < fc; break;
3013 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
3014 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
3015 case TOK_GT: v1->c.i = v1->c.i > fc; break;
3016 /* logical */
3017 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
3018 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
3019 default:
3020 goto general_case;
3022 vtop--;
3023 } else {
3024 /* if commutative ops, put c2 as constant */
3025 if (c1 && (op == '+' || op == '&' || op == '^' ||
3026 op == '|' || op == '*')) {
3027 vswap();
3028 swap(&c1, &c2);
3030 fc = vtop->c.i;
3031 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
3032 op == TOK_PDIV) &&
3033 fc == 1) ||
3034 ((op == '+' || op == '-' || op == '|' || op == '^' ||
3035 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
3036 fc == 0) ||
3037 (op == '&' &&
3038 fc == -1))) {
3039 /* nothing to do */
3040 vtop--;
3041 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
3042 /* try to use shifts instead of muls or divs */
3043 if (fc > 0 && (fc & (fc - 1)) == 0) {
3044 n = -1;
3045 while (fc) {
3046 fc >>= 1;
3047 n++;
3049 vtop->c.i = n;
3050 if (op == '*')
3051 op = TOK_SHL;
3052 else if (op == TOK_PDIV)
3053 op = TOK_SAR;
3054 else
3055 op = TOK_SHR;
3057 goto general_case;
3058 } else {
3059 general_case:
3060 /* call low level op generator */
3061 gen_opi(op);
3066 int pointed_size(int t)
3068 return type_size(pointed_type(t), &t);
3071 #if 0
3072 void check_pointer_types(SValue *p1, SValue *p2)
3074 char buf1[256], buf2[256];
3075 int t1, t2;
3076 t1 = p1->t;
3077 t2 = p2->t;
3078 if (!is_compatible_types(t1, t2)) {
3079 type_to_str(buf1, sizeof(buf1), t1, NULL);
3080 type_to_str(buf2, sizeof(buf2), t2, NULL);
3081 error("incompatible pointers '%s' and '%s'", buf1, buf2);
3084 #endif
3086 /* generic gen_op: handles types problems */
3087 void gen_op(int op)
3089 int u, t1, t2, bt1, bt2, t;
3091 t1 = vtop[-1].t;
3092 t2 = vtop[0].t;
3093 bt1 = t1 & VT_BTYPE;
3094 bt2 = t2 & VT_BTYPE;
3096 if (bt1 == VT_PTR || bt2 == VT_PTR) {
3097 /* at least one operand is a pointer */
3098 /* relationnal op: must be both pointers */
3099 if (op >= TOK_ULT && op <= TOK_GT) {
3100 // check_pointer_types(vtop, vtop - 1);
3101 /* pointers are handled are unsigned */
3102 t = VT_INT | VT_UNSIGNED;
3103 goto std_op;
3105 /* if both pointers, then it must be the '-' op */
3106 if ((t1 & VT_BTYPE) == VT_PTR &&
3107 (t2 & VT_BTYPE) == VT_PTR) {
3108 if (op != '-')
3109 error("cannot use pointers here");
3110 // check_pointer_types(vtop - 1, vtop);
3111 /* XXX: check that types are compatible */
3112 u = pointed_size(t1);
3113 gen_opc(op);
3114 /* set to integer type */
3115 vtop->t = VT_INT;
3116 vpushi(u);
3117 gen_op(TOK_PDIV);
3118 } else {
3119 /* exactly one pointer : must be '+' or '-'. */
3120 if (op != '-' && op != '+')
3121 error("cannot use pointers here");
3122 /* Put pointer as first operand */
3123 if ((t2 & VT_BTYPE) == VT_PTR) {
3124 vswap();
3125 swap(&t1, &t2);
3127 /* XXX: cast to int ? (long long case) */
3128 vpushi(pointed_size(vtop[-1].t));
3129 gen_op('*');
3130 /* if evaluating constant expression, no code should be
3131 generated, so no bound check */
3132 if (do_bounds_check && !const_wanted) {
3133 /* if bounded pointers, we generate a special code to
3134 test bounds */
3135 if (op == '-') {
3136 vpushi(0);
3137 vswap();
3138 gen_op('-');
3140 gen_bounded_ptr_add1();
3141 gen_bounded_ptr_add2(0);
3142 } else {
3143 gen_opc(op);
3145 /* put again type if gen_opc() swaped operands */
3146 vtop->t = t1;
3148 } else if (is_float(bt1) || is_float(bt2)) {
3149 /* compute bigger type and do implicit casts */
3150 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
3151 t = VT_LDOUBLE;
3152 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
3153 t = VT_DOUBLE;
3154 } else {
3155 t = VT_FLOAT;
3157 /* floats can only be used for a few operations */
3158 if (op != '+' && op != '-' && op != '*' && op != '/' &&
3159 (op < TOK_ULT || op > TOK_GT))
3160 error("invalid operands for binary operation");
3161 goto std_op;
3162 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
3163 /* cast to biggest op */
3164 t = VT_LLONG;
3165 /* convert to unsigned if it does not fit in a long long */
3166 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
3167 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
3168 t |= VT_UNSIGNED;
3169 goto std_op;
3170 } else {
3171 /* integer operations */
3172 t = VT_INT;
3173 /* convert to unsigned if it does not fit in an integer */
3174 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
3175 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3176 t |= VT_UNSIGNED;
3177 std_op:
3178 /* XXX: currently, some unsigned operations are explicit, so
3179 we modify them here */
3180 if (t & VT_UNSIGNED) {
3181 if (op == TOK_SAR)
3182 op = TOK_SHR;
3183 else if (op == '/')
3184 op = TOK_UDIV;
3185 else if (op == '%')
3186 op = TOK_UMOD;
3187 else if (op == TOK_LT)
3188 op = TOK_ULT;
3189 else if (op == TOK_GT)
3190 op = TOK_UGT;
3191 else if (op == TOK_LE)
3192 op = TOK_ULE;
3193 else if (op == TOK_GE)
3194 op = TOK_UGE;
3196 vswap();
3197 gen_cast(t);
3198 vswap();
3199 /* special case for shifts and long long: we keep the shift as
3200 an integer */
3201 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
3202 gen_cast(VT_INT);
3203 else
3204 gen_cast(t);
3205 if (is_float(t))
3206 gen_opf(op);
3207 else if ((t & VT_BTYPE) == VT_LLONG)
3208 gen_opl(op);
3209 else
3210 gen_opc(op);
3211 if (op >= TOK_ULT && op <= TOK_GT) {
3212 /* relationnal op: the result is an int */
3213 vtop->t = VT_INT;
3214 } else {
3215 vtop->t = t;
3220 /* generic itof for unsigned long long case */
3221 void gen_cvt_itof1(int t)
3223 GFuncContext gf;
3225 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
3226 (VT_LLONG | VT_UNSIGNED)) {
3228 gfunc_start(&gf, FUNC_CDECL);
3229 gfunc_param(&gf);
3230 if (t == VT_FLOAT)
3231 vpushi((int)&__ulltof);
3232 else if (t == VT_DOUBLE)
3233 vpushi((int)&__ulltod);
3234 else
3235 vpushi((int)&__ulltold);
3236 gfunc_call(&gf);
3237 vpushi(0);
3238 vtop->r = REG_FRET;
3239 } else {
3240 gen_cvt_itof(t);
3244 /* generic ftoi for unsigned long long case */
3245 void gen_cvt_ftoi1(int t)
3247 GFuncContext gf;
3248 int st;
3250 if (t == (VT_LLONG | VT_UNSIGNED)) {
3251 /* not handled natively */
3252 gfunc_start(&gf, FUNC_CDECL);
3253 st = vtop->t & VT_BTYPE;
3254 gfunc_param(&gf);
3255 if (st == VT_FLOAT)
3256 vpushi((int)&__ftoull);
3257 else if (st == VT_DOUBLE)
3258 vpushi((int)&__dtoull);
3259 else
3260 vpushi((int)&__ldtoull);
3261 gfunc_call(&gf);
3262 vpushi(0);
3263 vtop->r = REG_IRET;
3264 vtop->r2 = REG_LRET;
3265 } else {
3266 gen_cvt_ftoi(t);
3270 /* force char or short cast */
3271 void force_charshort_cast(int t)
3273 int bits, dbt;
3274 dbt = t & VT_BTYPE;
3275 /* XXX: add optimization if lvalue : just change type and offset */
3276 if (dbt == VT_BYTE)
3277 bits = 8;
3278 else
3279 bits = 16;
3280 if (t & VT_UNSIGNED) {
3281 vpushi((1 << bits) - 1);
3282 gen_op('&');
3283 } else {
3284 bits = 32 - bits;
3285 vpushi(bits);
3286 gen_op(TOK_SHL);
3287 vpushi(bits);
3288 gen_op(TOK_SAR);
3292 /* cast 'vtop' to 't' type */
3293 void gen_cast(int t)
3295 int sbt, dbt, sf, df, c, st1, dt1;
3297 /* special delayed cast for char/short */
3298 /* XXX: in some cases (multiple cascaded casts), it may still
3299 be incorrect */
3300 if (vtop->r & VT_MUSTCAST) {
3301 vtop->r &= ~VT_MUSTCAST;
3302 force_charshort_cast(vtop->t);
3305 dbt = t & VT_BTYPE;
3306 sbt = vtop->t & VT_BTYPE;
3308 if (sbt != dbt) {
3309 sf = is_float(sbt);
3310 df = is_float(dbt);
3311 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3312 if (sf && df) {
3313 /* convert from fp to fp */
3314 if (c) {
3315 /* constant case: we can do it now */
3316 /* XXX: in ISOC, cannot do it if error in convert */
3317 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
3318 vtop->c.f = (float)vtop->c.d;
3319 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
3320 vtop->c.f = (float)vtop->c.ld;
3321 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
3322 vtop->c.d = (double)vtop->c.f;
3323 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
3324 vtop->c.d = (double)vtop->c.ld;
3325 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
3326 vtop->c.ld = (long double)vtop->c.f;
3327 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
3328 vtop->c.ld = (long double)vtop->c.d;
3329 } else {
3330 /* non constant case: generate code */
3331 gen_cvt_ftof(dbt);
3333 } else if (df) {
3334 /* convert int to fp */
3335 st1 = vtop->t & (VT_BTYPE | VT_UNSIGNED);
3336 if (c) {
3337 switch(st1) {
3338 case VT_LLONG | VT_UNSIGNED:
3339 case VT_LLONG:
3340 /* XXX: add const cases for long long */
3341 goto do_itof;
3342 case VT_INT | VT_UNSIGNED:
3343 switch(dbt) {
3344 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
3345 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
3346 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
3348 break;
3349 default:
3350 switch(dbt) {
3351 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
3352 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
3353 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
3355 break;
3357 } else {
3358 do_itof:
3359 gen_cvt_itof1(dbt);
3361 } else if (sf) {
3362 /* convert fp to int */
3363 dt1 = t & (VT_BTYPE | VT_UNSIGNED);
3364 /* we handle char/short/etc... with generic code */
3365 if (dt1 != (VT_INT | VT_UNSIGNED) &&
3366 dt1 != (VT_LLONG | VT_UNSIGNED) &&
3367 dt1 != VT_LLONG)
3368 dt1 = VT_INT;
3369 if (c) {
3370 switch(dt1) {
3371 case VT_LLONG | VT_UNSIGNED:
3372 case VT_LLONG:
3373 /* XXX: add const cases for long long */
3374 goto do_ftoi;
3375 case VT_INT | VT_UNSIGNED:
3376 switch(sbt) {
3377 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
3378 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3379 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3381 break;
3382 default:
3383 /* int case */
3384 switch(sbt) {
3385 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
3386 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
3387 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
3389 break;
3391 } else {
3392 do_ftoi:
3393 gen_cvt_ftoi1(dt1);
3395 if (dt1 == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dt1) {
3396 /* additionnal cast for char/short/bool... */
3397 vtop->t = dt1;
3398 gen_cast(t);
3400 } else if (dbt == VT_LLONG) {
3401 /* scalar to long long */
3402 if (c) {
3403 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3404 vtop->c.ll = vtop->c.ui;
3405 else
3406 vtop->c.ll = vtop->c.i;
3407 } else {
3408 /* machine independant conversion */
3409 gv(RC_INT);
3410 /* generate high word */
3411 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) {
3412 vpushi(0);
3413 gv(RC_INT);
3414 } else {
3415 gv_dup();
3416 vpushi(31);
3417 gen_op(TOK_SAR);
3419 /* patch second register */
3420 vtop[-1].r2 = vtop->r;
3421 vpop();
3423 } else if (dbt == VT_BOOL) {
3424 /* scalar to bool */
3425 vpushi(0);
3426 gen_op(TOK_NE);
3427 } else if (dbt == VT_BYTE || dbt == VT_SHORT) {
3428 force_charshort_cast(t);
3429 } else if (dbt == VT_INT) {
3430 /* scalar to int */
3431 if (sbt == VT_LLONG) {
3432 /* from long long: just take low order word */
3433 lexpand();
3434 vpop();
3435 } else if (sbt == VT_PTR) {
3436 /* ok to cast */
3437 } else if (vtop->r & VT_LVAL) {
3438 /* if lvalue and single word type, nothing to do (XXX:
3439 maybe incorrect for sizeof op) */
3440 goto no_cast;
3444 vtop->t = t;
3445 no_cast: ;
3448 /* return type size. Put alignment at 'a' */
3449 int type_size(int t, int *a)
3451 Sym *s;
3452 int bt;
3454 bt = t & VT_BTYPE;
3455 if (bt == VT_STRUCT) {
3456 /* struct/union */
3457 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3458 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
3459 return s->c;
3460 } else if (bt == VT_PTR) {
3461 if (t & VT_ARRAY) {
3462 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3463 return type_size(s->t, a) * s->c;
3464 } else {
3465 *a = PTR_SIZE;
3466 return PTR_SIZE;
3468 } else if (bt == VT_LDOUBLE) {
3469 *a = LDOUBLE_ALIGN;
3470 return LDOUBLE_SIZE;
3471 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
3472 *a = 8;
3473 return 8;
3474 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
3475 *a = 4;
3476 return 4;
3477 } else if (bt == VT_SHORT) {
3478 *a = 2;
3479 return 2;
3480 } else {
3481 /* char, void, function, _Bool */
3482 *a = 1;
3483 return 1;
3487 /* return the pointed type of t */
3488 int pointed_type(int t)
3490 Sym *s;
3491 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3492 return s->t | (t & ~VT_TYPE);
3495 int mk_pointer(int t)
3497 int p;
3498 p = anon_sym++;
3499 sym_push(p, t, 0, -1);
3500 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
3503 int is_compatible_types(int t1, int t2)
3505 Sym *s1, *s2;
3506 int bt1, bt2;
3508 t1 &= VT_TYPE;
3509 t2 &= VT_TYPE;
3510 bt1 = t1 & VT_BTYPE;
3511 bt2 = t2 & VT_BTYPE;
3512 if (bt1 == VT_PTR) {
3513 t1 = pointed_type(t1);
3514 /* if function, then convert implicitely to function pointer */
3515 if (bt2 != VT_FUNC) {
3516 if (bt2 != VT_PTR)
3517 return 0;
3518 t2 = pointed_type(t2);
3520 /* void matches everything */
3521 t1 &= VT_TYPE;
3522 t2 &= VT_TYPE;
3523 if (t1 == VT_VOID || t2 == VT_VOID)
3524 return 1;
3525 return is_compatible_types(t1, t2);
3526 } else if (bt1 == VT_STRUCT) {
3527 return (t2 == t1);
3528 } else if (bt1 == VT_FUNC) {
3529 if (bt2 != VT_FUNC)
3530 return 0;
3531 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
3532 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
3533 if (!is_compatible_types(s1->t, s2->t))
3534 return 0;
3535 /* XXX: not complete */
3536 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
3537 return 1;
3538 if (s1->c != s2->c)
3539 return 0;
3540 while (s1 != NULL) {
3541 if (s2 == NULL)
3542 return 0;
3543 if (!is_compatible_types(s1->t, s2->t))
3544 return 0;
3545 s1 = s1->next;
3546 s2 = s2->next;
3548 if (s2)
3549 return 0;
3550 return 1;
3551 } else {
3552 /* XXX: not complete */
3553 return 1;
3557 /* print a type. If 'varstr' is not NULL, then the variable is also
3558 printed in the type */
3559 /* XXX: union */
3560 /* XXX: add array and function pointers */
3561 void type_to_str(char *buf, int buf_size,
3562 int t, const char *varstr)
3564 int bt, v;
3565 Sym *s, *sa;
3566 char buf1[256];
3567 const char *tstr;
3569 t = t & VT_TYPE;
3570 bt = t & VT_BTYPE;
3571 buf[0] = '\0';
3572 if (t & VT_UNSIGNED)
3573 pstrcat(buf, buf_size, "unsigned ");
3574 switch(bt) {
3575 case VT_VOID:
3576 tstr = "void";
3577 goto add_tstr;
3578 case VT_BOOL:
3579 tstr = "_Bool";
3580 goto add_tstr;
3581 case VT_BYTE:
3582 tstr = "char";
3583 goto add_tstr;
3584 case VT_SHORT:
3585 tstr = "short";
3586 goto add_tstr;
3587 case VT_INT:
3588 tstr = "int";
3589 goto add_tstr;
3590 case VT_LONG:
3591 tstr = "long";
3592 goto add_tstr;
3593 case VT_LLONG:
3594 tstr = "long long";
3595 goto add_tstr;
3596 case VT_FLOAT:
3597 tstr = "float";
3598 goto add_tstr;
3599 case VT_DOUBLE:
3600 tstr = "double";
3601 goto add_tstr;
3602 case VT_LDOUBLE:
3603 tstr = "long double";
3604 add_tstr:
3605 pstrcat(buf, buf_size, tstr);
3606 break;
3607 case VT_ENUM:
3608 case VT_STRUCT:
3609 if (bt == VT_STRUCT)
3610 tstr = "struct ";
3611 else
3612 tstr = "enum ";
3613 pstrcat(buf, buf_size, tstr);
3614 v = (unsigned)t >> VT_STRUCT_SHIFT;
3615 if (v >= SYM_FIRST_ANOM)
3616 pstrcat(buf, buf_size, "<anonymous>");
3617 else
3618 pstrcat(buf, buf_size, get_tok_str(v, NULL));
3619 break;
3620 case VT_FUNC:
3621 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3622 type_to_str(buf, buf_size, s->t, varstr);
3623 pstrcat(buf, buf_size, "(");
3624 sa = s->next;
3625 while (sa != NULL) {
3626 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
3627 pstrcat(buf, buf_size, buf1);
3628 sa = sa->next;
3629 if (sa)
3630 pstrcat(buf, buf_size, ", ");
3632 pstrcat(buf, buf_size, ")");
3633 goto no_var;
3634 case VT_PTR:
3635 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3636 pstrcpy(buf1, sizeof(buf1), "*");
3637 if (varstr)
3638 pstrcat(buf1, sizeof(buf1), varstr);
3639 type_to_str(buf, buf_size, s->t, buf1);
3640 goto no_var;
3642 if (varstr) {
3643 pstrcat(buf, buf_size, " ");
3644 pstrcat(buf, buf_size, varstr);
3646 no_var: ;
3649 /* verify type compatibility to store vtop in 'dt' type, and generate
3650 casts if needed. */
3651 void gen_assign_cast(int dt)
3653 int st;
3654 char buf1[256], buf2[256];
3656 st = vtop->t; /* source type */
3657 if ((dt & VT_BTYPE) == VT_PTR) {
3658 /* special cases for pointers */
3659 /* a function is implicitely a function pointer */
3660 if ((st & VT_BTYPE) == VT_FUNC) {
3661 if (!is_compatible_types(pointed_type(dt), st))
3662 goto error;
3663 else
3664 goto type_ok;
3666 /* '0' can also be a pointer */
3667 if ((st & VT_BTYPE) == VT_INT &&
3668 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) &&
3669 vtop->c.i == 0)
3670 goto type_ok;
3672 if (!is_compatible_types(dt, st)) {
3673 error:
3674 type_to_str(buf1, sizeof(buf1), st, NULL);
3675 type_to_str(buf2, sizeof(buf2), dt, NULL);
3676 error("cannot cast '%s' to '%s'", buf1, buf2);
3678 type_ok:
3679 gen_cast(dt);
3682 /* store vtop in lvalue pushed on stack */
3683 void vstore(void)
3685 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
3686 GFuncContext gf;
3688 ft = vtop[-1].t;
3689 sbt = vtop->t & VT_BTYPE;
3690 dbt = ft & VT_BTYPE;
3691 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
3692 (sbt == VT_INT && dbt == VT_SHORT)) {
3693 /* optimize char/short casts */
3694 delayed_cast = VT_MUSTCAST;
3695 vtop->t = ft & VT_TYPE;
3696 } else {
3697 delayed_cast = 0;
3698 gen_assign_cast(ft & VT_TYPE);
3701 if (sbt == VT_STRUCT) {
3702 /* if structure, only generate pointer */
3703 /* structure assignment : generate memcpy */
3704 /* XXX: optimize if small size */
3706 vdup();
3707 gfunc_start(&gf, FUNC_CDECL);
3708 /* type size */
3709 size = type_size(vtop->t, &align);
3710 vpushi(size);
3711 gfunc_param(&gf);
3712 /* source */
3713 vtop->t = VT_INT;
3714 gaddrof();
3715 gfunc_param(&gf);
3716 /* destination */
3717 vswap();
3718 vtop->t = VT_INT;
3719 gaddrof();
3720 gfunc_param(&gf);
3722 save_regs();
3723 vpushi((int)&memcpy);
3724 gfunc_call(&gf);
3725 /* leave source on stack */
3726 } else if (ft & VT_BITFIELD) {
3727 /* bitfield store handling */
3728 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
3729 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3730 /* remove bit field info to avoid loops */
3731 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3733 /* duplicate destination */
3734 vdup();
3735 vtop[-1] = vtop[-2];
3737 /* mask and shift source */
3738 vpushi((1 << bit_size) - 1);
3739 gen_op('&');
3740 vpushi(bit_pos);
3741 gen_op(TOK_SHL);
3742 /* load destination, mask and or with source */
3743 vswap();
3744 vpushi(~(((1 << bit_size) - 1) << bit_pos));
3745 gen_op('&');
3746 gen_op('|');
3747 /* store result */
3748 vstore();
3749 } else {
3750 /* bound check case */
3751 if (vtop[-1].r & VT_MUSTBOUND) {
3752 vswap();
3753 gbound();
3754 vswap();
3756 rc = RC_INT;
3757 if (is_float(ft))
3758 rc = RC_FLOAT;
3759 r = gv(rc); /* generate value */
3760 /* if lvalue was saved on stack, must read it */
3761 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
3762 SValue sv;
3763 t = get_reg(RC_INT);
3764 sv.t = VT_INT;
3765 sv.r = VT_LOCAL | VT_LVAL;
3766 sv.c.ul = vtop[-1].c.ul;
3767 load(t, &sv);
3768 vtop[-1].r = t | VT_LVAL;
3770 store(r, vtop - 1);
3771 /* two word case handling : store second register at word + 4 */
3772 if ((ft & VT_BTYPE) == VT_LLONG) {
3773 vswap();
3774 /* convert to int to increment easily */
3775 vtop->t = VT_INT;
3776 gaddrof();
3777 vpushi(4);
3778 gen_op('+');
3779 vtop->r |= VT_LVAL;
3780 vswap();
3781 /* XXX: it works because r2 is spilled last ! */
3782 store(vtop->r2, vtop - 1);
3784 vswap();
3785 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
3786 vtop->r |= delayed_cast;
3790 /* post defines POST/PRE add. c is the token ++ or -- */
3791 void inc(int post, int c)
3793 test_lvalue();
3794 vdup(); /* save lvalue */
3795 if (post) {
3796 gv_dup(); /* duplicate value */
3797 vrotb(3);
3798 vrotb(3);
3800 /* add constant */
3801 vpushi(c - TOK_MID);
3802 gen_op('+');
3803 vstore(); /* store value */
3804 if (post)
3805 vpop(); /* if post op, return saved value */
3808 /* Parse GNUC __attribute__ extension. Currently, the following
3809 extensions are recognized:
3810 - aligned(n) : set data/function alignment.
3811 - section(x) : generate data/code in this section.
3812 - unused : currently ignored, but may be used someday.
3814 void parse_attribute(AttributeDef *ad)
3816 int t, n;
3818 next();
3819 skip('(');
3820 skip('(');
3821 while (tok != ')') {
3822 if (tok < TOK_IDENT)
3823 expect("attribute name");
3824 t = tok;
3825 next();
3826 switch(t) {
3827 case TOK_SECTION:
3828 case TOK___SECTION__:
3829 skip('(');
3830 if (tok != TOK_STR)
3831 expect("section name");
3832 ad->section = find_section(tokc.ts->str);
3833 next();
3834 skip(')');
3835 break;
3836 case TOK_ALIGNED:
3837 case TOK___ALIGNED__:
3838 skip('(');
3839 n = expr_const();
3840 if (n <= 0 || (n & (n - 1)) != 0)
3841 error("alignment must be a positive power of two");
3842 ad->aligned = n;
3843 skip(')');
3844 break;
3845 case TOK_UNUSED:
3846 case TOK___UNUSED__:
3847 /* currently, no need to handle it because tcc does not
3848 track unused objects */
3849 break;
3850 case TOK_NORETURN:
3851 case TOK___NORETURN__:
3852 /* currently, no need to handle it because tcc does not
3853 track unused objects */
3854 break;
3855 case TOK_CDECL:
3856 case TOK___CDECL:
3857 case TOK___CDECL__:
3858 ad->func_call = FUNC_CDECL;
3859 break;
3860 case TOK_STDCALL:
3861 case TOK___STDCALL:
3862 case TOK___STDCALL__:
3863 ad->func_call = FUNC_STDCALL;
3864 break;
3865 default:
3866 warning("'%s' attribute ignored", get_tok_str(t, NULL));
3867 /* skip parameters */
3868 /* XXX: skip parenthesis too */
3869 if (tok == '(') {
3870 next();
3871 while (tok != ')' && tok != -1)
3872 next();
3873 next();
3875 break;
3877 if (tok != ',')
3878 break;
3879 next();
3881 skip(')');
3882 skip(')');
3885 /* enum/struct/union declaration */
3886 int struct_decl(int u)
3888 int a, t, b, v, size, align, maxalign, c, offset;
3889 int bit_size, bit_pos, bsize, bt, lbit_pos;
3890 Sym *s, *ss, **ps;
3891 AttributeDef ad;
3893 a = tok; /* save decl type */
3894 next();
3895 if (tok != '{') {
3896 v = tok;
3897 next();
3898 /* struct already defined ? return it */
3899 /* XXX: check consistency */
3900 s = sym_find(v | SYM_STRUCT);
3901 if (s) {
3902 if (s->t != a)
3903 error("invalid type");
3904 goto do_decl;
3906 } else {
3907 v = anon_sym++;
3909 s = sym_push(v | SYM_STRUCT, a, 0, 0);
3910 /* put struct/union/enum name in type */
3911 do_decl:
3912 u = u | (v << VT_STRUCT_SHIFT);
3914 if (tok == '{') {
3915 next();
3916 if (s->c)
3917 error("struct/union/enum already defined");
3918 /* cannot be empty */
3919 c = 0;
3920 maxalign = 0;
3921 ps = &s->next;
3922 bit_pos = 0;
3923 offset = 0;
3924 while (1) {
3925 if (a == TOK_ENUM) {
3926 v = tok;
3927 next();
3928 if (tok == '=') {
3929 next();
3930 c = expr_const();
3932 /* enum symbols have static storage */
3933 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
3934 if (tok == ',')
3935 next();
3936 c++;
3937 } else {
3938 parse_btype(&b, &ad);
3939 while (1) {
3940 bit_size = -1;
3941 v = 0;
3942 if (tok != ':') {
3943 t = type_decl(&ad, &v, b, TYPE_DIRECT);
3944 if ((t & VT_BTYPE) == VT_FUNC ||
3945 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
3946 error("invalid type for '%s'",
3947 get_tok_str(v, NULL));
3948 } else {
3949 t = b;
3951 if (tok == ':') {
3952 next();
3953 bit_size = expr_const();
3954 /* XXX: handle v = 0 case for messages */
3955 if (bit_size < 0)
3956 error("negative width in bit-field '%s'",
3957 get_tok_str(v, NULL));
3958 if (v && bit_size == 0)
3959 error("zero width for bit-field '%s'",
3960 get_tok_str(v, NULL));
3962 size = type_size(t, &align);
3963 lbit_pos = 0;
3964 if (bit_size >= 0) {
3965 bt = t & VT_BTYPE;
3966 if (bt != VT_INT &&
3967 bt != VT_BYTE &&
3968 bt != VT_SHORT)
3969 error("bitfields must have scalar type");
3970 bsize = size * 8;
3971 if (bit_size > bsize) {
3972 error("width of '%s' exceeds its type",
3973 get_tok_str(v, NULL));
3974 } else if (bit_size == bsize) {
3975 /* no need for bit fields */
3976 bit_pos = 0;
3977 } else if (bit_size == 0) {
3978 /* XXX: what to do if only padding in a
3979 structure ? */
3980 /* zero size: means to pad */
3981 if (bit_pos > 0)
3982 bit_pos = bsize;
3983 } else {
3984 /* we do not have enough room ? */
3985 if ((bit_pos + bit_size) > bsize)
3986 bit_pos = 0;
3987 lbit_pos = bit_pos;
3988 /* XXX: handle LSB first */
3989 t |= VT_BITFIELD |
3990 (bit_pos << VT_STRUCT_SHIFT) |
3991 (bit_size << (VT_STRUCT_SHIFT + 6));
3992 bit_pos += bit_size;
3994 } else {
3995 bit_pos = 0;
3997 if (v) {
3998 /* add new memory data only if starting
3999 bit field */
4000 if (lbit_pos == 0) {
4001 if (a == TOK_STRUCT) {
4002 c = (c + align - 1) & -align;
4003 offset = c;
4004 c += size;
4005 } else {
4006 offset = 0;
4007 if (size > c)
4008 c = size;
4010 if (align > maxalign)
4011 maxalign = align;
4013 #if 0
4014 printf("add field %s offset=%d",
4015 get_tok_str(v, NULL), offset);
4016 if (t & VT_BITFIELD) {
4017 printf(" pos=%d size=%d",
4018 (t >> VT_STRUCT_SHIFT) & 0x3f,
4019 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
4021 printf("\n");
4022 #endif
4023 ss = sym_push(v | SYM_FIELD, t, 0, offset);
4024 *ps = ss;
4025 ps = &ss->next;
4027 if (tok == ';' || tok == -1)
4028 break;
4029 skip(',');
4031 skip(';');
4033 if (tok == '}')
4034 break;
4036 skip('}');
4037 /* size for struct/union, dummy for enum */
4038 s->c = (c + maxalign - 1) & -maxalign;
4040 return u;
4043 /* return 0 if no type declaration. otherwise, return the basic type
4044 and skip it.
4046 int parse_btype(int *type_ptr, AttributeDef *ad)
4048 int t, u, type_found;
4049 Sym *s;
4051 memset(ad, 0, sizeof(AttributeDef));
4052 type_found = 0;
4053 t = 0;
4054 while(1) {
4055 switch(tok) {
4056 /* basic types */
4057 case TOK_CHAR:
4058 u = VT_BYTE;
4059 basic_type:
4060 next();
4061 basic_type1:
4062 if ((t & VT_BTYPE) != 0)
4063 error("too many basic types");
4064 t |= u;
4065 break;
4066 case TOK_VOID:
4067 u = VT_VOID;
4068 goto basic_type;
4069 case TOK_SHORT:
4070 u = VT_SHORT;
4071 goto basic_type;
4072 case TOK_INT:
4073 next();
4074 break;
4075 case TOK_LONG:
4076 next();
4077 if ((t & VT_BTYPE) == VT_DOUBLE) {
4078 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4079 } else if ((t & VT_BTYPE) == VT_LONG) {
4080 t = (t & ~VT_BTYPE) | VT_LLONG;
4081 } else {
4082 u = VT_LONG;
4083 goto basic_type1;
4085 break;
4086 case TOK_BOOL:
4087 u = VT_BOOL;
4088 goto basic_type;
4089 case TOK_FLOAT:
4090 u = VT_FLOAT;
4091 goto basic_type;
4092 case TOK_DOUBLE:
4093 next();
4094 if ((t & VT_BTYPE) == VT_LONG) {
4095 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4096 } else {
4097 u = VT_DOUBLE;
4098 goto basic_type1;
4100 break;
4101 case TOK_ENUM:
4102 u = struct_decl(VT_ENUM);
4103 goto basic_type1;
4104 case TOK_STRUCT:
4105 case TOK_UNION:
4106 u = struct_decl(VT_STRUCT);
4107 goto basic_type1;
4109 /* type modifiers */
4110 case TOK_CONST:
4111 case TOK_VOLATILE:
4112 case TOK_REGISTER:
4113 case TOK_SIGNED:
4114 case TOK___SIGNED__:
4115 case TOK_AUTO:
4116 case TOK_INLINE:
4117 case TOK___INLINE__:
4118 case TOK_RESTRICT:
4119 next();
4120 break;
4121 case TOK_UNSIGNED:
4122 t |= VT_UNSIGNED;
4123 next();
4124 break;
4126 /* storage */
4127 case TOK_EXTERN:
4128 t |= VT_EXTERN;
4129 next();
4130 break;
4131 case TOK_STATIC:
4132 t |= VT_STATIC;
4133 next();
4134 break;
4135 case TOK_TYPEDEF:
4136 t |= VT_TYPEDEF;
4137 next();
4138 break;
4139 /* GNUC attribute */
4140 case TOK___ATTRIBUTE__:
4141 parse_attribute(ad);
4142 break;
4143 default:
4144 s = sym_find(tok);
4145 if (!s || !(s->t & VT_TYPEDEF))
4146 goto the_end;
4147 t |= (s->t & ~VT_TYPEDEF);
4148 next();
4149 break;
4151 type_found = 1;
4153 the_end:
4154 /* long is never used as type */
4155 if ((t & VT_BTYPE) == VT_LONG)
4156 t = (t & ~VT_BTYPE) | VT_INT;
4157 *type_ptr = t;
4158 return type_found;
4161 int post_type(int t, AttributeDef *ad)
4163 int p, n, pt, l, t1;
4164 Sym **plast, *s, *first;
4165 AttributeDef ad1;
4167 if (tok == '(') {
4168 /* function declaration */
4169 next();
4170 l = 0;
4171 first = NULL;
4172 plast = &first;
4173 while (tok != ')') {
4174 /* read param name and compute offset */
4175 if (l != FUNC_OLD) {
4176 if (!parse_btype(&pt, &ad1)) {
4177 if (l) {
4178 error("invalid type");
4179 } else {
4180 l = FUNC_OLD;
4181 goto old_proto;
4184 l = FUNC_NEW;
4185 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
4186 break;
4187 pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
4188 if ((pt & VT_BTYPE) == VT_VOID)
4189 error("parameter declared as void");
4190 } else {
4191 old_proto:
4192 n = tok;
4193 pt = VT_INT;
4194 next();
4196 /* array must be transformed to pointer according to ANSI C */
4197 pt &= ~VT_ARRAY;
4198 s = sym_push(n | SYM_FIELD, pt, 0, 0);
4199 *plast = s;
4200 plast = &s->next;
4201 if (tok == ',') {
4202 next();
4203 if (l == FUNC_NEW && tok == TOK_DOTS) {
4204 l = FUNC_ELLIPSIS;
4205 next();
4206 break;
4210 /* if no parameters, then old type prototype */
4211 if (l == 0)
4212 l = FUNC_OLD;
4213 skip(')');
4214 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4215 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4216 /* we push a anonymous symbol which will contain the function prototype */
4217 p = anon_sym++;
4218 s = sym_push(p, t, ad->func_call, l);
4219 s->next = first;
4220 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
4221 } else if (tok == '[') {
4222 /* array definition */
4223 next();
4224 n = -1;
4225 if (tok != ']') {
4226 n = expr_const();
4227 if (n < 0)
4228 error("invalid array size");
4230 skip(']');
4231 /* parse next post type */
4232 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4233 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4235 /* we push a anonymous symbol which will contain the array
4236 element type */
4237 p = anon_sym++;
4238 sym_push(p, t, 0, n);
4239 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
4241 return t;
4244 /* Read a type declaration (except basic type), and return the
4245 type. 'td' is a bitmask indicating which kind of type decl is
4246 expected. 't' should contain the basic type. 'ad' is the attribute
4247 definition of the basic type. It can be modified by type_decl(). */
4248 int type_decl(AttributeDef *ad, int *v, int t, int td)
4250 int u, p;
4251 Sym *s;
4253 while (tok == '*') {
4254 next();
4255 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
4256 next();
4257 t = mk_pointer(t);
4260 /* recursive type */
4261 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4262 if (tok == '(') {
4263 next();
4264 /* XXX: this is not correct to modify 'ad' at this point, but
4265 the syntax is not clear */
4266 if (tok == TOK___ATTRIBUTE__)
4267 parse_attribute(ad);
4268 u = type_decl(ad, v, 0, td);
4269 skip(')');
4270 } else {
4271 u = 0;
4272 /* type identifier */
4273 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
4274 *v = tok;
4275 next();
4276 } else {
4277 if (!(td & TYPE_ABSTRACT))
4278 expect("identifier");
4279 *v = 0;
4282 /* append t at the end of u */
4283 t = post_type(t, ad);
4284 if (tok == TOK___ATTRIBUTE__)
4285 parse_attribute(ad);
4286 if (!u)
4287 return t;
4288 p = u;
4289 while(1) {
4290 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
4291 p = s->t;
4292 if (!p) {
4293 s->t = t;
4294 break;
4297 return u;
4300 /* define a new external reference to a function 'v' of type 'u' */
4301 Sym *external_sym(int v, int u, int r)
4303 Sym *s;
4304 s = sym_find(v);
4305 if (!s) {
4306 /* push forward reference */
4307 s = sym_push1(&global_stack,
4308 v, u, 0);
4309 s->r = r | VT_CONST | VT_FORWARD;
4311 return s;
4314 void indir(void)
4316 if ((vtop->t & VT_BTYPE) != VT_PTR)
4317 expect("pointer");
4318 if (vtop->r & VT_LVAL)
4319 gv(RC_INT);
4320 vtop->t = pointed_type(vtop->t);
4321 /* an array is never an lvalue */
4322 if (!(vtop->t & VT_ARRAY)) {
4323 vtop->r |= VT_LVAL;
4324 /* if bound checking, the referenced pointer must be checked */
4325 if (do_bounds_check)
4326 vtop->r |= VT_MUSTBOUND;
4330 /* pass a parameter to a function and do type checking and casting */
4331 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
4333 int func_type;
4334 func_type = func->c;
4335 if (func_type == FUNC_OLD ||
4336 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
4337 /* default casting : only need to convert float to double */
4338 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
4339 gen_cast(VT_DOUBLE);
4340 } else if (arg == NULL) {
4341 error("too many arguments to function");
4342 } else {
4343 gen_assign_cast(arg->t);
4345 gfunc_param(gf);
4348 void unary(void)
4350 int n, t, ft, fc, p, align, size, r, data_offset;
4351 Sym *s;
4352 GFuncContext gf;
4353 AttributeDef ad;
4355 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
4356 vpushi(tokc.i);
4357 next();
4358 } else if (tok == TOK_CUINT) {
4359 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
4360 next();
4361 } else if (tok == TOK_CLLONG) {
4362 vsetc(VT_LLONG, VT_CONST, &tokc);
4363 next();
4364 } else if (tok == TOK_CULLONG) {
4365 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
4366 next();
4367 } else if (tok == TOK_CFLOAT) {
4368 vsetc(VT_FLOAT, VT_CONST, &tokc);
4369 next();
4370 } else if (tok == TOK_CDOUBLE) {
4371 vsetc(VT_DOUBLE, VT_CONST, &tokc);
4372 next();
4373 } else if (tok == TOK_CLDOUBLE) {
4374 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
4375 next();
4376 } else if (tok == TOK___FUNC__) {
4377 /* special function name identifier */
4378 /* generate (char *) type */
4379 data_offset = (int)data_section->data_ptr;
4380 vset(mk_pointer(VT_BYTE), VT_CONST, data_offset);
4381 strcpy((void *)data_offset, funcname);
4382 data_offset += strlen(funcname) + 1;
4383 data_section->data_ptr = (unsigned char *)data_offset;
4384 next();
4385 } else if (tok == TOK_LSTR) {
4386 t = VT_INT;
4387 goto str_init;
4388 } else if (tok == TOK_STR) {
4389 /* string parsing */
4390 t = VT_BYTE;
4391 str_init:
4392 type_size(t, &align);
4393 data_offset = (int)data_section->data_ptr;
4394 data_offset = (data_offset + align - 1) & -align;
4395 fc = data_offset;
4396 /* we must declare it as an array first to use initializer parser */
4397 t = VT_ARRAY | mk_pointer(t);
4398 decl_initializer(t, VT_CONST, data_offset, 1, 0);
4399 data_offset += type_size(t, &align);
4400 /* put it as pointer */
4401 vset(t & ~VT_ARRAY, VT_CONST, fc);
4402 data_section->data_ptr = (unsigned char *)data_offset;
4403 } else {
4404 t = tok;
4405 next();
4406 if (t == '(') {
4407 /* cast ? */
4408 if (parse_btype(&t, &ad)) {
4409 ft = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4410 skip(')');
4411 /* check ISOC99 compound literal */
4412 if (tok == '{') {
4413 /* data is allocated locally by default */
4414 if (global_expr)
4415 r = VT_CONST;
4416 else
4417 r = VT_LOCAL;
4418 /* all except arrays are lvalues */
4419 if (!(ft & VT_ARRAY))
4420 r |= VT_LVAL;
4421 memset(&ad, 0, sizeof(AttributeDef));
4422 fc = decl_initializer_alloc(ft, &ad, r, 1);
4423 vset(ft, r, fc);
4424 } else {
4425 unary();
4426 gen_cast(ft);
4428 } else {
4429 gexpr();
4430 skip(')');
4432 } else if (t == '*') {
4433 unary();
4434 indir();
4435 } else if (t == '&') {
4436 unary();
4437 /* functions names must be treated as function pointers,
4438 except for unary '&' and sizeof. Since we consider that
4439 functions are not lvalues, we only have to handle it
4440 there and in function calls. */
4441 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4442 test_lvalue();
4443 vtop->t = mk_pointer(vtop->t);
4444 gaddrof();
4445 } else
4446 if (t == '!') {
4447 unary();
4448 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
4449 vtop->c.i = !vtop->c.i;
4450 else if ((vtop->r & VT_VALMASK) == VT_CMP)
4451 vtop->c.i = vtop->c.i ^ 1;
4452 else
4453 vset(VT_INT, VT_JMP, gtst(1, 0));
4454 } else
4455 if (t == '~') {
4456 unary();
4457 vpushi(-1);
4458 gen_op('^');
4459 } else
4460 if (t == '+') {
4461 unary();
4462 } else
4463 if (t == TOK_SIZEOF) {
4464 if (tok == '(') {
4465 next();
4466 if (parse_btype(&t, &ad)) {
4467 t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4468 } else {
4469 /* XXX: some code could be generated: add eval
4470 flag */
4471 gexpr();
4472 t = vtop->t;
4473 vpop();
4475 skip(')');
4476 } else {
4477 unary();
4478 t = vtop->t;
4479 vpop();
4481 vpushi(type_size(t, &t));
4482 } else
4483 if (t == TOK_INC || t == TOK_DEC) {
4484 unary();
4485 inc(0, t);
4486 } else if (t == '-') {
4487 vpushi(0);
4488 unary();
4489 gen_op('-');
4490 } else
4492 s = sym_find(t);
4493 if (!s) {
4494 if (tok != '(')
4495 error("'%s' undeclared", get_tok_str(t, NULL));
4496 /* for simple function calls, we tolerate undeclared
4497 external reference */
4498 p = anon_sym++;
4499 sym_push1(&global_stack, p, 0, FUNC_OLD);
4500 /* int() function */
4501 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT), 0);
4503 vset(s->t, s->r, s->c);
4504 /* if forward reference, we must point to s */
4505 if (vtop->r & VT_FORWARD)
4506 vtop->c.sym = s;
4510 /* post operations */
4511 while (1) {
4512 if (tok == TOK_INC || tok == TOK_DEC) {
4513 inc(1, tok);
4514 next();
4515 } else if (tok == '.' || tok == TOK_ARROW) {
4516 /* field */
4517 if (tok == TOK_ARROW)
4518 indir();
4519 test_lvalue();
4520 gaddrof();
4521 next();
4522 /* expect pointer on structure */
4523 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
4524 expect("struct or union");
4525 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4526 /* find field */
4527 tok |= SYM_FIELD;
4528 while ((s = s->next) != NULL) {
4529 if (s->v == tok)
4530 break;
4532 if (!s)
4533 error("field not found");
4534 /* add field offset to pointer */
4535 vtop->t = char_pointer_type; /* change type to 'char *' */
4536 vpushi(s->c);
4537 gen_op('+');
4538 /* change type to field type, and set to lvalue */
4539 vtop->t = s->t;
4540 /* an array is never an lvalue */
4541 if (!(vtop->t & VT_ARRAY))
4542 vtop->r |= VT_LVAL;
4543 next();
4544 } else if (tok == '[') {
4545 next();
4546 gexpr();
4547 gen_op('+');
4548 indir();
4549 skip(']');
4550 } else if (tok == '(') {
4551 SValue ret;
4552 Sym *sa;
4554 /* function call */
4555 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
4556 /* pointer test (no array accepted) */
4557 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
4558 vtop->t = pointed_type(vtop->t);
4559 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4560 goto error_func;
4561 } else {
4562 error_func:
4563 expect("function pointer");
4565 } else {
4566 vtop->r &= ~VT_LVAL; /* no lvalue */
4568 /* get return type */
4569 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
4570 save_regs(); /* save used temporary registers */
4571 gfunc_start(&gf, s->r);
4572 next();
4573 sa = s->next; /* first parameter */
4574 #ifdef INVERT_FUNC_PARAMS
4576 int *str, len, parlevel, *saved_macro_ptr;
4577 Sym *args, *s1;
4579 /* read each argument and store it on a stack */
4580 /* XXX: merge it with macro args ? */
4581 args = NULL;
4582 while (tok != ')') {
4583 len = 0;
4584 str = NULL;
4585 parlevel = 0;
4586 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
4587 tok != -1) {
4588 if (tok == '(')
4589 parlevel++;
4590 else if (tok == ')')
4591 parlevel--;
4592 tok_add2(&str, &len, tok, &tokc);
4593 next();
4595 tok_add(&str, &len, -1); /* end of file added */
4596 tok_add(&str, &len, 0);
4597 s1 = sym_push2(&args, 0, 0, (int)str);
4598 s1->next = sa; /* add reference to argument */
4599 if (sa)
4600 sa = sa->next;
4601 if (tok != ',')
4602 break;
4603 next();
4605 if (tok != ')')
4606 expect(")");
4608 /* now generate code in reverse order by reading the stack */
4609 saved_macro_ptr = macro_ptr;
4610 while (args) {
4611 macro_ptr = (int *)args->c;
4612 next();
4613 expr_eq();
4614 if (tok != -1)
4615 expect("',' or ')'");
4616 gfunc_param_typed(&gf, s, args->next);
4617 s1 = args->prev;
4618 free((int *)args->c);
4619 free(args);
4620 args = s1;
4622 macro_ptr = saved_macro_ptr;
4623 /* restore token */
4624 tok = ')';
4626 #endif
4627 /* compute first implicit argument if a structure is returned */
4628 if ((s->t & VT_BTYPE) == VT_STRUCT) {
4629 /* get some space for the returned structure */
4630 size = type_size(s->t, &align);
4631 loc = (loc - size) & -align;
4632 ret.t = s->t;
4633 ret.r = VT_LOCAL | VT_LVAL;
4634 /* pass it as 'int' to avoid structure arg passing
4635 problems */
4636 vset(VT_INT, VT_LOCAL, loc);
4637 ret.c = vtop->c;
4638 gfunc_param(&gf);
4639 } else {
4640 ret.t = s->t;
4641 ret.r2 = VT_CONST;
4642 /* return in register */
4643 if (is_float(ret.t)) {
4644 ret.r = REG_FRET;
4645 } else {
4646 if ((ret.t & VT_BTYPE) == VT_LLONG)
4647 ret.r2 = REG_LRET;
4648 ret.r = REG_IRET;
4650 ret.c.i = 0;
4652 #ifndef INVERT_FUNC_PARAMS
4653 while (tok != ')') {
4654 expr_eq();
4655 gfunc_param_typed(&gf, s, sa);
4656 if (sa)
4657 sa = sa->next;
4658 if (tok == ',')
4659 next();
4661 #endif
4662 if (sa)
4663 error("too few arguments to function");
4664 skip(')');
4665 gfunc_call(&gf);
4666 /* return value */
4667 vsetc(ret.t, ret.r, &ret.c);
4668 vtop->r2 = ret.r2;
4669 } else {
4670 break;
4675 void uneq(void)
4677 int t;
4679 unary();
4680 if (tok == '=' ||
4681 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
4682 tok == TOK_A_XOR || tok == TOK_A_OR ||
4683 tok == TOK_A_SHL || tok == TOK_A_SAR) {
4684 test_lvalue();
4685 t = tok;
4686 next();
4687 if (t == '=') {
4688 expr_eq();
4689 } else {
4690 vdup();
4691 expr_eq();
4692 gen_op(t & 0x7f);
4694 vstore();
4698 void sum(int l)
4700 int t;
4702 if (l == 0)
4703 uneq();
4704 else {
4705 sum(--l);
4706 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
4707 (l == 1 && (tok == '+' || tok == '-')) ||
4708 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
4709 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
4710 tok == TOK_ULT || tok == TOK_UGE)) ||
4711 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
4712 (l == 5 && tok == '&') ||
4713 (l == 6 && tok == '^') ||
4714 (l == 7 && tok == '|') ||
4715 (l == 8 && tok == TOK_LAND) ||
4716 (l == 9 && tok == TOK_LOR)) {
4717 t = tok;
4718 next();
4719 sum(l);
4720 gen_op(t);
4725 /* only used if non constant */
4726 void eand(void)
4728 int t;
4730 sum(8);
4731 t = 0;
4732 while (1) {
4733 if (tok != TOK_LAND) {
4734 if (t) {
4735 t = gtst(1, t);
4736 vset(VT_INT, VT_JMPI, t);
4738 break;
4740 t = gtst(1, t);
4741 next();
4742 sum(8);
4746 void eor(void)
4748 int t;
4750 eand();
4751 t = 0;
4752 while (1) {
4753 if (tok != TOK_LOR) {
4754 if (t) {
4755 t = gtst(0, t);
4756 vset(VT_INT, VT_JMP, t);
4758 break;
4760 t = gtst(0, t);
4761 next();
4762 eand();
4766 /* XXX: better constant handling */
4767 void expr_eq(void)
4769 int t, u, c, r1, r2, rc;
4771 if (const_wanted) {
4772 sum(10);
4773 if (tok == '?') {
4774 c = vtop->c.i;
4775 vpop();
4776 next();
4777 gexpr();
4778 t = vtop->c.i;
4779 vpop();
4780 skip(':');
4781 expr_eq();
4782 if (c)
4783 vtop->c.i = t;
4785 } else {
4786 eor();
4787 if (tok == '?') {
4788 next();
4789 t = gtst(1, 0);
4790 gexpr();
4791 /* XXX: long long handling ? */
4792 rc = RC_INT;
4793 if (is_float(vtop->t))
4794 rc = RC_FLOAT;
4795 r1 = gv(rc);
4796 vtop--; /* no vpop so that FP stack is not flushed */
4797 skip(':');
4798 u = gjmp(0);
4800 gsym(t);
4801 expr_eq();
4802 r2 = gv(rc);
4803 move_reg(r1, r2);
4804 vtop->r = r1;
4805 gsym(u);
4810 void gexpr(void)
4812 while (1) {
4813 expr_eq();
4814 if (tok != ',')
4815 break;
4816 vpop();
4817 next();
4821 /* parse a constant expression and return value in vtop */
4822 void expr_const1(void)
4824 int a;
4825 a = const_wanted;
4826 const_wanted = 1;
4827 expr_eq();
4828 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
4829 expect("constant");
4830 const_wanted = a;
4833 /* parse an integer constant and return its value */
4834 int expr_const(void)
4836 int c;
4837 expr_const1();
4838 c = vtop->c.i;
4839 vpop();
4840 return c;
4843 /* return the label token if current token is a label, otherwise
4844 return zero */
4845 int is_label(void)
4847 int t;
4848 CValue c;
4850 /* fast test first */
4851 if (tok < TOK_UIDENT)
4852 return 0;
4853 /* no need to save tokc since we expect an identifier */
4854 t = tok;
4855 c = tokc;
4856 next();
4857 if (tok == ':') {
4858 next();
4859 return t;
4860 } else {
4861 /* XXX: may not work in all cases (macros ?) */
4862 tok1 = tok;
4863 tok1c = tokc;
4864 tok = t;
4865 tokc = c;
4866 return 0;
4870 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
4872 int a, b, c, d;
4873 Sym *s;
4875 /* generate line number info */
4876 if (do_debug &&
4877 (last_line_num != file->line_num || last_ind != ind)) {
4878 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
4879 last_ind = ind;
4880 last_line_num = file->line_num;
4883 if (tok == TOK_IF) {
4884 /* if test */
4885 next();
4886 skip('(');
4887 gexpr();
4888 skip(')');
4889 a = gtst(1, 0);
4890 block(bsym, csym, case_sym, def_sym, case_reg);
4891 c = tok;
4892 if (c == TOK_ELSE) {
4893 next();
4894 d = gjmp(0);
4895 gsym(a);
4896 block(bsym, csym, case_sym, def_sym, case_reg);
4897 gsym(d); /* patch else jmp */
4898 } else
4899 gsym(a);
4900 } else if (tok == TOK_WHILE) {
4901 next();
4902 d = ind;
4903 skip('(');
4904 gexpr();
4905 skip(')');
4906 a = gtst(1, 0);
4907 b = 0;
4908 block(&a, &b, case_sym, def_sym, case_reg);
4909 gjmp_addr(d);
4910 gsym(a);
4911 gsym_addr(b, d);
4912 } else if (tok == '{') {
4913 next();
4914 /* declarations */
4915 s = local_stack.top;
4916 while (tok != '}') {
4917 decl(VT_LOCAL);
4918 if (tok != '}')
4919 block(bsym, csym, case_sym, def_sym, case_reg);
4921 /* pop locally defined symbols */
4922 sym_pop(&local_stack, s);
4923 next();
4924 } else if (tok == TOK_RETURN) {
4925 next();
4926 if (tok != ';') {
4927 gexpr();
4928 gen_assign_cast(func_vt);
4929 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
4930 /* if returning structure, must copy it to implicit
4931 first pointer arg location */
4932 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
4933 indir();
4934 vswap();
4935 /* copy structure value to pointer */
4936 vstore();
4937 } else if (is_float(func_vt)) {
4938 gv(RC_FRET);
4939 } else {
4940 gv(RC_IRET);
4942 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
4944 skip(';');
4945 rsym = gjmp(rsym); /* jmp */
4946 } else if (tok == TOK_BREAK) {
4947 /* compute jump */
4948 if (!bsym)
4949 error("cannot break");
4950 *bsym = gjmp(*bsym);
4951 next();
4952 skip(';');
4953 } else if (tok == TOK_CONTINUE) {
4954 /* compute jump */
4955 if (!csym)
4956 error("cannot continue");
4957 *csym = gjmp(*csym);
4958 next();
4959 skip(';');
4960 } else if (tok == TOK_FOR) {
4961 int e;
4962 next();
4963 skip('(');
4964 if (tok != ';') {
4965 gexpr();
4966 vpop();
4968 skip(';');
4969 d = ind;
4970 c = ind;
4971 a = 0;
4972 b = 0;
4973 if (tok != ';') {
4974 gexpr();
4975 a = gtst(1, 0);
4977 skip(';');
4978 if (tok != ')') {
4979 e = gjmp(0);
4980 c = ind;
4981 gexpr();
4982 vpop();
4983 gjmp_addr(d);
4984 gsym(e);
4986 skip(')');
4987 block(&a, &b, case_sym, def_sym, case_reg);
4988 gjmp_addr(c);
4989 gsym(a);
4990 gsym_addr(b, c);
4991 } else
4992 if (tok == TOK_DO) {
4993 next();
4994 a = 0;
4995 b = 0;
4996 d = ind;
4997 block(&a, &b, case_sym, def_sym, case_reg);
4998 skip(TOK_WHILE);
4999 skip('(');
5000 gsym(b);
5001 gexpr();
5002 c = gtst(0, 0);
5003 gsym_addr(c, d);
5004 skip(')');
5005 gsym(a);
5006 skip(';');
5007 } else
5008 if (tok == TOK_SWITCH) {
5009 next();
5010 skip('(');
5011 gexpr();
5012 /* XXX: other types than integer */
5013 case_reg = gv(RC_INT);
5014 vpop();
5015 skip(')');
5016 a = 0;
5017 b = gjmp(0); /* jump to first case */
5018 c = 0;
5019 block(&a, csym, &b, &c, case_reg);
5020 /* if no default, jmp after switch */
5021 if (c == 0)
5022 c = ind;
5023 /* default label */
5024 gsym_addr(b, c);
5025 /* break label */
5026 gsym(a);
5027 } else
5028 if (tok == TOK_CASE) {
5029 int v1, v2;
5030 if (!case_sym)
5031 expect("switch");
5032 next();
5033 v1 = expr_const();
5034 v2 = v1;
5035 if (gnu_ext && tok == TOK_DOTS) {
5036 next();
5037 v2 = expr_const();
5038 if (v2 < v1)
5039 warning("empty case range");
5041 /* since a case is like a label, we must skip it with a jmp */
5042 b = gjmp(0);
5043 gsym(*case_sym);
5044 vset(VT_INT, case_reg, 0);
5045 vpushi(v1);
5046 if (v1 == v2) {
5047 gen_op(TOK_EQ);
5048 *case_sym = gtst(1, 0);
5049 } else {
5050 gen_op(TOK_GE);
5051 *case_sym = gtst(1, 0);
5052 vset(VT_INT, case_reg, 0);
5053 vpushi(v2);
5054 gen_op(TOK_LE);
5055 *case_sym = gtst(1, *case_sym);
5057 gsym(b);
5058 skip(':');
5059 block(bsym, csym, case_sym, def_sym, case_reg);
5060 } else
5061 if (tok == TOK_DEFAULT) {
5062 next();
5063 skip(':');
5064 if (!def_sym)
5065 expect("switch");
5066 if (*def_sym)
5067 error("too many 'default'");
5068 *def_sym = ind;
5069 block(bsym, csym, case_sym, def_sym, case_reg);
5070 } else
5071 if (tok == TOK_GOTO) {
5072 next();
5073 s = sym_find1(&label_stack, tok);
5074 /* put forward definition if needed */
5075 if (!s)
5076 s = sym_push1(&label_stack, tok, VT_FORWARD, 0);
5077 /* label already defined */
5078 if (s->t & VT_FORWARD)
5079 s->c = gjmp(s->c);
5080 else
5081 gjmp_addr(s->c);
5082 next();
5083 skip(';');
5084 } else {
5085 b = is_label();
5086 if (b) {
5087 /* label case */
5088 s = sym_find1(&label_stack, b);
5089 if (s) {
5090 if (!(s->t & VT_FORWARD))
5091 error("multiple defined label");
5092 gsym(s->c);
5093 s->c = ind;
5094 s->t = 0;
5095 } else {
5096 sym_push1(&label_stack, b, 0, ind);
5098 /* we accept this, but it is a mistake */
5099 if (tok == '}')
5100 warning("deprecated use of label at end of compound statement");
5101 else
5102 block(bsym, csym, case_sym, def_sym, case_reg);
5103 } else {
5104 /* expression case */
5105 if (tok != ';') {
5106 gexpr();
5107 vpop();
5109 skip(';');
5114 /* t is the array or struct type. c is the array or struct
5115 address. cur_index/cur_field is the pointer to the current
5116 value. 'size_only' is true if only size info is needed (only used
5117 in arrays) */
5118 void decl_designator(int t, int r, int c,
5119 int *cur_index, Sym **cur_field,
5120 int size_only)
5122 Sym *s, *f;
5123 int notfirst, index, align, l;
5125 notfirst = 0;
5126 if (gnu_ext && (l = is_label()) != 0)
5127 goto struct_field;
5129 while (tok == '[' || tok == '.') {
5130 if (tok == '[') {
5131 if (!(t & VT_ARRAY))
5132 expect("array type");
5133 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5134 next();
5135 index = expr_const();
5136 if (index < 0 || (s->c >= 0 && index >= s->c))
5137 expect("invalid index");
5138 skip(']');
5139 if (!notfirst)
5140 *cur_index = index;
5141 t = pointed_type(t);
5142 c += index * type_size(t, &align);
5143 } else {
5144 next();
5145 l = tok;
5146 next();
5147 struct_field:
5148 if ((t & VT_BTYPE) != VT_STRUCT)
5149 expect("struct/union type");
5150 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5151 l |= SYM_FIELD;
5152 f = s->next;
5153 while (f) {
5154 if (f->v == l)
5155 break;
5156 f = f->next;
5158 if (!f)
5159 expect("field");
5160 if (!notfirst)
5161 *cur_field = f;
5162 t = f->t | (t & ~VT_TYPE);
5163 c += f->c;
5165 notfirst = 1;
5167 if (notfirst) {
5168 if (tok == '=') {
5169 next();
5170 } else {
5171 if (!gnu_ext)
5172 expect("=");
5174 } else {
5175 if (t & VT_ARRAY) {
5176 index = *cur_index;
5177 t = pointed_type(t);
5178 c += index * type_size(t, &align);
5179 } else {
5180 f = *cur_field;
5181 if (!f)
5182 error("too many field init");
5183 t = f->t | (t & ~VT_TYPE);
5184 c += f->c;
5187 decl_initializer(t, r, c, 0, size_only);
5190 #define EXPR_VAL 0
5191 #define EXPR_CONST 1
5192 #define EXPR_ANY 2
5194 /* store a value or an expression directly in global data or in local array */
5195 void init_putv(int t, int r, int c,
5196 int v, int expr_type)
5198 int saved_global_expr, bt;
5200 switch(expr_type) {
5201 case EXPR_VAL:
5202 vpushi(v);
5203 break;
5204 case EXPR_CONST:
5205 /* compound literals must be allocated globally in this case */
5206 saved_global_expr = global_expr;
5207 global_expr = 1;
5208 expr_const1();
5209 global_expr = saved_global_expr;
5210 break;
5211 case EXPR_ANY:
5212 expr_eq();
5213 break;
5216 if ((r & VT_VALMASK) == VT_CONST) {
5217 /* XXX: not portable */
5218 gen_assign_cast(t);
5219 bt = t & VT_BTYPE;
5220 switch(bt) {
5221 case VT_BYTE:
5222 *(char *)c = vtop->c.i;
5223 break;
5224 case VT_SHORT:
5225 *(short *)c = vtop->c.i;
5226 break;
5227 case VT_DOUBLE:
5228 *(double *)c = vtop->c.d;
5229 break;
5230 case VT_LDOUBLE:
5231 *(long double *)c = vtop->c.ld;
5232 break;
5233 case VT_LLONG:
5234 *(long long *)c = vtop->c.ll;
5235 break;
5236 default:
5237 *(int *)c = vtop->c.i;
5238 break;
5240 vtop--;
5241 } else {
5242 vset(t, r, c);
5243 vswap();
5244 vstore();
5245 vpop();
5249 /* put zeros for variable based init */
5250 void init_putz(int t, int r, int c, int size)
5252 GFuncContext gf;
5254 if ((r & VT_VALMASK) == VT_CONST) {
5255 /* nothing to do because globals are already set to zero */
5256 } else {
5257 gfunc_start(&gf, FUNC_CDECL);
5258 vpushi(size);
5259 gfunc_param(&gf);
5260 vpushi(0);
5261 gfunc_param(&gf);
5262 vset(VT_INT, VT_LOCAL, c);
5263 gfunc_param(&gf);
5264 vpushi((int)&memset);
5265 gfunc_call(&gf);
5269 /* 't' contains the type and storage info. c is the address of the
5270 object. 'first' is true if array '{' must be read (multi dimension
5271 implicit array init handling). 'size_only' is true if size only
5272 evaluation is wanted (only for arrays). */
5273 void decl_initializer(int t, int r, int c, int first, int size_only)
5275 int index, array_length, n, no_oblock, nb, parlevel, i;
5276 int t1, size1, align1, expr_type;
5277 Sym *s, *f;
5278 TokenSym *ts;
5280 if (t & VT_ARRAY) {
5281 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5282 n = s->c;
5283 array_length = 0;
5284 t1 = pointed_type(t);
5285 size1 = type_size(t1, &align1);
5287 no_oblock = 1;
5288 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
5289 tok == '{') {
5290 skip('{');
5291 no_oblock = 0;
5294 /* only parse strings here if correct type (otherwise: handle
5295 them as ((w)char *) expressions */
5296 if ((tok == TOK_LSTR &&
5297 (t1 & VT_BTYPE) == VT_INT) ||
5298 (tok == TOK_STR &&
5299 (t1 & VT_BTYPE) == VT_BYTE)) {
5300 /* XXX: move multiple string parsing in parser ? */
5301 while (tok == TOK_STR || tok == TOK_LSTR) {
5302 ts = tokc.ts;
5303 /* compute maximum number of chars wanted */
5304 nb = ts->len;
5305 if (n >= 0 && nb > (n - array_length))
5306 nb = n - array_length;
5307 if (!size_only) {
5308 if (ts->len > nb)
5309 warning("initializer-string for array is too long");
5310 for(i=0;i<nb;i++) {
5311 init_putv(t1, r, c + (array_length + i) * size1,
5312 ts->str[i], EXPR_VAL);
5315 array_length += nb;
5316 next();
5318 /* only add trailing zero if enough storage (no
5319 warning in this case since it is standard) */
5320 if (n < 0 || array_length < n) {
5321 if (!size_only) {
5322 init_putv(t1, r, c + (array_length * size1), 0, EXPR_VAL);
5324 array_length++;
5326 } else {
5327 index = 0;
5328 while (tok != '}') {
5329 decl_designator(t, r, c, &index, NULL, size_only);
5330 if (n >= 0 && index >= n)
5331 error("index too large");
5332 /* must put zero in holes (note that doing it that way
5333 ensures that it even works with designators) */
5334 if (!size_only && array_length < index) {
5335 init_putz(t1, r, c + array_length * size1,
5336 (index - array_length) * size1);
5338 index++;
5339 if (index > array_length)
5340 array_length = index;
5341 /* special test for multi dimensional arrays (may not
5342 be strictly correct if designators are used at the
5343 same time) */
5344 if (index >= n && no_oblock)
5345 break;
5346 if (tok == '}')
5347 break;
5348 skip(',');
5351 if (!no_oblock)
5352 skip('}');
5353 /* put zeros at the end */
5354 if (!size_only && n >= 0 && array_length < n) {
5355 init_putz(t1, r, c + array_length * size1,
5356 (n - array_length) * size1);
5358 /* patch type size if needed */
5359 if (n < 0)
5360 s->c = array_length;
5361 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
5362 /* XXX: union needs only one init */
5363 next();
5364 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5365 f = s->next;
5366 array_length = 0;
5367 index = 0;
5368 n = s->c;
5369 while (tok != '}') {
5370 decl_designator(t, r, c, NULL, &f, size_only);
5371 /* fill with zero between fields */
5372 index = f->c;
5373 if (!size_only && array_length < index) {
5374 init_putz(t, r, c + array_length,
5375 index - array_length);
5377 index = index + type_size(f->t, &align1);
5378 if (index > array_length)
5379 array_length = index;
5380 if (tok == '}')
5381 break;
5382 skip(',');
5383 f = f->next;
5385 /* put zeros at the end */
5386 if (!size_only && array_length < n) {
5387 init_putz(t, r, c + array_length,
5388 n - array_length);
5390 skip('}');
5391 } else if (tok == '{') {
5392 next();
5393 decl_initializer(t, r, c, first, size_only);
5394 skip('}');
5395 } else if (size_only) {
5396 /* just skip expression */
5397 parlevel = 0;
5398 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
5399 tok != -1) {
5400 if (tok == '(')
5401 parlevel++;
5402 else if (tok == ')')
5403 parlevel--;
5404 next();
5406 } else {
5407 /* currently, we always use constant expression for globals
5408 (may change for scripting case) */
5409 expr_type = EXPR_CONST;
5410 if ((r & VT_VALMASK) == VT_LOCAL)
5411 expr_type = EXPR_ANY;
5412 init_putv(t, r, c, 0, expr_type);
5416 /* parse an initializer for type 't' if 'has_init' is true, and
5417 allocate space in local or global data space ('r' is either
5418 VT_LOCAL or VT_CONST). The allocated address in returned */
5419 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init)
5421 int size, align, addr, tok1, data_offset;
5422 int *init_str, init_len, level, *saved_macro_ptr;
5423 Section *sec;
5425 size = type_size(t, &align);
5426 /* If unknown size, we must evaluate it before
5427 evaluating initializers because
5428 initializers can generate global data too
5429 (e.g. string pointers or ISOC99 compound
5430 literals). It also simplifies local
5431 initializers handling */
5432 init_len = 0;
5433 init_str = NULL;
5434 saved_macro_ptr = NULL; /* avoid warning */
5435 tok1 = 0;
5436 if (size < 0) {
5437 if (!has_init)
5438 error("unknown type size");
5439 /* get all init string */
5440 level = 0;
5441 while (level > 0 || (tok != ',' && tok != ';')) {
5442 if (tok < 0)
5443 error("unexpected end of file in initializer");
5444 tok_add2(&init_str, &init_len, tok, &tokc);
5445 if (tok == '{')
5446 level++;
5447 else if (tok == '}') {
5448 if (level == 0)
5449 break;
5450 level--;
5452 next();
5454 tok1 = tok;
5455 tok_add(&init_str, &init_len, -1);
5456 tok_add(&init_str, &init_len, 0);
5458 /* compute size */
5459 saved_macro_ptr = macro_ptr;
5460 macro_ptr = init_str;
5461 next();
5462 decl_initializer(t, r, 0, 1, 1);
5463 /* prepare second initializer parsing */
5464 macro_ptr = init_str;
5465 next();
5467 /* if still unknown size, error */
5468 size = type_size(t, &align);
5469 if (size < 0)
5470 error("unknown type size");
5472 /* take into account specified alignment if bigger */
5473 if (ad->aligned > align)
5474 align = ad->aligned;
5475 if ((r & VT_VALMASK) == VT_LOCAL) {
5476 if (do_bounds_check && (t & VT_ARRAY))
5477 loc--;
5478 #ifdef TCC_TARGET_IL
5479 /* XXX: ugly patch to allocate local variables for IL, just
5480 for testing */
5481 addr = loc;
5482 loc++;
5483 #else
5484 loc = (loc - size) & -align;
5485 addr = loc;
5486 #endif
5487 /* handles bounds */
5488 /* XXX: currently, since we do only one pass, we cannot track
5489 '&' operators, so we add only arrays */
5490 if (do_bounds_check && (t & VT_ARRAY)) {
5491 int *bounds_ptr;
5492 /* add padding between regions */
5493 loc--;
5494 /* then add local bound info */
5495 bounds_ptr = (int *)lbounds_section->data_ptr;
5496 *bounds_ptr++ = addr;
5497 *bounds_ptr++ = size;
5498 lbounds_section->data_ptr = (unsigned char *)bounds_ptr;
5500 } else {
5501 /* compute section */
5502 sec = ad->section;
5503 if (!sec) {
5504 if (has_init)
5505 sec = data_section;
5506 else
5507 sec = bss_section;
5509 data_offset = (int)sec->data_ptr;
5510 data_offset = (data_offset + align - 1) & -align;
5511 addr = data_offset;
5512 /* very important to increment global
5513 pointer at this time because
5514 initializers themselves can create new
5515 initializers */
5516 data_offset += size;
5517 /* handles bounds */
5518 if (do_bounds_check) {
5519 int *bounds_ptr;
5520 /* first, we need to add at least one byte between each region */
5521 data_offset++;
5522 /* then add global bound info */
5523 bounds_ptr = (int *)bounds_section->data_ptr;
5524 *bounds_ptr++ = addr;
5525 *bounds_ptr++ = size;
5526 bounds_section->data_ptr = (unsigned char *)bounds_ptr;
5528 sec->data_ptr = (unsigned char *)data_offset;
5530 if (has_init) {
5531 decl_initializer(t, r, addr, 1, 0);
5532 /* restore parse state if needed */
5533 if (init_str) {
5534 free(init_str);
5535 macro_ptr = saved_macro_ptr;
5536 tok = tok1;
5539 return addr;
5542 void put_func_debug(int t)
5544 int bind;
5545 char buf[512];
5547 if (t & VT_STATIC)
5548 bind = STB_LOCAL;
5549 else
5550 bind = STB_GLOBAL;
5551 put_elf_sym(symtab_section, ind, 0,
5552 ELF32_ST_INFO(bind, STT_FUNC), 0,
5553 cur_text_section->sh_num, funcname);
5554 /* stabs info */
5555 /* XXX: we put here a dummy type */
5556 snprintf(buf, sizeof(buf), "%s:%c1",
5557 funcname, t & VT_STATIC ? 'f' : 'F');
5558 put_stabs(buf, N_FUN, 0, file->line_num, ind);
5559 func_ind = ind;
5560 last_ind = 0;
5561 last_line_num = 0;
5564 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5565 void decl(int l)
5567 int t, b, v, addr, has_init, r;
5568 Sym *sym;
5569 AttributeDef ad;
5571 while (1) {
5572 if (!parse_btype(&b, &ad)) {
5573 /* skip redundant ';' */
5574 /* XXX: find more elegant solution */
5575 if (tok == ';') {
5576 next();
5577 continue;
5579 /* special test for old K&R protos without explicit int
5580 type. Only accepted when defining global data */
5581 if (l == VT_LOCAL || tok < TOK_DEFINE)
5582 break;
5583 b = VT_INT;
5585 if (((b & VT_BTYPE) == VT_ENUM ||
5586 (b & VT_BTYPE) == VT_STRUCT) &&
5587 tok == ';') {
5588 /* we accept no variable after */
5589 next();
5590 continue;
5592 while (1) { /* iterate thru each declaration */
5593 t = type_decl(&ad, &v, b, TYPE_DIRECT);
5594 #if 0
5596 char buf[500];
5597 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
5598 printf("type = '%s'\n", buf);
5600 #endif
5601 if (tok == '{') {
5602 if (l == VT_LOCAL)
5603 error("cannot use local functions");
5604 if (!(t & VT_FUNC))
5605 expect("function definition");
5606 /* compute text section */
5607 cur_text_section = ad.section;
5608 if (!cur_text_section)
5609 cur_text_section = text_section;
5610 ind = (int)cur_text_section->data_ptr;
5611 /* patch forward references */
5612 if ((sym = sym_find(v)) && (sym->r & VT_FORWARD)) {
5613 greloc_patch(sym, ind);
5614 sym->t = t;
5615 } else {
5616 /* put function address */
5617 sym = sym_push1(&global_stack, v, t, ind);
5619 sym->r = VT_CONST;
5620 funcname = get_tok_str(v, NULL);
5621 /* put debug symbol */
5622 if (do_debug)
5623 put_func_debug(t);
5624 /* push a dummy symbol to enable local sym storage */
5625 sym_push1(&local_stack, 0, 0, 0);
5626 gfunc_prolog(t);
5627 loc = 0;
5628 rsym = 0;
5629 block(NULL, NULL, NULL, NULL, 0);
5630 gsym(rsym);
5631 gfunc_epilog();
5632 cur_text_section->data_ptr = (unsigned char *)ind;
5633 sym_pop(&label_stack, NULL); /* reset label stack */
5634 sym_pop(&local_stack, NULL); /* reset local stack */
5635 /* end of function */
5636 if (do_debug) {
5637 put_stabn(N_FUN, 0, 0, ind - func_ind);
5639 funcname = ""; /* for safety */
5640 func_vt = VT_VOID; /* for safety */
5641 ind = 0; /* for safety */
5642 break;
5643 } else {
5644 if (b & VT_TYPEDEF) {
5645 /* save typedefed type */
5646 /* XXX: test storage specifiers ? */
5647 sym_push(v, t | VT_TYPEDEF, 0, 0);
5648 } else if ((t & VT_BTYPE) == VT_FUNC) {
5649 /* external function definition */
5650 external_sym(v, t, 0);
5651 } else {
5652 /* not lvalue if array */
5653 r = 0;
5654 if (!(t & VT_ARRAY))
5655 r |= VT_LVAL;
5656 if (b & VT_EXTERN) {
5657 /* external variable */
5658 external_sym(v, t, r);
5659 } else {
5660 if (t & VT_STATIC)
5661 r |= VT_CONST;
5662 else
5663 r |= l;
5664 has_init = (tok == '=');
5665 if (has_init)
5666 next();
5667 addr = decl_initializer_alloc(t, &ad, r,
5668 has_init);
5669 if (l == VT_CONST) {
5670 /* global scope: see if already defined */
5671 sym = sym_find(v);
5672 if (!sym)
5673 goto do_def;
5674 if (!is_compatible_types(sym->t, t))
5675 error("incompatible types for redefinition of '%s'",
5676 get_tok_str(v, NULL));
5677 if (!(sym->r & VT_FORWARD))
5678 error("redefinition of '%s'", get_tok_str(v, NULL));
5679 greloc_patch(sym, addr);
5680 } else {
5681 do_def:
5682 sym_push(v, t, r, addr);
5686 if (tok != ',') {
5687 skip(';');
5688 break;
5690 next();
5696 /* put all global symbols in the extern stack and do all the
5697 resolving which can be done without using external symbols from DLLs */
5698 /* XXX: could try to verify types, but would not to save them in
5699 extern_stack too */
5700 void resolve_global_syms(void)
5702 Sym *s, *s1, *ext_sym;
5703 Reloc **p;
5705 s = global_stack.top;
5706 while (s != NULL) {
5707 s1 = s->prev;
5708 /* do not save static or typedefed symbols or types */
5709 if (!(s->t & (VT_STATIC | VT_TYPEDEF)) &&
5710 !(s->v & (SYM_FIELD | SYM_STRUCT)) &&
5711 (s->v < SYM_FIRST_ANOM)) {
5712 ext_sym = sym_find1(&extern_stack, s->v);
5713 if (!ext_sym) {
5714 /* if the symbol do not exist, we simply save it */
5715 ext_sym = sym_push1(&extern_stack, s->v, s->t, s->c);
5716 ext_sym->r = s->r;
5717 } else if (ext_sym->r & VT_FORWARD) {
5718 /* external symbol already exists, but only as forward
5719 definition */
5720 if (!(s->r & VT_FORWARD)) {
5721 /* s is not forward, so we can relocate all symbols */
5722 greloc_patch(ext_sym, s->c);
5723 } else {
5724 /* the two symbols are forward: merge them */
5725 p = (Reloc **)&ext_sym->c;
5726 while (*p != NULL)
5727 p = &(*p)->next;
5728 *p = (Reloc *)s->c;
5730 } else {
5731 /* external symbol already exists and is defined :
5732 patch all references to it */
5733 if (!(s->r & VT_FORWARD))
5734 error("'%s' defined twice", get_tok_str(s->v, NULL));
5735 greloc_patch(s, ext_sym->c);
5738 s = s1;
5742 /* compile a C file. Return non zero if errors. */
5743 int tcc_compile_file(const char *filename1)
5745 Sym *define_start;
5746 char buf[512];
5748 funcname = "";
5750 file = tcc_open(filename1);
5751 if (!file)
5752 error("file '%s' not found", filename1);
5753 include_stack_ptr = include_stack;
5754 ifdef_stack_ptr = ifdef_stack;
5756 vtop = vstack - 1;
5757 anon_sym = SYM_FIRST_ANOM;
5759 /* file info: full path + filename */
5760 if (do_debug) {
5761 getcwd(buf, sizeof(buf));
5762 pstrcat(buf, sizeof(buf), "/");
5763 put_stabs(buf, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5764 put_stabs(file->filename, N_SO, 0, 0,
5765 (unsigned long)text_section->data_ptr);
5767 /* define common 'char *' type because it is often used internally
5768 for arrays and struct dereference */
5769 char_pointer_type = mk_pointer(VT_BYTE);
5771 define_start = define_stack.top;
5772 inp();
5773 ch = '\n'; /* needed to parse correctly first preprocessor command */
5774 next();
5775 decl(VT_CONST);
5776 if (tok != -1)
5777 expect("declaration");
5778 tcc_close(file);
5780 /* end of translation unit info */
5781 if (do_debug) {
5782 put_stabn(N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5785 /* reset define stack, but leave -Dsymbols (may be incorrect if
5786 they are undefined) */
5787 sym_pop(&define_stack, define_start);
5789 resolve_global_syms();
5791 sym_pop(&global_stack, NULL);
5793 return 0;
5796 /* define a symbol. A value can also be provided with the '=' operator */
5797 /* XXX: currently only handles integers and string defines. should use
5798 tcc parser, but would need a custom 'FILE *' */
5799 void define_symbol(const char *sym)
5801 char *p;
5802 BufferedFile bf1, *bf = &bf1;
5804 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
5805 p = strchr(bf->buffer, '=');
5806 if (!p) {
5807 /* default value */
5808 pstrcat(bf->buffer, IO_BUF_SIZE, " 1");
5809 } else {
5810 *p = ' ';
5813 /* init file structure */
5814 bf->fd = -1;
5815 bf->buf_ptr = bf->buffer;
5816 bf->buf_end = bf->buffer + strlen(bf->buffer);
5817 bf->filename[0] = '\0';
5818 bf->line_num = 1;
5819 file = bf;
5821 include_stack_ptr = include_stack;
5823 /* parse with define parser */
5824 inp();
5825 ch = '\n'; /* needed to parse correctly first preprocessor command */
5826 next_nomacro();
5827 parse_define();
5828 file = NULL;
5831 void undef_symbol(const char *sym)
5833 TokenSym *ts;
5834 Sym *s;
5835 ts = tok_alloc(sym, 0);
5836 s = sym_find1(&define_stack, tok);
5837 /* undefine symbol by putting an invalid name */
5838 if (s)
5839 sym_undef(&define_stack, s);
5842 /* open a dynamic library so that its symbol are available for
5843 compiled programs */
5844 void open_dll(char *libname)
5846 char buf[1024];
5847 void *h;
5849 snprintf(buf, sizeof(buf), "lib%s.so", libname);
5850 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
5851 if (!h)
5852 error((char *)dlerror());
5855 static void *resolve_sym(const char *sym)
5857 void *ptr;
5858 if (do_bounds_check) {
5859 ptr = bound_resolve_sym(sym);
5860 if (ptr)
5861 return ptr;
5863 return dlsym(NULL, sym);
5866 void resolve_extern_syms(void)
5868 Sym *s, *s1;
5869 char *str;
5870 int addr;
5872 s = extern_stack.top;
5873 while (s != NULL) {
5874 s1 = s->prev;
5875 if (s->r & VT_FORWARD) {
5876 /* if there is at least one relocation to do, then find it
5877 and patch it */
5878 if (s->c) {
5879 str = get_tok_str(s->v, NULL);
5880 addr = (int)resolve_sym(str);
5881 if (!addr)
5882 error("unresolved external reference '%s'", str);
5883 greloc_patch(s, addr);
5886 s = s1;
5890 static int put_elf_str(Section *s, const char *sym)
5892 int c, offset;
5893 offset = s->data_ptr - s->data;
5894 for(;;) {
5895 c = *sym++;
5896 *s->data_ptr++ = c;
5897 if (c == '\0')
5898 break;
5900 return offset;
5903 static void put_elf_sym(Section *s,
5904 unsigned long value, unsigned long size,
5905 int info, int other, int shndx, const char *name)
5907 int name_offset;
5908 Elf32_Sym *sym;
5910 sym = (Elf32_Sym *)s->data_ptr;
5911 if (name)
5912 name_offset = put_elf_str(s->link, name);
5913 else
5914 name_offset = 0;
5915 sym->st_name = name_offset;
5916 sym->st_value = value;
5917 sym->st_size = size;
5918 sym->st_info = info;
5919 sym->st_other = other;
5920 sym->st_shndx = shndx;
5921 s->data_ptr += sizeof(Elf32_Sym);
5924 /* put stab debug information */
5926 typedef struct {
5927 unsigned long n_strx; /* index into string table of name */
5928 unsigned char n_type; /* type of symbol */
5929 unsigned char n_other; /* misc info (usually empty) */
5930 unsigned short n_desc; /* description field */
5931 unsigned long n_value; /* value of symbol */
5932 } Stab_Sym;
5934 static void put_stabs(const char *str, int type, int other, int desc, int value)
5936 Stab_Sym *sym;
5938 sym = (Stab_Sym *)stab_section->data_ptr;
5939 if (str) {
5940 sym->n_strx = put_elf_str(stabstr_section, str);
5941 } else {
5942 sym->n_strx = 0;
5944 sym->n_type = type;
5945 sym->n_other = other;
5946 sym->n_desc = desc;
5947 sym->n_value = value;
5949 stab_section->data_ptr += sizeof(Stab_Sym);
5952 static void put_stabn(int type, int other, int desc, int value)
5954 put_stabs(NULL, type, other, desc, value);
5957 static void put_stabd(int type, int other, int desc)
5959 put_stabs(NULL, type, other, desc, 0);
5962 /* output an ELF file (currently, only for testing) */
5963 /* XXX: generate dynamic reloc info + DLL tables */
5964 /* XXX: generate startup code */
5965 /* XXX: better program header generation */
5966 /* XXX: handle realloc'ed sections (instead of mmaping them) */
5967 void build_exe(char *filename)
5969 Elf32_Ehdr ehdr;
5970 FILE *f;
5971 int shnum, i, phnum, file_offset, offset, size, j;
5972 Section *sec, *strsec;
5973 Elf32_Shdr *shdr, *sh;
5974 Elf32_Phdr *phdr, *ph;
5976 memset(&ehdr, 0, sizeof(ehdr));
5978 /* we add a section for symbols */
5979 strsec = new_section(".shstrtab", SHT_STRTAB, 0);
5980 put_elf_str(strsec, "");
5982 /* count number of sections and compute number of program segments */
5983 shnum = 1; /* section index zero is reserved */
5984 phnum = 0;
5985 for(sec = first_section; sec != NULL; sec = sec->next) {
5986 shnum++;
5987 if (sec->sh_flags & SHF_ALLOC)
5988 phnum++;
5990 /* allocate section headers */
5991 shdr = malloc(shnum * sizeof(Elf32_Shdr));
5992 if (!shdr)
5993 error("memory full");
5994 memset(shdr, 0, shnum * sizeof(Elf32_Shdr));
5995 /* allocate program segment headers */
5996 phdr = malloc(phnum * sizeof(Elf32_Phdr));
5997 if (!phdr)
5998 error("memory full");
5999 memset(phdr, 0, phnum * sizeof(Elf32_Phdr));
6001 /* XXX: find correct load order */
6002 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
6003 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
6004 sh = &shdr[i];
6005 sh->sh_name = put_elf_str(strsec, sec->name);
6006 sh->sh_type = sec->sh_type;
6007 sh->sh_flags = sec->sh_flags;
6008 sh->sh_entsize = sec->sh_entsize;
6009 if (sec->link)
6010 sh->sh_link = sec->link->sh_num;
6011 if (sh->sh_type == SHT_STRTAB) {
6012 sh->sh_addralign = 1;
6013 } else if (sh->sh_type == SHT_SYMTAB ||
6014 (sh->sh_flags & SHF_ALLOC) == 0) {
6015 sh->sh_addralign = 4;
6016 } else {
6017 sh->sh_addr = (Elf32_Word)sec->data;
6018 sh->sh_addralign = 4096;
6020 sh->sh_size = (Elf32_Word)sec->data_ptr - (Elf32_Word)sec->data;
6021 /* align to section start */
6022 file_offset = (file_offset + sh->sh_addralign - 1) &
6023 ~(sh->sh_addralign - 1);
6024 sh->sh_offset = file_offset;
6025 file_offset += sh->sh_size;
6027 /* build program headers (simplistic - not fully correct) */
6028 j = 0;
6029 for(i=1;i<shnum;i++) {
6030 sh = &shdr[i];
6031 if (sh->sh_type == SHT_PROGBITS &&
6032 (sh->sh_flags & SHF_ALLOC) != 0) {
6033 ph = &phdr[j++];
6034 ph->p_type = PT_LOAD;
6035 ph->p_offset = sh->sh_offset;
6036 ph->p_vaddr = sh->sh_addr;
6037 ph->p_paddr = ph->p_vaddr;
6038 ph->p_filesz = sh->sh_size;
6039 ph->p_memsz = sh->sh_size;
6040 ph->p_flags = PF_R;
6041 if (sh->sh_flags & SHF_WRITE)
6042 ph->p_flags |= PF_W;
6043 if (sh->sh_flags & SHF_EXECINSTR)
6044 ph->p_flags |= PF_X;
6045 ph->p_align = sh->sh_addralign;
6049 /* align to 4 */
6050 file_offset = (file_offset + 3) & -4;
6052 /* fill header */
6053 ehdr.e_ident[0] = ELFMAG0;
6054 ehdr.e_ident[1] = ELFMAG1;
6055 ehdr.e_ident[2] = ELFMAG2;
6056 ehdr.e_ident[3] = ELFMAG3;
6057 ehdr.e_ident[4] = ELFCLASS32;
6058 ehdr.e_ident[5] = ELFDATA2LSB;
6059 ehdr.e_ident[6] = EV_CURRENT;
6060 ehdr.e_type = ET_EXEC;
6061 ehdr.e_machine = EM_386;
6062 ehdr.e_version = EV_CURRENT;
6063 ehdr.e_entry = 0; /* XXX: patch it */
6064 ehdr.e_phoff = sizeof(Elf32_Ehdr);
6065 ehdr.e_shoff = file_offset;
6066 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
6067 ehdr.e_phentsize = sizeof(Elf32_Phdr);
6068 ehdr.e_phnum = phnum;
6069 ehdr.e_shentsize = sizeof(Elf32_Shdr);
6070 ehdr.e_shnum = shnum;
6071 ehdr.e_shstrndx = shnum - 1;
6073 /* write elf file */
6074 f = fopen(filename, "w");
6075 if (!f)
6076 error("could not write '%s'", filename);
6077 fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
6078 fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
6079 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
6080 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
6081 sh = &shdr[i];
6082 while (offset < sh->sh_offset) {
6083 fputc(0, f);
6084 offset++;
6086 size = sec->data_ptr - sec->data;
6087 fwrite(sec->data, 1, size, f);
6088 offset += size;
6090 while (offset < ehdr.e_shoff) {
6091 fputc(0, f);
6092 offset++;
6094 fwrite(shdr, 1, shnum * sizeof(Elf32_Shdr), f);
6095 fclose(f);
6098 /* print the position in the source file of PC value 'pc' by reading
6099 the stabs debug information */
6100 static void rt_printline(unsigned long wanted_pc)
6102 Stab_Sym *sym, *sym_end;
6103 char func_name[128];
6104 unsigned long func_addr, last_pc, pc;
6105 const char *incl_files[INCLUDE_STACK_SIZE];
6106 int incl_index, len, last_line_num, i;
6107 const char *str, *p;
6109 func_name[0] = '\0';
6110 func_addr = 0;
6111 incl_index = 0;
6112 last_pc = 0xffffffff;
6113 last_line_num = 1;
6114 sym = (Stab_Sym *)stab_section->data + 1;
6115 sym_end = (Stab_Sym *)stab_section->data_ptr;
6116 while (sym < sym_end) {
6117 switch(sym->n_type) {
6118 /* function start or end */
6119 case N_FUN:
6120 if (sym->n_strx == 0) {
6121 func_name[0] = '\0';
6122 func_addr = 0;
6123 } else {
6124 str = stabstr_section->data + sym->n_strx;
6125 p = strchr(str, ':');
6126 if (!p) {
6127 pstrcpy(func_name, sizeof(func_name), str);
6128 } else {
6129 len = p - str;
6130 if (len > sizeof(func_name) - 1)
6131 len = sizeof(func_name) - 1;
6132 memcpy(func_name, str, len);
6133 func_name[len] = '\0';
6135 func_addr = sym->n_value;
6137 break;
6138 /* line number info */
6139 case N_SLINE:
6140 pc = sym->n_value + func_addr;
6141 if (wanted_pc >= last_pc && wanted_pc < pc)
6142 goto found;
6143 last_pc = pc;
6144 last_line_num = sym->n_desc;
6145 break;
6146 /* include files */
6147 case N_BINCL:
6148 str = stabstr_section->data + sym->n_strx;
6149 add_incl:
6150 if (incl_index < INCLUDE_STACK_SIZE) {
6151 incl_files[incl_index++] = str;
6153 break;
6154 case N_EINCL:
6155 if (incl_index > 1)
6156 incl_index--;
6157 break;
6158 case N_SO:
6159 if (sym->n_strx == 0) {
6160 incl_index = 0; /* end of translation unit */
6161 } else {
6162 str = stabstr_section->data + sym->n_strx;
6163 /* do not add path */
6164 len = strlen(str);
6165 if (len > 0 && str[len - 1] != '/')
6166 goto add_incl;
6168 break;
6170 sym++;
6172 /* did not find line number info: */
6173 fprintf(stderr, "(no debug info, pc=0x%08lx): ", wanted_pc);
6174 return;
6175 found:
6176 for(i = 0; i < incl_index - 1; i++)
6177 fprintf(stderr, "In file included from %s\n",
6178 incl_files[i]);
6179 if (incl_index > 0) {
6180 fprintf(stderr, "%s:%d: ",
6181 incl_files[incl_index - 1], last_line_num);
6183 if (func_name[0] != '\0') {
6184 fprintf(stderr, "in function '%s()': ", func_name);
6188 /* emit a run time error at position 'pc' */
6189 void rt_error(unsigned long pc, const char *fmt, ...)
6191 va_list ap;
6192 va_start(ap, fmt);
6194 rt_printline(pc);
6195 vfprintf(stderr, fmt, ap);
6196 fprintf(stderr, "\n");
6197 exit(255);
6198 va_end(ap);
6201 #ifndef WIN32
6202 /* signal handler for fatal errors */
6203 static void sig_error(int signum, siginfo_t *siginf, void *puc)
6205 struct ucontext *uc = puc;
6206 unsigned long pc;
6208 #ifdef __i386__
6209 pc = uc->uc_mcontext.gregs[14];
6210 #else
6211 #error please put the right sigcontext field
6212 #endif
6214 switch(signum) {
6215 case SIGFPE:
6216 switch(siginf->si_code) {
6217 case FPE_INTDIV:
6218 case FPE_FLTDIV:
6219 rt_error(pc, "division by zero");
6220 break;
6221 default:
6222 rt_error(pc, "floating point exception");
6223 break;
6225 break;
6226 case SIGBUS:
6227 case SIGSEGV:
6228 rt_error(pc, "dereferencing invalid pointer");
6229 break;
6230 case SIGILL:
6231 rt_error(pc, "illegal instruction");
6232 break;
6233 case SIGABRT:
6234 rt_error(pc, "abort() called");
6235 break;
6236 default:
6237 rt_error(pc, "caught signal %d", signum);
6238 break;
6240 exit(255);
6242 #endif
6244 /* launch the compiled program with the given arguments */
6245 int launch_exe(int argc, char **argv)
6247 Sym *s;
6248 int (*t)();
6250 s = sym_find1(&extern_stack, TOK_MAIN);
6251 if (!s || (s->r & VT_FORWARD))
6252 error("main() not defined");
6254 if (do_debug) {
6255 #ifdef WIN32
6256 error("debug mode currently not available for Windows");
6257 #else
6258 struct sigaction sigact;
6259 /* install TCC signal handlers to print debug info on fatal
6260 runtime errors */
6261 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
6262 sigact.sa_sigaction = sig_error;
6263 sigemptyset(&sigact.sa_mask);
6264 sigaction(SIGFPE, &sigact, NULL);
6265 sigaction(SIGILL, &sigact, NULL);
6266 sigaction(SIGSEGV, &sigact, NULL);
6267 sigaction(SIGBUS, &sigact, NULL);
6268 sigaction(SIGABRT, &sigact, NULL);
6269 #endif
6272 if (do_bounds_check) {
6273 #ifdef WIN32
6274 error("bound checking currently not available for Windows");
6275 #else
6276 int *p, *p_end;
6277 __bound_init();
6278 /* add all known static regions */
6279 p = (int *)bounds_section->data;
6280 p_end = (int *)bounds_section->data_ptr;
6281 while (p < p_end) {
6282 __bound_new_region((void *)p[0], p[1]);
6283 p += 2;
6285 #endif
6288 t = (int (*)())s->c;
6289 return (*t)(argc, argv);
6293 void help(void)
6295 printf("tcc version 0.9.4 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
6296 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
6297 " [-i infile] infile [infile_args...]\n"
6298 "\n"
6299 "-Idir : add include path 'dir'\n"
6300 "-Dsym[=val] : define 'sym' with value 'val'\n"
6301 "-Usym : undefine 'sym'\n"
6302 "-llib : link with dynamic library 'lib'\n"
6303 "-g : generate runtime debug info\n"
6304 "-b : compile with built-in memory and bounds checker (implies -g)\n"
6305 "-i infile : compile infile\n"
6309 int main(int argc, char **argv)
6311 char *p, *r, *outfile;
6312 int optind;
6314 include_paths[0] = "/usr/include";
6315 include_paths[1] = "/usr/lib/tcc";
6316 include_paths[2] = "/usr/local/lib/tcc";
6317 nb_include_paths = 3;
6319 /* add all tokens */
6320 tok_ident = TOK_IDENT;
6321 p = tcc_keywords;
6322 while (*p) {
6323 r = p;
6324 while (*r++);
6325 tok_alloc(p, r - p - 1);
6326 p = r;
6329 /* standard defines */
6330 define_symbol("__STDC__");
6331 #ifdef __i386__
6332 define_symbol("__i386__");
6333 #endif
6334 /* tiny C specific defines */
6335 define_symbol("__TINYC__");
6337 /* create standard sections */
6338 text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
6339 data_section = new_section(".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6340 /* XXX: should change type to SHT_NOBITS */
6341 bss_section = new_section(".bss", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6343 optind = 1;
6344 outfile = NULL;
6345 while (1) {
6346 if (optind >= argc) {
6347 show_help:
6348 help();
6349 return 1;
6351 r = argv[optind];
6352 if (r[0] != '-')
6353 break;
6354 optind++;
6355 if (r[1] == 'I') {
6356 if (nb_include_paths >= INCLUDE_PATHS_MAX)
6357 error("too many include paths");
6358 include_paths[nb_include_paths++] = r + 2;
6359 } else if (r[1] == 'D') {
6360 define_symbol(r + 2);
6361 } else if (r[1] == 'U') {
6362 undef_symbol(r + 2);
6363 } else if (r[1] == 'l') {
6364 open_dll(r + 2);
6365 } else if (r[1] == 'i') {
6366 if (optind >= argc)
6367 goto show_help;
6368 tcc_compile_file(argv[optind++]);
6369 } else if (!strcmp(r + 1, "bench")) {
6370 do_bench = 1;
6371 } else if (r[1] == 'b') {
6372 if (!do_bounds_check) {
6373 do_bounds_check = 1;
6374 /* define symbol */
6375 define_symbol("__BOUNDS_CHECKING_ON");
6376 /* create bounds sections */
6377 bounds_section = new_section(".bounds",
6378 SHT_PROGBITS, SHF_ALLOC);
6379 lbounds_section = new_section(".lbounds",
6380 SHT_PROGBITS, SHF_ALLOC);
6381 /* debug is implied */
6382 goto debug_opt;
6384 } else if (r[1] == 'g') {
6385 debug_opt:
6386 if (!do_debug) {
6387 do_debug = 1;
6389 /* stab symbols */
6390 stab_section = new_section(".stab", SHT_PROGBITS, 0);
6391 stab_section->sh_entsize = sizeof(Stab_Sym);
6392 stabstr_section = new_section(".stabstr", SHT_STRTAB, 0);
6393 put_elf_str(stabstr_section, "");
6394 stab_section->link = stabstr_section;
6395 /* put first entry */
6396 put_stabs("", 0, 0, 0, 0);
6398 /* elf symbols */
6399 symtab_section = new_section(".symtab", SHT_SYMTAB, 0);
6400 symtab_section->sh_entsize = sizeof(Elf32_Sym);
6401 strtab_section = new_section(".strtab", SHT_STRTAB, 0);
6402 put_elf_str(strtab_section, "");
6403 symtab_section->link = strtab_section;
6404 put_elf_sym(symtab_section, 0, 0, 0, 0, 0, NULL);
6406 } else if (r[1] == 'o') {
6407 /* currently, only for testing, so not documented */
6408 if (optind >= argc)
6409 goto show_help;
6410 outfile = argv[optind++];
6411 } else {
6412 fprintf(stderr, "invalid option -- '%s'\n", r);
6413 exit(1);
6417 tcc_compile_file(argv[optind]);
6419 if (do_bench) {
6420 printf("total: %d idents, %d lines, %d bytes\n",
6421 tok_ident - TOK_IDENT, total_lines, total_bytes);
6424 resolve_extern_syms();
6426 if (outfile) {
6427 build_exe(outfile);
6428 return 0;
6429 } else {
6430 return launch_exe(argc - optind, argv + optind);