optimized bound checking
[tinycc.git] / tcc.c
blob0554cd4f3e075acad4cd9721cd8e045bd300375d
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 #include "libtcc.h"
43 //#define DEBUG
44 /* preprocessor debug */
45 //#define PP_DEBUG
47 /* target selection */
48 //#define TCC_TARGET_I386 /* i386 code generator */
49 //#define TCC_TARGET_IL /* .NET CLI generator */
51 /* default target is I386 */
52 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_IL)
53 #define TCC_TARGET_I386
54 #endif
56 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_IL)
57 #define CONFIG_TCC_BCHECK /* enable bound checking code */
58 #endif
60 #ifndef CONFIG_TCC_PREFIX
61 #define CONFIG_TCC_PREFIX "/usr/local"
62 #endif
64 /* amount of virtual memory associated to a section (currently, we do
65 not realloc them) */
66 #define SECTION_VSIZE (1024 * 1024)
68 #define INCLUDE_STACK_SIZE 32
69 #define IFDEF_STACK_SIZE 64
70 #define VSTACK_SIZE 64
71 #define STRING_MAX_SIZE 1024
72 #define INCLUDE_PATHS_MAX 32
74 #define TOK_HASH_SIZE 2048 /* must be a power of two */
75 #define TOK_ALLOC_INCR 512 /* must be a power of two */
76 #define SYM_HASH_SIZE 1031
78 /* token symbol management */
79 typedef struct TokenSym {
80 struct TokenSym *hash_next;
81 int tok; /* token number */
82 int len;
83 char str[1];
84 } TokenSym;
86 /* constant value */
87 typedef union CValue {
88 long double ld;
89 double d;
90 float f;
91 int i;
92 unsigned int ui;
93 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
94 long long ll;
95 unsigned long long ull;
96 struct TokenSym *ts;
97 struct Sym *sym;
98 int tab[1];
99 } CValue;
101 /* value on stack */
102 typedef struct SValue {
103 int t; /* type */
104 unsigned short r; /* register + flags */
105 unsigned short r2; /* second register, used for 'long long'
106 type. If not used, set to VT_CONST */
107 CValue c; /* constant */
108 } SValue;
110 /* symbol management */
111 typedef struct Sym {
112 int v; /* symbol token */
113 int t; /* associated type */
114 int r; /* associated register */
115 int c; /* associated number */
116 struct Sym *next; /* next related symbol */
117 struct Sym *prev; /* prev symbol in stack */
118 struct Sym *hash_next; /* next symbol in hash table */
119 } Sym;
121 typedef struct SymStack {
122 struct Sym *top;
123 struct Sym *hash[SYM_HASH_SIZE];
124 } SymStack;
126 /* relocation entry (currently only used for functions or variables */
127 typedef struct Reloc {
128 int type; /* type of relocation */
129 int addr; /* address of relocation */
130 struct Reloc *next; /* next relocation */
131 } Reloc;
133 #define RELOC_ADDR32 1 /* 32 bits relocation */
134 #define RELOC_REL32 2 /* 32 bits relative relocation */
136 /* section definition */
137 typedef struct Section {
138 unsigned char *data; /* section data */
139 unsigned char *data_ptr; /* current data pointer */
140 int sh_num; /* elf section number */
141 int sh_type; /* elf section type */
142 int sh_flags; /* elf section flags */
143 int sh_entsize; /* elf entry size */
144 struct Section *link; /* link to another section */
145 struct Section *next;
146 char name[64]; /* section name */
147 } Section;
149 /* GNUC attribute definition */
150 typedef struct AttributeDef {
151 int aligned;
152 Section *section;
153 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
154 } AttributeDef;
156 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
157 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
158 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
160 /* stored in 'Sym.c' field */
161 #define FUNC_NEW 1 /* ansi function prototype */
162 #define FUNC_OLD 2 /* old function prototype */
163 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
165 /* stored in 'Sym.r' field */
166 #define FUNC_CDECL 0 /* standard c call */
167 #define FUNC_STDCALL 1 /* pascal c call */
169 /* field 'Sym.t' for macros */
170 #define MACRO_OBJ 0 /* object like macro */
171 #define MACRO_FUNC 1 /* function like macro */
173 /* type_decl() types */
174 #define TYPE_ABSTRACT 1 /* type without variable */
175 #define TYPE_DIRECT 2 /* type with variable */
177 #define IO_BUF_SIZE 8192
179 typedef struct BufferedFile {
180 unsigned char *buf_ptr;
181 unsigned char *buf_end;
182 int fd;
183 int line_num; /* current line number - here to simply code */
184 char filename[1024]; /* current filename - here to simply code */
185 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
186 } BufferedFile;
188 #define CH_EOB 0 /* end of buffer or '\0' char in file */
189 #define CH_EOF (-1) /* end of file */
191 /* parsing state (used to save parser state to reparse part of the
192 source several times) */
193 typedef struct ParseState {
194 int *macro_ptr;
195 int line_num;
196 int tok;
197 CValue tokc;
198 } ParseState;
200 /* used to record tokens */
201 typedef struct TokenString {
202 int *str;
203 int len;
204 int last_line_num;
205 } TokenString;
207 /* parser */
208 struct BufferedFile *file;
209 int ch, ch1, tok, tok1;
210 CValue tokc, tok1c;
212 /* sections */
213 Section *first_section;
214 int section_num;
215 Section *text_section, *data_section, *bss_section; /* predefined sections */
216 Section *cur_text_section; /* current section where function code is
217 generated */
218 /* bound check related sections */
219 Section *bounds_section; /* contains global data bound description */
220 Section *lbounds_section; /* contains local data bound description */
221 /* debug sections */
222 Section *stab_section, *stabstr_section, *symtab_section, *strtab_section;
224 /* loc : local variable index
225 ind : output code index
226 rsym: return symbol
227 anon_sym: anonymous symbol index
229 int rsym, anon_sym,
230 prog, ind, loc, const_wanted;
231 int global_expr; /* true if compound literals must be allocated
232 globally (used during initializers parsing */
233 int func_vt, func_vc; /* current function return type (used by
234 return instruction) */
235 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
236 int tok_ident;
237 TokenSym **table_ident;
238 TokenSym *hash_ident[TOK_HASH_SIZE];
239 char token_buf[STRING_MAX_SIZE + 1];
240 char *funcname;
241 /* contains global symbols which remain between each translation unit */
242 SymStack extern_stack;
243 SymStack define_stack, global_stack, local_stack, label_stack;
245 SValue vstack[VSTACK_SIZE], *vtop;
246 int *macro_ptr, *macro_ptr_allocated;
247 BufferedFile *include_stack[INCLUDE_STACK_SIZE], **include_stack_ptr;
248 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
249 char *include_paths[INCLUDE_PATHS_MAX];
250 int nb_include_paths;
251 int char_pointer_type;
253 /* compile with debug symbol (and use them if error during execution) */
254 int do_debug = 0;
256 /* compile with built-in memory and bounds checker */
257 int do_bounds_check = 0;
259 /* display benchmark infos */
260 int do_bench = 0;
261 int total_lines;
262 int total_bytes;
264 /* use GNU C extensions */
265 int gnu_ext = 1;
267 /* use Tiny C extensions */
268 int tcc_ext = 1;
270 struct TCCState {
271 int dummy;
274 /* The current value can be: */
275 #define VT_VALMASK 0x00ff
276 #define VT_CONST 0x00f0 /* constant in vc
277 (must be first non register value) */
278 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
279 #define VT_LOCAL 0x00f2 /* offset on stack */
280 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
281 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
282 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
283 #define VT_LVAL 0x0100 /* var is an lvalue */
284 #define VT_FORWARD 0x0200 /* value is forward reference */
285 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
286 char/short stored in integer registers) */
287 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
288 dereferencing value */
289 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
290 bounding function call point is in vc */
291 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
292 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
293 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
294 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
296 /* types */
297 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
299 #define VT_INT 0 /* integer type */
300 #define VT_BYTE 1 /* signed byte type */
301 #define VT_SHORT 2 /* short type */
302 #define VT_VOID 3 /* void type */
303 #define VT_PTR 4 /* pointer */
304 #define VT_ENUM 5 /* enum definition */
305 #define VT_FUNC 6 /* function type */
306 #define VT_STRUCT 7 /* struct/union definition */
307 #define VT_FLOAT 8 /* IEEE float */
308 #define VT_DOUBLE 9 /* IEEE double */
309 #define VT_LDOUBLE 10 /* IEEE long double */
310 #define VT_BOOL 11 /* ISOC99 boolean type */
311 #define VT_LLONG 12 /* 64 bit integer */
312 #define VT_LONG 13 /* long integer (NEVER USED as type, only
313 during parsing) */
314 #define VT_BTYPE 0x000f /* mask for basic type */
315 #define VT_UNSIGNED 0x0010 /* unsigned type */
316 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
317 #define VT_BITFIELD 0x0040 /* bitfield modifier */
319 /* storage */
320 #define VT_EXTERN 0x00000080 /* extern definition */
321 #define VT_STATIC 0x00000100 /* static variable */
322 #define VT_TYPEDEF 0x00000200 /* typedef definition */
324 /* type mask (except storage) */
325 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
327 /* token values */
329 /* warning: the following compare tokens depend on i386 asm code */
330 #define TOK_ULT 0x92
331 #define TOK_UGE 0x93
332 #define TOK_EQ 0x94
333 #define TOK_NE 0x95
334 #define TOK_ULE 0x96
335 #define TOK_UGT 0x97
336 #define TOK_LT 0x9c
337 #define TOK_GE 0x9d
338 #define TOK_LE 0x9e
339 #define TOK_GT 0x9f
341 #define TOK_LAND 0xa0
342 #define TOK_LOR 0xa1
344 #define TOK_DEC 0xa2
345 #define TOK_MID 0xa3 /* inc/dec, to void constant */
346 #define TOK_INC 0xa4
347 #define TOK_UDIV 0xb0 /* unsigned division */
348 #define TOK_UMOD 0xb1 /* unsigned modulo */
349 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
350 #define TOK_CINT 0xb3 /* number in tokc */
351 #define TOK_CCHAR 0xb4 /* char constant in tokc */
352 #define TOK_STR 0xb5 /* pointer to string in tokc */
353 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
354 #define TOK_LCHAR 0xb7
355 #define TOK_LSTR 0xb8
356 #define TOK_CFLOAT 0xb9 /* float constant */
357 #define TOK_LINENUM 0xba /* line number info */
358 #define TOK_CDOUBLE 0xc0 /* double constant */
359 #define TOK_CLDOUBLE 0xc1 /* long double constant */
360 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
361 #define TOK_ADDC1 0xc3 /* add with carry generation */
362 #define TOK_ADDC2 0xc4 /* add with carry use */
363 #define TOK_SUBC1 0xc5 /* add with carry generation */
364 #define TOK_SUBC2 0xc6 /* add with carry use */
365 #define TOK_CUINT 0xc8 /* unsigned int constant */
366 #define TOK_CLLONG 0xc9 /* long long constant */
367 #define TOK_CULLONG 0xca /* unsigned long long constant */
368 #define TOK_ARROW 0xcb
369 #define TOK_DOTS 0xcc /* three dots */
370 #define TOK_SHR 0xcd /* unsigned shift right */
372 #define TOK_SHL 0x01 /* shift left */
373 #define TOK_SAR 0x02 /* signed shift right */
375 /* assignement operators : normal operator or 0x80 */
376 #define TOK_A_MOD 0xa5
377 #define TOK_A_AND 0xa6
378 #define TOK_A_MUL 0xaa
379 #define TOK_A_ADD 0xab
380 #define TOK_A_SUB 0xad
381 #define TOK_A_DIV 0xaf
382 #define TOK_A_XOR 0xde
383 #define TOK_A_OR 0xfc
384 #define TOK_A_SHL 0x81
385 #define TOK_A_SAR 0x82
387 #define TOK_EOF (-1) /* end of file */
389 /* all identificators and strings have token above that */
390 #define TOK_IDENT 256
392 enum {
393 TOK_INT = TOK_IDENT,
394 TOK_VOID,
395 TOK_CHAR,
396 TOK_IF,
397 TOK_ELSE,
398 TOK_WHILE,
399 TOK_BREAK,
400 TOK_RETURN,
401 TOK_FOR,
402 TOK_EXTERN,
403 TOK_STATIC,
404 TOK_UNSIGNED,
405 TOK_GOTO,
406 TOK_DO,
407 TOK_CONTINUE,
408 TOK_SWITCH,
409 TOK_CASE,
411 /* ignored types Must have contiguous values */
412 TOK_CONST,
413 TOK_VOLATILE,
414 TOK_LONG,
415 TOK_REGISTER,
416 TOK_SIGNED,
417 TOK___SIGNED__, /* gcc keyword */
418 TOK_AUTO,
419 TOK_INLINE,
420 TOK___INLINE__, /* gcc keyword */
421 TOK_RESTRICT,
423 /* unsupported type */
424 TOK_FLOAT,
425 TOK_DOUBLE,
426 TOK_BOOL,
428 TOK_SHORT,
429 TOK_STRUCT,
430 TOK_UNION,
431 TOK_TYPEDEF,
432 TOK_DEFAULT,
433 TOK_ENUM,
434 TOK_SIZEOF,
435 TOK___ATTRIBUTE__,
437 /* preprocessor only */
438 TOK_UIDENT, /* first "user" ident (not keyword) */
439 TOK_DEFINE = TOK_UIDENT,
440 TOK_INCLUDE,
441 TOK_IFDEF,
442 TOK_IFNDEF,
443 TOK_ELIF,
444 TOK_ENDIF,
445 TOK_DEFINED,
446 TOK_UNDEF,
447 TOK_ERROR,
448 TOK_LINE,
449 TOK___LINE__,
450 TOK___FILE__,
451 TOK___DATE__,
452 TOK___TIME__,
453 TOK___VA_ARGS__,
455 /* special identifiers */
456 TOK___FUNC__,
457 TOK_MAIN,
458 /* attribute identifiers */
459 TOK_SECTION,
460 TOK___SECTION__,
461 TOK_ALIGNED,
462 TOK___ALIGNED__,
463 TOK_UNUSED,
464 TOK___UNUSED__,
465 TOK_CDECL,
466 TOK___CDECL,
467 TOK___CDECL__,
468 TOK_STDCALL,
469 TOK___STDCALL,
470 TOK___STDCALL__,
471 TOK_NORETURN,
472 TOK___NORETURN__,
475 char *tcc_keywords =
476 "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
477 "unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
478 "register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
479 "float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
480 "sizeof\0__attribute__\0"
481 /* the following are not keywords. They are included to ease parsing */
482 "define\0include\0ifdef\0ifndef\0elif\0endif\0"
483 "defined\0undef\0error\0line\0"
484 "__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0"
485 "__func__\0main\0"
486 /* attributes */
487 "section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0"
488 "cdecl\0__cdecl\0__cdecl__\0stdcall\0__stdcall\0__stdcall__\0"
489 "noreturn\0__noreturn__\0"
492 #ifdef WIN32
493 #define snprintf _snprintf
494 #endif
496 #if defined(WIN32) || defined(TCC_UCLIBC)
497 /* currently incorrect */
498 long double strtold(const char *nptr, char **endptr)
500 return (long double)strtod(nptr, endptr);
502 float strtof(const char *nptr, char **endptr)
504 return (float)strtod(nptr, endptr);
506 #else
507 /* XXX: need to define this to use them in non ISOC99 context */
508 extern float strtof (const char *__nptr, char **__endptr);
509 extern long double strtold (const char *__nptr, char **__endptr);
510 #endif
512 char *pstrcpy(char *buf, int buf_size, const char *s);
513 char *pstrcat(char *buf, int buf_size, const char *s);
515 void sum(int l);
516 void next(void);
517 void next_nomacro(void);
518 int expr_const(void);
519 void expr_eq(void);
520 void gexpr(void);
521 void decl(int l);
522 void decl_initializer(int t, int r, int c, int first, int size_only);
523 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init);
524 int gv(int rc);
525 void gv2(int rc1, int rc2);
526 void move_reg(int r, int s);
527 void save_regs(int n);
528 void save_reg(int r);
529 void vpop(void);
530 void vswap(void);
531 void vdup(void);
532 int get_reg(int rc);
534 void macro_subst(TokenString *tok_str,
535 Sym **nested_list, int *macro_str);
536 int save_reg_forced(int r);
537 void gen_op(int op);
538 void force_charshort_cast(int t);
539 void gen_cast(int t);
540 void vstore(void);
541 Sym *sym_find(int v);
542 Sym *sym_push(int v, int t, int r, int c);
544 /* type handling */
545 int type_size(int t, int *a);
546 int pointed_type(int t);
547 int pointed_size(int t);
548 int is_compatible_types(int t1, int t2);
549 int parse_btype(int *type_ptr, AttributeDef *ad);
550 int type_decl(AttributeDef *ad, int *v, int t, int td);
552 void error(const char *fmt, ...);
553 void rt_error(unsigned long pc, const char *fmt, ...);
554 void vpushi(int v);
555 void vset(int t, int r, int v);
556 void type_to_str(char *buf, int buf_size,
557 int t, const char *varstr);
559 /* section generation */
560 void greloc(Sym *s, int addr, int type);
561 static int put_elf_str(Section *s, const char *sym);
562 static void put_elf_sym(Section *s,
563 unsigned long value, unsigned long size,
564 int info, int other, int shndx, const char *name);
565 static void put_stabs(const char *str, int type, int other, int desc, int value);
566 static void put_stabn(int type, int other, int desc, int value);
567 static void put_stabd(int type, int other, int desc);
569 /* true if float/double/long double type */
570 static inline int is_float(int t)
572 int bt;
573 bt = t & VT_BTYPE;
574 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
577 #ifdef CONFIG_TCC_BCHECK
578 #include "bcheck.c"
579 #endif
581 #ifdef TCC_TARGET_I386
582 #include "i386-gen.c"
583 #endif
584 #ifdef TCC_TARGET_IL
585 #include "il-gen.c"
586 #endif
588 #ifdef CONFIG_TCC_STATIC
590 #define RTLD_LAZY 0x001
591 #define RTLD_NOW 0x002
592 #define RTLD_GLOBAL 0x100
594 /* dummy function for profiling */
595 void *dlopen(const char *filename, int flag)
597 return NULL;
600 const char *dlerror(void)
602 return "error";
605 typedef struct TCCSyms {
606 char *str;
607 void *ptr;
608 } TCCSyms;
610 #define TCCSYM(a) { #a, &a, },
612 /* add the symbol you want here if no dynamic linking is done */
613 static TCCSyms tcc_syms[] = {
614 TCCSYM(printf)
615 TCCSYM(fprintf)
616 TCCSYM(fopen)
617 TCCSYM(fclose)
618 { NULL, NULL },
621 void *dlsym(void *handle, const char *symbol)
623 TCCSyms *p;
624 p = tcc_syms;
625 while (p->str != NULL) {
626 if (!strcmp(p->str, symbol))
627 return p->ptr;
628 p++;
630 return NULL;
633 #endif
635 /********************************************************/
636 /* runtime library is there */
637 /* XXX: we suppose that the host compiler handles 'long long'. It
638 would not be difficult to suppress this assumption */
640 long long __divll(long long a, long long b)
642 return a / b;
645 long long __modll(long long a, long long b)
647 return a % b;
650 unsigned long long __divull(unsigned long long a, unsigned long long b)
652 return a / b;
655 unsigned long long __modull(unsigned long long a, unsigned long long b)
657 return a % b;
660 long long __sardi3(long long a, int b)
662 return a >> b;
665 unsigned long long __shrdi3(unsigned long long a, int b)
667 return a >> b;
670 long long __shldi3(long long a, int b)
672 return a << b;
675 float __ulltof(unsigned long long a)
677 return (float)a;
680 double __ulltod(unsigned long long a)
682 return (double)a;
685 long double __ulltold(unsigned long long a)
687 return (long double)a;
690 unsigned long long __ftoull(float a)
692 return (unsigned long long)a;
695 unsigned long long __dtoull(double a)
697 return (unsigned long long)a;
700 unsigned long long __ldtoull(long double a)
702 return (unsigned long long)a;
706 /********************************************************/
708 /* we use our own 'finite' function to avoid potential problems with
709 non standard math libs */
710 /* XXX: endianness dependant */
711 int ieee_finite(double d)
713 int *p = (int *)&d;
714 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
717 /* copy a string and truncate it. */
718 char *pstrcpy(char *buf, int buf_size, const char *s)
720 char *q, *q_end;
721 int c;
723 if (buf_size > 0) {
724 q = buf;
725 q_end = buf + buf_size - 1;
726 while (q < q_end) {
727 c = *s++;
728 if (c == '\0')
729 break;
730 *q++ = c;
732 *q = '\0';
734 return buf;
737 /* strcat and truncate. */
738 char *pstrcat(char *buf, int buf_size, const char *s)
740 int len;
741 len = strlen(buf);
742 if (len < buf_size)
743 pstrcpy(buf + len, buf_size - len, s);
744 return buf;
747 Section *new_section(const char *name, int sh_type, int sh_flags)
749 Section *sec, **psec;
750 void *data;
752 sec = malloc(sizeof(Section));
753 if (!sec)
754 error("memory full");
755 memset(sec, 0, sizeof(Section));
756 pstrcpy(sec->name, sizeof(sec->name), name);
757 sec->link = NULL;
758 sec->sh_num = ++section_num;
759 sec->sh_type = sh_type;
760 sec->sh_flags = sh_flags;
761 #ifdef WIN32
762 /* XXX: currently, a single malloc */
763 data = malloc(SECTION_VSIZE);
764 if (data == NULL)
765 error("could not alloc section '%s'", name);
766 #else
767 data = mmap(NULL, SECTION_VSIZE,
768 PROT_EXEC | PROT_READ | PROT_WRITE,
769 MAP_PRIVATE | MAP_ANONYMOUS,
770 -1, 0);
771 if (data == (void *)(-1))
772 error("could not mmap section '%s'", name);
773 #endif
774 sec->data = data;
775 sec->data_ptr = data;
776 psec = &first_section;
777 while (*psec != NULL)
778 psec = &(*psec)->next;
779 sec->next = NULL;
780 *psec = sec;
781 return sec;
784 /* return a reference to a section, and create it if it does not
785 exists */
786 Section *find_section(const char *name)
788 Section *sec;
790 for(sec = first_section; sec != NULL; sec = sec->next) {
791 if (!strcmp(name, sec->name))
792 return sec;
794 /* sections are created as PROGBITS */
795 return new_section(name, SHT_PROGBITS, SHF_ALLOC);
798 /* add a new relocation entry to symbol 's' */
799 void greloc(Sym *s, int addr, int type)
801 Reloc *p;
802 p = malloc(sizeof(Reloc));
803 if (!p)
804 error("memory full");
805 p->type = type;
806 p->addr = addr;
807 p->next = (Reloc *)s->c;
808 s->c = (int)p;
811 /* patch each relocation entry with value 'val' */
812 void greloc_patch(Sym *s, int val)
814 Reloc *p, *p1;
816 p = (Reloc *)s->c;
817 while (p != NULL) {
818 p1 = p->next;
819 greloc_patch1(p, val);
820 free(p);
821 p = p1;
823 s->c = val;
824 s->r &= ~VT_FORWARD;
828 static inline int isid(int c)
830 return (c >= 'a' && c <= 'z') ||
831 (c >= 'A' && c <= 'Z') ||
832 c == '_';
835 static inline int isnum(int c)
837 return c >= '0' && c <= '9';
840 static inline int toup(int c)
842 if (ch >= 'a' && ch <= 'z')
843 return ch - 'a' + 'A';
844 else
845 return ch;
848 void printline(void)
850 BufferedFile **f;
851 if (file) {
852 for(f = include_stack; f < include_stack_ptr; f++)
853 fprintf(stderr, "In file included from %s:%d:\n",
854 (*f)->filename, (*f)->line_num);
855 fprintf(stderr, "%s:%d: ", file->filename, file->line_num);
856 } else {
857 fprintf(stderr, "tcc: ");
861 void error(const char *fmt, ...)
863 va_list ap;
864 va_start(ap, fmt);
865 printline();
866 vfprintf(stderr, fmt, ap);
867 fprintf(stderr, "\n");
868 exit(1);
869 va_end(ap);
872 void expect(const char *msg)
874 error("%s expected", msg);
877 void warning(const char *fmt, ...)
879 va_list ap;
881 va_start(ap, fmt);
882 printline();
883 fprintf(stderr, "warning: ");
884 vfprintf(stderr, fmt, ap);
885 fprintf(stderr, "\n");
886 va_end(ap);
889 void skip(int c)
891 if (tok != c)
892 error("'%c' expected", c);
893 next();
896 void test_lvalue(void)
898 if (!(vtop->r & VT_LVAL))
899 expect("lvalue");
902 TokenSym *tok_alloc(const char *str, int len)
904 TokenSym *ts, **pts, **ptable;
905 int h, i;
907 if (len <= 0)
908 len = strlen(str);
909 h = 1;
910 for(i=0;i<len;i++)
911 h = (h * 263 + ((unsigned char *)str)[i]) & (TOK_HASH_SIZE - 1);
913 pts = &hash_ident[h];
914 while (1) {
915 ts = *pts;
916 if (!ts)
917 break;
918 if (ts->len == len && !memcmp(ts->str, str, len))
919 return ts;
920 pts = &(ts->hash_next);
923 if (tok_ident >= SYM_FIRST_ANOM)
924 error("memory full");
926 /* expand token table if needed */
927 i = tok_ident - TOK_IDENT;
928 if ((i % TOK_ALLOC_INCR) == 0) {
929 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
930 if (!ptable)
931 error("memory full");
932 table_ident = ptable;
935 ts = malloc(sizeof(TokenSym) + len);
936 if (!ts)
937 error("memory full");
938 table_ident[i] = ts;
939 ts->tok = tok_ident++;
940 ts->len = len;
941 ts->hash_next = NULL;
942 memcpy(ts->str, str, len + 1);
943 *pts = ts;
944 return ts;
947 void add_char(char **pp, int c)
949 char *p;
950 p = *pp;
951 if (c == '\'' || c == '\"' || c == '\\') {
952 /* XXX: could be more precise if char or string */
953 *p++ = '\\';
955 if (c >= 32 && c <= 126) {
956 *p++ = c;
957 } else {
958 *p++ = '\\';
959 if (c == '\n') {
960 *p++ = 'n';
961 } else {
962 *p++ = '0' + ((c >> 6) & 7);
963 *p++ = '0' + ((c >> 3) & 7);
964 *p++ = '0' + (c & 7);
967 *pp = p;
970 /* XXX: buffer overflow */
971 char *get_tok_str(int v, CValue *cv)
973 static char buf[STRING_MAX_SIZE + 1];
974 TokenSym *ts;
975 char *p;
976 int i;
978 if (v == TOK_CINT || v == TOK_CUINT) {
979 sprintf(buf, "%u", cv->ui);
980 return buf;
981 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
982 p = buf;
983 *p++ = '\'';
984 add_char(&p, cv->i);
985 *p++ = '\'';
986 *p = '\0';
987 return buf;
988 } else if (v == TOK_STR || v == TOK_LSTR) {
989 ts = cv->ts;
990 p = buf;
991 *p++ = '\"';
992 for(i=0;i<ts->len;i++)
993 add_char(&p, ts->str[i]);
994 *p++ = '\"';
995 *p = '\0';
996 return buf;
997 } else if (v < TOK_IDENT) {
998 p = buf;
999 *p++ = v;
1000 *p = '\0';
1001 return buf;
1002 } else if (v < tok_ident) {
1003 return table_ident[v - TOK_IDENT]->str;
1004 } else {
1005 /* should never happen */
1006 return NULL;
1010 /* push, without hashing */
1011 Sym *sym_push2(Sym **ps, int v, int t, int c)
1013 Sym *s;
1014 s = malloc(sizeof(Sym));
1015 if (!s)
1016 error("memory full");
1017 s->v = v;
1018 s->t = t;
1019 s->c = c;
1020 s->next = NULL;
1021 /* add in stack */
1022 s->prev = *ps;
1023 *ps = s;
1024 return s;
1027 /* find a symbol and return its associated structure. 's' is the top
1028 of the symbol stack */
1029 Sym *sym_find2(Sym *s, int v)
1031 while (s) {
1032 if (s->v == v)
1033 return s;
1034 s = s->prev;
1036 return NULL;
1039 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
1041 /* find a symbol and return its associated structure. 'st' is the
1042 symbol stack */
1043 Sym *sym_find1(SymStack *st, int v)
1045 Sym *s;
1047 s = st->hash[HASH_SYM(v)];
1048 while (s) {
1049 if (s->v == v)
1050 return s;
1051 s = s->hash_next;
1053 return NULL;
1056 Sym *sym_push1(SymStack *st, int v, int t, int c)
1058 Sym *s, **ps;
1059 s = sym_push2(&st->top, v, t, c);
1060 /* add in hash table */
1061 if (v) {
1062 ps = &st->hash[HASH_SYM(v)];
1063 s->hash_next = *ps;
1064 *ps = s;
1066 return s;
1069 /* find a symbol in the right symbol space */
1070 Sym *sym_find(int v)
1072 Sym *s;
1073 s = sym_find1(&local_stack, v);
1074 if (!s)
1075 s = sym_find1(&global_stack, v);
1076 return s;
1079 /* push a given symbol on the symbol stack */
1080 Sym *sym_push(int v, int t, int r, int c)
1082 Sym *s;
1083 if (local_stack.top)
1084 s = sym_push1(&local_stack, v, t, c);
1085 else
1086 s = sym_push1(&global_stack, v, t, c);
1087 s->r = r;
1088 return s;
1091 /* pop symbols until top reaches 'b' */
1092 void sym_pop(SymStack *st, Sym *b)
1094 Sym *s, *ss;
1096 s = st->top;
1097 while(s != b) {
1098 ss = s->prev;
1099 /* free hash table entry, except if symbol was freed (only
1100 used for #undef symbols) */
1101 if (s->v)
1102 st->hash[HASH_SYM(s->v)] = s->hash_next;
1103 free(s);
1104 s = ss;
1106 st->top = b;
1109 /* undefined a hashed symbol (used for #undef). Its name is set to
1110 zero */
1111 void sym_undef(SymStack *st, Sym *s)
1113 Sym **ss;
1114 ss = &st->hash[HASH_SYM(s->v)];
1115 while (*ss != NULL) {
1116 if (*ss == s)
1117 break;
1118 ss = &(*ss)->hash_next;
1120 *ss = s->hash_next;
1121 s->v = 0;
1124 /* I/O layer */
1126 BufferedFile *tcc_open(const char *filename)
1128 int fd;
1129 BufferedFile *bf;
1131 fd = open(filename, O_RDONLY);
1132 if (fd < 0)
1133 return NULL;
1134 bf = malloc(sizeof(BufferedFile));
1135 if (!bf) {
1136 close(fd);
1137 return NULL;
1139 bf->fd = fd;
1140 bf->buf_ptr = bf->buffer;
1141 bf->buf_end = bf->buffer;
1142 bf->buffer[0] = CH_EOB; /* put eob symbol */
1143 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1144 bf->line_num = 1;
1145 // printf("opening '%s'\n", filename);
1146 return bf;
1149 void tcc_close(BufferedFile *bf)
1151 total_lines += bf->line_num;
1152 close(bf->fd);
1153 free(bf);
1156 /* read one char. MUST call tcc_fillbuf if CH_EOB is read */
1157 #define TCC_GETC(bf) (*(bf)->buf_ptr++)
1159 /* fill input buffer and return next char */
1160 int tcc_getc_slow(BufferedFile *bf)
1162 int len;
1163 /* only tries to read if really end of buffer */
1164 if (bf->buf_ptr >= bf->buf_end) {
1165 if (bf->fd != -1) {
1166 len = read(bf->fd, bf->buffer, IO_BUF_SIZE);
1167 if (len < 0)
1168 len = 0;
1169 } else {
1170 len = 0;
1172 total_bytes += len;
1173 bf->buf_ptr = bf->buffer;
1174 bf->buf_end = bf->buffer + len;
1175 *bf->buf_end = CH_EOB;
1177 if (bf->buf_ptr < bf->buf_end) {
1178 return *bf->buf_ptr++;
1179 } else {
1180 bf->buf_ptr = bf->buf_end;
1181 return CH_EOF;
1185 /* no need to put that inline */
1186 void handle_eob(void)
1188 for(;;) {
1189 ch1 = tcc_getc_slow(file);
1190 if (ch1 != CH_EOF)
1191 return;
1193 if (include_stack_ptr == include_stack)
1194 return;
1195 /* add end of include file debug info */
1196 if (do_debug) {
1197 put_stabd(N_EINCL, 0, 0);
1199 /* pop include stack */
1200 tcc_close(file);
1201 include_stack_ptr--;
1202 file = *include_stack_ptr;
1206 /* read next char from current input file */
1207 static inline void inp(void)
1209 ch1 = TCC_GETC(file);
1210 /* end of buffer/file handling */
1211 if (ch1 == CH_EOB)
1212 handle_eob();
1213 if (ch1 == '\n')
1214 file->line_num++;
1215 // printf("ch1=%c 0x%x\n", ch1, ch1);
1218 /* input with '\\n' handling */
1219 static inline void minp(void)
1221 redo:
1222 ch = ch1;
1223 inp();
1224 if (ch == '\\' && ch1 == '\n') {
1225 inp();
1226 goto redo;
1228 //printf("ch=%c 0x%x\n", ch, ch);
1232 /* same as minp, but also skip comments */
1233 void cinp(void)
1235 int c;
1237 if (ch1 == '/') {
1238 inp();
1239 if (ch1 == '/') {
1240 /* single line C++ comments */
1241 inp();
1242 while (ch1 != '\n' && ch1 != -1)
1243 inp();
1244 inp();
1245 ch = ' '; /* return space */
1246 } else if (ch1 == '*') {
1247 /* C comments */
1248 inp();
1249 while (ch1 != -1) {
1250 c = ch1;
1251 inp();
1252 if (c == '*' && ch1 == '/') {
1253 inp();
1254 ch = ' '; /* return space */
1255 break;
1258 } else {
1259 ch = '/';
1261 } else {
1262 minp();
1266 void skip_spaces(void)
1268 while (ch == ' ' || ch == '\t')
1269 cinp();
1272 /* skip block of text until #else, #elif or #endif. skip also pairs of
1273 #if/#endif */
1274 void preprocess_skip(void)
1276 int a;
1277 a = 0;
1278 while (1) {
1279 while (ch != '\n') {
1280 if (ch == -1)
1281 expect("#endif");
1282 cinp();
1284 cinp();
1285 skip_spaces();
1286 if (ch == '#') {
1287 cinp();
1288 next_nomacro();
1289 if (a == 0 &&
1290 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1291 break;
1292 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1293 a++;
1294 else if (tok == TOK_ENDIF)
1295 a--;
1300 /* ParseState handling */
1302 /* XXX: currently, no include file info is stored. Thus, we cannot display
1303 accurate messages if the function or data definition spans multiple
1304 files */
1306 /* save current parse state in 's' */
1307 void save_parse_state(ParseState *s)
1309 s->line_num = file->line_num;
1310 s->macro_ptr = macro_ptr;
1311 s->tok = tok;
1312 s->tokc = tokc;
1315 /* restore parse state from 's' */
1316 void restore_parse_state(ParseState *s)
1318 file->line_num = s->line_num;
1319 macro_ptr = s->macro_ptr;
1320 tok = s->tok;
1321 tokc = s->tokc;
1324 /* return the number of additionnal 'ints' necessary to store the
1325 token */
1326 static inline int tok_ext_size(int t)
1328 switch(t) {
1329 /* 4 bytes */
1330 case TOK_CINT:
1331 case TOK_CUINT:
1332 case TOK_CCHAR:
1333 case TOK_LCHAR:
1334 case TOK_STR:
1335 case TOK_LSTR:
1336 case TOK_CFLOAT:
1337 case TOK_LINENUM:
1338 return 1;
1339 case TOK_CDOUBLE:
1340 case TOK_CLLONG:
1341 case TOK_CULLONG:
1342 return 2;
1343 case TOK_CLDOUBLE:
1344 return LDOUBLE_SIZE / 4;
1345 default:
1346 return 0;
1350 /* token string handling */
1352 static inline void tok_str_new(TokenString *s)
1354 s->str = NULL;
1355 s->len = 0;
1356 s->last_line_num = -1;
1359 static void tok_str_add(TokenString *s, int t)
1361 int len, *str;
1363 len = s->len;
1364 str = s->str;
1365 if ((len & 63) == 0) {
1366 str = realloc(str, (len + 64) * sizeof(int));
1367 if (!str)
1368 return;
1369 s->str = str;
1371 str[len++] = t;
1372 s->len = len;
1375 static void tok_str_add2(TokenString *s, int t, CValue *cv)
1377 int n, i;
1378 tok_str_add(s, t);
1379 n = tok_ext_size(t);
1380 for(i=0;i<n;i++)
1381 tok_str_add(s, cv->tab[i]);
1384 /* add the current parse token in token string 's' */
1385 static void tok_str_add_tok(TokenString *s)
1387 CValue cval;
1389 /* save line number info */
1390 if (file->line_num != s->last_line_num) {
1391 s->last_line_num = file->line_num;
1392 cval.i = s->last_line_num;
1393 tok_str_add2(s, TOK_LINENUM, &cval);
1395 tok_str_add2(s, tok, &tokc);
1398 /* get a token from an integer array and increment pointer accordingly */
1399 static int tok_get(int **tok_str, CValue *cv)
1401 int *p, t, n, i;
1403 p = *tok_str;
1404 t = *p++;
1405 n = tok_ext_size(t);
1406 for(i=0;i<n;i++)
1407 cv->tab[i] = *p++;
1408 *tok_str = p;
1409 return t;
1412 /* eval an expression for #if/#elif */
1413 int expr_preprocess(void)
1415 int c, t;
1416 TokenString str;
1418 tok_str_new(&str);
1419 while (1) {
1420 skip_spaces();
1421 if (ch == '\n')
1422 break;
1423 next(); /* do macro subst */
1424 if (tok == TOK_DEFINED) {
1425 next_nomacro();
1426 t = tok;
1427 if (t == '(')
1428 next_nomacro();
1429 c = sym_find1(&define_stack, tok) != 0;
1430 if (t == '(')
1431 next_nomacro();
1432 tok = TOK_CINT;
1433 tokc.i = c;
1434 } else if (tok >= TOK_IDENT) {
1435 /* if undefined macro */
1436 tok = TOK_CINT;
1437 tokc.i = 0;
1439 tok_str_add_tok(&str);
1441 tok_str_add(&str, -1); /* simulate end of file */
1442 tok_str_add(&str, 0);
1443 /* now evaluate C constant expression */
1444 macro_ptr = str.str;
1445 next();
1446 c = expr_const();
1447 macro_ptr = NULL;
1448 free(str.str);
1449 return c != 0;
1452 #if defined(DEBUG) || defined(PP_DEBUG)
1453 void tok_print(int *str)
1455 int t;
1456 CValue cval;
1458 while (1) {
1459 t = tok_get(&str, &cval);
1460 if (!t)
1461 break;
1462 printf(" %s", get_tok_str(t, &cval));
1464 printf("\n");
1466 #endif
1468 /* parse after #define */
1469 void parse_define(void)
1471 Sym *s, *first, **ps;
1472 int v, t, varg, is_vaargs;
1473 TokenString str;
1475 v = tok;
1476 /* XXX: should check if same macro (ANSI) */
1477 first = NULL;
1478 t = MACRO_OBJ;
1479 /* '(' must be just after macro definition for MACRO_FUNC */
1480 if (ch == '(') {
1481 next_nomacro();
1482 next_nomacro();
1483 ps = &first;
1484 while (tok != ')') {
1485 varg = tok;
1486 next_nomacro();
1487 is_vaargs = 0;
1488 if (varg == TOK_DOTS) {
1489 varg = TOK___VA_ARGS__;
1490 is_vaargs = 1;
1491 } else if (tok == TOK_DOTS && gnu_ext) {
1492 is_vaargs = 1;
1493 next_nomacro();
1495 if (varg < TOK_IDENT)
1496 error("badly punctuated parameter list");
1497 s = sym_push1(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
1498 *ps = s;
1499 ps = &s->next;
1500 if (tok != ',')
1501 break;
1502 next_nomacro();
1504 t = MACRO_FUNC;
1506 tok_str_new(&str);
1507 while (1) {
1508 skip_spaces();
1509 if (ch == '\n' || ch == -1)
1510 break;
1511 next_nomacro();
1512 tok_str_add2(&str, tok, &tokc);
1514 tok_str_add(&str, 0);
1515 #ifdef PP_DEBUG
1516 printf("define %s %d: ", get_tok_str(v, NULL), t);
1517 tok_print(str);
1518 #endif
1519 s = sym_push1(&define_stack, v, t, (int)str.str);
1520 s->next = first;
1523 void preprocess(void)
1525 int size, i, c;
1526 char buf[1024], *q, *p;
1527 char buf1[1024];
1528 BufferedFile *f;
1529 Sym *s;
1531 cinp();
1532 next_nomacro();
1533 redo:
1534 if (tok == TOK_DEFINE) {
1535 next_nomacro();
1536 parse_define();
1537 } else if (tok == TOK_UNDEF) {
1538 next_nomacro();
1539 s = sym_find1(&define_stack, tok);
1540 /* undefine symbol by putting an invalid name */
1541 if (s)
1542 sym_undef(&define_stack, s);
1543 } else if (tok == TOK_INCLUDE) {
1544 skip_spaces();
1545 if (ch == '<') {
1546 c = '>';
1547 goto read_name;
1548 } else if (ch == '\"') {
1549 c = ch;
1550 read_name:
1551 minp();
1552 q = buf;
1553 while (ch != c && ch != '\n' && ch != -1) {
1554 if ((q - buf) < sizeof(buf) - 1)
1555 *q++ = ch;
1556 minp();
1558 *q = '\0';
1559 } else {
1560 next();
1561 if (tok != TOK_STR)
1562 error("#include syntax error");
1563 pstrcpy(buf, sizeof(buf), get_tok_str(tok, &tokc));
1564 c = '\"';
1566 /* eat all spaces and comments after include */
1567 /* XXX: slightly incorrect */
1568 while (ch1 != '\n' && ch1 != -1)
1569 inp();
1571 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
1572 error("memory full");
1573 if (c == '\"') {
1574 /* first search in current dir if "header.h" */
1575 size = 0;
1576 p = strrchr(file->filename, '/');
1577 if (p)
1578 size = p + 1 - file->filename;
1579 if (size > sizeof(buf1) - 1)
1580 size = sizeof(buf1) - 1;
1581 memcpy(buf1, file->filename, size);
1582 buf1[size] = '\0';
1583 pstrcat(buf1, sizeof(buf1), buf);
1584 f = tcc_open(buf1);
1585 if (f)
1586 goto found;
1588 /* now search in standard include path */
1589 for(i=nb_include_paths - 1;i>=0;i--) {
1590 strcpy(buf1, include_paths[i]);
1591 strcat(buf1, "/");
1592 strcat(buf1, buf);
1593 f = tcc_open(buf1);
1594 if (f)
1595 goto found;
1597 error("include file '%s' not found", buf);
1598 f = NULL;
1599 found:
1600 /* push current file in stack */
1601 /* XXX: fix current line init */
1602 *include_stack_ptr++ = file;
1603 file = f;
1604 /* add include file debug info */
1605 if (do_debug) {
1606 put_stabs(file->filename, N_BINCL, 0, 0, 0);
1608 } else if (tok == TOK_IFNDEF) {
1609 c = 1;
1610 goto do_ifdef;
1611 } else if (tok == TOK_IF) {
1612 c = expr_preprocess();
1613 goto do_if;
1614 } else if (tok == TOK_IFDEF) {
1615 c = 0;
1616 do_ifdef:
1617 next_nomacro();
1618 c = (sym_find1(&define_stack, tok) != 0) ^ c;
1619 do_if:
1620 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
1621 error("memory full");
1622 *ifdef_stack_ptr++ = c;
1623 goto test_skip;
1624 } else if (tok == TOK_ELSE) {
1625 if (ifdef_stack_ptr == ifdef_stack)
1626 error("#else without matching #if");
1627 if (ifdef_stack_ptr[-1] & 2)
1628 error("#else after #else");
1629 c = (ifdef_stack_ptr[-1] ^= 3);
1630 goto test_skip;
1631 } else if (tok == TOK_ELIF) {
1632 if (ifdef_stack_ptr == ifdef_stack)
1633 error("#elif without matching #if");
1634 c = ifdef_stack_ptr[-1];
1635 if (c > 1)
1636 error("#elif after #else");
1637 /* last #if/#elif expression was true: we skip */
1638 if (c == 1)
1639 goto skip;
1640 c = expr_preprocess();
1641 ifdef_stack_ptr[-1] = c;
1642 test_skip:
1643 if (!(c & 1)) {
1644 skip:
1645 preprocess_skip();
1646 goto redo;
1648 } else if (tok == TOK_ENDIF) {
1649 if (ifdef_stack_ptr == ifdef_stack)
1650 error("#endif without matching #if");
1651 ifdef_stack_ptr--;
1652 } else if (tok == TOK_LINE) {
1653 next();
1654 if (tok != TOK_CINT)
1655 error("#line");
1656 file->line_num = tokc.i;
1657 skip_spaces();
1658 if (ch != '\n') {
1659 next();
1660 if (tok != TOK_STR)
1661 error("#line");
1662 pstrcpy(file->filename, sizeof(file->filename),
1663 get_tok_str(tok, &tokc));
1665 } else if (tok == TOK_ERROR) {
1666 error("#error");
1668 /* ignore other preprocess commands or #! for C scripts */
1669 while (ch != '\n' && ch != -1)
1670 cinp();
1673 /* read a number in base b */
1674 int getn(b)
1676 int n, t;
1677 n = 0;
1678 while (1) {
1679 if (ch >= 'a' && ch <= 'f')
1680 t = ch - 'a' + 10;
1681 else if (ch >= 'A' && ch <= 'F')
1682 t = ch - 'A' + 10;
1683 else if (isnum(ch))
1684 t = ch - '0';
1685 else
1686 break;
1687 if (t < 0 || t >= b)
1688 break;
1689 n = n * b + t;
1690 cinp();
1692 return n;
1695 /* read a character for string or char constant and eval escape codes */
1696 int getq()
1698 int c;
1700 c = ch;
1701 minp();
1702 if (c == '\\') {
1703 if (isnum(ch)) {
1704 /* at most three octal digits */
1705 c = ch - '0';
1706 minp();
1707 if (isnum(ch)) {
1708 c = c * 8 + ch - '0';
1709 minp();
1710 if (isnum(ch)) {
1711 c = c * 8 + ch - '0';
1712 minp();
1715 return c;
1716 } else if (ch == 'x') {
1717 minp();
1718 return getn(16);
1719 } else {
1720 if (ch == 'a')
1721 c = '\a';
1722 else if (ch == 'b')
1723 c = '\b';
1724 else if (ch == 'f')
1725 c = '\f';
1726 else if (ch == 'n')
1727 c = '\n';
1728 else if (ch == 'r')
1729 c = '\r';
1730 else if (ch == 't')
1731 c = '\t';
1732 else if (ch == 'v')
1733 c = '\v';
1734 else if (ch == 'e' && gnu_ext)
1735 c = 27;
1736 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
1737 c = ch;
1738 else
1739 error("invalid escaped char");
1740 minp();
1743 return c;
1746 /* we use 64 bit numbers */
1747 #define BN_SIZE 2
1749 /* bn = (bn << shift) | or_val */
1750 void bn_lshift(unsigned int *bn, int shift, int or_val)
1752 int i;
1753 unsigned int v;
1754 for(i=0;i<BN_SIZE;i++) {
1755 v = bn[i];
1756 bn[i] = (v << shift) | or_val;
1757 or_val = v >> (32 - shift);
1761 void bn_zero(unsigned int *bn)
1763 int i;
1764 for(i=0;i<BN_SIZE;i++) {
1765 bn[i] = 0;
1769 void parse_number(void)
1771 int b, t, shift, frac_bits, s, exp_val;
1772 char *q;
1773 unsigned int bn[BN_SIZE];
1774 double d;
1776 /* number */
1777 q = token_buf;
1778 t = ch;
1779 cinp();
1780 *q++ = t;
1781 b = 10;
1782 if (t == '.') {
1783 /* special dot handling */
1784 if (ch >= '0' && ch <= '9') {
1785 goto float_frac_parse;
1786 } else if (ch == '.') {
1787 cinp();
1788 if (ch != '.')
1789 expect("'.'");
1790 cinp();
1791 tok = TOK_DOTS;
1792 } else {
1793 /* dots */
1794 tok = t;
1796 return;
1797 } else if (t == '0') {
1798 if (ch == 'x' || ch == 'X') {
1799 q--;
1800 cinp();
1801 b = 16;
1802 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1803 q--;
1804 cinp();
1805 b = 2;
1808 /* parse all digits. cannot check octal numbers at this stage
1809 because of floating point constants */
1810 while (1) {
1811 if (ch >= 'a' && ch <= 'f')
1812 t = ch - 'a' + 10;
1813 else if (ch >= 'A' && ch <= 'F')
1814 t = ch - 'A' + 10;
1815 else if (isnum(ch))
1816 t = ch - '0';
1817 else
1818 break;
1819 if (t >= b)
1820 break;
1821 if (q >= token_buf + STRING_MAX_SIZE) {
1822 num_too_long:
1823 error("number too long");
1825 *q++ = ch;
1826 cinp();
1828 if (ch == '.' ||
1829 ((ch == 'e' || ch == 'E') && b == 10) ||
1830 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1831 if (b != 10) {
1832 /* NOTE: strtox should support that for hexa numbers, but
1833 non ISOC99 libcs do not support it, so we prefer to do
1834 it by hand */
1835 /* hexadecimal or binary floats */
1836 /* XXX: handle overflows */
1837 *q = '\0';
1838 if (b == 16)
1839 shift = 4;
1840 else
1841 shift = 2;
1842 bn_zero(bn);
1843 q = token_buf;
1844 while (1) {
1845 t = *q++;
1846 if (t == '\0') {
1847 break;
1848 } else if (t >= 'a') {
1849 t = t - 'a' + 10;
1850 } else if (t >= 'A') {
1851 t = t - 'A' + 10;
1852 } else {
1853 t = t - '0';
1855 bn_lshift(bn, shift, t);
1857 frac_bits = 0;
1858 if (ch == '.') {
1859 cinp();
1860 while (1) {
1861 t = ch;
1862 if (t >= 'a' && t <= 'f') {
1863 t = t - 'a' + 10;
1864 } else if (t >= 'A' && t <= 'F') {
1865 t = t - 'A' + 10;
1866 } else if (t >= '0' && t <= '9') {
1867 t = t - '0';
1868 } else {
1869 break;
1871 if (t >= b)
1872 error("invalid digit");
1873 bn_lshift(bn, shift, t);
1874 frac_bits += shift;
1875 cinp();
1878 if (ch != 'p' && ch != 'P')
1879 error("exponent expected");
1880 cinp();
1881 s = 1;
1882 exp_val = 0;
1883 if (ch == '+') {
1884 cinp();
1885 } else if (ch == '-') {
1886 s = -1;
1887 cinp();
1889 if (ch < '0' || ch > '9')
1890 error("exponent digits expected");
1891 while (ch >= '0' && ch <= '9') {
1892 exp_val = exp_val * 10 + ch - '0';
1893 cinp();
1895 exp_val = exp_val * s;
1897 /* now we can generate the number */
1898 /* XXX: should patch directly float number */
1899 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1900 d = ldexp(d, exp_val - frac_bits);
1901 t = toup(ch);
1902 if (t == 'F') {
1903 cinp();
1904 tok = TOK_CFLOAT;
1905 /* float : should handle overflow */
1906 tokc.f = (float)d;
1907 } else if (t == 'L') {
1908 cinp();
1909 tok = TOK_CLDOUBLE;
1910 /* XXX: not large enough */
1911 tokc.ld = (long double)d;
1912 } else {
1913 tok = TOK_CDOUBLE;
1914 tokc.d = d;
1916 } else {
1917 /* decimal floats */
1918 if (ch == '.') {
1919 if (q >= token_buf + STRING_MAX_SIZE)
1920 goto num_too_long;
1921 *q++ = ch;
1922 cinp();
1923 float_frac_parse:
1924 while (ch >= '0' && ch <= '9') {
1925 if (q >= token_buf + STRING_MAX_SIZE)
1926 goto num_too_long;
1927 *q++ = ch;
1928 cinp();
1931 if (ch == 'e' || ch == 'E') {
1932 if (q >= token_buf + STRING_MAX_SIZE)
1933 goto num_too_long;
1934 *q++ = ch;
1935 cinp();
1936 if (ch == '-' || ch == '+') {
1937 if (q >= token_buf + STRING_MAX_SIZE)
1938 goto num_too_long;
1939 *q++ = ch;
1940 cinp();
1942 if (ch < '0' || ch > '9')
1943 error("exponent digits expected");
1944 while (ch >= '0' && ch <= '9') {
1945 if (q >= token_buf + STRING_MAX_SIZE)
1946 goto num_too_long;
1947 *q++ = ch;
1948 cinp();
1951 *q = '\0';
1952 t = toup(ch);
1953 errno = 0;
1954 if (t == 'F') {
1955 cinp();
1956 tok = TOK_CFLOAT;
1957 tokc.f = strtof(token_buf, NULL);
1958 } else if (t == 'L') {
1959 cinp();
1960 tok = TOK_CLDOUBLE;
1961 tokc.ld = strtold(token_buf, NULL);
1962 } else {
1963 tok = TOK_CDOUBLE;
1964 tokc.d = strtod(token_buf, NULL);
1967 } else {
1968 unsigned long long n, n1;
1969 int lcount;
1971 /* integer number */
1972 *q = '\0';
1973 q = token_buf;
1974 if (b == 10 && *q == '0') {
1975 b = 8;
1976 q++;
1978 n = 0;
1979 while(1) {
1980 t = *q++;
1981 /* no need for checks except for base 10 / 8 errors */
1982 if (t == '\0') {
1983 break;
1984 } else if (t >= 'a') {
1985 t = t - 'a' + 10;
1986 } else if (t >= 'A') {
1987 t = t - 'A' + 10;
1988 } else {
1989 t = t - '0';
1990 if (t >= b)
1991 error("invalid digit");
1993 n1 = n;
1994 n = n * b + t;
1995 /* detect overflow */
1996 if (n < n1)
1997 error("integer constant overflow");
2000 /* XXX: not exactly ANSI compliant */
2001 if ((n & 0xffffffff00000000LL) != 0) {
2002 if ((n >> 63) != 0)
2003 tok = TOK_CULLONG;
2004 else
2005 tok = TOK_CLLONG;
2006 } else if (n > 0x7fffffff) {
2007 tok = TOK_CUINT;
2008 } else {
2009 tok = TOK_CINT;
2011 lcount = 0;
2012 for(;;) {
2013 t = toup(ch);
2014 if (t == 'L') {
2015 if (lcount >= 2)
2016 error("three 'l' in integer constant");
2017 lcount++;
2018 if (lcount == 2) {
2019 if (tok == TOK_CINT)
2020 tok = TOK_CLLONG;
2021 else if (tok == TOK_CUINT)
2022 tok = TOK_CULLONG;
2024 cinp();
2025 } else if (t == 'U') {
2026 if (tok == TOK_CINT)
2027 tok = TOK_CUINT;
2028 else if (tok == TOK_CLLONG)
2029 tok = TOK_CULLONG;
2030 cinp();
2031 } else {
2032 break;
2035 if (tok == TOK_CINT || tok == TOK_CUINT)
2036 tokc.ui = n;
2037 else
2038 tokc.ull = n;
2043 /* return next token without macro substitution */
2044 void next_nomacro1(void)
2046 int b;
2047 char *q;
2048 TokenSym *ts;
2050 /* skip spaces */
2051 while(1) {
2052 while (ch == '\n') {
2053 cinp();
2054 while (ch == ' ' || ch == '\t')
2055 cinp();
2056 if (ch == '#') {
2057 /* preprocessor command if # at start of line after
2058 spaces */
2059 preprocess();
2062 if (ch != ' ' && ch != '\t' && ch != '\f')
2063 break;
2064 cinp();
2066 if (isid(ch)) {
2067 q = token_buf;
2068 *q++ = ch;
2069 cinp();
2070 if (q[-1] == 'L') {
2071 if (ch == '\'') {
2072 tok = TOK_LCHAR;
2073 goto char_const;
2075 if (ch == '\"') {
2076 tok = TOK_LSTR;
2077 goto str_const;
2080 while (isid(ch) || isnum(ch)) {
2081 if (q >= token_buf + STRING_MAX_SIZE)
2082 error("ident too long");
2083 *q++ = ch;
2084 cinp();
2086 *q = '\0';
2087 ts = tok_alloc(token_buf, q - token_buf);
2088 tok = ts->tok;
2089 } else if (isnum(ch) || ch == '.') {
2090 parse_number();
2091 } else if (ch == '\'') {
2092 tok = TOK_CCHAR;
2093 char_const:
2094 minp();
2095 tokc.i = getq();
2096 if (ch != '\'')
2097 expect("\'");
2098 minp();
2099 } else if (ch == '\"') {
2100 tok = TOK_STR;
2101 str_const:
2102 minp();
2103 q = token_buf;
2104 while (ch != '\"') {
2105 b = getq();
2106 if (ch == -1)
2107 error("unterminated string");
2108 if (q >= token_buf + STRING_MAX_SIZE)
2109 error("string too long");
2110 *q++ = b;
2112 *q = '\0';
2113 tokc.ts = tok_alloc(token_buf, q - token_buf);
2114 minp();
2115 } else {
2116 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
2117 /* two chars */
2118 tok = ch;
2119 cinp();
2120 while (*q) {
2121 if (*q == tok && q[1] == ch) {
2122 cinp();
2123 tok = q[2] & 0xff;
2124 /* three chars tests */
2125 if (tok == TOK_SHL || tok == TOK_SAR) {
2126 if (ch == '=') {
2127 tok = tok | 0x80;
2128 cinp();
2130 } else if (tok == TOK_DOTS) {
2131 if (ch != '.')
2132 error("parse error");
2133 cinp();
2135 return;
2137 q = q + 3;
2139 /* single char substitutions */
2140 if (tok == '<')
2141 tok = TOK_LT;
2142 else if (tok == '>')
2143 tok = TOK_GT;
2147 /* return next token without macro substitution. Can read input from
2148 macro_ptr buffer */
2149 void next_nomacro()
2151 if (macro_ptr) {
2152 redo:
2153 tok = *macro_ptr;
2154 if (tok) {
2155 tok = tok_get(&macro_ptr, &tokc);
2156 if (tok == TOK_LINENUM) {
2157 file->line_num = tokc.i;
2158 goto redo;
2161 } else {
2162 next_nomacro1();
2166 /* substitute args in macro_str and return allocated string */
2167 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
2169 int *st, last_tok, t, notfirst;
2170 Sym *s;
2171 TokenSym *ts;
2172 CValue cval;
2173 TokenString str;
2175 tok_str_new(&str);
2176 last_tok = 0;
2177 while(1) {
2178 t = tok_get(&macro_str, &cval);
2179 if (!t)
2180 break;
2181 if (t == '#') {
2182 /* stringize */
2183 t = tok_get(&macro_str, &cval);
2184 if (!t)
2185 break;
2186 s = sym_find2(args, t);
2187 if (s) {
2188 token_buf[0] = '\0';
2189 st = (int *)s->c;
2190 notfirst = 0;
2191 while (*st) {
2192 if (notfirst)
2193 pstrcat(token_buf, sizeof(token_buf), " ");
2194 t = tok_get(&st, &cval);
2195 pstrcat(token_buf, sizeof(token_buf), get_tok_str(t, &cval));
2196 notfirst = 1;
2198 #ifdef PP_DEBUG
2199 printf("stringize: %s\n", token_buf);
2200 #endif
2201 /* add string */
2202 ts = tok_alloc(token_buf, 0);
2203 cval.ts = ts;
2204 tok_str_add2(&str, TOK_STR, &cval);
2205 } else {
2206 tok_str_add2(&str, t, &cval);
2208 } else if (t >= TOK_IDENT) {
2209 s = sym_find2(args, t);
2210 if (s) {
2211 st = (int *)s->c;
2212 /* if '##' is present before or after, no arg substitution */
2213 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
2214 /* special case for var arg macros : ## eats the
2215 ',' if empty VA_ARGS riable. */
2216 /* XXX: test of the ',' is not 100%
2217 reliable. should fix it to avoid security
2218 problems */
2219 if (gnu_ext && s->t && *st == 0 &&
2220 last_tok == TOK_TWOSHARPS &&
2221 str.len >= 2&& str.str[str.len - 2] == ',') {
2222 /* suppress ',' '##' */
2223 str.len -= 2;
2224 } else {
2225 while (*st)
2226 tok_str_add(&str, *st++);
2228 } else {
2229 macro_subst(&str, nested_list, st);
2231 } else {
2232 tok_str_add(&str, t);
2234 } else {
2235 tok_str_add2(&str, t, &cval);
2237 last_tok = t;
2239 tok_str_add(&str, 0);
2240 return str.str;
2243 /* handle the '##' operator */
2244 int *macro_twosharps(int *macro_str)
2246 TokenSym *ts;
2247 int *macro_ptr1;
2248 int t;
2249 char *p;
2250 CValue cval;
2251 TokenString macro_str1;
2253 tok_str_new(&macro_str1);
2254 tok = 0;
2255 while (1) {
2256 next_nomacro();
2257 if (tok == 0)
2258 break;
2259 while (*macro_ptr == TOK_TWOSHARPS) {
2260 macro_ptr++;
2261 macro_ptr1 = macro_ptr;
2262 t = *macro_ptr;
2263 if (t) {
2264 t = tok_get(&macro_ptr, &cval);
2265 /* XXX: we handle only most common cases:
2266 ident + ident or ident + number */
2267 if (tok >= TOK_IDENT &&
2268 (t >= TOK_IDENT || t == TOK_CINT)) {
2269 p = get_tok_str(tok, &tokc);
2270 pstrcpy(token_buf, sizeof(token_buf), p);
2271 p = get_tok_str(t, &cval);
2272 pstrcat(token_buf, sizeof(token_buf), p);
2273 ts = tok_alloc(token_buf, 0);
2274 tok = ts->tok; /* modify current token */
2275 } else {
2276 /* cannot merge tokens: skip '##' */
2277 macro_ptr = macro_ptr1;
2278 break;
2282 tok_str_add2(&macro_str1, tok, &tokc);
2284 tok_str_add(&macro_str1, 0);
2285 return macro_str1.str;
2288 /* do macro substitution of macro_str and add result to
2289 (tok_str,tok_len). If macro_str is NULL, then input stream token is
2290 substituted. 'nested_list' is the list of all macros we got inside
2291 to avoid recursing. */
2292 void macro_subst(TokenString *tok_str,
2293 Sym **nested_list, int *macro_str)
2295 Sym *s, *args, *sa, *sa1;
2296 int parlevel, *mstr, t, *saved_macro_ptr;
2297 int mstr_allocated, *macro_str1;
2298 CValue cval;
2299 TokenString str;
2301 saved_macro_ptr = macro_ptr;
2302 macro_ptr = macro_str;
2303 macro_str1 = NULL;
2304 if (macro_str) {
2305 /* first scan for '##' operator handling */
2306 macro_str1 = macro_twosharps(macro_str);
2307 macro_ptr = macro_str1;
2310 while (1) {
2311 next_nomacro();
2312 if (tok == 0)
2313 break;
2314 /* special macros */
2315 if (tok == TOK___LINE__) {
2316 cval.i = file->line_num;
2317 tok_str_add2(tok_str, TOK_CINT, &cval);
2318 } else if (tok == TOK___FILE__) {
2319 cval.ts = tok_alloc(file->filename, 0);
2320 tok_str_add2(tok_str, TOK_STR, &cval);
2321 } else if (tok == TOK___DATE__) {
2322 cval.ts = tok_alloc("Jan 1 1970", 0);
2323 tok_str_add2(tok_str, TOK_STR, &cval);
2324 } else if (tok == TOK___TIME__) {
2325 cval.ts = tok_alloc("00:00:00", 0);
2326 tok_str_add2(tok_str, TOK_STR, &cval);
2327 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
2328 /* if symbol is a macro, prepare substitution */
2329 /* if nested substitution, do nothing */
2330 if (sym_find2(*nested_list, tok))
2331 goto no_subst;
2332 mstr = (int *)s->c;
2333 mstr_allocated = 0;
2334 if (s->t == MACRO_FUNC) {
2335 /* NOTE: we do not use next_nomacro to avoid eating the
2336 next token. XXX: find better solution */
2337 if (macro_ptr) {
2338 t = *macro_ptr;
2339 } else {
2340 while (ch == ' ' || ch == '\t' || ch == '\n')
2341 cinp();
2342 t = ch;
2344 if (t != '(') /* no macro subst */
2345 goto no_subst;
2347 /* argument macro */
2348 next_nomacro();
2349 next_nomacro();
2350 args = NULL;
2351 sa = s->next;
2352 /* NOTE: empty args are allowed, except if no args */
2353 for(;;) {
2354 /* handle '()' case */
2355 if (!args && tok == ')')
2356 break;
2357 if (!sa)
2358 error("macro '%s' used with too many args",
2359 get_tok_str(s->v, 0));
2360 tok_str_new(&str);
2361 parlevel = 0;
2362 /* NOTE: non zero sa->t indicates VA_ARGS */
2363 while ((parlevel > 0 ||
2364 (tok != ')' &&
2365 (tok != ',' || sa->t))) &&
2366 tok != -1) {
2367 if (tok == '(')
2368 parlevel++;
2369 else if (tok == ')')
2370 parlevel--;
2371 tok_str_add2(&str, tok, &tokc);
2372 next_nomacro();
2374 tok_str_add(&str, 0);
2375 sym_push2(&args, sa->v & ~SYM_FIELD, sa->t, (int)str.str);
2376 sa = sa->next;
2377 if (tok == ')') {
2378 /* special case for gcc var args: add an empty
2379 var arg argument if it is omitted */
2380 if (sa && sa->t && gnu_ext)
2381 continue;
2382 else
2383 break;
2385 if (tok != ',')
2386 expect(",");
2387 next_nomacro();
2389 if (sa) {
2390 error("macro '%s' used with too few args",
2391 get_tok_str(s->v, 0));
2394 /* now subst each arg */
2395 mstr = macro_arg_subst(nested_list, mstr, args);
2396 /* free memory */
2397 sa = args;
2398 while (sa) {
2399 sa1 = sa->prev;
2400 free((int *)sa->c);
2401 free(sa);
2402 sa = sa1;
2404 mstr_allocated = 1;
2406 sym_push2(nested_list, s->v, 0, 0);
2407 macro_subst(tok_str, nested_list, mstr);
2408 /* pop nested defined symbol */
2409 sa1 = *nested_list;
2410 *nested_list = sa1->prev;
2411 free(sa1);
2412 if (mstr_allocated)
2413 free(mstr);
2414 } else {
2415 no_subst:
2416 /* no need to add if reading input stream */
2417 if (!macro_str)
2418 return;
2419 tok_str_add2(tok_str, tok, &tokc);
2421 /* only replace one macro while parsing input stream */
2422 if (!macro_str)
2423 return;
2425 macro_ptr = saved_macro_ptr;
2426 if (macro_str1)
2427 free(macro_str1);
2430 /* return next token with macro substitution */
2431 void next(void)
2433 Sym *nested_list;
2434 TokenString str;
2436 /* special 'ungettok' case for label parsing */
2437 if (tok1) {
2438 tok = tok1;
2439 tokc = tok1c;
2440 tok1 = 0;
2441 } else {
2442 redo:
2443 if (!macro_ptr) {
2444 /* if not reading from macro substituted string, then try
2445 to substitute */
2446 /* XXX: optimize non macro case */
2447 tok_str_new(&str);
2448 nested_list = NULL;
2449 macro_subst(&str, &nested_list, NULL);
2450 if (str.str) {
2451 tok_str_add(&str, 0);
2452 macro_ptr = str.str;
2453 macro_ptr_allocated = str.str;
2454 goto redo;
2456 if (tok == 0)
2457 goto redo;
2458 } else {
2459 next_nomacro();
2460 if (tok == 0) {
2461 /* end of macro string: free it */
2462 free(macro_ptr_allocated);
2463 macro_ptr = NULL;
2464 goto redo;
2468 #if defined(DEBUG)
2469 printf("token = %s\n", get_tok_str(tok, tokc));
2470 #endif
2473 void swap(int *p, int *q)
2475 int t;
2476 t = *p;
2477 *p = *q;
2478 *q = t;
2481 void vsetc(int t, int r, CValue *vc)
2483 if (vtop >= vstack + VSTACK_SIZE)
2484 error("memory full");
2485 /* cannot let cpu flags if other instruction are generated */
2486 /* XXX: VT_JMP test too ? */
2487 if ((vtop->r & VT_VALMASK) == VT_CMP)
2488 gv(RC_INT);
2489 vtop++;
2490 vtop->t = t;
2491 vtop->r = r;
2492 vtop->r2 = VT_CONST;
2493 vtop->c = *vc;
2496 /* push integer constant */
2497 void vpushi(int v)
2499 CValue cval;
2500 cval.i = v;
2501 vsetc(VT_INT, VT_CONST, &cval);
2504 void vset(int t, int r, int v)
2506 CValue cval;
2508 cval.i = v;
2509 vsetc(t, r, &cval);
2512 void vswap(void)
2514 SValue tmp;
2516 tmp = vtop[0];
2517 vtop[0] = vtop[-1];
2518 vtop[-1] = tmp;
2521 void vpushv(SValue *v)
2523 if (vtop >= vstack + VSTACK_SIZE)
2524 error("memory full");
2525 vtop++;
2526 *vtop = *v;
2529 void vdup(void)
2531 vpushv(vtop);
2534 /* save r to the memory stack, and mark it as being free */
2535 void save_reg(int r)
2537 int l, i, saved, t, size, align;
2538 SValue *p, sv;
2540 /* modify all stack values */
2541 saved = 0;
2542 l = 0;
2543 for(p=vstack;p<=vtop;p++) {
2544 i = p->r & VT_VALMASK;
2545 if ((p->r & VT_VALMASK) == r ||
2546 (p->r2 & VT_VALMASK) == r) {
2547 /* must save value on stack if not already done */
2548 if (!saved) {
2549 /* store register in the stack */
2550 t = p->t;
2551 if ((p->r & VT_LVAL) ||
2552 (!is_float(t) && (t & VT_BTYPE) != VT_LLONG))
2553 t = VT_INT;
2554 size = type_size(t, &align);
2555 loc = (loc - size) & -align;
2556 sv.t = t;
2557 sv.r = VT_LOCAL | VT_LVAL;
2558 sv.c.ul = loc;
2559 store(r, &sv);
2560 #ifdef TCC_TARGET_I386
2561 /* x86 specific: need to pop fp register ST0 if saved */
2562 if (r == REG_ST0) {
2563 o(0xd9dd); /* fstp %st(1) */
2565 #endif
2566 /* special long long case */
2567 if ((t & VT_BTYPE) == VT_LLONG) {
2568 sv.c.ul += 4;
2569 store(p->r2, &sv);
2571 l = loc;
2572 saved = 1;
2574 /* mark that stack entry as being saved on the stack */
2575 if (p->r & VT_LVAL)
2576 t = VT_LLOCAL;
2577 else
2578 t = VT_LOCAL;
2579 p->r = VT_LVAL | t;
2580 p->r2 = VT_CONST;
2581 p->c.ul = l;
2586 /* find a free register of class 'rc'. If none, save one register */
2587 int get_reg(int rc)
2589 int r;
2590 SValue *p;
2592 /* find a free register */
2593 for(r=0;r<NB_REGS;r++) {
2594 if (reg_classes[r] & rc) {
2595 for(p=vstack;p<=vtop;p++) {
2596 if ((p->r & VT_VALMASK) == r ||
2597 (p->r2 & VT_VALMASK) == r)
2598 goto notfound;
2600 return r;
2602 notfound: ;
2605 /* no register left : free the first one on the stack (VERY
2606 IMPORTANT to start from the bottom to ensure that we don't
2607 spill registers used in gen_opi()) */
2608 for(p=vstack;p<=vtop;p++) {
2609 r = p->r & VT_VALMASK;
2610 if (r < VT_CONST && (reg_classes[r] & rc)) {
2611 save_reg(r);
2612 break;
2615 return r;
2618 /* save registers up to (vtop - n) stack entry */
2619 void save_regs(int n)
2621 int r;
2622 SValue *p, *p1;
2623 p1 = vtop - n;
2624 for(p = vstack;p <= p1; p++) {
2625 r = p->r & VT_VALMASK;
2626 if (r < VT_CONST) {
2627 save_reg(r);
2632 /* move register 's' to 'r', and flush previous value of r to memory
2633 if needed */
2634 void move_reg(int r, int s)
2636 SValue sv;
2638 if (r != s) {
2639 save_reg(r);
2640 sv.t = VT_INT;
2641 sv.r = s;
2642 sv.c.ul = 0;
2643 load(r, &sv);
2647 /* get address of vtop (vtop MUST BE an lvalue) */
2648 void gaddrof(void)
2650 vtop->r &= ~VT_LVAL;
2651 /* tricky: if saved lvalue, then we can go back to lvalue */
2652 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
2653 vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
2656 #ifdef CONFIG_TCC_BCHECK
2657 /* generate lvalue bound code */
2658 void gbound(void)
2660 int lval_type;
2662 vtop->r &= ~VT_MUSTBOUND;
2663 /* if lvalue, then use checking code before dereferencing */
2664 if (vtop->r & VT_LVAL) {
2665 /* if not VT_BOUNDED value, then make one */
2666 if (!(vtop->r & VT_BOUNDED)) {
2667 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
2668 gaddrof();
2669 vpushi(0);
2670 gen_bounded_ptr_add();
2671 vtop->r |= lval_type;
2673 /* then check for dereferencing */
2674 gen_bounded_ptr_deref();
2677 #endif
2679 /* store vtop a register belonging to class 'rc'. lvalues are
2680 converted to values. Cannot be used if cannot be converted to
2681 register value (such as structures). */
2682 int gv(int rc)
2684 int r, r2, rc2, bit_pos, bit_size, size, align, i, data_offset;
2685 unsigned long long ll;
2687 /* NOTE: get_reg can modify vstack[] */
2688 if (vtop->t & VT_BITFIELD) {
2689 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
2690 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2691 /* remove bit field info to avoid loops */
2692 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2693 /* generate shifts */
2694 vpushi(32 - (bit_pos + bit_size));
2695 gen_op(TOK_SHL);
2696 vpushi(32 - bit_size);
2697 /* NOTE: transformed to SHR if unsigned */
2698 gen_op(TOK_SAR);
2699 r = gv(rc);
2700 } else {
2701 if (is_float(vtop->t) &&
2702 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2703 /* CPUs usually cannot use float constants, so we store them
2704 generically in data segment */
2705 size = type_size(vtop->t, &align);
2706 data_offset = (int)data_section->data_ptr;
2707 data_offset = (data_offset + align - 1) & -align;
2708 /* XXX: not portable yet */
2709 size = size >> 2;
2710 for(i=0;i<size;i++)
2711 ((int *)data_offset)[i] = vtop->c.tab[i];
2712 vtop->r |= VT_LVAL;
2713 vtop->c.ul = data_offset;
2714 data_offset += size << 2;
2715 data_section->data_ptr = (unsigned char *)data_offset;
2717 #ifdef CONFIG_TCC_BCHECK
2718 if (vtop->r & VT_MUSTBOUND)
2719 gbound();
2720 #endif
2722 r = vtop->r & VT_VALMASK;
2723 /* need to reload if:
2724 - constant
2725 - lvalue (need to dereference pointer)
2726 - already a register, but not in the right class */
2727 if (r >= VT_CONST ||
2728 (vtop->r & VT_LVAL) ||
2729 !(reg_classes[r] & rc) ||
2730 ((vtop->t & VT_BTYPE) == VT_LLONG &&
2731 !(reg_classes[vtop->r2] & rc))) {
2732 r = get_reg(rc);
2733 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
2734 /* two register type load : expand to two words
2735 temporarily */
2736 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2737 /* load constant */
2738 ll = vtop->c.ull;
2739 vtop->c.ui = ll; /* first word */
2740 load(r, vtop);
2741 vtop->r = r; /* save register value */
2742 vpushi(ll >> 32); /* second word */
2743 } else if (r >= VT_CONST ||
2744 (vtop->r & VT_LVAL)) {
2745 /* load from memory */
2746 load(r, vtop);
2747 vdup();
2748 vtop[-1].r = r; /* save register value */
2749 /* increment pointer to get second word */
2750 vtop->t = VT_INT;
2751 gaddrof();
2752 vpushi(4);
2753 gen_op('+');
2754 vtop->r |= VT_LVAL;
2755 } else {
2756 /* move registers */
2757 load(r, vtop);
2758 vdup();
2759 vtop[-1].r = r; /* save register value */
2760 vtop->r = vtop[-1].r2;
2762 /* allocate second register */
2763 rc2 = RC_INT;
2764 if (rc == RC_IRET)
2765 rc2 = RC_LRET;
2766 r2 = get_reg(rc2);
2767 load(r2, vtop);
2768 vpop();
2769 /* write second register */
2770 vtop->r2 = r2;
2771 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->t)) {
2772 int t1, t;
2773 /* lvalue of scalar type : need to use lvalue type
2774 because of possible cast */
2775 t = vtop->t;
2776 t1 = t;
2777 /* compute memory access type */
2778 if (vtop->r & VT_LVAL_BYTE)
2779 t = VT_BYTE;
2780 else if (vtop->r & VT_LVAL_SHORT)
2781 t = VT_SHORT;
2782 if (vtop->r & VT_LVAL_UNSIGNED)
2783 t |= VT_UNSIGNED;
2784 vtop->t = t;
2785 load(r, vtop);
2786 /* restore wanted type */
2787 vtop->t = t1;
2788 } else {
2789 /* one register type load */
2790 load(r, vtop);
2793 vtop->r = r;
2795 return r;
2798 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
2799 void gv2(int rc1, int rc2)
2801 /* generate more generic register first */
2802 if (rc1 <= rc2) {
2803 vswap();
2804 gv(rc1);
2805 vswap();
2806 gv(rc2);
2807 /* test if reload is needed for first register */
2808 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
2809 vswap();
2810 gv(rc1);
2811 vswap();
2813 } else {
2814 gv(rc2);
2815 vswap();
2816 gv(rc1);
2817 vswap();
2818 /* test if reload is needed for first register */
2819 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
2820 gv(rc2);
2825 /* expand long long on stack in two int registers */
2826 void lexpand(void)
2828 int u;
2830 u = vtop->t & VT_UNSIGNED;
2831 gv(RC_INT);
2832 vdup();
2833 vtop[0].r = vtop[-1].r2;
2834 vtop[0].r2 = VT_CONST;
2835 vtop[-1].r2 = VT_CONST;
2836 vtop[0].t = VT_INT | u;
2837 vtop[-1].t = VT_INT | u;
2840 /* build a long long from two ints */
2841 void lbuild(int t)
2843 gv2(RC_INT, RC_INT);
2844 vtop[-1].r2 = vtop[0].r;
2845 vtop[-1].t = t;
2846 vpop();
2849 /* rotate n first stack elements to the bottom */
2850 void vrotb(int n)
2852 int i;
2853 SValue tmp;
2855 tmp = vtop[-n + 1];
2856 for(i=-n+1;i!=0;i++)
2857 vtop[i] = vtop[i+1];
2858 vtop[0] = tmp;
2861 /* pop stack value */
2862 void vpop(void)
2864 int v;
2865 v = vtop->r & VT_VALMASK;
2866 #ifdef TCC_TARGET_I386
2867 /* for x86, we need to pop the FP stack */
2868 if (v == REG_ST0) {
2869 o(0xd9dd); /* fstp %st(1) */
2870 } else
2871 #endif
2872 if (v == VT_JMP || v == VT_JMPI) {
2873 /* need to put correct jump if && or || without test */
2874 gsym(vtop->c.ul);
2876 vtop--;
2879 /* convert stack entry to register and duplicate its value in another
2880 register */
2881 void gv_dup(void)
2883 int rc, t, r, r1;
2884 SValue sv;
2886 t = vtop->t;
2887 if ((t & VT_BTYPE) == VT_LLONG) {
2888 lexpand();
2889 gv_dup();
2890 vswap();
2891 vrotb(3);
2892 gv_dup();
2893 vrotb(4);
2894 /* stack: H L L1 H1 */
2895 lbuild(t);
2896 vrotb(3);
2897 vrotb(3);
2898 vswap();
2899 lbuild(t);
2900 vswap();
2901 } else {
2902 /* duplicate value */
2903 rc = RC_INT;
2904 sv.t = VT_INT;
2905 if (is_float(t)) {
2906 rc = RC_FLOAT;
2907 sv.t = t;
2909 r = gv(rc);
2910 r1 = get_reg(rc);
2911 sv.r = r;
2912 sv.c.ul = 0;
2913 load(r1, &sv); /* move r to r1 */
2914 vdup();
2915 /* duplicates value */
2916 vtop->r = r1;
2920 /* generate CPU independent (unsigned) long long operations */
2921 void gen_opl(int op)
2923 int t, a, b, op1, c, i;
2924 void *func;
2925 GFuncContext gf;
2926 SValue tmp;
2928 switch(op) {
2929 case '/':
2930 case TOK_PDIV:
2931 func = __divll;
2932 goto gen_func;
2933 case TOK_UDIV:
2934 func = __divull;
2935 goto gen_func;
2936 case '%':
2937 func = __modll;
2938 goto gen_func;
2939 case TOK_UMOD:
2940 func = __modull;
2941 gen_func:
2942 /* call generic long long function */
2943 gfunc_start(&gf, FUNC_CDECL);
2944 gfunc_param(&gf);
2945 gfunc_param(&gf);
2946 vpushi((int)func);
2947 gfunc_call(&gf);
2948 vpushi(0);
2949 vtop->r = REG_IRET;
2950 vtop->r2 = REG_LRET;
2951 break;
2952 case '^':
2953 case '&':
2954 case '|':
2955 case '*':
2956 case '+':
2957 case '-':
2958 t = vtop->t;
2959 vswap();
2960 lexpand();
2961 vrotb(3);
2962 lexpand();
2963 /* stack: L1 H1 L2 H2 */
2964 tmp = vtop[0];
2965 vtop[0] = vtop[-3];
2966 vtop[-3] = tmp;
2967 tmp = vtop[-2];
2968 vtop[-2] = vtop[-3];
2969 vtop[-3] = tmp;
2970 vswap();
2971 /* stack: H1 H2 L1 L2 */
2972 if (op == '*') {
2973 vpushv(vtop - 1);
2974 vpushv(vtop - 1);
2975 gen_op(TOK_UMULL);
2976 lexpand();
2977 /* stack: H1 H2 L1 L2 ML MH */
2978 for(i=0;i<4;i++)
2979 vrotb(6);
2980 /* stack: ML MH H1 H2 L1 L2 */
2981 tmp = vtop[0];
2982 vtop[0] = vtop[-2];
2983 vtop[-2] = tmp;
2984 /* stack: ML MH H1 L2 H2 L1 */
2985 gen_op('*');
2986 vrotb(3);
2987 vrotb(3);
2988 gen_op('*');
2989 /* stack: ML MH M1 M2 */
2990 gen_op('+');
2991 gen_op('+');
2992 } else if (op == '+' || op == '-') {
2993 /* XXX: add non carry method too (for MIPS or alpha) */
2994 if (op == '+')
2995 op1 = TOK_ADDC1;
2996 else
2997 op1 = TOK_SUBC1;
2998 gen_op(op1);
2999 /* stack: H1 H2 (L1 op L2) */
3000 vrotb(3);
3001 vrotb(3);
3002 gen_op(op1 + 1); /* TOK_xxxC2 */
3003 } else {
3004 gen_op(op);
3005 /* stack: H1 H2 (L1 op L2) */
3006 vrotb(3);
3007 vrotb(3);
3008 /* stack: (L1 op L2) H1 H2 */
3009 gen_op(op);
3010 /* stack: (L1 op L2) (H1 op H2) */
3012 /* stack: L H */
3013 lbuild(t);
3014 break;
3015 case TOK_SAR:
3016 case TOK_SHR:
3017 case TOK_SHL:
3018 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
3019 t = vtop[-1].t;
3020 vswap();
3021 lexpand();
3022 vrotb(3);
3023 /* stack: L H shift */
3024 c = (int)vtop->c.i;
3025 /* constant: simpler */
3026 /* NOTE: all comments are for SHL. the other cases are
3027 done by swaping words */
3028 vpop();
3029 if (op != TOK_SHL)
3030 vswap();
3031 if (c >= 32) {
3032 /* stack: L H */
3033 vpop();
3034 if (c > 32) {
3035 vpushi(c - 32);
3036 gen_op(op);
3038 if (op != TOK_SAR) {
3039 vpushi(0);
3040 } else {
3041 gv_dup();
3042 vpushi(31);
3043 gen_op(TOK_SAR);
3045 vswap();
3046 } else {
3047 vswap();
3048 gv_dup();
3049 /* stack: H L L */
3050 vpushi(c);
3051 gen_op(op);
3052 vswap();
3053 vpushi(32 - c);
3054 if (op == TOK_SHL)
3055 gen_op(TOK_SHR);
3056 else
3057 gen_op(TOK_SHL);
3058 vrotb(3);
3059 /* stack: L L H */
3060 vpushi(c);
3061 gen_op(op);
3062 gen_op('|');
3064 if (op != TOK_SHL)
3065 vswap();
3066 lbuild(t);
3067 } else {
3068 /* XXX: should provide a faster fallback on x86 ? */
3069 switch(op) {
3070 case TOK_SAR:
3071 func = __sardi3;
3072 goto gen_func;
3073 case TOK_SHR:
3074 func = __shrdi3;
3075 goto gen_func;
3076 case TOK_SHL:
3077 func = __shldi3;
3078 goto gen_func;
3081 break;
3082 default:
3083 /* compare operations */
3084 t = vtop->t;
3085 vswap();
3086 lexpand();
3087 vrotb(3);
3088 lexpand();
3089 /* stack: L1 H1 L2 H2 */
3090 tmp = vtop[-1];
3091 vtop[-1] = vtop[-2];
3092 vtop[-2] = tmp;
3093 /* stack: L1 L2 H1 H2 */
3094 /* compare high */
3095 op1 = op;
3096 /* when values are equal, we need to compare low words. since
3097 the jump is inverted, we invert the test too. */
3098 if (op1 == TOK_LT)
3099 op1 = TOK_LE;
3100 else if (op1 == TOK_GT)
3101 op1 = TOK_GE;
3102 else if (op1 == TOK_ULT)
3103 op1 = TOK_ULE;
3104 else if (op1 == TOK_UGT)
3105 op1 = TOK_UGE;
3106 a = 0;
3107 b = 0;
3108 gen_op(op1);
3109 if (op1 != TOK_NE) {
3110 a = gtst(1, 0);
3112 if (op != TOK_EQ) {
3113 /* generate non equal test */
3114 /* XXX: NOT PORTABLE yet */
3115 if (a == 0) {
3116 b = gtst(0, 0);
3117 } else {
3118 #ifdef TCC_TARGET_I386
3119 b = psym(0x850f, 0);
3120 #else
3121 error("not implemented");
3122 #endif
3125 /* compare low */
3126 gen_op(op);
3127 a = gtst(1, a);
3128 gsym(b);
3129 vset(VT_INT, VT_JMPI, a);
3130 break;
3134 /* handle integer constant optimizations and various machine
3135 independant opt */
3136 void gen_opic(int op)
3138 int fc, c1, c2, n;
3139 SValue *v1, *v2;
3141 v1 = vtop - 1;
3142 v2 = vtop;
3143 /* currently, we cannot do computations with forward symbols */
3144 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3145 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3146 if (c1 && c2) {
3147 fc = v2->c.i;
3148 switch(op) {
3149 case '+': v1->c.i += fc; break;
3150 case '-': v1->c.i -= fc; break;
3151 case '&': v1->c.i &= fc; break;
3152 case '^': v1->c.i ^= fc; break;
3153 case '|': v1->c.i |= fc; break;
3154 case '*': v1->c.i *= fc; break;
3156 case TOK_PDIV:
3157 case '/':
3158 case '%':
3159 case TOK_UDIV:
3160 case TOK_UMOD:
3161 /* if division by zero, generate explicit division */
3162 if (fc == 0) {
3163 if (const_wanted)
3164 error("division by zero in constant");
3165 goto general_case;
3167 switch(op) {
3168 default: v1->c.i /= fc; break;
3169 case '%': v1->c.i %= fc; break;
3170 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
3171 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
3173 break;
3174 case TOK_SHL: v1->c.i <<= fc; break;
3175 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
3176 case TOK_SAR: v1->c.i >>= fc; break;
3177 /* tests */
3178 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
3179 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
3180 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
3181 case TOK_NE: v1->c.i = v1->c.i != fc; break;
3182 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
3183 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
3184 case TOK_LT: v1->c.i = v1->c.i < fc; break;
3185 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
3186 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
3187 case TOK_GT: v1->c.i = v1->c.i > fc; break;
3188 /* logical */
3189 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
3190 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
3191 default:
3192 goto general_case;
3194 vtop--;
3195 } else {
3196 /* if commutative ops, put c2 as constant */
3197 if (c1 && (op == '+' || op == '&' || op == '^' ||
3198 op == '|' || op == '*')) {
3199 vswap();
3200 swap(&c1, &c2);
3202 fc = vtop->c.i;
3203 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
3204 op == TOK_PDIV) &&
3205 fc == 1) ||
3206 ((op == '+' || op == '-' || op == '|' || op == '^' ||
3207 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
3208 fc == 0) ||
3209 (op == '&' &&
3210 fc == -1))) {
3211 /* nothing to do */
3212 vtop--;
3213 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
3214 /* try to use shifts instead of muls or divs */
3215 if (fc > 0 && (fc & (fc - 1)) == 0) {
3216 n = -1;
3217 while (fc) {
3218 fc >>= 1;
3219 n++;
3221 vtop->c.i = n;
3222 if (op == '*')
3223 op = TOK_SHL;
3224 else if (op == TOK_PDIV)
3225 op = TOK_SAR;
3226 else
3227 op = TOK_SHR;
3229 goto general_case;
3230 } else {
3231 general_case:
3232 /* call low level op generator */
3233 gen_opi(op);
3238 /* generate a floating point operation with constant propagation */
3239 void gen_opif(int op)
3241 int c1, c2;
3242 SValue *v1, *v2;
3243 long double f1, f2;
3245 v1 = vtop - 1;
3246 v2 = vtop;
3247 /* currently, we cannot do computations with forward symbols */
3248 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3249 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3250 if (c1 && c2) {
3251 if (v1->t == VT_FLOAT) {
3252 f1 = v1->c.f;
3253 f2 = v2->c.f;
3254 } else if (v1->t == VT_DOUBLE) {
3255 f1 = v1->c.d;
3256 f2 = v2->c.d;
3257 } else {
3258 f1 = v1->c.ld;
3259 f2 = v2->c.ld;
3262 /* NOTE: we only do constant propagation if finite number (not
3263 NaN or infinity) (ANSI spec) */
3264 if (!ieee_finite(f1) || !ieee_finite(f2))
3265 goto general_case;
3267 switch(op) {
3268 case '+': f1 += f2; break;
3269 case '-': f1 -= f2; break;
3270 case '*': f1 *= f2; break;
3271 case '/':
3272 if (f2 == 0.0) {
3273 if (const_wanted)
3274 error("division by zero in constant");
3275 goto general_case;
3277 f1 /= f2;
3278 break;
3279 /* XXX: also handles tests ? */
3280 default:
3281 goto general_case;
3283 /* XXX: overflow test ? */
3284 if (v1->t == VT_FLOAT) {
3285 v1->c.f = f1;
3286 } else if (v1->t == VT_DOUBLE) {
3287 v1->c.d = f1;
3288 } else {
3289 v1->c.ld = f1;
3291 vtop--;
3292 } else {
3293 general_case:
3294 gen_opf(op);
3299 int pointed_size(int t)
3301 return type_size(pointed_type(t), &t);
3304 #if 0
3305 void check_pointer_types(SValue *p1, SValue *p2)
3307 char buf1[256], buf2[256];
3308 int t1, t2;
3309 t1 = p1->t;
3310 t2 = p2->t;
3311 if (!is_compatible_types(t1, t2)) {
3312 type_to_str(buf1, sizeof(buf1), t1, NULL);
3313 type_to_str(buf2, sizeof(buf2), t2, NULL);
3314 error("incompatible pointers '%s' and '%s'", buf1, buf2);
3317 #endif
3319 /* generic gen_op: handles types problems */
3320 void gen_op(int op)
3322 int u, t1, t2, bt1, bt2, t;
3324 t1 = vtop[-1].t;
3325 t2 = vtop[0].t;
3326 bt1 = t1 & VT_BTYPE;
3327 bt2 = t2 & VT_BTYPE;
3329 if (bt1 == VT_PTR || bt2 == VT_PTR) {
3330 /* at least one operand is a pointer */
3331 /* relationnal op: must be both pointers */
3332 if (op >= TOK_ULT && op <= TOK_GT) {
3333 // check_pointer_types(vtop, vtop - 1);
3334 /* pointers are handled are unsigned */
3335 t = VT_INT | VT_UNSIGNED;
3336 goto std_op;
3338 /* if both pointers, then it must be the '-' op */
3339 if ((t1 & VT_BTYPE) == VT_PTR &&
3340 (t2 & VT_BTYPE) == VT_PTR) {
3341 if (op != '-')
3342 error("cannot use pointers here");
3343 // check_pointer_types(vtop - 1, vtop);
3344 /* XXX: check that types are compatible */
3345 u = pointed_size(t1);
3346 gen_opic(op);
3347 /* set to integer type */
3348 vtop->t = VT_INT;
3349 vpushi(u);
3350 gen_op(TOK_PDIV);
3351 } else {
3352 /* exactly one pointer : must be '+' or '-'. */
3353 if (op != '-' && op != '+')
3354 error("cannot use pointers here");
3355 /* Put pointer as first operand */
3356 if ((t2 & VT_BTYPE) == VT_PTR) {
3357 vswap();
3358 swap(&t1, &t2);
3360 /* XXX: cast to int ? (long long case) */
3361 vpushi(pointed_size(vtop[-1].t));
3362 gen_op('*');
3363 #ifdef CONFIG_TCC_BCHECK
3364 /* if evaluating constant expression, no code should be
3365 generated, so no bound check */
3366 if (do_bounds_check && !const_wanted) {
3367 /* if bounded pointers, we generate a special code to
3368 test bounds */
3369 if (op == '-') {
3370 vpushi(0);
3371 vswap();
3372 gen_op('-');
3374 gen_bounded_ptr_add();
3375 } else
3376 #endif
3378 gen_opic(op);
3380 /* put again type if gen_opic() swaped operands */
3381 vtop->t = t1;
3383 } else if (is_float(bt1) || is_float(bt2)) {
3384 /* compute bigger type and do implicit casts */
3385 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
3386 t = VT_LDOUBLE;
3387 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
3388 t = VT_DOUBLE;
3389 } else {
3390 t = VT_FLOAT;
3392 /* floats can only be used for a few operations */
3393 if (op != '+' && op != '-' && op != '*' && op != '/' &&
3394 (op < TOK_ULT || op > TOK_GT))
3395 error("invalid operands for binary operation");
3396 goto std_op;
3397 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
3398 /* cast to biggest op */
3399 t = VT_LLONG;
3400 /* convert to unsigned if it does not fit in a long long */
3401 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
3402 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
3403 t |= VT_UNSIGNED;
3404 goto std_op;
3405 } else {
3406 /* integer operations */
3407 t = VT_INT;
3408 /* convert to unsigned if it does not fit in an integer */
3409 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
3410 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3411 t |= VT_UNSIGNED;
3412 std_op:
3413 /* XXX: currently, some unsigned operations are explicit, so
3414 we modify them here */
3415 if (t & VT_UNSIGNED) {
3416 if (op == TOK_SAR)
3417 op = TOK_SHR;
3418 else if (op == '/')
3419 op = TOK_UDIV;
3420 else if (op == '%')
3421 op = TOK_UMOD;
3422 else if (op == TOK_LT)
3423 op = TOK_ULT;
3424 else if (op == TOK_GT)
3425 op = TOK_UGT;
3426 else if (op == TOK_LE)
3427 op = TOK_ULE;
3428 else if (op == TOK_GE)
3429 op = TOK_UGE;
3431 vswap();
3432 gen_cast(t);
3433 vswap();
3434 /* special case for shifts and long long: we keep the shift as
3435 an integer */
3436 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
3437 gen_cast(VT_INT);
3438 else
3439 gen_cast(t);
3440 if (is_float(t))
3441 gen_opif(op);
3442 else if ((t & VT_BTYPE) == VT_LLONG)
3443 gen_opl(op);
3444 else
3445 gen_opic(op);
3446 if (op >= TOK_ULT && op <= TOK_GT) {
3447 /* relationnal op: the result is an int */
3448 vtop->t = VT_INT;
3449 } else {
3450 vtop->t = t;
3455 /* generic itof for unsigned long long case */
3456 void gen_cvt_itof1(int t)
3458 GFuncContext gf;
3460 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
3461 (VT_LLONG | VT_UNSIGNED)) {
3463 gfunc_start(&gf, FUNC_CDECL);
3464 gfunc_param(&gf);
3465 if (t == VT_FLOAT)
3466 vpushi((int)&__ulltof);
3467 else if (t == VT_DOUBLE)
3468 vpushi((int)&__ulltod);
3469 else
3470 vpushi((int)&__ulltold);
3471 gfunc_call(&gf);
3472 vpushi(0);
3473 vtop->r = REG_FRET;
3474 } else {
3475 gen_cvt_itof(t);
3479 /* generic ftoi for unsigned long long case */
3480 void gen_cvt_ftoi1(int t)
3482 GFuncContext gf;
3483 int st;
3485 if (t == (VT_LLONG | VT_UNSIGNED)) {
3486 /* not handled natively */
3487 gfunc_start(&gf, FUNC_CDECL);
3488 st = vtop->t & VT_BTYPE;
3489 gfunc_param(&gf);
3490 if (st == VT_FLOAT)
3491 vpushi((int)&__ftoull);
3492 else if (st == VT_DOUBLE)
3493 vpushi((int)&__dtoull);
3494 else
3495 vpushi((int)&__ldtoull);
3496 gfunc_call(&gf);
3497 vpushi(0);
3498 vtop->r = REG_IRET;
3499 vtop->r2 = REG_LRET;
3500 } else {
3501 gen_cvt_ftoi(t);
3505 /* force char or short cast */
3506 void force_charshort_cast(int t)
3508 int bits, dbt;
3509 dbt = t & VT_BTYPE;
3510 /* XXX: add optimization if lvalue : just change type and offset */
3511 if (dbt == VT_BYTE)
3512 bits = 8;
3513 else
3514 bits = 16;
3515 if (t & VT_UNSIGNED) {
3516 vpushi((1 << bits) - 1);
3517 gen_op('&');
3518 } else {
3519 bits = 32 - bits;
3520 vpushi(bits);
3521 gen_op(TOK_SHL);
3522 vpushi(bits);
3523 gen_op(TOK_SAR);
3527 /* cast 'vtop' to 't' type */
3528 void gen_cast(int t)
3530 int sbt, dbt, sf, df, c;
3532 /* special delayed cast for char/short */
3533 /* XXX: in some cases (multiple cascaded casts), it may still
3534 be incorrect */
3535 if (vtop->r & VT_MUSTCAST) {
3536 vtop->r &= ~VT_MUSTCAST;
3537 force_charshort_cast(vtop->t);
3540 dbt = t & (VT_BTYPE | VT_UNSIGNED);
3541 sbt = vtop->t & (VT_BTYPE | VT_UNSIGNED);
3543 if (sbt != dbt) {
3544 sf = is_float(sbt);
3545 df = is_float(dbt);
3546 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
3547 if (sf && df) {
3548 /* convert from fp to fp */
3549 if (c) {
3550 /* constant case: we can do it now */
3551 /* XXX: in ISOC, cannot do it if error in convert */
3552 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
3553 vtop->c.f = (float)vtop->c.d;
3554 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
3555 vtop->c.f = (float)vtop->c.ld;
3556 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
3557 vtop->c.d = (double)vtop->c.f;
3558 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
3559 vtop->c.d = (double)vtop->c.ld;
3560 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
3561 vtop->c.ld = (long double)vtop->c.f;
3562 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
3563 vtop->c.ld = (long double)vtop->c.d;
3564 } else {
3565 /* non constant case: generate code */
3566 gen_cvt_ftof(dbt);
3568 } else if (df) {
3569 /* convert int to fp */
3570 if (c) {
3571 switch(sbt) {
3572 case VT_LLONG | VT_UNSIGNED:
3573 case VT_LLONG:
3574 /* XXX: add const cases for long long */
3575 goto do_itof;
3576 case VT_INT | VT_UNSIGNED:
3577 switch(dbt) {
3578 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
3579 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
3580 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
3582 break;
3583 default:
3584 switch(dbt) {
3585 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
3586 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
3587 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
3589 break;
3591 } else {
3592 do_itof:
3593 gen_cvt_itof1(dbt);
3595 } else if (sf) {
3596 /* convert fp to int */
3597 /* we handle char/short/etc... with generic code */
3598 if (dbt != (VT_INT | VT_UNSIGNED) &&
3599 dbt != (VT_LLONG | VT_UNSIGNED) &&
3600 dbt != VT_LLONG)
3601 dbt = VT_INT;
3602 if (c) {
3603 switch(dbt) {
3604 case VT_LLONG | VT_UNSIGNED:
3605 case VT_LLONG:
3606 /* XXX: add const cases for long long */
3607 goto do_ftoi;
3608 case VT_INT | VT_UNSIGNED:
3609 switch(sbt) {
3610 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
3611 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3612 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3614 break;
3615 default:
3616 /* int case */
3617 switch(sbt) {
3618 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
3619 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
3620 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
3622 break;
3624 } else {
3625 do_ftoi:
3626 gen_cvt_ftoi1(dbt);
3628 if (dbt == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
3629 /* additionnal cast for char/short/bool... */
3630 vtop->t = dbt;
3631 gen_cast(t);
3633 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
3634 if ((sbt & VT_BTYPE) != VT_LLONG) {
3635 /* scalar to long long */
3636 if (c) {
3637 if (sbt == (VT_INT | VT_UNSIGNED))
3638 vtop->c.ll = vtop->c.ui;
3639 else
3640 vtop->c.ll = vtop->c.i;
3641 } else {
3642 /* machine independant conversion */
3643 gv(RC_INT);
3644 /* generate high word */
3645 if (sbt == (VT_INT | VT_UNSIGNED)) {
3646 vpushi(0);
3647 gv(RC_INT);
3648 } else {
3649 gv_dup();
3650 vpushi(31);
3651 gen_op(TOK_SAR);
3653 /* patch second register */
3654 vtop[-1].r2 = vtop->r;
3655 vpop();
3658 } else if (dbt == VT_BOOL) {
3659 /* scalar to bool */
3660 vpushi(0);
3661 gen_op(TOK_NE);
3662 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
3663 (dbt & VT_BTYPE) == VT_SHORT) {
3664 force_charshort_cast(t);
3665 } else if ((dbt & VT_BTYPE) == VT_INT) {
3666 /* scalar to int */
3667 if (sbt == VT_LLONG) {
3668 /* from long long: just take low order word */
3669 lexpand();
3670 vpop();
3672 /* if lvalue and single word type, nothing to do because
3673 the lvalue already contains the real type size (see
3674 VT_LVAL_xxx constants) */
3677 vtop->t = t;
3680 /* return type size. Put alignment at 'a' */
3681 int type_size(int t, int *a)
3683 Sym *s;
3684 int bt;
3686 bt = t & VT_BTYPE;
3687 if (bt == VT_STRUCT) {
3688 /* struct/union */
3689 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3690 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
3691 return s->c;
3692 } else if (bt == VT_PTR) {
3693 if (t & VT_ARRAY) {
3694 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3695 return type_size(s->t, a) * s->c;
3696 } else {
3697 *a = PTR_SIZE;
3698 return PTR_SIZE;
3700 } else if (bt == VT_LDOUBLE) {
3701 *a = LDOUBLE_ALIGN;
3702 return LDOUBLE_SIZE;
3703 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
3704 *a = 8;
3705 return 8;
3706 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
3707 *a = 4;
3708 return 4;
3709 } else if (bt == VT_SHORT) {
3710 *a = 2;
3711 return 2;
3712 } else {
3713 /* char, void, function, _Bool */
3714 *a = 1;
3715 return 1;
3719 /* return the pointed type of t */
3720 int pointed_type(int t)
3722 Sym *s;
3723 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3724 return s->t | (t & ~VT_TYPE);
3727 int mk_pointer(int t)
3729 int p;
3730 p = anon_sym++;
3731 sym_push(p, t, 0, -1);
3732 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
3735 int is_compatible_types(int t1, int t2)
3737 Sym *s1, *s2;
3738 int bt1, bt2;
3740 t1 &= VT_TYPE;
3741 t2 &= VT_TYPE;
3742 bt1 = t1 & VT_BTYPE;
3743 bt2 = t2 & VT_BTYPE;
3744 if (bt1 == VT_PTR) {
3745 t1 = pointed_type(t1);
3746 /* if function, then convert implicitely to function pointer */
3747 if (bt2 != VT_FUNC) {
3748 if (bt2 != VT_PTR)
3749 return 0;
3750 t2 = pointed_type(t2);
3752 /* void matches everything */
3753 t1 &= VT_TYPE;
3754 t2 &= VT_TYPE;
3755 if (t1 == VT_VOID || t2 == VT_VOID)
3756 return 1;
3757 return is_compatible_types(t1, t2);
3758 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
3759 return (t2 == t1);
3760 } else if (bt1 == VT_FUNC) {
3761 if (bt2 != VT_FUNC)
3762 return 0;
3763 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
3764 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
3765 if (!is_compatible_types(s1->t, s2->t))
3766 return 0;
3767 /* XXX: not complete */
3768 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
3769 return 1;
3770 if (s1->c != s2->c)
3771 return 0;
3772 while (s1 != NULL) {
3773 if (s2 == NULL)
3774 return 0;
3775 if (!is_compatible_types(s1->t, s2->t))
3776 return 0;
3777 s1 = s1->next;
3778 s2 = s2->next;
3780 if (s2)
3781 return 0;
3782 return 1;
3783 } else {
3784 /* XXX: not complete */
3785 return 1;
3789 /* print a type. If 'varstr' is not NULL, then the variable is also
3790 printed in the type */
3791 /* XXX: union */
3792 /* XXX: add array and function pointers */
3793 void type_to_str(char *buf, int buf_size,
3794 int t, const char *varstr)
3796 int bt, v;
3797 Sym *s, *sa;
3798 char buf1[256];
3799 const char *tstr;
3801 t = t & VT_TYPE;
3802 bt = t & VT_BTYPE;
3803 buf[0] = '\0';
3804 if (t & VT_UNSIGNED)
3805 pstrcat(buf, buf_size, "unsigned ");
3806 switch(bt) {
3807 case VT_VOID:
3808 tstr = "void";
3809 goto add_tstr;
3810 case VT_BOOL:
3811 tstr = "_Bool";
3812 goto add_tstr;
3813 case VT_BYTE:
3814 tstr = "char";
3815 goto add_tstr;
3816 case VT_SHORT:
3817 tstr = "short";
3818 goto add_tstr;
3819 case VT_INT:
3820 tstr = "int";
3821 goto add_tstr;
3822 case VT_LONG:
3823 tstr = "long";
3824 goto add_tstr;
3825 case VT_LLONG:
3826 tstr = "long long";
3827 goto add_tstr;
3828 case VT_FLOAT:
3829 tstr = "float";
3830 goto add_tstr;
3831 case VT_DOUBLE:
3832 tstr = "double";
3833 goto add_tstr;
3834 case VT_LDOUBLE:
3835 tstr = "long double";
3836 add_tstr:
3837 pstrcat(buf, buf_size, tstr);
3838 break;
3839 case VT_ENUM:
3840 case VT_STRUCT:
3841 if (bt == VT_STRUCT)
3842 tstr = "struct ";
3843 else
3844 tstr = "enum ";
3845 pstrcat(buf, buf_size, tstr);
3846 v = (unsigned)t >> VT_STRUCT_SHIFT;
3847 if (v >= SYM_FIRST_ANOM)
3848 pstrcat(buf, buf_size, "<anonymous>");
3849 else
3850 pstrcat(buf, buf_size, get_tok_str(v, NULL));
3851 break;
3852 case VT_FUNC:
3853 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3854 type_to_str(buf, buf_size, s->t, varstr);
3855 pstrcat(buf, buf_size, "(");
3856 sa = s->next;
3857 while (sa != NULL) {
3858 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
3859 pstrcat(buf, buf_size, buf1);
3860 sa = sa->next;
3861 if (sa)
3862 pstrcat(buf, buf_size, ", ");
3864 pstrcat(buf, buf_size, ")");
3865 goto no_var;
3866 case VT_PTR:
3867 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3868 pstrcpy(buf1, sizeof(buf1), "*");
3869 if (varstr)
3870 pstrcat(buf1, sizeof(buf1), varstr);
3871 type_to_str(buf, buf_size, s->t, buf1);
3872 goto no_var;
3874 if (varstr) {
3875 pstrcat(buf, buf_size, " ");
3876 pstrcat(buf, buf_size, varstr);
3878 no_var: ;
3881 /* verify type compatibility to store vtop in 'dt' type, and generate
3882 casts if needed. */
3883 void gen_assign_cast(int dt)
3885 int st;
3886 char buf1[256], buf2[256];
3888 st = vtop->t; /* source type */
3889 if ((dt & VT_BTYPE) == VT_PTR) {
3890 /* special cases for pointers */
3891 /* a function is implicitely a function pointer */
3892 if ((st & VT_BTYPE) == VT_FUNC) {
3893 if (!is_compatible_types(pointed_type(dt), st))
3894 goto error;
3895 else
3896 goto type_ok;
3898 /* '0' can also be a pointer */
3899 if ((st & VT_BTYPE) == VT_INT &&
3900 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) &&
3901 vtop->c.i == 0)
3902 goto type_ok;
3904 if (!is_compatible_types(dt, st)) {
3905 error:
3906 type_to_str(buf1, sizeof(buf1), st, NULL);
3907 type_to_str(buf2, sizeof(buf2), dt, NULL);
3908 error("cannot cast '%s' to '%s'", buf1, buf2);
3910 type_ok:
3911 gen_cast(dt);
3914 /* store vtop in lvalue pushed on stack */
3915 void vstore(void)
3917 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
3918 GFuncContext gf;
3920 ft = vtop[-1].t;
3921 sbt = vtop->t & VT_BTYPE;
3922 dbt = ft & VT_BTYPE;
3923 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
3924 (sbt == VT_INT && dbt == VT_SHORT)) {
3925 /* optimize char/short casts */
3926 delayed_cast = VT_MUSTCAST;
3927 vtop->t = ft & VT_TYPE;
3928 } else {
3929 delayed_cast = 0;
3930 gen_assign_cast(ft & VT_TYPE);
3933 if (sbt == VT_STRUCT) {
3934 /* if structure, only generate pointer */
3935 /* structure assignment : generate memcpy */
3936 /* XXX: optimize if small size */
3937 vdup();
3938 gfunc_start(&gf, FUNC_CDECL);
3939 /* type size */
3940 size = type_size(vtop->t, &align);
3941 vpushi(size);
3942 gfunc_param(&gf);
3943 /* source */
3944 vtop->t = VT_INT;
3945 gaddrof();
3946 gfunc_param(&gf);
3947 /* destination */
3948 vswap();
3949 vtop->t = VT_INT;
3950 gaddrof();
3951 gfunc_param(&gf);
3953 save_regs(0);
3954 vpushi((int)&memcpy);
3955 gfunc_call(&gf);
3956 /* leave source on stack */
3957 } else if (ft & VT_BITFIELD) {
3958 /* bitfield store handling */
3959 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
3960 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3961 /* remove bit field info to avoid loops */
3962 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3964 /* duplicate destination */
3965 vdup();
3966 vtop[-1] = vtop[-2];
3968 /* mask and shift source */
3969 vpushi((1 << bit_size) - 1);
3970 gen_op('&');
3971 vpushi(bit_pos);
3972 gen_op(TOK_SHL);
3973 /* load destination, mask and or with source */
3974 vswap();
3975 vpushi(~(((1 << bit_size) - 1) << bit_pos));
3976 gen_op('&');
3977 gen_op('|');
3978 /* store result */
3979 vstore();
3980 } else {
3981 #ifdef CONFIG_TCC_BCHECK
3982 /* bound check case */
3983 if (vtop[-1].r & VT_MUSTBOUND) {
3984 vswap();
3985 gbound();
3986 vswap();
3988 #endif
3989 rc = RC_INT;
3990 if (is_float(ft))
3991 rc = RC_FLOAT;
3992 r = gv(rc); /* generate value */
3993 /* if lvalue was saved on stack, must read it */
3994 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
3995 SValue sv;
3996 t = get_reg(RC_INT);
3997 sv.t = VT_INT;
3998 sv.r = VT_LOCAL | VT_LVAL;
3999 sv.c.ul = vtop[-1].c.ul;
4000 load(t, &sv);
4001 vtop[-1].r = t | VT_LVAL;
4003 store(r, vtop - 1);
4004 /* two word case handling : store second register at word + 4 */
4005 if ((ft & VT_BTYPE) == VT_LLONG) {
4006 vswap();
4007 /* convert to int to increment easily */
4008 vtop->t = VT_INT;
4009 gaddrof();
4010 vpushi(4);
4011 gen_op('+');
4012 vtop->r |= VT_LVAL;
4013 vswap();
4014 /* XXX: it works because r2 is spilled last ! */
4015 store(vtop->r2, vtop - 1);
4017 vswap();
4018 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
4019 vtop->r |= delayed_cast;
4023 /* post defines POST/PRE add. c is the token ++ or -- */
4024 void inc(int post, int c)
4026 test_lvalue();
4027 vdup(); /* save lvalue */
4028 if (post) {
4029 gv_dup(); /* duplicate value */
4030 vrotb(3);
4031 vrotb(3);
4033 /* add constant */
4034 vpushi(c - TOK_MID);
4035 gen_op('+');
4036 vstore(); /* store value */
4037 if (post)
4038 vpop(); /* if post op, return saved value */
4041 /* Parse GNUC __attribute__ extension. Currently, the following
4042 extensions are recognized:
4043 - aligned(n) : set data/function alignment.
4044 - section(x) : generate data/code in this section.
4045 - unused : currently ignored, but may be used someday.
4047 void parse_attribute(AttributeDef *ad)
4049 int t, n;
4051 next();
4052 skip('(');
4053 skip('(');
4054 while (tok != ')') {
4055 if (tok < TOK_IDENT)
4056 expect("attribute name");
4057 t = tok;
4058 next();
4059 switch(t) {
4060 case TOK_SECTION:
4061 case TOK___SECTION__:
4062 skip('(');
4063 if (tok != TOK_STR)
4064 expect("section name");
4065 ad->section = find_section(tokc.ts->str);
4066 next();
4067 skip(')');
4068 break;
4069 case TOK_ALIGNED:
4070 case TOK___ALIGNED__:
4071 skip('(');
4072 n = expr_const();
4073 if (n <= 0 || (n & (n - 1)) != 0)
4074 error("alignment must be a positive power of two");
4075 ad->aligned = n;
4076 skip(')');
4077 break;
4078 case TOK_UNUSED:
4079 case TOK___UNUSED__:
4080 /* currently, no need to handle it because tcc does not
4081 track unused objects */
4082 break;
4083 case TOK_NORETURN:
4084 case TOK___NORETURN__:
4085 /* currently, no need to handle it because tcc does not
4086 track unused objects */
4087 break;
4088 case TOK_CDECL:
4089 case TOK___CDECL:
4090 case TOK___CDECL__:
4091 ad->func_call = FUNC_CDECL;
4092 break;
4093 case TOK_STDCALL:
4094 case TOK___STDCALL:
4095 case TOK___STDCALL__:
4096 ad->func_call = FUNC_STDCALL;
4097 break;
4098 default:
4099 warning("'%s' attribute ignored", get_tok_str(t, NULL));
4100 /* skip parameters */
4101 /* XXX: skip parenthesis too */
4102 if (tok == '(') {
4103 next();
4104 while (tok != ')' && tok != -1)
4105 next();
4106 next();
4108 break;
4110 if (tok != ',')
4111 break;
4112 next();
4114 skip(')');
4115 skip(')');
4118 /* enum/struct/union declaration */
4119 int struct_decl(int u)
4121 int a, t, b, v, size, align, maxalign, c, offset;
4122 int bit_size, bit_pos, bsize, bt, lbit_pos;
4123 Sym *s, *ss, **ps;
4124 AttributeDef ad;
4126 a = tok; /* save decl type */
4127 next();
4128 if (tok != '{') {
4129 v = tok;
4130 next();
4131 /* struct already defined ? return it */
4132 /* XXX: check consistency */
4133 s = sym_find(v | SYM_STRUCT);
4134 if (s) {
4135 if (s->t != a)
4136 error("invalid type");
4137 goto do_decl;
4139 } else {
4140 v = anon_sym++;
4142 s = sym_push(v | SYM_STRUCT, a, 0, 0);
4143 /* put struct/union/enum name in type */
4144 do_decl:
4145 u = u | (v << VT_STRUCT_SHIFT);
4147 if (tok == '{') {
4148 next();
4149 if (s->c)
4150 error("struct/union/enum already defined");
4151 /* cannot be empty */
4152 c = 0;
4153 maxalign = 0;
4154 ps = &s->next;
4155 bit_pos = 0;
4156 offset = 0;
4157 while (1) {
4158 if (a == TOK_ENUM) {
4159 v = tok;
4160 next();
4161 if (tok == '=') {
4162 next();
4163 c = expr_const();
4165 /* enum symbols have static storage */
4166 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
4167 if (tok == ',')
4168 next();
4169 c++;
4170 } else {
4171 parse_btype(&b, &ad);
4172 while (1) {
4173 bit_size = -1;
4174 v = 0;
4175 if (tok != ':') {
4176 t = type_decl(&ad, &v, b, TYPE_DIRECT);
4177 if ((t & VT_BTYPE) == VT_FUNC ||
4178 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
4179 error("invalid type for '%s'",
4180 get_tok_str(v, NULL));
4181 } else {
4182 t = b;
4184 if (tok == ':') {
4185 next();
4186 bit_size = expr_const();
4187 /* XXX: handle v = 0 case for messages */
4188 if (bit_size < 0)
4189 error("negative width in bit-field '%s'",
4190 get_tok_str(v, NULL));
4191 if (v && bit_size == 0)
4192 error("zero width for bit-field '%s'",
4193 get_tok_str(v, NULL));
4195 size = type_size(t, &align);
4196 lbit_pos = 0;
4197 if (bit_size >= 0) {
4198 bt = t & VT_BTYPE;
4199 if (bt != VT_INT &&
4200 bt != VT_BYTE &&
4201 bt != VT_SHORT)
4202 error("bitfields must have scalar type");
4203 bsize = size * 8;
4204 if (bit_size > bsize) {
4205 error("width of '%s' exceeds its type",
4206 get_tok_str(v, NULL));
4207 } else if (bit_size == bsize) {
4208 /* no need for bit fields */
4209 bit_pos = 0;
4210 } else if (bit_size == 0) {
4211 /* XXX: what to do if only padding in a
4212 structure ? */
4213 /* zero size: means to pad */
4214 if (bit_pos > 0)
4215 bit_pos = bsize;
4216 } else {
4217 /* we do not have enough room ? */
4218 if ((bit_pos + bit_size) > bsize)
4219 bit_pos = 0;
4220 lbit_pos = bit_pos;
4221 /* XXX: handle LSB first */
4222 t |= VT_BITFIELD |
4223 (bit_pos << VT_STRUCT_SHIFT) |
4224 (bit_size << (VT_STRUCT_SHIFT + 6));
4225 bit_pos += bit_size;
4227 } else {
4228 bit_pos = 0;
4230 if (v) {
4231 /* add new memory data only if starting
4232 bit field */
4233 if (lbit_pos == 0) {
4234 if (a == TOK_STRUCT) {
4235 c = (c + align - 1) & -align;
4236 offset = c;
4237 c += size;
4238 } else {
4239 offset = 0;
4240 if (size > c)
4241 c = size;
4243 if (align > maxalign)
4244 maxalign = align;
4246 #if 0
4247 printf("add field %s offset=%d",
4248 get_tok_str(v, NULL), offset);
4249 if (t & VT_BITFIELD) {
4250 printf(" pos=%d size=%d",
4251 (t >> VT_STRUCT_SHIFT) & 0x3f,
4252 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
4254 printf("\n");
4255 #endif
4256 ss = sym_push(v | SYM_FIELD, t, 0, offset);
4257 *ps = ss;
4258 ps = &ss->next;
4260 if (tok == ';' || tok == -1)
4261 break;
4262 skip(',');
4264 skip(';');
4266 if (tok == '}')
4267 break;
4269 skip('}');
4270 /* size for struct/union, dummy for enum */
4271 s->c = (c + maxalign - 1) & -maxalign;
4273 return u;
4276 /* return 0 if no type declaration. otherwise, return the basic type
4277 and skip it.
4279 int parse_btype(int *type_ptr, AttributeDef *ad)
4281 int t, u, type_found;
4282 Sym *s;
4284 memset(ad, 0, sizeof(AttributeDef));
4285 type_found = 0;
4286 t = 0;
4287 while(1) {
4288 switch(tok) {
4289 /* basic types */
4290 case TOK_CHAR:
4291 u = VT_BYTE;
4292 basic_type:
4293 next();
4294 basic_type1:
4295 if ((t & VT_BTYPE) != 0)
4296 error("too many basic types");
4297 t |= u;
4298 break;
4299 case TOK_VOID:
4300 u = VT_VOID;
4301 goto basic_type;
4302 case TOK_SHORT:
4303 u = VT_SHORT;
4304 goto basic_type;
4305 case TOK_INT:
4306 next();
4307 break;
4308 case TOK_LONG:
4309 next();
4310 if ((t & VT_BTYPE) == VT_DOUBLE) {
4311 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4312 } else if ((t & VT_BTYPE) == VT_LONG) {
4313 t = (t & ~VT_BTYPE) | VT_LLONG;
4314 } else {
4315 u = VT_LONG;
4316 goto basic_type1;
4318 break;
4319 case TOK_BOOL:
4320 u = VT_BOOL;
4321 goto basic_type;
4322 case TOK_FLOAT:
4323 u = VT_FLOAT;
4324 goto basic_type;
4325 case TOK_DOUBLE:
4326 next();
4327 if ((t & VT_BTYPE) == VT_LONG) {
4328 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4329 } else {
4330 u = VT_DOUBLE;
4331 goto basic_type1;
4333 break;
4334 case TOK_ENUM:
4335 u = struct_decl(VT_ENUM);
4336 goto basic_type1;
4337 case TOK_STRUCT:
4338 case TOK_UNION:
4339 u = struct_decl(VT_STRUCT);
4340 goto basic_type1;
4342 /* type modifiers */
4343 case TOK_CONST:
4344 case TOK_VOLATILE:
4345 case TOK_REGISTER:
4346 case TOK_SIGNED:
4347 case TOK___SIGNED__:
4348 case TOK_AUTO:
4349 case TOK_INLINE:
4350 case TOK___INLINE__:
4351 case TOK_RESTRICT:
4352 next();
4353 break;
4354 case TOK_UNSIGNED:
4355 t |= VT_UNSIGNED;
4356 next();
4357 break;
4359 /* storage */
4360 case TOK_EXTERN:
4361 t |= VT_EXTERN;
4362 next();
4363 break;
4364 case TOK_STATIC:
4365 t |= VT_STATIC;
4366 next();
4367 break;
4368 case TOK_TYPEDEF:
4369 t |= VT_TYPEDEF;
4370 next();
4371 break;
4372 /* GNUC attribute */
4373 case TOK___ATTRIBUTE__:
4374 parse_attribute(ad);
4375 break;
4376 default:
4377 s = sym_find(tok);
4378 if (!s || !(s->t & VT_TYPEDEF))
4379 goto the_end;
4380 t |= (s->t & ~VT_TYPEDEF);
4381 next();
4382 break;
4384 type_found = 1;
4386 the_end:
4387 /* long is never used as type */
4388 if ((t & VT_BTYPE) == VT_LONG)
4389 t = (t & ~VT_BTYPE) | VT_INT;
4390 *type_ptr = t;
4391 return type_found;
4394 int post_type(int t, AttributeDef *ad)
4396 int p, n, pt, l, t1;
4397 Sym **plast, *s, *first;
4398 AttributeDef ad1;
4400 if (tok == '(') {
4401 /* function declaration */
4402 next();
4403 l = 0;
4404 first = NULL;
4405 plast = &first;
4406 while (tok != ')') {
4407 /* read param name and compute offset */
4408 if (l != FUNC_OLD) {
4409 if (!parse_btype(&pt, &ad1)) {
4410 if (l) {
4411 error("invalid type");
4412 } else {
4413 l = FUNC_OLD;
4414 goto old_proto;
4417 l = FUNC_NEW;
4418 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
4419 break;
4420 pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
4421 if ((pt & VT_BTYPE) == VT_VOID)
4422 error("parameter declared as void");
4423 } else {
4424 old_proto:
4425 n = tok;
4426 pt = VT_INT;
4427 next();
4429 /* array must be transformed to pointer according to ANSI C */
4430 pt &= ~VT_ARRAY;
4431 s = sym_push(n | SYM_FIELD, pt, 0, 0);
4432 *plast = s;
4433 plast = &s->next;
4434 if (tok == ',') {
4435 next();
4436 if (l == FUNC_NEW && tok == TOK_DOTS) {
4437 l = FUNC_ELLIPSIS;
4438 next();
4439 break;
4443 /* if no parameters, then old type prototype */
4444 if (l == 0)
4445 l = FUNC_OLD;
4446 skip(')');
4447 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4448 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4449 /* we push a anonymous symbol which will contain the function prototype */
4450 p = anon_sym++;
4451 s = sym_push(p, t, ad->func_call, l);
4452 s->next = first;
4453 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
4454 } else if (tok == '[') {
4455 /* array definition */
4456 next();
4457 n = -1;
4458 if (tok != ']') {
4459 n = expr_const();
4460 if (n < 0)
4461 error("invalid array size");
4463 skip(']');
4464 /* parse next post type */
4465 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4466 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4468 /* we push a anonymous symbol which will contain the array
4469 element type */
4470 p = anon_sym++;
4471 sym_push(p, t, 0, n);
4472 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
4474 return t;
4477 /* Read a type declaration (except basic type), and return the
4478 type. 'td' is a bitmask indicating which kind of type decl is
4479 expected. 't' should contain the basic type. 'ad' is the attribute
4480 definition of the basic type. It can be modified by type_decl(). */
4481 int type_decl(AttributeDef *ad, int *v, int t, int td)
4483 int u, p;
4484 Sym *s;
4486 while (tok == '*') {
4487 next();
4488 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
4489 next();
4490 t = mk_pointer(t);
4493 /* recursive type */
4494 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4495 if (tok == '(') {
4496 next();
4497 /* XXX: this is not correct to modify 'ad' at this point, but
4498 the syntax is not clear */
4499 if (tok == TOK___ATTRIBUTE__)
4500 parse_attribute(ad);
4501 u = type_decl(ad, v, 0, td);
4502 skip(')');
4503 } else {
4504 u = 0;
4505 /* type identifier */
4506 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
4507 *v = tok;
4508 next();
4509 } else {
4510 if (!(td & TYPE_ABSTRACT))
4511 expect("identifier");
4512 *v = 0;
4515 /* append t at the end of u */
4516 t = post_type(t, ad);
4517 if (tok == TOK___ATTRIBUTE__)
4518 parse_attribute(ad);
4519 if (!u)
4520 return t;
4521 p = u;
4522 while(1) {
4523 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
4524 p = s->t;
4525 if (!p) {
4526 s->t = t;
4527 break;
4530 return u;
4533 /* define a new external reference to a function 'v' of type 'u' */
4534 Sym *external_sym(int v, int u, int r)
4536 Sym *s;
4537 s = sym_find(v);
4538 if (!s) {
4539 /* push forward reference */
4540 s = sym_push1(&global_stack,
4541 v, u, 0);
4542 s->r = r | VT_CONST | VT_FORWARD;
4544 return s;
4547 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
4548 static int lvalue_type(int t)
4550 int bt, r;
4551 r = VT_LVAL;
4552 bt = t & VT_BTYPE;
4553 if (bt == VT_BYTE)
4554 r |= VT_LVAL_BYTE;
4555 else if (bt == VT_SHORT)
4556 r |= VT_LVAL_SHORT;
4557 else
4558 return r;
4559 if (t & VT_UNSIGNED)
4560 r |= VT_LVAL_UNSIGNED;
4561 return r;
4564 /* indirection with full error checking and bound check */
4565 static void indir(void)
4567 if ((vtop->t & VT_BTYPE) != VT_PTR)
4568 expect("pointer");
4569 if (vtop->r & VT_LVAL)
4570 gv(RC_INT);
4571 vtop->t = pointed_type(vtop->t);
4572 /* an array is never an lvalue */
4573 if (!(vtop->t & VT_ARRAY)) {
4574 vtop->r |= lvalue_type(vtop->t);
4575 /* if bound checking, the referenced pointer must be checked */
4576 if (do_bounds_check)
4577 vtop->r |= VT_MUSTBOUND;
4581 /* pass a parameter to a function and do type checking and casting */
4582 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
4584 int func_type;
4585 func_type = func->c;
4586 if (func_type == FUNC_OLD ||
4587 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
4588 /* default casting : only need to convert float to double */
4589 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
4590 gen_cast(VT_DOUBLE);
4591 } else if (arg == NULL) {
4592 error("too many arguments to function");
4593 } else {
4594 gen_assign_cast(arg->t);
4596 gfunc_param(gf);
4599 void unary(void)
4601 int n, t, ft, fc, p, align, size, r, data_offset;
4602 Sym *s;
4603 GFuncContext gf;
4604 AttributeDef ad;
4606 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
4607 vpushi(tokc.i);
4608 next();
4609 } else if (tok == TOK_CUINT) {
4610 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
4611 next();
4612 } else if (tok == TOK_CLLONG) {
4613 vsetc(VT_LLONG, VT_CONST, &tokc);
4614 next();
4615 } else if (tok == TOK_CULLONG) {
4616 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
4617 next();
4618 } else if (tok == TOK_CFLOAT) {
4619 vsetc(VT_FLOAT, VT_CONST, &tokc);
4620 next();
4621 } else if (tok == TOK_CDOUBLE) {
4622 vsetc(VT_DOUBLE, VT_CONST, &tokc);
4623 next();
4624 } else if (tok == TOK_CLDOUBLE) {
4625 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
4626 next();
4627 } else if (tok == TOK___FUNC__) {
4628 /* special function name identifier */
4629 /* generate (char *) type */
4630 data_offset = (int)data_section->data_ptr;
4631 vset(mk_pointer(VT_BYTE), VT_CONST, data_offset);
4632 strcpy((void *)data_offset, funcname);
4633 data_offset += strlen(funcname) + 1;
4634 data_section->data_ptr = (unsigned char *)data_offset;
4635 next();
4636 } else if (tok == TOK_LSTR) {
4637 t = VT_INT;
4638 goto str_init;
4639 } else if (tok == TOK_STR) {
4640 /* string parsing */
4641 t = VT_BYTE;
4642 str_init:
4643 type_size(t, &align);
4644 data_offset = (int)data_section->data_ptr;
4645 data_offset = (data_offset + align - 1) & -align;
4646 fc = data_offset;
4647 /* we must declare it as an array first to use initializer parser */
4648 t = VT_ARRAY | mk_pointer(t);
4649 decl_initializer(t, VT_CONST, data_offset, 1, 0);
4650 data_offset += type_size(t, &align);
4651 /* put it as pointer */
4652 vset(t & ~VT_ARRAY, VT_CONST, fc);
4653 data_section->data_ptr = (unsigned char *)data_offset;
4654 } else {
4655 t = tok;
4656 next();
4657 if (t == '(') {
4658 /* cast ? */
4659 if (parse_btype(&t, &ad)) {
4660 ft = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4661 skip(')');
4662 /* check ISOC99 compound literal */
4663 if (tok == '{') {
4664 /* data is allocated locally by default */
4665 if (global_expr)
4666 r = VT_CONST;
4667 else
4668 r = VT_LOCAL;
4669 /* all except arrays are lvalues */
4670 if (!(ft & VT_ARRAY))
4671 r |= lvalue_type(ft);
4672 memset(&ad, 0, sizeof(AttributeDef));
4673 fc = decl_initializer_alloc(ft, &ad, r, 1);
4674 vset(ft, r, fc);
4675 } else {
4676 unary();
4677 gen_cast(ft);
4679 } else {
4680 gexpr();
4681 skip(')');
4683 } else if (t == '*') {
4684 unary();
4685 indir();
4686 } else if (t == '&') {
4687 unary();
4688 /* functions names must be treated as function pointers,
4689 except for unary '&' and sizeof. Since we consider that
4690 functions are not lvalues, we only have to handle it
4691 there and in function calls. */
4692 /* arrays can also be used although they are not lvalues */
4693 if ((vtop->t & VT_BTYPE) != VT_FUNC &&
4694 !(vtop->t & VT_ARRAY))
4695 test_lvalue();
4696 vtop->t = mk_pointer(vtop->t);
4697 gaddrof();
4698 } else
4699 if (t == '!') {
4700 unary();
4701 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
4702 vtop->c.i = !vtop->c.i;
4703 else if ((vtop->r & VT_VALMASK) == VT_CMP)
4704 vtop->c.i = vtop->c.i ^ 1;
4705 else
4706 vset(VT_INT, VT_JMP, gtst(1, 0));
4707 } else
4708 if (t == '~') {
4709 unary();
4710 vpushi(-1);
4711 gen_op('^');
4712 } else
4713 if (t == '+') {
4714 unary();
4715 } else
4716 if (t == TOK_SIZEOF) {
4717 if (tok == '(') {
4718 next();
4719 if (parse_btype(&t, &ad)) {
4720 t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4721 } else {
4722 /* XXX: some code could be generated: add eval
4723 flag */
4724 gexpr();
4725 t = vtop->t;
4726 vpop();
4728 skip(')');
4729 } else {
4730 unary();
4731 t = vtop->t;
4732 vpop();
4734 vpushi(type_size(t, &t));
4735 } else
4736 if (t == TOK_INC || t == TOK_DEC) {
4737 unary();
4738 inc(0, t);
4739 } else if (t == '-') {
4740 vpushi(0);
4741 unary();
4742 gen_op('-');
4743 } else
4745 if (t < TOK_UIDENT)
4746 expect("identifier");
4747 s = sym_find(t);
4748 if (!s) {
4749 if (tok != '(')
4750 error("'%s' undeclared", get_tok_str(t, NULL));
4751 /* for simple function calls, we tolerate undeclared
4752 external reference */
4753 p = anon_sym++;
4754 sym_push1(&global_stack, p, 0, FUNC_OLD);
4755 /* int() function */
4756 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT), 0);
4758 vset(s->t, s->r, s->c);
4759 /* if forward reference, we must point to s */
4760 if (vtop->r & VT_FORWARD)
4761 vtop->c.sym = s;
4765 /* post operations */
4766 while (1) {
4767 if (tok == TOK_INC || tok == TOK_DEC) {
4768 inc(1, tok);
4769 next();
4770 } else if (tok == '.' || tok == TOK_ARROW) {
4771 /* field */
4772 if (tok == TOK_ARROW)
4773 indir();
4774 test_lvalue();
4775 gaddrof();
4776 next();
4777 /* expect pointer on structure */
4778 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
4779 expect("struct or union");
4780 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4781 /* find field */
4782 tok |= SYM_FIELD;
4783 while ((s = s->next) != NULL) {
4784 if (s->v == tok)
4785 break;
4787 if (!s)
4788 error("field not found");
4789 /* add field offset to pointer */
4790 vtop->t = char_pointer_type; /* change type to 'char *' */
4791 vpushi(s->c);
4792 gen_op('+');
4793 /* change type to field type, and set to lvalue */
4794 vtop->t = s->t;
4795 /* an array is never an lvalue */
4796 if (!(vtop->t & VT_ARRAY))
4797 vtop->r |= lvalue_type(vtop->t);
4798 next();
4799 } else if (tok == '[') {
4800 next();
4801 gexpr();
4802 gen_op('+');
4803 indir();
4804 skip(']');
4805 } else if (tok == '(') {
4806 SValue ret;
4807 Sym *sa;
4809 /* function call */
4810 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
4811 /* pointer test (no array accepted) */
4812 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
4813 vtop->t = pointed_type(vtop->t);
4814 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4815 goto error_func;
4816 } else {
4817 error_func:
4818 expect("function pointer");
4820 } else {
4821 vtop->r &= ~VT_LVAL; /* no lvalue */
4823 /* get return type */
4824 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
4825 save_regs(0); /* save used temporary registers */
4826 gfunc_start(&gf, s->r);
4827 next();
4828 sa = s->next; /* first parameter */
4829 #ifdef INVERT_FUNC_PARAMS
4831 int parlevel;
4832 Sym *args, *s1;
4833 ParseState saved_parse_state;
4834 TokenString str;
4836 /* read each argument and store it on a stack */
4837 /* XXX: merge it with macro args ? */
4838 args = NULL;
4839 if (tok != ')') {
4840 for(;;) {
4841 tok_str_new(&str);
4842 parlevel = 0;
4843 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
4844 tok != -1) {
4845 if (tok == '(')
4846 parlevel++;
4847 else if (tok == ')')
4848 parlevel--;
4849 tok_str_add_tok(&str);
4850 next();
4852 tok_str_add(&str, -1); /* end of file added */
4853 tok_str_add(&str, 0);
4854 s1 = sym_push2(&args, 0, 0, (int)str.str);
4855 s1->next = sa; /* add reference to argument */
4856 if (sa)
4857 sa = sa->next;
4858 if (tok == ')')
4859 break;
4860 skip(',');
4864 /* now generate code in reverse order by reading the stack */
4865 save_parse_state(&saved_parse_state);
4866 while (args) {
4867 macro_ptr = (int *)args->c;
4868 next();
4869 expr_eq();
4870 if (tok != -1)
4871 expect("',' or ')'");
4872 gfunc_param_typed(&gf, s, args->next);
4873 s1 = args->prev;
4874 free((int *)args->c);
4875 free(args);
4876 args = s1;
4878 restore_parse_state(&saved_parse_state);
4880 #endif
4881 /* compute first implicit argument if a structure is returned */
4882 if ((s->t & VT_BTYPE) == VT_STRUCT) {
4883 /* get some space for the returned structure */
4884 size = type_size(s->t, &align);
4885 loc = (loc - size) & -align;
4886 ret.t = s->t;
4887 ret.r = VT_LOCAL | VT_LVAL;
4888 /* pass it as 'int' to avoid structure arg passing
4889 problems */
4890 vset(VT_INT, VT_LOCAL, loc);
4891 ret.c = vtop->c;
4892 gfunc_param(&gf);
4893 } else {
4894 ret.t = s->t;
4895 ret.r2 = VT_CONST;
4896 /* return in register */
4897 if (is_float(ret.t)) {
4898 ret.r = REG_FRET;
4899 } else {
4900 if ((ret.t & VT_BTYPE) == VT_LLONG)
4901 ret.r2 = REG_LRET;
4902 ret.r = REG_IRET;
4904 ret.c.i = 0;
4906 #ifndef INVERT_FUNC_PARAMS
4907 if (tok != ')') {
4908 for(;;) {
4909 expr_eq();
4910 gfunc_param_typed(&gf, s, sa);
4911 if (sa)
4912 sa = sa->next;
4913 if (tok == ')')
4914 break;
4915 skip(',');
4918 #endif
4919 if (sa)
4920 error("too few arguments to function");
4921 skip(')');
4922 gfunc_call(&gf);
4923 /* return value */
4924 vsetc(ret.t, ret.r, &ret.c);
4925 vtop->r2 = ret.r2;
4926 } else {
4927 break;
4932 void uneq(void)
4934 int t;
4936 unary();
4937 if (tok == '=' ||
4938 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
4939 tok == TOK_A_XOR || tok == TOK_A_OR ||
4940 tok == TOK_A_SHL || tok == TOK_A_SAR) {
4941 test_lvalue();
4942 t = tok;
4943 next();
4944 if (t == '=') {
4945 expr_eq();
4946 } else {
4947 vdup();
4948 expr_eq();
4949 gen_op(t & 0x7f);
4951 vstore();
4955 void sum(int l)
4957 int t;
4959 if (l == 0)
4960 uneq();
4961 else {
4962 sum(--l);
4963 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
4964 (l == 1 && (tok == '+' || tok == '-')) ||
4965 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
4966 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
4967 tok == TOK_ULT || tok == TOK_UGE)) ||
4968 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
4969 (l == 5 && tok == '&') ||
4970 (l == 6 && tok == '^') ||
4971 (l == 7 && tok == '|') ||
4972 (l == 8 && tok == TOK_LAND) ||
4973 (l == 9 && tok == TOK_LOR)) {
4974 t = tok;
4975 next();
4976 sum(l);
4977 gen_op(t);
4982 /* only used if non constant */
4983 void eand(void)
4985 int t;
4987 sum(8);
4988 t = 0;
4989 while (1) {
4990 if (tok != TOK_LAND) {
4991 if (t) {
4992 t = gtst(1, t);
4993 vset(VT_INT, VT_JMPI, t);
4995 break;
4997 t = gtst(1, t);
4998 next();
4999 sum(8);
5003 void eor(void)
5005 int t;
5007 eand();
5008 t = 0;
5009 while (1) {
5010 if (tok != TOK_LOR) {
5011 if (t) {
5012 t = gtst(0, t);
5013 vset(VT_INT, VT_JMP, t);
5015 break;
5017 t = gtst(0, t);
5018 next();
5019 eand();
5023 /* XXX: better constant handling */
5024 void expr_eq(void)
5026 int t, u, c, r1, r2, rc;
5028 if (const_wanted) {
5029 sum(10);
5030 if (tok == '?') {
5031 c = vtop->c.i;
5032 vpop();
5033 next();
5034 gexpr();
5035 t = vtop->c.i;
5036 vpop();
5037 skip(':');
5038 expr_eq();
5039 if (c)
5040 vtop->c.i = t;
5042 } else {
5043 eor();
5044 if (tok == '?') {
5045 next();
5046 save_regs(1); /* we need to save all registers here except
5047 at the top because it is a branch point */
5048 t = gtst(1, 0);
5049 gexpr();
5050 /* XXX: long long handling ? */
5051 rc = RC_INT;
5052 if (is_float(vtop->t))
5053 rc = RC_FLOAT;
5054 r1 = gv(rc);
5055 vtop--; /* no vpop so that FP stack is not flushed */
5056 skip(':');
5057 u = gjmp(0);
5059 gsym(t);
5060 expr_eq();
5061 r2 = gv(rc);
5062 move_reg(r1, r2);
5063 vtop->r = r1;
5064 gsym(u);
5069 void gexpr(void)
5071 while (1) {
5072 expr_eq();
5073 if (tok != ',')
5074 break;
5075 vpop();
5076 next();
5080 /* parse a constant expression and return value in vtop */
5081 void expr_const1(void)
5083 int a;
5084 a = const_wanted;
5085 const_wanted = 1;
5086 expr_eq();
5087 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
5088 expect("constant");
5089 const_wanted = a;
5092 /* parse an integer constant and return its value */
5093 int expr_const(void)
5095 int c;
5096 expr_const1();
5097 c = vtop->c.i;
5098 vpop();
5099 return c;
5102 /* return the label token if current token is a label, otherwise
5103 return zero */
5104 int is_label(void)
5106 int t;
5107 CValue c;
5109 /* fast test first */
5110 if (tok < TOK_UIDENT)
5111 return 0;
5112 /* no need to save tokc since we expect an identifier */
5113 t = tok;
5114 c = tokc;
5115 next();
5116 if (tok == ':') {
5117 next();
5118 return t;
5119 } else {
5120 /* XXX: may not work in all cases (macros ?) */
5121 tok1 = tok;
5122 tok1c = tokc;
5123 tok = t;
5124 tokc = c;
5125 return 0;
5129 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
5131 int a, b, c, d;
5132 Sym *s;
5134 /* generate line number info */
5135 if (do_debug &&
5136 (last_line_num != file->line_num || last_ind != ind)) {
5137 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
5138 last_ind = ind;
5139 last_line_num = file->line_num;
5142 if (tok == TOK_IF) {
5143 /* if test */
5144 next();
5145 skip('(');
5146 gexpr();
5147 skip(')');
5148 a = gtst(1, 0);
5149 block(bsym, csym, case_sym, def_sym, case_reg);
5150 c = tok;
5151 if (c == TOK_ELSE) {
5152 next();
5153 d = gjmp(0);
5154 gsym(a);
5155 block(bsym, csym, case_sym, def_sym, case_reg);
5156 gsym(d); /* patch else jmp */
5157 } else
5158 gsym(a);
5159 } else if (tok == TOK_WHILE) {
5160 next();
5161 d = ind;
5162 skip('(');
5163 gexpr();
5164 skip(')');
5165 a = gtst(1, 0);
5166 b = 0;
5167 block(&a, &b, case_sym, def_sym, case_reg);
5168 gjmp_addr(d);
5169 gsym(a);
5170 gsym_addr(b, d);
5171 } else if (tok == '{') {
5172 next();
5173 /* declarations */
5174 s = local_stack.top;
5175 while (tok != '}') {
5176 decl(VT_LOCAL);
5177 if (tok != '}')
5178 block(bsym, csym, case_sym, def_sym, case_reg);
5180 /* pop locally defined symbols */
5181 sym_pop(&local_stack, s);
5182 next();
5183 } else if (tok == TOK_RETURN) {
5184 next();
5185 if (tok != ';') {
5186 gexpr();
5187 gen_assign_cast(func_vt);
5188 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
5189 /* if returning structure, must copy it to implicit
5190 first pointer arg location */
5191 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
5192 indir();
5193 vswap();
5194 /* copy structure value to pointer */
5195 vstore();
5196 } else if (is_float(func_vt)) {
5197 gv(RC_FRET);
5198 } else {
5199 gv(RC_IRET);
5201 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5203 skip(';');
5204 rsym = gjmp(rsym); /* jmp */
5205 } else if (tok == TOK_BREAK) {
5206 /* compute jump */
5207 if (!bsym)
5208 error("cannot break");
5209 *bsym = gjmp(*bsym);
5210 next();
5211 skip(';');
5212 } else if (tok == TOK_CONTINUE) {
5213 /* compute jump */
5214 if (!csym)
5215 error("cannot continue");
5216 *csym = gjmp(*csym);
5217 next();
5218 skip(';');
5219 } else if (tok == TOK_FOR) {
5220 int e;
5221 next();
5222 skip('(');
5223 if (tok != ';') {
5224 gexpr();
5225 vpop();
5227 skip(';');
5228 d = ind;
5229 c = ind;
5230 a = 0;
5231 b = 0;
5232 if (tok != ';') {
5233 gexpr();
5234 a = gtst(1, 0);
5236 skip(';');
5237 if (tok != ')') {
5238 e = gjmp(0);
5239 c = ind;
5240 gexpr();
5241 vpop();
5242 gjmp_addr(d);
5243 gsym(e);
5245 skip(')');
5246 block(&a, &b, case_sym, def_sym, case_reg);
5247 gjmp_addr(c);
5248 gsym(a);
5249 gsym_addr(b, c);
5250 } else
5251 if (tok == TOK_DO) {
5252 next();
5253 a = 0;
5254 b = 0;
5255 d = ind;
5256 block(&a, &b, case_sym, def_sym, case_reg);
5257 skip(TOK_WHILE);
5258 skip('(');
5259 gsym(b);
5260 gexpr();
5261 c = gtst(0, 0);
5262 gsym_addr(c, d);
5263 skip(')');
5264 gsym(a);
5265 skip(';');
5266 } else
5267 if (tok == TOK_SWITCH) {
5268 next();
5269 skip('(');
5270 gexpr();
5271 /* XXX: other types than integer */
5272 case_reg = gv(RC_INT);
5273 vpop();
5274 skip(')');
5275 a = 0;
5276 b = gjmp(0); /* jump to first case */
5277 c = 0;
5278 block(&a, csym, &b, &c, case_reg);
5279 /* if no default, jmp after switch */
5280 if (c == 0)
5281 c = ind;
5282 /* default label */
5283 gsym_addr(b, c);
5284 /* break label */
5285 gsym(a);
5286 } else
5287 if (tok == TOK_CASE) {
5288 int v1, v2;
5289 if (!case_sym)
5290 expect("switch");
5291 next();
5292 v1 = expr_const();
5293 v2 = v1;
5294 if (gnu_ext && tok == TOK_DOTS) {
5295 next();
5296 v2 = expr_const();
5297 if (v2 < v1)
5298 warning("empty case range");
5300 /* since a case is like a label, we must skip it with a jmp */
5301 b = gjmp(0);
5302 gsym(*case_sym);
5303 vset(VT_INT, case_reg, 0);
5304 vpushi(v1);
5305 if (v1 == v2) {
5306 gen_op(TOK_EQ);
5307 *case_sym = gtst(1, 0);
5308 } else {
5309 gen_op(TOK_GE);
5310 *case_sym = gtst(1, 0);
5311 vset(VT_INT, case_reg, 0);
5312 vpushi(v2);
5313 gen_op(TOK_LE);
5314 *case_sym = gtst(1, *case_sym);
5316 gsym(b);
5317 skip(':');
5318 block(bsym, csym, case_sym, def_sym, case_reg);
5319 } else
5320 if (tok == TOK_DEFAULT) {
5321 next();
5322 skip(':');
5323 if (!def_sym)
5324 expect("switch");
5325 if (*def_sym)
5326 error("too many 'default'");
5327 *def_sym = ind;
5328 block(bsym, csym, case_sym, def_sym, case_reg);
5329 } else
5330 if (tok == TOK_GOTO) {
5331 next();
5332 s = sym_find1(&label_stack, tok);
5333 /* put forward definition if needed */
5334 if (!s)
5335 s = sym_push1(&label_stack, tok, VT_FORWARD, 0);
5336 /* label already defined */
5337 if (s->t & VT_FORWARD)
5338 s->c = gjmp(s->c);
5339 else
5340 gjmp_addr(s->c);
5341 next();
5342 skip(';');
5343 } else {
5344 b = is_label();
5345 if (b) {
5346 /* label case */
5347 s = sym_find1(&label_stack, b);
5348 if (s) {
5349 if (!(s->t & VT_FORWARD))
5350 error("multiple defined label");
5351 gsym(s->c);
5352 s->c = ind;
5353 s->t = 0;
5354 } else {
5355 sym_push1(&label_stack, b, 0, ind);
5357 /* we accept this, but it is a mistake */
5358 if (tok == '}')
5359 warning("deprecated use of label at end of compound statement");
5360 else
5361 block(bsym, csym, case_sym, def_sym, case_reg);
5362 } else {
5363 /* expression case */
5364 if (tok != ';') {
5365 gexpr();
5366 vpop();
5368 skip(';');
5373 /* t is the array or struct type. c is the array or struct
5374 address. cur_index/cur_field is the pointer to the current
5375 value. 'size_only' is true if only size info is needed (only used
5376 in arrays) */
5377 void decl_designator(int t, int r, int c,
5378 int *cur_index, Sym **cur_field,
5379 int size_only)
5381 Sym *s, *f;
5382 int notfirst, index, align, l;
5384 notfirst = 0;
5385 if (gnu_ext && (l = is_label()) != 0)
5386 goto struct_field;
5388 while (tok == '[' || tok == '.') {
5389 if (tok == '[') {
5390 if (!(t & VT_ARRAY))
5391 expect("array type");
5392 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5393 next();
5394 index = expr_const();
5395 if (index < 0 || (s->c >= 0 && index >= s->c))
5396 expect("invalid index");
5397 skip(']');
5398 if (!notfirst)
5399 *cur_index = index;
5400 t = pointed_type(t);
5401 c += index * type_size(t, &align);
5402 } else {
5403 next();
5404 l = tok;
5405 next();
5406 struct_field:
5407 if ((t & VT_BTYPE) != VT_STRUCT)
5408 expect("struct/union type");
5409 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5410 l |= SYM_FIELD;
5411 f = s->next;
5412 while (f) {
5413 if (f->v == l)
5414 break;
5415 f = f->next;
5417 if (!f)
5418 expect("field");
5419 if (!notfirst)
5420 *cur_field = f;
5421 t = f->t | (t & ~VT_TYPE);
5422 c += f->c;
5424 notfirst = 1;
5426 if (notfirst) {
5427 if (tok == '=') {
5428 next();
5429 } else {
5430 if (!gnu_ext)
5431 expect("=");
5433 } else {
5434 if (t & VT_ARRAY) {
5435 index = *cur_index;
5436 t = pointed_type(t);
5437 c += index * type_size(t, &align);
5438 } else {
5439 f = *cur_field;
5440 if (!f)
5441 error("too many field init");
5442 t = f->t | (t & ~VT_TYPE);
5443 c += f->c;
5446 decl_initializer(t, r, c, 0, size_only);
5449 #define EXPR_VAL 0
5450 #define EXPR_CONST 1
5451 #define EXPR_ANY 2
5453 /* store a value or an expression directly in global data or in local array */
5454 void init_putv(int t, int r, int c,
5455 int v, int expr_type)
5457 int saved_global_expr, bt;
5459 switch(expr_type) {
5460 case EXPR_VAL:
5461 vpushi(v);
5462 break;
5463 case EXPR_CONST:
5464 /* compound literals must be allocated globally in this case */
5465 saved_global_expr = global_expr;
5466 global_expr = 1;
5467 expr_const1();
5468 global_expr = saved_global_expr;
5469 break;
5470 case EXPR_ANY:
5471 expr_eq();
5472 break;
5475 if ((r & VT_VALMASK) == VT_CONST) {
5476 /* XXX: not portable */
5477 gen_assign_cast(t);
5478 bt = t & VT_BTYPE;
5479 switch(bt) {
5480 case VT_BYTE:
5481 *(char *)c = vtop->c.i;
5482 break;
5483 case VT_SHORT:
5484 *(short *)c = vtop->c.i;
5485 break;
5486 case VT_DOUBLE:
5487 *(double *)c = vtop->c.d;
5488 break;
5489 case VT_LDOUBLE:
5490 *(long double *)c = vtop->c.ld;
5491 break;
5492 case VT_LLONG:
5493 *(long long *)c = vtop->c.ll;
5494 break;
5495 default:
5496 *(int *)c = vtop->c.i;
5497 break;
5499 vtop--;
5500 } else {
5501 vset(t, r, c);
5502 vswap();
5503 vstore();
5504 vpop();
5508 /* put zeros for variable based init */
5509 void init_putz(int t, int r, int c, int size)
5511 GFuncContext gf;
5513 if ((r & VT_VALMASK) == VT_CONST) {
5514 /* nothing to do because globals are already set to zero */
5515 } else {
5516 gfunc_start(&gf, FUNC_CDECL);
5517 vpushi(size);
5518 gfunc_param(&gf);
5519 vpushi(0);
5520 gfunc_param(&gf);
5521 vset(VT_INT, VT_LOCAL, c);
5522 gfunc_param(&gf);
5523 vpushi((int)&memset);
5524 gfunc_call(&gf);
5528 /* 't' contains the type and storage info. c is the address of the
5529 object. 'first' is true if array '{' must be read (multi dimension
5530 implicit array init handling). 'size_only' is true if size only
5531 evaluation is wanted (only for arrays). */
5532 void decl_initializer(int t, int r, int c, int first, int size_only)
5534 int index, array_length, n, no_oblock, nb, parlevel, i;
5535 int t1, size1, align1, expr_type;
5536 Sym *s, *f;
5537 TokenSym *ts;
5539 if (t & VT_ARRAY) {
5540 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5541 n = s->c;
5542 array_length = 0;
5543 t1 = pointed_type(t);
5544 size1 = type_size(t1, &align1);
5546 no_oblock = 1;
5547 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
5548 tok == '{') {
5549 skip('{');
5550 no_oblock = 0;
5553 /* only parse strings here if correct type (otherwise: handle
5554 them as ((w)char *) expressions */
5555 if ((tok == TOK_LSTR &&
5556 (t1 & VT_BTYPE) == VT_INT) ||
5557 (tok == TOK_STR &&
5558 (t1 & VT_BTYPE) == VT_BYTE)) {
5559 /* XXX: move multiple string parsing in parser ? */
5560 while (tok == TOK_STR || tok == TOK_LSTR) {
5561 ts = tokc.ts;
5562 /* compute maximum number of chars wanted */
5563 nb = ts->len;
5564 if (n >= 0 && nb > (n - array_length))
5565 nb = n - array_length;
5566 if (!size_only) {
5567 if (ts->len > nb)
5568 warning("initializer-string for array is too long");
5569 for(i=0;i<nb;i++) {
5570 init_putv(t1, r, c + (array_length + i) * size1,
5571 ts->str[i], EXPR_VAL);
5574 array_length += nb;
5575 next();
5577 /* only add trailing zero if enough storage (no
5578 warning in this case since it is standard) */
5579 if (n < 0 || array_length < n) {
5580 if (!size_only) {
5581 init_putv(t1, r, c + (array_length * size1), 0, EXPR_VAL);
5583 array_length++;
5585 } else {
5586 index = 0;
5587 while (tok != '}') {
5588 decl_designator(t, r, c, &index, NULL, size_only);
5589 if (n >= 0 && index >= n)
5590 error("index too large");
5591 /* must put zero in holes (note that doing it that way
5592 ensures that it even works with designators) */
5593 if (!size_only && array_length < index) {
5594 init_putz(t1, r, c + array_length * size1,
5595 (index - array_length) * size1);
5597 index++;
5598 if (index > array_length)
5599 array_length = index;
5600 /* special test for multi dimensional arrays (may not
5601 be strictly correct if designators are used at the
5602 same time) */
5603 if (index >= n && no_oblock)
5604 break;
5605 if (tok == '}')
5606 break;
5607 skip(',');
5610 if (!no_oblock)
5611 skip('}');
5612 /* put zeros at the end */
5613 if (!size_only && n >= 0 && array_length < n) {
5614 init_putz(t1, r, c + array_length * size1,
5615 (n - array_length) * size1);
5617 /* patch type size if needed */
5618 if (n < 0)
5619 s->c = array_length;
5620 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
5621 /* XXX: union needs only one init */
5622 next();
5623 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5624 f = s->next;
5625 array_length = 0;
5626 index = 0;
5627 n = s->c;
5628 while (tok != '}') {
5629 decl_designator(t, r, c, NULL, &f, size_only);
5630 /* fill with zero between fields */
5631 index = f->c;
5632 if (!size_only && array_length < index) {
5633 init_putz(t, r, c + array_length,
5634 index - array_length);
5636 index = index + type_size(f->t, &align1);
5637 if (index > array_length)
5638 array_length = index;
5639 if (tok == '}')
5640 break;
5641 skip(',');
5642 f = f->next;
5644 /* put zeros at the end */
5645 if (!size_only && array_length < n) {
5646 init_putz(t, r, c + array_length,
5647 n - array_length);
5649 skip('}');
5650 } else if (tok == '{') {
5651 next();
5652 decl_initializer(t, r, c, first, size_only);
5653 skip('}');
5654 } else if (size_only) {
5655 /* just skip expression */
5656 parlevel = 0;
5657 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
5658 tok != -1) {
5659 if (tok == '(')
5660 parlevel++;
5661 else if (tok == ')')
5662 parlevel--;
5663 next();
5665 } else {
5666 /* currently, we always use constant expression for globals
5667 (may change for scripting case) */
5668 expr_type = EXPR_CONST;
5669 if ((r & VT_VALMASK) == VT_LOCAL)
5670 expr_type = EXPR_ANY;
5671 init_putv(t, r, c, 0, expr_type);
5675 /* parse an initializer for type 't' if 'has_init' is true, and
5676 allocate space in local or global data space ('r' is either
5677 VT_LOCAL or VT_CONST). The allocated address in returned */
5678 int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init)
5680 int size, align, addr, data_offset;
5681 int level;
5682 ParseState saved_parse_state;
5683 TokenString init_str;
5684 Section *sec;
5686 size = type_size(t, &align);
5687 /* If unknown size, we must evaluate it before
5688 evaluating initializers because
5689 initializers can generate global data too
5690 (e.g. string pointers or ISOC99 compound
5691 literals). It also simplifies local
5692 initializers handling */
5693 tok_str_new(&init_str);
5694 if (size < 0) {
5695 if (!has_init)
5696 error("unknown type size");
5697 /* get all init string */
5698 level = 0;
5699 while (level > 0 || (tok != ',' && tok != ';')) {
5700 if (tok < 0)
5701 error("unexpected end of file in initializer");
5702 tok_str_add_tok(&init_str);
5703 if (tok == '{')
5704 level++;
5705 else if (tok == '}') {
5706 if (level == 0)
5707 break;
5708 level--;
5710 next();
5712 tok_str_add(&init_str, -1);
5713 tok_str_add(&init_str, 0);
5715 /* compute size */
5716 save_parse_state(&saved_parse_state);
5718 macro_ptr = init_str.str;
5719 next();
5720 decl_initializer(t, r, 0, 1, 1);
5721 /* prepare second initializer parsing */
5722 macro_ptr = init_str.str;
5723 next();
5725 /* if still unknown size, error */
5726 size = type_size(t, &align);
5727 if (size < 0)
5728 error("unknown type size");
5730 /* take into account specified alignment if bigger */
5731 if (ad->aligned > align)
5732 align = ad->aligned;
5733 if ((r & VT_VALMASK) == VT_LOCAL) {
5734 if (do_bounds_check && (t & VT_ARRAY))
5735 loc--;
5736 #ifdef TCC_TARGET_IL
5737 /* XXX: ugly patch to allocate local variables for IL, just
5738 for testing */
5739 addr = loc;
5740 loc++;
5741 #else
5742 loc = (loc - size) & -align;
5743 addr = loc;
5744 #endif
5745 /* handles bounds */
5746 /* XXX: currently, since we do only one pass, we cannot track
5747 '&' operators, so we add only arrays */
5748 if (do_bounds_check && (t & VT_ARRAY)) {
5749 int *bounds_ptr;
5750 /* add padding between regions */
5751 loc--;
5752 /* then add local bound info */
5753 bounds_ptr = (int *)lbounds_section->data_ptr;
5754 *bounds_ptr++ = addr;
5755 *bounds_ptr++ = size;
5756 lbounds_section->data_ptr = (unsigned char *)bounds_ptr;
5758 } else {
5759 /* compute section */
5760 sec = ad->section;
5761 if (!sec) {
5762 if (has_init)
5763 sec = data_section;
5764 else
5765 sec = bss_section;
5767 data_offset = (int)sec->data_ptr;
5768 data_offset = (data_offset + align - 1) & -align;
5769 addr = data_offset;
5770 /* very important to increment global
5771 pointer at this time because
5772 initializers themselves can create new
5773 initializers */
5774 data_offset += size;
5775 /* handles bounds */
5776 if (do_bounds_check) {
5777 int *bounds_ptr;
5778 /* first, we need to add at least one byte between each region */
5779 data_offset++;
5780 /* then add global bound info */
5781 bounds_ptr = (int *)bounds_section->data_ptr;
5782 *bounds_ptr++ = addr;
5783 *bounds_ptr++ = size;
5784 bounds_section->data_ptr = (unsigned char *)bounds_ptr;
5786 sec->data_ptr = (unsigned char *)data_offset;
5788 if (has_init) {
5789 decl_initializer(t, r, addr, 1, 0);
5790 /* restore parse state if needed */
5791 if (init_str.str) {
5792 free(init_str.str);
5793 restore_parse_state(&saved_parse_state);
5796 return addr;
5799 void put_func_debug(int t)
5801 int bind;
5802 char buf[512];
5804 if (t & VT_STATIC)
5805 bind = STB_LOCAL;
5806 else
5807 bind = STB_GLOBAL;
5808 put_elf_sym(symtab_section, ind, 0,
5809 ELF32_ST_INFO(bind, STT_FUNC), 0,
5810 cur_text_section->sh_num, funcname);
5811 /* stabs info */
5812 /* XXX: we put here a dummy type */
5813 snprintf(buf, sizeof(buf), "%s:%c1",
5814 funcname, t & VT_STATIC ? 'f' : 'F');
5815 put_stabs(buf, N_FUN, 0, file->line_num, ind);
5816 func_ind = ind;
5817 last_ind = 0;
5818 last_line_num = 0;
5821 /* not finished : try to put some local vars in registers */
5822 //#define CONFIG_REG_VARS
5824 #ifdef CONFIG_REG_VARS
5825 void add_var_ref(int t)
5827 printf("%s:%d: &%s\n",
5828 file->filename, file->line_num,
5829 get_tok_str(t, NULL));
5832 /* first pass on a function with heuristic to extract variable usage
5833 and pointer references to local variables for register allocation */
5834 void analyse_function(void)
5836 int level, t;
5838 for(;;) {
5839 if (tok == -1)
5840 break;
5841 /* any symbol coming after '&' is considered as being a
5842 variable whose reference is taken. It is highly unaccurate
5843 but it is difficult to do better without a complete parse */
5844 if (tok == '&') {
5845 next();
5846 /* if '& number', then no need to examine next tokens */
5847 if (tok == TOK_CINT ||
5848 tok == TOK_CUINT ||
5849 tok == TOK_CLLONG ||
5850 tok == TOK_CULLONG) {
5851 continue;
5852 } else if (tok >= TOK_UIDENT) {
5853 /* if '& ident [' or '& ident ->', then ident address
5854 is not needed */
5855 t = tok;
5856 next();
5857 if (tok != '[' && tok != TOK_ARROW)
5858 add_var_ref(t);
5859 } else {
5860 level = 0;
5861 while (tok != '}' && tok != ';' &&
5862 !((tok == ',' || tok == ')') && level == 0)) {
5863 if (tok >= TOK_UIDENT) {
5864 add_var_ref(tok);
5865 } else if (tok == '(') {
5866 level++;
5867 } else if (tok == ')') {
5868 level--;
5870 next();
5873 } else {
5874 next();
5878 #endif
5880 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5881 void decl(int l)
5883 int t, b, v, addr, has_init, r;
5884 Sym *sym;
5885 AttributeDef ad;
5887 while (1) {
5888 if (!parse_btype(&b, &ad)) {
5889 /* skip redundant ';' */
5890 /* XXX: find more elegant solution */
5891 if (tok == ';') {
5892 next();
5893 continue;
5895 /* special test for old K&R protos without explicit int
5896 type. Only accepted when defining global data */
5897 if (l == VT_LOCAL || tok < TOK_DEFINE)
5898 break;
5899 b = VT_INT;
5901 if (((b & VT_BTYPE) == VT_ENUM ||
5902 (b & VT_BTYPE) == VT_STRUCT) &&
5903 tok == ';') {
5904 /* we accept no variable after */
5905 next();
5906 continue;
5908 while (1) { /* iterate thru each declaration */
5909 t = type_decl(&ad, &v, b, TYPE_DIRECT);
5910 #if 0
5912 char buf[500];
5913 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
5914 printf("type = '%s'\n", buf);
5916 #endif
5917 if (tok == '{') {
5918 #ifdef CONFIG_REG_VARS
5919 TokenString func_str;
5920 ParseState saved_parse_state;
5921 int block_level;
5922 #endif
5924 if (l == VT_LOCAL)
5925 error("cannot use local functions");
5926 if (!(t & VT_FUNC))
5927 expect("function definition");
5929 #ifdef CONFIG_REG_VARS
5930 /* parse all function code and record it */
5932 tok_str_new(&func_str);
5934 block_level = 0;
5935 for(;;) {
5936 int t;
5937 if (tok == -1)
5938 error("unexpected end of file");
5939 tok_str_add_tok(&func_str);
5940 t = tok;
5941 next();
5942 if (t == '{') {
5943 block_level++;
5944 } else if (t == '}') {
5945 block_level--;
5946 if (block_level == 0)
5947 break;
5950 tok_str_add(&func_str, -1);
5951 tok_str_add(&func_str, 0);
5953 save_parse_state(&saved_parse_state);
5955 macro_ptr = func_str.str;
5956 next();
5957 analyse_function();
5958 #endif
5960 /* compute text section */
5961 cur_text_section = ad.section;
5962 if (!cur_text_section)
5963 cur_text_section = text_section;
5964 ind = (int)cur_text_section->data_ptr;
5965 /* patch forward references */
5966 if ((sym = sym_find(v)) && (sym->r & VT_FORWARD)) {
5967 greloc_patch(sym, ind);
5968 sym->t = t;
5969 } else {
5970 /* put function address */
5971 sym = sym_push1(&global_stack, v, t, ind);
5973 sym->r = VT_CONST;
5974 funcname = get_tok_str(v, NULL);
5975 /* put debug symbol */
5976 if (do_debug)
5977 put_func_debug(t);
5978 /* push a dummy symbol to enable local sym storage */
5979 sym_push1(&local_stack, 0, 0, 0);
5980 gfunc_prolog(t);
5981 loc = 0;
5982 rsym = 0;
5983 #ifdef CONFIG_REG_VARS
5984 macro_ptr = func_str.str;
5985 next();
5986 #endif
5987 block(NULL, NULL, NULL, NULL, 0);
5988 gsym(rsym);
5989 gfunc_epilog();
5990 cur_text_section->data_ptr = (unsigned char *)ind;
5991 sym_pop(&label_stack, NULL); /* reset label stack */
5992 sym_pop(&local_stack, NULL); /* reset local stack */
5993 /* end of function */
5994 if (do_debug) {
5995 put_stabn(N_FUN, 0, 0, ind - func_ind);
5997 funcname = ""; /* for safety */
5998 func_vt = VT_VOID; /* for safety */
5999 ind = 0; /* for safety */
6001 #ifdef CONFIG_REG_VARS
6002 free(func_str.str);
6003 restore_parse_state(&saved_parse_state);
6004 #endif
6005 break;
6006 } else {
6007 if (b & VT_TYPEDEF) {
6008 /* save typedefed type */
6009 /* XXX: test storage specifiers ? */
6010 sym_push(v, t | VT_TYPEDEF, 0, 0);
6011 } else if ((t & VT_BTYPE) == VT_FUNC) {
6012 /* external function definition */
6013 external_sym(v, t, 0);
6014 } else {
6015 /* not lvalue if array */
6016 r = 0;
6017 if (!(t & VT_ARRAY))
6018 r |= lvalue_type(t);
6019 if (b & VT_EXTERN) {
6020 /* external variable */
6021 external_sym(v, t, r);
6022 } else {
6023 if (t & VT_STATIC)
6024 r |= VT_CONST;
6025 else
6026 r |= l;
6027 has_init = (tok == '=');
6028 if (has_init)
6029 next();
6030 addr = decl_initializer_alloc(t, &ad, r,
6031 has_init);
6032 if (l == VT_CONST) {
6033 /* global scope: see if already defined */
6034 sym = sym_find(v);
6035 if (!sym)
6036 goto do_def;
6037 if (!is_compatible_types(sym->t, t))
6038 error("incompatible types for redefinition of '%s'",
6039 get_tok_str(v, NULL));
6040 if (!(sym->r & VT_FORWARD))
6041 error("redefinition of '%s'", get_tok_str(v, NULL));
6042 greloc_patch(sym, addr);
6043 } else {
6044 do_def:
6045 sym_push(v, t, r, addr);
6049 if (tok != ',') {
6050 skip(';');
6051 break;
6053 next();
6059 /* put all global symbols in the extern stack and do all the
6060 resolving which can be done without using external symbols from DLLs */
6061 /* XXX: could try to verify types, but would not to save them in
6062 extern_stack too */
6063 void resolve_global_syms(void)
6065 Sym *s, *s1, *ext_sym;
6066 Reloc **p;
6068 s = global_stack.top;
6069 while (s != NULL) {
6070 s1 = s->prev;
6071 /* do not save static or typedefed symbols or types */
6072 if (!(s->t & (VT_STATIC | VT_TYPEDEF)) &&
6073 !(s->v & (SYM_FIELD | SYM_STRUCT)) &&
6074 (s->v < SYM_FIRST_ANOM)) {
6075 ext_sym = sym_find1(&extern_stack, s->v);
6076 if (!ext_sym) {
6077 /* if the symbol do not exist, we simply save it */
6078 ext_sym = sym_push1(&extern_stack, s->v, s->t, s->c);
6079 ext_sym->r = s->r;
6080 } else if (ext_sym->r & VT_FORWARD) {
6081 /* external symbol already exists, but only as forward
6082 definition */
6083 if (!(s->r & VT_FORWARD)) {
6084 /* s is not forward, so we can relocate all symbols */
6085 greloc_patch(ext_sym, s->c);
6086 } else {
6087 /* the two symbols are forward: merge them */
6088 p = (Reloc **)&ext_sym->c;
6089 while (*p != NULL)
6090 p = &(*p)->next;
6091 *p = (Reloc *)s->c;
6093 } else {
6094 /* external symbol already exists and is defined :
6095 patch all references to it */
6096 if (!(s->r & VT_FORWARD))
6097 error("'%s' defined twice", get_tok_str(s->v, NULL));
6098 greloc_patch(s, ext_sym->c);
6101 s = s1;
6105 /* compile the C file opened in 'file'. Return non zero if errors. */
6106 int tcc_compile(TCCState *s)
6108 Sym *define_start;
6109 char buf[512];
6111 funcname = "";
6112 include_stack_ptr = include_stack;
6113 ifdef_stack_ptr = ifdef_stack;
6115 vtop = vstack - 1;
6116 anon_sym = SYM_FIRST_ANOM;
6118 /* file info: full path + filename */
6119 if (do_debug) {
6120 getcwd(buf, sizeof(buf));
6121 pstrcat(buf, sizeof(buf), "/");
6122 put_stabs(buf, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
6123 put_stabs(file->filename, N_SO, 0, 0,
6124 (unsigned long)text_section->data_ptr);
6126 /* define common 'char *' type because it is often used internally
6127 for arrays and struct dereference */
6128 char_pointer_type = mk_pointer(VT_BYTE);
6130 define_start = define_stack.top;
6131 inp();
6132 ch = '\n'; /* needed to parse correctly first preprocessor command */
6133 next();
6134 decl(VT_CONST);
6135 if (tok != -1)
6136 expect("declaration");
6138 /* end of translation unit info */
6139 if (do_debug) {
6140 put_stabn(N_SO, 0, 0, (unsigned long)text_section->data_ptr);
6143 /* reset define stack, but leave -Dsymbols (may be incorrect if
6144 they are undefined) */
6145 sym_pop(&define_stack, define_start);
6147 resolve_global_syms();
6149 sym_pop(&global_stack, NULL);
6151 return 0;
6154 int tcc_compile_file(TCCState *s, const char *filename1)
6156 int ret;
6157 file = tcc_open(filename1);
6158 if (!file)
6159 error("file '%s' not found", filename1);
6160 ret = tcc_compile(s);
6161 tcc_close(file);
6162 return ret;
6165 int tcc_compile_string(TCCState *s, const char *str)
6167 BufferedFile bf1, *bf = &bf1;
6168 int ret;
6170 /* init file structure */
6171 bf->fd = -1;
6172 bf->buf_ptr = (char *)str;
6173 bf->buf_end = (char *)str + strlen(bf->buffer);
6174 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
6175 bf->line_num = 1;
6176 file = bf;
6178 ret = tcc_compile(s);
6180 /* currently, no need to close */
6181 return ret;
6184 /* define a symbol. A value can also be provided with the '=' operator */
6185 void tcc_define_symbol(TCCState *s, const char *sym, const char *value)
6187 BufferedFile bf1, *bf = &bf1;
6189 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
6190 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
6191 /* default value */
6192 if (!value)
6193 value = "1";
6194 pstrcat(bf->buffer, IO_BUF_SIZE, value);
6196 /* init file structure */
6197 bf->fd = -1;
6198 bf->buf_ptr = bf->buffer;
6199 bf->buf_end = bf->buffer + strlen(bf->buffer);
6200 bf->filename[0] = '\0';
6201 bf->line_num = 1;
6202 file = bf;
6204 include_stack_ptr = include_stack;
6206 /* parse with define parser */
6207 inp();
6208 ch = '\n'; /* needed to parse correctly first preprocessor command */
6209 next_nomacro();
6210 parse_define();
6211 file = NULL;
6214 void tcc_undefine_symbol(TCCState *s1, const char *sym)
6216 TokenSym *ts;
6217 Sym *s;
6218 ts = tok_alloc(sym, 0);
6219 s = sym_find1(&define_stack, tok);
6220 /* undefine symbol by putting an invalid name */
6221 if (s)
6222 sym_undef(&define_stack, s);
6225 /* open a dynamic library so that its symbol are available for
6226 compiled programs */
6227 /* XXX: open the lib only to actually run the program */
6228 int tcc_add_dll(TCCState *s, const char *library_name)
6230 void *h;
6232 h = dlopen(library_name, RTLD_GLOBAL | RTLD_LAZY);
6233 if (!h)
6234 error((char *)dlerror());
6235 return 0;
6238 /* If the symbol already exists, then it is redefined */
6239 int tcc_add_symbol(TCCState *s, const char *name, void *value)
6241 TokenSym *ts;
6242 Sym *ext_sym;
6243 int v;
6245 ts = tok_alloc(name, 0);
6246 v = ts->tok;
6247 ext_sym = sym_find1(&extern_stack, v);
6248 if (ext_sym) {
6249 if (ext_sym->r & VT_FORWARD) {
6250 greloc_patch(ext_sym, (long)value);
6251 } else {
6252 /* redefine symbol */
6253 ext_sym->c = (long)value;
6255 } else {
6256 ext_sym = sym_push1(&extern_stack, v, VT_INT, (long)value);
6257 ext_sym->r = VT_CONST;
6259 return 0;
6262 static void *resolve_sym(const char *sym)
6264 #ifdef CONFIG_TCC_BCHECK
6265 if (do_bounds_check) {
6266 void *ptr;
6267 ptr = bound_resolve_sym(sym);
6268 if (ptr)
6269 return ptr;
6271 #endif
6272 return dlsym(NULL, sym);
6275 void resolve_extern_syms(void)
6277 Sym *s, *s1;
6278 char *str;
6279 int addr;
6281 s = extern_stack.top;
6282 while (s != NULL) {
6283 s1 = s->prev;
6284 if (s->r & VT_FORWARD) {
6285 /* if there is at least one relocation to do, then find it
6286 and patch it */
6287 if (s->c) {
6288 str = get_tok_str(s->v, NULL);
6289 addr = (int)resolve_sym(str);
6290 if (!addr)
6291 error("unresolved external reference '%s'", str);
6292 greloc_patch(s, addr);
6295 s = s1;
6299 static int put_elf_str(Section *s, const char *sym)
6301 int c, offset;
6302 offset = s->data_ptr - s->data;
6303 for(;;) {
6304 c = *sym++;
6305 *s->data_ptr++ = c;
6306 if (c == '\0')
6307 break;
6309 return offset;
6312 static void put_elf_sym(Section *s,
6313 unsigned long value, unsigned long size,
6314 int info, int other, int shndx, const char *name)
6316 int name_offset;
6317 Elf32_Sym *sym;
6319 sym = (Elf32_Sym *)s->data_ptr;
6320 if (name)
6321 name_offset = put_elf_str(s->link, name);
6322 else
6323 name_offset = 0;
6324 sym->st_name = name_offset;
6325 sym->st_value = value;
6326 sym->st_size = size;
6327 sym->st_info = info;
6328 sym->st_other = other;
6329 sym->st_shndx = shndx;
6330 s->data_ptr += sizeof(Elf32_Sym);
6333 /* put stab debug information */
6335 typedef struct {
6336 unsigned long n_strx; /* index into string table of name */
6337 unsigned char n_type; /* type of symbol */
6338 unsigned char n_other; /* misc info (usually empty) */
6339 unsigned short n_desc; /* description field */
6340 unsigned long n_value; /* value of symbol */
6341 } Stab_Sym;
6343 static void put_stabs(const char *str, int type, int other, int desc, int value)
6345 Stab_Sym *sym;
6347 sym = (Stab_Sym *)stab_section->data_ptr;
6348 if (str) {
6349 sym->n_strx = put_elf_str(stabstr_section, str);
6350 } else {
6351 sym->n_strx = 0;
6353 sym->n_type = type;
6354 sym->n_other = other;
6355 sym->n_desc = desc;
6356 sym->n_value = value;
6358 stab_section->data_ptr += sizeof(Stab_Sym);
6361 static void put_stabn(int type, int other, int desc, int value)
6363 put_stabs(NULL, type, other, desc, value);
6366 static void put_stabd(int type, int other, int desc)
6368 put_stabs(NULL, type, other, desc, 0);
6371 /* output an ELF file (currently, only for testing) */
6372 /* XXX: generate dynamic reloc info + DLL tables */
6373 /* XXX: generate startup code */
6374 /* XXX: better program header generation */
6375 /* XXX: handle realloc'ed sections (instead of mmaping them) */
6376 int tcc_output_file(TCCState *s, const char *filename, int file_type)
6378 Elf32_Ehdr ehdr;
6379 FILE *f;
6380 int shnum, i, phnum, file_offset, offset, size, j;
6381 Section *sec, *strsec;
6382 Elf32_Shdr *shdr, *sh;
6383 Elf32_Phdr *phdr, *ph;
6385 memset(&ehdr, 0, sizeof(ehdr));
6387 /* we add a section for symbols */
6388 strsec = new_section(".shstrtab", SHT_STRTAB, 0);
6389 put_elf_str(strsec, "");
6391 /* count number of sections and compute number of program segments */
6392 shnum = 1; /* section index zero is reserved */
6393 phnum = 0;
6394 for(sec = first_section; sec != NULL; sec = sec->next) {
6395 shnum++;
6396 if (sec->sh_flags & SHF_ALLOC)
6397 phnum++;
6399 /* allocate section headers */
6400 shdr = malloc(shnum * sizeof(Elf32_Shdr));
6401 if (!shdr)
6402 error("memory full");
6403 memset(shdr, 0, shnum * sizeof(Elf32_Shdr));
6404 /* allocate program segment headers */
6405 phdr = malloc(phnum * sizeof(Elf32_Phdr));
6406 if (!phdr)
6407 error("memory full");
6408 memset(phdr, 0, phnum * sizeof(Elf32_Phdr));
6410 /* XXX: find correct load order */
6411 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
6412 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
6413 sh = &shdr[i];
6414 sh->sh_name = put_elf_str(strsec, sec->name);
6415 sh->sh_type = sec->sh_type;
6416 sh->sh_flags = sec->sh_flags;
6417 sh->sh_entsize = sec->sh_entsize;
6418 if (sec->link)
6419 sh->sh_link = sec->link->sh_num;
6420 if (sh->sh_type == SHT_STRTAB) {
6421 sh->sh_addralign = 1;
6422 } else if (sh->sh_type == SHT_SYMTAB ||
6423 (sh->sh_flags & SHF_ALLOC) == 0) {
6424 sh->sh_addralign = 4;
6425 } else {
6426 sh->sh_addr = (Elf32_Word)sec->data;
6427 sh->sh_addralign = 4096;
6429 sh->sh_size = (Elf32_Word)sec->data_ptr - (Elf32_Word)sec->data;
6430 /* align to section start */
6431 file_offset = (file_offset + sh->sh_addralign - 1) &
6432 ~(sh->sh_addralign - 1);
6433 sh->sh_offset = file_offset;
6434 file_offset += sh->sh_size;
6436 /* build program headers (simplistic - not fully correct) */
6437 j = 0;
6438 for(i=1;i<shnum;i++) {
6439 sh = &shdr[i];
6440 if (sh->sh_type == SHT_PROGBITS &&
6441 (sh->sh_flags & SHF_ALLOC) != 0) {
6442 ph = &phdr[j++];
6443 ph->p_type = PT_LOAD;
6444 ph->p_offset = sh->sh_offset;
6445 ph->p_vaddr = sh->sh_addr;
6446 ph->p_paddr = ph->p_vaddr;
6447 ph->p_filesz = sh->sh_size;
6448 ph->p_memsz = sh->sh_size;
6449 ph->p_flags = PF_R;
6450 if (sh->sh_flags & SHF_WRITE)
6451 ph->p_flags |= PF_W;
6452 if (sh->sh_flags & SHF_EXECINSTR)
6453 ph->p_flags |= PF_X;
6454 ph->p_align = sh->sh_addralign;
6458 /* align to 4 */
6459 file_offset = (file_offset + 3) & -4;
6461 /* fill header */
6462 ehdr.e_ident[0] = ELFMAG0;
6463 ehdr.e_ident[1] = ELFMAG1;
6464 ehdr.e_ident[2] = ELFMAG2;
6465 ehdr.e_ident[3] = ELFMAG3;
6466 ehdr.e_ident[4] = ELFCLASS32;
6467 ehdr.e_ident[5] = ELFDATA2LSB;
6468 ehdr.e_ident[6] = EV_CURRENT;
6469 ehdr.e_type = ET_EXEC;
6470 ehdr.e_machine = EM_386;
6471 ehdr.e_version = EV_CURRENT;
6472 ehdr.e_entry = 0; /* XXX: patch it */
6473 ehdr.e_phoff = sizeof(Elf32_Ehdr);
6474 ehdr.e_shoff = file_offset;
6475 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
6476 ehdr.e_phentsize = sizeof(Elf32_Phdr);
6477 ehdr.e_phnum = phnum;
6478 ehdr.e_shentsize = sizeof(Elf32_Shdr);
6479 ehdr.e_shnum = shnum;
6480 ehdr.e_shstrndx = shnum - 1;
6482 /* write elf file */
6483 f = fopen(filename, "w");
6484 if (!f)
6485 error("could not write '%s'", filename);
6486 fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
6487 fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
6488 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
6489 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
6490 sh = &shdr[i];
6491 while (offset < sh->sh_offset) {
6492 fputc(0, f);
6493 offset++;
6495 size = sec->data_ptr - sec->data;
6496 fwrite(sec->data, 1, size, f);
6497 offset += size;
6499 while (offset < ehdr.e_shoff) {
6500 fputc(0, f);
6501 offset++;
6503 fwrite(shdr, 1, shnum * sizeof(Elf32_Shdr), f);
6504 fclose(f);
6505 return 0;
6508 /* print the position in the source file of PC value 'pc' by reading
6509 the stabs debug information */
6510 static void rt_printline(unsigned long wanted_pc)
6512 Stab_Sym *sym, *sym_end;
6513 char func_name[128];
6514 unsigned long func_addr, last_pc, pc;
6515 const char *incl_files[INCLUDE_STACK_SIZE];
6516 int incl_index, len, last_line_num, i;
6517 const char *str, *p;
6519 func_name[0] = '\0';
6520 func_addr = 0;
6521 incl_index = 0;
6522 last_pc = 0xffffffff;
6523 last_line_num = 1;
6524 sym = (Stab_Sym *)stab_section->data + 1;
6525 sym_end = (Stab_Sym *)stab_section->data_ptr;
6526 while (sym < sym_end) {
6527 switch(sym->n_type) {
6528 /* function start or end */
6529 case N_FUN:
6530 if (sym->n_strx == 0) {
6531 func_name[0] = '\0';
6532 func_addr = 0;
6533 } else {
6534 str = stabstr_section->data + sym->n_strx;
6535 p = strchr(str, ':');
6536 if (!p) {
6537 pstrcpy(func_name, sizeof(func_name), str);
6538 } else {
6539 len = p - str;
6540 if (len > sizeof(func_name) - 1)
6541 len = sizeof(func_name) - 1;
6542 memcpy(func_name, str, len);
6543 func_name[len] = '\0';
6545 func_addr = sym->n_value;
6547 break;
6548 /* line number info */
6549 case N_SLINE:
6550 pc = sym->n_value + func_addr;
6551 if (wanted_pc >= last_pc && wanted_pc < pc)
6552 goto found;
6553 last_pc = pc;
6554 last_line_num = sym->n_desc;
6555 break;
6556 /* include files */
6557 case N_BINCL:
6558 str = stabstr_section->data + sym->n_strx;
6559 add_incl:
6560 if (incl_index < INCLUDE_STACK_SIZE) {
6561 incl_files[incl_index++] = str;
6563 break;
6564 case N_EINCL:
6565 if (incl_index > 1)
6566 incl_index--;
6567 break;
6568 case N_SO:
6569 if (sym->n_strx == 0) {
6570 incl_index = 0; /* end of translation unit */
6571 } else {
6572 str = stabstr_section->data + sym->n_strx;
6573 /* do not add path */
6574 len = strlen(str);
6575 if (len > 0 && str[len - 1] != '/')
6576 goto add_incl;
6578 break;
6580 sym++;
6582 /* did not find line number info: */
6583 fprintf(stderr, "(no debug info, pc=0x%08lx): ", wanted_pc);
6584 return;
6585 found:
6586 for(i = 0; i < incl_index - 1; i++)
6587 fprintf(stderr, "In file included from %s\n",
6588 incl_files[i]);
6589 if (incl_index > 0) {
6590 fprintf(stderr, "%s:%d: ",
6591 incl_files[incl_index - 1], last_line_num);
6593 if (func_name[0] != '\0') {
6594 fprintf(stderr, "in function '%s()': ", func_name);
6598 /* emit a run time error at position 'pc' */
6599 void rt_error(unsigned long pc, const char *fmt, ...)
6601 va_list ap;
6602 va_start(ap, fmt);
6604 rt_printline(pc);
6605 vfprintf(stderr, fmt, ap);
6606 fprintf(stderr, "\n");
6607 exit(255);
6608 va_end(ap);
6611 #ifndef WIN32
6612 /* signal handler for fatal errors */
6613 static void sig_error(int signum, siginfo_t *siginf, void *puc)
6615 struct ucontext *uc = puc;
6616 unsigned long pc;
6618 #ifdef __i386__
6619 pc = uc->uc_mcontext.gregs[14];
6620 #else
6621 #error please put the right sigcontext field
6622 #endif
6624 switch(signum) {
6625 case SIGFPE:
6626 switch(siginf->si_code) {
6627 case FPE_INTDIV:
6628 case FPE_FLTDIV:
6629 rt_error(pc, "division by zero");
6630 break;
6631 default:
6632 rt_error(pc, "floating point exception");
6633 break;
6635 break;
6636 case SIGBUS:
6637 case SIGSEGV:
6638 rt_error(pc, "dereferencing invalid pointer");
6639 break;
6640 case SIGILL:
6641 rt_error(pc, "illegal instruction");
6642 break;
6643 case SIGABRT:
6644 rt_error(pc, "abort() called");
6645 break;
6646 default:
6647 rt_error(pc, "caught signal %d", signum);
6648 break;
6650 exit(255);
6652 #endif
6654 /* launch the compiled program with the given arguments */
6655 int tcc_run(TCCState *s1, int argc, char **argv)
6657 Sym *s;
6658 int (*t)();
6660 resolve_extern_syms();
6662 s = sym_find1(&extern_stack, TOK_MAIN);
6663 if (!s || (s->r & VT_FORWARD))
6664 error("main() not defined");
6666 if (do_debug) {
6667 #ifdef WIN32
6668 error("debug mode currently not available for Windows");
6669 #else
6670 struct sigaction sigact;
6671 /* install TCC signal handlers to print debug info on fatal
6672 runtime errors */
6673 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
6674 sigact.sa_sigaction = sig_error;
6675 sigemptyset(&sigact.sa_mask);
6676 sigaction(SIGFPE, &sigact, NULL);
6677 sigaction(SIGILL, &sigact, NULL);
6678 sigaction(SIGSEGV, &sigact, NULL);
6679 sigaction(SIGBUS, &sigact, NULL);
6680 sigaction(SIGABRT, &sigact, NULL);
6681 #endif
6684 #ifdef CONFIG_TCC_BCHECK
6685 if (do_bounds_check) {
6686 int *p, *p_end;
6687 __bound_init();
6688 /* add all known static regions */
6689 p = (int *)bounds_section->data;
6690 p_end = (int *)bounds_section->data_ptr;
6691 while (p < p_end) {
6692 __bound_new_region((void *)p[0], p[1]);
6693 p += 2;
6696 #endif
6698 t = (int (*)())s->c;
6699 return (*t)(argc, argv);
6702 TCCState *tcc_new(void)
6704 char *p, *r;
6705 TCCState *s;
6707 s = malloc(sizeof(TCCState));
6708 if (!s)
6709 return NULL;
6711 /* default include paths */
6712 nb_include_paths = 0;
6713 tcc_add_include_path(s, "/usr/include");
6714 tcc_add_include_path(s, CONFIG_TCC_PREFIX "/lib/tcc/include");
6716 /* add all tokens */
6717 tok_ident = TOK_IDENT;
6718 p = tcc_keywords;
6719 while (*p) {
6720 r = p;
6721 while (*r++);
6722 tok_alloc(p, r - p - 1);
6723 p = r;
6726 /* standard defines */
6727 tcc_define_symbol(s, "__STDC__", NULL);
6728 #ifdef __i386__
6729 tcc_define_symbol(s, "__i386__", NULL);
6730 #endif
6731 /* tiny C specific defines */
6732 tcc_define_symbol(s, "__TINYC__", NULL);
6734 /* create standard sections */
6735 text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
6736 data_section = new_section(".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6737 /* XXX: should change type to SHT_NOBITS */
6738 bss_section = new_section(".bss", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6740 return s;
6743 void tcc_delete(TCCState *s)
6745 free(s);
6748 int tcc_add_include_path(TCCState *s, const char *pathname)
6750 char *pathname1;
6752 if (nb_include_paths >= INCLUDE_PATHS_MAX)
6753 return -1;
6754 pathname1 = strdup(pathname);
6755 if (!pathname1)
6756 return -1;
6757 include_paths[nb_include_paths++] = pathname1;
6758 return 0;
6761 #if !defined(LIBTCC)
6763 void help(void)
6765 printf("tcc version 0.9.8 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
6766 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
6767 " [-i infile] infile [infile_args...]\n"
6768 "\n"
6769 "-Idir : add include path 'dir'\n"
6770 "-Dsym[=val] : define 'sym' with value 'val'\n"
6771 "-Usym : undefine 'sym'\n"
6772 "-llib : link with dynamic library 'lib'\n"
6773 "-g : generate runtime debug info\n"
6774 #ifdef CONFIG_TCC_BCHECK
6775 "-b : compile with built-in memory and bounds checker (implies -g)\n"
6776 #endif
6777 "-i infile : compile infile\n"
6781 int main(int argc, char **argv)
6783 char *r, *outfile;
6784 int optind;
6785 TCCState *s;
6787 s = tcc_new();
6789 optind = 1;
6790 outfile = NULL;
6791 while (1) {
6792 if (optind >= argc) {
6793 show_help:
6794 help();
6795 return 1;
6797 r = argv[optind];
6798 if (r[0] != '-')
6799 break;
6800 optind++;
6801 if (r[1] == 'I') {
6802 if (tcc_add_include_path(s, r + 2) < 0)
6803 error("too many include paths");
6804 } else if (r[1] == 'D') {
6805 char *sym, *value;
6806 sym = r + 2;
6807 value = strchr(sym, '=');
6808 if (value) {
6809 *value = '\0';
6810 value++;
6812 tcc_define_symbol(s, sym, value);
6813 } else if (r[1] == 'U') {
6814 tcc_undefine_symbol(s, r + 2);
6815 } else if (r[1] == 'l') {
6816 char buf[1024];
6817 snprintf(buf, sizeof(buf), "lib%s.so", r + 2);
6818 tcc_add_dll(s, buf);
6819 } else if (r[1] == 'i') {
6820 if (optind >= argc)
6821 goto show_help;
6822 tcc_compile_file(s, argv[optind++]);
6823 } else if (!strcmp(r + 1, "bench")) {
6824 do_bench = 1;
6825 #ifdef CONFIG_TCC_BCHECK
6826 } else if (r[1] == 'b') {
6827 if (!do_bounds_check) {
6828 do_bounds_check = 1;
6829 /* define symbol */
6830 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
6831 /* create bounds sections */
6832 bounds_section = new_section(".bounds",
6833 SHT_PROGBITS, SHF_ALLOC);
6834 lbounds_section = new_section(".lbounds",
6835 SHT_PROGBITS, SHF_ALLOC);
6836 /* debug is implied */
6837 goto debug_opt;
6839 #endif
6840 } else if (r[1] == 'g') {
6841 #ifdef CONFIG_TCC_BCHECK
6842 debug_opt:
6843 #endif
6844 if (!do_debug) {
6845 do_debug = 1;
6847 /* stab symbols */
6848 stab_section = new_section(".stab", SHT_PROGBITS, 0);
6849 stab_section->sh_entsize = sizeof(Stab_Sym);
6850 stabstr_section = new_section(".stabstr", SHT_STRTAB, 0);
6851 put_elf_str(stabstr_section, "");
6852 stab_section->link = stabstr_section;
6853 /* put first entry */
6854 put_stabs("", 0, 0, 0, 0);
6856 /* elf symbols */
6857 symtab_section = new_section(".symtab", SHT_SYMTAB, 0);
6858 symtab_section->sh_entsize = sizeof(Elf32_Sym);
6859 strtab_section = new_section(".strtab", SHT_STRTAB, 0);
6860 put_elf_str(strtab_section, "");
6861 symtab_section->link = strtab_section;
6862 put_elf_sym(symtab_section, 0, 0, 0, 0, 0, NULL);
6864 } else if (r[1] == 'o') {
6865 /* currently, only for testing, so not documented */
6866 if (optind >= argc)
6867 goto show_help;
6868 outfile = argv[optind++];
6869 } else {
6870 error("invalid option -- '%s'", r);
6874 tcc_compile_file(s, argv[optind]);
6876 if (do_bench) {
6877 printf("total: %d idents, %d lines, %d bytes\n",
6878 tok_ident - TOK_IDENT, total_lines, total_bytes);
6881 if (outfile) {
6882 tcc_output_file(s, outfile, TCC_FILE_EXE);
6883 return 0;
6884 } else {
6885 return tcc_run(s, argc - optind, argv + optind);
6889 #endif