added tcc finite math function to avoid portability problems
[tinycc.git] / tcc.c
blob7ed803f6ba38aead5daa3bc09434863f53d7f3e7
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 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_IL)
55 #define CONFIG_TCC_BCHECK /* enable bound checking code */
56 #endif
58 /* amount of virtual memory associated to a section (currently, we do
59 not realloc them) */
60 #define SECTION_VSIZE (1024 * 1024)
62 #define INCLUDE_STACK_SIZE 32
63 #define IFDEF_STACK_SIZE 64
64 #define VSTACK_SIZE 64
65 #define STRING_MAX_SIZE 1024
66 #define INCLUDE_PATHS_MAX 32
68 #define TOK_HASH_SIZE 2048 /* must be a power of two */
69 #define TOK_ALLOC_INCR 512 /* must be a power of two */
70 #define SYM_HASH_SIZE 1031
72 /* token symbol management */
73 typedef struct TokenSym {
74 struct TokenSym *hash_next;
75 int tok; /* token number */
76 int len;
77 char str[1];
78 } TokenSym;
80 /* constant value */
81 typedef union CValue {
82 long double ld;
83 double d;
84 float f;
85 int i;
86 unsigned int ui;
87 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
88 long long ll;
89 unsigned long long ull;
90 struct TokenSym *ts;
91 struct Sym *sym;
92 int tab[1];
93 } CValue;
95 /* value on stack */
96 typedef struct SValue {
97 int t; /* type */
98 unsigned short r; /* register + flags */
99 unsigned short r2; /* second register, used for 'long long'
100 type. If not used, set to VT_CONST */
101 CValue c; /* constant */
102 } SValue;
104 /* symbol management */
105 typedef struct Sym {
106 int v; /* symbol token */
107 int t; /* associated type */
108 int r; /* associated register */
109 int c; /* associated number */
110 struct Sym *next; /* next related symbol */
111 struct Sym *prev; /* prev symbol in stack */
112 struct Sym *hash_next; /* next symbol in hash table */
113 } Sym;
115 typedef struct SymStack {
116 struct Sym *top;
117 struct Sym *hash[SYM_HASH_SIZE];
118 } SymStack;
120 /* relocation entry (currently only used for functions or variables */
121 typedef struct Reloc {
122 int type; /* type of relocation */
123 int addr; /* address of relocation */
124 struct Reloc *next; /* next relocation */
125 } Reloc;
127 #define RELOC_ADDR32 1 /* 32 bits relocation */
128 #define RELOC_REL32 2 /* 32 bits relative relocation */
130 /* section definition */
131 typedef struct Section {
132 char name[64]; /* section name */
133 unsigned char *data; /* section data */
134 unsigned char *data_ptr; /* current data pointer */
135 int sh_num; /* elf section number */
136 int sh_type; /* elf section type */
137 int sh_flags; /* elf section flags */
138 int sh_entsize; /* elf entry size */
139 struct Section *link; /* link to another section */
140 struct Section *next;
141 } Section;
143 /* GNUC attribute definition */
144 typedef struct AttributeDef {
145 int aligned;
146 Section *section;
147 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
148 } AttributeDef;
150 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
151 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
152 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
154 /* stored in 'Sym.c' field */
155 #define FUNC_NEW 1 /* ansi function prototype */
156 #define FUNC_OLD 2 /* old function prototype */
157 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
159 /* stored in 'Sym.r' field */
160 #define FUNC_CDECL 0 /* standard c call */
161 #define FUNC_STDCALL 1 /* pascal c call */
163 /* field 'Sym.t' for macros */
164 #define MACRO_OBJ 0 /* object like macro */
165 #define MACRO_FUNC 1 /* function like macro */
167 /* type_decl() types */
168 #define TYPE_ABSTRACT 1 /* type without variable */
169 #define TYPE_DIRECT 2 /* type with variable */
171 #define IO_BUF_SIZE 8192
173 typedef struct BufferedFile {
174 unsigned char *buf_ptr;
175 unsigned char *buf_end;
176 int fd;
177 int line_num; /* current line number - here to simply code */
178 char filename[1024]; /* current filename - here to simply code */
179 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
180 } BufferedFile;
182 #define CH_EOB 0 /* end of buffer or '\0' char in file */
183 #define CH_EOF (-1) /* end of file */
185 /* parser */
186 struct BufferedFile *file;
187 int ch, ch1, tok, tok1;
188 CValue tokc, tok1c;
190 /* sections */
191 Section *first_section;
192 int section_num;
193 Section *text_section, *data_section, *bss_section; /* predefined sections */
194 Section *cur_text_section; /* current section where function code is
195 generated */
196 /* bound check related sections */
197 Section *bounds_section; /* contains global data bound description */
198 Section *lbounds_section; /* contains local data bound description */
199 /* debug sections */
200 Section *stab_section, *stabstr_section, *symtab_section, *strtab_section;
202 /* loc : local variable index
203 ind : output code index
204 rsym: return symbol
205 anon_sym: anonymous symbol index
207 int rsym, anon_sym,
208 prog, ind, loc, const_wanted;
209 int global_expr; /* true if compound literals must be allocated
210 globally (used during initializers parsing */
211 int func_vt, func_vc; /* current function return type (used by
212 return instruction) */
213 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
214 int tok_ident;
215 TokenSym **table_ident;
216 TokenSym *hash_ident[TOK_HASH_SIZE];
217 char token_buf[STRING_MAX_SIZE + 1];
218 char *funcname;
219 /* contains global symbols which remain between each translation unit */
220 SymStack extern_stack;
221 SymStack define_stack, global_stack, local_stack, label_stack;
223 SValue vstack[VSTACK_SIZE], *vtop;
224 int *macro_ptr, *macro_ptr_allocated;
225 BufferedFile *include_stack[INCLUDE_STACK_SIZE], **include_stack_ptr;
226 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
227 char *include_paths[INCLUDE_PATHS_MAX];
228 int nb_include_paths;
229 int char_pointer_type;
231 /* compile with debug symbol (and use them if error during execution) */
232 int do_debug = 0;
234 /* compile with built-in memory and bounds checker */
235 int do_bounds_check = 0;
237 /* display benchmark infos */
238 int do_bench = 0;
239 int total_lines;
240 int total_bytes;
242 /* use GNU C extensions */
243 int gnu_ext = 1;
245 /* use Tiny C extensions */
246 int tcc_ext = 1;
248 /* The current value can be: */
249 #define VT_VALMASK 0x00ff
250 #define VT_CONST 0x00f0 /* constant in vc
251 (must be first non register value) */
252 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
253 #define VT_LOCAL 0x00f2 /* offset on stack */
254 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
255 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
256 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
257 #define VT_LVAL 0x0100 /* var is an lvalue */
258 #define VT_FORWARD 0x0200 /* value is forward reference */
259 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
260 char/short stored in integer registers) */
261 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
262 dereferencing value */
264 /* types */
265 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
267 #define VT_INT 0 /* integer type */
268 #define VT_BYTE 1 /* signed byte type */
269 #define VT_SHORT 2 /* short type */
270 #define VT_VOID 3 /* void type */
271 #define VT_PTR 4 /* pointer increment */
272 #define VT_ENUM 5 /* enum definition */
273 #define VT_FUNC 6 /* function type */
274 #define VT_STRUCT 7 /* struct/union definition */
275 #define VT_FLOAT 8 /* IEEE float */
276 #define VT_DOUBLE 9 /* IEEE double */
277 #define VT_LDOUBLE 10 /* IEEE long double */
278 #define VT_BOOL 11 /* ISOC99 boolean type */
279 #define VT_LLONG 12 /* 64 bit integer */
280 #define VT_LONG 13 /* long integer (NEVER USED as type, only
281 during parsing) */
282 #define VT_BTYPE 0x000f /* mask for basic type */
283 #define VT_UNSIGNED 0x0010 /* unsigned type */
284 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
285 #define VT_BITFIELD 0x0040 /* bitfield modifier */
287 /* storage */
288 #define VT_EXTERN 0x00000080 /* extern definition */
289 #define VT_STATIC 0x00000100 /* static variable */
290 #define VT_TYPEDEF 0x00000200 /* typedef definition */
292 /* type mask (except storage) */
293 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
295 /* token values */
297 /* warning: the following compare tokens depend on i386 asm code */
298 #define TOK_ULT 0x92
299 #define TOK_UGE 0x93
300 #define TOK_EQ 0x94
301 #define TOK_NE 0x95
302 #define TOK_ULE 0x96
303 #define TOK_UGT 0x97
304 #define TOK_LT 0x9c
305 #define TOK_GE 0x9d
306 #define TOK_LE 0x9e
307 #define TOK_GT 0x9f
309 #define TOK_LAND 0xa0
310 #define TOK_LOR 0xa1
312 #define TOK_DEC 0xa2
313 #define TOK_MID 0xa3 /* inc/dec, to void constant */
314 #define TOK_INC 0xa4
315 #define TOK_UDIV 0xb0 /* unsigned division */
316 #define TOK_UMOD 0xb1 /* unsigned modulo */
317 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
318 #define TOK_CINT 0xb3 /* number in tokc */
319 #define TOK_CCHAR 0xb4 /* char constant in tokc */
320 #define TOK_STR 0xb5 /* pointer to string in tokc */
321 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
322 #define TOK_LCHAR 0xb7
323 #define TOK_LSTR 0xb8
324 #define TOK_CFLOAT 0xb9 /* float constant */
325 #define TOK_CDOUBLE 0xc0 /* double constant */
326 #define TOK_CLDOUBLE 0xc1 /* long double constant */
327 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
328 #define TOK_ADDC1 0xc3 /* add with carry generation */
329 #define TOK_ADDC2 0xc4 /* add with carry use */
330 #define TOK_SUBC1 0xc5 /* add with carry generation */
331 #define TOK_SUBC2 0xc6 /* add with carry use */
332 #define TOK_CUINT 0xc8 /* unsigned int constant */
333 #define TOK_CLLONG 0xc9 /* long long constant */
334 #define TOK_CULLONG 0xca /* unsigned long long constant */
335 #define TOK_ARROW 0xcb
336 #define TOK_DOTS 0xcc /* three dots */
337 #define TOK_SHR 0xcd /* unsigned shift right */
339 #define TOK_SHL 0x01 /* shift left */
340 #define TOK_SAR 0x02 /* signed shift right */
342 /* assignement operators : normal operator or 0x80 */
343 #define TOK_A_MOD 0xa5
344 #define TOK_A_AND 0xa6
345 #define TOK_A_MUL 0xaa
346 #define TOK_A_ADD 0xab
347 #define TOK_A_SUB 0xad
348 #define TOK_A_DIV 0xaf
349 #define TOK_A_XOR 0xde
350 #define TOK_A_OR 0xfc
351 #define TOK_A_SHL 0x81
352 #define TOK_A_SAR 0x82
354 #define TOK_EOF (-1) /* end of file */
356 /* all identificators and strings have token above that */
357 #define TOK_IDENT 256
359 enum {
360 TOK_INT = TOK_IDENT,
361 TOK_VOID,
362 TOK_CHAR,
363 TOK_IF,
364 TOK_ELSE,
365 TOK_WHILE,
366 TOK_BREAK,
367 TOK_RETURN,
368 TOK_FOR,
369 TOK_EXTERN,
370 TOK_STATIC,
371 TOK_UNSIGNED,
372 TOK_GOTO,
373 TOK_DO,
374 TOK_CONTINUE,
375 TOK_SWITCH,
376 TOK_CASE,
378 /* ignored types Must have contiguous values */
379 TOK_CONST,
380 TOK_VOLATILE,
381 TOK_LONG,
382 TOK_REGISTER,
383 TOK_SIGNED,
384 TOK___SIGNED__, /* gcc keyword */
385 TOK_AUTO,
386 TOK_INLINE,
387 TOK___INLINE__, /* gcc keyword */
388 TOK_RESTRICT,
390 /* unsupported type */
391 TOK_FLOAT,
392 TOK_DOUBLE,
393 TOK_BOOL,
395 TOK_SHORT,
396 TOK_STRUCT,
397 TOK_UNION,
398 TOK_TYPEDEF,
399 TOK_DEFAULT,
400 TOK_ENUM,
401 TOK_SIZEOF,
402 TOK___ATTRIBUTE__,
404 /* preprocessor only */
405 TOK_UIDENT, /* first "user" ident (not keyword) */
406 TOK_DEFINE = TOK_UIDENT,
407 TOK_INCLUDE,
408 TOK_IFDEF,
409 TOK_IFNDEF,
410 TOK_ELIF,
411 TOK_ENDIF,
412 TOK_DEFINED,
413 TOK_UNDEF,
414 TOK_ERROR,
415 TOK_LINE,
416 TOK___LINE__,
417 TOK___FILE__,
418 TOK___DATE__,
419 TOK___TIME__,
420 TOK___VA_ARGS__,
422 /* special identifiers */
423 TOK___FUNC__,
424 TOK_MAIN,
425 /* attribute identifiers */
426 TOK_SECTION,
427 TOK___SECTION__,
428 TOK_ALIGNED,
429 TOK___ALIGNED__,
430 TOK_UNUSED,
431 TOK___UNUSED__,
432 TOK_CDECL,
433 TOK___CDECL,
434 TOK___CDECL__,
435 TOK_STDCALL,
436 TOK___STDCALL,
437 TOK___STDCALL__,
438 TOK_NORETURN,
439 TOK___NORETURN__,
442 char *tcc_keywords =
443 "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
444 "unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
445 "register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
446 "float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
447 "sizeof\0__attribute__\0"
448 /* the following are not keywords. They are included to ease parsing */
449 "define\0include\0ifdef\0ifndef\0elif\0endif\0"
450 "defined\0undef\0error\0line\0"
451 "__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0"
452 "__func__\0main\0"
453 /* attributes */
454 "section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0"
455 "cdecl\0__cdecl\0__cdecl__\0stdcall\0__stdcall\0__stdcall__\0"
456 "noreturn\0__noreturn__\0"
459 #ifdef WIN32
460 #define snprintf _snprintf
461 #endif
463 #if defined(WIN32) || defined(TCC_UCLIBC)
464 /* currently incorrect */
465 long double strtold(const char *nptr, char **endptr)
467 return (long double)strtod(nptr, endptr);
469 float strtof(const char *nptr, char **endptr)
471 return (float)strtod(nptr, endptr);
473 #else
474 /* XXX: need to define this to use them in non ISOC99 context */
475 extern float strtof (const char *__nptr, char **__endptr);
476 extern long double strtold (const char *__nptr, char **__endptr);
477 #endif
479 char *pstrcpy(char *buf, int buf_size, const char *s);
480 char *pstrcat(char *buf, int buf_size, const char *s);
482 void sum(int l);
483 void next(void);
484 void next_nomacro(void);
485 int expr_const(void);
486 void expr_eq(void);
487 void gexpr(void);
488 void decl(int l);
489 void decl_initializer(int t, int r, int c, int first, int size_only);
490 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init);
491 int gv(int rc);
492 void gv2(int rc1, int rc2);
493 void move_reg(int r, int s);
494 void save_regs(void);
495 void save_reg(int r);
496 void vpop(void);
497 void vswap(void);
498 void vdup(void);
499 int get_reg(int rc);
501 void macro_subst(int **tok_str, int *tok_len,
502 Sym **nested_list, int *macro_str);
503 int save_reg_forced(int r);
504 void gen_op(int op);
505 void force_charshort_cast(int t);
506 void gen_cast(int t);
507 void vstore(void);
508 Sym *sym_find(int v);
509 Sym *sym_push(int v, int t, int r, int c);
511 /* type handling */
512 int type_size(int t, int *a);
513 int pointed_type(int t);
514 int pointed_size(int t);
515 int is_compatible_types(int t1, int t2);
516 int parse_btype(int *type_ptr, AttributeDef *ad);
517 int type_decl(AttributeDef *ad, int *v, int t, int td);
519 void error(const char *fmt, ...);
520 void rt_error(unsigned long pc, const char *fmt, ...);
521 void vpushi(int v);
522 void vset(int t, int r, int v);
523 void type_to_str(char *buf, int buf_size,
524 int t, const char *varstr);
526 /* section generation */
527 void greloc(Sym *s, int addr, int type);
528 static int put_elf_str(Section *s, const char *sym);
529 static void put_elf_sym(Section *s,
530 unsigned long value, unsigned long size,
531 int info, int other, int shndx, const char *name);
532 static void put_stabs(const char *str, int type, int other, int desc, int value);
533 static void put_stabn(int type, int other, int desc, int value);
534 static void put_stabd(int type, int other, int desc);
536 /* true if float/double/long double type */
537 static inline int is_float(int t)
539 int bt;
540 bt = t & VT_BTYPE;
541 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
544 #ifdef CONFIG_TCC_BCHECK
545 #include "bcheck.c"
546 #endif
548 #ifdef TCC_TARGET_I386
549 #include "i386-gen.c"
550 #endif
551 #ifdef TCC_TARGET_IL
552 #include "il-gen.c"
553 #endif
555 #ifdef CONFIG_TCC_STATIC
557 #define RTLD_LAZY 0x001
558 #define RTLD_NOW 0x002
559 #define RTLD_GLOBAL 0x100
561 /* dummy function for profiling */
562 void *dlopen(const char *filename, int flag)
564 return NULL;
567 const char *dlerror(void)
569 return "error";
572 typedef struct TCCSyms {
573 char *str;
574 void *ptr;
575 } TCCSyms;
577 #define TCCSYM(a) { #a, &a, },
579 /* add the symbol you want here if no dynamic linking is done */
580 static TCCSyms tcc_syms[] = {
581 TCCSYM(printf)
582 TCCSYM(fprintf)
583 TCCSYM(fopen)
584 TCCSYM(fclose)
585 { NULL, NULL },
588 void *dlsym(void *handle, const char *symbol)
590 TCCSyms *p;
591 p = tcc_syms;
592 while (p->str != NULL) {
593 if (!strcmp(p->str, symbol))
594 return p->ptr;
595 p++;
597 return NULL;
600 #endif
602 /********************************************************/
603 /* runtime library is there */
604 /* XXX: we suppose that the host compiler handles 'long long'. It
605 would not be difficult to suppress this assumption */
607 long long __divll(long long a, long long b)
609 return a / b;
612 long long __modll(long long a, long long b)
614 return a % b;
617 unsigned long long __divull(unsigned long long a, unsigned long long b)
619 return a / b;
622 unsigned long long __modull(unsigned long long a, unsigned long long b)
624 return a % b;
627 long long __sardi3(long long a, int b)
629 return a >> b;
632 unsigned long long __shrdi3(unsigned long long a, int b)
634 return a >> b;
637 long long __shldi3(long long a, int b)
639 return a << b;
642 float __ulltof(unsigned long long a)
644 return (float)a;
647 double __ulltod(unsigned long long a)
649 return (double)a;
652 long double __ulltold(unsigned long long a)
654 return (long double)a;
657 unsigned long long __ftoull(float a)
659 return (unsigned long long)a;
662 unsigned long long __dtoull(double a)
664 return (unsigned long long)a;
667 unsigned long long __ldtoull(long double a)
669 return (unsigned long long)a;
673 /********************************************************/
675 /* we use our own 'finite' function to avoid potential problems with
676 non standard math libs */
677 /* XXX: endianness dependant */
678 int ieee_finite(double d)
680 int *p = (int *)&d;
681 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
684 /* copy a string and truncate it. */
685 char *pstrcpy(char *buf, int buf_size, const char *s)
687 char *q, *q_end;
688 int c;
690 if (buf_size > 0) {
691 q = buf;
692 q_end = buf + buf_size - 1;
693 while (q < q_end) {
694 c = *s++;
695 if (c == '\0')
696 break;
697 *q++ = c;
699 *q = '\0';
701 return buf;
704 /* strcat and truncate. */
705 char *pstrcat(char *buf, int buf_size, const char *s)
707 int len;
708 len = strlen(buf);
709 if (len < buf_size)
710 pstrcpy(buf + len, buf_size - len, s);
711 return buf;
714 Section *new_section(const char *name, int sh_type, int sh_flags)
716 Section *sec, **psec;
717 void *data;
719 sec = malloc(sizeof(Section));
720 if (!sec)
721 error("memory full");
722 memset(sec, 0, sizeof(Section));
723 pstrcpy(sec->name, sizeof(sec->name), name);
724 sec->link = NULL;
725 sec->sh_num = ++section_num;
726 sec->sh_type = sh_type;
727 sec->sh_flags = sh_flags;
728 #ifdef WIN32
729 /* XXX: currently, a single malloc */
730 data = malloc(SECTION_VSIZE);
731 if (data == NULL)
732 error("could not alloc section '%s'", name);
733 #else
734 data = mmap(NULL, SECTION_VSIZE,
735 PROT_EXEC | PROT_READ | PROT_WRITE,
736 MAP_PRIVATE | MAP_ANONYMOUS,
737 -1, 0);
738 if (data == (void *)(-1))
739 error("could not mmap section '%s'", name);
740 #endif
741 sec->data = data;
742 sec->data_ptr = data;
743 psec = &first_section;
744 while (*psec != NULL)
745 psec = &(*psec)->next;
746 sec->next = NULL;
747 *psec = sec;
748 return sec;
751 /* return a reference to a section, and create it if it does not
752 exists */
753 Section *find_section(const char *name)
755 Section *sec;
757 for(sec = first_section; sec != NULL; sec = sec->next) {
758 if (!strcmp(name, sec->name))
759 return sec;
761 /* sections are created as PROGBITS */
762 return new_section(name, SHT_PROGBITS, SHF_ALLOC);
765 /* add a new relocation entry to symbol 's' */
766 void greloc(Sym *s, int addr, int type)
768 Reloc *p;
769 p = malloc(sizeof(Reloc));
770 if (!p)
771 error("memory full");
772 p->type = type;
773 p->addr = addr;
774 p->next = (Reloc *)s->c;
775 s->c = (int)p;
778 /* patch each relocation entry with value 'val' */
779 void greloc_patch(Sym *s, int val)
781 Reloc *p, *p1;
783 p = (Reloc *)s->c;
784 while (p != NULL) {
785 p1 = p->next;
786 greloc_patch1(p, val);
787 free(p);
788 p = p1;
790 s->c = val;
791 s->r &= ~VT_FORWARD;
795 static inline int isid(int c)
797 return (c >= 'a' && c <= 'z') ||
798 (c >= 'A' && c <= 'Z') ||
799 c == '_';
802 static inline int isnum(int c)
804 return c >= '0' && c <= '9';
807 static inline int toup(int c)
809 if (ch >= 'a' && ch <= 'z')
810 return ch - 'a' + 'A';
811 else
812 return ch;
815 void printline(void)
817 BufferedFile **f;
818 if (file) {
819 for(f = include_stack; f < include_stack_ptr; f++)
820 fprintf(stderr, "In file included from %s:%d:\n",
821 (*f)->filename, (*f)->line_num);
822 fprintf(stderr, "%s:%d: ", file->filename, file->line_num);
823 } else {
824 fprintf(stderr, "tcc: ");
828 void error(const char *fmt, ...)
830 va_list ap;
831 va_start(ap, fmt);
832 printline();
833 vfprintf(stderr, fmt, ap);
834 fprintf(stderr, "\n");
835 exit(1);
836 va_end(ap);
839 void expect(const char *msg)
841 error("%s expected", msg);
844 void warning(const char *fmt, ...)
846 va_list ap;
848 va_start(ap, fmt);
849 printline();
850 fprintf(stderr, "warning: ");
851 vfprintf(stderr, fmt, ap);
852 fprintf(stderr, "\n");
853 va_end(ap);
856 void skip(int c)
858 if (tok != c)
859 error("'%c' expected", c);
860 next();
863 void test_lvalue(void)
865 if (!(vtop->r & VT_LVAL))
866 expect("lvalue");
869 TokenSym *tok_alloc(const char *str, int len)
871 TokenSym *ts, **pts, **ptable;
872 int h, i;
874 if (len <= 0)
875 len = strlen(str);
876 h = 1;
877 for(i=0;i<len;i++)
878 h = (h * 263 + ((unsigned char *)str)[i]) & (TOK_HASH_SIZE - 1);
880 pts = &hash_ident[h];
881 while (1) {
882 ts = *pts;
883 if (!ts)
884 break;
885 if (ts->len == len && !memcmp(ts->str, str, len))
886 return ts;
887 pts = &(ts->hash_next);
890 if (tok_ident >= SYM_FIRST_ANOM)
891 error("memory full");
893 /* expand token table if needed */
894 i = tok_ident - TOK_IDENT;
895 if ((i % TOK_ALLOC_INCR) == 0) {
896 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
897 if (!ptable)
898 error("memory full");
899 table_ident = ptable;
902 ts = malloc(sizeof(TokenSym) + len);
903 if (!ts)
904 error("memory full");
905 table_ident[i] = ts;
906 ts->tok = tok_ident++;
907 ts->len = len;
908 ts->hash_next = NULL;
909 memcpy(ts->str, str, len + 1);
910 *pts = ts;
911 return ts;
914 void add_char(char **pp, int c)
916 char *p;
917 p = *pp;
918 if (c == '\'' || c == '\"' || c == '\\') {
919 /* XXX: could be more precise if char or string */
920 *p++ = '\\';
922 if (c >= 32 && c <= 126) {
923 *p++ = c;
924 } else {
925 *p++ = '\\';
926 if (c == '\n') {
927 *p++ = 'n';
928 } else {
929 *p++ = '0' + ((c >> 6) & 7);
930 *p++ = '0' + ((c >> 3) & 7);
931 *p++ = '0' + (c & 7);
934 *pp = p;
937 /* XXX: buffer overflow */
938 char *get_tok_str(int v, CValue *cv)
940 static char buf[STRING_MAX_SIZE + 1];
941 TokenSym *ts;
942 char *p;
943 int i;
945 if (v == TOK_CINT || v == TOK_CUINT) {
946 sprintf(buf, "%u", cv->ui);
947 return buf;
948 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
949 p = buf;
950 *p++ = '\'';
951 add_char(&p, cv->i);
952 *p++ = '\'';
953 *p = '\0';
954 return buf;
955 } else if (v == TOK_STR || v == TOK_LSTR) {
956 ts = cv->ts;
957 p = buf;
958 *p++ = '\"';
959 for(i=0;i<ts->len;i++)
960 add_char(&p, ts->str[i]);
961 *p++ = '\"';
962 *p = '\0';
963 return buf;
964 } else if (v < TOK_IDENT) {
965 p = buf;
966 *p++ = v;
967 *p = '\0';
968 return buf;
969 } else if (v < tok_ident) {
970 return table_ident[v - TOK_IDENT]->str;
971 } else {
972 /* should never happen */
973 return NULL;
977 /* push, without hashing */
978 Sym *sym_push2(Sym **ps, int v, int t, int c)
980 Sym *s;
981 s = malloc(sizeof(Sym));
982 if (!s)
983 error("memory full");
984 s->v = v;
985 s->t = t;
986 s->c = c;
987 s->next = NULL;
988 /* add in stack */
989 s->prev = *ps;
990 *ps = s;
991 return s;
994 /* find a symbol and return its associated structure. 's' is the top
995 of the symbol stack */
996 Sym *sym_find2(Sym *s, int v)
998 while (s) {
999 if (s->v == v)
1000 return s;
1001 s = s->prev;
1003 return NULL;
1006 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
1008 /* find a symbol and return its associated structure. 'st' is the
1009 symbol stack */
1010 Sym *sym_find1(SymStack *st, int v)
1012 Sym *s;
1014 s = st->hash[HASH_SYM(v)];
1015 while (s) {
1016 if (s->v == v)
1017 return s;
1018 s = s->hash_next;
1020 return NULL;
1023 Sym *sym_push1(SymStack *st, int v, int t, int c)
1025 Sym *s, **ps;
1026 s = sym_push2(&st->top, v, t, c);
1027 /* add in hash table */
1028 if (v) {
1029 ps = &st->hash[HASH_SYM(v)];
1030 s->hash_next = *ps;
1031 *ps = s;
1033 return s;
1036 /* find a symbol in the right symbol space */
1037 Sym *sym_find(int v)
1039 Sym *s;
1040 s = sym_find1(&local_stack, v);
1041 if (!s)
1042 s = sym_find1(&global_stack, v);
1043 return s;
1046 /* push a given symbol on the symbol stack */
1047 Sym *sym_push(int v, int t, int r, int c)
1049 Sym *s;
1050 if (local_stack.top)
1051 s = sym_push1(&local_stack, v, t, c);
1052 else
1053 s = sym_push1(&global_stack, v, t, c);
1054 s->r = r;
1055 return s;
1058 /* pop symbols until top reaches 'b' */
1059 void sym_pop(SymStack *st, Sym *b)
1061 Sym *s, *ss;
1063 s = st->top;
1064 while(s != b) {
1065 ss = s->prev;
1066 /* free hash table entry, except if symbol was freed (only
1067 used for #undef symbols) */
1068 if (s->v)
1069 st->hash[HASH_SYM(s->v)] = s->hash_next;
1070 free(s);
1071 s = ss;
1073 st->top = b;
1076 /* undefined a hashed symbol (used for #undef). Its name is set to
1077 zero */
1078 void sym_undef(SymStack *st, Sym *s)
1080 Sym **ss;
1081 ss = &st->hash[HASH_SYM(s->v)];
1082 while (*ss != NULL) {
1083 if (*ss == s)
1084 break;
1085 ss = &(*ss)->hash_next;
1087 *ss = s->hash_next;
1088 s->v = 0;
1091 /* I/O layer */
1093 BufferedFile *tcc_open(const char *filename)
1095 int fd;
1096 BufferedFile *bf;
1098 fd = open(filename, O_RDONLY);
1099 if (fd < 0)
1100 return NULL;
1101 bf = malloc(sizeof(BufferedFile));
1102 if (!bf) {
1103 close(fd);
1104 return NULL;
1106 bf->fd = fd;
1107 bf->buf_ptr = bf->buffer;
1108 bf->buf_end = bf->buffer;
1109 bf->buffer[0] = CH_EOB; /* put eob symbol */
1110 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1111 bf->line_num = 1;
1112 // printf("opening '%s'\n", filename);
1113 return bf;
1116 void tcc_close(BufferedFile *bf)
1118 total_lines += bf->line_num;
1119 close(bf->fd);
1120 free(bf);
1123 /* read one char. MUST call tcc_fillbuf if CH_EOB is read */
1124 #define TCC_GETC(bf) (*(bf)->buf_ptr++)
1126 /* fill input buffer and return next char */
1127 int tcc_getc_slow(BufferedFile *bf)
1129 int len;
1130 /* only tries to read if really end of buffer */
1131 if (bf->buf_ptr >= bf->buf_end) {
1132 if (bf->fd != -1) {
1133 len = read(bf->fd, bf->buffer, IO_BUF_SIZE);
1134 if (len < 0)
1135 len = 0;
1136 } else {
1137 len = 0;
1139 total_bytes += len;
1140 bf->buf_ptr = bf->buffer;
1141 bf->buf_end = bf->buffer + len;
1142 *bf->buf_end = CH_EOB;
1144 if (bf->buf_ptr < bf->buf_end) {
1145 return *bf->buf_ptr++;
1146 } else {
1147 bf->buf_ptr = bf->buf_end;
1148 return CH_EOF;
1152 /* no need to put that inline */
1153 void handle_eob(void)
1155 for(;;) {
1156 ch1 = tcc_getc_slow(file);
1157 if (ch1 != CH_EOF)
1158 return;
1160 if (include_stack_ptr == include_stack)
1161 return;
1162 /* add end of include file debug info */
1163 if (do_debug) {
1164 put_stabd(N_EINCL, 0, 0);
1166 /* pop include stack */
1167 tcc_close(file);
1168 include_stack_ptr--;
1169 file = *include_stack_ptr;
1173 /* read next char from current input file */
1174 static inline void inp(void)
1176 ch1 = TCC_GETC(file);
1177 /* end of buffer/file handling */
1178 if (ch1 == CH_EOB)
1179 handle_eob();
1180 if (ch1 == '\n')
1181 file->line_num++;
1182 // printf("ch1=%c 0x%x\n", ch1, ch1);
1185 /* input with '\\n' handling */
1186 static inline void minp(void)
1188 redo:
1189 ch = ch1;
1190 inp();
1191 if (ch == '\\' && ch1 == '\n') {
1192 inp();
1193 goto redo;
1195 //printf("ch=%c 0x%x\n", ch, ch);
1199 /* same as minp, but also skip comments */
1200 void cinp(void)
1202 int c;
1204 if (ch1 == '/') {
1205 inp();
1206 if (ch1 == '/') {
1207 /* single line C++ comments */
1208 inp();
1209 while (ch1 != '\n' && ch1 != -1)
1210 inp();
1211 inp();
1212 ch = ' '; /* return space */
1213 } else if (ch1 == '*') {
1214 /* C comments */
1215 inp();
1216 while (ch1 != -1) {
1217 c = ch1;
1218 inp();
1219 if (c == '*' && ch1 == '/') {
1220 inp();
1221 ch = ' '; /* return space */
1222 break;
1225 } else {
1226 ch = '/';
1228 } else {
1229 minp();
1233 void skip_spaces(void)
1235 while (ch == ' ' || ch == '\t')
1236 cinp();
1239 /* skip block of text until #else, #elif or #endif. skip also pairs of
1240 #if/#endif */
1241 void preprocess_skip(void)
1243 int a;
1244 a = 0;
1245 while (1) {
1246 while (ch != '\n') {
1247 if (ch == -1)
1248 expect("#endif");
1249 cinp();
1251 cinp();
1252 skip_spaces();
1253 if (ch == '#') {
1254 cinp();
1255 next_nomacro();
1256 if (a == 0 &&
1257 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1258 break;
1259 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1260 a++;
1261 else if (tok == TOK_ENDIF)
1262 a--;
1267 /* return the number of additionnal 'ints' necessary to store the
1268 token */
1269 static inline int tok_ext_size(int t)
1271 switch(t) {
1272 /* 4 bytes */
1273 case TOK_CINT:
1274 case TOK_CUINT:
1275 case TOK_CCHAR:
1276 case TOK_LCHAR:
1277 case TOK_STR:
1278 case TOK_LSTR:
1279 case TOK_CFLOAT:
1280 return 1;
1281 case TOK_CDOUBLE:
1282 case TOK_CLLONG:
1283 case TOK_CULLONG:
1284 return 2;
1285 case TOK_CLDOUBLE:
1286 return LDOUBLE_SIZE / 4;
1287 default:
1288 return 0;
1292 void tok_add(int **tok_str, int *tok_len, int t)
1294 int len, *str;
1295 len = *tok_len;
1296 str = *tok_str;
1297 if ((len & 63) == 0) {
1298 str = realloc(str, (len + 64) * sizeof(int));
1299 if (!str)
1300 return;
1301 *tok_str = str;
1303 str[len++] = t;
1304 *tok_len = len;
1307 void tok_add2(int **tok_str, int *tok_len, int t, CValue *cv)
1309 int n, i;
1311 tok_add(tok_str, tok_len, t);
1312 n = tok_ext_size(t);
1313 for(i=0;i<n;i++)
1314 tok_add(tok_str, tok_len, cv->tab[i]);
1317 /* get a token from an integer array and increment pointer accordingly */
1318 int tok_get(int **tok_str, CValue *cv)
1320 int *p, t, n, i;
1322 p = *tok_str;
1323 t = *p++;
1324 n = tok_ext_size(t);
1325 for(i=0;i<n;i++)
1326 cv->tab[i] = *p++;
1327 *tok_str = p;
1328 return t;
1331 /* eval an expression for #if/#elif */
1332 int expr_preprocess(void)
1334 int *str, len, c, t;
1336 str = NULL;
1337 len = 0;
1338 while (1) {
1339 skip_spaces();
1340 if (ch == '\n')
1341 break;
1342 next(); /* do macro subst */
1343 if (tok == TOK_DEFINED) {
1344 next_nomacro();
1345 t = tok;
1346 if (t == '(')
1347 next_nomacro();
1348 c = sym_find1(&define_stack, tok) != 0;
1349 if (t == '(')
1350 next_nomacro();
1351 tok = TOK_CINT;
1352 tokc.i = c;
1353 } else if (tok >= TOK_IDENT) {
1354 /* if undefined macro */
1355 tok = TOK_CINT;
1356 tokc.i = 0;
1358 tok_add2(&str, &len, tok, &tokc);
1360 tok_add(&str, &len, -1); /* simulate end of file */
1361 tok_add(&str, &len, 0);
1362 /* now evaluate C constant expression */
1363 macro_ptr = str;
1364 next();
1365 c = expr_const();
1366 macro_ptr = NULL;
1367 free(str);
1368 return c != 0;
1371 #if defined(DEBUG) || defined(PP_DEBUG)
1372 void tok_print(int *str)
1374 int t;
1375 CValue cval;
1377 while (1) {
1378 t = tok_get(&str, &cval);
1379 if (!t)
1380 break;
1381 printf(" %s", get_tok_str(t, &cval));
1383 printf("\n");
1385 #endif
1387 /* parse after #define */
1388 void parse_define(void)
1390 Sym *s, *first, **ps;
1391 int v, t, *str, len;
1393 v = tok;
1394 /* XXX: should check if same macro (ANSI) */
1395 first = NULL;
1396 t = MACRO_OBJ;
1397 /* '(' must be just after macro definition for MACRO_FUNC */
1398 if (ch == '(') {
1399 next_nomacro();
1400 next_nomacro();
1401 ps = &first;
1402 while (tok != ')') {
1403 if (tok == TOK_DOTS)
1404 tok = TOK___VA_ARGS__;
1405 s = sym_push1(&define_stack, tok | SYM_FIELD, 0, 0);
1406 *ps = s;
1407 ps = &s->next;
1408 next_nomacro();
1409 if (tok != ',')
1410 break;
1411 next_nomacro();
1413 t = MACRO_FUNC;
1415 str = NULL;
1416 len = 0;
1417 while (1) {
1418 skip_spaces();
1419 if (ch == '\n' || ch == -1)
1420 break;
1421 next_nomacro();
1422 tok_add2(&str, &len, tok, &tokc);
1424 tok_add(&str, &len, 0);
1425 #ifdef PP_DEBUG
1426 printf("define %s %d: ", get_tok_str(v, NULL), t);
1427 tok_print(str);
1428 #endif
1429 s = sym_push1(&define_stack, v, t, (int)str);
1430 s->next = first;
1433 void preprocess(void)
1435 int size, i, c;
1436 char buf[1024], *q, *p;
1437 char buf1[1024];
1438 BufferedFile *f;
1439 Sym *s;
1441 cinp();
1442 next_nomacro();
1443 redo:
1444 if (tok == TOK_DEFINE) {
1445 next_nomacro();
1446 parse_define();
1447 } else if (tok == TOK_UNDEF) {
1448 next_nomacro();
1449 s = sym_find1(&define_stack, tok);
1450 /* undefine symbol by putting an invalid name */
1451 if (s)
1452 sym_undef(&define_stack, s);
1453 } else if (tok == TOK_INCLUDE) {
1454 skip_spaces();
1455 if (ch == '<') {
1456 c = '>';
1457 goto read_name;
1458 } else if (ch == '\"') {
1459 c = ch;
1460 read_name:
1461 minp();
1462 q = buf;
1463 while (ch != c && ch != '\n' && ch != -1) {
1464 if ((q - buf) < sizeof(buf) - 1)
1465 *q++ = ch;
1466 minp();
1468 *q = '\0';
1469 } else {
1470 next();
1471 if (tok != TOK_STR)
1472 error("#include syntax error");
1473 pstrcpy(buf, sizeof(buf), get_tok_str(tok, &tokc));
1474 c = '\"';
1476 /* eat all spaces and comments after include */
1477 /* XXX: slightly incorrect */
1478 while (ch1 != '\n' && ch1 != -1)
1479 inp();
1481 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
1482 error("memory full");
1483 if (c == '\"') {
1484 /* first search in current dir if "header.h" */
1485 size = 0;
1486 p = strrchr(file->filename, '/');
1487 if (p)
1488 size = p + 1 - file->filename;
1489 if (size > sizeof(buf1) - 1)
1490 size = sizeof(buf1) - 1;
1491 memcpy(buf1, file->filename, size);
1492 buf1[size] = '\0';
1493 pstrcat(buf1, sizeof(buf1), buf);
1494 f = tcc_open(buf1);
1495 if (f)
1496 goto found;
1498 /* now search in standard include path */
1499 for(i=nb_include_paths - 1;i>=0;i--) {
1500 strcpy(buf1, include_paths[i]);
1501 strcat(buf1, "/");
1502 strcat(buf1, buf);
1503 f = tcc_open(buf1);
1504 if (f)
1505 goto found;
1507 error("include file '%s' not found", buf1);
1508 f = NULL;
1509 found:
1510 /* push current file in stack */
1511 /* XXX: fix current line init */
1512 *include_stack_ptr++ = file;
1513 file = f;
1514 /* add include file debug info */
1515 if (do_debug) {
1516 put_stabs(file->filename, N_BINCL, 0, 0, 0);
1518 } else if (tok == TOK_IFNDEF) {
1519 c = 1;
1520 goto do_ifdef;
1521 } else if (tok == TOK_IF) {
1522 c = expr_preprocess();
1523 goto do_if;
1524 } else if (tok == TOK_IFDEF) {
1525 c = 0;
1526 do_ifdef:
1527 next_nomacro();
1528 c = (sym_find1(&define_stack, tok) != 0) ^ c;
1529 do_if:
1530 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
1531 error("memory full");
1532 *ifdef_stack_ptr++ = c;
1533 goto test_skip;
1534 } else if (tok == TOK_ELSE) {
1535 if (ifdef_stack_ptr == ifdef_stack)
1536 error("#else without matching #if");
1537 if (ifdef_stack_ptr[-1] & 2)
1538 error("#else after #else");
1539 c = (ifdef_stack_ptr[-1] ^= 3);
1540 goto test_skip;
1541 } else if (tok == TOK_ELIF) {
1542 if (ifdef_stack_ptr == ifdef_stack)
1543 error("#elif without matching #if");
1544 c = ifdef_stack_ptr[-1];
1545 if (c > 1)
1546 error("#elif after #else");
1547 /* last #if/#elif expression was true: we skip */
1548 if (c == 1)
1549 goto skip;
1550 c = expr_preprocess();
1551 ifdef_stack_ptr[-1] = c;
1552 test_skip:
1553 if (!(c & 1)) {
1554 skip:
1555 preprocess_skip();
1556 goto redo;
1558 } else if (tok == TOK_ENDIF) {
1559 if (ifdef_stack_ptr == ifdef_stack)
1560 error("#endif without matching #if");
1561 ifdef_stack_ptr--;
1562 } else if (tok == TOK_LINE) {
1563 next();
1564 if (tok != TOK_CINT)
1565 error("#line");
1566 file->line_num = tokc.i;
1567 skip_spaces();
1568 if (ch != '\n') {
1569 next();
1570 if (tok != TOK_STR)
1571 error("#line");
1572 pstrcpy(file->filename, sizeof(file->filename),
1573 get_tok_str(tok, &tokc));
1575 } else if (tok == TOK_ERROR) {
1576 error("#error");
1578 /* ignore other preprocess commands or #! for C scripts */
1579 while (ch != '\n' && ch != -1)
1580 cinp();
1583 /* read a number in base b */
1584 int getn(b)
1586 int n, t;
1587 n = 0;
1588 while (1) {
1589 if (ch >= 'a' && ch <= 'f')
1590 t = ch - 'a' + 10;
1591 else if (ch >= 'A' && ch <= 'F')
1592 t = ch - 'A' + 10;
1593 else if (isnum(ch))
1594 t = ch - '0';
1595 else
1596 break;
1597 if (t < 0 || t >= b)
1598 break;
1599 n = n * b + t;
1600 cinp();
1602 return n;
1605 /* read a character for string or char constant and eval escape codes */
1606 int getq()
1608 int c;
1610 c = ch;
1611 minp();
1612 if (c == '\\') {
1613 if (isnum(ch)) {
1614 /* at most three octal digits */
1615 c = ch - '0';
1616 minp();
1617 if (isnum(ch)) {
1618 c = c * 8 + ch - '0';
1619 minp();
1620 if (isnum(ch)) {
1621 c = c * 8 + ch - '0';
1622 minp();
1625 return c;
1626 } else if (ch == 'x') {
1627 minp();
1628 return getn(16);
1629 } else {
1630 if (ch == 'a')
1631 c = '\a';
1632 else if (ch == 'b')
1633 c = '\b';
1634 else if (ch == 'f')
1635 c = '\f';
1636 else if (ch == 'n')
1637 c = '\n';
1638 else if (ch == 'r')
1639 c = '\r';
1640 else if (ch == 't')
1641 c = '\t';
1642 else if (ch == 'v')
1643 c = '\v';
1644 else if (ch == 'e' && gnu_ext)
1645 c = 27;
1646 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
1647 c = ch;
1648 else
1649 error("invalid escaped char");
1650 minp();
1653 return c;
1656 /* we use 64 bit numbers */
1657 #define BN_SIZE 2
1659 /* bn = (bn << shift) | or_val */
1660 void bn_lshift(unsigned int *bn, int shift, int or_val)
1662 int i;
1663 unsigned int v;
1664 for(i=0;i<BN_SIZE;i++) {
1665 v = bn[i];
1666 bn[i] = (v << shift) | or_val;
1667 or_val = v >> (32 - shift);
1671 void bn_zero(unsigned int *bn)
1673 int i;
1674 for(i=0;i<BN_SIZE;i++) {
1675 bn[i] = 0;
1679 void parse_number(void)
1681 int b, t, shift, frac_bits, s, exp_val;
1682 char *q;
1683 unsigned int bn[BN_SIZE];
1684 double d;
1686 /* number */
1687 q = token_buf;
1688 t = ch;
1689 cinp();
1690 *q++ = t;
1691 b = 10;
1692 if (t == '.') {
1693 /* special dot handling */
1694 if (ch >= '0' && ch <= '9') {
1695 goto float_frac_parse;
1696 } else if (ch == '.') {
1697 cinp();
1698 if (ch != '.')
1699 expect("'.'");
1700 cinp();
1701 tok = TOK_DOTS;
1702 } else {
1703 /* dots */
1704 tok = t;
1706 return;
1707 } else if (t == '0') {
1708 if (ch == 'x' || ch == 'X') {
1709 q--;
1710 cinp();
1711 b = 16;
1712 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1713 q--;
1714 cinp();
1715 b = 2;
1718 /* parse all digits. cannot check octal numbers at this stage
1719 because of floating point constants */
1720 while (1) {
1721 if (ch >= 'a' && ch <= 'f')
1722 t = ch - 'a' + 10;
1723 else if (ch >= 'A' && ch <= 'F')
1724 t = ch - 'A' + 10;
1725 else if (isnum(ch))
1726 t = ch - '0';
1727 else
1728 break;
1729 if (t >= b)
1730 break;
1731 if (q >= token_buf + STRING_MAX_SIZE) {
1732 num_too_long:
1733 error("number too long");
1735 *q++ = ch;
1736 cinp();
1738 if (ch == '.' ||
1739 ((ch == 'e' || ch == 'E') && b == 10) ||
1740 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1741 if (b != 10) {
1742 /* NOTE: strtox should support that for hexa numbers, but
1743 non ISOC99 libcs do not support it, so we prefer to do
1744 it by hand */
1745 /* hexadecimal or binary floats */
1746 /* XXX: handle overflows */
1747 *q = '\0';
1748 if (b == 16)
1749 shift = 4;
1750 else
1751 shift = 2;
1752 bn_zero(bn);
1753 q = token_buf;
1754 while (1) {
1755 t = *q++;
1756 if (t == '\0') {
1757 break;
1758 } else if (t >= 'a') {
1759 t = t - 'a' + 10;
1760 } else if (t >= 'A') {
1761 t = t - 'A' + 10;
1762 } else {
1763 t = t - '0';
1765 bn_lshift(bn, shift, t);
1767 frac_bits = 0;
1768 if (ch == '.') {
1769 cinp();
1770 while (1) {
1771 t = ch;
1772 if (t >= 'a' && t <= 'f') {
1773 t = t - 'a' + 10;
1774 } else if (t >= 'A' && t <= 'F') {
1775 t = t - 'A' + 10;
1776 } else if (t >= '0' && t <= '9') {
1777 t = t - '0';
1778 } else {
1779 break;
1781 if (t >= b)
1782 error("invalid digit");
1783 bn_lshift(bn, shift, t);
1784 frac_bits += shift;
1785 cinp();
1788 if (ch != 'p' && ch != 'P')
1789 error("exponent expected");
1790 cinp();
1791 s = 1;
1792 exp_val = 0;
1793 if (ch == '+') {
1794 cinp();
1795 } else if (ch == '-') {
1796 s = -1;
1797 cinp();
1799 if (ch < '0' || ch > '9')
1800 error("exponent digits expected");
1801 while (ch >= '0' && ch <= '9') {
1802 exp_val = exp_val * 10 + ch - '0';
1803 cinp();
1805 exp_val = exp_val * s;
1807 /* now we can generate the number */
1808 /* XXX: should patch directly float number */
1809 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1810 d = ldexp(d, exp_val - frac_bits);
1811 t = toup(ch);
1812 if (t == 'F') {
1813 cinp();
1814 tok = TOK_CFLOAT;
1815 /* float : should handle overflow */
1816 tokc.f = (float)d;
1817 } else if (t == 'L') {
1818 cinp();
1819 tok = TOK_CLDOUBLE;
1820 /* XXX: not large enough */
1821 tokc.ld = (long double)d;
1822 } else {
1823 tok = TOK_CDOUBLE;
1824 tokc.d = d;
1826 } else {
1827 /* decimal floats */
1828 if (ch == '.') {
1829 if (q >= token_buf + STRING_MAX_SIZE)
1830 goto num_too_long;
1831 *q++ = ch;
1832 cinp();
1833 float_frac_parse:
1834 while (ch >= '0' && ch <= '9') {
1835 if (q >= token_buf + STRING_MAX_SIZE)
1836 goto num_too_long;
1837 *q++ = ch;
1838 cinp();
1841 if (ch == 'e' || ch == 'E') {
1842 if (q >= token_buf + STRING_MAX_SIZE)
1843 goto num_too_long;
1844 *q++ = ch;
1845 cinp();
1846 if (ch == '-' || ch == '+') {
1847 if (q >= token_buf + STRING_MAX_SIZE)
1848 goto num_too_long;
1849 *q++ = ch;
1850 cinp();
1852 if (ch < '0' || ch > '9')
1853 error("exponent digits expected");
1854 while (ch >= '0' && ch <= '9') {
1855 if (q >= token_buf + STRING_MAX_SIZE)
1856 goto num_too_long;
1857 *q++ = ch;
1858 cinp();
1861 *q = '\0';
1862 t = toup(ch);
1863 errno = 0;
1864 if (t == 'F') {
1865 cinp();
1866 tok = TOK_CFLOAT;
1867 tokc.f = strtof(token_buf, NULL);
1868 } else if (t == 'L') {
1869 cinp();
1870 tok = TOK_CLDOUBLE;
1871 tokc.ld = strtold(token_buf, NULL);
1872 } else {
1873 tok = TOK_CDOUBLE;
1874 tokc.d = strtod(token_buf, NULL);
1877 } else {
1878 unsigned long long n, n1;
1879 int lcount;
1881 /* integer number */
1882 *q = '\0';
1883 q = token_buf;
1884 if (b == 10 && *q == '0') {
1885 b = 8;
1886 q++;
1888 n = 0;
1889 while(1) {
1890 t = *q++;
1891 /* no need for checks except for base 10 / 8 errors */
1892 if (t == '\0') {
1893 break;
1894 } else if (t >= 'a') {
1895 t = t - 'a' + 10;
1896 } else if (t >= 'A') {
1897 t = t - 'A' + 10;
1898 } else {
1899 t = t - '0';
1900 if (t >= b)
1901 error("invalid digit");
1903 n1 = n;
1904 n = n * b + t;
1905 /* detect overflow */
1906 if (n < n1)
1907 error("integer constant overflow");
1910 /* XXX: not exactly ANSI compliant */
1911 if ((n & 0xffffffff00000000LL) != 0) {
1912 if ((n >> 63) != 0)
1913 tok = TOK_CULLONG;
1914 else
1915 tok = TOK_CLLONG;
1916 } else if (n > 0x7fffffff) {
1917 tok = TOK_CUINT;
1918 } else {
1919 tok = TOK_CINT;
1921 lcount = 0;
1922 for(;;) {
1923 t = toup(ch);
1924 if (t == 'L') {
1925 if (lcount >= 2)
1926 error("three 'l' in integer constant");
1927 lcount++;
1928 if (lcount == 2) {
1929 if (tok == TOK_CINT)
1930 tok = TOK_CLLONG;
1931 else if (tok == TOK_CUINT)
1932 tok = TOK_CULLONG;
1934 cinp();
1935 } else if (t == 'U') {
1936 if (tok == TOK_CINT)
1937 tok = TOK_CUINT;
1938 else if (tok == TOK_CLLONG)
1939 tok = TOK_CULLONG;
1940 cinp();
1941 } else {
1942 break;
1945 if (tok == TOK_CINT || tok == TOK_CUINT)
1946 tokc.ui = n;
1947 else
1948 tokc.ull = n;
1953 /* return next token without macro substitution */
1954 void next_nomacro1(void)
1956 int b;
1957 char *q;
1958 TokenSym *ts;
1960 /* skip spaces */
1961 while(1) {
1962 while (ch == '\n') {
1963 cinp();
1964 while (ch == ' ' || ch == '\t')
1965 cinp();
1966 if (ch == '#') {
1967 /* preprocessor command if # at start of line after
1968 spaces */
1969 preprocess();
1972 if (ch != ' ' && ch != '\t' && ch != '\f')
1973 break;
1974 cinp();
1976 if (isid(ch)) {
1977 q = token_buf;
1978 *q++ = ch;
1979 cinp();
1980 if (q[-1] == 'L') {
1981 if (ch == '\'') {
1982 tok = TOK_LCHAR;
1983 goto char_const;
1985 if (ch == '\"') {
1986 tok = TOK_LSTR;
1987 goto str_const;
1990 while (isid(ch) || isnum(ch)) {
1991 if (q >= token_buf + STRING_MAX_SIZE)
1992 error("ident too long");
1993 *q++ = ch;
1994 cinp();
1996 *q = '\0';
1997 ts = tok_alloc(token_buf, q - token_buf);
1998 tok = ts->tok;
1999 } else if (isnum(ch) || ch == '.') {
2000 parse_number();
2001 } else if (ch == '\'') {
2002 tok = TOK_CCHAR;
2003 char_const:
2004 minp();
2005 tokc.i = getq();
2006 if (ch != '\'')
2007 expect("\'");
2008 minp();
2009 } else if (ch == '\"') {
2010 tok = TOK_STR;
2011 str_const:
2012 minp();
2013 q = token_buf;
2014 while (ch != '\"') {
2015 b = getq();
2016 if (ch == -1)
2017 error("unterminated string");
2018 if (q >= token_buf + STRING_MAX_SIZE)
2019 error("string too long");
2020 *q++ = b;
2022 *q = '\0';
2023 tokc.ts = tok_alloc(token_buf, q - token_buf);
2024 minp();
2025 } else {
2026 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
2027 /* two chars */
2028 tok = ch;
2029 cinp();
2030 while (*q) {
2031 if (*q == tok && q[1] == ch) {
2032 cinp();
2033 tok = q[2] & 0xff;
2034 /* three chars tests */
2035 if (tok == TOK_SHL || tok == TOK_SAR) {
2036 if (ch == '=') {
2037 tok = tok | 0x80;
2038 cinp();
2040 } else if (tok == TOK_DOTS) {
2041 if (ch != '.')
2042 error("parse error");
2043 cinp();
2045 return;
2047 q = q + 3;
2049 /* single char substitutions */
2050 if (tok == '<')
2051 tok = TOK_LT;
2052 else if (tok == '>')
2053 tok = TOK_GT;
2057 /* return next token without macro substitution. Can read input from
2058 macro_ptr buffer */
2059 void next_nomacro()
2061 if (macro_ptr) {
2062 tok = *macro_ptr;
2063 if (tok)
2064 tok = tok_get(&macro_ptr, &tokc);
2065 } else {
2066 next_nomacro1();
2070 /* substitute args in macro_str and return allocated string */
2071 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
2073 int *st, last_tok, t, notfirst, *str, len;
2074 Sym *s;
2075 TokenSym *ts;
2076 CValue cval;
2078 str = NULL;
2079 len = 0;
2080 last_tok = 0;
2081 while(1) {
2082 t = tok_get(&macro_str, &cval);
2083 if (!t)
2084 break;
2085 if (t == '#') {
2086 /* stringize */
2087 t = tok_get(&macro_str, &cval);
2088 if (!t)
2089 break;
2090 s = sym_find2(args, t);
2091 if (s) {
2092 token_buf[0] = '\0';
2093 st = (int *)s->c;
2094 notfirst = 0;
2095 while (*st) {
2096 if (notfirst)
2097 pstrcat(token_buf, sizeof(token_buf), " ");
2098 t = tok_get(&st, &cval);
2099 pstrcat(token_buf, sizeof(token_buf), get_tok_str(t, &cval));
2100 notfirst = 1;
2102 #ifdef PP_DEBUG
2103 printf("stringize: %s\n", token_buf);
2104 #endif
2105 /* add string */
2106 ts = tok_alloc(token_buf, 0);
2107 cval.ts = ts;
2108 tok_add2(&str, &len, TOK_STR, &cval);
2109 } else {
2110 tok_add2(&str, &len, t, &cval);
2112 } else if (t >= TOK_IDENT) {
2113 s = sym_find2(args, t);
2114 if (s) {
2115 st = (int *)s->c;
2116 /* if '##' is present before or after , no arg substitution */
2117 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
2118 while (*st)
2119 tok_add(&str, &len, *st++);
2120 } else {
2121 macro_subst(&str, &len, nested_list, st);
2123 } else {
2124 tok_add(&str, &len, t);
2126 } else {
2127 tok_add2(&str, &len, t, &cval);
2129 last_tok = t;
2131 tok_add(&str, &len, 0);
2132 return str;
2135 /* handle the '##' operator */
2136 int *macro_twosharps(int *macro_str)
2138 TokenSym *ts;
2139 int *macro_str1, macro_str1_len, *macro_ptr1;
2140 int t;
2141 char *p;
2142 CValue cval;
2144 macro_str1 = NULL;
2145 macro_str1_len = 0;
2146 tok = 0;
2147 while (1) {
2148 next_nomacro();
2149 if (tok == 0)
2150 break;
2151 while (*macro_ptr == TOK_TWOSHARPS) {
2152 macro_ptr++;
2153 macro_ptr1 = macro_ptr;
2154 t = *macro_ptr;
2155 if (t) {
2156 t = tok_get(&macro_ptr, &cval);
2157 /* XXX: we handle only most common cases:
2158 ident + ident or ident + number */
2159 if (tok >= TOK_IDENT &&
2160 (t >= TOK_IDENT || t == TOK_CINT)) {
2161 p = get_tok_str(tok, &tokc);
2162 pstrcpy(token_buf, sizeof(token_buf), p);
2163 p = get_tok_str(t, &cval);
2164 pstrcat(token_buf, sizeof(token_buf), p);
2165 ts = tok_alloc(token_buf, 0);
2166 tok = ts->tok; /* modify current token */
2167 } else {
2168 /* cannot merge tokens: skip '##' */
2169 macro_ptr = macro_ptr1;
2170 break;
2174 tok_add2(&macro_str1, &macro_str1_len, tok, &tokc);
2176 tok_add(&macro_str1, &macro_str1_len, 0);
2177 return macro_str1;
2182 /* do macro substitution of macro_str and add result to
2183 (tok_str,tok_len). If macro_str is NULL, then input stream token is
2184 substituted. 'nested_list' is the list of all macros we got inside
2185 to avoid recursing. */
2186 void macro_subst(int **tok_str, int *tok_len,
2187 Sym **nested_list, int *macro_str)
2189 Sym *s, *args, *sa, *sa1;
2190 int *str, parlevel, len, *mstr, t, *saved_macro_ptr;
2191 int mstr_allocated, *macro_str1;
2192 CValue cval;
2194 saved_macro_ptr = macro_ptr;
2195 macro_ptr = macro_str;
2196 macro_str1 = NULL;
2197 if (macro_str) {
2198 /* first scan for '##' operator handling */
2199 macro_str1 = macro_twosharps(macro_str);
2200 macro_ptr = macro_str1;
2203 while (1) {
2204 next_nomacro();
2205 if (tok == 0)
2206 break;
2207 /* special macros */
2208 if (tok == TOK___LINE__) {
2209 cval.i = file->line_num;
2210 tok_add2(tok_str, tok_len, TOK_CINT, &cval);
2211 } else if (tok == TOK___FILE__) {
2212 cval.ts = tok_alloc(file->filename, 0);
2213 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2214 } else if (tok == TOK___DATE__) {
2215 cval.ts = tok_alloc("Jan 1 1970", 0);
2216 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2217 } else if (tok == TOK___TIME__) {
2218 cval.ts = tok_alloc("00:00:00", 0);
2219 tok_add2(tok_str, tok_len, TOK_STR, &cval);
2220 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
2221 /* if symbol is a macro, prepare substitution */
2222 /* if nested substitution, do nothing */
2223 if (sym_find2(*nested_list, tok))
2224 goto no_subst;
2225 mstr = (int *)s->c;
2226 mstr_allocated = 0;
2227 if (s->t == MACRO_FUNC) {
2228 /* NOTE: we do not use next_nomacro to avoid eating the
2229 next token. XXX: find better solution */
2230 if (macro_ptr) {
2231 t = *macro_ptr;
2232 } else {
2233 while (ch == ' ' || ch == '\t' || ch == '\n')
2234 cinp();
2235 t = ch;
2237 if (t != '(') /* no macro subst */
2238 goto no_subst;
2240 /* argument macro */
2241 next_nomacro();
2242 next_nomacro();
2243 args = NULL;
2244 sa = s->next;
2245 /* NOTE: empty args are allowed, except if no args */
2246 for(;;) {
2247 /* handle '()' case */
2248 if (!args && tok == ')')
2249 break;
2250 if (!sa)
2251 error("macro '%s' used with too many args",
2252 get_tok_str(s->v, 0));
2253 len = 0;
2254 str = NULL;
2255 parlevel = 0;
2256 while ((parlevel > 0 ||
2257 (tok != ')' &&
2258 (tok != ',' ||
2259 sa->v == (TOK___VA_ARGS__ | SYM_FIELD)))) &&
2260 tok != -1) {
2261 if (tok == '(')
2262 parlevel++;
2263 else if (tok == ')')
2264 parlevel--;
2265 tok_add2(&str, &len, tok, &tokc);
2266 next_nomacro();
2268 tok_add(&str, &len, 0);
2269 sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
2270 if (tok == ')')
2271 break;
2272 if (tok != ',')
2273 expect(",");
2274 next_nomacro();
2275 sa = sa->next;
2277 if (sa->next)
2278 error("macro '%s' used with too few args",
2279 get_tok_str(s->v, 0));
2281 /* now subst each arg */
2282 mstr = macro_arg_subst(nested_list, mstr, args);
2283 /* free memory */
2284 sa = args;
2285 while (sa) {
2286 sa1 = sa->prev;
2287 free((int *)sa->c);
2288 free(sa);
2289 sa = sa1;
2291 mstr_allocated = 1;
2293 sym_push2(nested_list, s->v, 0, 0);
2294 macro_subst(tok_str, tok_len, nested_list, mstr);
2295 /* pop nested defined symbol */
2296 sa1 = *nested_list;
2297 *nested_list = sa1->prev;
2298 free(sa1);
2299 if (mstr_allocated)
2300 free(mstr);
2301 } else {
2302 no_subst:
2303 /* no need to add if reading input stream */
2304 if (!macro_str)
2305 return;
2306 tok_add2(tok_str, tok_len, tok, &tokc);
2308 /* only replace one macro while parsing input stream */
2309 if (!macro_str)
2310 return;
2312 macro_ptr = saved_macro_ptr;
2313 if (macro_str1)
2314 free(macro_str1);
2317 /* return next token with macro substitution */
2318 void next(void)
2320 int len, *ptr;
2321 Sym *nested_list;
2323 /* special 'ungettok' case for label parsing */
2324 if (tok1) {
2325 tok = tok1;
2326 tokc = tok1c;
2327 tok1 = 0;
2328 } else {
2329 redo:
2330 if (!macro_ptr) {
2331 /* if not reading from macro substituted string, then try to substitute */
2332 len = 0;
2333 ptr = NULL;
2334 nested_list = NULL;
2335 macro_subst(&ptr, &len, &nested_list, NULL);
2336 if (ptr) {
2337 tok_add(&ptr, &len, 0);
2338 macro_ptr = ptr;
2339 macro_ptr_allocated = ptr;
2340 goto redo;
2342 if (tok == 0)
2343 goto redo;
2344 } else {
2345 next_nomacro();
2346 if (tok == 0) {
2347 /* end of macro string: free it */
2348 free(macro_ptr_allocated);
2349 macro_ptr = NULL;
2350 goto redo;
2354 #if defined(DEBUG)
2355 printf("token = %s\n", get_tok_str(tok, tokc));
2356 #endif
2359 void swap(int *p, int *q)
2361 int t;
2362 t = *p;
2363 *p = *q;
2364 *q = t;
2367 void vsetc(int t, int r, CValue *vc)
2369 if (vtop >= vstack + VSTACK_SIZE)
2370 error("memory full");
2371 /* cannot let cpu flags if other instruction are generated */
2372 /* XXX: VT_JMP test too ? */
2373 if ((vtop->r & VT_VALMASK) == VT_CMP)
2374 gv(RC_INT);
2375 vtop++;
2376 vtop->t = t;
2377 vtop->r = r;
2378 vtop->r2 = VT_CONST;
2379 vtop->c = *vc;
2382 /* push integer constant */
2383 void vpushi(int v)
2385 CValue cval;
2386 cval.i = v;
2387 vsetc(VT_INT, VT_CONST, &cval);
2390 void vset(int t, int r, int v)
2392 CValue cval;
2394 cval.i = v;
2395 vsetc(t, r, &cval);
2398 void vswap(void)
2400 SValue tmp;
2402 tmp = vtop[0];
2403 vtop[0] = vtop[-1];
2404 vtop[-1] = tmp;
2407 void vpushv(SValue *v)
2409 if (vtop >= vstack + VSTACK_SIZE)
2410 error("memory full");
2411 vtop++;
2412 *vtop = *v;
2415 void vdup(void)
2417 vpushv(vtop);
2420 /* save r to the memory stack, and mark it as being free */
2421 void save_reg(int r)
2423 int l, i, saved, t, size, align;
2424 SValue *p, sv;
2426 /* modify all stack values */
2427 saved = 0;
2428 l = 0;
2429 for(p=vstack;p<=vtop;p++) {
2430 i = p->r & VT_VALMASK;
2431 if ((p->r & VT_VALMASK) == r ||
2432 (p->r2 & VT_VALMASK) == r) {
2433 /* must save value on stack if not already done */
2434 if (!saved) {
2435 /* store register in the stack */
2436 t = p->t;
2437 if ((p->r & VT_LVAL) ||
2438 (!is_float(t) && (t & VT_BTYPE) != VT_LLONG))
2439 t = VT_INT;
2440 size = type_size(t, &align);
2441 loc = (loc - size) & -align;
2442 sv.t = t;
2443 sv.r = VT_LOCAL | VT_LVAL;
2444 sv.c.ul = loc;
2445 store(r, &sv);
2446 #ifdef TCC_TARGET_I386
2447 /* x86 specific: need to pop fp register ST0 if saved */
2448 if (r == REG_ST0) {
2449 o(0xd9dd); /* fstp %st(1) */
2451 #endif
2452 /* special long long case */
2453 if ((p->t & VT_BTYPE) == VT_LLONG) {
2454 sv.c.ul += 4;
2455 store(p->r2, &sv);
2457 l = loc;
2458 saved = 1;
2460 /* mark that stack entry as being saved on the stack */
2461 if (p->r & VT_LVAL)
2462 t = VT_LLOCAL;
2463 else
2464 t = VT_LOCAL;
2465 p->r = VT_LVAL | t;
2466 p->r2 = VT_CONST;
2467 p->c.ul = l;
2472 /* find a free register of class 'rc'. If none, save one register */
2473 int get_reg(int rc)
2475 int r;
2476 SValue *p;
2478 /* find a free register */
2479 for(r=0;r<NB_REGS;r++) {
2480 if (reg_classes[r] & rc) {
2481 for(p=vstack;p<=vtop;p++) {
2482 if ((p->r & VT_VALMASK) == r ||
2483 (p->r2 & VT_VALMASK) == r)
2484 goto notfound;
2486 return r;
2488 notfound: ;
2491 /* no register left : free the first one on the stack (VERY
2492 IMPORTANT to start from the bottom to ensure that we don't
2493 spill registers used in gen_opi()) */
2494 for(p=vstack;p<=vtop;p++) {
2495 r = p->r & VT_VALMASK;
2496 if (r < VT_CONST && (reg_classes[r] & rc)) {
2497 save_reg(r);
2498 break;
2501 return r;
2504 void save_regs(void)
2506 int r;
2507 SValue *p;
2509 for(p=vstack;p<=vtop;p++) {
2510 r = p->r & VT_VALMASK;
2511 if (r < VT_CONST) {
2512 save_reg(r);
2517 /* move register 's' to 'r', and flush previous value of r to memory
2518 if needed */
2519 void move_reg(int r, int s)
2521 SValue sv;
2523 if (r != s) {
2524 save_reg(r);
2525 sv.t = VT_INT;
2526 sv.r = s;
2527 sv.c.ul = 0;
2528 load(r, &sv);
2532 /* get address of vtop (vtop MUST BE an lvalue) */
2533 void gaddrof(void)
2535 vtop->r &= ~VT_LVAL;
2536 /* tricky: if saved lvalue, then we can go back to lvalue */
2537 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
2538 vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
2541 #ifdef CONFIG_TCC_BCHECK
2542 /* generate lvalue bound code */
2543 void gbound(void)
2545 vtop->r &= ~VT_MUSTBOUND;
2546 /* if lvalue, then use checking code before dereferencing */
2547 if (vtop->r & VT_LVAL) {
2548 gaddrof();
2549 vpushi(0);
2550 gen_bounded_ptr_add1();
2551 gen_bounded_ptr_add2(1);
2552 vtop->r |= VT_LVAL;
2555 #endif
2557 /* store vtop a register belonging to class 'rc'. lvalues are
2558 converted to values. Cannot be used if cannot be converted to
2559 register value (such as structures). */
2560 int gv(int rc)
2562 int r, r2, rc2, bit_pos, bit_size, size, align, i, data_offset;
2563 unsigned long long ll;
2565 /* NOTE: get_reg can modify vstack[] */
2566 if (vtop->t & VT_BITFIELD) {
2567 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
2568 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2569 /* remove bit field info to avoid loops */
2570 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2571 /* generate shifts */
2572 vpushi(32 - (bit_pos + bit_size));
2573 gen_op(TOK_SHL);
2574 vpushi(32 - bit_size);
2575 /* NOTE: transformed to SHR if unsigned */
2576 gen_op(TOK_SAR);
2577 r = gv(rc);
2578 } else {
2579 if (is_float(vtop->t) &&
2580 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2581 /* CPUs usually cannot use float constants, so we store them
2582 generically in data segment */
2583 size = type_size(vtop->t, &align);
2584 data_offset = (int)data_section->data_ptr;
2585 data_offset = (data_offset + align - 1) & -align;
2586 /* XXX: not portable yet */
2587 size = size >> 2;
2588 for(i=0;i<size;i++)
2589 ((int *)data_offset)[i] = vtop->c.tab[i];
2590 vtop->r |= VT_LVAL;
2591 vtop->c.ul = data_offset;
2592 data_offset += size << 2;
2593 data_section->data_ptr = (unsigned char *)data_offset;
2595 #ifdef CONFIG_TCC_BCHECK
2596 if (vtop->r & VT_MUSTBOUND)
2597 gbound();
2598 #endif
2600 r = vtop->r & VT_VALMASK;
2601 /* need to reload if:
2602 - constant
2603 - lvalue (need to dereference pointer)
2604 - already a register, but not in the right class */
2605 if (r >= VT_CONST ||
2606 (vtop->r & VT_LVAL) ||
2607 !(reg_classes[r] & rc) ||
2608 ((vtop->t & VT_BTYPE) == VT_LLONG &&
2609 !(reg_classes[vtop->r2] & rc))) {
2610 r = get_reg(rc);
2611 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
2612 /* two register type load : expand to two words
2613 temporarily */
2614 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2615 /* load constant */
2616 ll = vtop->c.ull;
2617 vtop->c.ui = ll; /* first word */
2618 load(r, vtop);
2619 vtop->r = r; /* save register value */
2620 vpushi(ll >> 32); /* second word */
2621 } else if (r >= VT_CONST ||
2622 (vtop->r & VT_LVAL)) {
2623 /* load from memory */
2624 load(r, vtop);
2625 vdup();
2626 vtop[-1].r = r; /* save register value */
2627 /* increment pointer to get second word */
2628 vtop->t = VT_INT;
2629 gaddrof();
2630 vpushi(4);
2631 gen_op('+');
2632 vtop->r |= VT_LVAL;
2633 } else {
2634 /* move registers */
2635 load(r, vtop);
2636 vdup();
2637 vtop[-1].r = r; /* save register value */
2638 vtop->r = vtop[-1].r2;
2640 /* allocate second register */
2641 rc2 = RC_INT;
2642 if (rc == RC_IRET)
2643 rc2 = RC_LRET;
2644 r2 = get_reg(rc2);
2645 load(r2, vtop);
2646 vpop();
2647 /* write second register */
2648 vtop->r2 = r2;
2649 } else {
2650 /* one register type load */
2651 load(r, vtop);
2654 vtop->r = r;
2656 return r;
2659 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
2660 void gv2(int rc1, int rc2)
2662 /* generate more generic register first */
2663 if (rc1 <= rc2) {
2664 vswap();
2665 gv(rc1);
2666 vswap();
2667 gv(rc2);
2668 /* test if reload is needed for first register */
2669 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
2670 vswap();
2671 gv(rc1);
2672 vswap();
2674 } else {
2675 gv(rc2);
2676 vswap();
2677 gv(rc1);
2678 vswap();
2679 /* test if reload is needed for first register */
2680 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
2681 gv(rc2);
2686 /* expand long long on stack in two int registers */
2687 void lexpand(void)
2689 int u;
2691 u = vtop->t & VT_UNSIGNED;
2692 gv(RC_INT);
2693 vdup();
2694 vtop[0].r = vtop[-1].r2;
2695 vtop[0].r2 = VT_CONST;
2696 vtop[-1].r2 = VT_CONST;
2697 vtop[0].t = VT_INT | u;
2698 vtop[-1].t = VT_INT | u;
2701 /* build a long long from two ints */
2702 void lbuild(int t)
2704 gv2(RC_INT, RC_INT);
2705 vtop[-1].r2 = vtop[0].r;
2706 vtop[-1].t = t;
2707 vpop();
2710 /* rotate n first stack elements to the bottom */
2711 void vrotb(int n)
2713 int i;
2714 SValue tmp;
2716 tmp = vtop[-n + 1];
2717 for(i=-n+1;i!=0;i++)
2718 vtop[i] = vtop[i+1];
2719 vtop[0] = tmp;
2722 /* pop stack value */
2723 void vpop(void)
2725 #ifdef TCC_TARGET_I386
2726 /* for x86, we need to pop the FP stack */
2727 if ((vtop->r & VT_VALMASK) == REG_ST0) {
2728 o(0xd9dd); /* fstp %st(1) */
2730 #endif
2731 vtop--;
2734 /* convert stack entry to register and duplicate its value in another
2735 register */
2736 void gv_dup(void)
2738 int rc, t, r, r1;
2739 SValue sv;
2741 t = vtop->t;
2742 if ((t & VT_BTYPE) == VT_LLONG) {
2743 lexpand();
2744 gv_dup();
2745 vswap();
2746 vrotb(3);
2747 gv_dup();
2748 vrotb(4);
2749 /* stack: H L L1 H1 */
2750 lbuild(t);
2751 vrotb(3);
2752 vrotb(3);
2753 vswap();
2754 lbuild(t);
2755 vswap();
2756 } else {
2757 /* duplicate value */
2758 rc = RC_INT;
2759 sv.t = VT_INT;
2760 if (is_float(t)) {
2761 rc = RC_FLOAT;
2762 sv.t = t;
2764 r = gv(rc);
2765 r1 = get_reg(rc);
2766 sv.r = r;
2767 sv.c.ul = 0;
2768 load(r1, &sv); /* move r to r1 */
2769 vdup();
2770 /* duplicates value */
2771 vtop->r = r1;
2775 /* generate CPU independent (unsigned) long long operations */
2776 void gen_opl(int op)
2778 int t, a, b, op1, c, i;
2779 void *func;
2780 GFuncContext gf;
2781 SValue tmp;
2783 switch(op) {
2784 case '/':
2785 case TOK_PDIV:
2786 func = __divll;
2787 goto gen_func;
2788 case TOK_UDIV:
2789 func = __divull;
2790 goto gen_func;
2791 case '%':
2792 func = __modll;
2793 goto gen_func;
2794 case TOK_UMOD:
2795 func = __modull;
2796 gen_func:
2797 /* call generic long long function */
2798 gfunc_start(&gf, FUNC_CDECL);
2799 gfunc_param(&gf);
2800 gfunc_param(&gf);
2801 vpushi((int)func);
2802 gfunc_call(&gf);
2803 vpushi(0);
2804 vtop->r = REG_IRET;
2805 vtop->r2 = REG_LRET;
2806 break;
2807 case '^':
2808 case '&':
2809 case '|':
2810 case '*':
2811 case '+':
2812 case '-':
2813 t = vtop->t;
2814 vswap();
2815 lexpand();
2816 vrotb(3);
2817 lexpand();
2818 /* stack: L1 H1 L2 H2 */
2819 tmp = vtop[0];
2820 vtop[0] = vtop[-3];
2821 vtop[-3] = tmp;
2822 tmp = vtop[-2];
2823 vtop[-2] = vtop[-3];
2824 vtop[-3] = tmp;
2825 vswap();
2826 /* stack: H1 H2 L1 L2 */
2827 if (op == '*') {
2828 vpushv(vtop - 1);
2829 vpushv(vtop - 1);
2830 gen_op(TOK_UMULL);
2831 lexpand();
2832 /* stack: H1 H2 L1 L2 ML MH */
2833 for(i=0;i<4;i++)
2834 vrotb(6);
2835 /* stack: ML MH H1 H2 L1 L2 */
2836 tmp = vtop[0];
2837 vtop[0] = vtop[-2];
2838 vtop[-2] = tmp;
2839 /* stack: ML MH H1 L2 H2 L1 */
2840 gen_op('*');
2841 vrotb(3);
2842 vrotb(3);
2843 gen_op('*');
2844 /* stack: ML MH M1 M2 */
2845 gen_op('+');
2846 gen_op('+');
2847 } else if (op == '+' || op == '-') {
2848 /* XXX: add non carry method too (for MIPS or alpha) */
2849 if (op == '+')
2850 op1 = TOK_ADDC1;
2851 else
2852 op1 = TOK_SUBC1;
2853 gen_op(op1);
2854 /* stack: H1 H2 (L1 op L2) */
2855 vrotb(3);
2856 vrotb(3);
2857 gen_op(op1 + 1); /* TOK_xxxC2 */
2858 } else {
2859 gen_op(op);
2860 /* stack: H1 H2 (L1 op L2) */
2861 vrotb(3);
2862 vrotb(3);
2863 /* stack: (L1 op L2) H1 H2 */
2864 gen_op(op);
2865 /* stack: (L1 op L2) (H1 op H2) */
2867 /* stack: L H */
2868 lbuild(t);
2869 break;
2870 case TOK_SAR:
2871 case TOK_SHR:
2872 case TOK_SHL:
2873 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
2874 t = vtop[-1].t;
2875 vswap();
2876 lexpand();
2877 vrotb(3);
2878 /* stack: L H shift */
2879 c = (int)vtop->c.i;
2880 /* constant: simpler */
2881 /* NOTE: all comments are for SHL. the other cases are
2882 done by swaping words */
2883 vpop();
2884 if (op != TOK_SHL)
2885 vswap();
2886 if (c >= 32) {
2887 /* stack: L H */
2888 vpop();
2889 if (c > 32) {
2890 vpushi(c - 32);
2891 gen_op(op);
2893 if (op != TOK_SAR) {
2894 vpushi(0);
2895 } else {
2896 gv_dup();
2897 vpushi(31);
2898 gen_op(TOK_SAR);
2900 vswap();
2901 } else {
2902 vswap();
2903 gv_dup();
2904 /* stack: H L L */
2905 vpushi(c);
2906 gen_op(op);
2907 vswap();
2908 vpushi(32 - c);
2909 if (op == TOK_SHL)
2910 gen_op(TOK_SHR);
2911 else
2912 gen_op(TOK_SHL);
2913 vrotb(3);
2914 /* stack: L L H */
2915 vpushi(c);
2916 gen_op(op);
2917 gen_op('|');
2919 if (op != TOK_SHL)
2920 vswap();
2921 lbuild(t);
2922 } else {
2923 /* XXX: should provide a faster fallback on x86 ? */
2924 switch(op) {
2925 case TOK_SAR:
2926 func = __sardi3;
2927 goto gen_func;
2928 case TOK_SHR:
2929 func = __shrdi3;
2930 goto gen_func;
2931 case TOK_SHL:
2932 func = __shldi3;
2933 goto gen_func;
2936 break;
2937 default:
2938 /* compare operations */
2939 t = vtop->t;
2940 vswap();
2941 lexpand();
2942 vrotb(3);
2943 lexpand();
2944 /* stack: L1 H1 L2 H2 */
2945 tmp = vtop[-1];
2946 vtop[-1] = vtop[-2];
2947 vtop[-2] = tmp;
2948 /* stack: L1 L2 H1 H2 */
2949 /* compare high */
2950 op1 = op;
2951 /* when values are equal, we need to compare low words. since
2952 the jump is inverted, we invert the test too. */
2953 if (op1 == TOK_LT)
2954 op1 = TOK_LE;
2955 else if (op1 == TOK_GT)
2956 op1 = TOK_GE;
2957 else if (op1 == TOK_ULT)
2958 op1 = TOK_ULE;
2959 else if (op1 == TOK_UGT)
2960 op1 = TOK_UGE;
2961 a = 0;
2962 b = 0;
2963 gen_op(op1);
2964 if (op1 != TOK_NE) {
2965 a = gtst(1, 0);
2967 if (op != TOK_EQ) {
2968 /* generate non equal test */
2969 /* XXX: NOT PORTABLE yet */
2970 if (a == 0) {
2971 b = gtst(0, 0);
2972 } else {
2973 #ifdef TCC_TARGET_I386
2974 b = psym(0x850f, 0);
2975 #else
2976 error("not implemented");
2977 #endif
2980 /* compare low */
2981 gen_op(op);
2982 a = gtst(1, a);
2983 gsym(b);
2984 vset(VT_INT, VT_JMPI, a);
2985 break;
2989 /* handle integer constant optimizations and various machine
2990 independant opt */
2991 void gen_opic(int op)
2993 int fc, c1, c2, n;
2994 SValue *v1, *v2;
2996 v1 = vtop - 1;
2997 v2 = vtop;
2998 /* currently, we cannot do computations with forward symbols */
2999 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3000 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3001 if (c1 && c2) {
3002 fc = v2->c.i;
3003 switch(op) {
3004 case '+': v1->c.i += fc; break;
3005 case '-': v1->c.i -= fc; break;
3006 case '&': v1->c.i &= fc; break;
3007 case '^': v1->c.i ^= fc; break;
3008 case '|': v1->c.i |= fc; break;
3009 case '*': v1->c.i *= fc; break;
3011 case TOK_PDIV:
3012 case '/':
3013 case '%':
3014 case TOK_UDIV:
3015 case TOK_UMOD:
3016 /* if division by zero, generate explicit division */
3017 if (fc == 0) {
3018 if (const_wanted)
3019 error("division by zero in constant");
3020 goto general_case;
3022 switch(op) {
3023 default: v1->c.i /= fc; break;
3024 case '%': v1->c.i %= fc; break;
3025 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
3026 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
3028 break;
3029 case TOK_SHL: v1->c.i <<= fc; break;
3030 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
3031 case TOK_SAR: v1->c.i >>= fc; break;
3032 /* tests */
3033 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
3034 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
3035 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
3036 case TOK_NE: v1->c.i = v1->c.i != fc; break;
3037 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
3038 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
3039 case TOK_LT: v1->c.i = v1->c.i < fc; break;
3040 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
3041 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
3042 case TOK_GT: v1->c.i = v1->c.i > fc; break;
3043 /* logical */
3044 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
3045 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
3046 default:
3047 goto general_case;
3049 vtop--;
3050 } else {
3051 /* if commutative ops, put c2 as constant */
3052 if (c1 && (op == '+' || op == '&' || op == '^' ||
3053 op == '|' || op == '*')) {
3054 vswap();
3055 swap(&c1, &c2);
3057 fc = vtop->c.i;
3058 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
3059 op == TOK_PDIV) &&
3060 fc == 1) ||
3061 ((op == '+' || op == '-' || op == '|' || op == '^' ||
3062 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
3063 fc == 0) ||
3064 (op == '&' &&
3065 fc == -1))) {
3066 /* nothing to do */
3067 vtop--;
3068 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
3069 /* try to use shifts instead of muls or divs */
3070 if (fc > 0 && (fc & (fc - 1)) == 0) {
3071 n = -1;
3072 while (fc) {
3073 fc >>= 1;
3074 n++;
3076 vtop->c.i = n;
3077 if (op == '*')
3078 op = TOK_SHL;
3079 else if (op == TOK_PDIV)
3080 op = TOK_SAR;
3081 else
3082 op = TOK_SHR;
3084 goto general_case;
3085 } else {
3086 general_case:
3087 /* call low level op generator */
3088 gen_opi(op);
3093 /* generate a floating point operation with constant propagation */
3094 void gen_opif(int op)
3096 int c1, c2;
3097 SValue *v1, *v2;
3098 long double f1, f2;
3100 v1 = vtop - 1;
3101 v2 = vtop;
3102 /* currently, we cannot do computations with forward symbols */
3103 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3104 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3105 if (c1 && c2) {
3106 if (v1->t == VT_FLOAT) {
3107 f1 = v1->c.f;
3108 f2 = v2->c.f;
3109 } else if (v1->t == VT_DOUBLE) {
3110 f1 = v1->c.d;
3111 f2 = v2->c.d;
3112 } else {
3113 f1 = v1->c.ld;
3114 f2 = v2->c.ld;
3117 /* NOTE: we only do constant propagation if finite number (not
3118 NaN or infinity) (ANSI spec) */
3119 if (!ieee_finite(f1) || !ieee_finite(f2))
3120 goto general_case;
3122 switch(op) {
3123 case '+': f1 += f2; break;
3124 case '-': f1 -= f2; break;
3125 case '*': f1 *= f2; break;
3126 case '/':
3127 if (f2 == 0.0) {
3128 if (const_wanted)
3129 error("division by zero in constant");
3130 goto general_case;
3132 f1 /= f2;
3133 break;
3134 /* XXX: also handles tests ? */
3135 default:
3136 goto general_case;
3138 /* XXX: overflow test ? */
3139 if (v1->t == VT_FLOAT) {
3140 v1->c.f = f1;
3141 } else if (v1->t == VT_DOUBLE) {
3142 v1->c.d = f1;
3143 } else {
3144 v1->c.ld = f1;
3146 vtop--;
3147 } else {
3148 general_case:
3149 gen_opf(op);
3154 int pointed_size(int t)
3156 return type_size(pointed_type(t), &t);
3159 #if 0
3160 void check_pointer_types(SValue *p1, SValue *p2)
3162 char buf1[256], buf2[256];
3163 int t1, t2;
3164 t1 = p1->t;
3165 t2 = p2->t;
3166 if (!is_compatible_types(t1, t2)) {
3167 type_to_str(buf1, sizeof(buf1), t1, NULL);
3168 type_to_str(buf2, sizeof(buf2), t2, NULL);
3169 error("incompatible pointers '%s' and '%s'", buf1, buf2);
3172 #endif
3174 /* generic gen_op: handles types problems */
3175 void gen_op(int op)
3177 int u, t1, t2, bt1, bt2, t;
3179 t1 = vtop[-1].t;
3180 t2 = vtop[0].t;
3181 bt1 = t1 & VT_BTYPE;
3182 bt2 = t2 & VT_BTYPE;
3184 if (bt1 == VT_PTR || bt2 == VT_PTR) {
3185 /* at least one operand is a pointer */
3186 /* relationnal op: must be both pointers */
3187 if (op >= TOK_ULT && op <= TOK_GT) {
3188 // check_pointer_types(vtop, vtop - 1);
3189 /* pointers are handled are unsigned */
3190 t = VT_INT | VT_UNSIGNED;
3191 goto std_op;
3193 /* if both pointers, then it must be the '-' op */
3194 if ((t1 & VT_BTYPE) == VT_PTR &&
3195 (t2 & VT_BTYPE) == VT_PTR) {
3196 if (op != '-')
3197 error("cannot use pointers here");
3198 // check_pointer_types(vtop - 1, vtop);
3199 /* XXX: check that types are compatible */
3200 u = pointed_size(t1);
3201 gen_opic(op);
3202 /* set to integer type */
3203 vtop->t = VT_INT;
3204 vpushi(u);
3205 gen_op(TOK_PDIV);
3206 } else {
3207 /* exactly one pointer : must be '+' or '-'. */
3208 if (op != '-' && op != '+')
3209 error("cannot use pointers here");
3210 /* Put pointer as first operand */
3211 if ((t2 & VT_BTYPE) == VT_PTR) {
3212 vswap();
3213 swap(&t1, &t2);
3215 /* XXX: cast to int ? (long long case) */
3216 vpushi(pointed_size(vtop[-1].t));
3217 gen_op('*');
3218 #ifdef CONFIG_TCC_BCHECK
3219 /* if evaluating constant expression, no code should be
3220 generated, so no bound check */
3221 if (do_bounds_check && !const_wanted) {
3222 /* if bounded pointers, we generate a special code to
3223 test bounds */
3224 if (op == '-') {
3225 vpushi(0);
3226 vswap();
3227 gen_op('-');
3229 gen_bounded_ptr_add1();
3230 gen_bounded_ptr_add2(0);
3231 } else
3232 #endif
3234 gen_opic(op);
3236 /* put again type if gen_opic() swaped operands */
3237 vtop->t = t1;
3239 } else if (is_float(bt1) || is_float(bt2)) {
3240 /* compute bigger type and do implicit casts */
3241 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
3242 t = VT_LDOUBLE;
3243 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
3244 t = VT_DOUBLE;
3245 } else {
3246 t = VT_FLOAT;
3248 /* floats can only be used for a few operations */
3249 if (op != '+' && op != '-' && op != '*' && op != '/' &&
3250 (op < TOK_ULT || op > TOK_GT))
3251 error("invalid operands for binary operation");
3252 goto std_op;
3253 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
3254 /* cast to biggest op */
3255 t = VT_LLONG;
3256 /* convert to unsigned if it does not fit in a long long */
3257 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
3258 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
3259 t |= VT_UNSIGNED;
3260 goto std_op;
3261 } else {
3262 /* integer operations */
3263 t = VT_INT;
3264 /* convert to unsigned if it does not fit in an integer */
3265 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
3266 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3267 t |= VT_UNSIGNED;
3268 std_op:
3269 /* XXX: currently, some unsigned operations are explicit, so
3270 we modify them here */
3271 if (t & VT_UNSIGNED) {
3272 if (op == TOK_SAR)
3273 op = TOK_SHR;
3274 else if (op == '/')
3275 op = TOK_UDIV;
3276 else if (op == '%')
3277 op = TOK_UMOD;
3278 else if (op == TOK_LT)
3279 op = TOK_ULT;
3280 else if (op == TOK_GT)
3281 op = TOK_UGT;
3282 else if (op == TOK_LE)
3283 op = TOK_ULE;
3284 else if (op == TOK_GE)
3285 op = TOK_UGE;
3287 vswap();
3288 gen_cast(t);
3289 vswap();
3290 /* special case for shifts and long long: we keep the shift as
3291 an integer */
3292 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
3293 gen_cast(VT_INT);
3294 else
3295 gen_cast(t);
3296 if (is_float(t))
3297 gen_opif(op);
3298 else if ((t & VT_BTYPE) == VT_LLONG)
3299 gen_opl(op);
3300 else
3301 gen_opic(op);
3302 if (op >= TOK_ULT && op <= TOK_GT) {
3303 /* relationnal op: the result is an int */
3304 vtop->t = VT_INT;
3305 } else {
3306 vtop->t = t;
3311 /* generic itof for unsigned long long case */
3312 void gen_cvt_itof1(int t)
3314 GFuncContext gf;
3316 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
3317 (VT_LLONG | VT_UNSIGNED)) {
3319 gfunc_start(&gf, FUNC_CDECL);
3320 gfunc_param(&gf);
3321 if (t == VT_FLOAT)
3322 vpushi((int)&__ulltof);
3323 else if (t == VT_DOUBLE)
3324 vpushi((int)&__ulltod);
3325 else
3326 vpushi((int)&__ulltold);
3327 gfunc_call(&gf);
3328 vpushi(0);
3329 vtop->r = REG_FRET;
3330 } else {
3331 gen_cvt_itof(t);
3335 /* generic ftoi for unsigned long long case */
3336 void gen_cvt_ftoi1(int t)
3338 GFuncContext gf;
3339 int st;
3341 if (t == (VT_LLONG | VT_UNSIGNED)) {
3342 /* not handled natively */
3343 gfunc_start(&gf, FUNC_CDECL);
3344 st = vtop->t & VT_BTYPE;
3345 gfunc_param(&gf);
3346 if (st == VT_FLOAT)
3347 vpushi((int)&__ftoull);
3348 else if (st == VT_DOUBLE)
3349 vpushi((int)&__dtoull);
3350 else
3351 vpushi((int)&__ldtoull);
3352 gfunc_call(&gf);
3353 vpushi(0);
3354 vtop->r = REG_IRET;
3355 vtop->r2 = REG_LRET;
3356 } else {
3357 gen_cvt_ftoi(t);
3361 /* force char or short cast */
3362 void force_charshort_cast(int t)
3364 int bits, dbt;
3365 dbt = t & VT_BTYPE;
3366 /* XXX: add optimization if lvalue : just change type and offset */
3367 if (dbt == VT_BYTE)
3368 bits = 8;
3369 else
3370 bits = 16;
3371 if (t & VT_UNSIGNED) {
3372 vpushi((1 << bits) - 1);
3373 gen_op('&');
3374 } else {
3375 bits = 32 - bits;
3376 vpushi(bits);
3377 gen_op(TOK_SHL);
3378 vpushi(bits);
3379 gen_op(TOK_SAR);
3383 /* cast 'vtop' to 't' type */
3384 void gen_cast(int t)
3386 int sbt, dbt, sf, df, c, st1, dt1;
3388 /* special delayed cast for char/short */
3389 /* XXX: in some cases (multiple cascaded casts), it may still
3390 be incorrect */
3391 if (vtop->r & VT_MUSTCAST) {
3392 vtop->r &= ~VT_MUSTCAST;
3393 force_charshort_cast(vtop->t);
3396 dbt = t & VT_BTYPE;
3397 sbt = vtop->t & VT_BTYPE;
3399 if (sbt != dbt) {
3400 sf = is_float(sbt);
3401 df = is_float(dbt);
3402 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3403 if (sf && df) {
3404 /* convert from fp to fp */
3405 if (c) {
3406 /* constant case: we can do it now */
3407 /* XXX: in ISOC, cannot do it if error in convert */
3408 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
3409 vtop->c.f = (float)vtop->c.d;
3410 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
3411 vtop->c.f = (float)vtop->c.ld;
3412 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
3413 vtop->c.d = (double)vtop->c.f;
3414 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
3415 vtop->c.d = (double)vtop->c.ld;
3416 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
3417 vtop->c.ld = (long double)vtop->c.f;
3418 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
3419 vtop->c.ld = (long double)vtop->c.d;
3420 } else {
3421 /* non constant case: generate code */
3422 gen_cvt_ftof(dbt);
3424 } else if (df) {
3425 /* convert int to fp */
3426 st1 = vtop->t & (VT_BTYPE | VT_UNSIGNED);
3427 if (c) {
3428 switch(st1) {
3429 case VT_LLONG | VT_UNSIGNED:
3430 case VT_LLONG:
3431 /* XXX: add const cases for long long */
3432 goto do_itof;
3433 case VT_INT | VT_UNSIGNED:
3434 switch(dbt) {
3435 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
3436 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
3437 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
3439 break;
3440 default:
3441 switch(dbt) {
3442 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
3443 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
3444 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
3446 break;
3448 } else {
3449 do_itof:
3450 gen_cvt_itof1(dbt);
3452 } else if (sf) {
3453 /* convert fp to int */
3454 dt1 = t & (VT_BTYPE | VT_UNSIGNED);
3455 /* we handle char/short/etc... with generic code */
3456 if (dt1 != (VT_INT | VT_UNSIGNED) &&
3457 dt1 != (VT_LLONG | VT_UNSIGNED) &&
3458 dt1 != VT_LLONG)
3459 dt1 = VT_INT;
3460 if (c) {
3461 switch(dt1) {
3462 case VT_LLONG | VT_UNSIGNED:
3463 case VT_LLONG:
3464 /* XXX: add const cases for long long */
3465 goto do_ftoi;
3466 case VT_INT | VT_UNSIGNED:
3467 switch(sbt) {
3468 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
3469 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3470 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3472 break;
3473 default:
3474 /* int case */
3475 switch(sbt) {
3476 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
3477 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
3478 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
3480 break;
3482 } else {
3483 do_ftoi:
3484 gen_cvt_ftoi1(dt1);
3486 if (dt1 == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dt1) {
3487 /* additionnal cast for char/short/bool... */
3488 vtop->t = dt1;
3489 gen_cast(t);
3491 } else if (dbt == VT_LLONG) {
3492 /* scalar to long long */
3493 if (c) {
3494 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3495 vtop->c.ll = vtop->c.ui;
3496 else
3497 vtop->c.ll = vtop->c.i;
3498 } else {
3499 /* machine independant conversion */
3500 gv(RC_INT);
3501 /* generate high word */
3502 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) {
3503 vpushi(0);
3504 gv(RC_INT);
3505 } else {
3506 gv_dup();
3507 vpushi(31);
3508 gen_op(TOK_SAR);
3510 /* patch second register */
3511 vtop[-1].r2 = vtop->r;
3512 vpop();
3514 } else if (dbt == VT_BOOL) {
3515 /* scalar to bool */
3516 vpushi(0);
3517 gen_op(TOK_NE);
3518 } else if (dbt == VT_BYTE || dbt == VT_SHORT) {
3519 force_charshort_cast(t);
3520 } else if (dbt == VT_INT) {
3521 /* scalar to int */
3522 if (sbt == VT_LLONG) {
3523 /* from long long: just take low order word */
3524 lexpand();
3525 vpop();
3526 } else if (sbt == VT_PTR) {
3527 /* ok to cast */
3528 } else if (vtop->r & VT_LVAL) {
3529 /* if lvalue and single word type, nothing to do (XXX:
3530 maybe incorrect for sizeof op) */
3531 goto no_cast;
3535 vtop->t = t;
3536 no_cast: ;
3539 /* return type size. Put alignment at 'a' */
3540 int type_size(int t, int *a)
3542 Sym *s;
3543 int bt;
3545 bt = t & VT_BTYPE;
3546 if (bt == VT_STRUCT) {
3547 /* struct/union */
3548 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3549 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
3550 return s->c;
3551 } else if (bt == VT_PTR) {
3552 if (t & VT_ARRAY) {
3553 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3554 return type_size(s->t, a) * s->c;
3555 } else {
3556 *a = PTR_SIZE;
3557 return PTR_SIZE;
3559 } else if (bt == VT_LDOUBLE) {
3560 *a = LDOUBLE_ALIGN;
3561 return LDOUBLE_SIZE;
3562 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
3563 *a = 8;
3564 return 8;
3565 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
3566 *a = 4;
3567 return 4;
3568 } else if (bt == VT_SHORT) {
3569 *a = 2;
3570 return 2;
3571 } else {
3572 /* char, void, function, _Bool */
3573 *a = 1;
3574 return 1;
3578 /* return the pointed type of t */
3579 int pointed_type(int t)
3581 Sym *s;
3582 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3583 return s->t | (t & ~VT_TYPE);
3586 int mk_pointer(int t)
3588 int p;
3589 p = anon_sym++;
3590 sym_push(p, t, 0, -1);
3591 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
3594 int is_compatible_types(int t1, int t2)
3596 Sym *s1, *s2;
3597 int bt1, bt2;
3599 t1 &= VT_TYPE;
3600 t2 &= VT_TYPE;
3601 bt1 = t1 & VT_BTYPE;
3602 bt2 = t2 & VT_BTYPE;
3603 if (bt1 == VT_PTR) {
3604 t1 = pointed_type(t1);
3605 /* if function, then convert implicitely to function pointer */
3606 if (bt2 != VT_FUNC) {
3607 if (bt2 != VT_PTR)
3608 return 0;
3609 t2 = pointed_type(t2);
3611 /* void matches everything */
3612 t1 &= VT_TYPE;
3613 t2 &= VT_TYPE;
3614 if (t1 == VT_VOID || t2 == VT_VOID)
3615 return 1;
3616 return is_compatible_types(t1, t2);
3617 } else if (bt1 == VT_STRUCT) {
3618 return (t2 == t1);
3619 } else if (bt1 == VT_FUNC) {
3620 if (bt2 != VT_FUNC)
3621 return 0;
3622 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
3623 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
3624 if (!is_compatible_types(s1->t, s2->t))
3625 return 0;
3626 /* XXX: not complete */
3627 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
3628 return 1;
3629 if (s1->c != s2->c)
3630 return 0;
3631 while (s1 != NULL) {
3632 if (s2 == NULL)
3633 return 0;
3634 if (!is_compatible_types(s1->t, s2->t))
3635 return 0;
3636 s1 = s1->next;
3637 s2 = s2->next;
3639 if (s2)
3640 return 0;
3641 return 1;
3642 } else {
3643 /* XXX: not complete */
3644 return 1;
3648 /* print a type. If 'varstr' is not NULL, then the variable is also
3649 printed in the type */
3650 /* XXX: union */
3651 /* XXX: add array and function pointers */
3652 void type_to_str(char *buf, int buf_size,
3653 int t, const char *varstr)
3655 int bt, v;
3656 Sym *s, *sa;
3657 char buf1[256];
3658 const char *tstr;
3660 t = t & VT_TYPE;
3661 bt = t & VT_BTYPE;
3662 buf[0] = '\0';
3663 if (t & VT_UNSIGNED)
3664 pstrcat(buf, buf_size, "unsigned ");
3665 switch(bt) {
3666 case VT_VOID:
3667 tstr = "void";
3668 goto add_tstr;
3669 case VT_BOOL:
3670 tstr = "_Bool";
3671 goto add_tstr;
3672 case VT_BYTE:
3673 tstr = "char";
3674 goto add_tstr;
3675 case VT_SHORT:
3676 tstr = "short";
3677 goto add_tstr;
3678 case VT_INT:
3679 tstr = "int";
3680 goto add_tstr;
3681 case VT_LONG:
3682 tstr = "long";
3683 goto add_tstr;
3684 case VT_LLONG:
3685 tstr = "long long";
3686 goto add_tstr;
3687 case VT_FLOAT:
3688 tstr = "float";
3689 goto add_tstr;
3690 case VT_DOUBLE:
3691 tstr = "double";
3692 goto add_tstr;
3693 case VT_LDOUBLE:
3694 tstr = "long double";
3695 add_tstr:
3696 pstrcat(buf, buf_size, tstr);
3697 break;
3698 case VT_ENUM:
3699 case VT_STRUCT:
3700 if (bt == VT_STRUCT)
3701 tstr = "struct ";
3702 else
3703 tstr = "enum ";
3704 pstrcat(buf, buf_size, tstr);
3705 v = (unsigned)t >> VT_STRUCT_SHIFT;
3706 if (v >= SYM_FIRST_ANOM)
3707 pstrcat(buf, buf_size, "<anonymous>");
3708 else
3709 pstrcat(buf, buf_size, get_tok_str(v, NULL));
3710 break;
3711 case VT_FUNC:
3712 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3713 type_to_str(buf, buf_size, s->t, varstr);
3714 pstrcat(buf, buf_size, "(");
3715 sa = s->next;
3716 while (sa != NULL) {
3717 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
3718 pstrcat(buf, buf_size, buf1);
3719 sa = sa->next;
3720 if (sa)
3721 pstrcat(buf, buf_size, ", ");
3723 pstrcat(buf, buf_size, ")");
3724 goto no_var;
3725 case VT_PTR:
3726 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3727 pstrcpy(buf1, sizeof(buf1), "*");
3728 if (varstr)
3729 pstrcat(buf1, sizeof(buf1), varstr);
3730 type_to_str(buf, buf_size, s->t, buf1);
3731 goto no_var;
3733 if (varstr) {
3734 pstrcat(buf, buf_size, " ");
3735 pstrcat(buf, buf_size, varstr);
3737 no_var: ;
3740 /* verify type compatibility to store vtop in 'dt' type, and generate
3741 casts if needed. */
3742 void gen_assign_cast(int dt)
3744 int st;
3745 char buf1[256], buf2[256];
3747 st = vtop->t; /* source type */
3748 if ((dt & VT_BTYPE) == VT_PTR) {
3749 /* special cases for pointers */
3750 /* a function is implicitely a function pointer */
3751 if ((st & VT_BTYPE) == VT_FUNC) {
3752 if (!is_compatible_types(pointed_type(dt), st))
3753 goto error;
3754 else
3755 goto type_ok;
3757 /* '0' can also be a pointer */
3758 if ((st & VT_BTYPE) == VT_INT &&
3759 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) &&
3760 vtop->c.i == 0)
3761 goto type_ok;
3763 if (!is_compatible_types(dt, st)) {
3764 error:
3765 type_to_str(buf1, sizeof(buf1), st, NULL);
3766 type_to_str(buf2, sizeof(buf2), dt, NULL);
3767 error("cannot cast '%s' to '%s'", buf1, buf2);
3769 type_ok:
3770 gen_cast(dt);
3773 /* store vtop in lvalue pushed on stack */
3774 void vstore(void)
3776 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
3777 GFuncContext gf;
3779 ft = vtop[-1].t;
3780 sbt = vtop->t & VT_BTYPE;
3781 dbt = ft & VT_BTYPE;
3782 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
3783 (sbt == VT_INT && dbt == VT_SHORT)) {
3784 /* optimize char/short casts */
3785 delayed_cast = VT_MUSTCAST;
3786 vtop->t = ft & VT_TYPE;
3787 } else {
3788 delayed_cast = 0;
3789 gen_assign_cast(ft & VT_TYPE);
3792 if (sbt == VT_STRUCT) {
3793 /* if structure, only generate pointer */
3794 /* structure assignment : generate memcpy */
3795 /* XXX: optimize if small size */
3797 vdup();
3798 gfunc_start(&gf, FUNC_CDECL);
3799 /* type size */
3800 size = type_size(vtop->t, &align);
3801 vpushi(size);
3802 gfunc_param(&gf);
3803 /* source */
3804 vtop->t = VT_INT;
3805 gaddrof();
3806 gfunc_param(&gf);
3807 /* destination */
3808 vswap();
3809 vtop->t = VT_INT;
3810 gaddrof();
3811 gfunc_param(&gf);
3813 save_regs();
3814 vpushi((int)&memcpy);
3815 gfunc_call(&gf);
3816 /* leave source on stack */
3817 } else if (ft & VT_BITFIELD) {
3818 /* bitfield store handling */
3819 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
3820 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3821 /* remove bit field info to avoid loops */
3822 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3824 /* duplicate destination */
3825 vdup();
3826 vtop[-1] = vtop[-2];
3828 /* mask and shift source */
3829 vpushi((1 << bit_size) - 1);
3830 gen_op('&');
3831 vpushi(bit_pos);
3832 gen_op(TOK_SHL);
3833 /* load destination, mask and or with source */
3834 vswap();
3835 vpushi(~(((1 << bit_size) - 1) << bit_pos));
3836 gen_op('&');
3837 gen_op('|');
3838 /* store result */
3839 vstore();
3840 } else {
3841 #ifdef CONFIG_TCC_BCHECK
3842 /* bound check case */
3843 if (vtop[-1].r & VT_MUSTBOUND) {
3844 vswap();
3845 gbound();
3846 vswap();
3848 #endif
3849 rc = RC_INT;
3850 if (is_float(ft))
3851 rc = RC_FLOAT;
3852 r = gv(rc); /* generate value */
3853 /* if lvalue was saved on stack, must read it */
3854 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
3855 SValue sv;
3856 t = get_reg(RC_INT);
3857 sv.t = VT_INT;
3858 sv.r = VT_LOCAL | VT_LVAL;
3859 sv.c.ul = vtop[-1].c.ul;
3860 load(t, &sv);
3861 vtop[-1].r = t | VT_LVAL;
3863 store(r, vtop - 1);
3864 /* two word case handling : store second register at word + 4 */
3865 if ((ft & VT_BTYPE) == VT_LLONG) {
3866 vswap();
3867 /* convert to int to increment easily */
3868 vtop->t = VT_INT;
3869 gaddrof();
3870 vpushi(4);
3871 gen_op('+');
3872 vtop->r |= VT_LVAL;
3873 vswap();
3874 /* XXX: it works because r2 is spilled last ! */
3875 store(vtop->r2, vtop - 1);
3877 vswap();
3878 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
3879 vtop->r |= delayed_cast;
3883 /* post defines POST/PRE add. c is the token ++ or -- */
3884 void inc(int post, int c)
3886 test_lvalue();
3887 vdup(); /* save lvalue */
3888 if (post) {
3889 gv_dup(); /* duplicate value */
3890 vrotb(3);
3891 vrotb(3);
3893 /* add constant */
3894 vpushi(c - TOK_MID);
3895 gen_op('+');
3896 vstore(); /* store value */
3897 if (post)
3898 vpop(); /* if post op, return saved value */
3901 /* Parse GNUC __attribute__ extension. Currently, the following
3902 extensions are recognized:
3903 - aligned(n) : set data/function alignment.
3904 - section(x) : generate data/code in this section.
3905 - unused : currently ignored, but may be used someday.
3907 void parse_attribute(AttributeDef *ad)
3909 int t, n;
3911 next();
3912 skip('(');
3913 skip('(');
3914 while (tok != ')') {
3915 if (tok < TOK_IDENT)
3916 expect("attribute name");
3917 t = tok;
3918 next();
3919 switch(t) {
3920 case TOK_SECTION:
3921 case TOK___SECTION__:
3922 skip('(');
3923 if (tok != TOK_STR)
3924 expect("section name");
3925 ad->section = find_section(tokc.ts->str);
3926 next();
3927 skip(')');
3928 break;
3929 case TOK_ALIGNED:
3930 case TOK___ALIGNED__:
3931 skip('(');
3932 n = expr_const();
3933 if (n <= 0 || (n & (n - 1)) != 0)
3934 error("alignment must be a positive power of two");
3935 ad->aligned = n;
3936 skip(')');
3937 break;
3938 case TOK_UNUSED:
3939 case TOK___UNUSED__:
3940 /* currently, no need to handle it because tcc does not
3941 track unused objects */
3942 break;
3943 case TOK_NORETURN:
3944 case TOK___NORETURN__:
3945 /* currently, no need to handle it because tcc does not
3946 track unused objects */
3947 break;
3948 case TOK_CDECL:
3949 case TOK___CDECL:
3950 case TOK___CDECL__:
3951 ad->func_call = FUNC_CDECL;
3952 break;
3953 case TOK_STDCALL:
3954 case TOK___STDCALL:
3955 case TOK___STDCALL__:
3956 ad->func_call = FUNC_STDCALL;
3957 break;
3958 default:
3959 warning("'%s' attribute ignored", get_tok_str(t, NULL));
3960 /* skip parameters */
3961 /* XXX: skip parenthesis too */
3962 if (tok == '(') {
3963 next();
3964 while (tok != ')' && tok != -1)
3965 next();
3966 next();
3968 break;
3970 if (tok != ',')
3971 break;
3972 next();
3974 skip(')');
3975 skip(')');
3978 /* enum/struct/union declaration */
3979 int struct_decl(int u)
3981 int a, t, b, v, size, align, maxalign, c, offset;
3982 int bit_size, bit_pos, bsize, bt, lbit_pos;
3983 Sym *s, *ss, **ps;
3984 AttributeDef ad;
3986 a = tok; /* save decl type */
3987 next();
3988 if (tok != '{') {
3989 v = tok;
3990 next();
3991 /* struct already defined ? return it */
3992 /* XXX: check consistency */
3993 s = sym_find(v | SYM_STRUCT);
3994 if (s) {
3995 if (s->t != a)
3996 error("invalid type");
3997 goto do_decl;
3999 } else {
4000 v = anon_sym++;
4002 s = sym_push(v | SYM_STRUCT, a, 0, 0);
4003 /* put struct/union/enum name in type */
4004 do_decl:
4005 u = u | (v << VT_STRUCT_SHIFT);
4007 if (tok == '{') {
4008 next();
4009 if (s->c)
4010 error("struct/union/enum already defined");
4011 /* cannot be empty */
4012 c = 0;
4013 maxalign = 0;
4014 ps = &s->next;
4015 bit_pos = 0;
4016 offset = 0;
4017 while (1) {
4018 if (a == TOK_ENUM) {
4019 v = tok;
4020 next();
4021 if (tok == '=') {
4022 next();
4023 c = expr_const();
4025 /* enum symbols have static storage */
4026 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
4027 if (tok == ',')
4028 next();
4029 c++;
4030 } else {
4031 parse_btype(&b, &ad);
4032 while (1) {
4033 bit_size = -1;
4034 v = 0;
4035 if (tok != ':') {
4036 t = type_decl(&ad, &v, b, TYPE_DIRECT);
4037 if ((t & VT_BTYPE) == VT_FUNC ||
4038 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
4039 error("invalid type for '%s'",
4040 get_tok_str(v, NULL));
4041 } else {
4042 t = b;
4044 if (tok == ':') {
4045 next();
4046 bit_size = expr_const();
4047 /* XXX: handle v = 0 case for messages */
4048 if (bit_size < 0)
4049 error("negative width in bit-field '%s'",
4050 get_tok_str(v, NULL));
4051 if (v && bit_size == 0)
4052 error("zero width for bit-field '%s'",
4053 get_tok_str(v, NULL));
4055 size = type_size(t, &align);
4056 lbit_pos = 0;
4057 if (bit_size >= 0) {
4058 bt = t & VT_BTYPE;
4059 if (bt != VT_INT &&
4060 bt != VT_BYTE &&
4061 bt != VT_SHORT)
4062 error("bitfields must have scalar type");
4063 bsize = size * 8;
4064 if (bit_size > bsize) {
4065 error("width of '%s' exceeds its type",
4066 get_tok_str(v, NULL));
4067 } else if (bit_size == bsize) {
4068 /* no need for bit fields */
4069 bit_pos = 0;
4070 } else if (bit_size == 0) {
4071 /* XXX: what to do if only padding in a
4072 structure ? */
4073 /* zero size: means to pad */
4074 if (bit_pos > 0)
4075 bit_pos = bsize;
4076 } else {
4077 /* we do not have enough room ? */
4078 if ((bit_pos + bit_size) > bsize)
4079 bit_pos = 0;
4080 lbit_pos = bit_pos;
4081 /* XXX: handle LSB first */
4082 t |= VT_BITFIELD |
4083 (bit_pos << VT_STRUCT_SHIFT) |
4084 (bit_size << (VT_STRUCT_SHIFT + 6));
4085 bit_pos += bit_size;
4087 } else {
4088 bit_pos = 0;
4090 if (v) {
4091 /* add new memory data only if starting
4092 bit field */
4093 if (lbit_pos == 0) {
4094 if (a == TOK_STRUCT) {
4095 c = (c + align - 1) & -align;
4096 offset = c;
4097 c += size;
4098 } else {
4099 offset = 0;
4100 if (size > c)
4101 c = size;
4103 if (align > maxalign)
4104 maxalign = align;
4106 #if 0
4107 printf("add field %s offset=%d",
4108 get_tok_str(v, NULL), offset);
4109 if (t & VT_BITFIELD) {
4110 printf(" pos=%d size=%d",
4111 (t >> VT_STRUCT_SHIFT) & 0x3f,
4112 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
4114 printf("\n");
4115 #endif
4116 ss = sym_push(v | SYM_FIELD, t, 0, offset);
4117 *ps = ss;
4118 ps = &ss->next;
4120 if (tok == ';' || tok == -1)
4121 break;
4122 skip(',');
4124 skip(';');
4126 if (tok == '}')
4127 break;
4129 skip('}');
4130 /* size for struct/union, dummy for enum */
4131 s->c = (c + maxalign - 1) & -maxalign;
4133 return u;
4136 /* return 0 if no type declaration. otherwise, return the basic type
4137 and skip it.
4139 int parse_btype(int *type_ptr, AttributeDef *ad)
4141 int t, u, type_found;
4142 Sym *s;
4144 memset(ad, 0, sizeof(AttributeDef));
4145 type_found = 0;
4146 t = 0;
4147 while(1) {
4148 switch(tok) {
4149 /* basic types */
4150 case TOK_CHAR:
4151 u = VT_BYTE;
4152 basic_type:
4153 next();
4154 basic_type1:
4155 if ((t & VT_BTYPE) != 0)
4156 error("too many basic types");
4157 t |= u;
4158 break;
4159 case TOK_VOID:
4160 u = VT_VOID;
4161 goto basic_type;
4162 case TOK_SHORT:
4163 u = VT_SHORT;
4164 goto basic_type;
4165 case TOK_INT:
4166 next();
4167 break;
4168 case TOK_LONG:
4169 next();
4170 if ((t & VT_BTYPE) == VT_DOUBLE) {
4171 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4172 } else if ((t & VT_BTYPE) == VT_LONG) {
4173 t = (t & ~VT_BTYPE) | VT_LLONG;
4174 } else {
4175 u = VT_LONG;
4176 goto basic_type1;
4178 break;
4179 case TOK_BOOL:
4180 u = VT_BOOL;
4181 goto basic_type;
4182 case TOK_FLOAT:
4183 u = VT_FLOAT;
4184 goto basic_type;
4185 case TOK_DOUBLE:
4186 next();
4187 if ((t & VT_BTYPE) == VT_LONG) {
4188 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4189 } else {
4190 u = VT_DOUBLE;
4191 goto basic_type1;
4193 break;
4194 case TOK_ENUM:
4195 u = struct_decl(VT_ENUM);
4196 goto basic_type1;
4197 case TOK_STRUCT:
4198 case TOK_UNION:
4199 u = struct_decl(VT_STRUCT);
4200 goto basic_type1;
4202 /* type modifiers */
4203 case TOK_CONST:
4204 case TOK_VOLATILE:
4205 case TOK_REGISTER:
4206 case TOK_SIGNED:
4207 case TOK___SIGNED__:
4208 case TOK_AUTO:
4209 case TOK_INLINE:
4210 case TOK___INLINE__:
4211 case TOK_RESTRICT:
4212 next();
4213 break;
4214 case TOK_UNSIGNED:
4215 t |= VT_UNSIGNED;
4216 next();
4217 break;
4219 /* storage */
4220 case TOK_EXTERN:
4221 t |= VT_EXTERN;
4222 next();
4223 break;
4224 case TOK_STATIC:
4225 t |= VT_STATIC;
4226 next();
4227 break;
4228 case TOK_TYPEDEF:
4229 t |= VT_TYPEDEF;
4230 next();
4231 break;
4232 /* GNUC attribute */
4233 case TOK___ATTRIBUTE__:
4234 parse_attribute(ad);
4235 break;
4236 default:
4237 s = sym_find(tok);
4238 if (!s || !(s->t & VT_TYPEDEF))
4239 goto the_end;
4240 t |= (s->t & ~VT_TYPEDEF);
4241 next();
4242 break;
4244 type_found = 1;
4246 the_end:
4247 /* long is never used as type */
4248 if ((t & VT_BTYPE) == VT_LONG)
4249 t = (t & ~VT_BTYPE) | VT_INT;
4250 *type_ptr = t;
4251 return type_found;
4254 int post_type(int t, AttributeDef *ad)
4256 int p, n, pt, l, t1;
4257 Sym **plast, *s, *first;
4258 AttributeDef ad1;
4260 if (tok == '(') {
4261 /* function declaration */
4262 next();
4263 l = 0;
4264 first = NULL;
4265 plast = &first;
4266 while (tok != ')') {
4267 /* read param name and compute offset */
4268 if (l != FUNC_OLD) {
4269 if (!parse_btype(&pt, &ad1)) {
4270 if (l) {
4271 error("invalid type");
4272 } else {
4273 l = FUNC_OLD;
4274 goto old_proto;
4277 l = FUNC_NEW;
4278 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
4279 break;
4280 pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
4281 if ((pt & VT_BTYPE) == VT_VOID)
4282 error("parameter declared as void");
4283 } else {
4284 old_proto:
4285 n = tok;
4286 pt = VT_INT;
4287 next();
4289 /* array must be transformed to pointer according to ANSI C */
4290 pt &= ~VT_ARRAY;
4291 s = sym_push(n | SYM_FIELD, pt, 0, 0);
4292 *plast = s;
4293 plast = &s->next;
4294 if (tok == ',') {
4295 next();
4296 if (l == FUNC_NEW && tok == TOK_DOTS) {
4297 l = FUNC_ELLIPSIS;
4298 next();
4299 break;
4303 /* if no parameters, then old type prototype */
4304 if (l == 0)
4305 l = FUNC_OLD;
4306 skip(')');
4307 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4308 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4309 /* we push a anonymous symbol which will contain the function prototype */
4310 p = anon_sym++;
4311 s = sym_push(p, t, ad->func_call, l);
4312 s->next = first;
4313 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
4314 } else if (tok == '[') {
4315 /* array definition */
4316 next();
4317 n = -1;
4318 if (tok != ']') {
4319 n = expr_const();
4320 if (n < 0)
4321 error("invalid array size");
4323 skip(']');
4324 /* parse next post type */
4325 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4326 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4328 /* we push a anonymous symbol which will contain the array
4329 element type */
4330 p = anon_sym++;
4331 sym_push(p, t, 0, n);
4332 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
4334 return t;
4337 /* Read a type declaration (except basic type), and return the
4338 type. 'td' is a bitmask indicating which kind of type decl is
4339 expected. 't' should contain the basic type. 'ad' is the attribute
4340 definition of the basic type. It can be modified by type_decl(). */
4341 int type_decl(AttributeDef *ad, int *v, int t, int td)
4343 int u, p;
4344 Sym *s;
4346 while (tok == '*') {
4347 next();
4348 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
4349 next();
4350 t = mk_pointer(t);
4353 /* recursive type */
4354 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4355 if (tok == '(') {
4356 next();
4357 /* XXX: this is not correct to modify 'ad' at this point, but
4358 the syntax is not clear */
4359 if (tok == TOK___ATTRIBUTE__)
4360 parse_attribute(ad);
4361 u = type_decl(ad, v, 0, td);
4362 skip(')');
4363 } else {
4364 u = 0;
4365 /* type identifier */
4366 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
4367 *v = tok;
4368 next();
4369 } else {
4370 if (!(td & TYPE_ABSTRACT))
4371 expect("identifier");
4372 *v = 0;
4375 /* append t at the end of u */
4376 t = post_type(t, ad);
4377 if (tok == TOK___ATTRIBUTE__)
4378 parse_attribute(ad);
4379 if (!u)
4380 return t;
4381 p = u;
4382 while(1) {
4383 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
4384 p = s->t;
4385 if (!p) {
4386 s->t = t;
4387 break;
4390 return u;
4393 /* define a new external reference to a function 'v' of type 'u' */
4394 Sym *external_sym(int v, int u, int r)
4396 Sym *s;
4397 s = sym_find(v);
4398 if (!s) {
4399 /* push forward reference */
4400 s = sym_push1(&global_stack,
4401 v, u, 0);
4402 s->r = r | VT_CONST | VT_FORWARD;
4404 return s;
4407 void indir(void)
4409 if ((vtop->t & VT_BTYPE) != VT_PTR)
4410 expect("pointer");
4411 if (vtop->r & VT_LVAL)
4412 gv(RC_INT);
4413 vtop->t = pointed_type(vtop->t);
4414 /* an array is never an lvalue */
4415 if (!(vtop->t & VT_ARRAY)) {
4416 vtop->r |= VT_LVAL;
4417 /* if bound checking, the referenced pointer must be checked */
4418 if (do_bounds_check)
4419 vtop->r |= VT_MUSTBOUND;
4423 /* pass a parameter to a function and do type checking and casting */
4424 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
4426 int func_type;
4427 func_type = func->c;
4428 if (func_type == FUNC_OLD ||
4429 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
4430 /* default casting : only need to convert float to double */
4431 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
4432 gen_cast(VT_DOUBLE);
4433 } else if (arg == NULL) {
4434 error("too many arguments to function");
4435 } else {
4436 gen_assign_cast(arg->t);
4438 gfunc_param(gf);
4441 void unary(void)
4443 int n, t, ft, fc, p, align, size, r, data_offset;
4444 Sym *s;
4445 GFuncContext gf;
4446 AttributeDef ad;
4448 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
4449 vpushi(tokc.i);
4450 next();
4451 } else if (tok == TOK_CUINT) {
4452 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
4453 next();
4454 } else if (tok == TOK_CLLONG) {
4455 vsetc(VT_LLONG, VT_CONST, &tokc);
4456 next();
4457 } else if (tok == TOK_CULLONG) {
4458 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
4459 next();
4460 } else if (tok == TOK_CFLOAT) {
4461 vsetc(VT_FLOAT, VT_CONST, &tokc);
4462 next();
4463 } else if (tok == TOK_CDOUBLE) {
4464 vsetc(VT_DOUBLE, VT_CONST, &tokc);
4465 next();
4466 } else if (tok == TOK_CLDOUBLE) {
4467 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
4468 next();
4469 } else if (tok == TOK___FUNC__) {
4470 /* special function name identifier */
4471 /* generate (char *) type */
4472 data_offset = (int)data_section->data_ptr;
4473 vset(mk_pointer(VT_BYTE), VT_CONST, data_offset);
4474 strcpy((void *)data_offset, funcname);
4475 data_offset += strlen(funcname) + 1;
4476 data_section->data_ptr = (unsigned char *)data_offset;
4477 next();
4478 } else if (tok == TOK_LSTR) {
4479 t = VT_INT;
4480 goto str_init;
4481 } else if (tok == TOK_STR) {
4482 /* string parsing */
4483 t = VT_BYTE;
4484 str_init:
4485 type_size(t, &align);
4486 data_offset = (int)data_section->data_ptr;
4487 data_offset = (data_offset + align - 1) & -align;
4488 fc = data_offset;
4489 /* we must declare it as an array first to use initializer parser */
4490 t = VT_ARRAY | mk_pointer(t);
4491 decl_initializer(t, VT_CONST, data_offset, 1, 0);
4492 data_offset += type_size(t, &align);
4493 /* put it as pointer */
4494 vset(t & ~VT_ARRAY, VT_CONST, fc);
4495 data_section->data_ptr = (unsigned char *)data_offset;
4496 } else {
4497 t = tok;
4498 next();
4499 if (t == '(') {
4500 /* cast ? */
4501 if (parse_btype(&t, &ad)) {
4502 ft = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4503 skip(')');
4504 /* check ISOC99 compound literal */
4505 if (tok == '{') {
4506 /* data is allocated locally by default */
4507 if (global_expr)
4508 r = VT_CONST;
4509 else
4510 r = VT_LOCAL;
4511 /* all except arrays are lvalues */
4512 if (!(ft & VT_ARRAY))
4513 r |= VT_LVAL;
4514 memset(&ad, 0, sizeof(AttributeDef));
4515 fc = decl_initializer_alloc(ft, &ad, r, 1);
4516 vset(ft, r, fc);
4517 } else {
4518 unary();
4519 gen_cast(ft);
4521 } else {
4522 gexpr();
4523 skip(')');
4525 } else if (t == '*') {
4526 unary();
4527 indir();
4528 } else if (t == '&') {
4529 unary();
4530 /* functions names must be treated as function pointers,
4531 except for unary '&' and sizeof. Since we consider that
4532 functions are not lvalues, we only have to handle it
4533 there and in function calls. */
4534 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4535 test_lvalue();
4536 vtop->t = mk_pointer(vtop->t);
4537 gaddrof();
4538 } else
4539 if (t == '!') {
4540 unary();
4541 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
4542 vtop->c.i = !vtop->c.i;
4543 else if ((vtop->r & VT_VALMASK) == VT_CMP)
4544 vtop->c.i = vtop->c.i ^ 1;
4545 else
4546 vset(VT_INT, VT_JMP, gtst(1, 0));
4547 } else
4548 if (t == '~') {
4549 unary();
4550 vpushi(-1);
4551 gen_op('^');
4552 } else
4553 if (t == '+') {
4554 unary();
4555 } else
4556 if (t == TOK_SIZEOF) {
4557 if (tok == '(') {
4558 next();
4559 if (parse_btype(&t, &ad)) {
4560 t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4561 } else {
4562 /* XXX: some code could be generated: add eval
4563 flag */
4564 gexpr();
4565 t = vtop->t;
4566 vpop();
4568 skip(')');
4569 } else {
4570 unary();
4571 t = vtop->t;
4572 vpop();
4574 vpushi(type_size(t, &t));
4575 } else
4576 if (t == TOK_INC || t == TOK_DEC) {
4577 unary();
4578 inc(0, t);
4579 } else if (t == '-') {
4580 vpushi(0);
4581 unary();
4582 gen_op('-');
4583 } else
4585 s = sym_find(t);
4586 if (!s) {
4587 if (tok != '(')
4588 error("'%s' undeclared", get_tok_str(t, NULL));
4589 /* for simple function calls, we tolerate undeclared
4590 external reference */
4591 p = anon_sym++;
4592 sym_push1(&global_stack, p, 0, FUNC_OLD);
4593 /* int() function */
4594 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT), 0);
4596 vset(s->t, s->r, s->c);
4597 /* if forward reference, we must point to s */
4598 if (vtop->r & VT_FORWARD)
4599 vtop->c.sym = s;
4603 /* post operations */
4604 while (1) {
4605 if (tok == TOK_INC || tok == TOK_DEC) {
4606 inc(1, tok);
4607 next();
4608 } else if (tok == '.' || tok == TOK_ARROW) {
4609 /* field */
4610 if (tok == TOK_ARROW)
4611 indir();
4612 test_lvalue();
4613 gaddrof();
4614 next();
4615 /* expect pointer on structure */
4616 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
4617 expect("struct or union");
4618 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4619 /* find field */
4620 tok |= SYM_FIELD;
4621 while ((s = s->next) != NULL) {
4622 if (s->v == tok)
4623 break;
4625 if (!s)
4626 error("field not found");
4627 /* add field offset to pointer */
4628 vtop->t = char_pointer_type; /* change type to 'char *' */
4629 vpushi(s->c);
4630 gen_op('+');
4631 /* change type to field type, and set to lvalue */
4632 vtop->t = s->t;
4633 /* an array is never an lvalue */
4634 if (!(vtop->t & VT_ARRAY))
4635 vtop->r |= VT_LVAL;
4636 next();
4637 } else if (tok == '[') {
4638 next();
4639 gexpr();
4640 gen_op('+');
4641 indir();
4642 skip(']');
4643 } else if (tok == '(') {
4644 SValue ret;
4645 Sym *sa;
4647 /* function call */
4648 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
4649 /* pointer test (no array accepted) */
4650 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
4651 vtop->t = pointed_type(vtop->t);
4652 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4653 goto error_func;
4654 } else {
4655 error_func:
4656 expect("function pointer");
4658 } else {
4659 vtop->r &= ~VT_LVAL; /* no lvalue */
4661 /* get return type */
4662 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
4663 save_regs(); /* save used temporary registers */
4664 gfunc_start(&gf, s->r);
4665 next();
4666 sa = s->next; /* first parameter */
4667 #ifdef INVERT_FUNC_PARAMS
4669 int *str, len, parlevel, *saved_macro_ptr;
4670 Sym *args, *s1;
4672 /* read each argument and store it on a stack */
4673 /* XXX: merge it with macro args ? */
4674 args = NULL;
4675 while (tok != ')') {
4676 len = 0;
4677 str = NULL;
4678 parlevel = 0;
4679 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
4680 tok != -1) {
4681 if (tok == '(')
4682 parlevel++;
4683 else if (tok == ')')
4684 parlevel--;
4685 tok_add2(&str, &len, tok, &tokc);
4686 next();
4688 tok_add(&str, &len, -1); /* end of file added */
4689 tok_add(&str, &len, 0);
4690 s1 = sym_push2(&args, 0, 0, (int)str);
4691 s1->next = sa; /* add reference to argument */
4692 if (sa)
4693 sa = sa->next;
4694 if (tok != ',')
4695 break;
4696 next();
4698 if (tok != ')')
4699 expect(")");
4701 /* now generate code in reverse order by reading the stack */
4702 saved_macro_ptr = macro_ptr;
4703 while (args) {
4704 macro_ptr = (int *)args->c;
4705 next();
4706 expr_eq();
4707 if (tok != -1)
4708 expect("',' or ')'");
4709 gfunc_param_typed(&gf, s, args->next);
4710 s1 = args->prev;
4711 free((int *)args->c);
4712 free(args);
4713 args = s1;
4715 macro_ptr = saved_macro_ptr;
4716 /* restore token */
4717 tok = ')';
4719 #endif
4720 /* compute first implicit argument if a structure is returned */
4721 if ((s->t & VT_BTYPE) == VT_STRUCT) {
4722 /* get some space for the returned structure */
4723 size = type_size(s->t, &align);
4724 loc = (loc - size) & -align;
4725 ret.t = s->t;
4726 ret.r = VT_LOCAL | VT_LVAL;
4727 /* pass it as 'int' to avoid structure arg passing
4728 problems */
4729 vset(VT_INT, VT_LOCAL, loc);
4730 ret.c = vtop->c;
4731 gfunc_param(&gf);
4732 } else {
4733 ret.t = s->t;
4734 ret.r2 = VT_CONST;
4735 /* return in register */
4736 if (is_float(ret.t)) {
4737 ret.r = REG_FRET;
4738 } else {
4739 if ((ret.t & VT_BTYPE) == VT_LLONG)
4740 ret.r2 = REG_LRET;
4741 ret.r = REG_IRET;
4743 ret.c.i = 0;
4745 #ifndef INVERT_FUNC_PARAMS
4746 while (tok != ')') {
4747 expr_eq();
4748 gfunc_param_typed(&gf, s, sa);
4749 if (sa)
4750 sa = sa->next;
4751 if (tok == ',')
4752 next();
4754 #endif
4755 if (sa)
4756 error("too few arguments to function");
4757 skip(')');
4758 gfunc_call(&gf);
4759 /* return value */
4760 vsetc(ret.t, ret.r, &ret.c);
4761 vtop->r2 = ret.r2;
4762 } else {
4763 break;
4768 void uneq(void)
4770 int t;
4772 unary();
4773 if (tok == '=' ||
4774 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
4775 tok == TOK_A_XOR || tok == TOK_A_OR ||
4776 tok == TOK_A_SHL || tok == TOK_A_SAR) {
4777 test_lvalue();
4778 t = tok;
4779 next();
4780 if (t == '=') {
4781 expr_eq();
4782 } else {
4783 vdup();
4784 expr_eq();
4785 gen_op(t & 0x7f);
4787 vstore();
4791 void sum(int l)
4793 int t;
4795 if (l == 0)
4796 uneq();
4797 else {
4798 sum(--l);
4799 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
4800 (l == 1 && (tok == '+' || tok == '-')) ||
4801 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
4802 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
4803 tok == TOK_ULT || tok == TOK_UGE)) ||
4804 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
4805 (l == 5 && tok == '&') ||
4806 (l == 6 && tok == '^') ||
4807 (l == 7 && tok == '|') ||
4808 (l == 8 && tok == TOK_LAND) ||
4809 (l == 9 && tok == TOK_LOR)) {
4810 t = tok;
4811 next();
4812 sum(l);
4813 gen_op(t);
4818 /* only used if non constant */
4819 void eand(void)
4821 int t;
4823 sum(8);
4824 t = 0;
4825 while (1) {
4826 if (tok != TOK_LAND) {
4827 if (t) {
4828 t = gtst(1, t);
4829 vset(VT_INT, VT_JMPI, t);
4831 break;
4833 t = gtst(1, t);
4834 next();
4835 sum(8);
4839 void eor(void)
4841 int t;
4843 eand();
4844 t = 0;
4845 while (1) {
4846 if (tok != TOK_LOR) {
4847 if (t) {
4848 t = gtst(0, t);
4849 vset(VT_INT, VT_JMP, t);
4851 break;
4853 t = gtst(0, t);
4854 next();
4855 eand();
4859 /* XXX: better constant handling */
4860 void expr_eq(void)
4862 int t, u, c, r1, r2, rc;
4864 if (const_wanted) {
4865 sum(10);
4866 if (tok == '?') {
4867 c = vtop->c.i;
4868 vpop();
4869 next();
4870 gexpr();
4871 t = vtop->c.i;
4872 vpop();
4873 skip(':');
4874 expr_eq();
4875 if (c)
4876 vtop->c.i = t;
4878 } else {
4879 eor();
4880 if (tok == '?') {
4881 next();
4882 t = gtst(1, 0);
4883 gexpr();
4884 /* XXX: long long handling ? */
4885 rc = RC_INT;
4886 if (is_float(vtop->t))
4887 rc = RC_FLOAT;
4888 r1 = gv(rc);
4889 vtop--; /* no vpop so that FP stack is not flushed */
4890 skip(':');
4891 u = gjmp(0);
4893 gsym(t);
4894 expr_eq();
4895 r2 = gv(rc);
4896 move_reg(r1, r2);
4897 vtop->r = r1;
4898 gsym(u);
4903 void gexpr(void)
4905 while (1) {
4906 expr_eq();
4907 if (tok != ',')
4908 break;
4909 vpop();
4910 next();
4914 /* parse a constant expression and return value in vtop */
4915 void expr_const1(void)
4917 int a;
4918 a = const_wanted;
4919 const_wanted = 1;
4920 expr_eq();
4921 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
4922 expect("constant");
4923 const_wanted = a;
4926 /* parse an integer constant and return its value */
4927 int expr_const(void)
4929 int c;
4930 expr_const1();
4931 c = vtop->c.i;
4932 vpop();
4933 return c;
4936 /* return the label token if current token is a label, otherwise
4937 return zero */
4938 int is_label(void)
4940 int t;
4941 CValue c;
4943 /* fast test first */
4944 if (tok < TOK_UIDENT)
4945 return 0;
4946 /* no need to save tokc since we expect an identifier */
4947 t = tok;
4948 c = tokc;
4949 next();
4950 if (tok == ':') {
4951 next();
4952 return t;
4953 } else {
4954 /* XXX: may not work in all cases (macros ?) */
4955 tok1 = tok;
4956 tok1c = tokc;
4957 tok = t;
4958 tokc = c;
4959 return 0;
4963 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
4965 int a, b, c, d;
4966 Sym *s;
4968 /* generate line number info */
4969 if (do_debug &&
4970 (last_line_num != file->line_num || last_ind != ind)) {
4971 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
4972 last_ind = ind;
4973 last_line_num = file->line_num;
4976 if (tok == TOK_IF) {
4977 /* if test */
4978 next();
4979 skip('(');
4980 gexpr();
4981 skip(')');
4982 a = gtst(1, 0);
4983 block(bsym, csym, case_sym, def_sym, case_reg);
4984 c = tok;
4985 if (c == TOK_ELSE) {
4986 next();
4987 d = gjmp(0);
4988 gsym(a);
4989 block(bsym, csym, case_sym, def_sym, case_reg);
4990 gsym(d); /* patch else jmp */
4991 } else
4992 gsym(a);
4993 } else if (tok == TOK_WHILE) {
4994 next();
4995 d = ind;
4996 skip('(');
4997 gexpr();
4998 skip(')');
4999 a = gtst(1, 0);
5000 b = 0;
5001 block(&a, &b, case_sym, def_sym, case_reg);
5002 gjmp_addr(d);
5003 gsym(a);
5004 gsym_addr(b, d);
5005 } else if (tok == '{') {
5006 next();
5007 /* declarations */
5008 s = local_stack.top;
5009 while (tok != '}') {
5010 decl(VT_LOCAL);
5011 if (tok != '}')
5012 block(bsym, csym, case_sym, def_sym, case_reg);
5014 /* pop locally defined symbols */
5015 sym_pop(&local_stack, s);
5016 next();
5017 } else if (tok == TOK_RETURN) {
5018 next();
5019 if (tok != ';') {
5020 gexpr();
5021 gen_assign_cast(func_vt);
5022 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
5023 /* if returning structure, must copy it to implicit
5024 first pointer arg location */
5025 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
5026 indir();
5027 vswap();
5028 /* copy structure value to pointer */
5029 vstore();
5030 } else if (is_float(func_vt)) {
5031 gv(RC_FRET);
5032 } else {
5033 gv(RC_IRET);
5035 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5037 skip(';');
5038 rsym = gjmp(rsym); /* jmp */
5039 } else if (tok == TOK_BREAK) {
5040 /* compute jump */
5041 if (!bsym)
5042 error("cannot break");
5043 *bsym = gjmp(*bsym);
5044 next();
5045 skip(';');
5046 } else if (tok == TOK_CONTINUE) {
5047 /* compute jump */
5048 if (!csym)
5049 error("cannot continue");
5050 *csym = gjmp(*csym);
5051 next();
5052 skip(';');
5053 } else if (tok == TOK_FOR) {
5054 int e;
5055 next();
5056 skip('(');
5057 if (tok != ';') {
5058 gexpr();
5059 vpop();
5061 skip(';');
5062 d = ind;
5063 c = ind;
5064 a = 0;
5065 b = 0;
5066 if (tok != ';') {
5067 gexpr();
5068 a = gtst(1, 0);
5070 skip(';');
5071 if (tok != ')') {
5072 e = gjmp(0);
5073 c = ind;
5074 gexpr();
5075 vpop();
5076 gjmp_addr(d);
5077 gsym(e);
5079 skip(')');
5080 block(&a, &b, case_sym, def_sym, case_reg);
5081 gjmp_addr(c);
5082 gsym(a);
5083 gsym_addr(b, c);
5084 } else
5085 if (tok == TOK_DO) {
5086 next();
5087 a = 0;
5088 b = 0;
5089 d = ind;
5090 block(&a, &b, case_sym, def_sym, case_reg);
5091 skip(TOK_WHILE);
5092 skip('(');
5093 gsym(b);
5094 gexpr();
5095 c = gtst(0, 0);
5096 gsym_addr(c, d);
5097 skip(')');
5098 gsym(a);
5099 skip(';');
5100 } else
5101 if (tok == TOK_SWITCH) {
5102 next();
5103 skip('(');
5104 gexpr();
5105 /* XXX: other types than integer */
5106 case_reg = gv(RC_INT);
5107 vpop();
5108 skip(')');
5109 a = 0;
5110 b = gjmp(0); /* jump to first case */
5111 c = 0;
5112 block(&a, csym, &b, &c, case_reg);
5113 /* if no default, jmp after switch */
5114 if (c == 0)
5115 c = ind;
5116 /* default label */
5117 gsym_addr(b, c);
5118 /* break label */
5119 gsym(a);
5120 } else
5121 if (tok == TOK_CASE) {
5122 int v1, v2;
5123 if (!case_sym)
5124 expect("switch");
5125 next();
5126 v1 = expr_const();
5127 v2 = v1;
5128 if (gnu_ext && tok == TOK_DOTS) {
5129 next();
5130 v2 = expr_const();
5131 if (v2 < v1)
5132 warning("empty case range");
5134 /* since a case is like a label, we must skip it with a jmp */
5135 b = gjmp(0);
5136 gsym(*case_sym);
5137 vset(VT_INT, case_reg, 0);
5138 vpushi(v1);
5139 if (v1 == v2) {
5140 gen_op(TOK_EQ);
5141 *case_sym = gtst(1, 0);
5142 } else {
5143 gen_op(TOK_GE);
5144 *case_sym = gtst(1, 0);
5145 vset(VT_INT, case_reg, 0);
5146 vpushi(v2);
5147 gen_op(TOK_LE);
5148 *case_sym = gtst(1, *case_sym);
5150 gsym(b);
5151 skip(':');
5152 block(bsym, csym, case_sym, def_sym, case_reg);
5153 } else
5154 if (tok == TOK_DEFAULT) {
5155 next();
5156 skip(':');
5157 if (!def_sym)
5158 expect("switch");
5159 if (*def_sym)
5160 error("too many 'default'");
5161 *def_sym = ind;
5162 block(bsym, csym, case_sym, def_sym, case_reg);
5163 } else
5164 if (tok == TOK_GOTO) {
5165 next();
5166 s = sym_find1(&label_stack, tok);
5167 /* put forward definition if needed */
5168 if (!s)
5169 s = sym_push1(&label_stack, tok, VT_FORWARD, 0);
5170 /* label already defined */
5171 if (s->t & VT_FORWARD)
5172 s->c = gjmp(s->c);
5173 else
5174 gjmp_addr(s->c);
5175 next();
5176 skip(';');
5177 } else {
5178 b = is_label();
5179 if (b) {
5180 /* label case */
5181 s = sym_find1(&label_stack, b);
5182 if (s) {
5183 if (!(s->t & VT_FORWARD))
5184 error("multiple defined label");
5185 gsym(s->c);
5186 s->c = ind;
5187 s->t = 0;
5188 } else {
5189 sym_push1(&label_stack, b, 0, ind);
5191 /* we accept this, but it is a mistake */
5192 if (tok == '}')
5193 warning("deprecated use of label at end of compound statement");
5194 else
5195 block(bsym, csym, case_sym, def_sym, case_reg);
5196 } else {
5197 /* expression case */
5198 if (tok != ';') {
5199 gexpr();
5200 vpop();
5202 skip(';');
5207 /* t is the array or struct type. c is the array or struct
5208 address. cur_index/cur_field is the pointer to the current
5209 value. 'size_only' is true if only size info is needed (only used
5210 in arrays) */
5211 void decl_designator(int t, int r, int c,
5212 int *cur_index, Sym **cur_field,
5213 int size_only)
5215 Sym *s, *f;
5216 int notfirst, index, align, l;
5218 notfirst = 0;
5219 if (gnu_ext && (l = is_label()) != 0)
5220 goto struct_field;
5222 while (tok == '[' || tok == '.') {
5223 if (tok == '[') {
5224 if (!(t & VT_ARRAY))
5225 expect("array type");
5226 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5227 next();
5228 index = expr_const();
5229 if (index < 0 || (s->c >= 0 && index >= s->c))
5230 expect("invalid index");
5231 skip(']');
5232 if (!notfirst)
5233 *cur_index = index;
5234 t = pointed_type(t);
5235 c += index * type_size(t, &align);
5236 } else {
5237 next();
5238 l = tok;
5239 next();
5240 struct_field:
5241 if ((t & VT_BTYPE) != VT_STRUCT)
5242 expect("struct/union type");
5243 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5244 l |= SYM_FIELD;
5245 f = s->next;
5246 while (f) {
5247 if (f->v == l)
5248 break;
5249 f = f->next;
5251 if (!f)
5252 expect("field");
5253 if (!notfirst)
5254 *cur_field = f;
5255 t = f->t | (t & ~VT_TYPE);
5256 c += f->c;
5258 notfirst = 1;
5260 if (notfirst) {
5261 if (tok == '=') {
5262 next();
5263 } else {
5264 if (!gnu_ext)
5265 expect("=");
5267 } else {
5268 if (t & VT_ARRAY) {
5269 index = *cur_index;
5270 t = pointed_type(t);
5271 c += index * type_size(t, &align);
5272 } else {
5273 f = *cur_field;
5274 if (!f)
5275 error("too many field init");
5276 t = f->t | (t & ~VT_TYPE);
5277 c += f->c;
5280 decl_initializer(t, r, c, 0, size_only);
5283 #define EXPR_VAL 0
5284 #define EXPR_CONST 1
5285 #define EXPR_ANY 2
5287 /* store a value or an expression directly in global data or in local array */
5288 void init_putv(int t, int r, int c,
5289 int v, int expr_type)
5291 int saved_global_expr, bt;
5293 switch(expr_type) {
5294 case EXPR_VAL:
5295 vpushi(v);
5296 break;
5297 case EXPR_CONST:
5298 /* compound literals must be allocated globally in this case */
5299 saved_global_expr = global_expr;
5300 global_expr = 1;
5301 expr_const1();
5302 global_expr = saved_global_expr;
5303 break;
5304 case EXPR_ANY:
5305 expr_eq();
5306 break;
5309 if ((r & VT_VALMASK) == VT_CONST) {
5310 /* XXX: not portable */
5311 gen_assign_cast(t);
5312 bt = t & VT_BTYPE;
5313 switch(bt) {
5314 case VT_BYTE:
5315 *(char *)c = vtop->c.i;
5316 break;
5317 case VT_SHORT:
5318 *(short *)c = vtop->c.i;
5319 break;
5320 case VT_DOUBLE:
5321 *(double *)c = vtop->c.d;
5322 break;
5323 case VT_LDOUBLE:
5324 *(long double *)c = vtop->c.ld;
5325 break;
5326 case VT_LLONG:
5327 *(long long *)c = vtop->c.ll;
5328 break;
5329 default:
5330 *(int *)c = vtop->c.i;
5331 break;
5333 vtop--;
5334 } else {
5335 vset(t, r, c);
5336 vswap();
5337 vstore();
5338 vpop();
5342 /* put zeros for variable based init */
5343 void init_putz(int t, int r, int c, int size)
5345 GFuncContext gf;
5347 if ((r & VT_VALMASK) == VT_CONST) {
5348 /* nothing to do because globals are already set to zero */
5349 } else {
5350 gfunc_start(&gf, FUNC_CDECL);
5351 vpushi(size);
5352 gfunc_param(&gf);
5353 vpushi(0);
5354 gfunc_param(&gf);
5355 vset(VT_INT, VT_LOCAL, c);
5356 gfunc_param(&gf);
5357 vpushi((int)&memset);
5358 gfunc_call(&gf);
5362 /* 't' contains the type and storage info. c is the address of the
5363 object. 'first' is true if array '{' must be read (multi dimension
5364 implicit array init handling). 'size_only' is true if size only
5365 evaluation is wanted (only for arrays). */
5366 void decl_initializer(int t, int r, int c, int first, int size_only)
5368 int index, array_length, n, no_oblock, nb, parlevel, i;
5369 int t1, size1, align1, expr_type;
5370 Sym *s, *f;
5371 TokenSym *ts;
5373 if (t & VT_ARRAY) {
5374 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5375 n = s->c;
5376 array_length = 0;
5377 t1 = pointed_type(t);
5378 size1 = type_size(t1, &align1);
5380 no_oblock = 1;
5381 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
5382 tok == '{') {
5383 skip('{');
5384 no_oblock = 0;
5387 /* only parse strings here if correct type (otherwise: handle
5388 them as ((w)char *) expressions */
5389 if ((tok == TOK_LSTR &&
5390 (t1 & VT_BTYPE) == VT_INT) ||
5391 (tok == TOK_STR &&
5392 (t1 & VT_BTYPE) == VT_BYTE)) {
5393 /* XXX: move multiple string parsing in parser ? */
5394 while (tok == TOK_STR || tok == TOK_LSTR) {
5395 ts = tokc.ts;
5396 /* compute maximum number of chars wanted */
5397 nb = ts->len;
5398 if (n >= 0 && nb > (n - array_length))
5399 nb = n - array_length;
5400 if (!size_only) {
5401 if (ts->len > nb)
5402 warning("initializer-string for array is too long");
5403 for(i=0;i<nb;i++) {
5404 init_putv(t1, r, c + (array_length + i) * size1,
5405 ts->str[i], EXPR_VAL);
5408 array_length += nb;
5409 next();
5411 /* only add trailing zero if enough storage (no
5412 warning in this case since it is standard) */
5413 if (n < 0 || array_length < n) {
5414 if (!size_only) {
5415 init_putv(t1, r, c + (array_length * size1), 0, EXPR_VAL);
5417 array_length++;
5419 } else {
5420 index = 0;
5421 while (tok != '}') {
5422 decl_designator(t, r, c, &index, NULL, size_only);
5423 if (n >= 0 && index >= n)
5424 error("index too large");
5425 /* must put zero in holes (note that doing it that way
5426 ensures that it even works with designators) */
5427 if (!size_only && array_length < index) {
5428 init_putz(t1, r, c + array_length * size1,
5429 (index - array_length) * size1);
5431 index++;
5432 if (index > array_length)
5433 array_length = index;
5434 /* special test for multi dimensional arrays (may not
5435 be strictly correct if designators are used at the
5436 same time) */
5437 if (index >= n && no_oblock)
5438 break;
5439 if (tok == '}')
5440 break;
5441 skip(',');
5444 if (!no_oblock)
5445 skip('}');
5446 /* put zeros at the end */
5447 if (!size_only && n >= 0 && array_length < n) {
5448 init_putz(t1, r, c + array_length * size1,
5449 (n - array_length) * size1);
5451 /* patch type size if needed */
5452 if (n < 0)
5453 s->c = array_length;
5454 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
5455 /* XXX: union needs only one init */
5456 next();
5457 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5458 f = s->next;
5459 array_length = 0;
5460 index = 0;
5461 n = s->c;
5462 while (tok != '}') {
5463 decl_designator(t, r, c, NULL, &f, size_only);
5464 /* fill with zero between fields */
5465 index = f->c;
5466 if (!size_only && array_length < index) {
5467 init_putz(t, r, c + array_length,
5468 index - array_length);
5470 index = index + type_size(f->t, &align1);
5471 if (index > array_length)
5472 array_length = index;
5473 if (tok == '}')
5474 break;
5475 skip(',');
5476 f = f->next;
5478 /* put zeros at the end */
5479 if (!size_only && array_length < n) {
5480 init_putz(t, r, c + array_length,
5481 n - array_length);
5483 skip('}');
5484 } else if (tok == '{') {
5485 next();
5486 decl_initializer(t, r, c, first, size_only);
5487 skip('}');
5488 } else if (size_only) {
5489 /* just skip expression */
5490 parlevel = 0;
5491 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
5492 tok != -1) {
5493 if (tok == '(')
5494 parlevel++;
5495 else if (tok == ')')
5496 parlevel--;
5497 next();
5499 } else {
5500 /* currently, we always use constant expression for globals
5501 (may change for scripting case) */
5502 expr_type = EXPR_CONST;
5503 if ((r & VT_VALMASK) == VT_LOCAL)
5504 expr_type = EXPR_ANY;
5505 init_putv(t, r, c, 0, expr_type);
5509 /* parse an initializer for type 't' if 'has_init' is true, and
5510 allocate space in local or global data space ('r' is either
5511 VT_LOCAL or VT_CONST). The allocated address in returned */
5512 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init)
5514 int size, align, addr, tok1, data_offset;
5515 int *init_str, init_len, level, *saved_macro_ptr;
5516 Section *sec;
5518 size = type_size(t, &align);
5519 /* If unknown size, we must evaluate it before
5520 evaluating initializers because
5521 initializers can generate global data too
5522 (e.g. string pointers or ISOC99 compound
5523 literals). It also simplifies local
5524 initializers handling */
5525 init_len = 0;
5526 init_str = NULL;
5527 saved_macro_ptr = NULL; /* avoid warning */
5528 tok1 = 0;
5529 if (size < 0) {
5530 if (!has_init)
5531 error("unknown type size");
5532 /* get all init string */
5533 level = 0;
5534 while (level > 0 || (tok != ',' && tok != ';')) {
5535 if (tok < 0)
5536 error("unexpected end of file in initializer");
5537 tok_add2(&init_str, &init_len, tok, &tokc);
5538 if (tok == '{')
5539 level++;
5540 else if (tok == '}') {
5541 if (level == 0)
5542 break;
5543 level--;
5545 next();
5547 tok1 = tok;
5548 tok_add(&init_str, &init_len, -1);
5549 tok_add(&init_str, &init_len, 0);
5551 /* compute size */
5552 saved_macro_ptr = macro_ptr;
5553 macro_ptr = init_str;
5554 next();
5555 decl_initializer(t, r, 0, 1, 1);
5556 /* prepare second initializer parsing */
5557 macro_ptr = init_str;
5558 next();
5560 /* if still unknown size, error */
5561 size = type_size(t, &align);
5562 if (size < 0)
5563 error("unknown type size");
5565 /* take into account specified alignment if bigger */
5566 if (ad->aligned > align)
5567 align = ad->aligned;
5568 if ((r & VT_VALMASK) == VT_LOCAL) {
5569 if (do_bounds_check && (t & VT_ARRAY))
5570 loc--;
5571 #ifdef TCC_TARGET_IL
5572 /* XXX: ugly patch to allocate local variables for IL, just
5573 for testing */
5574 addr = loc;
5575 loc++;
5576 #else
5577 loc = (loc - size) & -align;
5578 addr = loc;
5579 #endif
5580 /* handles bounds */
5581 /* XXX: currently, since we do only one pass, we cannot track
5582 '&' operators, so we add only arrays */
5583 if (do_bounds_check && (t & VT_ARRAY)) {
5584 int *bounds_ptr;
5585 /* add padding between regions */
5586 loc--;
5587 /* then add local bound info */
5588 bounds_ptr = (int *)lbounds_section->data_ptr;
5589 *bounds_ptr++ = addr;
5590 *bounds_ptr++ = size;
5591 lbounds_section->data_ptr = (unsigned char *)bounds_ptr;
5593 } else {
5594 /* compute section */
5595 sec = ad->section;
5596 if (!sec) {
5597 if (has_init)
5598 sec = data_section;
5599 else
5600 sec = bss_section;
5602 data_offset = (int)sec->data_ptr;
5603 data_offset = (data_offset + align - 1) & -align;
5604 addr = data_offset;
5605 /* very important to increment global
5606 pointer at this time because
5607 initializers themselves can create new
5608 initializers */
5609 data_offset += size;
5610 /* handles bounds */
5611 if (do_bounds_check) {
5612 int *bounds_ptr;
5613 /* first, we need to add at least one byte between each region */
5614 data_offset++;
5615 /* then add global bound info */
5616 bounds_ptr = (int *)bounds_section->data_ptr;
5617 *bounds_ptr++ = addr;
5618 *bounds_ptr++ = size;
5619 bounds_section->data_ptr = (unsigned char *)bounds_ptr;
5621 sec->data_ptr = (unsigned char *)data_offset;
5623 if (has_init) {
5624 decl_initializer(t, r, addr, 1, 0);
5625 /* restore parse state if needed */
5626 if (init_str) {
5627 free(init_str);
5628 macro_ptr = saved_macro_ptr;
5629 tok = tok1;
5632 return addr;
5635 void put_func_debug(int t)
5637 int bind;
5638 char buf[512];
5640 if (t & VT_STATIC)
5641 bind = STB_LOCAL;
5642 else
5643 bind = STB_GLOBAL;
5644 put_elf_sym(symtab_section, ind, 0,
5645 ELF32_ST_INFO(bind, STT_FUNC), 0,
5646 cur_text_section->sh_num, funcname);
5647 /* stabs info */
5648 /* XXX: we put here a dummy type */
5649 snprintf(buf, sizeof(buf), "%s:%c1",
5650 funcname, t & VT_STATIC ? 'f' : 'F');
5651 put_stabs(buf, N_FUN, 0, file->line_num, ind);
5652 func_ind = ind;
5653 last_ind = 0;
5654 last_line_num = 0;
5657 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5658 void decl(int l)
5660 int t, b, v, addr, has_init, r;
5661 Sym *sym;
5662 AttributeDef ad;
5664 while (1) {
5665 if (!parse_btype(&b, &ad)) {
5666 /* skip redundant ';' */
5667 /* XXX: find more elegant solution */
5668 if (tok == ';') {
5669 next();
5670 continue;
5672 /* special test for old K&R protos without explicit int
5673 type. Only accepted when defining global data */
5674 if (l == VT_LOCAL || tok < TOK_DEFINE)
5675 break;
5676 b = VT_INT;
5678 if (((b & VT_BTYPE) == VT_ENUM ||
5679 (b & VT_BTYPE) == VT_STRUCT) &&
5680 tok == ';') {
5681 /* we accept no variable after */
5682 next();
5683 continue;
5685 while (1) { /* iterate thru each declaration */
5686 t = type_decl(&ad, &v, b, TYPE_DIRECT);
5687 #if 0
5689 char buf[500];
5690 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
5691 printf("type = '%s'\n", buf);
5693 #endif
5694 if (tok == '{') {
5695 if (l == VT_LOCAL)
5696 error("cannot use local functions");
5697 if (!(t & VT_FUNC))
5698 expect("function definition");
5699 /* compute text section */
5700 cur_text_section = ad.section;
5701 if (!cur_text_section)
5702 cur_text_section = text_section;
5703 ind = (int)cur_text_section->data_ptr;
5704 /* patch forward references */
5705 if ((sym = sym_find(v)) && (sym->r & VT_FORWARD)) {
5706 greloc_patch(sym, ind);
5707 sym->t = t;
5708 } else {
5709 /* put function address */
5710 sym = sym_push1(&global_stack, v, t, ind);
5712 sym->r = VT_CONST;
5713 funcname = get_tok_str(v, NULL);
5714 /* put debug symbol */
5715 if (do_debug)
5716 put_func_debug(t);
5717 /* push a dummy symbol to enable local sym storage */
5718 sym_push1(&local_stack, 0, 0, 0);
5719 gfunc_prolog(t);
5720 loc = 0;
5721 rsym = 0;
5722 block(NULL, NULL, NULL, NULL, 0);
5723 gsym(rsym);
5724 gfunc_epilog();
5725 cur_text_section->data_ptr = (unsigned char *)ind;
5726 sym_pop(&label_stack, NULL); /* reset label stack */
5727 sym_pop(&local_stack, NULL); /* reset local stack */
5728 /* end of function */
5729 if (do_debug) {
5730 put_stabn(N_FUN, 0, 0, ind - func_ind);
5732 funcname = ""; /* for safety */
5733 func_vt = VT_VOID; /* for safety */
5734 ind = 0; /* for safety */
5735 break;
5736 } else {
5737 if (b & VT_TYPEDEF) {
5738 /* save typedefed type */
5739 /* XXX: test storage specifiers ? */
5740 sym_push(v, t | VT_TYPEDEF, 0, 0);
5741 } else if ((t & VT_BTYPE) == VT_FUNC) {
5742 /* external function definition */
5743 external_sym(v, t, 0);
5744 } else {
5745 /* not lvalue if array */
5746 r = 0;
5747 if (!(t & VT_ARRAY))
5748 r |= VT_LVAL;
5749 if (b & VT_EXTERN) {
5750 /* external variable */
5751 external_sym(v, t, r);
5752 } else {
5753 if (t & VT_STATIC)
5754 r |= VT_CONST;
5755 else
5756 r |= l;
5757 has_init = (tok == '=');
5758 if (has_init)
5759 next();
5760 addr = decl_initializer_alloc(t, &ad, r,
5761 has_init);
5762 if (l == VT_CONST) {
5763 /* global scope: see if already defined */
5764 sym = sym_find(v);
5765 if (!sym)
5766 goto do_def;
5767 if (!is_compatible_types(sym->t, t))
5768 error("incompatible types for redefinition of '%s'",
5769 get_tok_str(v, NULL));
5770 if (!(sym->r & VT_FORWARD))
5771 error("redefinition of '%s'", get_tok_str(v, NULL));
5772 greloc_patch(sym, addr);
5773 } else {
5774 do_def:
5775 sym_push(v, t, r, addr);
5779 if (tok != ',') {
5780 skip(';');
5781 break;
5783 next();
5789 /* put all global symbols in the extern stack and do all the
5790 resolving which can be done without using external symbols from DLLs */
5791 /* XXX: could try to verify types, but would not to save them in
5792 extern_stack too */
5793 void resolve_global_syms(void)
5795 Sym *s, *s1, *ext_sym;
5796 Reloc **p;
5798 s = global_stack.top;
5799 while (s != NULL) {
5800 s1 = s->prev;
5801 /* do not save static or typedefed symbols or types */
5802 if (!(s->t & (VT_STATIC | VT_TYPEDEF)) &&
5803 !(s->v & (SYM_FIELD | SYM_STRUCT)) &&
5804 (s->v < SYM_FIRST_ANOM)) {
5805 ext_sym = sym_find1(&extern_stack, s->v);
5806 if (!ext_sym) {
5807 /* if the symbol do not exist, we simply save it */
5808 ext_sym = sym_push1(&extern_stack, s->v, s->t, s->c);
5809 ext_sym->r = s->r;
5810 } else if (ext_sym->r & VT_FORWARD) {
5811 /* external symbol already exists, but only as forward
5812 definition */
5813 if (!(s->r & VT_FORWARD)) {
5814 /* s is not forward, so we can relocate all symbols */
5815 greloc_patch(ext_sym, s->c);
5816 } else {
5817 /* the two symbols are forward: merge them */
5818 p = (Reloc **)&ext_sym->c;
5819 while (*p != NULL)
5820 p = &(*p)->next;
5821 *p = (Reloc *)s->c;
5823 } else {
5824 /* external symbol already exists and is defined :
5825 patch all references to it */
5826 if (!(s->r & VT_FORWARD))
5827 error("'%s' defined twice", get_tok_str(s->v, NULL));
5828 greloc_patch(s, ext_sym->c);
5831 s = s1;
5835 /* compile a C file. Return non zero if errors. */
5836 int tcc_compile_file(const char *filename1)
5838 Sym *define_start;
5839 char buf[512];
5841 funcname = "";
5843 file = tcc_open(filename1);
5844 if (!file)
5845 error("file '%s' not found", filename1);
5846 include_stack_ptr = include_stack;
5847 ifdef_stack_ptr = ifdef_stack;
5849 vtop = vstack - 1;
5850 anon_sym = SYM_FIRST_ANOM;
5852 /* file info: full path + filename */
5853 if (do_debug) {
5854 getcwd(buf, sizeof(buf));
5855 pstrcat(buf, sizeof(buf), "/");
5856 put_stabs(buf, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5857 put_stabs(file->filename, N_SO, 0, 0,
5858 (unsigned long)text_section->data_ptr);
5860 /* define common 'char *' type because it is often used internally
5861 for arrays and struct dereference */
5862 char_pointer_type = mk_pointer(VT_BYTE);
5864 define_start = define_stack.top;
5865 inp();
5866 ch = '\n'; /* needed to parse correctly first preprocessor command */
5867 next();
5868 decl(VT_CONST);
5869 if (tok != -1)
5870 expect("declaration");
5871 tcc_close(file);
5873 /* end of translation unit info */
5874 if (do_debug) {
5875 put_stabn(N_SO, 0, 0, (unsigned long)text_section->data_ptr);
5878 /* reset define stack, but leave -Dsymbols (may be incorrect if
5879 they are undefined) */
5880 sym_pop(&define_stack, define_start);
5882 resolve_global_syms();
5884 sym_pop(&global_stack, NULL);
5886 return 0;
5889 /* define a symbol. A value can also be provided with the '=' operator */
5890 /* XXX: currently only handles integers and string defines. should use
5891 tcc parser, but would need a custom 'FILE *' */
5892 void define_symbol(const char *sym)
5894 char *p;
5895 BufferedFile bf1, *bf = &bf1;
5897 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
5898 p = strchr(bf->buffer, '=');
5899 if (!p) {
5900 /* default value */
5901 pstrcat(bf->buffer, IO_BUF_SIZE, " 1");
5902 } else {
5903 *p = ' ';
5906 /* init file structure */
5907 bf->fd = -1;
5908 bf->buf_ptr = bf->buffer;
5909 bf->buf_end = bf->buffer + strlen(bf->buffer);
5910 bf->filename[0] = '\0';
5911 bf->line_num = 1;
5912 file = bf;
5914 include_stack_ptr = include_stack;
5916 /* parse with define parser */
5917 inp();
5918 ch = '\n'; /* needed to parse correctly first preprocessor command */
5919 next_nomacro();
5920 parse_define();
5921 file = NULL;
5924 void undef_symbol(const char *sym)
5926 TokenSym *ts;
5927 Sym *s;
5928 ts = tok_alloc(sym, 0);
5929 s = sym_find1(&define_stack, tok);
5930 /* undefine symbol by putting an invalid name */
5931 if (s)
5932 sym_undef(&define_stack, s);
5935 /* open a dynamic library so that its symbol are available for
5936 compiled programs */
5937 void open_dll(char *libname)
5939 char buf[1024];
5940 void *h;
5942 snprintf(buf, sizeof(buf), "lib%s.so", libname);
5943 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
5944 if (!h)
5945 error((char *)dlerror());
5948 static void *resolve_sym(const char *sym)
5950 #ifdef CONFIG_TCC_BCHECK
5951 if (do_bounds_check) {
5952 void *ptr;
5953 ptr = bound_resolve_sym(sym);
5954 if (ptr)
5955 return ptr;
5957 #endif
5958 return dlsym(NULL, sym);
5961 void resolve_extern_syms(void)
5963 Sym *s, *s1;
5964 char *str;
5965 int addr;
5967 s = extern_stack.top;
5968 while (s != NULL) {
5969 s1 = s->prev;
5970 if (s->r & VT_FORWARD) {
5971 /* if there is at least one relocation to do, then find it
5972 and patch it */
5973 if (s->c) {
5974 str = get_tok_str(s->v, NULL);
5975 addr = (int)resolve_sym(str);
5976 if (!addr)
5977 error("unresolved external reference '%s'", str);
5978 greloc_patch(s, addr);
5981 s = s1;
5985 static int put_elf_str(Section *s, const char *sym)
5987 int c, offset;
5988 offset = s->data_ptr - s->data;
5989 for(;;) {
5990 c = *sym++;
5991 *s->data_ptr++ = c;
5992 if (c == '\0')
5993 break;
5995 return offset;
5998 static void put_elf_sym(Section *s,
5999 unsigned long value, unsigned long size,
6000 int info, int other, int shndx, const char *name)
6002 int name_offset;
6003 Elf32_Sym *sym;
6005 sym = (Elf32_Sym *)s->data_ptr;
6006 if (name)
6007 name_offset = put_elf_str(s->link, name);
6008 else
6009 name_offset = 0;
6010 sym->st_name = name_offset;
6011 sym->st_value = value;
6012 sym->st_size = size;
6013 sym->st_info = info;
6014 sym->st_other = other;
6015 sym->st_shndx = shndx;
6016 s->data_ptr += sizeof(Elf32_Sym);
6019 /* put stab debug information */
6021 typedef struct {
6022 unsigned long n_strx; /* index into string table of name */
6023 unsigned char n_type; /* type of symbol */
6024 unsigned char n_other; /* misc info (usually empty) */
6025 unsigned short n_desc; /* description field */
6026 unsigned long n_value; /* value of symbol */
6027 } Stab_Sym;
6029 static void put_stabs(const char *str, int type, int other, int desc, int value)
6031 Stab_Sym *sym;
6033 sym = (Stab_Sym *)stab_section->data_ptr;
6034 if (str) {
6035 sym->n_strx = put_elf_str(stabstr_section, str);
6036 } else {
6037 sym->n_strx = 0;
6039 sym->n_type = type;
6040 sym->n_other = other;
6041 sym->n_desc = desc;
6042 sym->n_value = value;
6044 stab_section->data_ptr += sizeof(Stab_Sym);
6047 static void put_stabn(int type, int other, int desc, int value)
6049 put_stabs(NULL, type, other, desc, value);
6052 static void put_stabd(int type, int other, int desc)
6054 put_stabs(NULL, type, other, desc, 0);
6057 /* output an ELF file (currently, only for testing) */
6058 /* XXX: generate dynamic reloc info + DLL tables */
6059 /* XXX: generate startup code */
6060 /* XXX: better program header generation */
6061 /* XXX: handle realloc'ed sections (instead of mmaping them) */
6062 void build_exe(char *filename)
6064 Elf32_Ehdr ehdr;
6065 FILE *f;
6066 int shnum, i, phnum, file_offset, offset, size, j;
6067 Section *sec, *strsec;
6068 Elf32_Shdr *shdr, *sh;
6069 Elf32_Phdr *phdr, *ph;
6071 memset(&ehdr, 0, sizeof(ehdr));
6073 /* we add a section for symbols */
6074 strsec = new_section(".shstrtab", SHT_STRTAB, 0);
6075 put_elf_str(strsec, "");
6077 /* count number of sections and compute number of program segments */
6078 shnum = 1; /* section index zero is reserved */
6079 phnum = 0;
6080 for(sec = first_section; sec != NULL; sec = sec->next) {
6081 shnum++;
6082 if (sec->sh_flags & SHF_ALLOC)
6083 phnum++;
6085 /* allocate section headers */
6086 shdr = malloc(shnum * sizeof(Elf32_Shdr));
6087 if (!shdr)
6088 error("memory full");
6089 memset(shdr, 0, shnum * sizeof(Elf32_Shdr));
6090 /* allocate program segment headers */
6091 phdr = malloc(phnum * sizeof(Elf32_Phdr));
6092 if (!phdr)
6093 error("memory full");
6094 memset(phdr, 0, phnum * sizeof(Elf32_Phdr));
6096 /* XXX: find correct load order */
6097 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
6098 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
6099 sh = &shdr[i];
6100 sh->sh_name = put_elf_str(strsec, sec->name);
6101 sh->sh_type = sec->sh_type;
6102 sh->sh_flags = sec->sh_flags;
6103 sh->sh_entsize = sec->sh_entsize;
6104 if (sec->link)
6105 sh->sh_link = sec->link->sh_num;
6106 if (sh->sh_type == SHT_STRTAB) {
6107 sh->sh_addralign = 1;
6108 } else if (sh->sh_type == SHT_SYMTAB ||
6109 (sh->sh_flags & SHF_ALLOC) == 0) {
6110 sh->sh_addralign = 4;
6111 } else {
6112 sh->sh_addr = (Elf32_Word)sec->data;
6113 sh->sh_addralign = 4096;
6115 sh->sh_size = (Elf32_Word)sec->data_ptr - (Elf32_Word)sec->data;
6116 /* align to section start */
6117 file_offset = (file_offset + sh->sh_addralign - 1) &
6118 ~(sh->sh_addralign - 1);
6119 sh->sh_offset = file_offset;
6120 file_offset += sh->sh_size;
6122 /* build program headers (simplistic - not fully correct) */
6123 j = 0;
6124 for(i=1;i<shnum;i++) {
6125 sh = &shdr[i];
6126 if (sh->sh_type == SHT_PROGBITS &&
6127 (sh->sh_flags & SHF_ALLOC) != 0) {
6128 ph = &phdr[j++];
6129 ph->p_type = PT_LOAD;
6130 ph->p_offset = sh->sh_offset;
6131 ph->p_vaddr = sh->sh_addr;
6132 ph->p_paddr = ph->p_vaddr;
6133 ph->p_filesz = sh->sh_size;
6134 ph->p_memsz = sh->sh_size;
6135 ph->p_flags = PF_R;
6136 if (sh->sh_flags & SHF_WRITE)
6137 ph->p_flags |= PF_W;
6138 if (sh->sh_flags & SHF_EXECINSTR)
6139 ph->p_flags |= PF_X;
6140 ph->p_align = sh->sh_addralign;
6144 /* align to 4 */
6145 file_offset = (file_offset + 3) & -4;
6147 /* fill header */
6148 ehdr.e_ident[0] = ELFMAG0;
6149 ehdr.e_ident[1] = ELFMAG1;
6150 ehdr.e_ident[2] = ELFMAG2;
6151 ehdr.e_ident[3] = ELFMAG3;
6152 ehdr.e_ident[4] = ELFCLASS32;
6153 ehdr.e_ident[5] = ELFDATA2LSB;
6154 ehdr.e_ident[6] = EV_CURRENT;
6155 ehdr.e_type = ET_EXEC;
6156 ehdr.e_machine = EM_386;
6157 ehdr.e_version = EV_CURRENT;
6158 ehdr.e_entry = 0; /* XXX: patch it */
6159 ehdr.e_phoff = sizeof(Elf32_Ehdr);
6160 ehdr.e_shoff = file_offset;
6161 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
6162 ehdr.e_phentsize = sizeof(Elf32_Phdr);
6163 ehdr.e_phnum = phnum;
6164 ehdr.e_shentsize = sizeof(Elf32_Shdr);
6165 ehdr.e_shnum = shnum;
6166 ehdr.e_shstrndx = shnum - 1;
6168 /* write elf file */
6169 f = fopen(filename, "w");
6170 if (!f)
6171 error("could not write '%s'", filename);
6172 fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
6173 fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
6174 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
6175 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
6176 sh = &shdr[i];
6177 while (offset < sh->sh_offset) {
6178 fputc(0, f);
6179 offset++;
6181 size = sec->data_ptr - sec->data;
6182 fwrite(sec->data, 1, size, f);
6183 offset += size;
6185 while (offset < ehdr.e_shoff) {
6186 fputc(0, f);
6187 offset++;
6189 fwrite(shdr, 1, shnum * sizeof(Elf32_Shdr), f);
6190 fclose(f);
6193 /* print the position in the source file of PC value 'pc' by reading
6194 the stabs debug information */
6195 static void rt_printline(unsigned long wanted_pc)
6197 Stab_Sym *sym, *sym_end;
6198 char func_name[128];
6199 unsigned long func_addr, last_pc, pc;
6200 const char *incl_files[INCLUDE_STACK_SIZE];
6201 int incl_index, len, last_line_num, i;
6202 const char *str, *p;
6204 func_name[0] = '\0';
6205 func_addr = 0;
6206 incl_index = 0;
6207 last_pc = 0xffffffff;
6208 last_line_num = 1;
6209 sym = (Stab_Sym *)stab_section->data + 1;
6210 sym_end = (Stab_Sym *)stab_section->data_ptr;
6211 while (sym < sym_end) {
6212 switch(sym->n_type) {
6213 /* function start or end */
6214 case N_FUN:
6215 if (sym->n_strx == 0) {
6216 func_name[0] = '\0';
6217 func_addr = 0;
6218 } else {
6219 str = stabstr_section->data + sym->n_strx;
6220 p = strchr(str, ':');
6221 if (!p) {
6222 pstrcpy(func_name, sizeof(func_name), str);
6223 } else {
6224 len = p - str;
6225 if (len > sizeof(func_name) - 1)
6226 len = sizeof(func_name) - 1;
6227 memcpy(func_name, str, len);
6228 func_name[len] = '\0';
6230 func_addr = sym->n_value;
6232 break;
6233 /* line number info */
6234 case N_SLINE:
6235 pc = sym->n_value + func_addr;
6236 if (wanted_pc >= last_pc && wanted_pc < pc)
6237 goto found;
6238 last_pc = pc;
6239 last_line_num = sym->n_desc;
6240 break;
6241 /* include files */
6242 case N_BINCL:
6243 str = stabstr_section->data + sym->n_strx;
6244 add_incl:
6245 if (incl_index < INCLUDE_STACK_SIZE) {
6246 incl_files[incl_index++] = str;
6248 break;
6249 case N_EINCL:
6250 if (incl_index > 1)
6251 incl_index--;
6252 break;
6253 case N_SO:
6254 if (sym->n_strx == 0) {
6255 incl_index = 0; /* end of translation unit */
6256 } else {
6257 str = stabstr_section->data + sym->n_strx;
6258 /* do not add path */
6259 len = strlen(str);
6260 if (len > 0 && str[len - 1] != '/')
6261 goto add_incl;
6263 break;
6265 sym++;
6267 /* did not find line number info: */
6268 fprintf(stderr, "(no debug info, pc=0x%08lx): ", wanted_pc);
6269 return;
6270 found:
6271 for(i = 0; i < incl_index - 1; i++)
6272 fprintf(stderr, "In file included from %s\n",
6273 incl_files[i]);
6274 if (incl_index > 0) {
6275 fprintf(stderr, "%s:%d: ",
6276 incl_files[incl_index - 1], last_line_num);
6278 if (func_name[0] != '\0') {
6279 fprintf(stderr, "in function '%s()': ", func_name);
6283 /* emit a run time error at position 'pc' */
6284 void rt_error(unsigned long pc, const char *fmt, ...)
6286 va_list ap;
6287 va_start(ap, fmt);
6289 rt_printline(pc);
6290 vfprintf(stderr, fmt, ap);
6291 fprintf(stderr, "\n");
6292 exit(255);
6293 va_end(ap);
6296 #ifndef WIN32
6297 /* signal handler for fatal errors */
6298 static void sig_error(int signum, siginfo_t *siginf, void *puc)
6300 struct ucontext *uc = puc;
6301 unsigned long pc;
6303 #ifdef __i386__
6304 pc = uc->uc_mcontext.gregs[14];
6305 #else
6306 #error please put the right sigcontext field
6307 #endif
6309 switch(signum) {
6310 case SIGFPE:
6311 switch(siginf->si_code) {
6312 case FPE_INTDIV:
6313 case FPE_FLTDIV:
6314 rt_error(pc, "division by zero");
6315 break;
6316 default:
6317 rt_error(pc, "floating point exception");
6318 break;
6320 break;
6321 case SIGBUS:
6322 case SIGSEGV:
6323 rt_error(pc, "dereferencing invalid pointer");
6324 break;
6325 case SIGILL:
6326 rt_error(pc, "illegal instruction");
6327 break;
6328 case SIGABRT:
6329 rt_error(pc, "abort() called");
6330 break;
6331 default:
6332 rt_error(pc, "caught signal %d", signum);
6333 break;
6335 exit(255);
6337 #endif
6339 /* launch the compiled program with the given arguments */
6340 int launch_exe(int argc, char **argv)
6342 Sym *s;
6343 int (*t)();
6345 s = sym_find1(&extern_stack, TOK_MAIN);
6346 if (!s || (s->r & VT_FORWARD))
6347 error("main() not defined");
6349 if (do_debug) {
6350 #ifdef WIN32
6351 error("debug mode currently not available for Windows");
6352 #else
6353 struct sigaction sigact;
6354 /* install TCC signal handlers to print debug info on fatal
6355 runtime errors */
6356 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
6357 sigact.sa_sigaction = sig_error;
6358 sigemptyset(&sigact.sa_mask);
6359 sigaction(SIGFPE, &sigact, NULL);
6360 sigaction(SIGILL, &sigact, NULL);
6361 sigaction(SIGSEGV, &sigact, NULL);
6362 sigaction(SIGBUS, &sigact, NULL);
6363 sigaction(SIGABRT, &sigact, NULL);
6364 #endif
6367 #ifdef CONFIG_TCC_BCHECK
6368 if (do_bounds_check) {
6369 int *p, *p_end;
6370 __bound_init();
6371 /* add all known static regions */
6372 p = (int *)bounds_section->data;
6373 p_end = (int *)bounds_section->data_ptr;
6374 while (p < p_end) {
6375 __bound_new_region((void *)p[0], p[1]);
6376 p += 2;
6379 #endif
6381 t = (int (*)())s->c;
6382 return (*t)(argc, argv);
6386 void help(void)
6388 printf("tcc version 0.9.6 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
6389 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
6390 " [-i infile] infile [infile_args...]\n"
6391 "\n"
6392 "-Idir : add include path 'dir'\n"
6393 "-Dsym[=val] : define 'sym' with value 'val'\n"
6394 "-Usym : undefine 'sym'\n"
6395 "-llib : link with dynamic library 'lib'\n"
6396 "-g : generate runtime debug info\n"
6397 #ifdef CONFIG_TCC_BCHECK
6398 "-b : compile with built-in memory and bounds checker (implies -g)\n"
6399 #endif
6400 "-i infile : compile infile\n"
6404 int main(int argc, char **argv)
6406 char *p, *r, *outfile;
6407 int optind;
6409 include_paths[0] = "/usr/include";
6410 include_paths[1] = "/usr/lib/tcc";
6411 include_paths[2] = "/usr/local/lib/tcc";
6412 nb_include_paths = 3;
6414 /* add all tokens */
6415 tok_ident = TOK_IDENT;
6416 p = tcc_keywords;
6417 while (*p) {
6418 r = p;
6419 while (*r++);
6420 tok_alloc(p, r - p - 1);
6421 p = r;
6424 /* standard defines */
6425 define_symbol("__STDC__");
6426 #ifdef __i386__
6427 define_symbol("__i386__");
6428 #endif
6429 /* tiny C specific defines */
6430 define_symbol("__TINYC__");
6432 /* create standard sections */
6433 text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
6434 data_section = new_section(".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6435 /* XXX: should change type to SHT_NOBITS */
6436 bss_section = new_section(".bss", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6438 optind = 1;
6439 outfile = NULL;
6440 while (1) {
6441 if (optind >= argc) {
6442 show_help:
6443 help();
6444 return 1;
6446 r = argv[optind];
6447 if (r[0] != '-')
6448 break;
6449 optind++;
6450 if (r[1] == 'I') {
6451 if (nb_include_paths >= INCLUDE_PATHS_MAX)
6452 error("too many include paths");
6453 include_paths[nb_include_paths++] = r + 2;
6454 } else if (r[1] == 'D') {
6455 define_symbol(r + 2);
6456 } else if (r[1] == 'U') {
6457 undef_symbol(r + 2);
6458 } else if (r[1] == 'l') {
6459 open_dll(r + 2);
6460 } else if (r[1] == 'i') {
6461 if (optind >= argc)
6462 goto show_help;
6463 tcc_compile_file(argv[optind++]);
6464 } else if (!strcmp(r + 1, "bench")) {
6465 do_bench = 1;
6466 #ifdef CONFIG_TCC_BCHECK
6467 } else if (r[1] == 'b') {
6468 if (!do_bounds_check) {
6469 do_bounds_check = 1;
6470 /* define symbol */
6471 define_symbol("__BOUNDS_CHECKING_ON");
6472 /* create bounds sections */
6473 bounds_section = new_section(".bounds",
6474 SHT_PROGBITS, SHF_ALLOC);
6475 lbounds_section = new_section(".lbounds",
6476 SHT_PROGBITS, SHF_ALLOC);
6477 /* debug is implied */
6478 goto debug_opt;
6480 #endif
6481 } else if (r[1] == 'g') {
6482 #ifdef CONFIG_TCC_BCHECK
6483 debug_opt:
6484 #endif
6485 if (!do_debug) {
6486 do_debug = 1;
6488 /* stab symbols */
6489 stab_section = new_section(".stab", SHT_PROGBITS, 0);
6490 stab_section->sh_entsize = sizeof(Stab_Sym);
6491 stabstr_section = new_section(".stabstr", SHT_STRTAB, 0);
6492 put_elf_str(stabstr_section, "");
6493 stab_section->link = stabstr_section;
6494 /* put first entry */
6495 put_stabs("", 0, 0, 0, 0);
6497 /* elf symbols */
6498 symtab_section = new_section(".symtab", SHT_SYMTAB, 0);
6499 symtab_section->sh_entsize = sizeof(Elf32_Sym);
6500 strtab_section = new_section(".strtab", SHT_STRTAB, 0);
6501 put_elf_str(strtab_section, "");
6502 symtab_section->link = strtab_section;
6503 put_elf_sym(symtab_section, 0, 0, 0, 0, 0, NULL);
6505 } else if (r[1] == 'o') {
6506 /* currently, only for testing, so not documented */
6507 if (optind >= argc)
6508 goto show_help;
6509 outfile = argv[optind++];
6510 } else {
6511 error("invalid option -- '%s'", r);
6515 tcc_compile_file(argv[optind]);
6517 if (do_bench) {
6518 printf("total: %d idents, %d lines, %d bytes\n",
6519 tok_ident - TOK_IDENT, total_lines, total_bytes);
6522 resolve_extern_syms();
6524 if (outfile) {
6525 build_exe(outfile);
6526 return 0;
6527 } else {
6528 return launch_exe(argc - optind, argv + optind);