restored include file optimization - added static on all globals
[tinycc/miki.git] / tcc.c
blobbf847954f3af23f9d73dd9999b6bf9bc7e10a943
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 <unistd.h>
29 #include <fcntl.h>
30 #include <setjmp.h>
31 #ifdef WIN32
32 #include <sys/timeb.h>
33 #endif
34 #ifndef WIN32
35 #include <sys/time.h>
36 #include <sys/ucontext.h>
37 #endif
38 #include "elf.h"
39 #include "stab.h"
40 #ifndef CONFIG_TCC_STATIC
41 #include <dlfcn.h>
42 #endif
44 #include "libtcc.h"
46 /* parser debug */
47 //#define PARSE_DEBUG
48 /* preprocessor debug */
49 //#define PP_DEBUG
50 /* include file debug */
51 //#define INC_DEBUG
53 //#define MEM_DEBUG
55 /* target selection */
56 //#define TCC_TARGET_I386 /* i386 code generator */
57 //#define TCC_TARGET_IL /* .NET CLI generator */
59 /* default target is I386 */
60 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_IL)
61 #define TCC_TARGET_I386
62 #endif
64 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_IL)
65 #define CONFIG_TCC_BCHECK /* enable bound checking code */
66 #endif
68 #ifndef CONFIG_TCC_PREFIX
69 #define CONFIG_TCC_PREFIX "/usr/local"
70 #endif
72 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
73 executables or dlls */
74 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
76 #define INCLUDE_STACK_SIZE 32
77 #define IFDEF_STACK_SIZE 64
78 #define VSTACK_SIZE 64
79 #define STRING_MAX_SIZE 1024
81 #define TOK_HASH_SIZE 2048 /* must be a power of two */
82 #define TOK_ALLOC_INCR 512 /* must be a power of two */
84 /* token symbol management */
85 typedef struct TokenSym {
86 struct TokenSym *hash_next;
87 struct Sym *sym_define; /* direct pointer to define */
88 struct Sym *sym_label; /* direct pointer to label */
89 struct Sym *sym_struct; /* direct pointer to structure */
90 struct Sym *sym_identifier; /* direct pointer to identifier */
91 int tok; /* token number */
92 int len;
93 char str[1];
94 } TokenSym;
96 typedef struct CString {
97 int size; /* size in bytes */
98 void *data; /* either 'char *' or 'int *' */
99 int size_allocated;
100 void *data_allocated; /* if non NULL, data has been malloced */
101 } CString;
103 /* type definition */
104 typedef struct CType {
105 int t;
106 struct Sym *ref;
107 } CType;
109 /* constant value */
110 typedef union CValue {
111 long double ld;
112 double d;
113 float f;
114 int i;
115 unsigned int ui;
116 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
117 long long ll;
118 unsigned long long ull;
119 struct CString *cstr;
120 void *ptr;
121 int tab[1];
122 } CValue;
124 /* value on stack */
125 typedef struct SValue {
126 CType type; /* type */
127 unsigned short r; /* register + flags */
128 unsigned short r2; /* second register, used for 'long long'
129 type. If not used, set to VT_CONST */
130 CValue c; /* constant, if VT_CONST */
131 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
132 } SValue;
134 /* symbol management */
135 typedef struct Sym {
136 int v; /* symbol token */
137 int r; /* associated register */
138 int c; /* associated number */
139 CType type; /* associated type */
140 struct Sym *next; /* next related symbol */
141 struct Sym *prev; /* prev symbol in stack */
142 struct Sym *prev_tok; /* previous symbol for this token */
143 } Sym;
145 /* section definition */
146 /* XXX: use directly ELF structure for parameters ? */
147 /* special flag to indicate that the section should not be linked to
148 the other ones */
149 #define SHF_PRIVATE 0x80000000
151 typedef struct Section {
152 unsigned long data_offset; /* current data offset */
153 unsigned char *data; /* section data */
154 unsigned long data_allocated; /* used for realloc() handling */
155 int sh_name; /* elf section name (only used during output) */
156 int sh_num; /* elf section number */
157 int sh_type; /* elf section type */
158 int sh_flags; /* elf section flags */
159 int sh_info; /* elf section info */
160 int sh_addralign; /* elf section alignment */
161 int sh_entsize; /* elf entry size */
162 unsigned long sh_size; /* section size (only used during output) */
163 unsigned long sh_addr; /* address at which the section is relocated */
164 unsigned long sh_offset; /* address at which the section is relocated */
165 int nb_hashed_syms; /* used to resize the hash table */
166 struct Section *link; /* link to another section */
167 struct Section *reloc; /* corresponding section for relocation, if any */
168 struct Section *hash; /* hash table for symbols */
169 struct Section *next;
170 char name[64]; /* section name */
171 } Section;
173 typedef struct DLLReference {
174 int level;
175 char name[1];
176 } DLLReference;
178 /* GNUC attribute definition */
179 typedef struct AttributeDef {
180 int aligned;
181 Section *section;
182 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
183 } AttributeDef;
185 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
186 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
187 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
189 /* stored in 'Sym.c' field */
190 #define FUNC_NEW 1 /* ansi function prototype */
191 #define FUNC_OLD 2 /* old function prototype */
192 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
194 /* stored in 'Sym.r' field */
195 #define FUNC_CDECL 0 /* standard c call */
196 #define FUNC_STDCALL 1 /* pascal c call */
198 /* field 'Sym.t' for macros */
199 #define MACRO_OBJ 0 /* object like macro */
200 #define MACRO_FUNC 1 /* function like macro */
202 /* field 'Sym.r' for labels */
203 #define LABEL_FORWARD 1 /* label is forward defined */
205 /* type_decl() types */
206 #define TYPE_ABSTRACT 1 /* type without variable */
207 #define TYPE_DIRECT 2 /* type with variable */
209 #define IO_BUF_SIZE 8192
211 typedef struct BufferedFile {
212 unsigned char *buf_ptr;
213 unsigned char *buf_end;
214 int fd;
215 int line_num; /* current line number - here to simply code */
216 int ifndef_macro; /* #ifndef macro / #endif search */
217 int ifndef_macro_saved; /* saved ifndef_macro */
218 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
219 char inc_type; /* type of include */
220 char inc_filename[512]; /* filename specified by the user */
221 char filename[1024]; /* current filename - here to simplify code */
222 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
223 } BufferedFile;
225 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
226 #define CH_EOF (-1) /* end of file */
228 /* parsing state (used to save parser state to reparse part of the
229 source several times) */
230 typedef struct ParseState {
231 int *macro_ptr;
232 int line_num;
233 int tok;
234 CValue tokc;
235 } ParseState;
237 /* used to record tokens */
238 typedef struct TokenString {
239 int *str;
240 int len;
241 int last_line_num;
242 } TokenString;
244 /* include file cache, used to find files faster and also to eliminate
245 inclusion if the include file is protected by #ifndef ... #endif */
246 typedef struct CachedInclude {
247 int ifndef_macro;
248 char type; /* '"' or '>' to give include type */
249 char filename[1]; /* path specified in #include */
250 } CachedInclude;
252 /* parser */
253 static struct BufferedFile *file;
254 static int ch, tok, tok1;
255 static CValue tokc, tok1c;
256 static CString tokcstr; /* current parsed string, if any */
257 /* additionnal informations about token */
258 static int tok_flags;
259 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
260 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
261 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
263 /* if true, line feed is returned as a token. line feed is also
264 returned at eof */
265 static int return_linefeed;
266 static Section *text_section, *data_section, *bss_section; /* predefined sections */
267 static Section *cur_text_section; /* current section where function code is
268 generated */
269 /* bound check related sections */
270 static Section *bounds_section; /* contains global data bound description */
271 static Section *lbounds_section; /* contains local data bound description */
272 /* symbol sections */
273 static Section *symtab_section, *strtab_section;
275 /* debug sections */
276 static Section *stab_section, *stabstr_section;
278 /* loc : local variable index
279 ind : output code index
280 rsym: return symbol
281 anon_sym: anonymous symbol index
283 static int rsym, anon_sym, ind, loc;
284 /* expression generation modifiers */
285 static int const_wanted; /* true if constant wanted */
286 static int nocode_wanted; /* true if no code generation wanted for an expression */
287 static int global_expr; /* true if compound literals must be allocated
288 globally (used during initializers parsing */
289 static CType func_vt; /* current function return type (used by return
290 instruction) */
291 static int func_vc;
292 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
293 static int tok_ident;
294 static TokenSym **table_ident;
295 static TokenSym *hash_ident[TOK_HASH_SIZE];
296 static char token_buf[STRING_MAX_SIZE + 1];
297 static char *funcname;
298 static Sym *global_stack, *local_stack;
299 static Sym *define_stack;
300 static Sym *label_stack;
302 static SValue vstack[VSTACK_SIZE], *vtop;
303 static int *macro_ptr, *macro_ptr_allocated;
304 /* some predefined types */
305 static CType char_pointer_type, func_old_type, int_type;
307 /* compile with debug symbol (and use them if error during execution) */
308 static int do_debug = 0;
310 /* compile with built-in memory and bounds checker */
311 static int do_bounds_check = 0;
313 /* display benchmark infos */
314 static int do_bench = 0;
315 static int total_lines;
316 static int total_bytes;
318 /* use GNU C extensions */
319 static int gnu_ext = 1;
321 /* use Tiny C extensions */
322 static int tcc_ext = 1;
324 /* max number of callers shown if error */
325 static int num_callers = 6;
326 static const char **rt_bound_error_msg;
328 /* XXX: suppress that ASAP */
329 static struct TCCState *tcc_state;
331 /* give the path of the tcc libraries */
332 static const char *tcc_lib_path = CONFIG_TCC_PREFIX "/lib/tcc";
334 struct TCCState {
335 int output_type;
337 BufferedFile **include_stack_ptr;
338 int *ifdef_stack_ptr;
340 /* include file handling */
341 char **include_paths;
342 int nb_include_paths;
343 char **sysinclude_paths;
344 int nb_sysinclude_paths;
345 CachedInclude **cached_includes;
346 int nb_cached_includes;
348 char **library_paths;
349 int nb_library_paths;
351 /* array of all loaded dlls (including those referenced by loaded
352 dlls) */
353 DLLReference **loaded_dlls;
354 int nb_loaded_dlls;
356 /* sections */
357 Section **sections;
358 int nb_sections; /* number of sections, including first dummy section */
360 /* got handling */
361 Section *got;
362 unsigned long *got_offsets;
363 int nb_got_offsets;
364 int nb_plt_entries;
365 /* give the correspondance from symtab indexes to dynsym indexes */
366 int *symtab_to_dynsym;
368 /* temporary dynamic symbol sections (for dll loading) */
369 Section *dynsymtab_section;
370 /* exported dynamic symbol section */
371 Section *dynsym;
373 /* if true, static linking is performed */
374 int static_link;
376 /* error handling */
377 void *error_opaque;
378 void (*error_func)(void *opaque, const char *msg);
379 int error_set_jmp_enabled;
380 jmp_buf error_jmp_buf;
381 int nb_errors;
383 /* see include_stack_ptr */
384 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
386 /* see ifdef_stack_ptr */
387 int ifdef_stack[IFDEF_STACK_SIZE];
390 /* The current value can be: */
391 #define VT_VALMASK 0x00ff
392 #define VT_CONST 0x00f0 /* constant in vc
393 (must be first non register value) */
394 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
395 #define VT_LOCAL 0x00f2 /* offset on stack */
396 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
397 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
398 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
399 #define VT_LVAL 0x0100 /* var is an lvalue */
400 #define VT_SYM 0x0200 /* a symbol value is added */
401 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
402 char/short stored in integer registers) */
403 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
404 dereferencing value */
405 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
406 bounding function call point is in vc */
407 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
408 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
409 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
410 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
412 /* types */
413 #define VT_STRUCT_SHIFT 12 /* structure/enum name shift (20 bits left) */
415 #define VT_INT 0 /* integer type */
416 #define VT_BYTE 1 /* signed byte type */
417 #define VT_SHORT 2 /* short type */
418 #define VT_VOID 3 /* void type */
419 #define VT_PTR 4 /* pointer */
420 #define VT_ENUM 5 /* enum definition */
421 #define VT_FUNC 6 /* function type */
422 #define VT_STRUCT 7 /* struct/union definition */
423 #define VT_FLOAT 8 /* IEEE float */
424 #define VT_DOUBLE 9 /* IEEE double */
425 #define VT_LDOUBLE 10 /* IEEE long double */
426 #define VT_BOOL 11 /* ISOC99 boolean type */
427 #define VT_LLONG 12 /* 64 bit integer */
428 #define VT_LONG 13 /* long integer (NEVER USED as type, only
429 during parsing) */
430 #define VT_BTYPE 0x000f /* mask for basic type */
431 #define VT_UNSIGNED 0x0010 /* unsigned type */
432 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
433 #define VT_BITFIELD 0x0040 /* bitfield modifier */
435 /* storage */
436 #define VT_EXTERN 0x00000080 /* extern definition */
437 #define VT_STATIC 0x00000100 /* static variable */
438 #define VT_TYPEDEF 0x00000200 /* typedef definition */
440 /* type mask (except storage) */
441 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
443 /* token values */
445 /* warning: the following compare tokens depend on i386 asm code */
446 #define TOK_ULT 0x92
447 #define TOK_UGE 0x93
448 #define TOK_EQ 0x94
449 #define TOK_NE 0x95
450 #define TOK_ULE 0x96
451 #define TOK_UGT 0x97
452 #define TOK_LT 0x9c
453 #define TOK_GE 0x9d
454 #define TOK_LE 0x9e
455 #define TOK_GT 0x9f
457 #define TOK_LAND 0xa0
458 #define TOK_LOR 0xa1
460 #define TOK_DEC 0xa2
461 #define TOK_MID 0xa3 /* inc/dec, to void constant */
462 #define TOK_INC 0xa4
463 #define TOK_UDIV 0xb0 /* unsigned division */
464 #define TOK_UMOD 0xb1 /* unsigned modulo */
465 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
466 #define TOK_CINT 0xb3 /* number in tokc */
467 #define TOK_CCHAR 0xb4 /* char constant in tokc */
468 #define TOK_STR 0xb5 /* pointer to string in tokc */
469 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
470 #define TOK_LCHAR 0xb7
471 #define TOK_LSTR 0xb8
472 #define TOK_CFLOAT 0xb9 /* float constant */
473 #define TOK_LINENUM 0xba /* line number info */
474 #define TOK_CDOUBLE 0xc0 /* double constant */
475 #define TOK_CLDOUBLE 0xc1 /* long double constant */
476 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
477 #define TOK_ADDC1 0xc3 /* add with carry generation */
478 #define TOK_ADDC2 0xc4 /* add with carry use */
479 #define TOK_SUBC1 0xc5 /* add with carry generation */
480 #define TOK_SUBC2 0xc6 /* add with carry use */
481 #define TOK_CUINT 0xc8 /* unsigned int constant */
482 #define TOK_CLLONG 0xc9 /* long long constant */
483 #define TOK_CULLONG 0xca /* unsigned long long constant */
484 #define TOK_ARROW 0xcb
485 #define TOK_DOTS 0xcc /* three dots */
486 #define TOK_SHR 0xcd /* unsigned shift right */
487 #define TOK_PPNUM 0xce /* preprocessor number */
489 #define TOK_SHL 0x01 /* shift left */
490 #define TOK_SAR 0x02 /* signed shift right */
492 /* assignement operators : normal operator or 0x80 */
493 #define TOK_A_MOD 0xa5
494 #define TOK_A_AND 0xa6
495 #define TOK_A_MUL 0xaa
496 #define TOK_A_ADD 0xab
497 #define TOK_A_SUB 0xad
498 #define TOK_A_DIV 0xaf
499 #define TOK_A_XOR 0xde
500 #define TOK_A_OR 0xfc
501 #define TOK_A_SHL 0x81
502 #define TOK_A_SAR 0x82
504 /* WARNING: the content of this string encodes token numbers */
505 static char tok_two_chars[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
507 #define TOK_EOF (-1) /* end of file */
508 #define TOK_LINEFEED 10 /* line feed */
510 /* all identificators and strings have token above that */
511 #define TOK_IDENT 256
513 enum {
514 TOK_LAST = TOK_IDENT - 1,
515 #define DEF(id, str) id,
516 #include "tcctok.h"
517 #undef DEF
520 static const char *tcc_keywords =
521 #define DEF(id, str) str "\0"
522 #include "tcctok.h"
523 #undef DEF
526 #define TOK_UIDENT TOK_DEFINE
528 #ifdef WIN32
529 #define snprintf _snprintf
530 #define vsnprintf _vsnprintf
531 #endif
533 #if defined(WIN32) || defined(TCC_UCLIBC)
534 /* currently incorrect */
535 long double strtold(const char *nptr, char **endptr)
537 return (long double)strtod(nptr, endptr);
539 float strtof(const char *nptr, char **endptr)
541 return (float)strtod(nptr, endptr);
543 #else
544 /* XXX: need to define this to use them in non ISOC99 context */
545 extern float strtof (const char *__nptr, char **__endptr);
546 extern long double strtold (const char *__nptr, char **__endptr);
547 #endif
549 static char *pstrcpy(char *buf, int buf_size, const char *s);
550 static char *pstrcat(char *buf, int buf_size, const char *s);
552 static void sum(int l);
553 static void next(void);
554 static void next_nomacro(void);
555 static void parse_expr_type(CType *type);
556 static void expr_type(CType *type);
557 static void unary_type(CType *type);
558 static int expr_const(void);
559 static void expr_eq(void);
560 static void gexpr(void);
561 static void decl(int l);
562 static void decl_initializer(CType *type, Section *sec, unsigned long c,
563 int first, int size_only);
564 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
565 int has_init, int v, int scope);
566 int gv(int rc);
567 void gv2(int rc1, int rc2);
568 void move_reg(int r, int s);
569 void save_regs(int n);
570 void save_reg(int r);
571 void vpop(void);
572 void vswap(void);
573 void vdup(void);
574 int get_reg(int rc);
576 static void macro_subst(TokenString *tok_str,
577 Sym **nested_list, int *macro_str);
578 int save_reg_forced(int r);
579 void gen_op(int op);
580 void force_charshort_cast(int t);
581 static void gen_cast(CType *type);
582 void vstore(void);
583 static Sym *sym_find(int v);
584 static Sym *sym_push(int v, CType *type, int r, int c);
586 /* type handling */
587 int type_size(CType *type, int *a);
588 static inline CType *pointed_type(CType *type);
589 static int pointed_size(CType *type);
590 static int lvalue_type(int t);
591 static int is_compatible_types(CType *type1, CType *type2);
592 static int parse_btype(CType *type, AttributeDef *ad);
593 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
595 void error(const char *fmt, ...);
596 void vpushi(int v);
597 void vset(CType *type, int r, int v);
598 void type_to_str(char *buf, int buf_size,
599 CType *type, const char *varstr);
600 char *get_tok_str(int v, CValue *cv);
601 static Sym *get_sym_ref(CType *type, Section *sec,
602 unsigned long offset, unsigned long size);
603 static Sym *external_global_sym(int v, CType *type, int r);
605 /* section generation */
606 static void section_realloc(Section *sec, unsigned long new_size);
607 static void *section_ptr_add(Section *sec, unsigned long size);
608 static void put_extern_sym(Sym *sym, Section *section,
609 unsigned long value, unsigned long size);
610 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
611 static int put_elf_str(Section *s, const char *sym);
612 static int put_elf_sym(Section *s,
613 unsigned long value, unsigned long size,
614 int info, int other, int shndx, const char *name);
615 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
616 int info, int sh_num, const char *name);
617 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
618 int type, int symbol);
619 static void put_stabs(const char *str, int type, int other, int desc,
620 unsigned long value);
621 static void put_stabs_r(const char *str, int type, int other, int desc,
622 unsigned long value, Section *sec, int sym_index);
623 static void put_stabn(int type, int other, int desc, int value);
624 static void put_stabd(int type, int other, int desc);
625 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
627 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
628 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
629 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
631 /* true if float/double/long double type */
632 static inline int is_float(int t)
634 int bt;
635 bt = t & VT_BTYPE;
636 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
639 #ifdef TCC_TARGET_I386
640 #include "i386-gen.c"
641 #endif
642 #ifdef TCC_TARGET_IL
643 #include "il-gen.c"
644 #endif
646 #ifdef CONFIG_TCC_STATIC
648 #define RTLD_LAZY 0x001
649 #define RTLD_NOW 0x002
650 #define RTLD_GLOBAL 0x100
651 #define RTLD_DEFAULT NULL
653 /* dummy function for profiling */
654 void *dlopen(const char *filename, int flag)
656 return NULL;
659 const char *dlerror(void)
661 return "error";
664 typedef struct TCCSyms {
665 char *str;
666 void *ptr;
667 } TCCSyms;
669 #define TCCSYM(a) { #a, &a, },
671 /* add the symbol you want here if no dynamic linking is done */
672 static TCCSyms tcc_syms[] = {
673 TCCSYM(printf)
674 TCCSYM(fprintf)
675 TCCSYM(fopen)
676 TCCSYM(fclose)
677 { NULL, NULL },
680 void *dlsym(void *handle, const char *symbol)
682 TCCSyms *p;
683 p = tcc_syms;
684 while (p->str != NULL) {
685 if (!strcmp(p->str, symbol))
686 return p->ptr;
687 p++;
689 return NULL;
692 #endif
694 /********************************************************/
696 /* we use our own 'finite' function to avoid potential problems with
697 non standard math libs */
698 /* XXX: endianness dependant */
699 int ieee_finite(double d)
701 int *p = (int *)&d;
702 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
705 /* copy a string and truncate it. */
706 static char *pstrcpy(char *buf, int buf_size, const char *s)
708 char *q, *q_end;
709 int c;
711 if (buf_size > 0) {
712 q = buf;
713 q_end = buf + buf_size - 1;
714 while (q < q_end) {
715 c = *s++;
716 if (c == '\0')
717 break;
718 *q++ = c;
720 *q = '\0';
722 return buf;
725 /* strcat and truncate. */
726 static char *pstrcat(char *buf, int buf_size, const char *s)
728 int len;
729 len = strlen(buf);
730 if (len < buf_size)
731 pstrcpy(buf + len, buf_size - len, s);
732 return buf;
735 /* memory management */
736 #ifdef MEM_DEBUG
737 int mem_cur_size;
738 int mem_max_size;
739 #endif
741 static inline void tcc_free(void *ptr)
743 #ifdef MEM_DEBUG
744 mem_cur_size -= malloc_usable_size(ptr);
745 #endif
746 free(ptr);
749 static void *tcc_malloc(unsigned long size)
751 void *ptr;
752 ptr = malloc(size);
753 if (!ptr && size)
754 error("memory full");
755 #ifdef MEM_DEBUG
756 mem_cur_size += malloc_usable_size(ptr);
757 if (mem_cur_size > mem_max_size)
758 mem_max_size = mem_cur_size;
759 #endif
760 return ptr;
763 static void *tcc_mallocz(unsigned long size)
765 void *ptr;
766 ptr = tcc_malloc(size);
767 memset(ptr, 0, size);
768 return ptr;
771 static inline void *tcc_realloc(void *ptr, unsigned long size)
773 void *ptr1;
774 #ifdef MEM_DEBUG
775 mem_cur_size -= malloc_usable_size(ptr);
776 #endif
777 ptr1 = realloc(ptr, size);
778 #ifdef MEM_DEBUG
779 /* NOTE: count not correct if alloc error, but not critical */
780 mem_cur_size += malloc_usable_size(ptr1);
781 if (mem_cur_size > mem_max_size)
782 mem_max_size = mem_cur_size;
783 #endif
784 return ptr1;
787 static char *tcc_strdup(const char *str)
789 char *ptr;
790 ptr = tcc_malloc(strlen(str) + 1);
791 strcpy(ptr, str);
792 return ptr;
795 #define free(p) use_tcc_free(p)
796 #define malloc(s) use_tcc_malloc(s)
797 #define realloc(p, s) use_tcc_realloc(p, s)
799 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
801 int nb, nb_alloc;
802 void **pp;
804 nb = *nb_ptr;
805 pp = *ptab;
806 /* every power of two we double array size */
807 if ((nb & (nb - 1)) == 0) {
808 if (!nb)
809 nb_alloc = 1;
810 else
811 nb_alloc = nb * 2;
812 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
813 if (!pp)
814 error("memory full");
815 *ptab = pp;
817 pp[nb++] = data;
818 *nb_ptr = nb;
821 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
823 Section *sec;
825 sec = tcc_mallocz(sizeof(Section));
826 pstrcpy(sec->name, sizeof(sec->name), name);
827 sec->sh_type = sh_type;
828 sec->sh_flags = sh_flags;
829 switch(sh_type) {
830 case SHT_HASH:
831 case SHT_REL:
832 case SHT_DYNSYM:
833 case SHT_SYMTAB:
834 case SHT_DYNAMIC:
835 sec->sh_addralign = 4;
836 break;
837 case SHT_STRTAB:
838 sec->sh_addralign = 1;
839 break;
840 default:
841 sec->sh_addralign = 32; /* default conservative alignment */
842 break;
845 /* only add section if not private */
846 if (!(sh_flags & SHF_PRIVATE)) {
847 sec->sh_num = s1->nb_sections;
848 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
850 return sec;
853 static void free_section(Section *s)
855 tcc_free(s->data);
856 tcc_free(s);
859 /* realloc section and set its content to zero */
860 static void section_realloc(Section *sec, unsigned long new_size)
862 unsigned long size;
863 unsigned char *data;
865 size = sec->data_allocated;
866 if (size == 0)
867 size = 1;
868 while (size < new_size)
869 size = size * 2;
870 data = tcc_realloc(sec->data, size);
871 if (!data)
872 error("memory full");
873 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
874 sec->data = data;
875 sec->data_allocated = size;
878 /* reserve at least 'size' bytes in section 'sec' from
879 sec->data_offset. */
880 static void *section_ptr_add(Section *sec, unsigned long size)
882 unsigned long offset, offset1;
884 offset = sec->data_offset;
885 offset1 = offset + size;
886 if (offset1 > sec->data_allocated)
887 section_realloc(sec, offset1);
888 sec->data_offset = offset1;
889 return sec->data + offset;
892 /* return a reference to a section, and create it if it does not
893 exists */
894 Section *find_section(TCCState *s1, const char *name)
896 Section *sec;
897 int i;
898 for(i = 1; i < s1->nb_sections; i++) {
899 sec = s1->sections[i];
900 if (!strcmp(name, sec->name))
901 return sec;
903 /* sections are created as PROGBITS */
904 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
907 /* update sym->c so that it points to an external symbol in section
908 'section' with value 'value' */
909 static void put_extern_sym(Sym *sym, Section *section,
910 unsigned long value, unsigned long size)
912 int sym_type, sym_bind, sh_num, info;
913 Elf32_Sym *esym;
914 const char *name;
916 if (section)
917 sh_num = section->sh_num;
918 else
919 sh_num = SHN_UNDEF;
920 if (!sym->c) {
921 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
922 sym_type = STT_FUNC;
923 else
924 sym_type = STT_OBJECT;
925 if (sym->type.t & VT_STATIC)
926 sym_bind = STB_LOCAL;
927 else
928 sym_bind = STB_GLOBAL;
930 name = get_tok_str(sym->v, NULL);
931 #ifdef CONFIG_TCC_BCHECK
932 if (do_bounds_check) {
933 char buf[32];
935 /* XXX: avoid doing that for statics ? */
936 /* if bound checking is activated, we change some function
937 names by adding the "__bound" prefix */
938 switch(sym->v) {
939 #if 0
940 /* XXX: we rely only on malloc hooks */
941 case TOK_malloc:
942 case TOK_free:
943 case TOK_realloc:
944 case TOK_memalign:
945 case TOK_calloc:
946 #endif
947 case TOK_memcpy:
948 case TOK_memmove:
949 case TOK_memset:
950 case TOK_strlen:
951 case TOK_strcpy:
952 strcpy(buf, "__bound_");
953 strcat(buf, name);
954 name = buf;
955 break;
958 #endif
959 info = ELF32_ST_INFO(sym_bind, sym_type);
960 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
961 } else {
962 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
963 esym->st_value = value;
964 esym->st_size = size;
965 esym->st_shndx = sh_num;
969 /* add a new relocation entry to symbol 'sym' in section 's' */
970 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
972 if (!sym->c)
973 put_extern_sym(sym, NULL, 0, 0);
974 /* now we can add ELF relocation info */
975 put_elf_reloc(symtab_section, s, offset, type, sym->c);
978 static inline int isid(int c)
980 return (c >= 'a' && c <= 'z') ||
981 (c >= 'A' && c <= 'Z') ||
982 c == '_';
985 static inline int isnum(int c)
987 return c >= '0' && c <= '9';
990 static inline int isoct(int c)
992 return c >= '0' && c <= '7';
995 static inline int toup(int c)
997 if (c >= 'a' && c <= 'z')
998 return c - 'a' + 'A';
999 else
1000 return c;
1003 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1005 int len;
1006 len = strlen(buf);
1007 vsnprintf(buf + len, buf_size - len, fmt, ap);
1010 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1012 va_list ap;
1013 va_start(ap, fmt);
1014 strcat_vprintf(buf, buf_size, fmt, ap);
1015 va_end(ap);
1018 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1020 char buf[2048];
1021 BufferedFile **f;
1023 buf[0] = '\0';
1024 if (file) {
1025 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1026 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1027 (*f)->filename, (*f)->line_num);
1028 if (file->line_num > 0) {
1029 strcat_printf(buf, sizeof(buf),
1030 "%s:%d: ", file->filename, file->line_num);
1031 } else {
1032 strcat_printf(buf, sizeof(buf),
1033 "%s: ", file->filename);
1035 } else {
1036 strcat_printf(buf, sizeof(buf),
1037 "tcc: ");
1039 if (is_warning)
1040 strcat_printf(buf, sizeof(buf), "warning: ");
1041 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1043 if (!s1->error_func) {
1044 /* default case: stderr */
1045 fprintf(stderr, "%s\n", buf);
1046 } else {
1047 s1->error_func(s1->error_opaque, buf);
1049 if (!is_warning)
1050 s1->nb_errors++;
1053 #ifdef LIBTCC
1054 void tcc_set_error_func(TCCState *s, void *error_opaque,
1055 void (*error_func)(void *opaque, const char *msg))
1057 s->error_opaque = error_opaque;
1058 s->error_func = error_func;
1060 #endif
1062 /* error without aborting current compilation */
1063 void error_noabort(const char *fmt, ...)
1065 TCCState *s1 = tcc_state;
1066 va_list ap;
1068 va_start(ap, fmt);
1069 error1(s1, 0, fmt, ap);
1070 va_end(ap);
1073 void error(const char *fmt, ...)
1075 TCCState *s1 = tcc_state;
1076 va_list ap;
1078 va_start(ap, fmt);
1079 error1(s1, 0, fmt, ap);
1080 va_end(ap);
1081 /* better than nothing: in some cases, we accept to handle errors */
1082 if (s1->error_set_jmp_enabled) {
1083 longjmp(s1->error_jmp_buf, 1);
1084 } else {
1085 /* XXX: suppress it someday */
1086 exit(1);
1090 void expect(const char *msg)
1092 error("%s expected", msg);
1095 void warning(const char *fmt, ...)
1097 TCCState *s1 = tcc_state;
1098 va_list ap;
1100 va_start(ap, fmt);
1101 error1(s1, 1, fmt, ap);
1102 va_end(ap);
1105 void skip(int c)
1107 if (tok != c)
1108 error("'%c' expected", c);
1109 next();
1112 void test_lvalue(void)
1114 if (!(vtop->r & VT_LVAL))
1115 expect("lvalue");
1118 TokenSym *tok_alloc(const char *str, int len)
1120 TokenSym *ts, **pts, **ptable;
1121 int h, i;
1123 h = 1;
1124 for(i=0;i<len;i++)
1125 h = (h * 263 + ((unsigned char *)str)[i]) & (TOK_HASH_SIZE - 1);
1127 pts = &hash_ident[h];
1128 while (1) {
1129 ts = *pts;
1130 if (!ts)
1131 break;
1132 if (ts->len == len && !memcmp(ts->str, str, len))
1133 return ts;
1134 pts = &(ts->hash_next);
1137 if (tok_ident >= SYM_FIRST_ANOM)
1138 error("memory full");
1140 /* expand token table if needed */
1141 i = tok_ident - TOK_IDENT;
1142 if ((i % TOK_ALLOC_INCR) == 0) {
1143 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1144 if (!ptable)
1145 error("memory full");
1146 table_ident = ptable;
1149 ts = tcc_malloc(sizeof(TokenSym) + len);
1150 table_ident[i] = ts;
1151 ts->tok = tok_ident++;
1152 ts->sym_define = NULL;
1153 ts->sym_label = NULL;
1154 ts->sym_struct = NULL;
1155 ts->sym_identifier = NULL;
1156 ts->len = len;
1157 ts->hash_next = NULL;
1158 memcpy(ts->str, str, len);
1159 ts->str[len] = '\0';
1160 *pts = ts;
1161 return ts;
1164 /* CString handling */
1166 static void cstr_realloc(CString *cstr, int new_size)
1168 int size;
1169 void *data;
1171 size = cstr->size_allocated;
1172 if (size == 0)
1173 size = 8; /* no need to allocate a too small first string */
1174 while (size < new_size)
1175 size = size * 2;
1176 data = tcc_realloc(cstr->data_allocated, size);
1177 if (!data)
1178 error("memory full");
1179 cstr->data_allocated = data;
1180 cstr->size_allocated = size;
1181 cstr->data = data;
1184 /* add a byte */
1185 static void cstr_ccat(CString *cstr, int ch)
1187 int size;
1188 size = cstr->size + 1;
1189 if (size > cstr->size_allocated)
1190 cstr_realloc(cstr, size);
1191 ((unsigned char *)cstr->data)[size - 1] = ch;
1192 cstr->size = size;
1195 static void cstr_cat(CString *cstr, const char *str)
1197 int c;
1198 for(;;) {
1199 c = *str;
1200 if (c == '\0')
1201 break;
1202 cstr_ccat(cstr, c);
1203 str++;
1207 /* add a wide char */
1208 static void cstr_wccat(CString *cstr, int ch)
1210 int size;
1211 size = cstr->size + sizeof(int);
1212 if (size > cstr->size_allocated)
1213 cstr_realloc(cstr, size);
1214 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1215 cstr->size = size;
1218 static void cstr_new(CString *cstr)
1220 memset(cstr, 0, sizeof(CString));
1223 /* free string and reset it to NULL */
1224 static void cstr_free(CString *cstr)
1226 tcc_free(cstr->data_allocated);
1227 cstr_new(cstr);
1230 #define cstr_reset(cstr) cstr_free(cstr)
1232 static CString *cstr_dup(CString *cstr1)
1234 CString *cstr;
1235 int size;
1237 cstr = tcc_malloc(sizeof(CString));
1238 size = cstr1->size;
1239 cstr->size = size;
1240 cstr->size_allocated = size;
1241 cstr->data_allocated = tcc_malloc(size);
1242 cstr->data = cstr->data_allocated;
1243 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1244 return cstr;
1247 /* XXX: unicode ? */
1248 static void add_char(CString *cstr, int c)
1250 if (c == '\'' || c == '\"' || c == '\\') {
1251 /* XXX: could be more precise if char or string */
1252 cstr_ccat(cstr, '\\');
1254 if (c >= 32 && c <= 126) {
1255 cstr_ccat(cstr, c);
1256 } else {
1257 cstr_ccat(cstr, '\\');
1258 if (c == '\n') {
1259 cstr_ccat(cstr, 'n');
1260 } else {
1261 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1262 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1263 cstr_ccat(cstr, '0' + (c & 7));
1268 /* XXX: buffer overflow */
1269 /* XXX: float tokens */
1270 char *get_tok_str(int v, CValue *cv)
1272 static char buf[STRING_MAX_SIZE + 1];
1273 static CString cstr_buf;
1274 CString *cstr;
1275 unsigned char *q;
1276 char *p;
1277 int i, len;
1279 /* NOTE: to go faster, we give a fixed buffer for small strings */
1280 cstr_reset(&cstr_buf);
1281 cstr_buf.data = buf;
1282 cstr_buf.size_allocated = sizeof(buf);
1283 p = buf;
1285 switch(v) {
1286 case TOK_CINT:
1287 case TOK_CUINT:
1288 /* XXX: not quite exact, but only useful for testing */
1289 sprintf(p, "%u", cv->ui);
1290 break;
1291 case TOK_CLLONG:
1292 case TOK_CULLONG:
1293 /* XXX: not quite exact, but only useful for testing */
1294 sprintf(p, "%Lu", cv->ull);
1295 break;
1296 case TOK_CCHAR:
1297 case TOK_LCHAR:
1298 cstr_ccat(&cstr_buf, '\'');
1299 add_char(&cstr_buf, cv->i);
1300 cstr_ccat(&cstr_buf, '\'');
1301 cstr_ccat(&cstr_buf, '\0');
1302 break;
1303 case TOK_PPNUM:
1304 cstr = cv->cstr;
1305 len = cstr->size - 1;
1306 for(i=0;i<len;i++)
1307 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1308 cstr_ccat(&cstr_buf, '\0');
1309 break;
1310 case TOK_STR:
1311 case TOK_LSTR:
1312 cstr = cv->cstr;
1313 cstr_ccat(&cstr_buf, '\"');
1314 if (v == TOK_STR) {
1315 len = cstr->size - 1;
1316 for(i=0;i<len;i++)
1317 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1318 } else {
1319 len = (cstr->size / sizeof(int)) - 1;
1320 for(i=0;i<len;i++)
1321 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1323 cstr_ccat(&cstr_buf, '\"');
1324 cstr_ccat(&cstr_buf, '\0');
1325 break;
1326 case TOK_LT:
1327 v = '<';
1328 goto addv;
1329 case TOK_GT:
1330 v = '>';
1331 goto addv;
1332 case TOK_A_SHL:
1333 return strcpy(p, "<<=");
1334 case TOK_A_SAR:
1335 return strcpy(p, ">>=");
1336 default:
1337 if (v < TOK_IDENT) {
1338 /* search in two bytes table */
1339 q = tok_two_chars;
1340 while (*q) {
1341 if (q[2] == v) {
1342 *p++ = q[0];
1343 *p++ = q[1];
1344 *p = '\0';
1345 return buf;
1347 q += 3;
1349 addv:
1350 *p++ = v;
1351 *p = '\0';
1352 } else if (v < tok_ident) {
1353 return table_ident[v - TOK_IDENT]->str;
1354 } else if (v >= SYM_FIRST_ANOM) {
1355 /* special name for anonymous symbol */
1356 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1357 } else {
1358 /* should never happen */
1359 return NULL;
1361 break;
1363 return cstr_buf.data;
1366 /* push, without hashing */
1367 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1369 Sym *s;
1370 s = tcc_malloc(sizeof(Sym));
1371 s->v = v;
1372 s->type.t = t;
1373 s->c = c;
1374 s->next = NULL;
1375 /* add in stack */
1376 s->prev = *ps;
1377 *ps = s;
1378 return s;
1381 /* find a symbol and return its associated structure. 's' is the top
1382 of the symbol stack */
1383 static Sym *sym_find2(Sym *s, int v)
1385 while (s) {
1386 if (s->v == v)
1387 return s;
1388 s = s->prev;
1390 return NULL;
1393 /* structure lookup */
1394 static Sym *struct_find(int v)
1396 v -= TOK_IDENT;
1397 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1398 return NULL;
1399 return table_ident[v]->sym_struct;
1402 /* find an identifier */
1403 static inline Sym *sym_find(int v)
1405 v -= TOK_IDENT;
1406 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1407 return NULL;
1408 return table_ident[v]->sym_identifier;
1411 /* push a given symbol on the symbol stack */
1412 static Sym *sym_push(int v, CType *type, int r, int c)
1414 Sym *s, **ps;
1415 TokenSym *ts;
1417 if (local_stack)
1418 ps = &local_stack;
1419 else
1420 ps = &global_stack;
1421 s = sym_push2(ps, v, type->t, c);
1422 s->type.ref = type->ref;
1423 s->r = r;
1424 /* don't record fields or anonymous symbols */
1425 /* XXX: simplify */
1426 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1427 /* record symbol in token array */
1428 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1429 if (v & SYM_STRUCT)
1430 ps = &ts->sym_struct;
1431 else
1432 ps = &ts->sym_identifier;
1433 s->prev_tok = *ps;
1434 *ps = s;
1436 return s;
1439 /* push a global identifier */
1440 static Sym *global_identifier_push(int v, int t, int c)
1442 Sym *s, **ps;
1443 s = sym_push2(&global_stack, v, t, c);
1444 /* don't record anonymous symbol */
1445 if (v < SYM_FIRST_ANOM) {
1446 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1447 /* modify the top most local identifier, so that
1448 sym_identifier will point to 's' when popped */
1449 while (*ps != NULL)
1450 ps = &(*ps)->prev_tok;
1451 s->prev_tok = NULL;
1452 *ps = s;
1454 return s;
1457 /* pop symbols until top reaches 'b' */
1458 static void sym_pop(Sym **ptop, Sym *b)
1460 Sym *s, *ss, **ps;
1461 TokenSym *ts;
1462 int v;
1464 s = *ptop;
1465 while(s != b) {
1466 ss = s->prev;
1467 v = s->v;
1468 /* remove symbol in token array */
1469 /* XXX: simplify */
1470 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1471 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1472 if (v & SYM_STRUCT)
1473 ps = &ts->sym_struct;
1474 else
1475 ps = &ts->sym_identifier;
1476 *ps = s->prev_tok;
1478 tcc_free(s);
1479 s = ss;
1481 *ptop = b;
1484 /* I/O layer */
1486 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1488 int fd;
1489 BufferedFile *bf;
1491 fd = open(filename, O_RDONLY);
1492 if (fd < 0)
1493 return NULL;
1494 bf = tcc_malloc(sizeof(BufferedFile));
1495 if (!bf) {
1496 close(fd);
1497 return NULL;
1499 bf->fd = fd;
1500 bf->buf_ptr = bf->buffer;
1501 bf->buf_end = bf->buffer;
1502 bf->buffer[0] = CH_EOB; /* put eob symbol */
1503 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1504 bf->line_num = 0;
1505 bf->ifndef_macro = 0;
1506 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1507 // printf("opening '%s'\n", filename);
1508 return bf;
1511 void tcc_close(BufferedFile *bf)
1513 total_lines += bf->line_num;
1514 close(bf->fd);
1515 tcc_free(bf);
1518 /* fill input buffer and return next char */
1519 int tcc_getc_slow(BufferedFile *bf)
1521 int len;
1522 /* only tries to read if really end of buffer */
1523 if (bf->buf_ptr >= bf->buf_end) {
1524 if (bf->fd != -1) {
1525 len = read(bf->fd, bf->buffer, IO_BUF_SIZE);
1526 if (len < 0)
1527 len = 0;
1528 } else {
1529 len = 0;
1531 total_bytes += len;
1532 bf->buf_ptr = bf->buffer;
1533 bf->buf_end = bf->buffer + len;
1534 *bf->buf_end = CH_EOB;
1536 if (bf->buf_ptr < bf->buf_end) {
1537 return *bf->buf_ptr++;
1538 } else {
1539 bf->buf_ptr = bf->buf_end;
1540 return CH_EOF;
1544 /* no need to put that inline */
1545 void handle_eob(void)
1547 /* no need to do anything if not at EOB */
1548 if (file->buf_ptr <= file->buf_end)
1549 return;
1550 ch = tcc_getc_slow(file);
1553 /* read next char from current input file and handle end of input buffer */
1554 static inline void inp(void)
1556 ch = *(file->buf_ptr++);
1557 /* end of buffer/file handling */
1558 if (ch == CH_EOB)
1559 handle_eob();
1562 /* handle '\[\r]\n' */
1563 static void handle_stray(void)
1565 while (ch == '\\') {
1566 inp();
1567 if (ch == '\n') {
1568 file->line_num++;
1569 inp();
1570 } else if (ch == '\r') {
1571 inp();
1572 if (ch != '\n')
1573 goto fail;
1574 file->line_num++;
1575 inp();
1576 } else {
1577 fail:
1578 error("stray '\\' in program");
1583 /* input with '\[\r]\n' handling. Note that this function cannot
1584 handle other characters after '\', so you cannot call it inside
1585 strings or comments */
1586 static void minp(void)
1588 inp();
1589 if (ch == '\\')
1590 handle_stray();
1594 static void parse_line_comment(void)
1596 /* single line C++ comments */
1597 /* XXX: accept '\\\n' ? */
1598 inp();
1599 while (ch != '\n' && ch != TOK_EOF)
1600 inp();
1603 static void parse_comment(void)
1605 /* C comments */
1606 minp();
1607 for(;;) {
1608 /* fast skip loop */
1609 while (ch != '\n' && ch != '*' && ch != TOK_EOF)
1610 inp();
1611 /* now we can handle all the cases */
1612 if (ch == '\n') {
1613 file->line_num++;
1614 inp();
1615 } else if (ch == '*') {
1616 for(;;) {
1617 inp();
1618 if (ch == '/') {
1619 goto end_of_comment;
1620 } else if (ch == '\\') {
1621 inp();
1622 if (ch == '\n') {
1623 file->line_num++;
1624 inp();
1625 } else if (ch == '\r') {
1626 inp();
1627 if (ch != '\n')
1628 break;
1629 file->line_num++;
1630 inp();
1631 } else {
1632 break;
1634 } else if (ch != '*') {
1635 break;
1638 } else {
1639 error("unexpected end of file in comment");
1642 end_of_comment:
1643 inp();
1646 #define cinp minp
1648 /* space exlcuding newline */
1649 static inline int is_space(int ch)
1651 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1654 static inline void skip_spaces(void)
1656 while (is_space(ch))
1657 cinp();
1660 /* skip block of text until #else, #elif or #endif. skip also pairs of
1661 #if/#endif */
1662 void preprocess_skip(void)
1664 int a, start_of_line, sep;
1666 start_of_line = 1;
1667 a = 0;
1668 for(;;) {
1669 redo_no_start:
1670 switch(ch) {
1671 case ' ':
1672 case '\t':
1673 case '\f':
1674 case '\v':
1675 case '\r':
1676 inp();
1677 goto redo_no_start;
1678 case '\n':
1679 start_of_line = 1;
1680 file->line_num++;
1681 inp();
1682 goto redo_no_start;
1683 case '\\':
1684 handle_stray();
1685 goto redo_no_start;
1686 /* skip strings */
1687 case '\"':
1688 case '\'':
1689 sep = ch;
1690 inp();
1691 while (ch != sep) {
1692 /* XXX: better error message */
1693 if (ch == TOK_EOF) {
1694 error("unterminated string");
1695 } else if (ch == '\n') {
1696 file->line_num++;
1697 } else if (ch == '\\') {
1698 /* ignore next char */
1699 inp();
1700 if (ch == '\n')
1701 file->line_num++;
1703 inp();
1705 minp();
1706 break;
1707 /* skip comments */
1708 case '/':
1709 minp();
1710 if (ch == '*') {
1711 parse_comment();
1712 } else if (ch == '/') {
1713 parse_line_comment();
1715 break;
1717 case '#':
1718 minp();
1719 if (start_of_line) {
1720 next_nomacro();
1721 if (a == 0 &&
1722 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1723 goto the_end;
1724 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1725 a++;
1726 else if (tok == TOK_ENDIF)
1727 a--;
1729 break;
1730 case CH_EOF:
1731 expect("#endif");
1732 break;
1733 default:
1734 inp();
1735 break;
1737 start_of_line = 0;
1739 the_end: ;
1742 /* ParseState handling */
1744 /* XXX: currently, no include file info is stored. Thus, we cannot display
1745 accurate messages if the function or data definition spans multiple
1746 files */
1748 /* save current parse state in 's' */
1749 void save_parse_state(ParseState *s)
1751 s->line_num = file->line_num;
1752 s->macro_ptr = macro_ptr;
1753 s->tok = tok;
1754 s->tokc = tokc;
1757 /* restore parse state from 's' */
1758 void restore_parse_state(ParseState *s)
1760 file->line_num = s->line_num;
1761 macro_ptr = s->macro_ptr;
1762 tok = s->tok;
1763 tokc = s->tokc;
1766 /* return the number of additionnal 'ints' necessary to store the
1767 token */
1768 static inline int tok_ext_size(int t)
1770 switch(t) {
1771 /* 4 bytes */
1772 case TOK_CINT:
1773 case TOK_CUINT:
1774 case TOK_CCHAR:
1775 case TOK_LCHAR:
1776 case TOK_STR:
1777 case TOK_LSTR:
1778 case TOK_CFLOAT:
1779 case TOK_LINENUM:
1780 case TOK_PPNUM:
1781 return 1;
1782 case TOK_CDOUBLE:
1783 case TOK_CLLONG:
1784 case TOK_CULLONG:
1785 return 2;
1786 case TOK_CLDOUBLE:
1787 return LDOUBLE_SIZE / 4;
1788 default:
1789 return 0;
1793 /* token string handling */
1795 static inline void tok_str_new(TokenString *s)
1797 s->str = NULL;
1798 s->len = 0;
1799 s->last_line_num = -1;
1802 static void tok_str_free(int *str)
1804 const int *p;
1805 CString *cstr;
1806 int t;
1808 p = str;
1809 for(;;) {
1810 t = *p++;
1811 if (t == 0)
1812 break;
1813 if (t == TOK_STR || t == TOK_LSTR || t == TOK_PPNUM) {
1814 /* XXX: use a macro to be portable on 64 bit ? */
1815 cstr = (CString *)(*p++);
1816 cstr_free(cstr);
1817 tcc_free(cstr);
1818 } else {
1819 p += tok_ext_size(t);
1822 tcc_free(str);
1825 static void tok_str_add(TokenString *s, int t)
1827 int len, *str;
1829 len = s->len;
1830 str = s->str;
1831 if ((len & 63) == 0) {
1832 str = tcc_realloc(str, (len + 64) * sizeof(int));
1833 if (!str)
1834 return;
1835 s->str = str;
1837 str[len++] = t;
1838 s->len = len;
1841 static void tok_str_add2(TokenString *s, int t, CValue *cv)
1843 int n, i;
1844 CValue cv1;
1846 tok_str_add(s, t);
1847 if (t == TOK_STR || t == TOK_LSTR || t == TOK_PPNUM) {
1848 /* special case: need to duplicate string */
1849 cv1.cstr = cstr_dup(cv->cstr);
1850 tok_str_add(s, cv1.tab[0]);
1851 } else {
1852 n = tok_ext_size(t);
1853 for(i=0;i<n;i++)
1854 tok_str_add(s, cv->tab[i]);
1858 /* add the current parse token in token string 's' */
1859 static void tok_str_add_tok(TokenString *s)
1861 CValue cval;
1863 /* save line number info */
1864 if (file->line_num != s->last_line_num) {
1865 s->last_line_num = file->line_num;
1866 cval.i = s->last_line_num;
1867 tok_str_add2(s, TOK_LINENUM, &cval);
1869 tok_str_add2(s, tok, &tokc);
1872 /* get a token from an integer array and increment pointer accordingly */
1873 static int tok_get(int **tok_str, CValue *cv)
1875 int *p, t, n, i;
1877 p = *tok_str;
1878 t = *p++;
1879 n = tok_ext_size(t);
1880 for(i=0;i<n;i++)
1881 cv->tab[i] = *p++;
1882 *tok_str = p;
1883 return t;
1886 /* defines handling */
1887 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
1889 Sym *s;
1891 s = sym_push2(&define_stack, v, macro_type, (int)str);
1892 s->next = first_arg;
1893 table_ident[v - TOK_IDENT]->sym_define = s;
1896 /* undefined a define symbol. Its name is just set to zero */
1897 static void define_undef(Sym *s)
1899 int v;
1900 v = s->v;
1901 if (v >= TOK_IDENT && v < tok_ident)
1902 table_ident[v - TOK_IDENT]->sym_define = NULL;
1903 s->v = 0;
1906 static inline Sym *define_find(int v)
1908 v -= TOK_IDENT;
1909 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1910 return NULL;
1911 return table_ident[v]->sym_define;
1914 /* free define stack until top reaches 'b' */
1915 static void free_defines(Sym *b)
1917 Sym *top, *top1;
1918 int v;
1920 top = define_stack;
1921 while (top != b) {
1922 top1 = top->prev;
1923 /* do not free args or predefined defines */
1924 if (top->c)
1925 tok_str_free((int *)top->c);
1926 v = top->v;
1927 if (v >= TOK_IDENT && v < tok_ident)
1928 table_ident[v - TOK_IDENT]->sym_define = NULL;
1929 tcc_free(top);
1930 top = top1;
1932 define_stack = b;
1935 /* label lookup */
1936 static Sym *label_find(int v)
1938 v -= TOK_IDENT;
1939 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1940 return NULL;
1941 return table_ident[v]->sym_label;
1944 static Sym *label_push(int v, int flags)
1946 Sym *s;
1947 s = sym_push2(&label_stack, v, 0, 0);
1948 s->r = flags;
1949 table_ident[v - TOK_IDENT]->sym_label = s;
1950 return s;
1953 /* eval an expression for #if/#elif */
1954 int expr_preprocess(void)
1956 int c, t;
1957 TokenString str;
1959 tok_str_new(&str);
1960 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
1961 next(); /* do macro subst */
1962 if (tok == TOK_DEFINED) {
1963 next_nomacro();
1964 t = tok;
1965 if (t == '(')
1966 next_nomacro();
1967 c = define_find(tok) != 0;
1968 if (t == '(')
1969 next_nomacro();
1970 tok = TOK_CINT;
1971 tokc.i = c;
1972 } else if (tok >= TOK_IDENT) {
1973 /* if undefined macro */
1974 tok = TOK_CINT;
1975 tokc.i = 0;
1977 tok_str_add_tok(&str);
1979 tok_str_add(&str, -1); /* simulate end of file */
1980 tok_str_add(&str, 0);
1981 /* now evaluate C constant expression */
1982 macro_ptr = str.str;
1983 next();
1984 c = expr_const();
1985 macro_ptr = NULL;
1986 tok_str_free(str.str);
1987 return c != 0;
1990 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
1991 void tok_print(int *str)
1993 int t;
1994 CValue cval;
1996 while (1) {
1997 t = tok_get(&str, &cval);
1998 if (!t)
1999 break;
2000 printf(" %s", get_tok_str(t, &cval));
2002 printf("\n");
2004 #endif
2006 /* parse after #define */
2007 void parse_define(void)
2009 Sym *s, *first, **ps;
2010 int v, t, varg, is_vaargs;
2011 TokenString str;
2013 v = tok;
2014 if (v < TOK_IDENT)
2015 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2016 /* XXX: should check if same macro (ANSI) */
2017 first = NULL;
2018 t = MACRO_OBJ;
2019 /* '(' must be just after macro definition for MACRO_FUNC */
2020 if (ch == '(') {
2021 next_nomacro();
2022 next_nomacro();
2023 ps = &first;
2024 while (tok != ')') {
2025 varg = tok;
2026 next_nomacro();
2027 is_vaargs = 0;
2028 if (varg == TOK_DOTS) {
2029 varg = TOK___VA_ARGS__;
2030 is_vaargs = 1;
2031 } else if (tok == TOK_DOTS && gnu_ext) {
2032 is_vaargs = 1;
2033 next_nomacro();
2035 if (varg < TOK_IDENT)
2036 error("badly punctuated parameter list");
2037 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2038 *ps = s;
2039 ps = &s->next;
2040 if (tok != ',')
2041 break;
2042 next_nomacro();
2044 t = MACRO_FUNC;
2046 tok_str_new(&str);
2047 next_nomacro();
2048 /* EOF testing necessary for '-D' handling */
2049 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2050 tok_str_add2(&str, tok, &tokc);
2051 next_nomacro();
2053 tok_str_add(&str, 0);
2054 #ifdef PP_DEBUG
2055 printf("define %s %d: ", get_tok_str(v, NULL), t);
2056 tok_print(str.str);
2057 #endif
2058 define_push(v, t, str.str, first);
2061 /* XXX: use a token or a hash table to accelerate matching ? */
2062 static CachedInclude *search_cached_include(TCCState *s1,
2063 int type, const char *filename)
2065 CachedInclude *e;
2066 int i;
2068 for(i = 0;i < s1->nb_cached_includes; i++) {
2069 e = s1->cached_includes[i];
2070 if (e->type == type && !strcmp(e->filename, filename))
2071 return e;
2073 return NULL;
2076 static inline void add_cached_include(TCCState *s1, int type,
2077 const char *filename, int ifndef_macro)
2079 CachedInclude *e;
2081 if (search_cached_include(s1, type, filename))
2082 return;
2083 #ifdef INC_DEBUG
2084 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2085 #endif
2086 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2087 if (!e)
2088 return;
2089 e->type = type;
2090 strcpy(e->filename, filename);
2091 e->ifndef_macro = ifndef_macro;
2092 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2095 /* is_bof is true if first non space token at beginning of file */
2096 static void preprocess(int is_bof)
2098 TCCState *s1 = tcc_state;
2099 int size, i, c, n, line_num;
2100 char buf[1024], *q, *p;
2101 char buf1[1024];
2102 BufferedFile *f;
2103 Sym *s;
2104 CachedInclude *e;
2106 return_linefeed = 1; /* linefeed will be returned as a
2107 token. EOF is also returned as line feed */
2108 next_nomacro();
2109 redo:
2110 switch(tok) {
2111 case TOK_DEFINE:
2112 next_nomacro();
2113 parse_define();
2114 break;
2115 case TOK_UNDEF:
2116 next_nomacro();
2117 s = define_find(tok);
2118 /* undefine symbol by putting an invalid name */
2119 if (s)
2120 define_undef(s);
2121 break;
2122 case TOK_INCLUDE:
2123 skip_spaces();
2124 if (ch == '<') {
2125 c = '>';
2126 goto read_name;
2127 } else if (ch == '\"') {
2128 c = ch;
2129 read_name:
2130 minp();
2131 q = buf;
2132 while (ch != c && ch != '\n' && ch != CH_EOF) {
2133 if ((q - buf) < sizeof(buf) - 1)
2134 *q++ = ch;
2135 minp();
2137 *q = '\0';
2138 #if 0
2139 /* eat all spaces and comments after include */
2140 /* XXX: slightly incorrect */
2141 while (ch1 != '\n' && ch1 != CH_EOF)
2142 inp();
2143 #endif
2144 } else {
2145 /* computed #include : either we have only strings or
2146 we have anything enclosed in '<>' */
2147 next();
2148 buf[0] = '\0';
2149 if (tok == TOK_STR) {
2150 while (tok != TOK_LINEFEED) {
2151 if (tok != TOK_STR) {
2152 include_syntax:
2153 error("'#include' expects \"FILENAME\" or <FILENAME>");
2155 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2156 next();
2158 c = '\"';
2159 } else {
2160 int len;
2161 while (tok != TOK_LINEFEED) {
2162 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2163 next();
2165 len = strlen(buf);
2166 /* check syntax and remove '<>' */
2167 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2168 goto include_syntax;
2169 memmove(buf, buf + 1, len - 2);
2170 buf[len - 2] = '\0';
2171 c = '>';
2175 ch = '\n';
2176 e = search_cached_include(s1, c, buf);
2177 if (e && define_find(e->ifndef_macro)) {
2178 /* no need to parse the include because the 'ifndef macro'
2179 is defined */
2180 #ifdef INC_DEBUG
2181 printf("%s: skipping %s\n", file->filename, buf);
2182 #endif
2183 } else {
2184 if (c == '\"') {
2185 /* first search in current dir if "header.h" */
2186 size = 0;
2187 p = strrchr(file->filename, '/');
2188 if (p)
2189 size = p + 1 - file->filename;
2190 if (size > sizeof(buf1) - 1)
2191 size = sizeof(buf1) - 1;
2192 memcpy(buf1, file->filename, size);
2193 buf1[size] = '\0';
2194 pstrcat(buf1, sizeof(buf1), buf);
2195 f = tcc_open(s1, buf1);
2196 if (f)
2197 goto found;
2199 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2200 error("#include recursion too deep");
2201 /* now search in all the include paths */
2202 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2203 for(i = 0; i < n; i++) {
2204 const char *path;
2205 if (i < s1->nb_include_paths)
2206 path = s1->include_paths[i];
2207 else
2208 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2209 pstrcpy(buf1, sizeof(buf1), path);
2210 pstrcat(buf1, sizeof(buf1), "/");
2211 pstrcat(buf1, sizeof(buf1), buf);
2212 f = tcc_open(s1, buf1);
2213 if (f)
2214 goto found;
2216 error("include file '%s' not found", buf);
2217 f = NULL;
2218 found:
2219 #ifdef INC_DEBUG
2220 printf("%s: including %s\n", file->filename, buf1);
2221 #endif
2222 f->inc_type = c;
2223 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2224 /* push current file in stack */
2225 /* XXX: fix current line init */
2226 *s1->include_stack_ptr++ = file;
2227 file = f;
2228 /* add include file debug info */
2229 if (do_debug) {
2230 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2232 tok_flags |= TOK_FLAG_BOF;
2233 goto the_end;
2235 break;
2236 case TOK_IFNDEF:
2237 c = 1;
2238 goto do_ifdef;
2239 case TOK_IF:
2240 c = expr_preprocess();
2241 goto do_if;
2242 case TOK_IFDEF:
2243 c = 0;
2244 do_ifdef:
2245 next_nomacro();
2246 if (tok < TOK_IDENT)
2247 error("invalid argument for '#if%sdef'", c ? "n" : "");
2248 if (is_bof) {
2249 if (c) {
2250 #ifdef INC_DEBUG
2251 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2252 #endif
2253 file->ifndef_macro = tok;
2256 c = (define_find(tok) != 0) ^ c;
2257 do_if:
2258 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2259 error("memory full");
2260 *s1->ifdef_stack_ptr++ = c;
2261 goto test_skip;
2262 case TOK_ELSE:
2263 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2264 error("#else without matching #if");
2265 if (s1->ifdef_stack_ptr[-1] & 2)
2266 error("#else after #else");
2267 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2268 goto test_skip;
2269 case TOK_ELIF:
2270 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2271 error("#elif without matching #if");
2272 c = s1->ifdef_stack_ptr[-1];
2273 if (c > 1)
2274 error("#elif after #else");
2275 /* last #if/#elif expression was true: we skip */
2276 if (c == 1)
2277 goto skip;
2278 c = expr_preprocess();
2279 s1->ifdef_stack_ptr[-1] = c;
2280 test_skip:
2281 if (!(c & 1)) {
2282 skip:
2283 preprocess_skip();
2284 is_bof = 0;
2285 goto redo;
2287 break;
2288 case TOK_ENDIF:
2289 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2290 error("#endif without matching #if");
2291 s1->ifdef_stack_ptr--;
2292 /* '#ifndef macro' was at the start of file. Now we check if
2293 an '#endif' is exactly at the end of file */
2294 if (file->ifndef_macro &&
2295 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2296 file->ifndef_macro_saved = file->ifndef_macro;
2297 /* need to set to zero to avoid false matches if another
2298 #ifndef at middle of file */
2299 file->ifndef_macro = 0;
2300 while (tok != TOK_LINEFEED)
2301 next_nomacro();
2302 tok_flags |= TOK_FLAG_ENDIF;
2303 goto the_end;
2305 break;
2306 case TOK_LINE:
2307 next();
2308 if (tok != TOK_CINT)
2309 error("#line");
2310 line_num = tokc.i;
2311 next();
2312 if (tok != TOK_LINEFEED) {
2313 if (tok != TOK_STR)
2314 error("#line");
2315 pstrcpy(file->filename, sizeof(file->filename),
2316 (char *)tokc.cstr->data);
2318 /* NOTE: we do it there to avoid problems with linefeed */
2319 file->line_num = line_num;
2320 break;
2321 case TOK_ERROR:
2322 case TOK_WARNING:
2323 c = tok;
2324 skip_spaces();
2325 q = buf;
2326 while (ch != '\n' && ch != CH_EOF) {
2327 if ((q - buf) < sizeof(buf) - 1)
2328 *q++ = ch;
2329 minp();
2331 *q = '\0';
2332 if (c == TOK_ERROR)
2333 error("#error %s", buf);
2334 else
2335 warning("#warning %s", buf);
2336 break;
2337 default:
2338 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2339 /* '!' is ignored to allow C scripts. numbers are ignored
2340 to emulate cpp behaviour */
2341 } else {
2342 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2344 break;
2346 /* ignore other preprocess commands or #! for C scripts */
2347 while (tok != TOK_LINEFEED)
2348 next_nomacro();
2349 the_end:
2350 return_linefeed = 0;
2353 /* read a number in base b */
2354 static int getn(int b)
2356 int n, t;
2357 n = 0;
2358 while (1) {
2359 if (ch >= 'a' && ch <= 'f')
2360 t = ch - 'a' + 10;
2361 else if (ch >= 'A' && ch <= 'F')
2362 t = ch - 'A' + 10;
2363 else if (isnum(ch))
2364 t = ch - '0';
2365 else
2366 break;
2367 if (t < 0 || t >= b)
2368 break;
2369 n = n * b + t;
2370 inp();
2372 return n;
2375 /* read a character for string or char constant and eval escape codes */
2376 static int getq(void)
2378 int c;
2380 redo:
2381 c = ch;
2382 inp();
2383 if (c == '\\') {
2384 switch(ch) {
2385 case '0': case '1': case '2': case '3':
2386 case '4': case '5': case '6': case '7':
2387 /* at most three octal digits */
2388 c = ch - '0';
2389 inp();
2390 if (isoct(ch)) {
2391 c = c * 8 + ch - '0';
2392 inp();
2393 if (isoct(ch)) {
2394 c = c * 8 + ch - '0';
2395 inp();
2398 return c;
2399 case 'x':
2400 inp();
2401 return getn(16);
2402 case 'a':
2403 c = '\a';
2404 break;
2405 case 'b':
2406 c = '\b';
2407 break;
2408 case 'f':
2409 c = '\f';
2410 break;
2411 case 'n':
2412 c = '\n';
2413 break;
2414 case 'r':
2415 c = '\r';
2416 break;
2417 case 't':
2418 c = '\t';
2419 break;
2420 case 'v':
2421 c = '\v';
2422 break;
2423 case 'e':
2424 if (!gnu_ext)
2425 goto invalid_escape;
2426 c = 27;
2427 break;
2428 case '\'':
2429 case '\"':
2430 case '\\':
2431 case '?':
2432 c = ch;
2433 break;
2434 case '\n':
2435 inp();
2436 goto redo;
2437 case '\r':
2438 inp();
2439 if (ch != '\n')
2440 goto invalid_escape;
2441 inp();
2442 goto redo;
2443 default:
2444 invalid_escape:
2445 error("invalid escaped char");
2447 inp();
2448 } else if (c == '\r' && ch == '\n') {
2449 inp();
2450 c = '\n';
2452 return c;
2455 /* we use 64 bit numbers */
2456 #define BN_SIZE 2
2458 /* bn = (bn << shift) | or_val */
2459 void bn_lshift(unsigned int *bn, int shift, int or_val)
2461 int i;
2462 unsigned int v;
2463 for(i=0;i<BN_SIZE;i++) {
2464 v = bn[i];
2465 bn[i] = (v << shift) | or_val;
2466 or_val = v >> (32 - shift);
2470 void bn_zero(unsigned int *bn)
2472 int i;
2473 for(i=0;i<BN_SIZE;i++) {
2474 bn[i] = 0;
2478 /* parse number in null terminated string 'p' and return it in the
2479 current token */
2480 void parse_number(const char *p)
2482 int b, t, shift, frac_bits, s, exp_val, ch;
2483 char *q;
2484 unsigned int bn[BN_SIZE];
2485 double d;
2487 /* number */
2488 q = token_buf;
2489 ch = *p++;
2490 t = ch;
2491 ch = *p++;
2492 *q++ = t;
2493 b = 10;
2494 if (t == '.') {
2495 goto float_frac_parse;
2496 } else if (t == '0') {
2497 if (ch == 'x' || ch == 'X') {
2498 q--;
2499 ch = *p++;
2500 b = 16;
2501 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2502 q--;
2503 ch = *p++;
2504 b = 2;
2507 /* parse all digits. cannot check octal numbers at this stage
2508 because of floating point constants */
2509 while (1) {
2510 if (ch >= 'a' && ch <= 'f')
2511 t = ch - 'a' + 10;
2512 else if (ch >= 'A' && ch <= 'F')
2513 t = ch - 'A' + 10;
2514 else if (isnum(ch))
2515 t = ch - '0';
2516 else
2517 break;
2518 if (t >= b)
2519 break;
2520 if (q >= token_buf + STRING_MAX_SIZE) {
2521 num_too_long:
2522 error("number too long");
2524 *q++ = ch;
2525 ch = *p++;
2527 if (ch == '.' ||
2528 ((ch == 'e' || ch == 'E') && b == 10) ||
2529 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
2530 if (b != 10) {
2531 /* NOTE: strtox should support that for hexa numbers, but
2532 non ISOC99 libcs do not support it, so we prefer to do
2533 it by hand */
2534 /* hexadecimal or binary floats */
2535 /* XXX: handle overflows */
2536 *q = '\0';
2537 if (b == 16)
2538 shift = 4;
2539 else
2540 shift = 2;
2541 bn_zero(bn);
2542 q = token_buf;
2543 while (1) {
2544 t = *q++;
2545 if (t == '\0') {
2546 break;
2547 } else if (t >= 'a') {
2548 t = t - 'a' + 10;
2549 } else if (t >= 'A') {
2550 t = t - 'A' + 10;
2551 } else {
2552 t = t - '0';
2554 bn_lshift(bn, shift, t);
2556 frac_bits = 0;
2557 if (ch == '.') {
2558 ch = *p++;
2559 while (1) {
2560 t = ch;
2561 if (t >= 'a' && t <= 'f') {
2562 t = t - 'a' + 10;
2563 } else if (t >= 'A' && t <= 'F') {
2564 t = t - 'A' + 10;
2565 } else if (t >= '0' && t <= '9') {
2566 t = t - '0';
2567 } else {
2568 break;
2570 if (t >= b)
2571 error("invalid digit");
2572 bn_lshift(bn, shift, t);
2573 frac_bits += shift;
2574 ch = *p++;
2577 if (ch != 'p' && ch != 'P')
2578 expect("exponent");
2579 ch = *p++;
2580 s = 1;
2581 exp_val = 0;
2582 if (ch == '+') {
2583 ch = *p++;
2584 } else if (ch == '-') {
2585 s = -1;
2586 ch = *p++;
2588 if (ch < '0' || ch > '9')
2589 expect("exponent digits");
2590 while (ch >= '0' && ch <= '9') {
2591 exp_val = exp_val * 10 + ch - '0';
2592 ch = *p++;
2594 exp_val = exp_val * s;
2596 /* now we can generate the number */
2597 /* XXX: should patch directly float number */
2598 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
2599 d = ldexp(d, exp_val - frac_bits);
2600 t = toup(ch);
2601 if (t == 'F') {
2602 ch = *p++;
2603 tok = TOK_CFLOAT;
2604 /* float : should handle overflow */
2605 tokc.f = (float)d;
2606 } else if (t == 'L') {
2607 ch = *p++;
2608 tok = TOK_CLDOUBLE;
2609 /* XXX: not large enough */
2610 tokc.ld = (long double)d;
2611 } else {
2612 tok = TOK_CDOUBLE;
2613 tokc.d = d;
2615 } else {
2616 /* decimal floats */
2617 if (ch == '.') {
2618 if (q >= token_buf + STRING_MAX_SIZE)
2619 goto num_too_long;
2620 *q++ = ch;
2621 ch = *p++;
2622 float_frac_parse:
2623 while (ch >= '0' && ch <= '9') {
2624 if (q >= token_buf + STRING_MAX_SIZE)
2625 goto num_too_long;
2626 *q++ = ch;
2627 ch = *p++;
2630 if (ch == 'e' || ch == 'E') {
2631 if (q >= token_buf + STRING_MAX_SIZE)
2632 goto num_too_long;
2633 *q++ = ch;
2634 ch = *p++;
2635 if (ch == '-' || ch == '+') {
2636 if (q >= token_buf + STRING_MAX_SIZE)
2637 goto num_too_long;
2638 *q++ = ch;
2639 ch = *p++;
2641 if (ch < '0' || ch > '9')
2642 expect("exponent digits");
2643 while (ch >= '0' && ch <= '9') {
2644 if (q >= token_buf + STRING_MAX_SIZE)
2645 goto num_too_long;
2646 *q++ = ch;
2647 ch = *p++;
2650 *q = '\0';
2651 t = toup(ch);
2652 errno = 0;
2653 if (t == 'F') {
2654 ch = *p++;
2655 tok = TOK_CFLOAT;
2656 tokc.f = strtof(token_buf, NULL);
2657 } else if (t == 'L') {
2658 ch = *p++;
2659 tok = TOK_CLDOUBLE;
2660 tokc.ld = strtold(token_buf, NULL);
2661 } else {
2662 tok = TOK_CDOUBLE;
2663 tokc.d = strtod(token_buf, NULL);
2666 } else {
2667 unsigned long long n, n1;
2668 int lcount, ucount;
2670 /* integer number */
2671 *q = '\0';
2672 q = token_buf;
2673 if (b == 10 && *q == '0') {
2674 b = 8;
2675 q++;
2677 n = 0;
2678 while(1) {
2679 t = *q++;
2680 /* no need for checks except for base 10 / 8 errors */
2681 if (t == '\0') {
2682 break;
2683 } else if (t >= 'a') {
2684 t = t - 'a' + 10;
2685 } else if (t >= 'A') {
2686 t = t - 'A' + 10;
2687 } else {
2688 t = t - '0';
2689 if (t >= b)
2690 error("invalid digit");
2692 n1 = n;
2693 n = n * b + t;
2694 /* detect overflow */
2695 /* XXX: this test is not reliable */
2696 if (n < n1)
2697 error("integer constant overflow");
2700 /* XXX: not exactly ANSI compliant */
2701 if ((n & 0xffffffff00000000LL) != 0) {
2702 if ((n >> 63) != 0)
2703 tok = TOK_CULLONG;
2704 else
2705 tok = TOK_CLLONG;
2706 } else if (n > 0x7fffffff) {
2707 tok = TOK_CUINT;
2708 } else {
2709 tok = TOK_CINT;
2711 lcount = 0;
2712 ucount = 0;
2713 for(;;) {
2714 t = toup(ch);
2715 if (t == 'L') {
2716 if (lcount >= 2)
2717 error("three 'l's in integer constant");
2718 lcount++;
2719 if (lcount == 2) {
2720 if (tok == TOK_CINT)
2721 tok = TOK_CLLONG;
2722 else if (tok == TOK_CUINT)
2723 tok = TOK_CULLONG;
2725 ch = *p++;
2726 } else if (t == 'U') {
2727 if (ucount >= 1)
2728 error("two 'u's in integer constant");
2729 ucount++;
2730 if (tok == TOK_CINT)
2731 tok = TOK_CUINT;
2732 else if (tok == TOK_CLLONG)
2733 tok = TOK_CULLONG;
2734 ch = *p++;
2735 } else {
2736 break;
2739 if (tok == TOK_CINT || tok == TOK_CUINT)
2740 tokc.ui = n;
2741 else
2742 tokc.ull = n;
2746 /* return next token without macro substitution */
2747 static inline void next_nomacro1(void)
2749 int b, t;
2750 char *q;
2751 TokenSym *ts;
2753 redo_no_start:
2754 switch(ch) {
2755 case ' ':
2756 case '\t':
2757 case '\f':
2758 case '\v':
2759 case '\r':
2760 inp();
2761 goto redo_no_start;
2763 case '\\':
2764 handle_stray();
2765 goto redo_no_start;
2767 case CH_EOF:
2769 TCCState *s1 = tcc_state;
2771 if (return_linefeed) {
2772 tok = TOK_LINEFEED;
2773 } else if (s1->include_stack_ptr == s1->include_stack) {
2774 /* no include left : end of file */
2775 tok = TOK_EOF;
2776 } else {
2777 /* pop include file */
2779 /* test if previous '#endif' was after a #ifdef at
2780 start of file */
2781 if (tok_flags & TOK_FLAG_ENDIF) {
2782 #ifdef INC_DEBUG
2783 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
2784 #endif
2785 add_cached_include(s1, file->inc_type, file->inc_filename,
2786 file->ifndef_macro_saved);
2789 /* add end of include file debug info */
2790 if (do_debug) {
2791 put_stabd(N_EINCL, 0, 0);
2793 /* pop include stack */
2794 tcc_close(file);
2795 s1->include_stack_ptr--;
2796 file = *s1->include_stack_ptr;
2797 inp();
2798 goto redo_no_start;
2801 break;
2803 case '\n':
2804 file->line_num++;
2805 if (return_linefeed) {
2806 tok = TOK_LINEFEED;
2807 } else {
2808 tok_flags |= TOK_FLAG_BOL;
2809 inp();
2810 goto redo_no_start;
2812 break;
2814 case '#':
2815 minp();
2816 if (tok_flags & TOK_FLAG_BOL) {
2817 preprocess(tok_flags & TOK_FLAG_BOF);
2818 goto redo_no_start;
2819 } else {
2820 if (ch == '#') {
2821 inp();
2822 tok = TOK_TWOSHARPS;
2823 } else {
2824 tok = '#';
2827 break;
2829 case 'a': case 'b': case 'c': case 'd':
2830 case 'e': case 'f': case 'g': case 'h':
2831 case 'i': case 'j': case 'k': case 'l':
2832 case 'm': case 'n': case 'o': case 'p':
2833 case 'q': case 'r': case 's': case 't':
2834 case 'u': case 'v': case 'w': case 'x':
2835 case 'y': case 'z':
2836 case 'A': case 'B': case 'C': case 'D':
2837 case 'E': case 'F': case 'G': case 'H':
2838 case 'I': case 'J': case 'K':
2839 case 'M': case 'N': case 'O': case 'P':
2840 case 'Q': case 'R': case 'S': case 'T':
2841 case 'U': case 'V': case 'W': case 'X':
2842 case 'Y': case 'Z':
2843 case '_':
2844 q = token_buf;
2845 *q++ = ch;
2846 cinp();
2847 parse_ident:
2848 while (isid(ch) || isnum(ch)) {
2849 if (q >= token_buf + STRING_MAX_SIZE)
2850 error("ident too long");
2851 *q++ = ch;
2852 cinp();
2854 *q = '\0';
2855 ts = tok_alloc(token_buf, q - token_buf);
2856 tok = ts->tok;
2857 break;
2858 case 'L':
2859 minp();
2860 if (ch == '\'') {
2861 tok = TOK_LCHAR;
2862 goto char_const;
2864 if (ch == '\"') {
2865 tok = TOK_LSTR;
2866 goto str_const;
2868 q = token_buf;
2869 *q++ = 'L';
2870 goto parse_ident;
2872 case '0': case '1': case '2': case '3':
2873 case '4': case '5': case '6': case '7':
2874 case '8': case '9':
2876 cstr_reset(&tokcstr);
2877 /* after the first digit, accept digits, alpha, '.' or sign if
2878 prefixed by 'eEpP' */
2879 parse_num:
2880 for(;;) {
2881 t = ch;
2882 cstr_ccat(&tokcstr, ch);
2883 cinp();
2884 if (!(isnum(ch) || isid(ch) || ch == '.' ||
2885 ((ch == '+' || ch == '-') &&
2886 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
2887 break;
2889 /* We add a trailing '\0' to ease parsing */
2890 cstr_ccat(&tokcstr, '\0');
2891 tokc.cstr = &tokcstr;
2892 tok = TOK_PPNUM;
2893 break;
2894 case '.':
2895 /* special dot handling because it can also start a number */
2896 cinp();
2897 if (isnum(ch)) {
2898 cstr_reset(&tokcstr);
2899 cstr_ccat(&tokcstr, '.');
2900 goto parse_num;
2902 if (ch == '.') {
2903 cinp();
2904 if (ch != '.')
2905 expect("'.'");
2906 cinp();
2907 tok = TOK_DOTS;
2908 } else {
2909 tok = '.';
2911 break;
2912 case '\'':
2913 tok = TOK_CCHAR;
2914 char_const:
2915 inp();
2916 b = getq();
2917 /* this cast is needed if >= 128 */
2918 if (tok == TOK_CCHAR)
2919 b = (char)b;
2920 tokc.i = b;
2921 if (ch != '\'')
2922 error("unterminated character constant");
2923 inp();
2924 break;
2925 case '\"':
2926 tok = TOK_STR;
2927 str_const:
2928 inp();
2929 cstr_reset(&tokcstr);
2930 while (ch != '\"') {
2931 b = getq();
2932 if (ch == CH_EOF)
2933 error("unterminated string");
2934 if (tok == TOK_STR)
2935 cstr_ccat(&tokcstr, b);
2936 else
2937 cstr_wccat(&tokcstr, b);
2939 if (tok == TOK_STR)
2940 cstr_ccat(&tokcstr, '\0');
2941 else
2942 cstr_wccat(&tokcstr, '\0');
2943 tokc.cstr = &tokcstr;
2944 inp();
2945 break;
2947 case '<':
2948 cinp();
2949 if (ch == '=') {
2950 cinp();
2951 tok = TOK_LE;
2952 } else if (ch == '<') {
2953 cinp();
2954 if (ch == '=') {
2955 cinp();
2956 tok = TOK_A_SHL;
2957 } else {
2958 tok = TOK_SHL;
2960 } else {
2961 tok = TOK_LT;
2963 break;
2965 case '>':
2966 cinp();
2967 if (ch == '=') {
2968 cinp();
2969 tok = TOK_GE;
2970 } else if (ch == '>') {
2971 cinp();
2972 if (ch == '=') {
2973 cinp();
2974 tok = TOK_A_SAR;
2975 } else {
2976 tok = TOK_SAR;
2978 } else {
2979 tok = TOK_GT;
2981 break;
2983 case '!':
2984 tok = ch;
2985 cinp();
2986 if (ch == '=') {
2987 cinp();
2988 tok = TOK_NE;
2990 break;
2992 case '=':
2993 tok = ch;
2994 cinp();
2995 if (ch == '=') {
2996 cinp();
2997 tok = TOK_EQ;
2999 break;
3001 case '&':
3002 tok = ch;
3003 cinp();
3004 if (ch == '&') {
3005 cinp();
3006 tok = TOK_LAND;
3007 } else if (ch == '=') {
3008 cinp();
3009 tok = TOK_A_AND;
3011 break;
3013 case '|':
3014 tok = ch;
3015 cinp();
3016 if (ch == '|') {
3017 cinp();
3018 tok = TOK_LOR;
3019 } else if (ch == '=') {
3020 cinp();
3021 tok = TOK_A_OR;
3023 break;
3025 case '+':
3026 tok = ch;
3027 cinp();
3028 if (ch == '+') {
3029 cinp();
3030 tok = TOK_INC;
3031 } else if (ch == '=') {
3032 cinp();
3033 tok = TOK_A_ADD;
3035 break;
3037 case '-':
3038 tok = ch;
3039 cinp();
3040 if (ch == '-') {
3041 cinp();
3042 tok = TOK_DEC;
3043 } else if (ch == '=') {
3044 cinp();
3045 tok = TOK_A_SUB;
3046 } else if (ch == '>') {
3047 cinp();
3048 tok = TOK_ARROW;
3050 break;
3052 case '*':
3053 tok = ch;
3054 cinp();
3055 if (ch == '=') {
3056 cinp();
3057 tok = TOK_A_MUL;
3059 break;
3061 case '%':
3062 tok = ch;
3063 cinp();
3064 if (ch == '=') {
3065 cinp();
3066 tok = TOK_A_MOD;
3068 break;
3070 case '^':
3071 tok = ch;
3072 cinp();
3073 if (ch == '=') {
3074 cinp();
3075 tok = TOK_A_XOR;
3077 break;
3079 /* comments or operator */
3080 case '/':
3081 minp();
3082 if (ch == '*') {
3083 parse_comment();
3084 goto redo_no_start;
3085 } else if (ch == '/') {
3086 parse_line_comment();
3087 goto redo_no_start;
3088 } else if (ch == '=') {
3089 cinp();
3090 tok = TOK_A_DIV;
3091 } else {
3092 tok = '/';
3094 break;
3096 /* simple tokens */
3097 case '(':
3098 case ')':
3099 case '[':
3100 case ']':
3101 case '{':
3102 case '}':
3103 case ',':
3104 case ';':
3105 case ':':
3106 case '?':
3107 case '~':
3108 tok = ch;
3109 cinp();
3110 break;
3111 default:
3112 error("unrecognized character \\x%02x", ch);
3113 break;
3115 tok_flags = 0;
3116 #if defined(PARSE_DEBUG)
3117 printf("token = %s\n", get_tok_str(tok, &tokc));
3118 #endif
3121 /* return next token without macro substitution. Can read input from
3122 macro_ptr buffer */
3123 static void next_nomacro(void)
3125 if (macro_ptr) {
3126 redo:
3127 tok = *macro_ptr;
3128 if (tok) {
3129 tok = tok_get(&macro_ptr, &tokc);
3130 if (tok == TOK_LINENUM) {
3131 file->line_num = tokc.i;
3132 goto redo;
3135 } else {
3136 next_nomacro1();
3140 /* substitute args in macro_str and return allocated string */
3141 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3143 int *st, last_tok, t, notfirst;
3144 Sym *s;
3145 CValue cval;
3146 TokenString str;
3147 CString cstr;
3149 tok_str_new(&str);
3150 last_tok = 0;
3151 while(1) {
3152 t = tok_get(&macro_str, &cval);
3153 if (!t)
3154 break;
3155 if (t == '#') {
3156 /* stringize */
3157 t = tok_get(&macro_str, &cval);
3158 if (!t)
3159 break;
3160 s = sym_find2(args, t);
3161 if (s) {
3162 cstr_new(&cstr);
3163 st = (int *)s->c;
3164 notfirst = 0;
3165 while (*st) {
3166 if (notfirst)
3167 cstr_ccat(&cstr, ' ');
3168 t = tok_get(&st, &cval);
3169 cstr_cat(&cstr, get_tok_str(t, &cval));
3170 notfirst = 1;
3172 cstr_ccat(&cstr, '\0');
3173 #ifdef PP_DEBUG
3174 printf("stringize: %s\n", (char *)cstr.data);
3175 #endif
3176 /* add string */
3177 cval.cstr = &cstr;
3178 tok_str_add2(&str, TOK_STR, &cval);
3179 cstr_free(&cstr);
3180 } else {
3181 tok_str_add2(&str, t, &cval);
3183 } else if (t >= TOK_IDENT) {
3184 s = sym_find2(args, t);
3185 if (s) {
3186 st = (int *)s->c;
3187 /* if '##' is present before or after, no arg substitution */
3188 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3189 /* special case for var arg macros : ## eats the
3190 ',' if empty VA_ARGS variable. */
3191 /* XXX: test of the ',' is not 100%
3192 reliable. should fix it to avoid security
3193 problems */
3194 if (gnu_ext && s->type.t &&
3195 last_tok == TOK_TWOSHARPS &&
3196 str.len >= 2 && str.str[str.len - 2] == ',') {
3197 if (*st == 0) {
3198 /* suppress ',' '##' */
3199 str.len -= 2;
3200 } else {
3201 /* suppress '##' and add variable */
3202 str.len--;
3203 goto add_var;
3205 } else {
3206 int t1;
3207 add_var:
3208 for(;;) {
3209 t1 = tok_get(&st, &cval);
3210 if (!t1)
3211 break;
3212 tok_str_add2(&str, t1, &cval);
3215 } else {
3216 macro_subst(&str, nested_list, st);
3218 } else {
3219 tok_str_add(&str, t);
3221 } else {
3222 tok_str_add2(&str, t, &cval);
3224 last_tok = t;
3226 tok_str_add(&str, 0);
3227 return str.str;
3230 /* handle the '##' operator */
3231 static int *macro_twosharps(void)
3233 TokenSym *ts;
3234 int *macro_ptr1;
3235 int t;
3236 const char *p1, *p2;
3237 CValue cval;
3238 TokenString macro_str1;
3239 CString cstr;
3241 cstr_new(&cstr);
3242 tok_str_new(&macro_str1);
3243 tok = 0;
3244 while (1) {
3245 next_nomacro();
3246 if (tok == 0)
3247 break;
3248 while (*macro_ptr == TOK_TWOSHARPS) {
3249 macro_ptr++;
3250 macro_ptr1 = macro_ptr;
3251 t = *macro_ptr;
3252 if (t) {
3253 t = tok_get(&macro_ptr, &cval);
3255 /* We concatenate the two tokens if we have an
3256 identifier or a preprocessing number */
3257 cstr_reset(&cstr);
3258 p1 = get_tok_str(tok, &tokc);
3259 cstr_cat(&cstr, p1);
3260 p2 = get_tok_str(t, &cval);
3261 cstr_cat(&cstr, p2);
3262 cstr_ccat(&cstr, '\0');
3264 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3265 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3266 if (tok == TOK_PPNUM) {
3267 /* if number, then create a number token */
3268 /* NOTE: no need to allocate because
3269 tok_str_add2() does it */
3270 tokc.cstr = &cstr;
3271 } else {
3272 /* if identifier, we must do a test to
3273 validate we have a correct identifier */
3274 if (t == TOK_PPNUM) {
3275 const char *p;
3276 int c;
3278 p = p2;
3279 for(;;) {
3280 c = *p;
3281 if (c == '\0')
3282 break;
3283 p++;
3284 if (!isnum(c) && !isid(c))
3285 goto error_pasting;
3288 ts = tok_alloc(cstr.data, strlen(cstr.data));
3289 tok = ts->tok; /* modify current token */
3291 } else {
3292 const char *str = cstr.data;
3293 const unsigned char *q;
3295 /* we look for a valid token */
3296 /* XXX: do more extensive checks */
3297 if (!strcmp(str, ">>=")) {
3298 tok = TOK_A_SAR;
3299 } else if (!strcmp(str, "<<=")) {
3300 tok = TOK_A_SHL;
3301 } else if (strlen(str) == 2) {
3302 /* search in two bytes table */
3303 q = tok_two_chars;
3304 for(;;) {
3305 if (!*q)
3306 goto error_pasting;
3307 if (q[0] == str[0] && q[1] == str[1])
3308 break;
3309 q += 3;
3311 tok = q[2];
3312 } else {
3313 error_pasting:
3314 /* NOTE: because get_tok_str use a static buffer,
3315 we must save it */
3316 cstr_reset(&cstr);
3317 p1 = get_tok_str(tok, &tokc);
3318 cstr_cat(&cstr, p1);
3319 cstr_ccat(&cstr, '\0');
3320 p2 = get_tok_str(t, &cval);
3321 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
3322 /* cannot merge tokens: just add them separately */
3323 tok_str_add2(&macro_str1, tok, &tokc);
3324 /* XXX: free associated memory ? */
3325 tok = t;
3326 tokc = cval;
3331 tok_str_add2(&macro_str1, tok, &tokc);
3333 cstr_free(&cstr);
3334 tok_str_add(&macro_str1, 0);
3335 return macro_str1.str;
3339 /* do macro substitution of current token with macro 's' and add
3340 result to (tok_str,tok_len). 'nested_list' is the list of all
3341 macros we got inside to avoid recursing. Return non zero if no
3342 substitution needs to be done */
3343 static int macro_subst_tok(TokenString *tok_str,
3344 Sym **nested_list, Sym *s)
3346 Sym *args, *sa, *sa1;
3347 int mstr_allocated, parlevel, *mstr, t;
3348 TokenString str;
3349 char *cstrval;
3350 CValue cval;
3351 CString cstr;
3353 /* if symbol is a macro, prepare substitution */
3354 /* if nested substitution, do nothing */
3355 if (sym_find2(*nested_list, tok))
3356 return -1;
3358 /* special macros */
3359 if (tok == TOK___LINE__) {
3360 cval.i = file->line_num;
3361 tok_str_add2(tok_str, TOK_CINT, &cval);
3362 } else if (tok == TOK___FILE__) {
3363 cstrval = file->filename;
3364 goto add_cstr;
3365 tok_str_add2(tok_str, TOK_STR, &cval);
3366 } else if (tok == TOK___DATE__) {
3367 cstrval = "Jan 1 2002";
3368 goto add_cstr;
3369 } else if (tok == TOK___TIME__) {
3370 cstrval = "00:00:00";
3371 add_cstr:
3372 cstr_new(&cstr);
3373 cstr_cat(&cstr, cstrval);
3374 cstr_ccat(&cstr, '\0');
3375 cval.cstr = &cstr;
3376 tok_str_add2(tok_str, TOK_STR, &cval);
3377 cstr_free(&cstr);
3378 } else {
3379 mstr = (int *)s->c;
3380 mstr_allocated = 0;
3381 if (s->type.t == MACRO_FUNC) {
3382 /* NOTE: we do not use next_nomacro to avoid eating the
3383 next token. XXX: find better solution */
3384 if (macro_ptr) {
3385 t = *macro_ptr;
3386 } else {
3387 /* XXX: incorrect with comments */
3388 while (is_space(ch) || ch == '\n')
3389 cinp();
3390 t = ch;
3392 if (t != '(') /* no macro subst */
3393 return -1;
3395 /* argument macro */
3396 next_nomacro();
3397 next_nomacro();
3398 args = NULL;
3399 sa = s->next;
3400 /* NOTE: empty args are allowed, except if no args */
3401 for(;;) {
3402 /* handle '()' case */
3403 if (!args && tok == ')')
3404 break;
3405 if (!sa)
3406 error("macro '%s' used with too many args",
3407 get_tok_str(s->v, 0));
3408 tok_str_new(&str);
3409 parlevel = 0;
3410 /* NOTE: non zero sa->t indicates VA_ARGS */
3411 while ((parlevel > 0 ||
3412 (tok != ')' &&
3413 (tok != ',' || sa->type.t))) &&
3414 tok != -1) {
3415 if (tok == '(')
3416 parlevel++;
3417 else if (tok == ')')
3418 parlevel--;
3419 tok_str_add2(&str, tok, &tokc);
3420 next_nomacro();
3422 tok_str_add(&str, 0);
3423 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3424 sa = sa->next;
3425 if (tok == ')') {
3426 /* special case for gcc var args: add an empty
3427 var arg argument if it is omitted */
3428 if (sa && sa->type.t && gnu_ext)
3429 continue;
3430 else
3431 break;
3433 if (tok != ',')
3434 expect(",");
3435 next_nomacro();
3437 if (sa) {
3438 error("macro '%s' used with too few args",
3439 get_tok_str(s->v, 0));
3442 /* now subst each arg */
3443 mstr = macro_arg_subst(nested_list, mstr, args);
3444 /* free memory */
3445 sa = args;
3446 while (sa) {
3447 sa1 = sa->prev;
3448 tok_str_free((int *)sa->c);
3449 tcc_free(sa);
3450 sa = sa1;
3452 mstr_allocated = 1;
3454 sym_push2(nested_list, s->v, 0, 0);
3455 macro_subst(tok_str, nested_list, mstr);
3456 /* pop nested defined symbol */
3457 sa1 = *nested_list;
3458 *nested_list = sa1->prev;
3459 tcc_free(sa1);
3460 if (mstr_allocated)
3461 tok_str_free(mstr);
3463 return 0;
3466 /* do macro substitution of macro_str and add result to
3467 (tok_str,tok_len). 'nested_list' is the list of all macros we got
3468 inside to avoid recursing. */
3469 static void macro_subst(TokenString *tok_str,
3470 Sym **nested_list, int *macro_str)
3472 Sym *s;
3473 int *saved_macro_ptr;
3474 int *macro_str1;
3476 saved_macro_ptr = macro_ptr;
3477 macro_ptr = macro_str;
3478 /* first scan for '##' operator handling */
3479 macro_str1 = macro_twosharps();
3480 macro_ptr = macro_str1;
3482 while (1) {
3483 next_nomacro();
3484 if (tok == 0)
3485 break;
3486 s = define_find(tok);
3487 if (s != NULL) {
3488 if (macro_subst_tok(tok_str, nested_list, s) != 0)
3489 goto no_subst;
3490 } else {
3491 no_subst:
3492 tok_str_add2(tok_str, tok, &tokc);
3495 macro_ptr = saved_macro_ptr;
3496 tok_str_free(macro_str1);
3499 /* return next token with macro substitution */
3500 static void next(void)
3502 Sym *nested_list, *s;
3503 TokenString str;
3505 /* special 'ungettok' case for label parsing */
3506 if (tok1) {
3507 tok = tok1;
3508 tokc = tok1c;
3509 tok1 = 0;
3510 } else {
3511 redo:
3512 next_nomacro();
3513 if (!macro_ptr) {
3514 /* if not reading from macro substituted string, then try
3515 to substitute macros */
3516 if (tok >= TOK_IDENT) {
3517 s = define_find(tok);
3518 if (s) {
3519 /* we have a macro: we try to substitute */
3520 tok_str_new(&str);
3521 nested_list = NULL;
3522 if (macro_subst_tok(&str, &nested_list, s) == 0) {
3523 /* substitution done, NOTE: maybe empty */
3524 tok_str_add(&str, 0);
3525 macro_ptr = str.str;
3526 macro_ptr_allocated = str.str;
3527 goto redo;
3531 } else {
3532 if (tok == 0) {
3533 /* end of macro string: free it */
3534 tok_str_free(macro_ptr_allocated);
3535 macro_ptr = NULL;
3536 goto redo;
3540 /* convert preprocessor tokens into C tokens */
3541 if (tok == TOK_PPNUM) {
3542 parse_number((char *)tokc.cstr->data);
3547 void swap(int *p, int *q)
3549 int t;
3550 t = *p;
3551 *p = *q;
3552 *q = t;
3555 void vsetc(CType *type, int r, CValue *vc)
3557 int v;
3559 if (vtop >= vstack + VSTACK_SIZE)
3560 error("memory full");
3561 /* cannot let cpu flags if other instruction are generated. Also
3562 avoid leaving VT_JMP anywhere except on the top of the stack
3563 because it would complicate the code generator. */
3564 if (vtop >= vstack) {
3565 v = vtop->r & VT_VALMASK;
3566 if (v == VT_CMP || (v & ~1) == VT_JMP)
3567 gv(RC_INT);
3569 vtop++;
3570 vtop->type = *type;
3571 vtop->r = r;
3572 vtop->r2 = VT_CONST;
3573 vtop->c = *vc;
3576 /* push integer constant */
3577 void vpushi(int v)
3579 CValue cval;
3580 cval.i = v;
3581 vsetc(&int_type, VT_CONST, &cval);
3584 /* Return a static symbol pointing to a section */
3585 static Sym *get_sym_ref(CType *type, Section *sec,
3586 unsigned long offset, unsigned long size)
3588 int v;
3589 Sym *sym;
3591 v = anon_sym++;
3592 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
3593 sym->type.ref = type->ref;
3594 sym->r = VT_CONST | VT_SYM;
3595 put_extern_sym(sym, sec, offset, size);
3596 return sym;
3599 /* push a reference to a section offset by adding a dummy symbol */
3600 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
3602 CValue cval;
3604 cval.ul = 0;
3605 vsetc(type, VT_CONST | VT_SYM, &cval);
3606 vtop->sym = get_sym_ref(type, sec, offset, size);
3609 /* define a new external reference to a symbol 'v' of type 'u' */
3610 static Sym *external_global_sym(int v, CType *type, int r)
3612 Sym *s;
3614 s = sym_find(v);
3615 if (!s) {
3616 /* push forward reference */
3617 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
3618 s->type.ref = type->ref;
3619 s->r = r | VT_CONST | VT_SYM;
3621 return s;
3624 /* define a new external reference to a symbol 'v' of type 'u' */
3625 static Sym *external_sym(int v, CType *type, int r)
3627 Sym *s;
3629 s = sym_find(v);
3630 if (!s) {
3631 /* push forward reference */
3632 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
3633 s->type.t |= VT_EXTERN;
3635 return s;
3638 /* push a reference to global symbol v */
3639 static void vpush_global_sym(CType *type, int v)
3641 Sym *sym;
3642 CValue cval;
3644 sym = external_global_sym(v, type, 0);
3645 cval.ul = 0;
3646 vsetc(type, VT_CONST | VT_SYM, &cval);
3647 vtop->sym = sym;
3650 void vset(CType *type, int r, int v)
3652 CValue cval;
3654 cval.i = v;
3655 vsetc(type, r, &cval);
3658 void vseti(int r, int v)
3660 CType type;
3661 type.t = VT_INT;
3662 vset(&type, r, v);
3665 void vswap(void)
3667 SValue tmp;
3669 tmp = vtop[0];
3670 vtop[0] = vtop[-1];
3671 vtop[-1] = tmp;
3674 void vpushv(SValue *v)
3676 if (vtop >= vstack + VSTACK_SIZE)
3677 error("memory full");
3678 vtop++;
3679 *vtop = *v;
3682 void vdup(void)
3684 vpushv(vtop);
3687 /* save r to the memory stack, and mark it as being free */
3688 void save_reg(int r)
3690 int l, saved, size, align;
3691 SValue *p, sv;
3692 CType *type;
3694 /* modify all stack values */
3695 saved = 0;
3696 l = 0;
3697 for(p=vstack;p<=vtop;p++) {
3698 if ((p->r & VT_VALMASK) == r ||
3699 (p->r2 & VT_VALMASK) == r) {
3700 /* must save value on stack if not already done */
3701 if (!saved) {
3702 /* NOTE: must reload 'r' because r might be equal to r2 */
3703 r = p->r & VT_VALMASK;
3704 /* store register in the stack */
3705 type = &p->type;
3706 if ((p->r & VT_LVAL) ||
3707 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
3708 type = &int_type;
3709 size = type_size(type, &align);
3710 loc = (loc - size) & -align;
3711 sv.type.t = type->t;
3712 sv.r = VT_LOCAL | VT_LVAL;
3713 sv.c.ul = loc;
3714 store(r, &sv);
3715 #ifdef TCC_TARGET_I386
3716 /* x86 specific: need to pop fp register ST0 if saved */
3717 if (r == REG_ST0) {
3718 o(0xd9dd); /* fstp %st(1) */
3720 #endif
3721 /* special long long case */
3722 if ((type->t & VT_BTYPE) == VT_LLONG) {
3723 sv.c.ul += 4;
3724 store(p->r2, &sv);
3726 l = loc;
3727 saved = 1;
3729 /* mark that stack entry as being saved on the stack */
3730 if (p->r & VT_LVAL) {
3731 /* also suppress the bounded flag because the
3732 relocation address of the function was stored in
3733 p->c.ul */
3734 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
3735 } else {
3736 p->r = lvalue_type(p->type.t) | VT_LOCAL;
3738 p->r2 = VT_CONST;
3739 p->c.ul = l;
3744 /* find a free register of class 'rc'. If none, save one register */
3745 int get_reg(int rc)
3747 int r;
3748 SValue *p;
3750 /* find a free register */
3751 for(r=0;r<NB_REGS;r++) {
3752 if (reg_classes[r] & rc) {
3753 for(p=vstack;p<=vtop;p++) {
3754 if ((p->r & VT_VALMASK) == r ||
3755 (p->r2 & VT_VALMASK) == r)
3756 goto notfound;
3758 return r;
3760 notfound: ;
3763 /* no register left : free the first one on the stack (VERY
3764 IMPORTANT to start from the bottom to ensure that we don't
3765 spill registers used in gen_opi()) */
3766 for(p=vstack;p<=vtop;p++) {
3767 r = p->r & VT_VALMASK;
3768 if (r < VT_CONST && (reg_classes[r] & rc))
3769 goto save_found;
3770 /* also look at second register (if long long) */
3771 r = p->r2 & VT_VALMASK;
3772 if (r < VT_CONST && (reg_classes[r] & rc)) {
3773 save_found:
3774 save_reg(r);
3775 return r;
3778 /* Should never comes here */
3779 return -1;
3782 /* save registers up to (vtop - n) stack entry */
3783 void save_regs(int n)
3785 int r;
3786 SValue *p, *p1;
3787 p1 = vtop - n;
3788 for(p = vstack;p <= p1; p++) {
3789 r = p->r & VT_VALMASK;
3790 if (r < VT_CONST) {
3791 save_reg(r);
3796 /* move register 's' to 'r', and flush previous value of r to memory
3797 if needed */
3798 void move_reg(int r, int s)
3800 SValue sv;
3802 if (r != s) {
3803 save_reg(r);
3804 sv.type.t = VT_INT;
3805 sv.r = s;
3806 sv.c.ul = 0;
3807 load(r, &sv);
3811 /* get address of vtop (vtop MUST BE an lvalue) */
3812 void gaddrof(void)
3814 vtop->r &= ~VT_LVAL;
3815 /* tricky: if saved lvalue, then we can go back to lvalue */
3816 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
3817 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
3820 #ifdef CONFIG_TCC_BCHECK
3821 /* generate lvalue bound code */
3822 void gbound(void)
3824 int lval_type;
3825 CType type1;
3827 vtop->r &= ~VT_MUSTBOUND;
3828 /* if lvalue, then use checking code before dereferencing */
3829 if (vtop->r & VT_LVAL) {
3830 /* if not VT_BOUNDED value, then make one */
3831 if (!(vtop->r & VT_BOUNDED)) {
3832 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
3833 /* must save type because we must set it to int to get pointer */
3834 type1 = vtop->type;
3835 vtop->type.t = VT_INT;
3836 gaddrof();
3837 vpushi(0);
3838 gen_bounded_ptr_add();
3839 vtop->r |= lval_type;
3840 vtop->type = type1;
3842 /* then check for dereferencing */
3843 gen_bounded_ptr_deref();
3846 #endif
3848 /* store vtop a register belonging to class 'rc'. lvalues are
3849 converted to values. Cannot be used if cannot be converted to
3850 register value (such as structures). */
3851 int gv(int rc)
3853 int r, r2, rc2, bit_pos, bit_size, size, align, i;
3854 unsigned long long ll;
3856 /* NOTE: get_reg can modify vstack[] */
3857 if (vtop->type.t & VT_BITFIELD) {
3858 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
3859 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3860 /* remove bit field info to avoid loops */
3861 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3862 /* generate shifts */
3863 vpushi(32 - (bit_pos + bit_size));
3864 gen_op(TOK_SHL);
3865 vpushi(32 - bit_size);
3866 /* NOTE: transformed to SHR if unsigned */
3867 gen_op(TOK_SAR);
3868 r = gv(rc);
3869 } else {
3870 if (is_float(vtop->type.t) &&
3871 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
3872 Sym *sym;
3873 int *ptr;
3874 unsigned long offset;
3876 /* XXX: unify with initializers handling ? */
3877 /* CPUs usually cannot use float constants, so we store them
3878 generically in data segment */
3879 size = type_size(&vtop->type, &align);
3880 offset = (data_section->data_offset + align - 1) & -align;
3881 data_section->data_offset = offset;
3882 /* XXX: not portable yet */
3883 ptr = section_ptr_add(data_section, size);
3884 size = size >> 2;
3885 for(i=0;i<size;i++)
3886 ptr[i] = vtop->c.tab[i];
3887 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
3888 vtop->r |= VT_LVAL | VT_SYM;
3889 vtop->sym = sym;
3890 vtop->c.ul = 0;
3892 #ifdef CONFIG_TCC_BCHECK
3893 if (vtop->r & VT_MUSTBOUND)
3894 gbound();
3895 #endif
3897 r = vtop->r & VT_VALMASK;
3898 /* need to reload if:
3899 - constant
3900 - lvalue (need to dereference pointer)
3901 - already a register, but not in the right class */
3902 if (r >= VT_CONST ||
3903 (vtop->r & VT_LVAL) ||
3904 !(reg_classes[r] & rc) ||
3905 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
3906 !(reg_classes[vtop->r2] & rc))) {
3907 r = get_reg(rc);
3908 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
3909 /* two register type load : expand to two words
3910 temporarily */
3911 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
3912 /* load constant */
3913 ll = vtop->c.ull;
3914 vtop->c.ui = ll; /* first word */
3915 load(r, vtop);
3916 vtop->r = r; /* save register value */
3917 vpushi(ll >> 32); /* second word */
3918 } else if (r >= VT_CONST ||
3919 (vtop->r & VT_LVAL)) {
3920 /* load from memory */
3921 load(r, vtop);
3922 vdup();
3923 vtop[-1].r = r; /* save register value */
3924 /* increment pointer to get second word */
3925 vtop->type.t = VT_INT;
3926 gaddrof();
3927 vpushi(4);
3928 gen_op('+');
3929 vtop->r |= VT_LVAL;
3930 } else {
3931 /* move registers */
3932 load(r, vtop);
3933 vdup();
3934 vtop[-1].r = r; /* save register value */
3935 vtop->r = vtop[-1].r2;
3937 /* allocate second register */
3938 rc2 = RC_INT;
3939 if (rc == RC_IRET)
3940 rc2 = RC_LRET;
3941 r2 = get_reg(rc2);
3942 load(r2, vtop);
3943 vpop();
3944 /* write second register */
3945 vtop->r2 = r2;
3946 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
3947 int t1, t;
3948 /* lvalue of scalar type : need to use lvalue type
3949 because of possible cast */
3950 t = vtop->type.t;
3951 t1 = t;
3952 /* compute memory access type */
3953 if (vtop->r & VT_LVAL_BYTE)
3954 t = VT_BYTE;
3955 else if (vtop->r & VT_LVAL_SHORT)
3956 t = VT_SHORT;
3957 if (vtop->r & VT_LVAL_UNSIGNED)
3958 t |= VT_UNSIGNED;
3959 vtop->type.t = t;
3960 load(r, vtop);
3961 /* restore wanted type */
3962 vtop->type.t = t1;
3963 } else {
3964 /* one register type load */
3965 load(r, vtop);
3968 vtop->r = r;
3970 return r;
3973 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
3974 void gv2(int rc1, int rc2)
3976 int v;
3978 /* generate more generic register first. But VT_JMP or VT_CMP
3979 values must be generated first in all cases to avoid possible
3980 reload errors */
3981 v = vtop[0].r & VT_VALMASK;
3982 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
3983 vswap();
3984 gv(rc1);
3985 vswap();
3986 gv(rc2);
3987 /* test if reload is needed for first register */
3988 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
3989 vswap();
3990 gv(rc1);
3991 vswap();
3993 } else {
3994 gv(rc2);
3995 vswap();
3996 gv(rc1);
3997 vswap();
3998 /* test if reload is needed for first register */
3999 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4000 gv(rc2);
4005 /* expand long long on stack in two int registers */
4006 void lexpand(void)
4008 int u;
4010 u = vtop->type.t & VT_UNSIGNED;
4011 gv(RC_INT);
4012 vdup();
4013 vtop[0].r = vtop[-1].r2;
4014 vtop[0].r2 = VT_CONST;
4015 vtop[-1].r2 = VT_CONST;
4016 vtop[0].type.t = VT_INT | u;
4017 vtop[-1].type.t = VT_INT | u;
4020 /* build a long long from two ints */
4021 void lbuild(int t)
4023 gv2(RC_INT, RC_INT);
4024 vtop[-1].r2 = vtop[0].r;
4025 vtop[-1].type.t = t;
4026 vpop();
4029 /* rotate n first stack elements to the bottom */
4030 void vrotb(int n)
4032 int i;
4033 SValue tmp;
4035 tmp = vtop[-n + 1];
4036 for(i=-n+1;i!=0;i++)
4037 vtop[i] = vtop[i+1];
4038 vtop[0] = tmp;
4041 /* pop stack value */
4042 void vpop(void)
4044 int v;
4045 v = vtop->r & VT_VALMASK;
4046 #ifdef TCC_TARGET_I386
4047 /* for x86, we need to pop the FP stack */
4048 if (v == REG_ST0 && !nocode_wanted) {
4049 o(0xd9dd); /* fstp %st(1) */
4050 } else
4051 #endif
4052 if (v == VT_JMP || v == VT_JMPI) {
4053 /* need to put correct jump if && or || without test */
4054 gsym(vtop->c.ul);
4056 vtop--;
4059 /* convert stack entry to register and duplicate its value in another
4060 register */
4061 void gv_dup(void)
4063 int rc, t, r, r1;
4064 SValue sv;
4066 t = vtop->type.t;
4067 if ((t & VT_BTYPE) == VT_LLONG) {
4068 lexpand();
4069 gv_dup();
4070 vswap();
4071 vrotb(3);
4072 gv_dup();
4073 vrotb(4);
4074 /* stack: H L L1 H1 */
4075 lbuild(t);
4076 vrotb(3);
4077 vrotb(3);
4078 vswap();
4079 lbuild(t);
4080 vswap();
4081 } else {
4082 /* duplicate value */
4083 rc = RC_INT;
4084 sv.type.t = VT_INT;
4085 if (is_float(t)) {
4086 rc = RC_FLOAT;
4087 sv.type.t = t;
4089 r = gv(rc);
4090 r1 = get_reg(rc);
4091 sv.r = r;
4092 sv.c.ul = 0;
4093 load(r1, &sv); /* move r to r1 */
4094 vdup();
4095 /* duplicates value */
4096 vtop->r = r1;
4100 /* generate CPU independent (unsigned) long long operations */
4101 void gen_opl(int op)
4103 int t, a, b, op1, c, i;
4104 int func;
4105 GFuncContext gf;
4106 SValue tmp;
4108 switch(op) {
4109 case '/':
4110 case TOK_PDIV:
4111 func = TOK___divdi3;
4112 goto gen_func;
4113 case TOK_UDIV:
4114 func = TOK___udivdi3;
4115 goto gen_func;
4116 case '%':
4117 func = TOK___moddi3;
4118 goto gen_func;
4119 case TOK_UMOD:
4120 func = TOK___umoddi3;
4121 gen_func:
4122 /* call generic long long function */
4123 gfunc_start(&gf, FUNC_CDECL);
4124 gfunc_param(&gf);
4125 gfunc_param(&gf);
4126 vpush_global_sym(&func_old_type, func);
4127 gfunc_call(&gf);
4128 vpushi(0);
4129 vtop->r = REG_IRET;
4130 vtop->r2 = REG_LRET;
4131 break;
4132 case '^':
4133 case '&':
4134 case '|':
4135 case '*':
4136 case '+':
4137 case '-':
4138 t = vtop->type.t;
4139 vswap();
4140 lexpand();
4141 vrotb(3);
4142 lexpand();
4143 /* stack: L1 H1 L2 H2 */
4144 tmp = vtop[0];
4145 vtop[0] = vtop[-3];
4146 vtop[-3] = tmp;
4147 tmp = vtop[-2];
4148 vtop[-2] = vtop[-3];
4149 vtop[-3] = tmp;
4150 vswap();
4151 /* stack: H1 H2 L1 L2 */
4152 if (op == '*') {
4153 vpushv(vtop - 1);
4154 vpushv(vtop - 1);
4155 gen_op(TOK_UMULL);
4156 lexpand();
4157 /* stack: H1 H2 L1 L2 ML MH */
4158 for(i=0;i<4;i++)
4159 vrotb(6);
4160 /* stack: ML MH H1 H2 L1 L2 */
4161 tmp = vtop[0];
4162 vtop[0] = vtop[-2];
4163 vtop[-2] = tmp;
4164 /* stack: ML MH H1 L2 H2 L1 */
4165 gen_op('*');
4166 vrotb(3);
4167 vrotb(3);
4168 gen_op('*');
4169 /* stack: ML MH M1 M2 */
4170 gen_op('+');
4171 gen_op('+');
4172 } else if (op == '+' || op == '-') {
4173 /* XXX: add non carry method too (for MIPS or alpha) */
4174 if (op == '+')
4175 op1 = TOK_ADDC1;
4176 else
4177 op1 = TOK_SUBC1;
4178 gen_op(op1);
4179 /* stack: H1 H2 (L1 op L2) */
4180 vrotb(3);
4181 vrotb(3);
4182 gen_op(op1 + 1); /* TOK_xxxC2 */
4183 } else {
4184 gen_op(op);
4185 /* stack: H1 H2 (L1 op L2) */
4186 vrotb(3);
4187 vrotb(3);
4188 /* stack: (L1 op L2) H1 H2 */
4189 gen_op(op);
4190 /* stack: (L1 op L2) (H1 op H2) */
4192 /* stack: L H */
4193 lbuild(t);
4194 break;
4195 case TOK_SAR:
4196 case TOK_SHR:
4197 case TOK_SHL:
4198 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4199 t = vtop[-1].type.t;
4200 vswap();
4201 lexpand();
4202 vrotb(3);
4203 /* stack: L H shift */
4204 c = (int)vtop->c.i;
4205 /* constant: simpler */
4206 /* NOTE: all comments are for SHL. the other cases are
4207 done by swaping words */
4208 vpop();
4209 if (op != TOK_SHL)
4210 vswap();
4211 if (c >= 32) {
4212 /* stack: L H */
4213 vpop();
4214 if (c > 32) {
4215 vpushi(c - 32);
4216 gen_op(op);
4218 if (op != TOK_SAR) {
4219 vpushi(0);
4220 } else {
4221 gv_dup();
4222 vpushi(31);
4223 gen_op(TOK_SAR);
4225 vswap();
4226 } else {
4227 vswap();
4228 gv_dup();
4229 /* stack: H L L */
4230 vpushi(c);
4231 gen_op(op);
4232 vswap();
4233 vpushi(32 - c);
4234 if (op == TOK_SHL)
4235 gen_op(TOK_SHR);
4236 else
4237 gen_op(TOK_SHL);
4238 vrotb(3);
4239 /* stack: L L H */
4240 vpushi(c);
4241 if (op == TOK_SHL)
4242 gen_op(TOK_SHL);
4243 else
4244 gen_op(TOK_SHR);
4245 gen_op('|');
4247 if (op != TOK_SHL)
4248 vswap();
4249 lbuild(t);
4250 } else {
4251 /* XXX: should provide a faster fallback on x86 ? */
4252 switch(op) {
4253 case TOK_SAR:
4254 func = TOK___sardi3;
4255 goto gen_func;
4256 case TOK_SHR:
4257 func = TOK___shrdi3;
4258 goto gen_func;
4259 case TOK_SHL:
4260 func = TOK___shldi3;
4261 goto gen_func;
4264 break;
4265 default:
4266 /* compare operations */
4267 t = vtop->type.t;
4268 vswap();
4269 lexpand();
4270 vrotb(3);
4271 lexpand();
4272 /* stack: L1 H1 L2 H2 */
4273 tmp = vtop[-1];
4274 vtop[-1] = vtop[-2];
4275 vtop[-2] = tmp;
4276 /* stack: L1 L2 H1 H2 */
4277 /* compare high */
4278 op1 = op;
4279 /* when values are equal, we need to compare low words. since
4280 the jump is inverted, we invert the test too. */
4281 if (op1 == TOK_LT)
4282 op1 = TOK_LE;
4283 else if (op1 == TOK_GT)
4284 op1 = TOK_GE;
4285 else if (op1 == TOK_ULT)
4286 op1 = TOK_ULE;
4287 else if (op1 == TOK_UGT)
4288 op1 = TOK_UGE;
4289 a = 0;
4290 b = 0;
4291 gen_op(op1);
4292 if (op1 != TOK_NE) {
4293 a = gtst(1, 0);
4295 if (op != TOK_EQ) {
4296 /* generate non equal test */
4297 /* XXX: NOT PORTABLE yet */
4298 if (a == 0) {
4299 b = gtst(0, 0);
4300 } else {
4301 #ifdef TCC_TARGET_I386
4302 b = psym(0x850f, 0);
4303 #else
4304 error("not implemented");
4305 #endif
4308 /* compare low */
4309 gen_op(op);
4310 a = gtst(1, a);
4311 gsym(b);
4312 vseti(VT_JMPI, a);
4313 break;
4317 /* handle integer constant optimizations and various machine
4318 independant opt */
4319 void gen_opic(int op)
4321 int fc, c1, c2, n;
4322 SValue *v1, *v2;
4324 v1 = vtop - 1;
4325 v2 = vtop;
4326 /* currently, we cannot do computations with forward symbols */
4327 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4328 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4329 if (c1 && c2) {
4330 fc = v2->c.i;
4331 switch(op) {
4332 case '+': v1->c.i += fc; break;
4333 case '-': v1->c.i -= fc; break;
4334 case '&': v1->c.i &= fc; break;
4335 case '^': v1->c.i ^= fc; break;
4336 case '|': v1->c.i |= fc; break;
4337 case '*': v1->c.i *= fc; break;
4339 case TOK_PDIV:
4340 case '/':
4341 case '%':
4342 case TOK_UDIV:
4343 case TOK_UMOD:
4344 /* if division by zero, generate explicit division */
4345 if (fc == 0) {
4346 if (const_wanted)
4347 error("division by zero in constant");
4348 goto general_case;
4350 switch(op) {
4351 default: v1->c.i /= fc; break;
4352 case '%': v1->c.i %= fc; break;
4353 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
4354 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
4356 break;
4357 case TOK_SHL: v1->c.i <<= fc; break;
4358 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
4359 case TOK_SAR: v1->c.i >>= fc; break;
4360 /* tests */
4361 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
4362 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
4363 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
4364 case TOK_NE: v1->c.i = v1->c.i != fc; break;
4365 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
4366 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
4367 case TOK_LT: v1->c.i = v1->c.i < fc; break;
4368 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
4369 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
4370 case TOK_GT: v1->c.i = v1->c.i > fc; break;
4371 /* logical */
4372 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
4373 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
4374 default:
4375 goto general_case;
4377 vtop--;
4378 } else {
4379 /* if commutative ops, put c2 as constant */
4380 if (c1 && (op == '+' || op == '&' || op == '^' ||
4381 op == '|' || op == '*')) {
4382 vswap();
4383 swap(&c1, &c2);
4385 fc = vtop->c.i;
4386 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
4387 op == TOK_PDIV) &&
4388 fc == 1) ||
4389 ((op == '+' || op == '-' || op == '|' || op == '^' ||
4390 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
4391 fc == 0) ||
4392 (op == '&' &&
4393 fc == -1))) {
4394 /* nothing to do */
4395 vtop--;
4396 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
4397 /* try to use shifts instead of muls or divs */
4398 if (fc > 0 && (fc & (fc - 1)) == 0) {
4399 n = -1;
4400 while (fc) {
4401 fc >>= 1;
4402 n++;
4404 vtop->c.i = n;
4405 if (op == '*')
4406 op = TOK_SHL;
4407 else if (op == TOK_PDIV)
4408 op = TOK_SAR;
4409 else
4410 op = TOK_SHR;
4412 goto general_case;
4413 } else if (c2 && (op == '+' || op == '-') &&
4414 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
4415 (VT_CONST | VT_SYM)) {
4416 /* symbol + constant case */
4417 if (op == '-')
4418 fc = -fc;
4419 vtop--;
4420 vtop->c.i += fc;
4421 } else {
4422 general_case:
4423 if (!nocode_wanted) {
4424 /* call low level op generator */
4425 gen_opi(op);
4426 } else {
4427 vtop--;
4433 /* generate a floating point operation with constant propagation */
4434 void gen_opif(int op)
4436 int c1, c2;
4437 SValue *v1, *v2;
4438 long double f1, f2;
4440 v1 = vtop - 1;
4441 v2 = vtop;
4442 /* currently, we cannot do computations with forward symbols */
4443 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4444 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4445 if (c1 && c2) {
4446 if (v1->type.t == VT_FLOAT) {
4447 f1 = v1->c.f;
4448 f2 = v2->c.f;
4449 } else if (v1->type.t == VT_DOUBLE) {
4450 f1 = v1->c.d;
4451 f2 = v2->c.d;
4452 } else {
4453 f1 = v1->c.ld;
4454 f2 = v2->c.ld;
4457 /* NOTE: we only do constant propagation if finite number (not
4458 NaN or infinity) (ANSI spec) */
4459 if (!ieee_finite(f1) || !ieee_finite(f2))
4460 goto general_case;
4462 switch(op) {
4463 case '+': f1 += f2; break;
4464 case '-': f1 -= f2; break;
4465 case '*': f1 *= f2; break;
4466 case '/':
4467 if (f2 == 0.0) {
4468 if (const_wanted)
4469 error("division by zero in constant");
4470 goto general_case;
4472 f1 /= f2;
4473 break;
4474 /* XXX: also handles tests ? */
4475 default:
4476 goto general_case;
4478 /* XXX: overflow test ? */
4479 if (v1->type.t == VT_FLOAT) {
4480 v1->c.f = f1;
4481 } else if (v1->type.t == VT_DOUBLE) {
4482 v1->c.d = f1;
4483 } else {
4484 v1->c.ld = f1;
4486 vtop--;
4487 } else {
4488 general_case:
4489 if (!nocode_wanted) {
4490 gen_opf(op);
4491 } else {
4492 vtop--;
4497 static int pointed_size(CType *type)
4499 int align;
4500 return type_size(pointed_type(type), &align);
4503 #if 0
4504 void check_pointer_types(SValue *p1, SValue *p2)
4506 char buf1[256], buf2[256];
4507 int t1, t2;
4508 t1 = p1->t;
4509 t2 = p2->t;
4510 if (!is_compatible_types(t1, t2)) {
4511 type_to_str(buf1, sizeof(buf1), t1, NULL);
4512 type_to_str(buf2, sizeof(buf2), t2, NULL);
4513 error("incompatible pointers '%s' and '%s'", buf1, buf2);
4516 #endif
4518 /* generic gen_op: handles types problems */
4519 void gen_op(int op)
4521 int u, t1, t2, bt1, bt2, t;
4522 CType type1;
4524 t1 = vtop[-1].type.t;
4525 t2 = vtop[0].type.t;
4526 bt1 = t1 & VT_BTYPE;
4527 bt2 = t2 & VT_BTYPE;
4529 if (bt1 == VT_PTR || bt2 == VT_PTR) {
4530 /* at least one operand is a pointer */
4531 /* relationnal op: must be both pointers */
4532 if (op >= TOK_ULT && op <= TOK_GT) {
4533 // check_pointer_types(vtop, vtop - 1);
4534 /* pointers are handled are unsigned */
4535 t = VT_INT | VT_UNSIGNED;
4536 goto std_op;
4538 /* if both pointers, then it must be the '-' op */
4539 if (bt1 == VT_PTR && bt2 == VT_PTR) {
4540 if (op != '-')
4541 error("cannot use pointers here");
4542 // check_pointer_types(vtop - 1, vtop);
4543 /* XXX: check that types are compatible */
4544 u = pointed_size(&vtop[-1].type);
4545 gen_opic(op);
4546 /* set to integer type */
4547 vtop->type.t = VT_INT;
4548 vpushi(u);
4549 gen_op(TOK_PDIV);
4550 } else {
4551 /* exactly one pointer : must be '+' or '-'. */
4552 if (op != '-' && op != '+')
4553 error("cannot use pointers here");
4554 /* Put pointer as first operand */
4555 if (bt2 == VT_PTR) {
4556 vswap();
4557 swap(&t1, &t2);
4559 type1 = vtop[-1].type;
4560 /* XXX: cast to int ? (long long case) */
4561 vpushi(pointed_size(&vtop[-1].type));
4562 gen_op('*');
4563 #ifdef CONFIG_TCC_BCHECK
4564 /* if evaluating constant expression, no code should be
4565 generated, so no bound check */
4566 if (do_bounds_check && !const_wanted) {
4567 /* if bounded pointers, we generate a special code to
4568 test bounds */
4569 if (op == '-') {
4570 vpushi(0);
4571 vswap();
4572 gen_op('-');
4574 gen_bounded_ptr_add();
4575 } else
4576 #endif
4578 gen_opic(op);
4580 /* put again type if gen_opic() swaped operands */
4581 vtop->type = type1;
4583 } else if (is_float(bt1) || is_float(bt2)) {
4584 /* compute bigger type and do implicit casts */
4585 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
4586 t = VT_LDOUBLE;
4587 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
4588 t = VT_DOUBLE;
4589 } else {
4590 t = VT_FLOAT;
4592 /* floats can only be used for a few operations */
4593 if (op != '+' && op != '-' && op != '*' && op != '/' &&
4594 (op < TOK_ULT || op > TOK_GT))
4595 error("invalid operands for binary operation");
4596 goto std_op;
4597 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
4598 /* cast to biggest op */
4599 t = VT_LLONG;
4600 /* convert to unsigned if it does not fit in a long long */
4601 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
4602 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
4603 t |= VT_UNSIGNED;
4604 goto std_op;
4605 } else {
4606 /* integer operations */
4607 t = VT_INT;
4608 /* convert to unsigned if it does not fit in an integer */
4609 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
4610 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
4611 t |= VT_UNSIGNED;
4612 std_op:
4613 /* XXX: currently, some unsigned operations are explicit, so
4614 we modify them here */
4615 if (t & VT_UNSIGNED) {
4616 if (op == TOK_SAR)
4617 op = TOK_SHR;
4618 else if (op == '/')
4619 op = TOK_UDIV;
4620 else if (op == '%')
4621 op = TOK_UMOD;
4622 else if (op == TOK_LT)
4623 op = TOK_ULT;
4624 else if (op == TOK_GT)
4625 op = TOK_UGT;
4626 else if (op == TOK_LE)
4627 op = TOK_ULE;
4628 else if (op == TOK_GE)
4629 op = TOK_UGE;
4631 vswap();
4632 type1.t = t;
4633 gen_cast(&type1);
4634 vswap();
4635 /* special case for shifts and long long: we keep the shift as
4636 an integer */
4637 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
4638 type1.t = VT_INT;
4639 gen_cast(&type1);
4640 if (is_float(t))
4641 gen_opif(op);
4642 else if ((t & VT_BTYPE) == VT_LLONG)
4643 gen_opl(op);
4644 else
4645 gen_opic(op);
4646 if (op >= TOK_ULT && op <= TOK_GT) {
4647 /* relationnal op: the result is an int */
4648 vtop->type.t = VT_INT;
4649 } else {
4650 vtop->type.t = t;
4655 /* generic itof for unsigned long long case */
4656 void gen_cvt_itof1(int t)
4658 GFuncContext gf;
4660 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
4661 (VT_LLONG | VT_UNSIGNED)) {
4663 gfunc_start(&gf, FUNC_CDECL);
4664 gfunc_param(&gf);
4665 if (t == VT_FLOAT)
4666 vpush_global_sym(&func_old_type, TOK___ulltof);
4667 else if (t == VT_DOUBLE)
4668 vpush_global_sym(&func_old_type, TOK___ulltod);
4669 else
4670 vpush_global_sym(&func_old_type, TOK___ulltold);
4671 gfunc_call(&gf);
4672 vpushi(0);
4673 vtop->r = REG_FRET;
4674 } else {
4675 gen_cvt_itof(t);
4679 /* generic ftoi for unsigned long long case */
4680 void gen_cvt_ftoi1(int t)
4682 GFuncContext gf;
4683 int st;
4685 if (t == (VT_LLONG | VT_UNSIGNED)) {
4686 /* not handled natively */
4687 gfunc_start(&gf, FUNC_CDECL);
4688 st = vtop->type.t & VT_BTYPE;
4689 gfunc_param(&gf);
4690 if (st == VT_FLOAT)
4691 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
4692 else if (st == VT_DOUBLE)
4693 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
4694 else
4695 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
4696 gfunc_call(&gf);
4697 vpushi(0);
4698 vtop->r = REG_IRET;
4699 vtop->r2 = REG_LRET;
4700 } else {
4701 gen_cvt_ftoi(t);
4705 /* force char or short cast */
4706 void force_charshort_cast(int t)
4708 int bits, dbt;
4709 dbt = t & VT_BTYPE;
4710 /* XXX: add optimization if lvalue : just change type and offset */
4711 if (dbt == VT_BYTE)
4712 bits = 8;
4713 else
4714 bits = 16;
4715 if (t & VT_UNSIGNED) {
4716 vpushi((1 << bits) - 1);
4717 gen_op('&');
4718 } else {
4719 bits = 32 - bits;
4720 vpushi(bits);
4721 gen_op(TOK_SHL);
4722 vpushi(bits);
4723 gen_op(TOK_SAR);
4727 /* cast 'vtop' to 'type' */
4728 static void gen_cast(CType *type)
4730 int sbt, dbt, sf, df, c;
4732 /* special delayed cast for char/short */
4733 /* XXX: in some cases (multiple cascaded casts), it may still
4734 be incorrect */
4735 if (vtop->r & VT_MUSTCAST) {
4736 vtop->r &= ~VT_MUSTCAST;
4737 force_charshort_cast(vtop->type.t);
4740 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
4741 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
4743 if (sbt != dbt && !nocode_wanted) {
4744 sf = is_float(sbt);
4745 df = is_float(dbt);
4746 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4747 if (sf && df) {
4748 /* convert from fp to fp */
4749 if (c) {
4750 /* constant case: we can do it now */
4751 /* XXX: in ISOC, cannot do it if error in convert */
4752 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
4753 vtop->c.f = (float)vtop->c.d;
4754 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
4755 vtop->c.f = (float)vtop->c.ld;
4756 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
4757 vtop->c.d = (double)vtop->c.f;
4758 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
4759 vtop->c.d = (double)vtop->c.ld;
4760 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
4761 vtop->c.ld = (long double)vtop->c.f;
4762 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
4763 vtop->c.ld = (long double)vtop->c.d;
4764 } else {
4765 /* non constant case: generate code */
4766 gen_cvt_ftof(dbt);
4768 } else if (df) {
4769 /* convert int to fp */
4770 if (c) {
4771 switch(sbt) {
4772 case VT_LLONG | VT_UNSIGNED:
4773 case VT_LLONG:
4774 /* XXX: add const cases for long long */
4775 goto do_itof;
4776 case VT_INT | VT_UNSIGNED:
4777 switch(dbt) {
4778 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
4779 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
4780 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
4782 break;
4783 default:
4784 switch(dbt) {
4785 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
4786 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
4787 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
4789 break;
4791 } else {
4792 do_itof:
4793 gen_cvt_itof1(dbt);
4795 } else if (sf) {
4796 /* convert fp to int */
4797 /* we handle char/short/etc... with generic code */
4798 if (dbt != (VT_INT | VT_UNSIGNED) &&
4799 dbt != (VT_LLONG | VT_UNSIGNED) &&
4800 dbt != VT_LLONG)
4801 dbt = VT_INT;
4802 if (c) {
4803 switch(dbt) {
4804 case VT_LLONG | VT_UNSIGNED:
4805 case VT_LLONG:
4806 /* XXX: add const cases for long long */
4807 goto do_ftoi;
4808 case VT_INT | VT_UNSIGNED:
4809 switch(sbt) {
4810 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
4811 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
4812 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
4814 break;
4815 default:
4816 /* int case */
4817 switch(sbt) {
4818 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
4819 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
4820 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
4822 break;
4824 } else {
4825 do_ftoi:
4826 gen_cvt_ftoi1(dbt);
4828 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
4829 /* additionnal cast for char/short/bool... */
4830 vtop->type.t = dbt;
4831 gen_cast(type);
4833 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
4834 if ((sbt & VT_BTYPE) != VT_LLONG) {
4835 /* scalar to long long */
4836 if (c) {
4837 if (sbt == (VT_INT | VT_UNSIGNED))
4838 vtop->c.ll = vtop->c.ui;
4839 else
4840 vtop->c.ll = vtop->c.i;
4841 } else {
4842 /* machine independant conversion */
4843 gv(RC_INT);
4844 /* generate high word */
4845 if (sbt == (VT_INT | VT_UNSIGNED)) {
4846 vpushi(0);
4847 gv(RC_INT);
4848 } else {
4849 gv_dup();
4850 vpushi(31);
4851 gen_op(TOK_SAR);
4853 /* patch second register */
4854 vtop[-1].r2 = vtop->r;
4855 vpop();
4858 } else if (dbt == VT_BOOL) {
4859 /* scalar to bool */
4860 vpushi(0);
4861 gen_op(TOK_NE);
4862 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
4863 (dbt & VT_BTYPE) == VT_SHORT) {
4864 force_charshort_cast(dbt);
4865 } else if ((dbt & VT_BTYPE) == VT_INT) {
4866 /* scalar to int */
4867 if (sbt == VT_LLONG) {
4868 /* from long long: just take low order word */
4869 lexpand();
4870 vpop();
4872 /* if lvalue and single word type, nothing to do because
4873 the lvalue already contains the real type size (see
4874 VT_LVAL_xxx constants) */
4877 vtop->type = *type;
4880 /* return type size. Put alignment at 'a' */
4881 int type_size(CType *type, int *a)
4883 Sym *s;
4884 int bt;
4886 bt = type->t & VT_BTYPE;
4887 if (bt == VT_STRUCT) {
4888 /* struct/union */
4889 s = type->ref;
4890 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
4891 return s->c;
4892 } else if (bt == VT_PTR) {
4893 if (type->t & VT_ARRAY) {
4894 s = type->ref;
4895 return type_size(&s->type, a) * s->c;
4896 } else {
4897 *a = PTR_SIZE;
4898 return PTR_SIZE;
4900 } else if (bt == VT_LDOUBLE) {
4901 *a = LDOUBLE_ALIGN;
4902 return LDOUBLE_SIZE;
4903 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
4904 *a = 8;
4905 return 8;
4906 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
4907 *a = 4;
4908 return 4;
4909 } else if (bt == VT_SHORT) {
4910 *a = 2;
4911 return 2;
4912 } else {
4913 /* char, void, function, _Bool */
4914 *a = 1;
4915 return 1;
4919 /* return the pointed type of t */
4920 static inline CType *pointed_type(CType *type)
4922 return &type->ref->type;
4925 /* modify type so that its it is a pointer to type. */
4926 static void mk_pointer(CType *type)
4928 Sym *s;
4929 s = sym_push(SYM_FIELD, type, 0, -1);
4930 type->t = VT_PTR | (type->t & ~VT_TYPE);
4931 type->ref = s;
4934 static int is_compatible_types(CType *type1, CType *type2)
4936 Sym *s1, *s2;
4937 int bt1, bt2, t1, t2;
4939 t1 = type1->t & VT_TYPE;
4940 t2 = type2->t & VT_TYPE;
4941 bt1 = t1 & VT_BTYPE;
4942 bt2 = t2 & VT_BTYPE;
4943 if (bt1 == VT_PTR) {
4944 type1 = pointed_type(type1);
4945 /* if function, then convert implicitely to function pointer */
4946 if (bt2 != VT_FUNC) {
4947 if (bt2 != VT_PTR)
4948 return 0;
4949 type2 = pointed_type(type2);
4951 /* void matches everything */
4952 /* XXX: not fully compliant */
4953 if ((type1->t & VT_TYPE) == VT_VOID || (type2->t & VT_TYPE) == VT_VOID)
4954 return 1;
4955 return is_compatible_types(type1, type2);
4956 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
4957 return (t2 == t1);
4958 } else if (bt1 == VT_FUNC) {
4959 if (bt2 != VT_FUNC)
4960 return 0;
4961 s1 = type1->ref;
4962 s2 = type2->ref;
4963 if (!is_compatible_types(&s1->type, &s2->type))
4964 return 0;
4965 /* XXX: not complete */
4966 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
4967 return 1;
4968 if (s1->c != s2->c)
4969 return 0;
4970 while (s1 != NULL) {
4971 if (s2 == NULL)
4972 return 0;
4973 if (!is_compatible_types(&s1->type, &s2->type))
4974 return 0;
4975 s1 = s1->next;
4976 s2 = s2->next;
4978 if (s2)
4979 return 0;
4980 return 1;
4981 } else {
4982 /* XXX: not complete */
4983 return 1;
4987 /* print a type. If 'varstr' is not NULL, then the variable is also
4988 printed in the type */
4989 /* XXX: union */
4990 /* XXX: add array and function pointers */
4991 void type_to_str(char *buf, int buf_size,
4992 CType *type, const char *varstr)
4994 int bt, v, t;
4995 Sym *s, *sa;
4996 char buf1[256];
4997 const char *tstr;
4999 t = type->t & VT_TYPE;
5000 bt = t & VT_BTYPE;
5001 buf[0] = '\0';
5002 if (t & VT_UNSIGNED)
5003 pstrcat(buf, buf_size, "unsigned ");
5004 switch(bt) {
5005 case VT_VOID:
5006 tstr = "void";
5007 goto add_tstr;
5008 case VT_BOOL:
5009 tstr = "_Bool";
5010 goto add_tstr;
5011 case VT_BYTE:
5012 tstr = "char";
5013 goto add_tstr;
5014 case VT_SHORT:
5015 tstr = "short";
5016 goto add_tstr;
5017 case VT_INT:
5018 tstr = "int";
5019 goto add_tstr;
5020 case VT_LONG:
5021 tstr = "long";
5022 goto add_tstr;
5023 case VT_LLONG:
5024 tstr = "long long";
5025 goto add_tstr;
5026 case VT_FLOAT:
5027 tstr = "float";
5028 goto add_tstr;
5029 case VT_DOUBLE:
5030 tstr = "double";
5031 goto add_tstr;
5032 case VT_LDOUBLE:
5033 tstr = "long double";
5034 add_tstr:
5035 pstrcat(buf, buf_size, tstr);
5036 break;
5037 case VT_ENUM:
5038 case VT_STRUCT:
5039 if (bt == VT_STRUCT)
5040 tstr = "struct ";
5041 else
5042 tstr = "enum ";
5043 pstrcat(buf, buf_size, tstr);
5044 v = type->ref->v;
5045 if (v >= SYM_FIRST_ANOM)
5046 pstrcat(buf, buf_size, "<anonymous>");
5047 else
5048 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5049 break;
5050 case VT_FUNC:
5051 s = type->ref;
5052 type_to_str(buf, buf_size, &s->type, varstr);
5053 pstrcat(buf, buf_size, "(");
5054 sa = s->next;
5055 while (sa != NULL) {
5056 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5057 pstrcat(buf, buf_size, buf1);
5058 sa = sa->next;
5059 if (sa)
5060 pstrcat(buf, buf_size, ", ");
5062 pstrcat(buf, buf_size, ")");
5063 goto no_var;
5064 case VT_PTR:
5065 s = type->ref;
5066 pstrcpy(buf1, sizeof(buf1), "*");
5067 if (varstr)
5068 pstrcat(buf1, sizeof(buf1), varstr);
5069 type_to_str(buf, buf_size, &s->type, buf1);
5070 goto no_var;
5072 if (varstr) {
5073 pstrcat(buf, buf_size, " ");
5074 pstrcat(buf, buf_size, varstr);
5076 no_var: ;
5079 /* verify type compatibility to store vtop in 'dt' type, and generate
5080 casts if needed. */
5081 void gen_assign_cast(CType *dt)
5083 CType *st;
5084 char buf1[256], buf2[256];
5086 st = &vtop->type; /* source type */
5087 if ((dt->t & VT_BTYPE) == VT_PTR) {
5088 /* special cases for pointers */
5089 /* a function is implicitely a function pointer */
5090 if ((st->t & VT_BTYPE) == VT_FUNC) {
5091 if (!is_compatible_types(pointed_type(dt), st))
5092 goto error;
5093 else
5094 goto type_ok;
5096 /* '0' can also be a pointer */
5097 if ((st->t & VT_BTYPE) == VT_INT &&
5098 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) &&
5099 vtop->c.i == 0)
5100 goto type_ok;
5102 if (!is_compatible_types(dt, st)) {
5103 error:
5104 type_to_str(buf1, sizeof(buf1), st, NULL);
5105 type_to_str(buf2, sizeof(buf2), dt, NULL);
5106 error("cannot cast '%s' to '%s'", buf1, buf2);
5108 type_ok:
5109 gen_cast(dt);
5112 /* store vtop in lvalue pushed on stack */
5113 void vstore(void)
5115 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5116 GFuncContext gf;
5118 ft = vtop[-1].type.t;
5119 sbt = vtop->type.t & VT_BTYPE;
5120 dbt = ft & VT_BTYPE;
5121 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5122 (sbt == VT_INT && dbt == VT_SHORT)) {
5123 /* optimize char/short casts */
5124 delayed_cast = VT_MUSTCAST;
5125 vtop->type.t = ft & VT_TYPE;
5126 } else {
5127 delayed_cast = 0;
5128 gen_assign_cast(&vtop[-1].type);
5131 if (sbt == VT_STRUCT) {
5132 /* if structure, only generate pointer */
5133 /* structure assignment : generate memcpy */
5134 /* XXX: optimize if small size */
5135 if (!nocode_wanted) {
5136 vdup();
5137 gfunc_start(&gf, FUNC_CDECL);
5138 /* type size */
5139 size = type_size(&vtop->type, &align);
5140 vpushi(size);
5141 gfunc_param(&gf);
5142 /* source */
5143 vtop->type.t = VT_INT;
5144 gaddrof();
5145 gfunc_param(&gf);
5146 /* destination */
5147 vswap();
5148 vtop->type.t = VT_INT;
5149 gaddrof();
5150 gfunc_param(&gf);
5152 save_regs(0);
5153 vpush_global_sym(&func_old_type, TOK_memcpy);
5154 gfunc_call(&gf);
5155 } else {
5156 vswap();
5157 vpop();
5159 /* leave source on stack */
5160 } else if (ft & VT_BITFIELD) {
5161 /* bitfield store handling */
5162 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5163 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5164 /* remove bit field info to avoid loops */
5165 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5167 /* duplicate destination */
5168 vdup();
5169 vtop[-1] = vtop[-2];
5171 /* mask and shift source */
5172 vpushi((1 << bit_size) - 1);
5173 gen_op('&');
5174 vpushi(bit_pos);
5175 gen_op(TOK_SHL);
5176 /* load destination, mask and or with source */
5177 vswap();
5178 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5179 gen_op('&');
5180 gen_op('|');
5181 /* store result */
5182 vstore();
5183 } else {
5184 #ifdef CONFIG_TCC_BCHECK
5185 /* bound check case */
5186 if (vtop[-1].r & VT_MUSTBOUND) {
5187 vswap();
5188 gbound();
5189 vswap();
5191 #endif
5192 if (!nocode_wanted) {
5193 rc = RC_INT;
5194 if (is_float(ft))
5195 rc = RC_FLOAT;
5196 r = gv(rc); /* generate value */
5197 /* if lvalue was saved on stack, must read it */
5198 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5199 SValue sv;
5200 t = get_reg(RC_INT);
5201 sv.type.t = VT_INT;
5202 sv.r = VT_LOCAL | VT_LVAL;
5203 sv.c.ul = vtop[-1].c.ul;
5204 load(t, &sv);
5205 vtop[-1].r = t | VT_LVAL;
5207 store(r, vtop - 1);
5208 /* two word case handling : store second register at word + 4 */
5209 if ((ft & VT_BTYPE) == VT_LLONG) {
5210 vswap();
5211 /* convert to int to increment easily */
5212 vtop->type.t = VT_INT;
5213 gaddrof();
5214 vpushi(4);
5215 gen_op('+');
5216 vtop->r |= VT_LVAL;
5217 vswap();
5218 /* XXX: it works because r2 is spilled last ! */
5219 store(vtop->r2, vtop - 1);
5222 vswap();
5223 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5224 vtop->r |= delayed_cast;
5228 /* post defines POST/PRE add. c is the token ++ or -- */
5229 void inc(int post, int c)
5231 test_lvalue();
5232 vdup(); /* save lvalue */
5233 if (post) {
5234 gv_dup(); /* duplicate value */
5235 vrotb(3);
5236 vrotb(3);
5238 /* add constant */
5239 vpushi(c - TOK_MID);
5240 gen_op('+');
5241 vstore(); /* store value */
5242 if (post)
5243 vpop(); /* if post op, return saved value */
5246 /* Parse GNUC __attribute__ extension. Currently, the following
5247 extensions are recognized:
5248 - aligned(n) : set data/function alignment.
5249 - section(x) : generate data/code in this section.
5250 - unused : currently ignored, but may be used someday.
5252 void parse_attribute(AttributeDef *ad)
5254 int t, n;
5256 next();
5257 skip('(');
5258 skip('(');
5259 while (tok != ')') {
5260 if (tok < TOK_IDENT)
5261 expect("attribute name");
5262 t = tok;
5263 next();
5264 switch(t) {
5265 case TOK_SECTION:
5266 case TOK___SECTION__:
5267 skip('(');
5268 if (tok != TOK_STR)
5269 expect("section name");
5270 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
5271 next();
5272 skip(')');
5273 break;
5274 case TOK_ALIGNED:
5275 case TOK___ALIGNED__:
5276 skip('(');
5277 n = expr_const();
5278 if (n <= 0 || (n & (n - 1)) != 0)
5279 error("alignment must be a positive power of two");
5280 ad->aligned = n;
5281 skip(')');
5282 break;
5283 case TOK_UNUSED:
5284 case TOK___UNUSED__:
5285 /* currently, no need to handle it because tcc does not
5286 track unused objects */
5287 break;
5288 case TOK_NORETURN:
5289 case TOK___NORETURN__:
5290 /* currently, no need to handle it because tcc does not
5291 track unused objects */
5292 break;
5293 case TOK_CDECL:
5294 case TOK___CDECL:
5295 case TOK___CDECL__:
5296 ad->func_call = FUNC_CDECL;
5297 break;
5298 case TOK_STDCALL:
5299 case TOK___STDCALL:
5300 case TOK___STDCALL__:
5301 ad->func_call = FUNC_STDCALL;
5302 break;
5303 default:
5304 warning("'%s' attribute ignored", get_tok_str(t, NULL));
5305 /* skip parameters */
5306 /* XXX: skip parenthesis too */
5307 if (tok == '(') {
5308 next();
5309 while (tok != ')' && tok != -1)
5310 next();
5311 next();
5313 break;
5315 if (tok != ',')
5316 break;
5317 next();
5319 skip(')');
5320 skip(')');
5323 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
5324 static void struct_decl(CType *type, int u)
5326 int a, v, size, align, maxalign, c, offset;
5327 int bit_size, bit_pos, bsize, bt, lbit_pos;
5328 Sym *s, *ss, **ps;
5329 AttributeDef ad;
5330 CType type1, btype;
5332 a = tok; /* save decl type */
5333 next();
5334 if (tok != '{') {
5335 v = tok;
5336 next();
5337 /* struct already defined ? return it */
5338 /* XXX: check consistency */
5339 s = struct_find(v);
5340 if (s) {
5341 if (s->type.t != a)
5342 error("invalid type");
5343 goto do_decl;
5345 } else {
5346 v = anon_sym++;
5348 type1.t = a;
5349 s = sym_push(v | SYM_STRUCT, &type1, 0, 0);
5350 /* put struct/union/enum name in type */
5351 do_decl:
5352 type->t = u;
5353 type->ref = s;
5355 if (tok == '{') {
5356 next();
5357 if (s->c)
5358 error("struct/union/enum already defined");
5359 /* cannot be empty */
5360 c = 0;
5361 maxalign = 0;
5362 ps = &s->next;
5363 bit_pos = 0;
5364 offset = 0;
5365 while (1) {
5366 if (a == TOK_ENUM) {
5367 v = tok;
5368 next();
5369 if (tok == '=') {
5370 next();
5371 c = expr_const();
5373 /* enum symbols have static storage */
5374 ss = sym_push(v, &int_type, VT_CONST, c);
5375 ss->type.t |= VT_STATIC;
5376 if (tok == ',')
5377 next();
5378 c++;
5379 } else {
5380 parse_btype(&btype, &ad);
5381 while (1) {
5382 bit_size = -1;
5383 v = 0;
5384 type1 = btype;
5385 if (tok != ':') {
5386 type_decl(&type1, &ad, &v, TYPE_DIRECT);
5387 if ((type1.t & VT_BTYPE) == VT_FUNC ||
5388 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
5389 error("invalid type for '%s'",
5390 get_tok_str(v, NULL));
5392 if (tok == ':') {
5393 next();
5394 bit_size = expr_const();
5395 /* XXX: handle v = 0 case for messages */
5396 if (bit_size < 0)
5397 error("negative width in bit-field '%s'",
5398 get_tok_str(v, NULL));
5399 if (v && bit_size == 0)
5400 error("zero width for bit-field '%s'",
5401 get_tok_str(v, NULL));
5403 size = type_size(&type1, &align);
5404 lbit_pos = 0;
5405 if (bit_size >= 0) {
5406 bt = type1.t & VT_BTYPE;
5407 if (bt != VT_INT &&
5408 bt != VT_BYTE &&
5409 bt != VT_SHORT)
5410 error("bitfields must have scalar type");
5411 bsize = size * 8;
5412 if (bit_size > bsize) {
5413 error("width of '%s' exceeds its type",
5414 get_tok_str(v, NULL));
5415 } else if (bit_size == bsize) {
5416 /* no need for bit fields */
5417 bit_pos = 0;
5418 } else if (bit_size == 0) {
5419 /* XXX: what to do if only padding in a
5420 structure ? */
5421 /* zero size: means to pad */
5422 if (bit_pos > 0)
5423 bit_pos = bsize;
5424 } else {
5425 /* we do not have enough room ? */
5426 if ((bit_pos + bit_size) > bsize)
5427 bit_pos = 0;
5428 lbit_pos = bit_pos;
5429 /* XXX: handle LSB first */
5430 type1.t |= VT_BITFIELD |
5431 (bit_pos << VT_STRUCT_SHIFT) |
5432 (bit_size << (VT_STRUCT_SHIFT + 6));
5433 bit_pos += bit_size;
5435 } else {
5436 bit_pos = 0;
5438 if (v) {
5439 /* add new memory data only if starting
5440 bit field */
5441 if (lbit_pos == 0) {
5442 if (a == TOK_STRUCT) {
5443 c = (c + align - 1) & -align;
5444 offset = c;
5445 c += size;
5446 } else {
5447 offset = 0;
5448 if (size > c)
5449 c = size;
5451 if (align > maxalign)
5452 maxalign = align;
5454 #if 0
5455 printf("add field %s offset=%d",
5456 get_tok_str(v, NULL), offset);
5457 if (type1.t & VT_BITFIELD) {
5458 printf(" pos=%d size=%d",
5459 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
5460 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
5462 printf("\n");
5463 #endif
5464 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
5465 *ps = ss;
5466 ps = &ss->next;
5468 if (tok == ';' || tok == -1)
5469 break;
5470 skip(',');
5472 skip(';');
5474 if (tok == '}')
5475 break;
5477 skip('}');
5478 /* size for struct/union, dummy for enum */
5479 s->c = (c + maxalign - 1) & -maxalign;
5483 /* return 0 if no type declaration. otherwise, return the basic type
5484 and skip it.
5486 static int parse_btype(CType *type, AttributeDef *ad)
5488 int t, u, type_found;
5489 Sym *s;
5490 CType type1;
5492 memset(ad, 0, sizeof(AttributeDef));
5493 type_found = 0;
5494 t = 0;
5495 while(1) {
5496 switch(tok) {
5497 /* basic types */
5498 case TOK_CHAR:
5499 u = VT_BYTE;
5500 basic_type:
5501 next();
5502 basic_type1:
5503 if ((t & VT_BTYPE) != 0)
5504 error("too many basic types");
5505 t |= u;
5506 break;
5507 case TOK_VOID:
5508 u = VT_VOID;
5509 goto basic_type;
5510 case TOK_SHORT:
5511 u = VT_SHORT;
5512 goto basic_type;
5513 case TOK_INT:
5514 next();
5515 break;
5516 case TOK_LONG:
5517 next();
5518 if ((t & VT_BTYPE) == VT_DOUBLE) {
5519 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
5520 } else if ((t & VT_BTYPE) == VT_LONG) {
5521 t = (t & ~VT_BTYPE) | VT_LLONG;
5522 } else {
5523 u = VT_LONG;
5524 goto basic_type1;
5526 break;
5527 case TOK_BOOL:
5528 u = VT_BOOL;
5529 goto basic_type;
5530 case TOK_FLOAT:
5531 u = VT_FLOAT;
5532 goto basic_type;
5533 case TOK_DOUBLE:
5534 next();
5535 if ((t & VT_BTYPE) == VT_LONG) {
5536 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
5537 } else {
5538 u = VT_DOUBLE;
5539 goto basic_type1;
5541 break;
5542 case TOK_ENUM:
5543 struct_decl(&type1, VT_ENUM);
5544 basic_type2:
5545 u = type1.t;
5546 type->ref = type1.ref;
5547 goto basic_type1;
5548 case TOK_STRUCT:
5549 case TOK_UNION:
5550 struct_decl(&type1, VT_STRUCT);
5551 goto basic_type2;
5553 /* type modifiers */
5554 case TOK_CONST:
5555 case TOK_VOLATILE:
5556 case TOK_REGISTER:
5557 case TOK_SIGNED:
5558 case TOK___SIGNED__:
5559 case TOK_AUTO:
5560 case TOK_INLINE:
5561 case TOK___INLINE__:
5562 case TOK_RESTRICT:
5563 next();
5564 break;
5565 case TOK_UNSIGNED:
5566 t |= VT_UNSIGNED;
5567 next();
5568 break;
5570 /* storage */
5571 case TOK_EXTERN:
5572 t |= VT_EXTERN;
5573 next();
5574 break;
5575 case TOK_STATIC:
5576 t |= VT_STATIC;
5577 next();
5578 break;
5579 case TOK_TYPEDEF:
5580 t |= VT_TYPEDEF;
5581 next();
5582 break;
5583 /* GNUC attribute */
5584 case TOK___ATTRIBUTE__:
5585 parse_attribute(ad);
5586 break;
5587 /* GNUC typeof */
5588 case TOK_TYPEOF:
5589 next();
5590 parse_expr_type(&type1);
5591 goto basic_type2;
5592 default:
5593 s = sym_find(tok);
5594 if (!s || !(s->type.t & VT_TYPEDEF))
5595 goto the_end;
5596 t |= (s->type.t & ~VT_TYPEDEF);
5597 type->ref = s->type.ref;
5598 next();
5599 break;
5601 type_found = 1;
5603 the_end:
5604 /* long is never used as type */
5605 if ((t & VT_BTYPE) == VT_LONG)
5606 t = (t & ~VT_BTYPE) | VT_INT;
5607 type->t = t;
5608 return type_found;
5611 static void post_type(CType *type, AttributeDef *ad)
5613 int n, l, t1;
5614 Sym **plast, *s, *first;
5615 AttributeDef ad1;
5616 CType pt;
5618 if (tok == '(') {
5619 /* function declaration */
5620 next();
5621 l = 0;
5622 first = NULL;
5623 plast = &first;
5624 while (tok != ')') {
5625 /* read param name and compute offset */
5626 if (l != FUNC_OLD) {
5627 if (!parse_btype(&pt, &ad1)) {
5628 if (l) {
5629 error("invalid type");
5630 } else {
5631 l = FUNC_OLD;
5632 goto old_proto;
5635 l = FUNC_NEW;
5636 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
5637 break;
5638 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
5639 if ((pt.t & VT_BTYPE) == VT_VOID)
5640 error("parameter declared as void");
5641 } else {
5642 old_proto:
5643 n = tok;
5644 pt.t = VT_INT;
5645 next();
5647 /* array must be transformed to pointer according to ANSI C */
5648 pt.t &= ~VT_ARRAY;
5649 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
5650 *plast = s;
5651 plast = &s->next;
5652 if (tok == ',') {
5653 next();
5654 if (l == FUNC_NEW && tok == TOK_DOTS) {
5655 l = FUNC_ELLIPSIS;
5656 next();
5657 break;
5661 /* if no parameters, then old type prototype */
5662 if (l == 0)
5663 l = FUNC_OLD;
5664 skip(')');
5665 t1 = type->t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5666 type->t &= ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5667 post_type(type, ad);
5668 /* we push a anonymous symbol which will contain the function prototype */
5669 s = sym_push(SYM_FIELD, type, ad->func_call, l);
5670 s->next = first;
5671 type->t = t1 | VT_FUNC;
5672 type->ref = s;
5673 } else if (tok == '[') {
5674 /* array definition */
5675 next();
5676 n = -1;
5677 if (tok != ']') {
5678 n = expr_const();
5679 if (n < 0)
5680 error("invalid array size");
5682 skip(']');
5683 /* parse next post type */
5684 t1 = type->t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5685 type->t &= ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5686 post_type(type, ad);
5688 /* we push a anonymous symbol which will contain the array
5689 element type */
5690 s = sym_push(SYM_FIELD, type, 0, n);
5691 type->t = t1 | VT_ARRAY | VT_PTR;
5692 type->ref = s;
5696 /* Parse a type declaration (except basic type), and return the type
5697 in 'type'. 'td' is a bitmask indicating which kind of type decl is
5698 expected. 'type' should contain the basic type. 'ad' is the
5699 attribute definition of the basic type. It can be modified by
5700 type_decl().
5702 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
5704 Sym *s;
5705 CType type1, *type2;
5707 while (tok == '*') {
5708 next();
5709 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
5710 next();
5711 mk_pointer(type);
5714 /* recursive type */
5715 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
5716 type1.t = 0; /* XXX: same as int */
5717 if (tok == '(') {
5718 next();
5719 /* XXX: this is not correct to modify 'ad' at this point, but
5720 the syntax is not clear */
5721 if (tok == TOK___ATTRIBUTE__)
5722 parse_attribute(ad);
5723 type_decl(&type1, ad, v, td);
5724 skip(')');
5725 } else {
5726 /* type identifier */
5727 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
5728 *v = tok;
5729 next();
5730 } else {
5731 if (!(td & TYPE_ABSTRACT))
5732 expect("identifier");
5733 *v = 0;
5736 post_type(type, ad);
5737 if (tok == TOK___ATTRIBUTE__)
5738 parse_attribute(ad);
5739 if (!type1.t)
5740 return;
5741 /* append type at the end of type1 */
5742 type2 = &type1;
5743 for(;;) {
5744 s = type2->ref;
5745 type2 = &s->type;
5746 if (!type2->t) {
5747 *type2 = *type;
5748 break;
5751 *type = type1;
5754 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
5755 static int lvalue_type(int t)
5757 int bt, r;
5758 r = VT_LVAL;
5759 bt = t & VT_BTYPE;
5760 if (bt == VT_BYTE)
5761 r |= VT_LVAL_BYTE;
5762 else if (bt == VT_SHORT)
5763 r |= VT_LVAL_SHORT;
5764 else
5765 return r;
5766 if (t & VT_UNSIGNED)
5767 r |= VT_LVAL_UNSIGNED;
5768 return r;
5771 /* indirection with full error checking and bound check */
5772 static void indir(void)
5774 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
5775 expect("pointer");
5776 if ((vtop->r & VT_LVAL) && !nocode_wanted)
5777 gv(RC_INT);
5778 vtop->type = *pointed_type(&vtop->type);
5779 /* an array is never an lvalue */
5780 if (!(vtop->type.t & VT_ARRAY)) {
5781 vtop->r |= lvalue_type(vtop->type.t);
5782 /* if bound checking, the referenced pointer must be checked */
5783 if (do_bounds_check)
5784 vtop->r |= VT_MUSTBOUND;
5788 /* pass a parameter to a function and do type checking and casting */
5789 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
5791 int func_type;
5792 CType type;
5794 func_type = func->c;
5795 if (func_type == FUNC_OLD ||
5796 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
5797 /* default casting : only need to convert float to double */
5798 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
5799 type.t = VT_DOUBLE;
5800 gen_cast(&type);
5802 } else if (arg == NULL) {
5803 error("too many arguments to function");
5804 } else {
5805 gen_assign_cast(&arg->type);
5807 if (!nocode_wanted) {
5808 gfunc_param(gf);
5809 } else {
5810 vpop();
5814 /* parse an expression of the form '(type)' or '(expr)' and return its
5815 type */
5816 static void parse_expr_type(CType *type)
5818 int n;
5819 AttributeDef ad;
5821 skip('(');
5822 if (parse_btype(type, &ad)) {
5823 type_decl(type, &ad, &n, TYPE_ABSTRACT);
5824 } else {
5825 expr_type(type);
5827 skip(')');
5830 static void vpush_tokc(int t)
5832 CType type;
5833 type.t = t;
5834 vsetc(&type, VT_CONST, &tokc);
5837 static void unary(void)
5839 int n, t, align, size, r;
5840 CType type;
5841 Sym *s;
5842 GFuncContext gf;
5843 AttributeDef ad;
5845 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
5846 vpushi(tokc.i);
5847 next();
5848 } else if (tok == TOK_CUINT) {
5849 vpush_tokc(VT_INT | VT_UNSIGNED);
5850 next();
5851 } else if (tok == TOK_CLLONG) {
5852 vpush_tokc(VT_LLONG);
5853 next();
5854 } else if (tok == TOK_CULLONG) {
5855 vpush_tokc(VT_LLONG | VT_UNSIGNED);
5856 next();
5857 } else if (tok == TOK_CFLOAT) {
5858 vpush_tokc(VT_FLOAT);
5859 next();
5860 } else if (tok == TOK_CDOUBLE) {
5861 vpush_tokc(VT_DOUBLE);
5862 next();
5863 } else if (tok == TOK_CLDOUBLE) {
5864 vpush_tokc(VT_LDOUBLE);
5865 next();
5866 } else if (tok == TOK___FUNC__ || (tok == TOK___FUNCTION__ && gnu_ext)) {
5867 void *ptr;
5868 int len;
5869 /* special function name identifier */
5871 len = strlen(funcname) + 1;
5872 /* generate char[len] type */
5873 type.t = VT_BYTE;
5874 mk_pointer(&type);
5875 type.t |= VT_ARRAY;
5876 type.ref->c = len;
5877 vpush_ref(&type, data_section, data_section->data_offset, len);
5878 ptr = section_ptr_add(data_section, len);
5879 memcpy(ptr, funcname, len);
5880 next();
5881 } else if (tok == TOK_LSTR) {
5882 t = VT_INT;
5883 goto str_init;
5884 } else if (tok == TOK_STR) {
5885 /* string parsing */
5886 t = VT_BYTE;
5887 str_init:
5888 type.t = t;
5889 mk_pointer(&type);
5890 type.t |= VT_ARRAY;
5891 memset(&ad, 0, sizeof(AttributeDef));
5892 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
5893 } else {
5894 t = tok;
5895 next();
5896 if (t == '(') {
5897 /* cast ? */
5898 if (parse_btype(&type, &ad)) {
5899 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
5900 skip(')');
5901 /* check ISOC99 compound literal */
5902 if (tok == '{') {
5903 /* data is allocated locally by default */
5904 if (global_expr)
5905 r = VT_CONST;
5906 else
5907 r = VT_LOCAL;
5908 /* all except arrays are lvalues */
5909 if (!(type.t & VT_ARRAY))
5910 r |= lvalue_type(type.t);
5911 memset(&ad, 0, sizeof(AttributeDef));
5912 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
5913 } else {
5914 unary();
5915 gen_cast(&type);
5917 } else {
5918 gexpr();
5919 skip(')');
5921 } else if (t == '*') {
5922 unary();
5923 indir();
5924 } else if (t == '&') {
5925 unary();
5926 /* functions names must be treated as function pointers,
5927 except for unary '&' and sizeof. Since we consider that
5928 functions are not lvalues, we only have to handle it
5929 there and in function calls. */
5930 /* arrays can also be used although they are not lvalues */
5931 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
5932 !(vtop->type.t & VT_ARRAY))
5933 test_lvalue();
5934 mk_pointer(&vtop->type);
5935 gaddrof();
5936 } else if (t == '!') {
5937 unary();
5938 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
5939 vtop->c.i = !vtop->c.i;
5940 else if ((vtop->r & VT_VALMASK) == VT_CMP)
5941 vtop->c.i = vtop->c.i ^ 1;
5942 else
5943 vseti(VT_JMP, gtst(1, 0));
5944 } else if (t == '~') {
5945 unary();
5946 vpushi(-1);
5947 gen_op('^');
5948 } else if (t == '+') {
5949 /* in order to force cast, we add zero */
5950 unary();
5951 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
5952 error("pointer not accepted for unary plus");
5953 vpushi(0);
5954 gen_op('+');
5955 } else if (t == TOK_SIZEOF || t == TOK_ALIGNOF) {
5956 if (tok == '(') {
5957 parse_expr_type(&type);
5958 } else {
5959 unary_type(&type);
5961 size = type_size(&type, &align);
5962 if (t == TOK_SIZEOF)
5963 vpushi(size);
5964 else
5965 vpushi(align);
5966 } else if (t == TOK_INC || t == TOK_DEC) {
5967 unary();
5968 inc(0, t);
5969 } else if (t == '-') {
5970 vpushi(0);
5971 unary();
5972 gen_op('-');
5973 } else if (t == TOK_LAND && gnu_ext) {
5974 /* allow to take the address of a label */
5975 if (tok < TOK_UIDENT)
5976 expect("label identifier");
5977 s = label_find(tok);
5978 if (!s) {
5979 s = label_push(tok, LABEL_FORWARD);
5981 if (!s->type.t) {
5982 s->type.t = VT_VOID;
5983 mk_pointer(&s->type);
5984 s->type.t |= VT_STATIC;
5986 vset(&s->type, VT_CONST | VT_SYM, 0);
5987 vtop->sym = s;
5988 next();
5989 } else {
5990 if (t < TOK_UIDENT)
5991 expect("identifier");
5992 s = sym_find(t);
5993 if (!s) {
5994 if (tok != '(')
5995 error("'%s' undeclared", get_tok_str(t, NULL));
5996 /* for simple function calls, we tolerate undeclared
5997 external reference to int() function */
5998 s = external_global_sym(t, &func_old_type, 0);
6000 vset(&s->type, s->r, s->c);
6001 /* if forward reference, we must point to s */
6002 if (vtop->r & VT_SYM) {
6003 vtop->sym = s;
6004 vtop->c.ul = 0;
6009 /* post operations */
6010 while (1) {
6011 if (tok == TOK_INC || tok == TOK_DEC) {
6012 inc(1, tok);
6013 next();
6014 } else if (tok == '.' || tok == TOK_ARROW) {
6015 /* field */
6016 if (tok == TOK_ARROW)
6017 indir();
6018 test_lvalue();
6019 gaddrof();
6020 next();
6021 /* expect pointer on structure */
6022 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6023 expect("struct or union");
6024 s = vtop->type.ref;
6025 /* find field */
6026 tok |= SYM_FIELD;
6027 while ((s = s->next) != NULL) {
6028 if (s->v == tok)
6029 break;
6031 if (!s)
6032 error("field not found");
6033 /* add field offset to pointer */
6034 vtop->type = char_pointer_type; /* change type to 'char *' */
6035 vpushi(s->c);
6036 gen_op('+');
6037 /* change type to field type, and set to lvalue */
6038 vtop->type = s->type;
6039 /* an array is never an lvalue */
6040 if (!(vtop->type.t & VT_ARRAY)) {
6041 vtop->r |= lvalue_type(vtop->type.t);
6042 /* if bound checking, the referenced pointer must be checked */
6043 if (do_bounds_check)
6044 vtop->r |= VT_MUSTBOUND;
6046 next();
6047 } else if (tok == '[') {
6048 next();
6049 gexpr();
6050 gen_op('+');
6051 indir();
6052 skip(']');
6053 } else if (tok == '(') {
6054 SValue ret;
6055 Sym *sa;
6057 /* function call */
6058 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
6059 /* pointer test (no array accepted) */
6060 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
6061 vtop->type = *pointed_type(&vtop->type);
6062 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
6063 goto error_func;
6064 } else {
6065 error_func:
6066 expect("function pointer");
6068 } else {
6069 vtop->r &= ~VT_LVAL; /* no lvalue */
6071 /* get return type */
6072 s = vtop->type.ref;
6073 if (!nocode_wanted) {
6074 save_regs(0); /* save used temporary registers */
6075 gfunc_start(&gf, s->r);
6077 next();
6078 sa = s->next; /* first parameter */
6079 #ifdef INVERT_FUNC_PARAMS
6081 int parlevel;
6082 Sym *args, *s1;
6083 ParseState saved_parse_state;
6084 TokenString str;
6086 /* read each argument and store it on a stack */
6087 args = NULL;
6088 if (tok != ')') {
6089 for(;;) {
6090 tok_str_new(&str);
6091 parlevel = 0;
6092 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
6093 tok != TOK_EOF) {
6094 if (tok == '(')
6095 parlevel++;
6096 else if (tok == ')')
6097 parlevel--;
6098 tok_str_add_tok(&str);
6099 next();
6101 tok_str_add(&str, -1); /* end of file added */
6102 tok_str_add(&str, 0);
6103 s1 = sym_push2(&args, 0, 0, (int)str.str);
6104 s1->next = sa; /* add reference to argument */
6105 if (sa)
6106 sa = sa->next;
6107 if (tok == ')')
6108 break;
6109 skip(',');
6113 /* now generate code in reverse order by reading the stack */
6114 save_parse_state(&saved_parse_state);
6115 while (args) {
6116 macro_ptr = (int *)args->c;
6117 next();
6118 expr_eq();
6119 if (tok != -1)
6120 expect("',' or ')'");
6121 gfunc_param_typed(&gf, s, args->next);
6122 s1 = args->prev;
6123 tok_str_free((int *)args->c);
6124 tcc_free(args);
6125 args = s1;
6127 restore_parse_state(&saved_parse_state);
6129 #endif
6130 /* compute first implicit argument if a structure is returned */
6131 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
6132 /* get some space for the returned structure */
6133 size = type_size(&s->type, &align);
6134 loc = (loc - size) & -align;
6135 ret.type = s->type;
6136 ret.r = VT_LOCAL | VT_LVAL;
6137 /* pass it as 'int' to avoid structure arg passing
6138 problems */
6139 vseti(VT_LOCAL, loc);
6140 ret.c = vtop->c;
6141 if (!nocode_wanted)
6142 gfunc_param(&gf);
6143 else
6144 vtop--;
6145 } else {
6146 ret.type = s->type;
6147 ret.r2 = VT_CONST;
6148 /* return in register */
6149 if (is_float(ret.type.t)) {
6150 ret.r = REG_FRET;
6151 } else {
6152 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
6153 ret.r2 = REG_LRET;
6154 ret.r = REG_IRET;
6156 ret.c.i = 0;
6158 #ifndef INVERT_FUNC_PARAMS
6159 if (tok != ')') {
6160 for(;;) {
6161 expr_eq();
6162 gfunc_param_typed(&gf, s, sa);
6163 if (sa)
6164 sa = sa->next;
6165 if (tok == ')')
6166 break;
6167 skip(',');
6170 #endif
6171 if (sa)
6172 error("too few arguments to function");
6173 skip(')');
6174 if (!nocode_wanted)
6175 gfunc_call(&gf);
6176 else
6177 vtop--;
6178 /* return value */
6179 vsetc(&ret.type, ret.r, &ret.c);
6180 vtop->r2 = ret.r2;
6181 } else {
6182 break;
6187 static void uneq(void)
6189 int t;
6191 unary();
6192 if (tok == '=' ||
6193 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
6194 tok == TOK_A_XOR || tok == TOK_A_OR ||
6195 tok == TOK_A_SHL || tok == TOK_A_SAR) {
6196 test_lvalue();
6197 t = tok;
6198 next();
6199 if (t == '=') {
6200 expr_eq();
6201 } else {
6202 vdup();
6203 expr_eq();
6204 gen_op(t & 0x7f);
6206 vstore();
6210 static void sum(int l)
6212 int t;
6214 if (l == 0)
6215 uneq();
6216 else {
6217 sum(--l);
6218 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
6219 (l == 1 && (tok == '+' || tok == '-')) ||
6220 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
6221 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
6222 tok == TOK_ULT || tok == TOK_UGE)) ||
6223 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
6224 (l == 5 && tok == '&') ||
6225 (l == 6 && tok == '^') ||
6226 (l == 7 && tok == '|') ||
6227 (l == 8 && tok == TOK_LAND) ||
6228 (l == 9 && tok == TOK_LOR)) {
6229 t = tok;
6230 next();
6231 sum(l);
6232 gen_op(t);
6237 /* only used if non constant */
6238 static void eand(void)
6240 int t;
6242 sum(8);
6243 t = 0;
6244 while (1) {
6245 if (tok != TOK_LAND) {
6246 if (t) {
6247 t = gtst(1, t);
6248 vseti(VT_JMPI, t);
6250 break;
6252 t = gtst(1, t);
6253 next();
6254 sum(8);
6258 static void eor(void)
6260 int t;
6262 eand();
6263 t = 0;
6264 while (1) {
6265 if (tok != TOK_LOR) {
6266 if (t) {
6267 t = gtst(0, t);
6268 vseti(VT_JMP, t);
6270 break;
6272 t = gtst(0, t);
6273 next();
6274 eand();
6278 /* XXX: better constant handling */
6279 static void expr_eq(void)
6281 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
6282 SValue sv;
6283 CType type, type1, type2;
6285 if (const_wanted) {
6286 int c1, c;
6287 sum(10);
6288 if (tok == '?') {
6289 c = vtop->c.i;
6290 vpop();
6291 next();
6292 gexpr();
6293 c1 = vtop->c.i;
6294 vpop();
6295 skip(':');
6296 expr_eq();
6297 if (c)
6298 vtop->c.i = c1;
6300 } else {
6301 eor();
6302 if (tok == '?') {
6303 next();
6304 save_regs(1); /* we need to save all registers here except
6305 at the top because it is a branch point */
6306 tt = gtst(1, 0);
6307 gexpr();
6308 type1 = vtop->type;
6309 sv = *vtop; /* save value to handle it later */
6310 vtop--; /* no vpop so that FP stack is not flushed */
6311 skip(':');
6312 u = gjmp(0);
6314 gsym(tt);
6315 expr_eq();
6316 type2 = vtop->type;
6318 t1 = type1.t;
6319 bt1 = t1 & VT_BTYPE;
6320 t2 = type2.t;
6321 bt2 = t2 & VT_BTYPE;
6322 /* cast operands to correct type according to ISOC rules */
6323 if (is_float(bt1) || is_float(bt2)) {
6324 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
6325 type.t = VT_LDOUBLE;
6326 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
6327 type.t = VT_DOUBLE;
6328 } else {
6329 type.t = VT_FLOAT;
6331 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
6332 /* cast to biggest op */
6333 type.t = VT_LLONG;
6334 /* convert to unsigned if it does not fit in a long long */
6335 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
6336 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
6337 type.t |= VT_UNSIGNED;
6338 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
6339 /* XXX: test pointer compatibility */
6340 type = type1;
6341 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
6342 /* XXX: test structure compatibility */
6343 type = type1;
6344 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
6345 /* NOTE: as an extension, we accept void on only one side */
6346 type.t = VT_VOID;
6347 } else {
6348 /* integer operations */
6349 type.t = VT_INT;
6350 /* convert to unsigned if it does not fit in an integer */
6351 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
6352 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
6353 type.t |= VT_UNSIGNED;
6356 /* now we convert second operand */
6357 gen_cast(&type);
6358 rc = RC_INT;
6359 if (is_float(type.t)) {
6360 rc = RC_FLOAT;
6361 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
6362 /* for long longs, we use fixed registers to avoid having
6363 to handle a complicated move */
6364 rc = RC_IRET;
6366 r2 = gv(rc);
6367 /* this is horrible, but we must also convert first
6368 operand */
6369 tt = gjmp(0);
6370 gsym(u);
6371 /* put again first value and cast it */
6372 *vtop = sv;
6373 gen_cast(&type);
6374 r1 = gv(rc);
6375 move_reg(r2, r1);
6376 vtop->r = r2;
6377 gsym(tt);
6382 static void gexpr(void)
6384 while (1) {
6385 expr_eq();
6386 if (tok != ',')
6387 break;
6388 vpop();
6389 next();
6393 /* parse an expression and return its type without any side effect. */
6394 static void expr_type(CType *type)
6396 int a;
6398 a = nocode_wanted;
6399 nocode_wanted = 1;
6400 gexpr();
6401 *type = vtop->type;
6402 vpop();
6403 nocode_wanted = a;
6406 /* parse a unary expression and return its type without any side
6407 effect. */
6408 static void unary_type(CType *type)
6410 int a;
6412 a = nocode_wanted;
6413 nocode_wanted = 1;
6414 unary();
6415 *type = vtop->type;
6416 vpop();
6417 nocode_wanted = a;
6420 /* parse a constant expression and return value in vtop. */
6421 static void expr_const1(void)
6423 int a;
6424 a = const_wanted;
6425 const_wanted = 1;
6426 expr_eq();
6427 const_wanted = a;
6430 /* parse an integer constant and return its value. */
6431 static int expr_const(void)
6433 int c;
6434 expr_const1();
6435 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
6436 expect("constant expression");
6437 c = vtop->c.i;
6438 vpop();
6439 return c;
6442 /* return the label token if current token is a label, otherwise
6443 return zero */
6444 static int is_label(void)
6446 int t;
6447 CValue c;
6449 /* fast test first */
6450 if (tok < TOK_UIDENT)
6451 return 0;
6452 /* no need to save tokc since we expect an identifier */
6453 t = tok;
6454 c = tokc;
6455 next();
6456 if (tok == ':') {
6457 next();
6458 return t;
6459 } else {
6460 /* XXX: may not work in all cases (macros ?) */
6461 tok1 = tok;
6462 tok1c = tokc;
6463 tok = t;
6464 tokc = c;
6465 return 0;
6469 static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
6471 int a, b, c, d;
6472 Sym *s;
6474 /* generate line number info */
6475 if (do_debug &&
6476 (last_line_num != file->line_num || last_ind != ind)) {
6477 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
6478 last_ind = ind;
6479 last_line_num = file->line_num;
6482 if (tok == TOK_IF) {
6483 /* if test */
6484 next();
6485 skip('(');
6486 gexpr();
6487 skip(')');
6488 a = gtst(1, 0);
6489 block(bsym, csym, case_sym, def_sym, case_reg);
6490 c = tok;
6491 if (c == TOK_ELSE) {
6492 next();
6493 d = gjmp(0);
6494 gsym(a);
6495 block(bsym, csym, case_sym, def_sym, case_reg);
6496 gsym(d); /* patch else jmp */
6497 } else
6498 gsym(a);
6499 } else if (tok == TOK_WHILE) {
6500 next();
6501 d = ind;
6502 skip('(');
6503 gexpr();
6504 skip(')');
6505 a = gtst(1, 0);
6506 b = 0;
6507 block(&a, &b, case_sym, def_sym, case_reg);
6508 gjmp_addr(d);
6509 gsym(a);
6510 gsym_addr(b, d);
6511 } else if (tok == '{') {
6512 next();
6513 /* declarations */
6514 s = local_stack;
6515 while (tok != '}') {
6516 decl(VT_LOCAL);
6517 if (tok != '}')
6518 block(bsym, csym, case_sym, def_sym, case_reg);
6520 /* pop locally defined symbols */
6521 sym_pop(&local_stack, s);
6522 next();
6523 } else if (tok == TOK_RETURN) {
6524 next();
6525 if (tok != ';') {
6526 gexpr();
6527 gen_assign_cast(&func_vt);
6528 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
6529 CType type;
6530 /* if returning structure, must copy it to implicit
6531 first pointer arg location */
6532 type = func_vt;
6533 mk_pointer(&type);
6534 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
6535 indir();
6536 vswap();
6537 /* copy structure value to pointer */
6538 vstore();
6539 } else if (is_float(func_vt.t)) {
6540 gv(RC_FRET);
6541 } else {
6542 gv(RC_IRET);
6544 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6546 skip(';');
6547 rsym = gjmp(rsym); /* jmp */
6548 } else if (tok == TOK_BREAK) {
6549 /* compute jump */
6550 if (!bsym)
6551 error("cannot break");
6552 *bsym = gjmp(*bsym);
6553 next();
6554 skip(';');
6555 } else if (tok == TOK_CONTINUE) {
6556 /* compute jump */
6557 if (!csym)
6558 error("cannot continue");
6559 *csym = gjmp(*csym);
6560 next();
6561 skip(';');
6562 } else if (tok == TOK_FOR) {
6563 int e;
6564 next();
6565 skip('(');
6566 if (tok != ';') {
6567 gexpr();
6568 vpop();
6570 skip(';');
6571 d = ind;
6572 c = ind;
6573 a = 0;
6574 b = 0;
6575 if (tok != ';') {
6576 gexpr();
6577 a = gtst(1, 0);
6579 skip(';');
6580 if (tok != ')') {
6581 e = gjmp(0);
6582 c = ind;
6583 gexpr();
6584 vpop();
6585 gjmp_addr(d);
6586 gsym(e);
6588 skip(')');
6589 block(&a, &b, case_sym, def_sym, case_reg);
6590 gjmp_addr(c);
6591 gsym(a);
6592 gsym_addr(b, c);
6593 } else
6594 if (tok == TOK_DO) {
6595 next();
6596 a = 0;
6597 b = 0;
6598 d = ind;
6599 block(&a, &b, case_sym, def_sym, case_reg);
6600 skip(TOK_WHILE);
6601 skip('(');
6602 gsym(b);
6603 gexpr();
6604 c = gtst(0, 0);
6605 gsym_addr(c, d);
6606 skip(')');
6607 gsym(a);
6608 skip(';');
6609 } else
6610 if (tok == TOK_SWITCH) {
6611 next();
6612 skip('(');
6613 gexpr();
6614 /* XXX: other types than integer */
6615 case_reg = gv(RC_INT);
6616 vpop();
6617 skip(')');
6618 a = 0;
6619 b = gjmp(0); /* jump to first case */
6620 c = 0;
6621 block(&a, csym, &b, &c, case_reg);
6622 /* if no default, jmp after switch */
6623 if (c == 0)
6624 c = ind;
6625 /* default label */
6626 gsym_addr(b, c);
6627 /* break label */
6628 gsym(a);
6629 } else
6630 if (tok == TOK_CASE) {
6631 int v1, v2;
6632 if (!case_sym)
6633 expect("switch");
6634 next();
6635 v1 = expr_const();
6636 v2 = v1;
6637 if (gnu_ext && tok == TOK_DOTS) {
6638 next();
6639 v2 = expr_const();
6640 if (v2 < v1)
6641 warning("empty case range");
6643 /* since a case is like a label, we must skip it with a jmp */
6644 b = gjmp(0);
6645 gsym(*case_sym);
6646 vseti(case_reg, 0);
6647 vpushi(v1);
6648 if (v1 == v2) {
6649 gen_op(TOK_EQ);
6650 *case_sym = gtst(1, 0);
6651 } else {
6652 gen_op(TOK_GE);
6653 *case_sym = gtst(1, 0);
6654 vseti(case_reg, 0);
6655 vpushi(v2);
6656 gen_op(TOK_LE);
6657 *case_sym = gtst(1, *case_sym);
6659 gsym(b);
6660 skip(':');
6661 block(bsym, csym, case_sym, def_sym, case_reg);
6662 } else
6663 if (tok == TOK_DEFAULT) {
6664 next();
6665 skip(':');
6666 if (!def_sym)
6667 expect("switch");
6668 if (*def_sym)
6669 error("too many 'default'");
6670 *def_sym = ind;
6671 block(bsym, csym, case_sym, def_sym, case_reg);
6672 } else
6673 if (tok == TOK_GOTO) {
6674 next();
6675 if (tok == '*' && gnu_ext) {
6676 /* computed goto */
6677 next();
6678 gexpr();
6679 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6680 expect("pointer");
6681 ggoto();
6682 } else if (tok >= TOK_UIDENT) {
6683 s = label_find(tok);
6684 /* put forward definition if needed */
6685 if (!s) {
6686 s = label_push(tok, LABEL_FORWARD);
6688 /* label already defined */
6689 if (s->r & LABEL_FORWARD)
6690 s->next = (void *)gjmp((long)s->next);
6691 else
6692 gjmp_addr((long)s->next);
6693 next();
6694 } else {
6695 expect("label identifier");
6697 skip(';');
6698 } else {
6699 b = is_label();
6700 if (b) {
6701 /* label case */
6702 s = label_find(b);
6703 if (s) {
6704 if (!(s->r & LABEL_FORWARD))
6705 error("multiple defined label");
6706 gsym((long)s->next);
6707 } else {
6708 s = label_push(b, 0);
6710 s->next = (void *)ind;
6711 s->r = 0;
6712 /* we accept this, but it is a mistake */
6713 if (tok == '}')
6714 warning("deprecated use of label at end of compound statement");
6715 else
6716 block(bsym, csym, case_sym, def_sym, case_reg);
6717 } else {
6718 /* expression case */
6719 if (tok != ';') {
6720 gexpr();
6721 vpop();
6723 skip(';');
6728 /* t is the array or struct type. c is the array or struct
6729 address. cur_index/cur_field is the pointer to the current
6730 value. 'size_only' is true if only size info is needed (only used
6731 in arrays) */
6732 static void decl_designator(CType *type, Section *sec, unsigned long c,
6733 int *cur_index, Sym **cur_field,
6734 int size_only)
6736 Sym *s, *f;
6737 int notfirst, index, align, l;
6738 CType type1;
6740 notfirst = 0;
6741 if (gnu_ext && (l = is_label()) != 0)
6742 goto struct_field;
6744 while (tok == '[' || tok == '.') {
6745 if (tok == '[') {
6746 if (!(type->t & VT_ARRAY))
6747 expect("array type");
6748 s = type->ref;
6749 next();
6750 index = expr_const();
6751 if (index < 0 || (s->c >= 0 && index >= s->c))
6752 expect("invalid index");
6753 skip(']');
6754 if (!notfirst)
6755 *cur_index = index;
6756 type = pointed_type(type);
6757 c += index * type_size(type, &align);
6758 } else {
6759 next();
6760 l = tok;
6761 next();
6762 struct_field:
6763 if ((type->t & VT_BTYPE) != VT_STRUCT)
6764 expect("struct/union type");
6765 s = type->ref;
6766 l |= SYM_FIELD;
6767 f = s->next;
6768 while (f) {
6769 if (f->v == l)
6770 break;
6771 f = f->next;
6773 if (!f)
6774 expect("field");
6775 if (!notfirst)
6776 *cur_field = f;
6777 /* XXX: suppress this mess by using explicit storage field */
6778 type1 = f->type;
6779 type1.t |= (type->t & ~VT_TYPE);
6780 type = &type1;
6781 c += f->c;
6783 notfirst = 1;
6785 if (notfirst) {
6786 if (tok == '=') {
6787 next();
6788 } else {
6789 if (!gnu_ext)
6790 expect("=");
6792 } else {
6793 if (type->t & VT_ARRAY) {
6794 index = *cur_index;
6795 type = pointed_type(type);
6796 c += index * type_size(type, &align);
6797 } else {
6798 f = *cur_field;
6799 if (!f)
6800 error("too many field init");
6801 /* XXX: suppress this mess by using explicit storage field */
6802 type1 = f->type;
6803 type1.t |= (type->t & ~VT_TYPE);
6804 type = &type1;
6805 c += f->c;
6808 decl_initializer(type, sec, c, 0, size_only);
6811 #define EXPR_VAL 0
6812 #define EXPR_CONST 1
6813 #define EXPR_ANY 2
6815 /* store a value or an expression directly in global data or in local array */
6816 static void init_putv(CType *type, Section *sec, unsigned long c,
6817 int v, int expr_type)
6819 int saved_global_expr, bt;
6820 void *ptr;
6822 switch(expr_type) {
6823 case EXPR_VAL:
6824 vpushi(v);
6825 break;
6826 case EXPR_CONST:
6827 /* compound literals must be allocated globally in this case */
6828 saved_global_expr = global_expr;
6829 global_expr = 1;
6830 expr_const1();
6831 global_expr = saved_global_expr;
6832 /* NOTE: symbols are accepted */
6833 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
6834 error("initializer element is not constant");
6835 break;
6836 case EXPR_ANY:
6837 expr_eq();
6838 break;
6841 if (sec) {
6842 /* XXX: not portable */
6843 /* XXX: generate error if incorrect relocation */
6844 gen_assign_cast(type);
6845 bt = type->t & VT_BTYPE;
6846 ptr = sec->data + c;
6847 if ((vtop->r & VT_SYM) &&
6848 (bt == VT_BYTE ||
6849 bt == VT_SHORT ||
6850 bt == VT_DOUBLE ||
6851 bt == VT_LDOUBLE ||
6852 bt == VT_LLONG))
6853 error("initializer element is not computable at load time");
6854 switch(bt) {
6855 case VT_BYTE:
6856 *(char *)ptr = vtop->c.i;
6857 break;
6858 case VT_SHORT:
6859 *(short *)ptr = vtop->c.i;
6860 break;
6861 case VT_DOUBLE:
6862 *(double *)ptr = vtop->c.d;
6863 break;
6864 case VT_LDOUBLE:
6865 *(long double *)ptr = vtop->c.ld;
6866 break;
6867 case VT_LLONG:
6868 *(long long *)ptr = vtop->c.ll;
6869 break;
6870 default:
6871 if (vtop->r & VT_SYM) {
6872 greloc(sec, vtop->sym, c, R_DATA_32);
6874 *(int *)ptr = vtop->c.i;
6875 break;
6877 vtop--;
6878 } else {
6879 vset(type, VT_LOCAL, c);
6880 vswap();
6881 vstore();
6882 vpop();
6886 /* put zeros for variable based init */
6887 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
6889 GFuncContext gf;
6891 if (sec) {
6892 /* nothing to do because globals are already set to zero */
6893 } else {
6894 gfunc_start(&gf, FUNC_CDECL);
6895 vpushi(size);
6896 gfunc_param(&gf);
6897 vpushi(0);
6898 gfunc_param(&gf);
6899 vseti(VT_LOCAL, c);
6900 gfunc_param(&gf);
6901 vpush_global_sym(&func_old_type, TOK_memset);
6902 gfunc_call(&gf);
6906 /* 't' contains the type and storage info. 'c' is the offset of the
6907 object in section 'sec'. If 'sec' is NULL, it means stack based
6908 allocation. 'first' is true if array '{' must be read (multi
6909 dimension implicit array init handling). 'size_only' is true if
6910 size only evaluation is wanted (only for arrays). */
6911 static void decl_initializer(CType *type, Section *sec, unsigned long c,
6912 int first, int size_only)
6914 int index, array_length, n, no_oblock, nb, parlevel, i;
6915 int size1, align1, expr_type;
6916 Sym *s, *f;
6917 CType *t1;
6919 if (type->t & VT_ARRAY) {
6920 s = type->ref;
6921 n = s->c;
6922 array_length = 0;
6923 t1 = pointed_type(type);
6924 size1 = type_size(t1, &align1);
6926 no_oblock = 1;
6927 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
6928 tok == '{') {
6929 skip('{');
6930 no_oblock = 0;
6933 /* only parse strings here if correct type (otherwise: handle
6934 them as ((w)char *) expressions */
6935 if ((tok == TOK_LSTR &&
6936 (t1->t & VT_BTYPE) == VT_INT) ||
6937 (tok == TOK_STR &&
6938 (t1->t & VT_BTYPE) == VT_BYTE)) {
6939 while (tok == TOK_STR || tok == TOK_LSTR) {
6940 int cstr_len, ch;
6941 CString *cstr;
6943 cstr = tokc.cstr;
6944 /* compute maximum number of chars wanted */
6945 if (tok == TOK_STR)
6946 cstr_len = cstr->size;
6947 else
6948 cstr_len = cstr->size / sizeof(int);
6949 cstr_len--;
6950 nb = cstr_len;
6951 if (n >= 0 && nb > (n - array_length))
6952 nb = n - array_length;
6953 if (!size_only) {
6954 if (cstr_len > nb)
6955 warning("initializer-string for array is too long");
6956 /* in order to go faster for common case (char
6957 string in global variable, we handle it
6958 specifically */
6959 if (sec && tok == TOK_STR && size1 == 1) {
6960 memcpy(sec->data + c + array_length, cstr->data, nb);
6961 } else {
6962 for(i=0;i<nb;i++) {
6963 if (tok == TOK_STR)
6964 ch = ((unsigned char *)cstr->data)[i];
6965 else
6966 ch = ((int *)cstr->data)[i];
6967 init_putv(t1, sec, c + (array_length + i) * size1,
6968 ch, EXPR_VAL);
6972 array_length += nb;
6973 next();
6975 /* only add trailing zero if enough storage (no
6976 warning in this case since it is standard) */
6977 if (n < 0 || array_length < n) {
6978 if (!size_only) {
6979 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
6981 array_length++;
6983 } else {
6984 index = 0;
6985 while (tok != '}') {
6986 decl_designator(type, sec, c, &index, NULL, size_only);
6987 if (n >= 0 && index >= n)
6988 error("index too large");
6989 /* must put zero in holes (note that doing it that way
6990 ensures that it even works with designators) */
6991 if (!size_only && array_length < index) {
6992 init_putz(t1, sec, c + array_length * size1,
6993 (index - array_length) * size1);
6995 index++;
6996 if (index > array_length)
6997 array_length = index;
6998 /* special test for multi dimensional arrays (may not
6999 be strictly correct if designators are used at the
7000 same time) */
7001 if (index >= n && no_oblock)
7002 break;
7003 if (tok == '}')
7004 break;
7005 skip(',');
7008 if (!no_oblock)
7009 skip('}');
7010 /* put zeros at the end */
7011 if (!size_only && n >= 0 && array_length < n) {
7012 init_putz(t1, sec, c + array_length * size1,
7013 (n - array_length) * size1);
7015 /* patch type size if needed */
7016 if (n < 0)
7017 s->c = array_length;
7018 } else if ((type->t & VT_BTYPE) == VT_STRUCT && tok == '{') {
7019 /* XXX: union needs only one init */
7020 next();
7021 s = type->ref;
7022 f = s->next;
7023 array_length = 0;
7024 index = 0;
7025 n = s->c;
7026 while (tok != '}') {
7027 decl_designator(type, sec, c, NULL, &f, size_only);
7028 /* fill with zero between fields */
7029 index = f->c;
7030 if (!size_only && array_length < index) {
7031 init_putz(type, sec, c + array_length,
7032 index - array_length);
7034 index = index + type_size(&f->type, &align1);
7035 if (index > array_length)
7036 array_length = index;
7037 if (tok == '}')
7038 break;
7039 skip(',');
7040 f = f->next;
7042 /* put zeros at the end */
7043 if (!size_only && array_length < n) {
7044 init_putz(type, sec, c + array_length,
7045 n - array_length);
7047 skip('}');
7048 } else if (tok == '{') {
7049 next();
7050 decl_initializer(type, sec, c, first, size_only);
7051 skip('}');
7052 } else if (size_only) {
7053 /* just skip expression */
7054 parlevel = 0;
7055 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
7056 tok != -1) {
7057 if (tok == '(')
7058 parlevel++;
7059 else if (tok == ')')
7060 parlevel--;
7061 next();
7063 } else {
7064 /* currently, we always use constant expression for globals
7065 (may change for scripting case) */
7066 expr_type = EXPR_CONST;
7067 if (!sec)
7068 expr_type = EXPR_ANY;
7069 init_putv(type, sec, c, 0, expr_type);
7073 /* parse an initializer for type 't' if 'has_init' is non zero, and
7074 allocate space in local or global data space ('r' is either
7075 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
7076 variable 'v' of scope 'scope' is declared before initializers are
7077 parsed. If 'v' is zero, then a reference to the new object is put
7078 in the value stack. If 'has_init' is 2, a special parsing is done
7079 to handle string constants. */
7080 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
7081 int has_init, int v, int scope)
7083 int size, align, addr, data_offset;
7084 int level;
7085 ParseState saved_parse_state;
7086 TokenString init_str;
7087 Section *sec;
7089 size = type_size(type, &align);
7090 /* If unknown size, we must evaluate it before
7091 evaluating initializers because
7092 initializers can generate global data too
7093 (e.g. string pointers or ISOC99 compound
7094 literals). It also simplifies local
7095 initializers handling */
7096 tok_str_new(&init_str);
7097 if (size < 0) {
7098 if (!has_init)
7099 error("unknown type size");
7100 /* get all init string */
7101 if (has_init == 2) {
7102 /* only get strings */
7103 while (tok == TOK_STR || tok == TOK_LSTR) {
7104 tok_str_add_tok(&init_str);
7105 next();
7107 } else {
7108 level = 0;
7109 while (level > 0 || (tok != ',' && tok != ';')) {
7110 if (tok < 0)
7111 error("unexpected end of file in initializer");
7112 tok_str_add_tok(&init_str);
7113 if (tok == '{')
7114 level++;
7115 else if (tok == '}') {
7116 if (level == 0)
7117 break;
7118 level--;
7120 next();
7123 tok_str_add(&init_str, -1);
7124 tok_str_add(&init_str, 0);
7126 /* compute size */
7127 save_parse_state(&saved_parse_state);
7129 macro_ptr = init_str.str;
7130 next();
7131 decl_initializer(type, NULL, 0, 1, 1);
7132 /* prepare second initializer parsing */
7133 macro_ptr = init_str.str;
7134 next();
7136 /* if still unknown size, error */
7137 size = type_size(type, &align);
7138 if (size < 0)
7139 error("unknown type size");
7141 /* take into account specified alignment if bigger */
7142 if (ad->aligned > align)
7143 align = ad->aligned;
7144 if ((r & VT_VALMASK) == VT_LOCAL) {
7145 sec = NULL;
7146 if (do_bounds_check && (type->t & VT_ARRAY))
7147 loc--;
7148 #ifdef TCC_TARGET_IL
7149 /* XXX: ugly patch to allocate local variables for IL, just
7150 for testing */
7151 addr = loc;
7152 loc++;
7153 #else
7154 loc = (loc - size) & -align;
7155 addr = loc;
7156 #endif
7157 /* handles bounds */
7158 /* XXX: currently, since we do only one pass, we cannot track
7159 '&' operators, so we add only arrays */
7160 if (do_bounds_check && (type->t & VT_ARRAY)) {
7161 unsigned long *bounds_ptr;
7162 /* add padding between regions */
7163 loc--;
7164 /* then add local bound info */
7165 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
7166 bounds_ptr[0] = addr;
7167 bounds_ptr[1] = size;
7169 } else {
7170 /* compute section */
7171 sec = ad->section;
7172 if (!sec) {
7173 if (has_init)
7174 sec = data_section;
7175 else
7176 sec = bss_section;
7178 data_offset = sec->data_offset;
7179 data_offset = (data_offset + align - 1) & -align;
7180 addr = data_offset;
7181 /* very important to increment global pointer at this time
7182 because initializers themselves can create new initializers */
7183 data_offset += size;
7184 /* add padding if bound check */
7185 if (do_bounds_check)
7186 data_offset++;
7187 sec->data_offset = data_offset;
7188 /* allocate section space to put the data */
7189 if (sec->sh_type != SHT_NOBITS &&
7190 data_offset > sec->data_allocated)
7191 section_realloc(sec, data_offset);
7193 if (!sec) {
7194 if (v) {
7195 /* local variable */
7196 sym_push(v, type, r, addr);
7197 } else {
7198 /* push local reference */
7199 vset(type, r, addr);
7201 } else {
7202 Sym *sym;
7204 if (v) {
7205 if (scope == VT_CONST) {
7206 /* global scope: see if already defined */
7207 sym = sym_find(v);
7208 if (!sym)
7209 goto do_def;
7210 if (!is_compatible_types(&sym->type, type))
7211 error("incompatible types for redefinition of '%s'",
7212 get_tok_str(v, NULL));
7213 if (!(sym->type.t & VT_EXTERN))
7214 error("redefinition of '%s'", get_tok_str(v, NULL));
7215 sym->type.t &= ~VT_EXTERN;
7216 } else {
7217 do_def:
7218 sym = sym_push(v, type, r | VT_SYM, 0);
7220 put_extern_sym(sym, sec, addr, size);
7221 } else {
7222 CValue cval;
7224 /* push global reference */
7225 sym = get_sym_ref(type, sec, addr, size);
7226 cval.ul = 0;
7227 vsetc(type, VT_CONST | VT_SYM, &cval);
7228 vtop->sym = sym;
7231 /* handles bounds now because the symbol must be defined
7232 before for the relocation */
7233 if (do_bounds_check) {
7234 unsigned long *bounds_ptr;
7236 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
7237 /* then add global bound info */
7238 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
7239 bounds_ptr[0] = 0; /* relocated */
7240 bounds_ptr[1] = size;
7243 if (has_init) {
7244 decl_initializer(type, sec, addr, 1, 0);
7245 /* restore parse state if needed */
7246 if (init_str.str) {
7247 tok_str_free(init_str.str);
7248 restore_parse_state(&saved_parse_state);
7253 void put_func_debug(Sym *sym)
7255 char buf[512];
7257 /* stabs info */
7258 /* XXX: we put here a dummy type */
7259 snprintf(buf, sizeof(buf), "%s:%c1",
7260 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
7261 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
7262 cur_text_section, sym->c);
7263 last_ind = 0;
7264 last_line_num = 0;
7267 /* not finished : try to put some local vars in registers */
7268 //#define CONFIG_REG_VARS
7270 #ifdef CONFIG_REG_VARS
7271 void add_var_ref(int t)
7273 printf("%s:%d: &%s\n",
7274 file->filename, file->line_num,
7275 get_tok_str(t, NULL));
7278 /* first pass on a function with heuristic to extract variable usage
7279 and pointer references to local variables for register allocation */
7280 void analyse_function(void)
7282 int level, t;
7284 for(;;) {
7285 if (tok == -1)
7286 break;
7287 /* any symbol coming after '&' is considered as being a
7288 variable whose reference is taken. It is highly unaccurate
7289 but it is difficult to do better without a complete parse */
7290 if (tok == '&') {
7291 next();
7292 /* if '& number', then no need to examine next tokens */
7293 if (tok == TOK_CINT ||
7294 tok == TOK_CUINT ||
7295 tok == TOK_CLLONG ||
7296 tok == TOK_CULLONG) {
7297 continue;
7298 } else if (tok >= TOK_UIDENT) {
7299 /* if '& ident [' or '& ident ->', then ident address
7300 is not needed */
7301 t = tok;
7302 next();
7303 if (tok != '[' && tok != TOK_ARROW)
7304 add_var_ref(t);
7305 } else {
7306 level = 0;
7307 while (tok != '}' && tok != ';' &&
7308 !((tok == ',' || tok == ')') && level == 0)) {
7309 if (tok >= TOK_UIDENT) {
7310 add_var_ref(tok);
7311 } else if (tok == '(') {
7312 level++;
7313 } else if (tok == ')') {
7314 level--;
7316 next();
7319 } else {
7320 next();
7324 #endif
7326 /* parse an old style function declaration list */
7327 /* XXX: check multiple parameter */
7328 static void func_decl_list(Sym *func_sym)
7330 AttributeDef ad;
7331 int v;
7332 Sym *s;
7333 CType btype, type;
7335 /* parse each declaration */
7336 while (tok != '{' && tok != ';' && tok != TOK_EOF) {
7337 if (!parse_btype(&btype, &ad))
7338 expect("declaration list");
7339 if (((btype.t & VT_BTYPE) == VT_ENUM ||
7340 (btype.t & VT_BTYPE) == VT_STRUCT) &&
7341 tok == ';') {
7342 /* we accept no variable after */
7343 } else {
7344 for(;;) {
7345 type = btype;
7346 type_decl(&type, &ad, &v, TYPE_DIRECT);
7347 /* find parameter in function parameter list */
7348 s = func_sym->next;
7349 while (s != NULL) {
7350 if ((s->v & ~SYM_FIELD) == v)
7351 goto found;
7352 s = s->next;
7354 error("declaration for parameter '%s' but no such parameter",
7355 get_tok_str(v, NULL));
7356 found:
7357 /* check that no storage specifier except 'register' was given */
7358 if (type.t & (VT_EXTERN | VT_STATIC | VT_TYPEDEF))
7359 error("storage class specified for '%s'", get_tok_str(v, NULL));
7360 /* we can add the type (NOTE: it could be local to the function) */
7361 s->type = type;
7362 /* accept other parameters */
7363 if (tok == ',')
7364 next();
7365 else
7366 break;
7369 skip(';');
7373 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
7374 static void decl(int l)
7376 int v, has_init, r;
7377 CType type, btype;
7378 Sym *sym;
7379 AttributeDef ad;
7381 while (1) {
7382 if (!parse_btype(&btype, &ad)) {
7383 /* skip redundant ';' */
7384 /* XXX: find more elegant solution */
7385 if (tok == ';') {
7386 next();
7387 continue;
7389 /* special test for old K&R protos without explicit int
7390 type. Only accepted when defining global data */
7391 if (l == VT_LOCAL || tok < TOK_DEFINE)
7392 break;
7393 btype.t = VT_INT;
7395 if (((btype.t & VT_BTYPE) == VT_ENUM ||
7396 (btype.t & VT_BTYPE) == VT_STRUCT) &&
7397 tok == ';') {
7398 /* we accept no variable after */
7399 next();
7400 continue;
7402 while (1) { /* iterate thru each declaration */
7403 type = btype;
7404 type_decl(&type, &ad, &v, TYPE_DIRECT);
7405 #if 0
7407 char buf[500];
7408 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
7409 printf("type = '%s'\n", buf);
7411 #endif
7412 if ((type.t & VT_BTYPE) == VT_FUNC) {
7413 /* if old style function prototype, we accept a
7414 declaration list */
7415 sym = type.ref;
7416 if (sym->c == FUNC_OLD)
7417 func_decl_list(sym);
7420 if (tok == '{') {
7421 #ifdef CONFIG_REG_VARS
7422 TokenString func_str;
7423 ParseState saved_parse_state;
7424 int block_level;
7425 #endif
7427 if (l == VT_LOCAL)
7428 error("cannot use local functions");
7429 if (!(type.t & VT_FUNC))
7430 expect("function definition");
7432 #ifdef CONFIG_REG_VARS
7433 /* parse all function code and record it */
7435 tok_str_new(&func_str);
7437 block_level = 0;
7438 for(;;) {
7439 int t;
7440 if (tok == -1)
7441 error("unexpected end of file");
7442 tok_str_add_tok(&func_str);
7443 t = tok;
7444 next();
7445 if (t == '{') {
7446 block_level++;
7447 } else if (t == '}') {
7448 block_level--;
7449 if (block_level == 0)
7450 break;
7453 tok_str_add(&func_str, -1);
7454 tok_str_add(&func_str, 0);
7456 save_parse_state(&saved_parse_state);
7458 macro_ptr = func_str.str;
7459 next();
7460 analyse_function();
7461 #endif
7463 /* compute text section */
7464 cur_text_section = ad.section;
7465 if (!cur_text_section)
7466 cur_text_section = text_section;
7467 ind = cur_text_section->data_offset;
7468 funcname = get_tok_str(v, NULL);
7469 sym = sym_find(v);
7470 if (sym) {
7471 /* if symbol is already defined, then put complete type */
7472 sym->type = type;
7473 } else {
7474 /* put function symbol */
7475 sym = global_identifier_push(v, type.t, 0);
7476 sym->type.ref = type.ref;
7478 /* NOTE: we patch the symbol size later */
7479 put_extern_sym(sym, cur_text_section, ind, 0);
7480 func_ind = ind;
7481 sym->r = VT_SYM | VT_CONST;
7482 /* put debug symbol */
7483 if (do_debug)
7484 put_func_debug(sym);
7485 /* push a dummy symbol to enable local sym storage */
7486 sym_push2(&local_stack, SYM_FIELD, 0, 0);
7487 gfunc_prolog(&type);
7488 loc = 0;
7489 rsym = 0;
7490 #ifdef CONFIG_REG_VARS
7491 macro_ptr = func_str.str;
7492 next();
7493 #endif
7494 block(NULL, NULL, NULL, NULL, 0);
7495 gsym(rsym);
7496 gfunc_epilog();
7497 cur_text_section->data_offset = ind;
7498 /* look if any labels are undefined. Define symbols if
7499 '&&label' was used. */
7501 Sym *s, *s1;
7502 for(s = label_stack; s != NULL; s = s1) {
7503 s1 = s->prev;
7504 if (s->r & LABEL_FORWARD) {
7505 error("label '%s' used but not defined",
7506 get_tok_str(s->v, NULL));
7508 if (s->c) {
7509 /* define corresponding symbol. A size of
7510 1 is put. */
7511 put_extern_sym(s, cur_text_section, (long)s->next, 1);
7513 /* remove label */
7514 table_ident[s->v - TOK_IDENT]->sym_label = NULL;
7515 tcc_free(s);
7517 label_stack = NULL;
7519 sym_pop(&local_stack, NULL); /* reset local stack */
7520 /* end of function */
7521 /* patch symbol size */
7522 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
7523 ind - func_ind;
7524 if (do_debug) {
7525 put_stabn(N_FUN, 0, 0, ind - func_ind);
7527 funcname = ""; /* for safety */
7528 func_vt.t = VT_VOID; /* for safety */
7529 ind = 0; /* for safety */
7531 #ifdef CONFIG_REG_VARS
7532 tok_str_free(func_str.str);
7533 restore_parse_state(&saved_parse_state);
7534 #endif
7535 break;
7536 } else {
7537 if (btype.t & VT_TYPEDEF) {
7538 /* save typedefed type */
7539 /* XXX: test storage specifiers ? */
7540 sym = sym_push(v, &type, 0, 0);
7541 sym->type.t |= VT_TYPEDEF;
7542 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
7543 /* external function definition */
7544 external_sym(v, &type, 0);
7545 } else {
7546 /* not lvalue if array */
7547 r = 0;
7548 if (!(type.t & VT_ARRAY))
7549 r |= lvalue_type(type.t);
7550 if (btype.t & VT_EXTERN) {
7551 /* external variable */
7552 external_sym(v, &type, r);
7553 } else {
7554 if (type.t & VT_STATIC)
7555 r |= VT_CONST;
7556 else
7557 r |= l;
7558 has_init = (tok == '=');
7559 if (has_init)
7560 next();
7561 decl_initializer_alloc(&type, &ad, r,
7562 has_init, v, l);
7565 if (tok != ',') {
7566 skip(';');
7567 break;
7569 next();
7575 /* compile the C file opened in 'file'. Return non zero if errors. */
7576 static int tcc_compile(TCCState *s1)
7578 Sym *define_start;
7579 char buf[512];
7580 volatile int section_sym;
7582 #ifdef INC_DEBUG
7583 printf("%s: **** new file\n", file->filename);
7584 #endif
7585 funcname = "";
7586 s1->include_stack_ptr = s1->include_stack;
7587 /* XXX: move that before to avoid having to initialize
7588 file->ifdef_stack_ptr ? */
7589 s1->ifdef_stack_ptr = s1->ifdef_stack;
7590 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
7592 /* XXX: not ANSI compliant: bound checking says error */
7593 vtop = vstack - 1;
7594 anon_sym = SYM_FIRST_ANOM;
7596 /* file info: full path + filename */
7597 section_sym = 0; /* avoid warning */
7598 if (do_debug) {
7599 section_sym = put_elf_sym(symtab_section, 0, 0,
7600 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
7601 text_section->sh_num, NULL);
7602 getcwd(buf, sizeof(buf));
7603 pstrcat(buf, sizeof(buf), "/");
7604 put_stabs_r(buf, N_SO, 0, 0,
7605 text_section->data_offset, text_section, section_sym);
7606 put_stabs_r(file->filename, N_SO, 0, 0,
7607 text_section->data_offset, text_section, section_sym);
7609 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
7610 symbols can be safely used */
7611 put_elf_sym(symtab_section, 0, 0,
7612 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
7613 SHN_ABS, file->filename);
7615 /* define some often used types */
7616 int_type.t = VT_INT;
7618 char_pointer_type.t = VT_BYTE;
7619 mk_pointer(&char_pointer_type);
7621 func_old_type.t = VT_FUNC;
7622 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
7624 #if 0
7625 /* define 'void *alloca(unsigned int)' builtin function */
7627 Sym *s1;
7629 p = anon_sym++;
7630 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
7631 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
7632 s1->next = NULL;
7633 sym->next = s1;
7634 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
7636 #endif
7638 define_start = define_stack;
7640 if (setjmp(s1->error_jmp_buf) == 0) {
7641 s1->nb_errors = 0;
7642 s1->error_set_jmp_enabled = 1;
7644 ch = '\n'; /* XXX: suppress that*/
7645 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
7646 next();
7647 decl(VT_CONST);
7648 if (tok != -1)
7649 expect("declaration");
7651 /* end of translation unit info */
7652 if (do_debug) {
7653 put_stabs_r(NULL, N_SO, 0, 0,
7654 text_section->data_offset, text_section, section_sym);
7657 s1->error_set_jmp_enabled = 0;
7659 /* reset define stack, but leave -Dsymbols (may be incorrect if
7660 they are undefined) */
7661 free_defines(define_start);
7663 sym_pop(&global_stack, NULL);
7665 return s1->nb_errors != 0 ? -1 : 0;
7668 #ifdef LIBTCC
7669 int tcc_compile_string(TCCState *s, const char *str)
7671 BufferedFile bf1, *bf = &bf1;
7672 int ret, len;
7673 char *buf;
7675 /* init file structure */
7676 bf->fd = -1;
7677 /* XXX: avoid copying */
7678 len = strlen(str);
7679 buf = tcc_malloc(len + 1);
7680 if (!buf)
7681 return -1;
7682 buf[len] = CH_EOB;
7683 bf->buf_ptr = buf;
7684 bf->buf_end = buf + len;
7685 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
7686 bf->line_num = 1;
7687 file = bf;
7689 ret = tcc_compile(s);
7691 tcc_free(buf);
7693 /* currently, no need to close */
7694 return ret;
7696 #endif
7698 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
7699 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
7701 BufferedFile bf1, *bf = &bf1;
7703 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
7704 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
7705 /* default value */
7706 if (!value)
7707 value = "1";
7708 pstrcat(bf->buffer, IO_BUF_SIZE, value);
7710 /* init file structure */
7711 bf->fd = -1;
7712 bf->buf_ptr = bf->buffer;
7713 bf->buf_end = bf->buffer + strlen(bf->buffer);
7714 *bf->buf_end = CH_EOB;
7715 bf->filename[0] = '\0';
7716 bf->line_num = 1;
7717 file = bf;
7719 s1->include_stack_ptr = s1->include_stack;
7721 /* parse with define parser */
7722 ch = '\n'; /* needed to parse correctly first preprocessor command */
7723 next_nomacro();
7724 parse_define();
7725 file = NULL;
7728 /* undefine a preprocessor symbol */
7729 void tcc_undefine_symbol(TCCState *s1, const char *sym)
7731 TokenSym *ts;
7732 Sym *s;
7733 ts = tok_alloc(sym, strlen(sym));
7734 s = define_find(ts->tok);
7735 /* undefine symbol by putting an invalid name */
7736 if (s)
7737 define_undef(s);
7740 #include "tccelf.c"
7742 /* print the position in the source file of PC value 'pc' by reading
7743 the stabs debug information */
7744 static void rt_printline(unsigned long wanted_pc)
7746 Stab_Sym *sym, *sym_end;
7747 char func_name[128], last_func_name[128];
7748 unsigned long func_addr, last_pc, pc;
7749 const char *incl_files[INCLUDE_STACK_SIZE];
7750 int incl_index, len, last_line_num, i;
7751 const char *str, *p;
7753 fprintf(stderr, "0x%08lx:", wanted_pc);
7755 func_name[0] = '\0';
7756 func_addr = 0;
7757 incl_index = 0;
7758 last_func_name[0] = '\0';
7759 last_pc = 0xffffffff;
7760 last_line_num = 1;
7761 sym = (Stab_Sym *)stab_section->data + 1;
7762 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
7763 while (sym < sym_end) {
7764 switch(sym->n_type) {
7765 /* function start or end */
7766 case N_FUN:
7767 if (sym->n_strx == 0) {
7768 /* we test if between last line and end of function */
7769 pc = sym->n_value + func_addr;
7770 if (wanted_pc >= last_pc && wanted_pc < pc)
7771 goto found;
7772 func_name[0] = '\0';
7773 func_addr = 0;
7774 } else {
7775 str = stabstr_section->data + sym->n_strx;
7776 p = strchr(str, ':');
7777 if (!p) {
7778 pstrcpy(func_name, sizeof(func_name), str);
7779 } else {
7780 len = p - str;
7781 if (len > sizeof(func_name) - 1)
7782 len = sizeof(func_name) - 1;
7783 memcpy(func_name, str, len);
7784 func_name[len] = '\0';
7786 func_addr = sym->n_value;
7788 break;
7789 /* line number info */
7790 case N_SLINE:
7791 pc = sym->n_value + func_addr;
7792 if (wanted_pc >= last_pc && wanted_pc < pc)
7793 goto found;
7794 last_pc = pc;
7795 last_line_num = sym->n_desc;
7796 /* XXX: slow! */
7797 strcpy(last_func_name, func_name);
7798 break;
7799 /* include files */
7800 case N_BINCL:
7801 str = stabstr_section->data + sym->n_strx;
7802 add_incl:
7803 if (incl_index < INCLUDE_STACK_SIZE) {
7804 incl_files[incl_index++] = str;
7806 break;
7807 case N_EINCL:
7808 if (incl_index > 1)
7809 incl_index--;
7810 break;
7811 case N_SO:
7812 if (sym->n_strx == 0) {
7813 incl_index = 0; /* end of translation unit */
7814 } else {
7815 str = stabstr_section->data + sym->n_strx;
7816 /* do not add path */
7817 len = strlen(str);
7818 if (len > 0 && str[len - 1] != '/')
7819 goto add_incl;
7821 break;
7823 sym++;
7826 /* second pass: we try symtab symbols (no line number info) */
7827 incl_index = 0;
7829 Elf32_Sym *sym, *sym_end;
7830 int type;
7832 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
7833 for(sym = (Elf32_Sym *)symtab_section->data + 1;
7834 sym < sym_end;
7835 sym++) {
7836 type = ELF32_ST_TYPE(sym->st_info);
7837 if (type == STT_FUNC) {
7838 if (wanted_pc >= sym->st_value &&
7839 wanted_pc < sym->st_value + sym->st_size) {
7840 pstrcpy(last_func_name, sizeof(last_func_name),
7841 strtab_section->data + sym->st_name);
7842 goto found;
7847 /* did not find any info: */
7848 fprintf(stderr, " ???\n");
7849 return;
7850 found:
7851 if (last_func_name[0] != '\0') {
7852 fprintf(stderr, " %s()", last_func_name);
7854 if (incl_index > 0) {
7855 fprintf(stderr, " (%s:%d",
7856 incl_files[incl_index - 1], last_line_num);
7857 for(i = incl_index - 2; i >= 0; i--)
7858 fprintf(stderr, ", included from %s", incl_files[i]);
7859 fprintf(stderr, ")");
7861 fprintf(stderr, "\n");
7864 #ifndef WIN32
7866 #ifdef __i386__
7868 #ifndef EIP
7869 #define EIP 14
7870 #define EBP 6
7871 #endif
7873 /* return the PC at frame level 'level'. Return non zero if not found */
7874 static int rt_get_caller_pc(unsigned long *paddr,
7875 struct ucontext *uc, int level)
7877 unsigned long fp;
7878 int i;
7880 if (level == 0) {
7881 *paddr = uc->uc_mcontext.gregs[EIP];
7882 return 0;
7883 } else {
7884 fp = uc->uc_mcontext.gregs[EBP];
7885 for(i=1;i<level;i++) {
7886 /* XXX: check address validity with program info */
7887 if (fp <= 0x1000 || fp >= 0xc0000000)
7888 return -1;
7889 fp = ((unsigned long *)fp)[0];
7891 *paddr = ((unsigned long *)fp)[1];
7892 return 0;
7895 #else
7896 #error add arch specific rt_get_caller_pc()
7897 #endif
7899 /* emit a run time error at position 'pc' */
7900 void rt_error(struct ucontext *uc, const char *fmt, ...)
7902 va_list ap;
7903 unsigned long pc;
7904 int i;
7906 va_start(ap, fmt);
7907 fprintf(stderr, "Runtime error: ");
7908 vfprintf(stderr, fmt, ap);
7909 fprintf(stderr, "\n");
7910 for(i=0;i<num_callers;i++) {
7911 if (rt_get_caller_pc(&pc, uc, i) < 0)
7912 break;
7913 if (i == 0)
7914 fprintf(stderr, "at ");
7915 else
7916 fprintf(stderr, "by ");
7917 rt_printline(pc);
7919 exit(255);
7920 va_end(ap);
7923 /* signal handler for fatal errors */
7924 static void sig_error(int signum, siginfo_t *siginf, void *puc)
7926 struct ucontext *uc = puc;
7928 switch(signum) {
7929 case SIGFPE:
7930 switch(siginf->si_code) {
7931 case FPE_INTDIV:
7932 case FPE_FLTDIV:
7933 rt_error(uc, "division by zero");
7934 break;
7935 default:
7936 rt_error(uc, "floating point exception");
7937 break;
7939 break;
7940 case SIGBUS:
7941 case SIGSEGV:
7942 if (rt_bound_error_msg && *rt_bound_error_msg)
7943 rt_error(uc, *rt_bound_error_msg);
7944 else
7945 rt_error(uc, "dereferencing invalid pointer");
7946 break;
7947 case SIGILL:
7948 rt_error(uc, "illegal instruction");
7949 break;
7950 case SIGABRT:
7951 rt_error(uc, "abort() called");
7952 break;
7953 default:
7954 rt_error(uc, "caught signal %d", signum);
7955 break;
7957 exit(255);
7959 #endif
7961 /* do all relocations (needed before using tcc_get_symbol()) */
7962 int tcc_relocate(TCCState *s1)
7964 Section *s;
7965 int i;
7967 s1->nb_errors = 0;
7969 tcc_add_runtime(s1);
7971 relocate_common_syms();
7973 /* compute relocation address : section are relocated in place. We
7974 also alloc the bss space */
7975 for(i = 1; i < s1->nb_sections; i++) {
7976 s = s1->sections[i];
7977 if (s->sh_flags & SHF_ALLOC) {
7978 if (s->sh_type == SHT_NOBITS)
7979 s->data = tcc_mallocz(s->data_offset);
7980 s->sh_addr = (unsigned long)s->data;
7984 relocate_syms(s1, 1);
7986 if (s1->nb_errors != 0)
7987 return -1;
7989 /* relocate each section */
7990 for(i = 1; i < s1->nb_sections; i++) {
7991 s = s1->sections[i];
7992 if (s->reloc)
7993 relocate_section(s1, s);
7995 return 0;
7998 /* launch the compiled program with the given arguments */
7999 int tcc_run(TCCState *s1, int argc, char **argv)
8001 int (*prog_main)(int, char **);
8003 if (tcc_relocate(s1) < 0)
8004 return -1;
8006 prog_main = tcc_get_symbol(s1, "main");
8008 if (do_debug) {
8009 #ifdef WIN32
8010 error("debug mode currently not available for Windows");
8011 #else
8012 struct sigaction sigact;
8013 /* install TCC signal handlers to print debug info on fatal
8014 runtime errors */
8015 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
8016 sigact.sa_sigaction = sig_error;
8017 sigemptyset(&sigact.sa_mask);
8018 sigaction(SIGFPE, &sigact, NULL);
8019 sigaction(SIGILL, &sigact, NULL);
8020 sigaction(SIGSEGV, &sigact, NULL);
8021 sigaction(SIGBUS, &sigact, NULL);
8022 sigaction(SIGABRT, &sigact, NULL);
8023 #endif
8026 #ifdef CONFIG_TCC_BCHECK
8027 if (do_bounds_check) {
8028 void (*bound_init)(void);
8030 /* set error function */
8031 rt_bound_error_msg = (void *)tcc_get_symbol(s1, "__bound_error_msg");
8033 /* XXX: use .init section so that it also work in binary ? */
8034 bound_init = (void *)tcc_get_symbol(s1, "__bound_init");
8035 bound_init();
8037 #endif
8038 return (*prog_main)(argc, argv);
8041 TCCState *tcc_new(void)
8043 const char *p, *r;
8044 TCCState *s;
8046 s = tcc_mallocz(sizeof(TCCState));
8047 if (!s)
8048 return NULL;
8049 tcc_state = s;
8050 s->output_type = TCC_OUTPUT_MEMORY;
8052 /* default include paths */
8053 tcc_add_sysinclude_path(s, "/usr/local/include");
8054 tcc_add_sysinclude_path(s, "/usr/include");
8055 tcc_add_sysinclude_path(s, CONFIG_TCC_PREFIX "/lib/tcc/include");
8057 /* add all tokens */
8058 table_ident = NULL;
8059 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
8061 tok_ident = TOK_IDENT;
8062 p = tcc_keywords;
8063 while (*p) {
8064 r = p;
8065 while (*r++);
8066 tok_alloc(p, r - p - 1);
8067 p = r;
8070 /* we add dummy defines for some special macros to speed up tests
8071 and to have working defined() */
8072 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
8073 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
8074 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
8075 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
8077 /* standard defines */
8078 tcc_define_symbol(s, "__STDC__", NULL);
8079 #if defined(TCC_TARGET_I386)
8080 tcc_define_symbol(s, "__i386__", NULL);
8081 #endif
8082 #if defined(linux)
8083 tcc_define_symbol(s, "linux", NULL);
8084 #endif
8085 /* tiny C specific defines */
8086 tcc_define_symbol(s, "__TINYC__", NULL);
8088 /* default library paths */
8089 tcc_add_library_path(s, "/usr/local/lib");
8090 tcc_add_library_path(s, "/usr/lib");
8091 tcc_add_library_path(s, "/lib");
8093 /* no section zero */
8094 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
8096 /* create standard sections */
8097 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
8098 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
8099 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
8101 /* symbols are always generated for linking stage */
8102 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
8103 ".strtab",
8104 ".hashtab", SHF_PRIVATE);
8105 strtab_section = symtab_section->link;
8107 /* private symbol table for dynamic symbols */
8108 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
8109 ".dynstrtab",
8110 ".dynhashtab", SHF_PRIVATE);
8111 return s;
8114 void tcc_delete(TCCState *s1)
8116 int i, n;
8118 /* free -D defines */
8119 free_defines(NULL);
8121 /* free tokens */
8122 n = tok_ident - TOK_IDENT;
8123 for(i = 0; i < n; i++)
8124 tcc_free(table_ident[i]);
8125 tcc_free(table_ident);
8127 /* free all sections */
8129 free_section(symtab_section->hash);
8131 free_section(s1->dynsymtab_section->hash);
8132 free_section(s1->dynsymtab_section->link);
8133 free_section(s1->dynsymtab_section);
8135 for(i = 1; i < s1->nb_sections; i++)
8136 free_section(s1->sections[i]);
8137 tcc_free(s1->sections);
8139 /* free loaded dlls array */
8140 for(i = 0; i < s1->nb_loaded_dlls; i++)
8141 tcc_free(s1->loaded_dlls[i]);
8142 tcc_free(s1->loaded_dlls);
8144 /* library paths */
8145 for(i = 0; i < s1->nb_library_paths; i++)
8146 tcc_free(s1->library_paths[i]);
8147 tcc_free(s1->library_paths);
8149 /* cached includes */
8150 for(i = 0; i < s1->nb_cached_includes; i++)
8151 tcc_free(s1->cached_includes[i]);
8152 tcc_free(s1->cached_includes);
8154 for(i = 0; i < s1->nb_include_paths; i++)
8155 tcc_free(s1->include_paths[i]);
8156 tcc_free(s1->include_paths);
8158 for(i = 0; i < s1->nb_sysinclude_paths; i++)
8159 tcc_free(s1->sysinclude_paths[i]);
8160 tcc_free(s1->sysinclude_paths);
8162 tcc_free(s1);
8165 int tcc_add_include_path(TCCState *s1, const char *pathname)
8167 char *pathname1;
8169 pathname1 = tcc_strdup(pathname);
8170 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
8171 return 0;
8174 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
8176 char *pathname1;
8178 pathname1 = tcc_strdup(pathname);
8179 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
8180 return 0;
8183 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
8185 const char *ext;
8186 Elf32_Ehdr ehdr;
8187 int fd, ret;
8188 BufferedFile *saved_file;
8190 /* find source file type with extension */
8191 ext = strrchr(filename, '.');
8192 if (ext)
8193 ext++;
8195 /* open the file */
8196 saved_file = file;
8197 file = tcc_open(s1, filename);
8198 if (!file) {
8199 if (flags & AFF_PRINT_ERROR) {
8200 error_noabort("file '%s' not found", filename);
8202 ret = -1;
8203 goto fail1;
8206 if (!ext || !strcmp(ext, "c")) {
8207 /* C file assumed */
8208 ret = tcc_compile(s1);
8209 } else {
8210 fd = file->fd;
8211 /* assume executable format: auto guess file type */
8212 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
8213 error_noabort("could not read header");
8214 goto fail;
8216 lseek(fd, 0, SEEK_SET);
8218 if (ehdr.e_ident[0] == ELFMAG0 &&
8219 ehdr.e_ident[1] == ELFMAG1 &&
8220 ehdr.e_ident[2] == ELFMAG2 &&
8221 ehdr.e_ident[3] == ELFMAG3) {
8222 file->line_num = 0; /* do not display line number if error */
8223 if (ehdr.e_type == ET_REL) {
8224 ret = tcc_load_object_file(s1, fd, 0);
8225 } else if (ehdr.e_type == ET_DYN) {
8226 ret = tcc_load_dll(s1, fd, filename,
8227 (flags & AFF_REFERENCED_DLL) != 0);
8228 } else {
8229 error_noabort("unrecognized ELF file");
8230 goto fail;
8232 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
8233 file->line_num = 0; /* do not display line number if error */
8234 ret = tcc_load_archive(s1, fd);
8235 } else {
8236 /* as GNU ld, consider it is an ld script if not recognized */
8237 ret = tcc_load_ldscript(s1);
8238 if (ret < 0) {
8239 error_noabort("unrecognized file type");
8240 goto fail;
8244 the_end:
8245 tcc_close(file);
8246 fail1:
8247 file = saved_file;
8248 return ret;
8249 fail:
8250 ret = -1;
8251 goto the_end;
8254 int tcc_add_file(TCCState *s, const char *filename)
8256 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
8259 int tcc_add_library_path(TCCState *s, const char *pathname)
8261 char *pathname1;
8263 pathname1 = tcc_strdup(pathname);
8264 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
8265 return 0;
8268 /* find and load a dll. Return non zero if not found */
8269 /* XXX: add '-rpath' option support ? */
8270 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
8272 char buf[1024];
8273 int i;
8275 for(i = 0; i < s->nb_library_paths; i++) {
8276 snprintf(buf, sizeof(buf), "%s/%s",
8277 s->library_paths[i], filename);
8278 if (tcc_add_file_internal(s, buf, flags) == 0)
8279 return 0;
8281 return -1;
8284 /* the library name is the same as the argument of the '-l' option */
8285 int tcc_add_library(TCCState *s, const char *libraryname)
8287 char buf[1024];
8288 int i;
8289 void *h;
8291 /* first we look for the dynamic library if not static linking */
8292 if (!s->static_link) {
8293 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
8294 /* if we output to memory, then we simply we dlopen(). */
8295 if (s->output_type == TCC_OUTPUT_MEMORY) {
8296 /* Since the libc is already loaded, we don't need to load it again */
8297 if (!strcmp(libraryname, "c"))
8298 return 0;
8299 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
8300 if (h)
8301 return 0;
8302 } else {
8303 if (tcc_add_dll(s, buf, 0) == 0)
8304 return 0;
8308 /* then we look for the static library */
8309 for(i = 0; i < s->nb_library_paths; i++) {
8310 snprintf(buf, sizeof(buf), "%s/lib%s.a",
8311 s->library_paths[i], libraryname);
8312 if (tcc_add_file_internal(s, buf, 0) == 0)
8313 return 0;
8315 return -1;
8318 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
8320 add_elf_sym(symtab_section, val, 0,
8321 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
8322 SHN_ABS, name);
8323 return 0;
8326 int tcc_set_output_type(TCCState *s, int output_type)
8328 s->output_type = output_type;
8330 /* if bound checking, then add corresponding sections */
8331 #ifdef CONFIG_TCC_BCHECK
8332 if (do_bounds_check) {
8333 /* define symbol */
8334 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
8335 /* create bounds sections */
8336 bounds_section = new_section(s, ".bounds",
8337 SHT_PROGBITS, SHF_ALLOC);
8338 lbounds_section = new_section(s, ".lbounds",
8339 SHT_PROGBITS, SHF_ALLOC);
8341 #endif
8343 /* add debug sections */
8344 if (do_debug) {
8345 /* stab symbols */
8346 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
8347 stab_section->sh_entsize = sizeof(Stab_Sym);
8348 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
8349 put_elf_str(stabstr_section, "");
8350 stab_section->link = stabstr_section;
8351 /* put first entry */
8352 put_stabs("", 0, 0, 0, 0);
8355 /* add libc crt1/crti objects */
8356 if (output_type == TCC_OUTPUT_EXE ||
8357 output_type == TCC_OUTPUT_DLL) {
8358 if (output_type != TCC_OUTPUT_DLL)
8359 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
8360 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
8362 return 0;
8365 #if !defined(LIBTCC)
8367 static int64_t getclock_us(void)
8369 #ifdef WIN32
8370 struct _timeb tb;
8371 _ftime(&tb);
8372 return (tb.time * 1000LL + tb.millitm) * 1000LL;
8373 #else
8374 struct timeval tv;
8375 gettimeofday(&tv, NULL);
8376 return tv.tv_sec * 1000000LL + tv.tv_usec;
8377 #endif
8380 void help(void)
8382 printf("tcc version 0.9.13 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
8383 "usage: tcc [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
8384 " [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
8385 " [--] infile1 [infile2... --] [infile_args...]\n"
8386 "\n"
8387 "General options:\n"
8388 " -c compile only - generate an object file\n"
8389 " -o outfile set output filename\n"
8390 " -- allows multiples input files if no -o option given. Also\n"
8391 " separate input files from runtime arguments\n"
8392 " -Bdir set tcc internal library path\n"
8393 " -bench output compilation statistics\n"
8394 "Preprocessor options:\n"
8395 " -Idir add include path 'dir'\n"
8396 " -Dsym[=val] define 'sym' with value 'val'\n"
8397 " -Usym undefine 'sym'\n"
8398 "Linker options:\n"
8399 " -Ldir add library path 'dir'\n"
8400 " -llib link with dynamic or static library 'lib'\n"
8401 " -shared generate a shared library\n"
8402 " -static static linking\n"
8403 " -r relocatable output\n"
8404 "Debugger options:\n"
8405 " -g generate runtime debug info\n"
8406 #ifdef CONFIG_TCC_BCHECK
8407 " -b compile with built-in memory and bounds checker (implies -g)\n"
8408 #endif
8409 " -bt N show N callers in stack traces\n"
8413 int main(int argc, char **argv)
8415 char *r, *outfile;
8416 int optind, output_type, multiple_files, i, reloc_output;
8417 TCCState *s;
8418 char **files;
8419 int nb_files, nb_libraries, nb_objfiles, dminus, ret;
8420 char objfilename[1024];
8421 int64_t start_time = 0;
8423 s = tcc_new();
8424 output_type = TCC_OUTPUT_MEMORY;
8426 optind = 1;
8427 outfile = NULL;
8428 multiple_files = 0;
8429 dminus = 0;
8430 files = NULL;
8431 nb_files = 0;
8432 nb_libraries = 0;
8433 reloc_output = 0;
8434 while (1) {
8435 if (optind >= argc) {
8436 if (nb_files == 0)
8437 goto show_help;
8438 else
8439 break;
8441 r = argv[optind++];
8442 if (r[0] != '-') {
8443 /* add a new file */
8444 dynarray_add((void ***)&files, &nb_files, r);
8445 if (!multiple_files) {
8446 optind--;
8447 /* argv[0] will be this file */
8448 break;
8450 } else if (r[1] == '-') {
8451 /* '--' enables multiple files input and also ends several file input */
8452 if (dminus && multiple_files) {
8453 optind--; /* argv[0] will be '--' */
8454 break;
8456 dminus = 1;
8457 multiple_files = 1;
8458 } else if (r[1] == 'h' || r[1] == '?') {
8459 show_help:
8460 help();
8461 return 1;
8462 } else if (r[1] == 'I') {
8463 if (tcc_add_include_path(s, r + 2) < 0)
8464 error("too many include paths");
8465 } else if (r[1] == 'D') {
8466 char *sym, *value;
8467 sym = r + 2;
8468 value = strchr(sym, '=');
8469 if (value) {
8470 *value = '\0';
8471 value++;
8473 tcc_define_symbol(s, sym, value);
8474 } else if (r[1] == 'U') {
8475 tcc_undefine_symbol(s, r + 2);
8476 } else if (r[1] == 'L') {
8477 tcc_add_library_path(s, r + 2);
8478 } else if (r[1] == 'B') {
8479 /* set tcc utilities path (mainly for tcc development) */
8480 tcc_lib_path = r + 2;
8481 } else if (r[1] == 'l') {
8482 dynarray_add((void ***)&files, &nb_files, r);
8483 nb_libraries++;
8484 } else if (!strcmp(r + 1, "bench")) {
8485 do_bench = 1;
8486 } else if (!strcmp(r + 1, "bt")) {
8487 num_callers = atoi(argv[optind++]);
8488 } else
8489 #ifdef CONFIG_TCC_BCHECK
8490 if (r[1] == 'b') {
8491 do_bounds_check = 1;
8492 do_debug = 1;
8493 } else
8494 #endif
8495 if (r[1] == 'g') {
8496 do_debug = 1;
8497 } else if (r[1] == 'c') {
8498 multiple_files = 1;
8499 output_type = TCC_OUTPUT_OBJ;
8500 } else if (!strcmp(r + 1, "static")) {
8501 s->static_link = 1;
8502 } else if (!strcmp(r + 1, "shared")) {
8503 output_type = TCC_OUTPUT_DLL;
8504 } else if (r[1] == 'o') {
8505 if (optind >= argc)
8506 goto show_help;
8507 multiple_files = 1;
8508 outfile = argv[optind++];
8509 } else if (r[1] == 'r') {
8510 /* generate a .o merging several output files */
8511 reloc_output = 1;
8512 output_type = TCC_OUTPUT_OBJ;
8513 } else if (r[1] == 'W' || r[1] == 'O' || r[1] == 'm' || r[1] == 'f') {
8514 /* ignore those options to be a drop-in replacement for gcc */
8515 } else {
8516 error("invalid option -- '%s'", r);
8520 nb_objfiles = nb_files - nb_libraries;
8522 /* if outfile provided without other options, we output an
8523 executable */
8524 if (outfile && output_type == TCC_OUTPUT_MEMORY)
8525 output_type = TCC_OUTPUT_EXE;
8527 /* check -c consistency : only single file handled. XXX: checks file type */
8528 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
8529 /* accepts only a single input file */
8530 if (nb_objfiles != 1)
8531 error("cannot specify multiple files with -c");
8532 if (nb_libraries != 0)
8533 error("cannot specify libraries with -c");
8536 /* compute default outfile name */
8537 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
8538 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
8539 char *ext;
8540 /* add .o extension */
8541 pstrcpy(objfilename, sizeof(objfilename) - 1, files[0]);
8542 ext = strrchr(objfilename, '.');
8543 if (!ext)
8544 goto default_outfile;
8545 strcpy(ext + 1, "o");
8546 } else {
8547 default_outfile:
8548 pstrcpy(objfilename, sizeof(objfilename), "a.out");
8550 outfile = objfilename;
8553 if (do_bench) {
8554 start_time = getclock_us();
8557 tcc_set_output_type(s, output_type);
8559 /* compile or add each files or library */
8560 for(i = 0;i < nb_files; i++) {
8561 const char *filename;
8563 filename = files[i];
8564 if (filename[0] == '-') {
8565 if (tcc_add_library(s, filename + 2) < 0)
8566 error("cannot find %s", filename);
8567 } else {
8568 if (tcc_add_file(s, filename) < 0) {
8569 ret = 1;
8570 goto the_end;
8575 /* free all files */
8576 tcc_free(files);
8578 if (do_bench) {
8579 double total_time;
8580 total_time = (double)(getclock_us() - start_time) / 1000000.0;
8581 if (total_time < 0.001)
8582 total_time = 0.001;
8583 if (total_bytes < 1)
8584 total_bytes = 1;
8585 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
8586 tok_ident - TOK_IDENT, total_lines, total_bytes,
8587 total_time, (int)(total_lines / total_time),
8588 total_bytes / total_time / 1000000.0);
8591 if (s->output_type != TCC_OUTPUT_MEMORY) {
8592 tcc_output_file(s, outfile);
8593 ret = 0;
8594 } else {
8595 ret = tcc_run(s, argc - optind, argv + optind);
8597 the_end:
8598 /* XXX: cannot do it with bound checking because of the malloc hooks */
8599 if (!do_bounds_check)
8600 tcc_delete(s);
8602 #ifdef MEM_DEBUG
8603 if (do_bench) {
8604 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
8606 #endif
8607 return ret;
8610 #endif