optimized unary() - fix long long signed comparisons
[tinycc/miki.git] / tcc.c
blobfc753c457f76655836bbc8225b4589d2616652a9
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 */
83 #define TOK_STR_ALLOC_INCR_BITS 6
84 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
85 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
87 /* token symbol management */
88 typedef struct TokenSym {
89 struct TokenSym *hash_next;
90 struct Sym *sym_define; /* direct pointer to define */
91 struct Sym *sym_label; /* direct pointer to label */
92 struct Sym *sym_struct; /* direct pointer to structure */
93 struct Sym *sym_identifier; /* direct pointer to identifier */
94 int tok; /* token number */
95 int len;
96 char str[1];
97 } TokenSym;
99 typedef struct CString {
100 int size; /* size in bytes */
101 void *data; /* either 'char *' or 'int *' */
102 int size_allocated;
103 void *data_allocated; /* if non NULL, data has been malloced */
104 } CString;
106 /* type definition */
107 typedef struct CType {
108 int t;
109 struct Sym *ref;
110 } CType;
112 /* constant value */
113 typedef union CValue {
114 long double ld;
115 double d;
116 float f;
117 int i;
118 unsigned int ui;
119 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
120 long long ll;
121 unsigned long long ull;
122 struct CString *cstr;
123 void *ptr;
124 int tab[1];
125 } CValue;
127 /* value on stack */
128 typedef struct SValue {
129 CType type; /* type */
130 unsigned short r; /* register + flags */
131 unsigned short r2; /* second register, used for 'long long'
132 type. If not used, set to VT_CONST */
133 CValue c; /* constant, if VT_CONST */
134 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
135 } SValue;
137 /* symbol management */
138 typedef struct Sym {
139 int v; /* symbol token */
140 int r; /* associated register */
141 int c; /* associated number */
142 CType type; /* associated type */
143 struct Sym *next; /* next related symbol */
144 struct Sym *prev; /* prev symbol in stack */
145 struct Sym *prev_tok; /* previous symbol for this token */
146 } Sym;
148 /* section definition */
149 /* XXX: use directly ELF structure for parameters ? */
150 /* special flag to indicate that the section should not be linked to
151 the other ones */
152 #define SHF_PRIVATE 0x80000000
154 typedef struct Section {
155 unsigned long data_offset; /* current data offset */
156 unsigned char *data; /* section data */
157 unsigned long data_allocated; /* used for realloc() handling */
158 int sh_name; /* elf section name (only used during output) */
159 int sh_num; /* elf section number */
160 int sh_type; /* elf section type */
161 int sh_flags; /* elf section flags */
162 int sh_info; /* elf section info */
163 int sh_addralign; /* elf section alignment */
164 int sh_entsize; /* elf entry size */
165 unsigned long sh_size; /* section size (only used during output) */
166 unsigned long sh_addr; /* address at which the section is relocated */
167 unsigned long sh_offset; /* address at which the section is relocated */
168 int nb_hashed_syms; /* used to resize the hash table */
169 struct Section *link; /* link to another section */
170 struct Section *reloc; /* corresponding section for relocation, if any */
171 struct Section *hash; /* hash table for symbols */
172 struct Section *next;
173 char name[64]; /* section name */
174 } Section;
176 typedef struct DLLReference {
177 int level;
178 char name[1];
179 } DLLReference;
181 /* GNUC attribute definition */
182 typedef struct AttributeDef {
183 int aligned;
184 Section *section;
185 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
186 } AttributeDef;
188 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
189 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
190 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
192 /* stored in 'Sym.c' field */
193 #define FUNC_NEW 1 /* ansi function prototype */
194 #define FUNC_OLD 2 /* old function prototype */
195 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
197 /* stored in 'Sym.r' field */
198 #define FUNC_CDECL 0 /* standard c call */
199 #define FUNC_STDCALL 1 /* pascal c call */
201 /* field 'Sym.t' for macros */
202 #define MACRO_OBJ 0 /* object like macro */
203 #define MACRO_FUNC 1 /* function like macro */
205 /* field 'Sym.r' for labels */
206 #define LABEL_FORWARD 1 /* label is forward defined */
208 /* type_decl() types */
209 #define TYPE_ABSTRACT 1 /* type without variable */
210 #define TYPE_DIRECT 2 /* type with variable */
212 #define IO_BUF_SIZE 8192
214 typedef struct BufferedFile {
215 uint8_t *buf_ptr;
216 uint8_t *buf_end;
217 int fd;
218 int line_num; /* current line number - here to simply code */
219 int ifndef_macro; /* #ifndef macro / #endif search */
220 int ifndef_macro_saved; /* saved ifndef_macro */
221 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
222 char inc_type; /* type of include */
223 char inc_filename[512]; /* filename specified by the user */
224 char filename[1024]; /* current filename - here to simplify code */
225 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
226 } BufferedFile;
228 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
229 #define CH_EOF (-1) /* end of file */
231 /* parsing state (used to save parser state to reparse part of the
232 source several times) */
233 typedef struct ParseState {
234 int *macro_ptr;
235 int line_num;
236 int tok;
237 CValue tokc;
238 } ParseState;
240 /* used to record tokens */
241 typedef struct TokenString {
242 int *str;
243 int len;
244 int allocated_len;
245 int last_line_num;
246 } TokenString;
248 /* include file cache, used to find files faster and also to eliminate
249 inclusion if the include file is protected by #ifndef ... #endif */
250 typedef struct CachedInclude {
251 int ifndef_macro;
252 char type; /* '"' or '>' to give include type */
253 char filename[1]; /* path specified in #include */
254 } CachedInclude;
256 /* parser */
257 static struct BufferedFile *file;
258 static int ch, tok, tok1;
259 static CValue tokc, tok1c;
260 static CString tokcstr; /* current parsed string, if any */
261 /* additionnal informations about token */
262 static int tok_flags;
263 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
264 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
265 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
267 /* if true, line feed is returned as a token. line feed is also
268 returned at eof */
269 static int return_linefeed;
270 static Section *text_section, *data_section, *bss_section; /* predefined sections */
271 static Section *cur_text_section; /* current section where function code is
272 generated */
273 /* bound check related sections */
274 static Section *bounds_section; /* contains global data bound description */
275 static Section *lbounds_section; /* contains local data bound description */
276 /* symbol sections */
277 static Section *symtab_section, *strtab_section;
279 /* debug sections */
280 static Section *stab_section, *stabstr_section;
282 /* loc : local variable index
283 ind : output code index
284 rsym: return symbol
285 anon_sym: anonymous symbol index
287 static int rsym, anon_sym, ind, loc;
288 /* expression generation modifiers */
289 static int const_wanted; /* true if constant wanted */
290 static int nocode_wanted; /* true if no code generation wanted for an expression */
291 static int global_expr; /* true if compound literals must be allocated
292 globally (used during initializers parsing */
293 static CType func_vt; /* current function return type (used by return
294 instruction) */
295 static int func_vc;
296 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
297 static int tok_ident;
298 static TokenSym **table_ident;
299 static TokenSym *hash_ident[TOK_HASH_SIZE];
300 static char token_buf[STRING_MAX_SIZE + 1];
301 static char *funcname;
302 static Sym *global_stack, *local_stack;
303 static Sym *define_stack;
304 static Sym *label_stack;
306 static SValue vstack[VSTACK_SIZE], *vtop;
307 static int *macro_ptr, *macro_ptr_allocated;
308 /* some predefined types */
309 static CType char_pointer_type, func_old_type, int_type;
311 /* compile with debug symbol (and use them if error during execution) */
312 static int do_debug = 0;
314 /* compile with built-in memory and bounds checker */
315 static int do_bounds_check = 0;
317 /* display benchmark infos */
318 static int do_bench = 0;
319 static int total_lines;
320 static int total_bytes;
322 /* use GNU C extensions */
323 static int gnu_ext = 1;
325 /* use Tiny C extensions */
326 static int tcc_ext = 1;
328 /* max number of callers shown if error */
329 static int num_callers = 6;
330 static const char **rt_bound_error_msg;
332 /* XXX: suppress that ASAP */
333 static struct TCCState *tcc_state;
335 /* give the path of the tcc libraries */
336 static const char *tcc_lib_path = CONFIG_TCC_PREFIX "/lib/tcc";
338 struct TCCState {
339 int output_type;
341 BufferedFile **include_stack_ptr;
342 int *ifdef_stack_ptr;
344 /* include file handling */
345 char **include_paths;
346 int nb_include_paths;
347 char **sysinclude_paths;
348 int nb_sysinclude_paths;
349 CachedInclude **cached_includes;
350 int nb_cached_includes;
352 char **library_paths;
353 int nb_library_paths;
355 /* array of all loaded dlls (including those referenced by loaded
356 dlls) */
357 DLLReference **loaded_dlls;
358 int nb_loaded_dlls;
360 /* sections */
361 Section **sections;
362 int nb_sections; /* number of sections, including first dummy section */
364 /* got handling */
365 Section *got;
366 unsigned long *got_offsets;
367 int nb_got_offsets;
368 int nb_plt_entries;
369 /* give the correspondance from symtab indexes to dynsym indexes */
370 int *symtab_to_dynsym;
372 /* temporary dynamic symbol sections (for dll loading) */
373 Section *dynsymtab_section;
374 /* exported dynamic symbol section */
375 Section *dynsym;
377 /* if true, static linking is performed */
378 int static_link;
380 /* error handling */
381 void *error_opaque;
382 void (*error_func)(void *opaque, const char *msg);
383 int error_set_jmp_enabled;
384 jmp_buf error_jmp_buf;
385 int nb_errors;
387 /* see include_stack_ptr */
388 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
390 /* see ifdef_stack_ptr */
391 int ifdef_stack[IFDEF_STACK_SIZE];
394 /* The current value can be: */
395 #define VT_VALMASK 0x00ff
396 #define VT_CONST 0x00f0 /* constant in vc
397 (must be first non register value) */
398 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
399 #define VT_LOCAL 0x00f2 /* offset on stack */
400 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
401 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
402 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
403 #define VT_LVAL 0x0100 /* var is an lvalue */
404 #define VT_SYM 0x0200 /* a symbol value is added */
405 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
406 char/short stored in integer registers) */
407 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
408 dereferencing value */
409 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
410 bounding function call point is in vc */
411 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
412 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
413 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
414 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
416 /* types */
417 #define VT_STRUCT_SHIFT 12 /* structure/enum name shift (20 bits left) */
419 #define VT_INT 0 /* integer type */
420 #define VT_BYTE 1 /* signed byte type */
421 #define VT_SHORT 2 /* short type */
422 #define VT_VOID 3 /* void type */
423 #define VT_PTR 4 /* pointer */
424 #define VT_ENUM 5 /* enum definition */
425 #define VT_FUNC 6 /* function type */
426 #define VT_STRUCT 7 /* struct/union definition */
427 #define VT_FLOAT 8 /* IEEE float */
428 #define VT_DOUBLE 9 /* IEEE double */
429 #define VT_LDOUBLE 10 /* IEEE long double */
430 #define VT_BOOL 11 /* ISOC99 boolean type */
431 #define VT_LLONG 12 /* 64 bit integer */
432 #define VT_LONG 13 /* long integer (NEVER USED as type, only
433 during parsing) */
434 #define VT_BTYPE 0x000f /* mask for basic type */
435 #define VT_UNSIGNED 0x0010 /* unsigned type */
436 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
437 #define VT_BITFIELD 0x0040 /* bitfield modifier */
439 /* storage */
440 #define VT_EXTERN 0x00000080 /* extern definition */
441 #define VT_STATIC 0x00000100 /* static variable */
442 #define VT_TYPEDEF 0x00000200 /* typedef definition */
444 /* type mask (except storage) */
445 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
447 /* token values */
449 /* warning: the following compare tokens depend on i386 asm code */
450 #define TOK_ULT 0x92
451 #define TOK_UGE 0x93
452 #define TOK_EQ 0x94
453 #define TOK_NE 0x95
454 #define TOK_ULE 0x96
455 #define TOK_UGT 0x97
456 #define TOK_LT 0x9c
457 #define TOK_GE 0x9d
458 #define TOK_LE 0x9e
459 #define TOK_GT 0x9f
461 #define TOK_LAND 0xa0
462 #define TOK_LOR 0xa1
464 #define TOK_DEC 0xa2
465 #define TOK_MID 0xa3 /* inc/dec, to void constant */
466 #define TOK_INC 0xa4
467 #define TOK_UDIV 0xb0 /* unsigned division */
468 #define TOK_UMOD 0xb1 /* unsigned modulo */
469 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
470 #define TOK_CINT 0xb3 /* number in tokc */
471 #define TOK_CCHAR 0xb4 /* char constant in tokc */
472 #define TOK_STR 0xb5 /* pointer to string in tokc */
473 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
474 #define TOK_LCHAR 0xb7
475 #define TOK_LSTR 0xb8
476 #define TOK_CFLOAT 0xb9 /* float constant */
477 #define TOK_LINENUM 0xba /* line number info */
478 #define TOK_CDOUBLE 0xc0 /* double constant */
479 #define TOK_CLDOUBLE 0xc1 /* long double constant */
480 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
481 #define TOK_ADDC1 0xc3 /* add with carry generation */
482 #define TOK_ADDC2 0xc4 /* add with carry use */
483 #define TOK_SUBC1 0xc5 /* add with carry generation */
484 #define TOK_SUBC2 0xc6 /* add with carry use */
485 #define TOK_CUINT 0xc8 /* unsigned int constant */
486 #define TOK_CLLONG 0xc9 /* long long constant */
487 #define TOK_CULLONG 0xca /* unsigned long long constant */
488 #define TOK_ARROW 0xcb
489 #define TOK_DOTS 0xcc /* three dots */
490 #define TOK_SHR 0xcd /* unsigned shift right */
491 #define TOK_PPNUM 0xce /* preprocessor number */
493 #define TOK_SHL 0x01 /* shift left */
494 #define TOK_SAR 0x02 /* signed shift right */
496 /* assignement operators : normal operator or 0x80 */
497 #define TOK_A_MOD 0xa5
498 #define TOK_A_AND 0xa6
499 #define TOK_A_MUL 0xaa
500 #define TOK_A_ADD 0xab
501 #define TOK_A_SUB 0xad
502 #define TOK_A_DIV 0xaf
503 #define TOK_A_XOR 0xde
504 #define TOK_A_OR 0xfc
505 #define TOK_A_SHL 0x81
506 #define TOK_A_SAR 0x82
508 /* WARNING: the content of this string encodes token numbers */
509 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";
511 #define TOK_EOF (-1) /* end of file */
512 #define TOK_LINEFEED 10 /* line feed */
514 /* all identificators and strings have token above that */
515 #define TOK_IDENT 256
517 enum {
518 TOK_LAST = TOK_IDENT - 1,
519 #define DEF(id, str) id,
520 #include "tcctok.h"
521 #undef DEF
524 static const char *tcc_keywords =
525 #define DEF(id, str) str "\0"
526 #include "tcctok.h"
527 #undef DEF
530 #define TOK_UIDENT TOK_DEFINE
532 #ifdef WIN32
533 #define snprintf _snprintf
534 #define vsnprintf _vsnprintf
535 #endif
537 #if defined(WIN32) || defined(TCC_UCLIBC)
538 /* currently incorrect */
539 long double strtold(const char *nptr, char **endptr)
541 return (long double)strtod(nptr, endptr);
543 float strtof(const char *nptr, char **endptr)
545 return (float)strtod(nptr, endptr);
547 #else
548 /* XXX: need to define this to use them in non ISOC99 context */
549 extern float strtof (const char *__nptr, char **__endptr);
550 extern long double strtold (const char *__nptr, char **__endptr);
551 #endif
553 static char *pstrcpy(char *buf, int buf_size, const char *s);
554 static char *pstrcat(char *buf, int buf_size, const char *s);
556 static void next(void);
557 static void next_nomacro(void);
558 static void parse_expr_type(CType *type);
559 static void expr_type(CType *type);
560 static void unary_type(CType *type);
561 static int expr_const(void);
562 static void expr_eq(void);
563 static void gexpr(void);
564 static void decl(int l);
565 static void decl_initializer(CType *type, Section *sec, unsigned long c,
566 int first, int size_only);
567 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
568 int has_init, int v, int scope);
569 int gv(int rc);
570 void gv2(int rc1, int rc2);
571 void move_reg(int r, int s);
572 void save_regs(int n);
573 void save_reg(int r);
574 void vpop(void);
575 void vswap(void);
576 void vdup(void);
577 int get_reg(int rc);
579 static void macro_subst(TokenString *tok_str,
580 Sym **nested_list, int *macro_str);
581 int save_reg_forced(int r);
582 void gen_op(int op);
583 void force_charshort_cast(int t);
584 static void gen_cast(CType *type);
585 void vstore(void);
586 static Sym *sym_find(int v);
587 static Sym *sym_push(int v, CType *type, int r, int c);
589 /* type handling */
590 int type_size(CType *type, int *a);
591 static inline CType *pointed_type(CType *type);
592 static int pointed_size(CType *type);
593 static int lvalue_type(int t);
594 static int is_compatible_types(CType *type1, CType *type2);
595 static int parse_btype(CType *type, AttributeDef *ad);
596 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
598 void error(const char *fmt, ...);
599 void vpushi(int v);
600 void vset(CType *type, int r, int v);
601 void type_to_str(char *buf, int buf_size,
602 CType *type, const char *varstr);
603 char *get_tok_str(int v, CValue *cv);
604 static Sym *get_sym_ref(CType *type, Section *sec,
605 unsigned long offset, unsigned long size);
606 static Sym *external_global_sym(int v, CType *type, int r);
608 /* section generation */
609 static void section_realloc(Section *sec, unsigned long new_size);
610 static void *section_ptr_add(Section *sec, unsigned long size);
611 static void put_extern_sym(Sym *sym, Section *section,
612 unsigned long value, unsigned long size);
613 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
614 static int put_elf_str(Section *s, const char *sym);
615 static int put_elf_sym(Section *s,
616 unsigned long value, unsigned long size,
617 int info, int other, int shndx, const char *name);
618 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
619 int info, int sh_num, const char *name);
620 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
621 int type, int symbol);
622 static void put_stabs(const char *str, int type, int other, int desc,
623 unsigned long value);
624 static void put_stabs_r(const char *str, int type, int other, int desc,
625 unsigned long value, Section *sec, int sym_index);
626 static void put_stabn(int type, int other, int desc, int value);
627 static void put_stabd(int type, int other, int desc);
628 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
630 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
631 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
632 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
634 /* true if float/double/long double type */
635 static inline int is_float(int t)
637 int bt;
638 bt = t & VT_BTYPE;
639 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
642 #ifdef TCC_TARGET_I386
643 #include "i386-gen.c"
644 #endif
645 #ifdef TCC_TARGET_IL
646 #include "il-gen.c"
647 #endif
649 #ifdef CONFIG_TCC_STATIC
651 #define RTLD_LAZY 0x001
652 #define RTLD_NOW 0x002
653 #define RTLD_GLOBAL 0x100
654 #define RTLD_DEFAULT NULL
656 /* dummy function for profiling */
657 void *dlopen(const char *filename, int flag)
659 return NULL;
662 const char *dlerror(void)
664 return "error";
667 typedef struct TCCSyms {
668 char *str;
669 void *ptr;
670 } TCCSyms;
672 #define TCCSYM(a) { #a, &a, },
674 /* add the symbol you want here if no dynamic linking is done */
675 static TCCSyms tcc_syms[] = {
676 TCCSYM(printf)
677 TCCSYM(fprintf)
678 TCCSYM(fopen)
679 TCCSYM(fclose)
680 { NULL, NULL },
683 void *dlsym(void *handle, const char *symbol)
685 TCCSyms *p;
686 p = tcc_syms;
687 while (p->str != NULL) {
688 if (!strcmp(p->str, symbol))
689 return p->ptr;
690 p++;
692 return NULL;
695 #endif
697 /********************************************************/
699 /* we use our own 'finite' function to avoid potential problems with
700 non standard math libs */
701 /* XXX: endianness dependant */
702 int ieee_finite(double d)
704 int *p = (int *)&d;
705 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
708 /* copy a string and truncate it. */
709 static char *pstrcpy(char *buf, int buf_size, const char *s)
711 char *q, *q_end;
712 int c;
714 if (buf_size > 0) {
715 q = buf;
716 q_end = buf + buf_size - 1;
717 while (q < q_end) {
718 c = *s++;
719 if (c == '\0')
720 break;
721 *q++ = c;
723 *q = '\0';
725 return buf;
728 /* strcat and truncate. */
729 static char *pstrcat(char *buf, int buf_size, const char *s)
731 int len;
732 len = strlen(buf);
733 if (len < buf_size)
734 pstrcpy(buf + len, buf_size - len, s);
735 return buf;
738 /* memory management */
739 #ifdef MEM_DEBUG
740 int mem_cur_size;
741 int mem_max_size;
742 #endif
744 static inline void tcc_free(void *ptr)
746 #ifdef MEM_DEBUG
747 mem_cur_size -= malloc_usable_size(ptr);
748 #endif
749 free(ptr);
752 static void *tcc_malloc(unsigned long size)
754 void *ptr;
755 ptr = malloc(size);
756 if (!ptr && size)
757 error("memory full");
758 #ifdef MEM_DEBUG
759 mem_cur_size += malloc_usable_size(ptr);
760 if (mem_cur_size > mem_max_size)
761 mem_max_size = mem_cur_size;
762 #endif
763 return ptr;
766 static void *tcc_mallocz(unsigned long size)
768 void *ptr;
769 ptr = tcc_malloc(size);
770 memset(ptr, 0, size);
771 return ptr;
774 static inline void *tcc_realloc(void *ptr, unsigned long size)
776 void *ptr1;
777 #ifdef MEM_DEBUG
778 mem_cur_size -= malloc_usable_size(ptr);
779 #endif
780 ptr1 = realloc(ptr, size);
781 #ifdef MEM_DEBUG
782 /* NOTE: count not correct if alloc error, but not critical */
783 mem_cur_size += malloc_usable_size(ptr1);
784 if (mem_cur_size > mem_max_size)
785 mem_max_size = mem_cur_size;
786 #endif
787 return ptr1;
790 static char *tcc_strdup(const char *str)
792 char *ptr;
793 ptr = tcc_malloc(strlen(str) + 1);
794 strcpy(ptr, str);
795 return ptr;
798 #define free(p) use_tcc_free(p)
799 #define malloc(s) use_tcc_malloc(s)
800 #define realloc(p, s) use_tcc_realloc(p, s)
802 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
804 int nb, nb_alloc;
805 void **pp;
807 nb = *nb_ptr;
808 pp = *ptab;
809 /* every power of two we double array size */
810 if ((nb & (nb - 1)) == 0) {
811 if (!nb)
812 nb_alloc = 1;
813 else
814 nb_alloc = nb * 2;
815 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
816 if (!pp)
817 error("memory full");
818 *ptab = pp;
820 pp[nb++] = data;
821 *nb_ptr = nb;
824 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
826 Section *sec;
828 sec = tcc_mallocz(sizeof(Section));
829 pstrcpy(sec->name, sizeof(sec->name), name);
830 sec->sh_type = sh_type;
831 sec->sh_flags = sh_flags;
832 switch(sh_type) {
833 case SHT_HASH:
834 case SHT_REL:
835 case SHT_DYNSYM:
836 case SHT_SYMTAB:
837 case SHT_DYNAMIC:
838 sec->sh_addralign = 4;
839 break;
840 case SHT_STRTAB:
841 sec->sh_addralign = 1;
842 break;
843 default:
844 sec->sh_addralign = 32; /* default conservative alignment */
845 break;
848 /* only add section if not private */
849 if (!(sh_flags & SHF_PRIVATE)) {
850 sec->sh_num = s1->nb_sections;
851 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
853 return sec;
856 static void free_section(Section *s)
858 tcc_free(s->data);
859 tcc_free(s);
862 /* realloc section and set its content to zero */
863 static void section_realloc(Section *sec, unsigned long new_size)
865 unsigned long size;
866 unsigned char *data;
868 size = sec->data_allocated;
869 if (size == 0)
870 size = 1;
871 while (size < new_size)
872 size = size * 2;
873 data = tcc_realloc(sec->data, size);
874 if (!data)
875 error("memory full");
876 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
877 sec->data = data;
878 sec->data_allocated = size;
881 /* reserve at least 'size' bytes in section 'sec' from
882 sec->data_offset. */
883 static void *section_ptr_add(Section *sec, unsigned long size)
885 unsigned long offset, offset1;
887 offset = sec->data_offset;
888 offset1 = offset + size;
889 if (offset1 > sec->data_allocated)
890 section_realloc(sec, offset1);
891 sec->data_offset = offset1;
892 return sec->data + offset;
895 /* return a reference to a section, and create it if it does not
896 exists */
897 Section *find_section(TCCState *s1, const char *name)
899 Section *sec;
900 int i;
901 for(i = 1; i < s1->nb_sections; i++) {
902 sec = s1->sections[i];
903 if (!strcmp(name, sec->name))
904 return sec;
906 /* sections are created as PROGBITS */
907 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
910 /* update sym->c so that it points to an external symbol in section
911 'section' with value 'value' */
912 static void put_extern_sym(Sym *sym, Section *section,
913 unsigned long value, unsigned long size)
915 int sym_type, sym_bind, sh_num, info;
916 Elf32_Sym *esym;
917 const char *name;
919 if (section)
920 sh_num = section->sh_num;
921 else
922 sh_num = SHN_UNDEF;
923 if (!sym->c) {
924 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
925 sym_type = STT_FUNC;
926 else
927 sym_type = STT_OBJECT;
928 if (sym->type.t & VT_STATIC)
929 sym_bind = STB_LOCAL;
930 else
931 sym_bind = STB_GLOBAL;
933 name = get_tok_str(sym->v, NULL);
934 #ifdef CONFIG_TCC_BCHECK
935 if (do_bounds_check) {
936 char buf[32];
938 /* XXX: avoid doing that for statics ? */
939 /* if bound checking is activated, we change some function
940 names by adding the "__bound" prefix */
941 switch(sym->v) {
942 #if 0
943 /* XXX: we rely only on malloc hooks */
944 case TOK_malloc:
945 case TOK_free:
946 case TOK_realloc:
947 case TOK_memalign:
948 case TOK_calloc:
949 #endif
950 case TOK_memcpy:
951 case TOK_memmove:
952 case TOK_memset:
953 case TOK_strlen:
954 case TOK_strcpy:
955 strcpy(buf, "__bound_");
956 strcat(buf, name);
957 name = buf;
958 break;
961 #endif
962 info = ELF32_ST_INFO(sym_bind, sym_type);
963 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
964 } else {
965 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
966 esym->st_value = value;
967 esym->st_size = size;
968 esym->st_shndx = sh_num;
972 /* add a new relocation entry to symbol 'sym' in section 's' */
973 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
975 if (!sym->c)
976 put_extern_sym(sym, NULL, 0, 0);
977 /* now we can add ELF relocation info */
978 put_elf_reloc(symtab_section, s, offset, type, sym->c);
981 static inline int isid(int c)
983 return (c >= 'a' && c <= 'z') ||
984 (c >= 'A' && c <= 'Z') ||
985 c == '_';
988 static inline int isnum(int c)
990 return c >= '0' && c <= '9';
993 static inline int isoct(int c)
995 return c >= '0' && c <= '7';
998 static inline int toup(int c)
1000 if (c >= 'a' && c <= 'z')
1001 return c - 'a' + 'A';
1002 else
1003 return c;
1006 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1008 int len;
1009 len = strlen(buf);
1010 vsnprintf(buf + len, buf_size - len, fmt, ap);
1013 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1015 va_list ap;
1016 va_start(ap, fmt);
1017 strcat_vprintf(buf, buf_size, fmt, ap);
1018 va_end(ap);
1021 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1023 char buf[2048];
1024 BufferedFile **f;
1026 buf[0] = '\0';
1027 if (file) {
1028 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1029 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1030 (*f)->filename, (*f)->line_num);
1031 if (file->line_num > 0) {
1032 strcat_printf(buf, sizeof(buf),
1033 "%s:%d: ", file->filename, file->line_num);
1034 } else {
1035 strcat_printf(buf, sizeof(buf),
1036 "%s: ", file->filename);
1038 } else {
1039 strcat_printf(buf, sizeof(buf),
1040 "tcc: ");
1042 if (is_warning)
1043 strcat_printf(buf, sizeof(buf), "warning: ");
1044 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1046 if (!s1->error_func) {
1047 /* default case: stderr */
1048 fprintf(stderr, "%s\n", buf);
1049 } else {
1050 s1->error_func(s1->error_opaque, buf);
1052 if (!is_warning)
1053 s1->nb_errors++;
1056 #ifdef LIBTCC
1057 void tcc_set_error_func(TCCState *s, void *error_opaque,
1058 void (*error_func)(void *opaque, const char *msg))
1060 s->error_opaque = error_opaque;
1061 s->error_func = error_func;
1063 #endif
1065 /* error without aborting current compilation */
1066 void error_noabort(const char *fmt, ...)
1068 TCCState *s1 = tcc_state;
1069 va_list ap;
1071 va_start(ap, fmt);
1072 error1(s1, 0, fmt, ap);
1073 va_end(ap);
1076 void error(const char *fmt, ...)
1078 TCCState *s1 = tcc_state;
1079 va_list ap;
1081 va_start(ap, fmt);
1082 error1(s1, 0, fmt, ap);
1083 va_end(ap);
1084 /* better than nothing: in some cases, we accept to handle errors */
1085 if (s1->error_set_jmp_enabled) {
1086 longjmp(s1->error_jmp_buf, 1);
1087 } else {
1088 /* XXX: suppress it someday */
1089 exit(1);
1093 void expect(const char *msg)
1095 error("%s expected", msg);
1098 void warning(const char *fmt, ...)
1100 TCCState *s1 = tcc_state;
1101 va_list ap;
1103 va_start(ap, fmt);
1104 error1(s1, 1, fmt, ap);
1105 va_end(ap);
1108 void skip(int c)
1110 if (tok != c)
1111 error("'%c' expected", c);
1112 next();
1115 void test_lvalue(void)
1117 if (!(vtop->r & VT_LVAL))
1118 expect("lvalue");
1121 /* allocate a new token */
1122 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1124 TokenSym *ts, **ptable;
1125 int i;
1127 if (tok_ident >= SYM_FIRST_ANOM)
1128 error("memory full");
1130 /* expand token table if needed */
1131 i = tok_ident - TOK_IDENT;
1132 if ((i % TOK_ALLOC_INCR) == 0) {
1133 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1134 if (!ptable)
1135 error("memory full");
1136 table_ident = ptable;
1139 ts = tcc_malloc(sizeof(TokenSym) + len);
1140 table_ident[i] = ts;
1141 ts->tok = tok_ident++;
1142 ts->sym_define = NULL;
1143 ts->sym_label = NULL;
1144 ts->sym_struct = NULL;
1145 ts->sym_identifier = NULL;
1146 ts->len = len;
1147 ts->hash_next = NULL;
1148 memcpy(ts->str, str, len);
1149 ts->str[len] = '\0';
1150 *pts = ts;
1151 return ts;
1154 #define TOK_HASH_INIT 1
1155 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1157 /* find a token and add it if not found */
1158 static TokenSym *tok_alloc(const char *str, int len)
1160 TokenSym *ts, **pts;
1161 int i;
1162 unsigned int h;
1164 h = TOK_HASH_INIT;
1165 for(i=0;i<len;i++)
1166 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1167 h &= (TOK_HASH_SIZE - 1);
1169 pts = &hash_ident[h];
1170 for(;;) {
1171 ts = *pts;
1172 if (!ts)
1173 break;
1174 if (ts->len == len && !memcmp(ts->str, str, len))
1175 return ts;
1176 pts = &(ts->hash_next);
1178 return tok_alloc_new(pts, str, len);
1181 /* CString handling */
1183 static void cstr_realloc(CString *cstr, int new_size)
1185 int size;
1186 void *data;
1188 size = cstr->size_allocated;
1189 if (size == 0)
1190 size = 8; /* no need to allocate a too small first string */
1191 while (size < new_size)
1192 size = size * 2;
1193 data = tcc_realloc(cstr->data_allocated, size);
1194 if (!data)
1195 error("memory full");
1196 cstr->data_allocated = data;
1197 cstr->size_allocated = size;
1198 cstr->data = data;
1201 /* add a byte */
1202 static void cstr_ccat(CString *cstr, int ch)
1204 int size;
1205 size = cstr->size + 1;
1206 if (size > cstr->size_allocated)
1207 cstr_realloc(cstr, size);
1208 ((unsigned char *)cstr->data)[size - 1] = ch;
1209 cstr->size = size;
1212 static void cstr_cat(CString *cstr, const char *str)
1214 int c;
1215 for(;;) {
1216 c = *str;
1217 if (c == '\0')
1218 break;
1219 cstr_ccat(cstr, c);
1220 str++;
1224 /* add a wide char */
1225 static void cstr_wccat(CString *cstr, int ch)
1227 int size;
1228 size = cstr->size + sizeof(int);
1229 if (size > cstr->size_allocated)
1230 cstr_realloc(cstr, size);
1231 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1232 cstr->size = size;
1235 static void cstr_new(CString *cstr)
1237 memset(cstr, 0, sizeof(CString));
1240 /* free string and reset it to NULL */
1241 static void cstr_free(CString *cstr)
1243 tcc_free(cstr->data_allocated);
1244 cstr_new(cstr);
1247 #define cstr_reset(cstr) cstr_free(cstr)
1249 static CString *cstr_dup(CString *cstr1)
1251 CString *cstr;
1252 int size;
1254 cstr = tcc_malloc(sizeof(CString));
1255 size = cstr1->size;
1256 cstr->size = size;
1257 cstr->size_allocated = size;
1258 cstr->data_allocated = tcc_malloc(size);
1259 cstr->data = cstr->data_allocated;
1260 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1261 return cstr;
1264 /* XXX: unicode ? */
1265 static void add_char(CString *cstr, int c)
1267 if (c == '\'' || c == '\"' || c == '\\') {
1268 /* XXX: could be more precise if char or string */
1269 cstr_ccat(cstr, '\\');
1271 if (c >= 32 && c <= 126) {
1272 cstr_ccat(cstr, c);
1273 } else {
1274 cstr_ccat(cstr, '\\');
1275 if (c == '\n') {
1276 cstr_ccat(cstr, 'n');
1277 } else {
1278 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1279 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1280 cstr_ccat(cstr, '0' + (c & 7));
1285 /* XXX: buffer overflow */
1286 /* XXX: float tokens */
1287 char *get_tok_str(int v, CValue *cv)
1289 static char buf[STRING_MAX_SIZE + 1];
1290 static CString cstr_buf;
1291 CString *cstr;
1292 unsigned char *q;
1293 char *p;
1294 int i, len;
1296 /* NOTE: to go faster, we give a fixed buffer for small strings */
1297 cstr_reset(&cstr_buf);
1298 cstr_buf.data = buf;
1299 cstr_buf.size_allocated = sizeof(buf);
1300 p = buf;
1302 switch(v) {
1303 case TOK_CINT:
1304 case TOK_CUINT:
1305 /* XXX: not quite exact, but only useful for testing */
1306 sprintf(p, "%u", cv->ui);
1307 break;
1308 case TOK_CLLONG:
1309 case TOK_CULLONG:
1310 /* XXX: not quite exact, but only useful for testing */
1311 sprintf(p, "%Lu", cv->ull);
1312 break;
1313 case TOK_CCHAR:
1314 case TOK_LCHAR:
1315 cstr_ccat(&cstr_buf, '\'');
1316 add_char(&cstr_buf, cv->i);
1317 cstr_ccat(&cstr_buf, '\'');
1318 cstr_ccat(&cstr_buf, '\0');
1319 break;
1320 case TOK_PPNUM:
1321 cstr = cv->cstr;
1322 len = cstr->size - 1;
1323 for(i=0;i<len;i++)
1324 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1325 cstr_ccat(&cstr_buf, '\0');
1326 break;
1327 case TOK_STR:
1328 case TOK_LSTR:
1329 cstr = cv->cstr;
1330 cstr_ccat(&cstr_buf, '\"');
1331 if (v == TOK_STR) {
1332 len = cstr->size - 1;
1333 for(i=0;i<len;i++)
1334 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1335 } else {
1336 len = (cstr->size / sizeof(int)) - 1;
1337 for(i=0;i<len;i++)
1338 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1340 cstr_ccat(&cstr_buf, '\"');
1341 cstr_ccat(&cstr_buf, '\0');
1342 break;
1343 case TOK_LT:
1344 v = '<';
1345 goto addv;
1346 case TOK_GT:
1347 v = '>';
1348 goto addv;
1349 case TOK_A_SHL:
1350 return strcpy(p, "<<=");
1351 case TOK_A_SAR:
1352 return strcpy(p, ">>=");
1353 default:
1354 if (v < TOK_IDENT) {
1355 /* search in two bytes table */
1356 q = tok_two_chars;
1357 while (*q) {
1358 if (q[2] == v) {
1359 *p++ = q[0];
1360 *p++ = q[1];
1361 *p = '\0';
1362 return buf;
1364 q += 3;
1366 addv:
1367 *p++ = v;
1368 *p = '\0';
1369 } else if (v < tok_ident) {
1370 return table_ident[v - TOK_IDENT]->str;
1371 } else if (v >= SYM_FIRST_ANOM) {
1372 /* special name for anonymous symbol */
1373 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1374 } else {
1375 /* should never happen */
1376 return NULL;
1378 break;
1380 return cstr_buf.data;
1383 /* push, without hashing */
1384 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1386 Sym *s;
1387 s = tcc_malloc(sizeof(Sym));
1388 s->v = v;
1389 s->type.t = t;
1390 s->c = c;
1391 s->next = NULL;
1392 /* add in stack */
1393 s->prev = *ps;
1394 *ps = s;
1395 return s;
1398 /* find a symbol and return its associated structure. 's' is the top
1399 of the symbol stack */
1400 static Sym *sym_find2(Sym *s, int v)
1402 while (s) {
1403 if (s->v == v)
1404 return s;
1405 s = s->prev;
1407 return NULL;
1410 /* structure lookup */
1411 static Sym *struct_find(int v)
1413 v -= TOK_IDENT;
1414 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1415 return NULL;
1416 return table_ident[v]->sym_struct;
1419 /* find an identifier */
1420 static inline Sym *sym_find(int v)
1422 v -= TOK_IDENT;
1423 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1424 return NULL;
1425 return table_ident[v]->sym_identifier;
1428 /* push a given symbol on the symbol stack */
1429 static Sym *sym_push(int v, CType *type, int r, int c)
1431 Sym *s, **ps;
1432 TokenSym *ts;
1434 if (local_stack)
1435 ps = &local_stack;
1436 else
1437 ps = &global_stack;
1438 s = sym_push2(ps, v, type->t, c);
1439 s->type.ref = type->ref;
1440 s->r = r;
1441 /* don't record fields or anonymous symbols */
1442 /* XXX: simplify */
1443 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1444 /* record symbol in token array */
1445 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1446 if (v & SYM_STRUCT)
1447 ps = &ts->sym_struct;
1448 else
1449 ps = &ts->sym_identifier;
1450 s->prev_tok = *ps;
1451 *ps = s;
1453 return s;
1456 /* push a global identifier */
1457 static Sym *global_identifier_push(int v, int t, int c)
1459 Sym *s, **ps;
1460 s = sym_push2(&global_stack, v, t, c);
1461 /* don't record anonymous symbol */
1462 if (v < SYM_FIRST_ANOM) {
1463 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1464 /* modify the top most local identifier, so that
1465 sym_identifier will point to 's' when popped */
1466 while (*ps != NULL)
1467 ps = &(*ps)->prev_tok;
1468 s->prev_tok = NULL;
1469 *ps = s;
1471 return s;
1474 /* pop symbols until top reaches 'b' */
1475 static void sym_pop(Sym **ptop, Sym *b)
1477 Sym *s, *ss, **ps;
1478 TokenSym *ts;
1479 int v;
1481 s = *ptop;
1482 while(s != b) {
1483 ss = s->prev;
1484 v = s->v;
1485 /* remove symbol in token array */
1486 /* XXX: simplify */
1487 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1488 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1489 if (v & SYM_STRUCT)
1490 ps = &ts->sym_struct;
1491 else
1492 ps = &ts->sym_identifier;
1493 *ps = s->prev_tok;
1495 tcc_free(s);
1496 s = ss;
1498 *ptop = b;
1501 /* I/O layer */
1503 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1505 int fd;
1506 BufferedFile *bf;
1508 fd = open(filename, O_RDONLY);
1509 if (fd < 0)
1510 return NULL;
1511 bf = tcc_malloc(sizeof(BufferedFile));
1512 if (!bf) {
1513 close(fd);
1514 return NULL;
1516 bf->fd = fd;
1517 bf->buf_ptr = bf->buffer;
1518 bf->buf_end = bf->buffer;
1519 bf->buffer[0] = CH_EOB; /* put eob symbol */
1520 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1521 bf->line_num = 1;
1522 bf->ifndef_macro = 0;
1523 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1524 // printf("opening '%s'\n", filename);
1525 return bf;
1528 void tcc_close(BufferedFile *bf)
1530 total_lines += bf->line_num;
1531 close(bf->fd);
1532 tcc_free(bf);
1535 /* fill input buffer and peek next char */
1536 static int tcc_peekc_slow(BufferedFile *bf)
1538 int len;
1539 /* only tries to read if really end of buffer */
1540 if (bf->buf_ptr >= bf->buf_end) {
1541 if (bf->fd != -1) {
1542 #if defined(PARSE_DEBUG)
1543 len = 8;
1544 #else
1545 len = IO_BUF_SIZE;
1546 #endif
1547 len = read(bf->fd, bf->buffer, len);
1548 if (len < 0)
1549 len = 0;
1550 } else {
1551 len = 0;
1553 total_bytes += len;
1554 bf->buf_ptr = bf->buffer;
1555 bf->buf_end = bf->buffer + len;
1556 *bf->buf_end = CH_EOB;
1558 if (bf->buf_ptr < bf->buf_end) {
1559 return bf->buf_ptr[0];
1560 } else {
1561 bf->buf_ptr = bf->buf_end;
1562 return CH_EOF;
1566 /* return the current character, handling end of block if necessary
1567 (but not stray) */
1568 static int handle_eob(void)
1570 return tcc_peekc_slow(file);
1573 /* read next char from current input file and handle end of input buffer */
1574 static inline void inp(void)
1576 ch = *(++(file->buf_ptr));
1577 /* end of buffer/file handling */
1578 if (ch == CH_EOB)
1579 ch = handle_eob();
1582 /* handle '\[\r]\n' */
1583 static void handle_stray(void)
1585 while (ch == '\\') {
1586 inp();
1587 if (ch == '\n') {
1588 file->line_num++;
1589 inp();
1590 } else if (ch == '\r') {
1591 inp();
1592 if (ch != '\n')
1593 goto fail;
1594 file->line_num++;
1595 inp();
1596 } else {
1597 fail:
1598 error("stray '\\' in program");
1603 /* skip the stray and handle the \\n case. Output an error if
1604 incorrect char after the stray */
1605 static int handle_stray1(uint8_t *p)
1607 int c;
1609 if (p >= file->buf_end) {
1610 file->buf_ptr = p;
1611 c = handle_eob();
1612 p = file->buf_ptr;
1613 if (c == '\\')
1614 goto parse_stray;
1615 } else {
1616 parse_stray:
1617 file->buf_ptr = p;
1618 ch = *p;
1619 handle_stray();
1620 p = file->buf_ptr;
1621 c = *p;
1623 return c;
1626 /* handle the complicated stray case */
1627 #define PEEKC(c, p)\
1629 p++;\
1630 c = *p;\
1631 if (c == '\\') {\
1632 c = handle_stray1(p);\
1633 p = file->buf_ptr;\
1637 /* input with '\[\r]\n' handling. Note that this function cannot
1638 handle other characters after '\', so you cannot call it inside
1639 strings or comments */
1640 static void minp(void)
1642 inp();
1643 if (ch == '\\')
1644 handle_stray();
1648 static void parse_line_comment(void)
1650 /* single line C++ comments */
1651 /* XXX: accept '\\\n' ? */
1652 inp();
1653 while (ch != '\n' && ch != CH_EOF)
1654 inp();
1657 static void parse_comment(void)
1659 uint8_t *p;
1660 int c;
1662 /* C comments */
1663 p = file->buf_ptr;
1664 p++;
1665 for(;;) {
1666 /* fast skip loop */
1667 for(;;) {
1668 c = *p;
1669 if (c == '\n' || c == '*' || c == '\\')
1670 break;
1671 p++;
1672 c = *p;
1673 if (c == '\n' || c == '*' || c == '\\')
1674 break;
1675 p++;
1677 /* now we can handle all the cases */
1678 if (c == '\n') {
1679 file->line_num++;
1680 p++;
1681 } else if (c == '*') {
1682 p++;
1683 for(;;) {
1684 c = *p;
1685 if (c == '*') {
1686 p++;
1687 } else if (c == '/') {
1688 goto end_of_comment;
1689 } else if (c == '\\') {
1690 file->buf_ptr = p;
1691 c = handle_eob();
1692 if (c == '\\') {
1693 /* skip '\\n', but if '\' followed but another
1694 char, behave asif a stray was parsed */
1695 ch = file->buf_ptr[0];
1696 while (ch == '\\') {
1697 inp();
1698 if (ch == '\n') {
1699 file->line_num++;
1700 inp();
1701 } else if (ch == '\r') {
1702 inp();
1703 if (ch == '\n') {
1704 file->line_num++;
1705 inp();
1707 } else {
1708 p = file->buf_ptr;
1709 break;
1713 p = file->buf_ptr;
1714 } else {
1715 break;
1718 } else {
1719 /* stray, eob or eof */
1720 file->buf_ptr = p;
1721 c = handle_eob();
1722 p = file->buf_ptr;
1723 if (c == CH_EOF) {
1724 error("unexpected end of file in comment");
1725 } else if (c == '\\') {
1726 p++;
1730 end_of_comment:
1731 p++;
1732 file->buf_ptr = p;
1733 ch = *p;
1736 #define cinp minp
1738 /* space exlcuding newline */
1739 static inline int is_space(int ch)
1741 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1744 static inline void skip_spaces(void)
1746 while (is_space(ch))
1747 cinp();
1750 /* skip block of text until #else, #elif or #endif. skip also pairs of
1751 #if/#endif */
1752 void preprocess_skip(void)
1754 int a, start_of_line, sep, c;
1755 uint8_t *p;
1757 p = file->buf_ptr;
1758 start_of_line = 1;
1759 a = 0;
1760 for(;;) {
1761 redo_no_start:
1762 c = *p;
1763 switch(c) {
1764 case ' ':
1765 case '\t':
1766 case '\f':
1767 case '\v':
1768 case '\r':
1769 p++;
1770 goto redo_no_start;
1771 case '\n':
1772 start_of_line = 1;
1773 file->line_num++;
1774 p++;
1775 goto redo_no_start;
1776 case '\\':
1777 file->buf_ptr = p;
1778 c = handle_eob();
1779 if (c == CH_EOF) {
1780 expect("#endif");
1781 } else if (c == '\\') {
1782 /* XXX: incorrect: should not give an error */
1783 ch = file->buf_ptr[0];
1784 handle_stray();
1786 p = file->buf_ptr;
1787 goto redo_no_start;
1788 /* skip strings */
1789 case '\"':
1790 case '\'':
1791 sep = c;
1792 p++;
1793 for(;;) {
1794 c = *p;
1795 if (c == sep) {
1796 break;
1797 } else if (c == '\\') {
1798 file->buf_ptr = p;
1799 c = handle_eob();
1800 p = file->buf_ptr;
1801 if (c == CH_EOF) {
1802 /* XXX: better error message */
1803 error("unterminated string");
1804 } else if (c == '\\') {
1805 /* ignore next char */
1806 p++;
1807 c = *p;
1808 if (c == '\\') {
1809 file->buf_ptr = p;
1810 c = handle_eob();
1811 p = file->buf_ptr;
1813 if (c == '\n')
1814 file->line_num++;
1815 else if (c != CH_EOF)
1816 p++;
1818 } else if (c == '\n') {
1819 file->line_num++;
1820 p++;
1821 } else {
1822 p++;
1825 p++;
1826 break;
1827 /* skip comments */
1828 case '/':
1829 file->buf_ptr = p;
1830 ch = *p;
1831 minp();
1832 if (ch == '*') {
1833 parse_comment();
1834 } else if (ch == '/') {
1835 parse_line_comment();
1837 p = file->buf_ptr;
1838 break;
1840 case '#':
1841 p++;
1842 if (start_of_line) {
1843 file->buf_ptr = p;
1844 next_nomacro();
1845 p = file->buf_ptr;
1846 if (a == 0 &&
1847 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1848 goto the_end;
1849 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1850 a++;
1851 else if (tok == TOK_ENDIF)
1852 a--;
1854 break;
1855 default:
1856 p++;
1857 break;
1859 start_of_line = 0;
1861 the_end: ;
1862 file->buf_ptr = p;
1865 /* ParseState handling */
1867 /* XXX: currently, no include file info is stored. Thus, we cannot display
1868 accurate messages if the function or data definition spans multiple
1869 files */
1871 /* save current parse state in 's' */
1872 void save_parse_state(ParseState *s)
1874 s->line_num = file->line_num;
1875 s->macro_ptr = macro_ptr;
1876 s->tok = tok;
1877 s->tokc = tokc;
1880 /* restore parse state from 's' */
1881 void restore_parse_state(ParseState *s)
1883 file->line_num = s->line_num;
1884 macro_ptr = s->macro_ptr;
1885 tok = s->tok;
1886 tokc = s->tokc;
1889 /* return the number of additionnal 'ints' necessary to store the
1890 token */
1891 static inline int tok_ext_size(int t)
1893 switch(t) {
1894 /* 4 bytes */
1895 case TOK_CINT:
1896 case TOK_CUINT:
1897 case TOK_CCHAR:
1898 case TOK_LCHAR:
1899 case TOK_STR:
1900 case TOK_LSTR:
1901 case TOK_CFLOAT:
1902 case TOK_LINENUM:
1903 case TOK_PPNUM:
1904 return 1;
1905 case TOK_CDOUBLE:
1906 case TOK_CLLONG:
1907 case TOK_CULLONG:
1908 return 2;
1909 case TOK_CLDOUBLE:
1910 return LDOUBLE_SIZE / 4;
1911 default:
1912 return 0;
1916 /* token string handling */
1918 static inline void tok_str_new(TokenString *s)
1920 s->str = NULL;
1921 s->len = 0;
1922 s->allocated_len = 0;
1923 s->last_line_num = -1;
1926 static void tok_str_free(int *str)
1928 const int *p;
1929 CString *cstr;
1930 int t;
1932 p = str;
1933 for(;;) {
1934 t = *p;
1935 /* NOTE: we test zero separately so that GCC can generate a
1936 table for the following switch */
1937 if (t == 0)
1938 break;
1939 switch(t) {
1940 case TOK_CINT:
1941 case TOK_CUINT:
1942 case TOK_CCHAR:
1943 case TOK_LCHAR:
1944 case TOK_CFLOAT:
1945 case TOK_LINENUM:
1946 p += 2;
1947 break;
1948 case TOK_PPNUM:
1949 case TOK_STR:
1950 case TOK_LSTR:
1951 /* XXX: use a macro to be portable on 64 bit ? */
1952 cstr = (CString *)p[1];
1953 cstr_free(cstr);
1954 tcc_free(cstr);
1955 p += 2;
1956 break;
1957 case TOK_CDOUBLE:
1958 case TOK_CLLONG:
1959 case TOK_CULLONG:
1960 p += 3;
1961 break;
1962 case TOK_CLDOUBLE:
1963 p += 1 + (LDOUBLE_SIZE / 4);
1964 break;
1965 default:
1966 p++;
1967 break;
1970 tcc_free(str);
1973 static int *tok_str_realloc(TokenString *s)
1975 int *str, len;
1977 len = s->allocated_len + TOK_STR_ALLOC_INCR;
1978 str = tcc_realloc(s->str, len * sizeof(int));
1979 if (!str)
1980 error("memory full");
1981 s->allocated_len = len;
1982 s->str = str;
1983 return str;
1986 static void tok_str_add(TokenString *s, int t)
1988 int len, *str;
1990 len = s->len;
1991 str = s->str;
1992 if (len >= s->allocated_len)
1993 str = tok_str_realloc(s);
1994 str[len++] = t;
1995 s->len = len;
1998 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2000 int len, *str;
2002 len = s->len;
2003 str = s->str;
2005 /* allocate space for worst case */
2006 if (len + TOK_MAX_SIZE > s->allocated_len)
2007 str = tok_str_realloc(s);
2008 str[len++] = t;
2009 switch(t) {
2010 case TOK_CINT:
2011 case TOK_CUINT:
2012 case TOK_CCHAR:
2013 case TOK_LCHAR:
2014 case TOK_CFLOAT:
2015 case TOK_LINENUM:
2016 str[len++] = cv->tab[0];
2017 break;
2018 case TOK_PPNUM:
2019 case TOK_STR:
2020 case TOK_LSTR:
2021 str[len++] = (int)cstr_dup(cv->cstr);
2022 break;
2023 case TOK_CDOUBLE:
2024 case TOK_CLLONG:
2025 case TOK_CULLONG:
2026 str[len++] = cv->tab[0];
2027 str[len++] = cv->tab[1];
2028 break;
2029 case TOK_CLDOUBLE:
2030 #if LDOUBLE_SIZE == 12
2031 str[len++] = cv->tab[0];
2032 str[len++] = cv->tab[1];
2033 str[len++] = cv->tab[2];
2034 #else
2035 #error add long double size support
2036 #endif
2037 break;
2038 default:
2039 break;
2041 s->len = len;
2044 /* add the current parse token in token string 's' */
2045 static void tok_str_add_tok(TokenString *s)
2047 CValue cval;
2049 /* save line number info */
2050 if (file->line_num != s->last_line_num) {
2051 s->last_line_num = file->line_num;
2052 cval.i = s->last_line_num;
2053 tok_str_add2(s, TOK_LINENUM, &cval);
2055 tok_str_add2(s, tok, &tokc);
2058 #if LDOUBLE_SIZE == 12
2059 #define LDOUBLE_GET(p, cv) \
2060 cv.tab[0] = p[0]; \
2061 cv.tab[1] = p[1]; \
2062 cv.tab[2] = p[2];
2063 #else
2064 #error add long double size support
2065 #endif
2068 /* get a token from an integer array and increment pointer
2069 accordingly. we code it as a macro to avoid pointer aliasing. */
2070 #define TOK_GET(t, p, cv) \
2072 t = *p++; \
2073 switch(t) { \
2074 case TOK_CINT: \
2075 case TOK_CUINT: \
2076 case TOK_CCHAR: \
2077 case TOK_LCHAR: \
2078 case TOK_CFLOAT: \
2079 case TOK_LINENUM: \
2080 case TOK_STR: \
2081 case TOK_LSTR: \
2082 case TOK_PPNUM: \
2083 cv.tab[0] = *p++; \
2084 break; \
2085 case TOK_CDOUBLE: \
2086 case TOK_CLLONG: \
2087 case TOK_CULLONG: \
2088 cv.tab[0] = p[0]; \
2089 cv.tab[1] = p[1]; \
2090 p += 2; \
2091 break; \
2092 case TOK_CLDOUBLE: \
2093 LDOUBLE_GET(p, cv); \
2094 p += LDOUBLE_SIZE / 4; \
2095 break; \
2096 default: \
2097 break; \
2101 /* defines handling */
2102 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2104 Sym *s;
2106 s = sym_push2(&define_stack, v, macro_type, (int)str);
2107 s->next = first_arg;
2108 table_ident[v - TOK_IDENT]->sym_define = s;
2111 /* undefined a define symbol. Its name is just set to zero */
2112 static void define_undef(Sym *s)
2114 int v;
2115 v = s->v;
2116 if (v >= TOK_IDENT && v < tok_ident)
2117 table_ident[v - TOK_IDENT]->sym_define = NULL;
2118 s->v = 0;
2121 static inline Sym *define_find(int v)
2123 v -= TOK_IDENT;
2124 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2125 return NULL;
2126 return table_ident[v]->sym_define;
2129 /* free define stack until top reaches 'b' */
2130 static void free_defines(Sym *b)
2132 Sym *top, *top1;
2133 int v;
2135 top = define_stack;
2136 while (top != b) {
2137 top1 = top->prev;
2138 /* do not free args or predefined defines */
2139 if (top->c)
2140 tok_str_free((int *)top->c);
2141 v = top->v;
2142 if (v >= TOK_IDENT && v < tok_ident)
2143 table_ident[v - TOK_IDENT]->sym_define = NULL;
2144 tcc_free(top);
2145 top = top1;
2147 define_stack = b;
2150 /* label lookup */
2151 static Sym *label_find(int v)
2153 v -= TOK_IDENT;
2154 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2155 return NULL;
2156 return table_ident[v]->sym_label;
2159 static Sym *label_push(int v, int flags)
2161 Sym *s;
2162 s = sym_push2(&label_stack, v, 0, 0);
2163 s->r = flags;
2164 table_ident[v - TOK_IDENT]->sym_label = s;
2165 return s;
2168 /* eval an expression for #if/#elif */
2169 static int expr_preprocess(void)
2171 int c, t;
2172 TokenString str;
2174 tok_str_new(&str);
2175 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2176 next(); /* do macro subst */
2177 if (tok == TOK_DEFINED) {
2178 next_nomacro();
2179 t = tok;
2180 if (t == '(')
2181 next_nomacro();
2182 c = define_find(tok) != 0;
2183 if (t == '(')
2184 next_nomacro();
2185 tok = TOK_CINT;
2186 tokc.i = c;
2187 } else if (tok >= TOK_IDENT) {
2188 /* if undefined macro */
2189 tok = TOK_CINT;
2190 tokc.i = 0;
2192 tok_str_add_tok(&str);
2194 tok_str_add(&str, -1); /* simulate end of file */
2195 tok_str_add(&str, 0);
2196 /* now evaluate C constant expression */
2197 macro_ptr = str.str;
2198 next();
2199 c = expr_const();
2200 macro_ptr = NULL;
2201 tok_str_free(str.str);
2202 return c != 0;
2205 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2206 static void tok_print(int *str)
2208 int t;
2209 CValue cval;
2211 while (1) {
2212 TOK_GET(t, str, cval);
2213 if (!t)
2214 break;
2215 printf(" %s", get_tok_str(t, &cval));
2217 printf("\n");
2219 #endif
2221 /* parse after #define */
2222 static void parse_define(void)
2224 Sym *s, *first, **ps;
2225 int v, t, varg, is_vaargs, c;
2226 TokenString str;
2228 v = tok;
2229 if (v < TOK_IDENT)
2230 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2231 /* XXX: should check if same macro (ANSI) */
2232 first = NULL;
2233 t = MACRO_OBJ;
2234 /* '(' must be just after macro definition for MACRO_FUNC */
2235 c = file->buf_ptr[0];
2236 if (c == '\\')
2237 c = handle_stray1(file->buf_ptr);
2238 if (c == '(') {
2239 next_nomacro();
2240 next_nomacro();
2241 ps = &first;
2242 while (tok != ')') {
2243 varg = tok;
2244 next_nomacro();
2245 is_vaargs = 0;
2246 if (varg == TOK_DOTS) {
2247 varg = TOK___VA_ARGS__;
2248 is_vaargs = 1;
2249 } else if (tok == TOK_DOTS && gnu_ext) {
2250 is_vaargs = 1;
2251 next_nomacro();
2253 if (varg < TOK_IDENT)
2254 error("badly punctuated parameter list");
2255 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2256 *ps = s;
2257 ps = &s->next;
2258 if (tok != ',')
2259 break;
2260 next_nomacro();
2262 t = MACRO_FUNC;
2264 tok_str_new(&str);
2265 next_nomacro();
2266 /* EOF testing necessary for '-D' handling */
2267 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2268 tok_str_add2(&str, tok, &tokc);
2269 next_nomacro();
2271 tok_str_add(&str, 0);
2272 #ifdef PP_DEBUG
2273 printf("define %s %d: ", get_tok_str(v, NULL), t);
2274 tok_print(str.str);
2275 #endif
2276 define_push(v, t, str.str, first);
2279 /* XXX: use a token or a hash table to accelerate matching ? */
2280 static CachedInclude *search_cached_include(TCCState *s1,
2281 int type, const char *filename)
2283 CachedInclude *e;
2284 int i;
2286 for(i = 0;i < s1->nb_cached_includes; i++) {
2287 e = s1->cached_includes[i];
2288 if (e->type == type && !strcmp(e->filename, filename))
2289 return e;
2291 return NULL;
2294 static inline void add_cached_include(TCCState *s1, int type,
2295 const char *filename, int ifndef_macro)
2297 CachedInclude *e;
2299 if (search_cached_include(s1, type, filename))
2300 return;
2301 #ifdef INC_DEBUG
2302 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2303 #endif
2304 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2305 if (!e)
2306 return;
2307 e->type = type;
2308 strcpy(e->filename, filename);
2309 e->ifndef_macro = ifndef_macro;
2310 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2313 /* is_bof is true if first non space token at beginning of file */
2314 static void preprocess(int is_bof)
2316 TCCState *s1 = tcc_state;
2317 int size, i, c, n;
2318 char buf[1024], *q, *p;
2319 char buf1[1024];
2320 BufferedFile *f;
2321 Sym *s;
2322 CachedInclude *e;
2324 return_linefeed = 1; /* linefeed will be returned as a
2325 token. EOF is also returned as line feed */
2326 next_nomacro();
2327 redo:
2328 switch(tok) {
2329 case TOK_DEFINE:
2330 next_nomacro();
2331 parse_define();
2332 break;
2333 case TOK_UNDEF:
2334 next_nomacro();
2335 s = define_find(tok);
2336 /* undefine symbol by putting an invalid name */
2337 if (s)
2338 define_undef(s);
2339 break;
2340 case TOK_INCLUDE:
2341 ch = file->buf_ptr[0];
2342 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2343 skip_spaces();
2344 if (ch == '<') {
2345 c = '>';
2346 goto read_name;
2347 } else if (ch == '\"') {
2348 c = ch;
2349 read_name:
2350 /* XXX: better stray handling */
2351 minp();
2352 q = buf;
2353 while (ch != c && ch != '\n' && ch != CH_EOF) {
2354 if ((q - buf) < sizeof(buf) - 1)
2355 *q++ = ch;
2356 minp();
2358 *q = '\0';
2359 minp();
2360 #if 0
2361 /* eat all spaces and comments after include */
2362 /* XXX: slightly incorrect */
2363 while (ch1 != '\n' && ch1 != CH_EOF)
2364 inp();
2365 #endif
2366 } else {
2367 /* computed #include : either we have only strings or
2368 we have anything enclosed in '<>' */
2369 next();
2370 buf[0] = '\0';
2371 if (tok == TOK_STR) {
2372 while (tok != TOK_LINEFEED) {
2373 if (tok != TOK_STR) {
2374 include_syntax:
2375 error("'#include' expects \"FILENAME\" or <FILENAME>");
2377 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2378 next();
2380 c = '\"';
2381 } else {
2382 int len;
2383 while (tok != TOK_LINEFEED) {
2384 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2385 next();
2387 len = strlen(buf);
2388 /* check syntax and remove '<>' */
2389 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2390 goto include_syntax;
2391 memmove(buf, buf + 1, len - 2);
2392 buf[len - 2] = '\0';
2393 c = '>';
2397 e = search_cached_include(s1, c, buf);
2398 if (e && define_find(e->ifndef_macro)) {
2399 /* no need to parse the include because the 'ifndef macro'
2400 is defined */
2401 #ifdef INC_DEBUG
2402 printf("%s: skipping %s\n", file->filename, buf);
2403 #endif
2404 } else {
2405 if (c == '\"') {
2406 /* first search in current dir if "header.h" */
2407 size = 0;
2408 p = strrchr(file->filename, '/');
2409 if (p)
2410 size = p + 1 - file->filename;
2411 if (size > sizeof(buf1) - 1)
2412 size = sizeof(buf1) - 1;
2413 memcpy(buf1, file->filename, size);
2414 buf1[size] = '\0';
2415 pstrcat(buf1, sizeof(buf1), buf);
2416 f = tcc_open(s1, buf1);
2417 if (f)
2418 goto found;
2420 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2421 error("#include recursion too deep");
2422 /* now search in all the include paths */
2423 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2424 for(i = 0; i < n; i++) {
2425 const char *path;
2426 if (i < s1->nb_include_paths)
2427 path = s1->include_paths[i];
2428 else
2429 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2430 pstrcpy(buf1, sizeof(buf1), path);
2431 pstrcat(buf1, sizeof(buf1), "/");
2432 pstrcat(buf1, sizeof(buf1), buf);
2433 f = tcc_open(s1, buf1);
2434 if (f)
2435 goto found;
2437 error("include file '%s' not found", buf);
2438 f = NULL;
2439 found:
2440 #ifdef INC_DEBUG
2441 printf("%s: including %s\n", file->filename, buf1);
2442 #endif
2443 f->inc_type = c;
2444 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2445 /* push current file in stack */
2446 /* XXX: fix current line init */
2447 *s1->include_stack_ptr++ = file;
2448 file = f;
2449 /* add include file debug info */
2450 if (do_debug) {
2451 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2453 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2454 ch = file->buf_ptr[0];
2455 goto the_end;
2457 break;
2458 case TOK_IFNDEF:
2459 c = 1;
2460 goto do_ifdef;
2461 case TOK_IF:
2462 c = expr_preprocess();
2463 goto do_if;
2464 case TOK_IFDEF:
2465 c = 0;
2466 do_ifdef:
2467 next_nomacro();
2468 if (tok < TOK_IDENT)
2469 error("invalid argument for '#if%sdef'", c ? "n" : "");
2470 if (is_bof) {
2471 if (c) {
2472 #ifdef INC_DEBUG
2473 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2474 #endif
2475 file->ifndef_macro = tok;
2478 c = (define_find(tok) != 0) ^ c;
2479 do_if:
2480 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2481 error("memory full");
2482 *s1->ifdef_stack_ptr++ = c;
2483 goto test_skip;
2484 case TOK_ELSE:
2485 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2486 error("#else without matching #if");
2487 if (s1->ifdef_stack_ptr[-1] & 2)
2488 error("#else after #else");
2489 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2490 goto test_skip;
2491 case TOK_ELIF:
2492 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2493 error("#elif without matching #if");
2494 c = s1->ifdef_stack_ptr[-1];
2495 if (c > 1)
2496 error("#elif after #else");
2497 /* last #if/#elif expression was true: we skip */
2498 if (c == 1)
2499 goto skip;
2500 c = expr_preprocess();
2501 s1->ifdef_stack_ptr[-1] = c;
2502 test_skip:
2503 if (!(c & 1)) {
2504 skip:
2505 preprocess_skip();
2506 is_bof = 0;
2507 goto redo;
2509 break;
2510 case TOK_ENDIF:
2511 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2512 error("#endif without matching #if");
2513 s1->ifdef_stack_ptr--;
2514 /* '#ifndef macro' was at the start of file. Now we check if
2515 an '#endif' is exactly at the end of file */
2516 if (file->ifndef_macro &&
2517 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2518 file->ifndef_macro_saved = file->ifndef_macro;
2519 /* need to set to zero to avoid false matches if another
2520 #ifndef at middle of file */
2521 file->ifndef_macro = 0;
2522 while (tok != TOK_LINEFEED)
2523 next_nomacro();
2524 tok_flags |= TOK_FLAG_ENDIF;
2525 goto the_end;
2527 break;
2528 case TOK_LINE:
2529 next();
2530 if (tok != TOK_CINT)
2531 error("#line");
2532 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2533 next();
2534 if (tok != TOK_LINEFEED) {
2535 if (tok != TOK_STR)
2536 error("#line");
2537 pstrcpy(file->filename, sizeof(file->filename),
2538 (char *)tokc.cstr->data);
2540 break;
2541 case TOK_ERROR:
2542 case TOK_WARNING:
2543 c = tok;
2544 skip_spaces();
2545 q = buf;
2546 while (ch != '\n' && ch != CH_EOF) {
2547 if ((q - buf) < sizeof(buf) - 1)
2548 *q++ = ch;
2549 minp();
2551 *q = '\0';
2552 if (c == TOK_ERROR)
2553 error("#error %s", buf);
2554 else
2555 warning("#warning %s", buf);
2556 break;
2557 default:
2558 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2559 /* '!' is ignored to allow C scripts. numbers are ignored
2560 to emulate cpp behaviour */
2561 } else {
2562 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2564 break;
2566 /* ignore other preprocess commands or #! for C scripts */
2567 while (tok != TOK_LINEFEED)
2568 next_nomacro();
2569 the_end:
2570 return_linefeed = 0;
2573 /* read a number in base b */
2574 static int getn(int b)
2576 int n, t;
2577 n = 0;
2578 while (1) {
2579 if (ch >= 'a' && ch <= 'f')
2580 t = ch - 'a' + 10;
2581 else if (ch >= 'A' && ch <= 'F')
2582 t = ch - 'A' + 10;
2583 else if (isnum(ch))
2584 t = ch - '0';
2585 else
2586 break;
2587 if (t < 0 || t >= b)
2588 break;
2589 n = n * b + t;
2590 inp();
2592 return n;
2595 /* read a character for string or char constant and eval escape codes */
2596 static int getq(void)
2598 int c;
2600 redo:
2601 c = ch;
2602 inp();
2603 if (c == '\\') {
2604 switch(ch) {
2605 case '0': case '1': case '2': case '3':
2606 case '4': case '5': case '6': case '7':
2607 /* at most three octal digits */
2608 c = ch - '0';
2609 inp();
2610 if (isoct(ch)) {
2611 c = c * 8 + ch - '0';
2612 inp();
2613 if (isoct(ch)) {
2614 c = c * 8 + ch - '0';
2615 inp();
2618 return c;
2619 case 'x':
2620 inp();
2621 return getn(16);
2622 case 'a':
2623 c = '\a';
2624 break;
2625 case 'b':
2626 c = '\b';
2627 break;
2628 case 'f':
2629 c = '\f';
2630 break;
2631 case 'n':
2632 c = '\n';
2633 break;
2634 case 'r':
2635 c = '\r';
2636 break;
2637 case 't':
2638 c = '\t';
2639 break;
2640 case 'v':
2641 c = '\v';
2642 break;
2643 case 'e':
2644 if (!gnu_ext)
2645 goto invalid_escape;
2646 c = 27;
2647 break;
2648 case '\'':
2649 case '\"':
2650 case '\\':
2651 case '?':
2652 c = ch;
2653 break;
2654 case '\n':
2655 inp();
2656 goto redo;
2657 case '\r':
2658 inp();
2659 if (ch != '\n')
2660 goto invalid_escape;
2661 inp();
2662 goto redo;
2663 default:
2664 invalid_escape:
2665 error("invalid escaped char");
2667 inp();
2668 } else if (c == '\r' && ch == '\n') {
2669 inp();
2670 c = '\n';
2672 return c;
2675 /* we use 64 bit numbers */
2676 #define BN_SIZE 2
2678 /* bn = (bn << shift) | or_val */
2679 void bn_lshift(unsigned int *bn, int shift, int or_val)
2681 int i;
2682 unsigned int v;
2683 for(i=0;i<BN_SIZE;i++) {
2684 v = bn[i];
2685 bn[i] = (v << shift) | or_val;
2686 or_val = v >> (32 - shift);
2690 void bn_zero(unsigned int *bn)
2692 int i;
2693 for(i=0;i<BN_SIZE;i++) {
2694 bn[i] = 0;
2698 /* parse number in null terminated string 'p' and return it in the
2699 current token */
2700 void parse_number(const char *p)
2702 int b, t, shift, frac_bits, s, exp_val, ch;
2703 char *q;
2704 unsigned int bn[BN_SIZE];
2705 double d;
2707 /* number */
2708 q = token_buf;
2709 ch = *p++;
2710 t = ch;
2711 ch = *p++;
2712 *q++ = t;
2713 b = 10;
2714 if (t == '.') {
2715 goto float_frac_parse;
2716 } else if (t == '0') {
2717 if (ch == 'x' || ch == 'X') {
2718 q--;
2719 ch = *p++;
2720 b = 16;
2721 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2722 q--;
2723 ch = *p++;
2724 b = 2;
2727 /* parse all digits. cannot check octal numbers at this stage
2728 because of floating point constants */
2729 while (1) {
2730 if (ch >= 'a' && ch <= 'f')
2731 t = ch - 'a' + 10;
2732 else if (ch >= 'A' && ch <= 'F')
2733 t = ch - 'A' + 10;
2734 else if (isnum(ch))
2735 t = ch - '0';
2736 else
2737 break;
2738 if (t >= b)
2739 break;
2740 if (q >= token_buf + STRING_MAX_SIZE) {
2741 num_too_long:
2742 error("number too long");
2744 *q++ = ch;
2745 ch = *p++;
2747 if (ch == '.' ||
2748 ((ch == 'e' || ch == 'E') && b == 10) ||
2749 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
2750 if (b != 10) {
2751 /* NOTE: strtox should support that for hexa numbers, but
2752 non ISOC99 libcs do not support it, so we prefer to do
2753 it by hand */
2754 /* hexadecimal or binary floats */
2755 /* XXX: handle overflows */
2756 *q = '\0';
2757 if (b == 16)
2758 shift = 4;
2759 else
2760 shift = 2;
2761 bn_zero(bn);
2762 q = token_buf;
2763 while (1) {
2764 t = *q++;
2765 if (t == '\0') {
2766 break;
2767 } else if (t >= 'a') {
2768 t = t - 'a' + 10;
2769 } else if (t >= 'A') {
2770 t = t - 'A' + 10;
2771 } else {
2772 t = t - '0';
2774 bn_lshift(bn, shift, t);
2776 frac_bits = 0;
2777 if (ch == '.') {
2778 ch = *p++;
2779 while (1) {
2780 t = ch;
2781 if (t >= 'a' && t <= 'f') {
2782 t = t - 'a' + 10;
2783 } else if (t >= 'A' && t <= 'F') {
2784 t = t - 'A' + 10;
2785 } else if (t >= '0' && t <= '9') {
2786 t = t - '0';
2787 } else {
2788 break;
2790 if (t >= b)
2791 error("invalid digit");
2792 bn_lshift(bn, shift, t);
2793 frac_bits += shift;
2794 ch = *p++;
2797 if (ch != 'p' && ch != 'P')
2798 expect("exponent");
2799 ch = *p++;
2800 s = 1;
2801 exp_val = 0;
2802 if (ch == '+') {
2803 ch = *p++;
2804 } else if (ch == '-') {
2805 s = -1;
2806 ch = *p++;
2808 if (ch < '0' || ch > '9')
2809 expect("exponent digits");
2810 while (ch >= '0' && ch <= '9') {
2811 exp_val = exp_val * 10 + ch - '0';
2812 ch = *p++;
2814 exp_val = exp_val * s;
2816 /* now we can generate the number */
2817 /* XXX: should patch directly float number */
2818 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
2819 d = ldexp(d, exp_val - frac_bits);
2820 t = toup(ch);
2821 if (t == 'F') {
2822 ch = *p++;
2823 tok = TOK_CFLOAT;
2824 /* float : should handle overflow */
2825 tokc.f = (float)d;
2826 } else if (t == 'L') {
2827 ch = *p++;
2828 tok = TOK_CLDOUBLE;
2829 /* XXX: not large enough */
2830 tokc.ld = (long double)d;
2831 } else {
2832 tok = TOK_CDOUBLE;
2833 tokc.d = d;
2835 } else {
2836 /* decimal floats */
2837 if (ch == '.') {
2838 if (q >= token_buf + STRING_MAX_SIZE)
2839 goto num_too_long;
2840 *q++ = ch;
2841 ch = *p++;
2842 float_frac_parse:
2843 while (ch >= '0' && ch <= '9') {
2844 if (q >= token_buf + STRING_MAX_SIZE)
2845 goto num_too_long;
2846 *q++ = ch;
2847 ch = *p++;
2850 if (ch == 'e' || ch == 'E') {
2851 if (q >= token_buf + STRING_MAX_SIZE)
2852 goto num_too_long;
2853 *q++ = ch;
2854 ch = *p++;
2855 if (ch == '-' || ch == '+') {
2856 if (q >= token_buf + STRING_MAX_SIZE)
2857 goto num_too_long;
2858 *q++ = ch;
2859 ch = *p++;
2861 if (ch < '0' || ch > '9')
2862 expect("exponent digits");
2863 while (ch >= '0' && ch <= '9') {
2864 if (q >= token_buf + STRING_MAX_SIZE)
2865 goto num_too_long;
2866 *q++ = ch;
2867 ch = *p++;
2870 *q = '\0';
2871 t = toup(ch);
2872 errno = 0;
2873 if (t == 'F') {
2874 ch = *p++;
2875 tok = TOK_CFLOAT;
2876 tokc.f = strtof(token_buf, NULL);
2877 } else if (t == 'L') {
2878 ch = *p++;
2879 tok = TOK_CLDOUBLE;
2880 tokc.ld = strtold(token_buf, NULL);
2881 } else {
2882 tok = TOK_CDOUBLE;
2883 tokc.d = strtod(token_buf, NULL);
2886 } else {
2887 unsigned long long n, n1;
2888 int lcount, ucount;
2890 /* integer number */
2891 *q = '\0';
2892 q = token_buf;
2893 if (b == 10 && *q == '0') {
2894 b = 8;
2895 q++;
2897 n = 0;
2898 while(1) {
2899 t = *q++;
2900 /* no need for checks except for base 10 / 8 errors */
2901 if (t == '\0') {
2902 break;
2903 } else if (t >= 'a') {
2904 t = t - 'a' + 10;
2905 } else if (t >= 'A') {
2906 t = t - 'A' + 10;
2907 } else {
2908 t = t - '0';
2909 if (t >= b)
2910 error("invalid digit");
2912 n1 = n;
2913 n = n * b + t;
2914 /* detect overflow */
2915 /* XXX: this test is not reliable */
2916 if (n < n1)
2917 error("integer constant overflow");
2920 /* XXX: not exactly ANSI compliant */
2921 if ((n & 0xffffffff00000000LL) != 0) {
2922 if ((n >> 63) != 0)
2923 tok = TOK_CULLONG;
2924 else
2925 tok = TOK_CLLONG;
2926 } else if (n > 0x7fffffff) {
2927 tok = TOK_CUINT;
2928 } else {
2929 tok = TOK_CINT;
2931 lcount = 0;
2932 ucount = 0;
2933 for(;;) {
2934 t = toup(ch);
2935 if (t == 'L') {
2936 if (lcount >= 2)
2937 error("three 'l's in integer constant");
2938 lcount++;
2939 if (lcount == 2) {
2940 if (tok == TOK_CINT)
2941 tok = TOK_CLLONG;
2942 else if (tok == TOK_CUINT)
2943 tok = TOK_CULLONG;
2945 ch = *p++;
2946 } else if (t == 'U') {
2947 if (ucount >= 1)
2948 error("two 'u's in integer constant");
2949 ucount++;
2950 if (tok == TOK_CINT)
2951 tok = TOK_CUINT;
2952 else if (tok == TOK_CLLONG)
2953 tok = TOK_CULLONG;
2954 ch = *p++;
2955 } else {
2956 break;
2959 if (tok == TOK_CINT || tok == TOK_CUINT)
2960 tokc.ui = n;
2961 else
2962 tokc.ull = n;
2967 #define PARSE2(c1, tok1, c2, tok2) \
2968 case c1: \
2969 PEEKC(c, p); \
2970 if (c == c2) { \
2971 p++; \
2972 tok = tok2; \
2973 } else { \
2974 tok = tok1; \
2976 break;
2978 /* return next token without macro substitution */
2979 static inline void next_nomacro1(void)
2981 int b, t, c;
2982 TokenSym *ts;
2983 uint8_t *p, *p1;
2984 unsigned int h;
2986 p = file->buf_ptr;
2987 redo_no_start:
2988 c = *p;
2989 switch(c) {
2990 case ' ':
2991 case '\t':
2992 case '\f':
2993 case '\v':
2994 case '\r':
2995 p++;
2996 goto redo_no_start;
2998 case '\\':
2999 /* first look if it is in fact an end of buffer */
3000 if (p >= file->buf_end) {
3001 file->buf_ptr = p;
3002 handle_eob();
3003 p = file->buf_ptr;
3004 if (p >= file->buf_end)
3005 goto parse_eof;
3006 else
3007 goto redo_no_start;
3008 } else {
3009 file->buf_ptr = p;
3010 ch = *p;
3011 handle_stray();
3012 p = file->buf_ptr;
3013 goto redo_no_start;
3015 parse_eof:
3017 TCCState *s1 = tcc_state;
3019 if (return_linefeed) {
3020 tok = TOK_LINEFEED;
3021 } else if (s1->include_stack_ptr == s1->include_stack) {
3022 /* no include left : end of file */
3023 tok = TOK_EOF;
3024 } else {
3025 /* pop include file */
3027 /* test if previous '#endif' was after a #ifdef at
3028 start of file */
3029 if (tok_flags & TOK_FLAG_ENDIF) {
3030 #ifdef INC_DEBUG
3031 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3032 #endif
3033 add_cached_include(s1, file->inc_type, file->inc_filename,
3034 file->ifndef_macro_saved);
3037 /* add end of include file debug info */
3038 if (do_debug) {
3039 put_stabd(N_EINCL, 0, 0);
3041 /* pop include stack */
3042 tcc_close(file);
3043 s1->include_stack_ptr--;
3044 file = *s1->include_stack_ptr;
3045 p = file->buf_ptr;
3046 goto redo_no_start;
3049 break;
3051 case '\n':
3052 if (return_linefeed) {
3053 tok = TOK_LINEFEED;
3054 } else {
3055 file->line_num++;
3056 tok_flags |= TOK_FLAG_BOL;
3057 p++;
3058 goto redo_no_start;
3060 break;
3062 case '#':
3063 /* XXX: simplify */
3064 PEEKC(c, p);
3065 if (tok_flags & TOK_FLAG_BOL) {
3066 file->buf_ptr = p;
3067 preprocess(tok_flags & TOK_FLAG_BOF);
3068 p = file->buf_ptr;
3069 goto redo_no_start;
3070 } else {
3071 if (c == '#') {
3072 p++;
3073 tok = TOK_TWOSHARPS;
3074 } else {
3075 tok = '#';
3078 break;
3080 case 'a': case 'b': case 'c': case 'd':
3081 case 'e': case 'f': case 'g': case 'h':
3082 case 'i': case 'j': case 'k': case 'l':
3083 case 'm': case 'n': case 'o': case 'p':
3084 case 'q': case 'r': case 's': case 't':
3085 case 'u': case 'v': case 'w': case 'x':
3086 case 'y': case 'z':
3087 case 'A': case 'B': case 'C': case 'D':
3088 case 'E': case 'F': case 'G': case 'H':
3089 case 'I': case 'J': case 'K':
3090 case 'M': case 'N': case 'O': case 'P':
3091 case 'Q': case 'R': case 'S': case 'T':
3092 case 'U': case 'V': case 'W': case 'X':
3093 case 'Y': case 'Z':
3094 case '_':
3095 parse_ident_fast:
3096 p1 = p;
3097 h = TOK_HASH_INIT;
3098 h = TOK_HASH_FUNC(h, c);
3099 p++;
3100 for(;;) {
3101 c = *p;
3102 if (!isid(c) && !isnum(c))
3103 break;
3104 h = TOK_HASH_FUNC(h, c);
3105 p++;
3107 if (c != '\\') {
3108 TokenSym **pts;
3109 int len;
3111 /* fast case : no stray found, so we have the full token
3112 and we have already hashed it */
3113 len = p - p1;
3114 h &= (TOK_HASH_SIZE - 1);
3115 pts = &hash_ident[h];
3116 for(;;) {
3117 ts = *pts;
3118 if (!ts)
3119 break;
3120 if (ts->len == len && !memcmp(ts->str, p1, len))
3121 goto token_found;
3122 pts = &(ts->hash_next);
3124 ts = tok_alloc_new(pts, p1, len);
3125 token_found: ;
3126 } else {
3127 /* slower case */
3128 cstr_reset(&tokcstr);
3130 while (p1 < p) {
3131 cstr_ccat(&tokcstr, *p1);
3132 p1++;
3134 p--;
3135 PEEKC(c, p);
3136 parse_ident_slow:
3137 while (isid(c) || isnum(c)) {
3138 cstr_ccat(&tokcstr, c);
3139 PEEKC(c, p);
3141 ts = tok_alloc(tokcstr.data, tokcstr.size);
3143 tok = ts->tok;
3144 break;
3145 case 'L':
3146 t = p[1];
3147 if (t != '\\' && t != '\'' && t != '\"') {
3148 /* fast case */
3149 goto parse_ident_fast;
3150 } else {
3151 PEEKC(c, p);
3152 if (c == '\'') {
3153 tok = TOK_LCHAR;
3154 goto char_const;
3155 } else if (c == '\"') {
3156 tok = TOK_LSTR;
3157 goto str_const;
3158 } else {
3159 cstr_reset(&tokcstr);
3160 cstr_ccat(&tokcstr, 'L');
3161 goto parse_ident_slow;
3164 break;
3165 case '0': case '1': case '2': case '3':
3166 case '4': case '5': case '6': case '7':
3167 case '8': case '9':
3169 cstr_reset(&tokcstr);
3170 /* after the first digit, accept digits, alpha, '.' or sign if
3171 prefixed by 'eEpP' */
3172 parse_num:
3173 for(;;) {
3174 t = c;
3175 cstr_ccat(&tokcstr, c);
3176 PEEKC(c, p);
3177 if (!(isnum(c) || isid(c) || c == '.' ||
3178 ((c == '+' || c == '-') &&
3179 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3180 break;
3182 /* We add a trailing '\0' to ease parsing */
3183 cstr_ccat(&tokcstr, '\0');
3184 tokc.cstr = &tokcstr;
3185 tok = TOK_PPNUM;
3186 break;
3187 case '.':
3188 /* special dot handling because it can also start a number */
3189 PEEKC(c, p);
3190 if (isnum(c)) {
3191 cstr_reset(&tokcstr);
3192 cstr_ccat(&tokcstr, '.');
3193 goto parse_num;
3194 } else if (c == '.') {
3195 PEEKC(c, p);
3196 if (c != '.')
3197 expect("'.'");
3198 PEEKC(c, p);
3199 tok = TOK_DOTS;
3200 } else {
3201 tok = '.';
3203 break;
3204 case '\'':
3205 tok = TOK_CCHAR;
3206 char_const:
3207 file->buf_ptr = p;
3208 inp();
3209 b = getq();
3210 /* this cast is needed if >= 128 */
3211 if (tok == TOK_CCHAR)
3212 b = (char)b;
3213 tokc.i = b;
3214 if (ch != '\'')
3215 error("unterminated character constant");
3216 p = file->buf_ptr;
3217 p++;
3218 break;
3219 case '\"':
3220 tok = TOK_STR;
3221 str_const:
3222 file->buf_ptr = p;
3223 inp();
3224 cstr_reset(&tokcstr);
3225 while (ch != '\"') {
3226 b = getq();
3227 if (ch == CH_EOF)
3228 error("unterminated string");
3229 if (tok == TOK_STR)
3230 cstr_ccat(&tokcstr, b);
3231 else
3232 cstr_wccat(&tokcstr, b);
3234 if (tok == TOK_STR)
3235 cstr_ccat(&tokcstr, '\0');
3236 else
3237 cstr_wccat(&tokcstr, '\0');
3238 tokc.cstr = &tokcstr;
3239 p = file->buf_ptr;
3240 p++;
3241 break;
3243 case '<':
3244 PEEKC(c, p);
3245 if (c == '=') {
3246 p++;
3247 tok = TOK_LE;
3248 } else if (c == '<') {
3249 PEEKC(c, p);
3250 if (c == '=') {
3251 p++;
3252 tok = TOK_A_SHL;
3253 } else {
3254 tok = TOK_SHL;
3256 } else {
3257 tok = TOK_LT;
3259 break;
3261 case '>':
3262 PEEKC(c, p);
3263 if (c == '=') {
3264 p++;
3265 tok = TOK_GE;
3266 } else if (c == '>') {
3267 PEEKC(c, p);
3268 if (c == '=') {
3269 p++;
3270 tok = TOK_A_SAR;
3271 } else {
3272 tok = TOK_SAR;
3274 } else {
3275 tok = TOK_GT;
3277 break;
3279 case '&':
3280 PEEKC(c, p);
3281 if (c == '&') {
3282 p++;
3283 tok = TOK_LAND;
3284 } else if (c == '=') {
3285 p++;
3286 tok = TOK_A_AND;
3287 } else {
3288 tok = '&';
3290 break;
3292 case '|':
3293 PEEKC(c, p);
3294 if (c == '|') {
3295 p++;
3296 tok = TOK_LOR;
3297 } else if (c == '=') {
3298 p++;
3299 tok = TOK_A_OR;
3300 } else {
3301 tok = '|';
3303 break;
3305 case '+':
3306 PEEKC(c, p);
3307 if (c == '+') {
3308 p++;
3309 tok = TOK_INC;
3310 } else if (c == '=') {
3311 p++;
3312 tok = TOK_A_ADD;
3313 } else {
3314 tok = '+';
3316 break;
3318 case '-':
3319 PEEKC(c, p);
3320 if (c == '-') {
3321 p++;
3322 tok = TOK_DEC;
3323 } else if (c == '=') {
3324 p++;
3325 tok = TOK_A_SUB;
3326 } else if (c == '>') {
3327 p++;
3328 tok = TOK_ARROW;
3329 } else {
3330 tok = '-';
3332 break;
3334 PARSE2('!', '!', '=', TOK_NE)
3335 PARSE2('=', '=', '=', TOK_EQ)
3336 PARSE2('*', '*', '=', TOK_A_MUL)
3337 PARSE2('%', '%', '=', TOK_A_MOD)
3338 PARSE2('^', '^', '=', TOK_A_XOR)
3340 /* comments or operator */
3341 case '/':
3342 PEEKC(c, p);
3343 if (c == '*') {
3344 file->buf_ptr = p;
3345 parse_comment();
3346 p = file->buf_ptr;
3347 goto redo_no_start;
3348 } else if (c == '/') {
3349 file->buf_ptr = p;
3350 parse_line_comment();
3351 p = file->buf_ptr;
3352 goto redo_no_start;
3353 } else if (c == '=') {
3354 p++;
3355 tok = TOK_A_DIV;
3356 } else {
3357 tok = '/';
3359 break;
3361 /* simple tokens */
3362 case '(':
3363 case ')':
3364 case '[':
3365 case ']':
3366 case '{':
3367 case '}':
3368 case ',':
3369 case ';':
3370 case ':':
3371 case '?':
3372 case '~':
3373 tok = c;
3374 p++;
3375 break;
3376 default:
3377 error("unrecognized character \\x%02x", c);
3378 break;
3380 file->buf_ptr = p;
3381 tok_flags = 0;
3382 #if defined(PARSE_DEBUG)
3383 printf("token = %s\n", get_tok_str(tok, &tokc));
3384 #endif
3387 /* return next token without macro substitution. Can read input from
3388 macro_ptr buffer */
3389 static void next_nomacro(void)
3391 if (macro_ptr) {
3392 redo:
3393 tok = *macro_ptr;
3394 if (tok) {
3395 TOK_GET(tok, macro_ptr, tokc);
3396 if (tok == TOK_LINENUM) {
3397 file->line_num = tokc.i;
3398 goto redo;
3401 } else {
3402 next_nomacro1();
3406 /* substitute args in macro_str and return allocated string */
3407 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3409 int *st, last_tok, t, notfirst;
3410 Sym *s;
3411 CValue cval;
3412 TokenString str;
3413 CString cstr;
3415 tok_str_new(&str);
3416 last_tok = 0;
3417 while(1) {
3418 TOK_GET(t, macro_str, cval);
3419 if (!t)
3420 break;
3421 if (t == '#') {
3422 /* stringize */
3423 TOK_GET(t, macro_str, cval);
3424 if (!t)
3425 break;
3426 s = sym_find2(args, t);
3427 if (s) {
3428 cstr_new(&cstr);
3429 st = (int *)s->c;
3430 notfirst = 0;
3431 while (*st) {
3432 if (notfirst)
3433 cstr_ccat(&cstr, ' ');
3434 TOK_GET(t, st, cval);
3435 cstr_cat(&cstr, get_tok_str(t, &cval));
3436 notfirst = 1;
3438 cstr_ccat(&cstr, '\0');
3439 #ifdef PP_DEBUG
3440 printf("stringize: %s\n", (char *)cstr.data);
3441 #endif
3442 /* add string */
3443 cval.cstr = &cstr;
3444 tok_str_add2(&str, TOK_STR, &cval);
3445 cstr_free(&cstr);
3446 } else {
3447 tok_str_add2(&str, t, &cval);
3449 } else if (t >= TOK_IDENT) {
3450 s = sym_find2(args, t);
3451 if (s) {
3452 st = (int *)s->c;
3453 /* if '##' is present before or after, no arg substitution */
3454 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3455 /* special case for var arg macros : ## eats the
3456 ',' if empty VA_ARGS variable. */
3457 /* XXX: test of the ',' is not 100%
3458 reliable. should fix it to avoid security
3459 problems */
3460 if (gnu_ext && s->type.t &&
3461 last_tok == TOK_TWOSHARPS &&
3462 str.len >= 2 && str.str[str.len - 2] == ',') {
3463 if (*st == 0) {
3464 /* suppress ',' '##' */
3465 str.len -= 2;
3466 } else {
3467 /* suppress '##' and add variable */
3468 str.len--;
3469 goto add_var;
3471 } else {
3472 int t1;
3473 add_var:
3474 for(;;) {
3475 TOK_GET(t1, st, cval);
3476 if (!t1)
3477 break;
3478 tok_str_add2(&str, t1, &cval);
3481 } else {
3482 macro_subst(&str, nested_list, st);
3484 } else {
3485 tok_str_add(&str, t);
3487 } else {
3488 tok_str_add2(&str, t, &cval);
3490 last_tok = t;
3492 tok_str_add(&str, 0);
3493 return str.str;
3496 /* handle the '##' operator */
3497 static int *macro_twosharps(void)
3499 TokenSym *ts;
3500 int *macro_ptr1;
3501 int t;
3502 const char *p1, *p2;
3503 CValue cval;
3504 TokenString macro_str1;
3505 CString cstr;
3507 cstr_new(&cstr);
3508 tok_str_new(&macro_str1);
3509 tok = 0;
3510 while (1) {
3511 next_nomacro();
3512 if (tok == 0)
3513 break;
3514 while (*macro_ptr == TOK_TWOSHARPS) {
3515 macro_ptr++;
3516 macro_ptr1 = macro_ptr;
3517 t = *macro_ptr;
3518 if (t) {
3519 TOK_GET(t, macro_ptr, cval);
3521 /* We concatenate the two tokens if we have an
3522 identifier or a preprocessing number */
3523 cstr_reset(&cstr);
3524 p1 = get_tok_str(tok, &tokc);
3525 cstr_cat(&cstr, p1);
3526 p2 = get_tok_str(t, &cval);
3527 cstr_cat(&cstr, p2);
3528 cstr_ccat(&cstr, '\0');
3530 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3531 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3532 if (tok == TOK_PPNUM) {
3533 /* if number, then create a number token */
3534 /* NOTE: no need to allocate because
3535 tok_str_add2() does it */
3536 tokc.cstr = &cstr;
3537 } else {
3538 /* if identifier, we must do a test to
3539 validate we have a correct identifier */
3540 if (t == TOK_PPNUM) {
3541 const char *p;
3542 int c;
3544 p = p2;
3545 for(;;) {
3546 c = *p;
3547 if (c == '\0')
3548 break;
3549 p++;
3550 if (!isnum(c) && !isid(c))
3551 goto error_pasting;
3554 ts = tok_alloc(cstr.data, strlen(cstr.data));
3555 tok = ts->tok; /* modify current token */
3557 } else {
3558 const char *str = cstr.data;
3559 const unsigned char *q;
3561 /* we look for a valid token */
3562 /* XXX: do more extensive checks */
3563 if (!strcmp(str, ">>=")) {
3564 tok = TOK_A_SAR;
3565 } else if (!strcmp(str, "<<=")) {
3566 tok = TOK_A_SHL;
3567 } else if (strlen(str) == 2) {
3568 /* search in two bytes table */
3569 q = tok_two_chars;
3570 for(;;) {
3571 if (!*q)
3572 goto error_pasting;
3573 if (q[0] == str[0] && q[1] == str[1])
3574 break;
3575 q += 3;
3577 tok = q[2];
3578 } else {
3579 error_pasting:
3580 /* NOTE: because get_tok_str use a static buffer,
3581 we must save it */
3582 cstr_reset(&cstr);
3583 p1 = get_tok_str(tok, &tokc);
3584 cstr_cat(&cstr, p1);
3585 cstr_ccat(&cstr, '\0');
3586 p2 = get_tok_str(t, &cval);
3587 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
3588 /* cannot merge tokens: just add them separately */
3589 tok_str_add2(&macro_str1, tok, &tokc);
3590 /* XXX: free associated memory ? */
3591 tok = t;
3592 tokc = cval;
3597 tok_str_add2(&macro_str1, tok, &tokc);
3599 cstr_free(&cstr);
3600 tok_str_add(&macro_str1, 0);
3601 return macro_str1.str;
3605 /* do macro substitution of current token with macro 's' and add
3606 result to (tok_str,tok_len). 'nested_list' is the list of all
3607 macros we got inside to avoid recursing. Return non zero if no
3608 substitution needs to be done */
3609 static int macro_subst_tok(TokenString *tok_str,
3610 Sym **nested_list, Sym *s)
3612 Sym *args, *sa, *sa1;
3613 int mstr_allocated, parlevel, *mstr, t;
3614 TokenString str;
3615 char *cstrval;
3616 CValue cval;
3617 CString cstr;
3619 /* if symbol is a macro, prepare substitution */
3620 /* if nested substitution, do nothing */
3621 if (sym_find2(*nested_list, tok))
3622 return -1;
3624 /* special macros */
3625 if (tok == TOK___LINE__) {
3626 cval.i = file->line_num;
3627 tok_str_add2(tok_str, TOK_CINT, &cval);
3628 } else if (tok == TOK___FILE__) {
3629 cstrval = file->filename;
3630 goto add_cstr;
3631 tok_str_add2(tok_str, TOK_STR, &cval);
3632 } else if (tok == TOK___DATE__) {
3633 cstrval = "Jan 1 2002";
3634 goto add_cstr;
3635 } else if (tok == TOK___TIME__) {
3636 cstrval = "00:00:00";
3637 add_cstr:
3638 cstr_new(&cstr);
3639 cstr_cat(&cstr, cstrval);
3640 cstr_ccat(&cstr, '\0');
3641 cval.cstr = &cstr;
3642 tok_str_add2(tok_str, TOK_STR, &cval);
3643 cstr_free(&cstr);
3644 } else {
3645 mstr = (int *)s->c;
3646 mstr_allocated = 0;
3647 if (s->type.t == MACRO_FUNC) {
3648 /* NOTE: we do not use next_nomacro to avoid eating the
3649 next token. XXX: find better solution */
3650 if (macro_ptr) {
3651 t = *macro_ptr;
3652 } else {
3653 /* XXX: incorrect with comments */
3654 ch = file->buf_ptr[0];
3655 while (is_space(ch) || ch == '\n')
3656 cinp();
3657 t = ch;
3659 if (t != '(') /* no macro subst */
3660 return -1;
3662 /* argument macro */
3663 next_nomacro();
3664 next_nomacro();
3665 args = NULL;
3666 sa = s->next;
3667 /* NOTE: empty args are allowed, except if no args */
3668 for(;;) {
3669 /* handle '()' case */
3670 if (!args && tok == ')')
3671 break;
3672 if (!sa)
3673 error("macro '%s' used with too many args",
3674 get_tok_str(s->v, 0));
3675 tok_str_new(&str);
3676 parlevel = 0;
3677 /* NOTE: non zero sa->t indicates VA_ARGS */
3678 while ((parlevel > 0 ||
3679 (tok != ')' &&
3680 (tok != ',' || sa->type.t))) &&
3681 tok != -1) {
3682 if (tok == '(')
3683 parlevel++;
3684 else if (tok == ')')
3685 parlevel--;
3686 tok_str_add2(&str, tok, &tokc);
3687 next_nomacro();
3689 tok_str_add(&str, 0);
3690 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3691 sa = sa->next;
3692 if (tok == ')') {
3693 /* special case for gcc var args: add an empty
3694 var arg argument if it is omitted */
3695 if (sa && sa->type.t && gnu_ext)
3696 continue;
3697 else
3698 break;
3700 if (tok != ',')
3701 expect(",");
3702 next_nomacro();
3704 if (sa) {
3705 error("macro '%s' used with too few args",
3706 get_tok_str(s->v, 0));
3709 /* now subst each arg */
3710 mstr = macro_arg_subst(nested_list, mstr, args);
3711 /* free memory */
3712 sa = args;
3713 while (sa) {
3714 sa1 = sa->prev;
3715 tok_str_free((int *)sa->c);
3716 tcc_free(sa);
3717 sa = sa1;
3719 mstr_allocated = 1;
3721 sym_push2(nested_list, s->v, 0, 0);
3722 macro_subst(tok_str, nested_list, mstr);
3723 /* pop nested defined symbol */
3724 sa1 = *nested_list;
3725 *nested_list = sa1->prev;
3726 tcc_free(sa1);
3727 if (mstr_allocated)
3728 tok_str_free(mstr);
3730 return 0;
3733 /* do macro substitution of macro_str and add result to
3734 (tok_str,tok_len). 'nested_list' is the list of all macros we got
3735 inside to avoid recursing. */
3736 static void macro_subst(TokenString *tok_str,
3737 Sym **nested_list, int *macro_str)
3739 Sym *s;
3740 int *saved_macro_ptr;
3741 int *macro_str1;
3743 saved_macro_ptr = macro_ptr;
3744 macro_ptr = macro_str;
3745 /* first scan for '##' operator handling */
3746 macro_str1 = macro_twosharps();
3747 macro_ptr = macro_str1;
3749 while (1) {
3750 next_nomacro();
3751 if (tok == 0)
3752 break;
3753 s = define_find(tok);
3754 if (s != NULL) {
3755 if (macro_subst_tok(tok_str, nested_list, s) != 0)
3756 goto no_subst;
3757 } else {
3758 no_subst:
3759 tok_str_add2(tok_str, tok, &tokc);
3762 macro_ptr = saved_macro_ptr;
3763 tok_str_free(macro_str1);
3766 /* return next token with macro substitution */
3767 static void next(void)
3769 Sym *nested_list, *s;
3770 TokenString str;
3772 /* special 'ungettok' case for label parsing */
3773 if (tok1) {
3774 tok = tok1;
3775 tokc = tok1c;
3776 tok1 = 0;
3777 } else {
3778 redo:
3779 next_nomacro();
3780 if (!macro_ptr) {
3781 /* if not reading from macro substituted string, then try
3782 to substitute macros */
3783 if (tok >= TOK_IDENT) {
3784 s = define_find(tok);
3785 if (s) {
3786 /* we have a macro: we try to substitute */
3787 tok_str_new(&str);
3788 nested_list = NULL;
3789 if (macro_subst_tok(&str, &nested_list, s) == 0) {
3790 /* substitution done, NOTE: maybe empty */
3791 tok_str_add(&str, 0);
3792 macro_ptr = str.str;
3793 macro_ptr_allocated = str.str;
3794 goto redo;
3798 } else {
3799 if (tok == 0) {
3800 /* end of macro string: free it */
3801 tok_str_free(macro_ptr_allocated);
3802 macro_ptr = NULL;
3803 goto redo;
3807 /* convert preprocessor tokens into C tokens */
3808 if (tok == TOK_PPNUM) {
3809 parse_number((char *)tokc.cstr->data);
3814 void swap(int *p, int *q)
3816 int t;
3817 t = *p;
3818 *p = *q;
3819 *q = t;
3822 void vsetc(CType *type, int r, CValue *vc)
3824 int v;
3826 if (vtop >= vstack + VSTACK_SIZE)
3827 error("memory full");
3828 /* cannot let cpu flags if other instruction are generated. Also
3829 avoid leaving VT_JMP anywhere except on the top of the stack
3830 because it would complicate the code generator. */
3831 if (vtop >= vstack) {
3832 v = vtop->r & VT_VALMASK;
3833 if (v == VT_CMP || (v & ~1) == VT_JMP)
3834 gv(RC_INT);
3836 vtop++;
3837 vtop->type = *type;
3838 vtop->r = r;
3839 vtop->r2 = VT_CONST;
3840 vtop->c = *vc;
3843 /* push integer constant */
3844 void vpushi(int v)
3846 CValue cval;
3847 cval.i = v;
3848 vsetc(&int_type, VT_CONST, &cval);
3851 /* Return a static symbol pointing to a section */
3852 static Sym *get_sym_ref(CType *type, Section *sec,
3853 unsigned long offset, unsigned long size)
3855 int v;
3856 Sym *sym;
3858 v = anon_sym++;
3859 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
3860 sym->type.ref = type->ref;
3861 sym->r = VT_CONST | VT_SYM;
3862 put_extern_sym(sym, sec, offset, size);
3863 return sym;
3866 /* push a reference to a section offset by adding a dummy symbol */
3867 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
3869 CValue cval;
3871 cval.ul = 0;
3872 vsetc(type, VT_CONST | VT_SYM, &cval);
3873 vtop->sym = get_sym_ref(type, sec, offset, size);
3876 /* define a new external reference to a symbol 'v' of type 'u' */
3877 static Sym *external_global_sym(int v, CType *type, int r)
3879 Sym *s;
3881 s = sym_find(v);
3882 if (!s) {
3883 /* push forward reference */
3884 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
3885 s->type.ref = type->ref;
3886 s->r = r | VT_CONST | VT_SYM;
3888 return s;
3891 /* define a new external reference to a symbol 'v' of type 'u' */
3892 static Sym *external_sym(int v, CType *type, int r)
3894 Sym *s;
3896 s = sym_find(v);
3897 if (!s) {
3898 /* push forward reference */
3899 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
3900 s->type.t |= VT_EXTERN;
3902 return s;
3905 /* push a reference to global symbol v */
3906 static void vpush_global_sym(CType *type, int v)
3908 Sym *sym;
3909 CValue cval;
3911 sym = external_global_sym(v, type, 0);
3912 cval.ul = 0;
3913 vsetc(type, VT_CONST | VT_SYM, &cval);
3914 vtop->sym = sym;
3917 void vset(CType *type, int r, int v)
3919 CValue cval;
3921 cval.i = v;
3922 vsetc(type, r, &cval);
3925 void vseti(int r, int v)
3927 CType type;
3928 type.t = VT_INT;
3929 vset(&type, r, v);
3932 void vswap(void)
3934 SValue tmp;
3936 tmp = vtop[0];
3937 vtop[0] = vtop[-1];
3938 vtop[-1] = tmp;
3941 void vpushv(SValue *v)
3943 if (vtop >= vstack + VSTACK_SIZE)
3944 error("memory full");
3945 vtop++;
3946 *vtop = *v;
3949 void vdup(void)
3951 vpushv(vtop);
3954 /* save r to the memory stack, and mark it as being free */
3955 void save_reg(int r)
3957 int l, saved, size, align;
3958 SValue *p, sv;
3959 CType *type;
3961 /* modify all stack values */
3962 saved = 0;
3963 l = 0;
3964 for(p=vstack;p<=vtop;p++) {
3965 if ((p->r & VT_VALMASK) == r ||
3966 (p->r2 & VT_VALMASK) == r) {
3967 /* must save value on stack if not already done */
3968 if (!saved) {
3969 /* NOTE: must reload 'r' because r might be equal to r2 */
3970 r = p->r & VT_VALMASK;
3971 /* store register in the stack */
3972 type = &p->type;
3973 if ((p->r & VT_LVAL) ||
3974 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
3975 type = &int_type;
3976 size = type_size(type, &align);
3977 loc = (loc - size) & -align;
3978 sv.type.t = type->t;
3979 sv.r = VT_LOCAL | VT_LVAL;
3980 sv.c.ul = loc;
3981 store(r, &sv);
3982 #ifdef TCC_TARGET_I386
3983 /* x86 specific: need to pop fp register ST0 if saved */
3984 if (r == REG_ST0) {
3985 o(0xd9dd); /* fstp %st(1) */
3987 #endif
3988 /* special long long case */
3989 if ((type->t & VT_BTYPE) == VT_LLONG) {
3990 sv.c.ul += 4;
3991 store(p->r2, &sv);
3993 l = loc;
3994 saved = 1;
3996 /* mark that stack entry as being saved on the stack */
3997 if (p->r & VT_LVAL) {
3998 /* also suppress the bounded flag because the
3999 relocation address of the function was stored in
4000 p->c.ul */
4001 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4002 } else {
4003 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4005 p->r2 = VT_CONST;
4006 p->c.ul = l;
4011 /* find a free register of class 'rc'. If none, save one register */
4012 int get_reg(int rc)
4014 int r;
4015 SValue *p;
4017 /* find a free register */
4018 for(r=0;r<NB_REGS;r++) {
4019 if (reg_classes[r] & rc) {
4020 for(p=vstack;p<=vtop;p++) {
4021 if ((p->r & VT_VALMASK) == r ||
4022 (p->r2 & VT_VALMASK) == r)
4023 goto notfound;
4025 return r;
4027 notfound: ;
4030 /* no register left : free the first one on the stack (VERY
4031 IMPORTANT to start from the bottom to ensure that we don't
4032 spill registers used in gen_opi()) */
4033 for(p=vstack;p<=vtop;p++) {
4034 r = p->r & VT_VALMASK;
4035 if (r < VT_CONST && (reg_classes[r] & rc))
4036 goto save_found;
4037 /* also look at second register (if long long) */
4038 r = p->r2 & VT_VALMASK;
4039 if (r < VT_CONST && (reg_classes[r] & rc)) {
4040 save_found:
4041 save_reg(r);
4042 return r;
4045 /* Should never comes here */
4046 return -1;
4049 /* save registers up to (vtop - n) stack entry */
4050 void save_regs(int n)
4052 int r;
4053 SValue *p, *p1;
4054 p1 = vtop - n;
4055 for(p = vstack;p <= p1; p++) {
4056 r = p->r & VT_VALMASK;
4057 if (r < VT_CONST) {
4058 save_reg(r);
4063 /* move register 's' to 'r', and flush previous value of r to memory
4064 if needed */
4065 void move_reg(int r, int s)
4067 SValue sv;
4069 if (r != s) {
4070 save_reg(r);
4071 sv.type.t = VT_INT;
4072 sv.r = s;
4073 sv.c.ul = 0;
4074 load(r, &sv);
4078 /* get address of vtop (vtop MUST BE an lvalue) */
4079 void gaddrof(void)
4081 vtop->r &= ~VT_LVAL;
4082 /* tricky: if saved lvalue, then we can go back to lvalue */
4083 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4084 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4087 #ifdef CONFIG_TCC_BCHECK
4088 /* generate lvalue bound code */
4089 void gbound(void)
4091 int lval_type;
4092 CType type1;
4094 vtop->r &= ~VT_MUSTBOUND;
4095 /* if lvalue, then use checking code before dereferencing */
4096 if (vtop->r & VT_LVAL) {
4097 /* if not VT_BOUNDED value, then make one */
4098 if (!(vtop->r & VT_BOUNDED)) {
4099 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4100 /* must save type because we must set it to int to get pointer */
4101 type1 = vtop->type;
4102 vtop->type.t = VT_INT;
4103 gaddrof();
4104 vpushi(0);
4105 gen_bounded_ptr_add();
4106 vtop->r |= lval_type;
4107 vtop->type = type1;
4109 /* then check for dereferencing */
4110 gen_bounded_ptr_deref();
4113 #endif
4115 /* store vtop a register belonging to class 'rc'. lvalues are
4116 converted to values. Cannot be used if cannot be converted to
4117 register value (such as structures). */
4118 int gv(int rc)
4120 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4121 unsigned long long ll;
4123 /* NOTE: get_reg can modify vstack[] */
4124 if (vtop->type.t & VT_BITFIELD) {
4125 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4126 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4127 /* remove bit field info to avoid loops */
4128 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4129 /* generate shifts */
4130 vpushi(32 - (bit_pos + bit_size));
4131 gen_op(TOK_SHL);
4132 vpushi(32 - bit_size);
4133 /* NOTE: transformed to SHR if unsigned */
4134 gen_op(TOK_SAR);
4135 r = gv(rc);
4136 } else {
4137 if (is_float(vtop->type.t) &&
4138 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4139 Sym *sym;
4140 int *ptr;
4141 unsigned long offset;
4143 /* XXX: unify with initializers handling ? */
4144 /* CPUs usually cannot use float constants, so we store them
4145 generically in data segment */
4146 size = type_size(&vtop->type, &align);
4147 offset = (data_section->data_offset + align - 1) & -align;
4148 data_section->data_offset = offset;
4149 /* XXX: not portable yet */
4150 ptr = section_ptr_add(data_section, size);
4151 size = size >> 2;
4152 for(i=0;i<size;i++)
4153 ptr[i] = vtop->c.tab[i];
4154 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4155 vtop->r |= VT_LVAL | VT_SYM;
4156 vtop->sym = sym;
4157 vtop->c.ul = 0;
4159 #ifdef CONFIG_TCC_BCHECK
4160 if (vtop->r & VT_MUSTBOUND)
4161 gbound();
4162 #endif
4164 r = vtop->r & VT_VALMASK;
4165 /* need to reload if:
4166 - constant
4167 - lvalue (need to dereference pointer)
4168 - already a register, but not in the right class */
4169 if (r >= VT_CONST ||
4170 (vtop->r & VT_LVAL) ||
4171 !(reg_classes[r] & rc) ||
4172 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4173 !(reg_classes[vtop->r2] & rc))) {
4174 r = get_reg(rc);
4175 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4176 /* two register type load : expand to two words
4177 temporarily */
4178 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4179 /* load constant */
4180 ll = vtop->c.ull;
4181 vtop->c.ui = ll; /* first word */
4182 load(r, vtop);
4183 vtop->r = r; /* save register value */
4184 vpushi(ll >> 32); /* second word */
4185 } else if (r >= VT_CONST ||
4186 (vtop->r & VT_LVAL)) {
4187 /* load from memory */
4188 load(r, vtop);
4189 vdup();
4190 vtop[-1].r = r; /* save register value */
4191 /* increment pointer to get second word */
4192 vtop->type.t = VT_INT;
4193 gaddrof();
4194 vpushi(4);
4195 gen_op('+');
4196 vtop->r |= VT_LVAL;
4197 } else {
4198 /* move registers */
4199 load(r, vtop);
4200 vdup();
4201 vtop[-1].r = r; /* save register value */
4202 vtop->r = vtop[-1].r2;
4204 /* allocate second register */
4205 rc2 = RC_INT;
4206 if (rc == RC_IRET)
4207 rc2 = RC_LRET;
4208 r2 = get_reg(rc2);
4209 load(r2, vtop);
4210 vpop();
4211 /* write second register */
4212 vtop->r2 = r2;
4213 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4214 int t1, t;
4215 /* lvalue of scalar type : need to use lvalue type
4216 because of possible cast */
4217 t = vtop->type.t;
4218 t1 = t;
4219 /* compute memory access type */
4220 if (vtop->r & VT_LVAL_BYTE)
4221 t = VT_BYTE;
4222 else if (vtop->r & VT_LVAL_SHORT)
4223 t = VT_SHORT;
4224 if (vtop->r & VT_LVAL_UNSIGNED)
4225 t |= VT_UNSIGNED;
4226 vtop->type.t = t;
4227 load(r, vtop);
4228 /* restore wanted type */
4229 vtop->type.t = t1;
4230 } else {
4231 /* one register type load */
4232 load(r, vtop);
4235 vtop->r = r;
4237 return r;
4240 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4241 void gv2(int rc1, int rc2)
4243 int v;
4245 /* generate more generic register first. But VT_JMP or VT_CMP
4246 values must be generated first in all cases to avoid possible
4247 reload errors */
4248 v = vtop[0].r & VT_VALMASK;
4249 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4250 vswap();
4251 gv(rc1);
4252 vswap();
4253 gv(rc2);
4254 /* test if reload is needed for first register */
4255 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4256 vswap();
4257 gv(rc1);
4258 vswap();
4260 } else {
4261 gv(rc2);
4262 vswap();
4263 gv(rc1);
4264 vswap();
4265 /* test if reload is needed for first register */
4266 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4267 gv(rc2);
4272 /* expand long long on stack in two int registers */
4273 void lexpand(void)
4275 int u;
4277 u = vtop->type.t & VT_UNSIGNED;
4278 gv(RC_INT);
4279 vdup();
4280 vtop[0].r = vtop[-1].r2;
4281 vtop[0].r2 = VT_CONST;
4282 vtop[-1].r2 = VT_CONST;
4283 vtop[0].type.t = VT_INT | u;
4284 vtop[-1].type.t = VT_INT | u;
4287 /* build a long long from two ints */
4288 void lbuild(int t)
4290 gv2(RC_INT, RC_INT);
4291 vtop[-1].r2 = vtop[0].r;
4292 vtop[-1].type.t = t;
4293 vpop();
4296 /* rotate n first stack elements to the bottom */
4297 void vrotb(int n)
4299 int i;
4300 SValue tmp;
4302 tmp = vtop[-n + 1];
4303 for(i=-n+1;i!=0;i++)
4304 vtop[i] = vtop[i+1];
4305 vtop[0] = tmp;
4308 /* pop stack value */
4309 void vpop(void)
4311 int v;
4312 v = vtop->r & VT_VALMASK;
4313 #ifdef TCC_TARGET_I386
4314 /* for x86, we need to pop the FP stack */
4315 if (v == REG_ST0 && !nocode_wanted) {
4316 o(0xd9dd); /* fstp %st(1) */
4317 } else
4318 #endif
4319 if (v == VT_JMP || v == VT_JMPI) {
4320 /* need to put correct jump if && or || without test */
4321 gsym(vtop->c.ul);
4323 vtop--;
4326 /* convert stack entry to register and duplicate its value in another
4327 register */
4328 void gv_dup(void)
4330 int rc, t, r, r1;
4331 SValue sv;
4333 t = vtop->type.t;
4334 if ((t & VT_BTYPE) == VT_LLONG) {
4335 lexpand();
4336 gv_dup();
4337 vswap();
4338 vrotb(3);
4339 gv_dup();
4340 vrotb(4);
4341 /* stack: H L L1 H1 */
4342 lbuild(t);
4343 vrotb(3);
4344 vrotb(3);
4345 vswap();
4346 lbuild(t);
4347 vswap();
4348 } else {
4349 /* duplicate value */
4350 rc = RC_INT;
4351 sv.type.t = VT_INT;
4352 if (is_float(t)) {
4353 rc = RC_FLOAT;
4354 sv.type.t = t;
4356 r = gv(rc);
4357 r1 = get_reg(rc);
4358 sv.r = r;
4359 sv.c.ul = 0;
4360 load(r1, &sv); /* move r to r1 */
4361 vdup();
4362 /* duplicates value */
4363 vtop->r = r1;
4367 /* generate CPU independent (unsigned) long long operations */
4368 void gen_opl(int op)
4370 int t, a, b, op1, c, i;
4371 int func;
4372 GFuncContext gf;
4373 SValue tmp;
4375 switch(op) {
4376 case '/':
4377 case TOK_PDIV:
4378 func = TOK___divdi3;
4379 goto gen_func;
4380 case TOK_UDIV:
4381 func = TOK___udivdi3;
4382 goto gen_func;
4383 case '%':
4384 func = TOK___moddi3;
4385 goto gen_func;
4386 case TOK_UMOD:
4387 func = TOK___umoddi3;
4388 gen_func:
4389 /* call generic long long function */
4390 gfunc_start(&gf, FUNC_CDECL);
4391 gfunc_param(&gf);
4392 gfunc_param(&gf);
4393 vpush_global_sym(&func_old_type, func);
4394 gfunc_call(&gf);
4395 vpushi(0);
4396 vtop->r = REG_IRET;
4397 vtop->r2 = REG_LRET;
4398 break;
4399 case '^':
4400 case '&':
4401 case '|':
4402 case '*':
4403 case '+':
4404 case '-':
4405 t = vtop->type.t;
4406 vswap();
4407 lexpand();
4408 vrotb(3);
4409 lexpand();
4410 /* stack: L1 H1 L2 H2 */
4411 tmp = vtop[0];
4412 vtop[0] = vtop[-3];
4413 vtop[-3] = tmp;
4414 tmp = vtop[-2];
4415 vtop[-2] = vtop[-3];
4416 vtop[-3] = tmp;
4417 vswap();
4418 /* stack: H1 H2 L1 L2 */
4419 if (op == '*') {
4420 vpushv(vtop - 1);
4421 vpushv(vtop - 1);
4422 gen_op(TOK_UMULL);
4423 lexpand();
4424 /* stack: H1 H2 L1 L2 ML MH */
4425 for(i=0;i<4;i++)
4426 vrotb(6);
4427 /* stack: ML MH H1 H2 L1 L2 */
4428 tmp = vtop[0];
4429 vtop[0] = vtop[-2];
4430 vtop[-2] = tmp;
4431 /* stack: ML MH H1 L2 H2 L1 */
4432 gen_op('*');
4433 vrotb(3);
4434 vrotb(3);
4435 gen_op('*');
4436 /* stack: ML MH M1 M2 */
4437 gen_op('+');
4438 gen_op('+');
4439 } else if (op == '+' || op == '-') {
4440 /* XXX: add non carry method too (for MIPS or alpha) */
4441 if (op == '+')
4442 op1 = TOK_ADDC1;
4443 else
4444 op1 = TOK_SUBC1;
4445 gen_op(op1);
4446 /* stack: H1 H2 (L1 op L2) */
4447 vrotb(3);
4448 vrotb(3);
4449 gen_op(op1 + 1); /* TOK_xxxC2 */
4450 } else {
4451 gen_op(op);
4452 /* stack: H1 H2 (L1 op L2) */
4453 vrotb(3);
4454 vrotb(3);
4455 /* stack: (L1 op L2) H1 H2 */
4456 gen_op(op);
4457 /* stack: (L1 op L2) (H1 op H2) */
4459 /* stack: L H */
4460 lbuild(t);
4461 break;
4462 case TOK_SAR:
4463 case TOK_SHR:
4464 case TOK_SHL:
4465 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4466 t = vtop[-1].type.t;
4467 vswap();
4468 lexpand();
4469 vrotb(3);
4470 /* stack: L H shift */
4471 c = (int)vtop->c.i;
4472 /* constant: simpler */
4473 /* NOTE: all comments are for SHL. the other cases are
4474 done by swaping words */
4475 vpop();
4476 if (op != TOK_SHL)
4477 vswap();
4478 if (c >= 32) {
4479 /* stack: L H */
4480 vpop();
4481 if (c > 32) {
4482 vpushi(c - 32);
4483 gen_op(op);
4485 if (op != TOK_SAR) {
4486 vpushi(0);
4487 } else {
4488 gv_dup();
4489 vpushi(31);
4490 gen_op(TOK_SAR);
4492 vswap();
4493 } else {
4494 vswap();
4495 gv_dup();
4496 /* stack: H L L */
4497 vpushi(c);
4498 gen_op(op);
4499 vswap();
4500 vpushi(32 - c);
4501 if (op == TOK_SHL)
4502 gen_op(TOK_SHR);
4503 else
4504 gen_op(TOK_SHL);
4505 vrotb(3);
4506 /* stack: L L H */
4507 vpushi(c);
4508 if (op == TOK_SHL)
4509 gen_op(TOK_SHL);
4510 else
4511 gen_op(TOK_SHR);
4512 gen_op('|');
4514 if (op != TOK_SHL)
4515 vswap();
4516 lbuild(t);
4517 } else {
4518 /* XXX: should provide a faster fallback on x86 ? */
4519 switch(op) {
4520 case TOK_SAR:
4521 func = TOK___sardi3;
4522 goto gen_func;
4523 case TOK_SHR:
4524 func = TOK___shrdi3;
4525 goto gen_func;
4526 case TOK_SHL:
4527 func = TOK___shldi3;
4528 goto gen_func;
4531 break;
4532 default:
4533 /* compare operations */
4534 t = vtop->type.t;
4535 vswap();
4536 lexpand();
4537 vrotb(3);
4538 lexpand();
4539 /* stack: L1 H1 L2 H2 */
4540 tmp = vtop[-1];
4541 vtop[-1] = vtop[-2];
4542 vtop[-2] = tmp;
4543 /* stack: L1 L2 H1 H2 */
4544 /* compare high */
4545 op1 = op;
4546 /* when values are equal, we need to compare low words. since
4547 the jump is inverted, we invert the test too. */
4548 if (op1 == TOK_LT)
4549 op1 = TOK_LE;
4550 else if (op1 == TOK_GT)
4551 op1 = TOK_GE;
4552 else if (op1 == TOK_ULT)
4553 op1 = TOK_ULE;
4554 else if (op1 == TOK_UGT)
4555 op1 = TOK_UGE;
4556 a = 0;
4557 b = 0;
4558 gen_op(op1);
4559 if (op1 != TOK_NE) {
4560 a = gtst(1, 0);
4562 if (op != TOK_EQ) {
4563 /* generate non equal test */
4564 /* XXX: NOT PORTABLE yet */
4565 if (a == 0) {
4566 b = gtst(0, 0);
4567 } else {
4568 #ifdef TCC_TARGET_I386
4569 b = psym(0x850f, 0);
4570 #else
4571 error("not implemented");
4572 #endif
4575 /* compare low. Always unsigned */
4576 op1 = op;
4577 if (op1 == TOK_LT)
4578 op1 = TOK_ULT;
4579 else if (op1 == TOK_LE)
4580 op1 = TOK_ULE;
4581 else if (op1 == TOK_GT)
4582 op1 = TOK_UGT;
4583 else if (op1 == TOK_GE)
4584 op1 = TOK_UGE;
4585 gen_op(op1);
4586 a = gtst(1, a);
4587 gsym(b);
4588 vseti(VT_JMPI, a);
4589 break;
4593 /* handle integer constant optimizations and various machine
4594 independant opt */
4595 void gen_opic(int op)
4597 int fc, c1, c2, n;
4598 SValue *v1, *v2;
4600 v1 = vtop - 1;
4601 v2 = vtop;
4602 /* currently, we cannot do computations with forward symbols */
4603 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4604 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4605 if (c1 && c2) {
4606 fc = v2->c.i;
4607 switch(op) {
4608 case '+': v1->c.i += fc; break;
4609 case '-': v1->c.i -= fc; break;
4610 case '&': v1->c.i &= fc; break;
4611 case '^': v1->c.i ^= fc; break;
4612 case '|': v1->c.i |= fc; break;
4613 case '*': v1->c.i *= fc; break;
4615 case TOK_PDIV:
4616 case '/':
4617 case '%':
4618 case TOK_UDIV:
4619 case TOK_UMOD:
4620 /* if division by zero, generate explicit division */
4621 if (fc == 0) {
4622 if (const_wanted)
4623 error("division by zero in constant");
4624 goto general_case;
4626 switch(op) {
4627 default: v1->c.i /= fc; break;
4628 case '%': v1->c.i %= fc; break;
4629 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
4630 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
4632 break;
4633 case TOK_SHL: v1->c.i <<= fc; break;
4634 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
4635 case TOK_SAR: v1->c.i >>= fc; break;
4636 /* tests */
4637 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
4638 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
4639 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
4640 case TOK_NE: v1->c.i = v1->c.i != fc; break;
4641 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
4642 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
4643 case TOK_LT: v1->c.i = v1->c.i < fc; break;
4644 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
4645 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
4646 case TOK_GT: v1->c.i = v1->c.i > fc; break;
4647 /* logical */
4648 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
4649 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
4650 default:
4651 goto general_case;
4653 vtop--;
4654 } else {
4655 /* if commutative ops, put c2 as constant */
4656 if (c1 && (op == '+' || op == '&' || op == '^' ||
4657 op == '|' || op == '*')) {
4658 vswap();
4659 swap(&c1, &c2);
4661 fc = vtop->c.i;
4662 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
4663 op == TOK_PDIV) &&
4664 fc == 1) ||
4665 ((op == '+' || op == '-' || op == '|' || op == '^' ||
4666 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
4667 fc == 0) ||
4668 (op == '&' &&
4669 fc == -1))) {
4670 /* nothing to do */
4671 vtop--;
4672 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
4673 /* try to use shifts instead of muls or divs */
4674 if (fc > 0 && (fc & (fc - 1)) == 0) {
4675 n = -1;
4676 while (fc) {
4677 fc >>= 1;
4678 n++;
4680 vtop->c.i = n;
4681 if (op == '*')
4682 op = TOK_SHL;
4683 else if (op == TOK_PDIV)
4684 op = TOK_SAR;
4685 else
4686 op = TOK_SHR;
4688 goto general_case;
4689 } else if (c2 && (op == '+' || op == '-') &&
4690 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
4691 (VT_CONST | VT_SYM)) {
4692 /* symbol + constant case */
4693 if (op == '-')
4694 fc = -fc;
4695 vtop--;
4696 vtop->c.i += fc;
4697 } else {
4698 general_case:
4699 if (!nocode_wanted) {
4700 /* call low level op generator */
4701 gen_opi(op);
4702 } else {
4703 vtop--;
4709 /* generate a floating point operation with constant propagation */
4710 void gen_opif(int op)
4712 int c1, c2;
4713 SValue *v1, *v2;
4714 long double f1, f2;
4716 v1 = vtop - 1;
4717 v2 = vtop;
4718 /* currently, we cannot do computations with forward symbols */
4719 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4720 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4721 if (c1 && c2) {
4722 if (v1->type.t == VT_FLOAT) {
4723 f1 = v1->c.f;
4724 f2 = v2->c.f;
4725 } else if (v1->type.t == VT_DOUBLE) {
4726 f1 = v1->c.d;
4727 f2 = v2->c.d;
4728 } else {
4729 f1 = v1->c.ld;
4730 f2 = v2->c.ld;
4733 /* NOTE: we only do constant propagation if finite number (not
4734 NaN or infinity) (ANSI spec) */
4735 if (!ieee_finite(f1) || !ieee_finite(f2))
4736 goto general_case;
4738 switch(op) {
4739 case '+': f1 += f2; break;
4740 case '-': f1 -= f2; break;
4741 case '*': f1 *= f2; break;
4742 case '/':
4743 if (f2 == 0.0) {
4744 if (const_wanted)
4745 error("division by zero in constant");
4746 goto general_case;
4748 f1 /= f2;
4749 break;
4750 /* XXX: also handles tests ? */
4751 default:
4752 goto general_case;
4754 /* XXX: overflow test ? */
4755 if (v1->type.t == VT_FLOAT) {
4756 v1->c.f = f1;
4757 } else if (v1->type.t == VT_DOUBLE) {
4758 v1->c.d = f1;
4759 } else {
4760 v1->c.ld = f1;
4762 vtop--;
4763 } else {
4764 general_case:
4765 if (!nocode_wanted) {
4766 gen_opf(op);
4767 } else {
4768 vtop--;
4773 static int pointed_size(CType *type)
4775 int align;
4776 return type_size(pointed_type(type), &align);
4779 #if 0
4780 void check_pointer_types(SValue *p1, SValue *p2)
4782 char buf1[256], buf2[256];
4783 int t1, t2;
4784 t1 = p1->t;
4785 t2 = p2->t;
4786 if (!is_compatible_types(t1, t2)) {
4787 type_to_str(buf1, sizeof(buf1), t1, NULL);
4788 type_to_str(buf2, sizeof(buf2), t2, NULL);
4789 error("incompatible pointers '%s' and '%s'", buf1, buf2);
4792 #endif
4794 /* generic gen_op: handles types problems */
4795 void gen_op(int op)
4797 int u, t1, t2, bt1, bt2, t;
4798 CType type1;
4800 t1 = vtop[-1].type.t;
4801 t2 = vtop[0].type.t;
4802 bt1 = t1 & VT_BTYPE;
4803 bt2 = t2 & VT_BTYPE;
4805 if (bt1 == VT_PTR || bt2 == VT_PTR) {
4806 /* at least one operand is a pointer */
4807 /* relationnal op: must be both pointers */
4808 if (op >= TOK_ULT && op <= TOK_GT) {
4809 // check_pointer_types(vtop, vtop - 1);
4810 /* pointers are handled are unsigned */
4811 t = VT_INT | VT_UNSIGNED;
4812 goto std_op;
4814 /* if both pointers, then it must be the '-' op */
4815 if (bt1 == VT_PTR && bt2 == VT_PTR) {
4816 if (op != '-')
4817 error("cannot use pointers here");
4818 // check_pointer_types(vtop - 1, vtop);
4819 /* XXX: check that types are compatible */
4820 u = pointed_size(&vtop[-1].type);
4821 gen_opic(op);
4822 /* set to integer type */
4823 vtop->type.t = VT_INT;
4824 vpushi(u);
4825 gen_op(TOK_PDIV);
4826 } else {
4827 /* exactly one pointer : must be '+' or '-'. */
4828 if (op != '-' && op != '+')
4829 error("cannot use pointers here");
4830 /* Put pointer as first operand */
4831 if (bt2 == VT_PTR) {
4832 vswap();
4833 swap(&t1, &t2);
4835 type1 = vtop[-1].type;
4836 /* XXX: cast to int ? (long long case) */
4837 vpushi(pointed_size(&vtop[-1].type));
4838 gen_op('*');
4839 #ifdef CONFIG_TCC_BCHECK
4840 /* if evaluating constant expression, no code should be
4841 generated, so no bound check */
4842 if (do_bounds_check && !const_wanted) {
4843 /* if bounded pointers, we generate a special code to
4844 test bounds */
4845 if (op == '-') {
4846 vpushi(0);
4847 vswap();
4848 gen_op('-');
4850 gen_bounded_ptr_add();
4851 } else
4852 #endif
4854 gen_opic(op);
4856 /* put again type if gen_opic() swaped operands */
4857 vtop->type = type1;
4859 } else if (is_float(bt1) || is_float(bt2)) {
4860 /* compute bigger type and do implicit casts */
4861 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
4862 t = VT_LDOUBLE;
4863 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
4864 t = VT_DOUBLE;
4865 } else {
4866 t = VT_FLOAT;
4868 /* floats can only be used for a few operations */
4869 if (op != '+' && op != '-' && op != '*' && op != '/' &&
4870 (op < TOK_ULT || op > TOK_GT))
4871 error("invalid operands for binary operation");
4872 goto std_op;
4873 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
4874 /* cast to biggest op */
4875 t = VT_LLONG;
4876 /* convert to unsigned if it does not fit in a long long */
4877 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
4878 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
4879 t |= VT_UNSIGNED;
4880 goto std_op;
4881 } else {
4882 /* integer operations */
4883 t = VT_INT;
4884 /* convert to unsigned if it does not fit in an integer */
4885 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
4886 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
4887 t |= VT_UNSIGNED;
4888 std_op:
4889 /* XXX: currently, some unsigned operations are explicit, so
4890 we modify them here */
4891 if (t & VT_UNSIGNED) {
4892 if (op == TOK_SAR)
4893 op = TOK_SHR;
4894 else if (op == '/')
4895 op = TOK_UDIV;
4896 else if (op == '%')
4897 op = TOK_UMOD;
4898 else if (op == TOK_LT)
4899 op = TOK_ULT;
4900 else if (op == TOK_GT)
4901 op = TOK_UGT;
4902 else if (op == TOK_LE)
4903 op = TOK_ULE;
4904 else if (op == TOK_GE)
4905 op = TOK_UGE;
4907 vswap();
4908 type1.t = t;
4909 gen_cast(&type1);
4910 vswap();
4911 /* special case for shifts and long long: we keep the shift as
4912 an integer */
4913 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
4914 type1.t = VT_INT;
4915 gen_cast(&type1);
4916 if (is_float(t))
4917 gen_opif(op);
4918 else if ((t & VT_BTYPE) == VT_LLONG)
4919 gen_opl(op);
4920 else
4921 gen_opic(op);
4922 if (op >= TOK_ULT && op <= TOK_GT) {
4923 /* relationnal op: the result is an int */
4924 vtop->type.t = VT_INT;
4925 } else {
4926 vtop->type.t = t;
4931 /* generic itof for unsigned long long case */
4932 void gen_cvt_itof1(int t)
4934 GFuncContext gf;
4936 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
4937 (VT_LLONG | VT_UNSIGNED)) {
4939 gfunc_start(&gf, FUNC_CDECL);
4940 gfunc_param(&gf);
4941 if (t == VT_FLOAT)
4942 vpush_global_sym(&func_old_type, TOK___ulltof);
4943 else if (t == VT_DOUBLE)
4944 vpush_global_sym(&func_old_type, TOK___ulltod);
4945 else
4946 vpush_global_sym(&func_old_type, TOK___ulltold);
4947 gfunc_call(&gf);
4948 vpushi(0);
4949 vtop->r = REG_FRET;
4950 } else {
4951 gen_cvt_itof(t);
4955 /* generic ftoi for unsigned long long case */
4956 void gen_cvt_ftoi1(int t)
4958 GFuncContext gf;
4959 int st;
4961 if (t == (VT_LLONG | VT_UNSIGNED)) {
4962 /* not handled natively */
4963 gfunc_start(&gf, FUNC_CDECL);
4964 st = vtop->type.t & VT_BTYPE;
4965 gfunc_param(&gf);
4966 if (st == VT_FLOAT)
4967 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
4968 else if (st == VT_DOUBLE)
4969 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
4970 else
4971 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
4972 gfunc_call(&gf);
4973 vpushi(0);
4974 vtop->r = REG_IRET;
4975 vtop->r2 = REG_LRET;
4976 } else {
4977 gen_cvt_ftoi(t);
4981 /* force char or short cast */
4982 void force_charshort_cast(int t)
4984 int bits, dbt;
4985 dbt = t & VT_BTYPE;
4986 /* XXX: add optimization if lvalue : just change type and offset */
4987 if (dbt == VT_BYTE)
4988 bits = 8;
4989 else
4990 bits = 16;
4991 if (t & VT_UNSIGNED) {
4992 vpushi((1 << bits) - 1);
4993 gen_op('&');
4994 } else {
4995 bits = 32 - bits;
4996 vpushi(bits);
4997 gen_op(TOK_SHL);
4998 vpushi(bits);
4999 gen_op(TOK_SAR);
5003 /* cast 'vtop' to 'type' */
5004 static void gen_cast(CType *type)
5006 int sbt, dbt, sf, df, c;
5008 /* special delayed cast for char/short */
5009 /* XXX: in some cases (multiple cascaded casts), it may still
5010 be incorrect */
5011 if (vtop->r & VT_MUSTCAST) {
5012 vtop->r &= ~VT_MUSTCAST;
5013 force_charshort_cast(vtop->type.t);
5016 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5017 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5019 if (sbt != dbt && !nocode_wanted) {
5020 sf = is_float(sbt);
5021 df = is_float(dbt);
5022 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5023 if (sf && df) {
5024 /* convert from fp to fp */
5025 if (c) {
5026 /* constant case: we can do it now */
5027 /* XXX: in ISOC, cannot do it if error in convert */
5028 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5029 vtop->c.f = (float)vtop->c.d;
5030 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5031 vtop->c.f = (float)vtop->c.ld;
5032 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5033 vtop->c.d = (double)vtop->c.f;
5034 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5035 vtop->c.d = (double)vtop->c.ld;
5036 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5037 vtop->c.ld = (long double)vtop->c.f;
5038 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5039 vtop->c.ld = (long double)vtop->c.d;
5040 } else {
5041 /* non constant case: generate code */
5042 gen_cvt_ftof(dbt);
5044 } else if (df) {
5045 /* convert int to fp */
5046 if (c) {
5047 switch(sbt) {
5048 case VT_LLONG | VT_UNSIGNED:
5049 case VT_LLONG:
5050 /* XXX: add const cases for long long */
5051 goto do_itof;
5052 case VT_INT | VT_UNSIGNED:
5053 switch(dbt) {
5054 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5055 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5056 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5058 break;
5059 default:
5060 switch(dbt) {
5061 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5062 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5063 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5065 break;
5067 } else {
5068 do_itof:
5069 gen_cvt_itof1(dbt);
5071 } else if (sf) {
5072 /* convert fp to int */
5073 /* we handle char/short/etc... with generic code */
5074 if (dbt != (VT_INT | VT_UNSIGNED) &&
5075 dbt != (VT_LLONG | VT_UNSIGNED) &&
5076 dbt != VT_LLONG)
5077 dbt = VT_INT;
5078 if (c) {
5079 switch(dbt) {
5080 case VT_LLONG | VT_UNSIGNED:
5081 case VT_LLONG:
5082 /* XXX: add const cases for long long */
5083 goto do_ftoi;
5084 case VT_INT | VT_UNSIGNED:
5085 switch(sbt) {
5086 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5087 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5088 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5090 break;
5091 default:
5092 /* int case */
5093 switch(sbt) {
5094 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5095 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5096 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5098 break;
5100 } else {
5101 do_ftoi:
5102 gen_cvt_ftoi1(dbt);
5104 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5105 /* additionnal cast for char/short/bool... */
5106 vtop->type.t = dbt;
5107 gen_cast(type);
5109 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5110 if ((sbt & VT_BTYPE) != VT_LLONG) {
5111 /* scalar to long long */
5112 if (c) {
5113 if (sbt == (VT_INT | VT_UNSIGNED))
5114 vtop->c.ll = vtop->c.ui;
5115 else
5116 vtop->c.ll = vtop->c.i;
5117 } else {
5118 /* machine independant conversion */
5119 gv(RC_INT);
5120 /* generate high word */
5121 if (sbt == (VT_INT | VT_UNSIGNED)) {
5122 vpushi(0);
5123 gv(RC_INT);
5124 } else {
5125 gv_dup();
5126 vpushi(31);
5127 gen_op(TOK_SAR);
5129 /* patch second register */
5130 vtop[-1].r2 = vtop->r;
5131 vpop();
5134 } else if (dbt == VT_BOOL) {
5135 /* scalar to bool */
5136 vpushi(0);
5137 gen_op(TOK_NE);
5138 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5139 (dbt & VT_BTYPE) == VT_SHORT) {
5140 force_charshort_cast(dbt);
5141 } else if ((dbt & VT_BTYPE) == VT_INT) {
5142 /* scalar to int */
5143 if (sbt == VT_LLONG) {
5144 /* from long long: just take low order word */
5145 lexpand();
5146 vpop();
5148 /* if lvalue and single word type, nothing to do because
5149 the lvalue already contains the real type size (see
5150 VT_LVAL_xxx constants) */
5153 vtop->type = *type;
5156 /* return type size. Put alignment at 'a' */
5157 int type_size(CType *type, int *a)
5159 Sym *s;
5160 int bt;
5162 bt = type->t & VT_BTYPE;
5163 if (bt == VT_STRUCT) {
5164 /* struct/union */
5165 s = type->ref;
5166 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
5167 return s->c;
5168 } else if (bt == VT_PTR) {
5169 if (type->t & VT_ARRAY) {
5170 s = type->ref;
5171 return type_size(&s->type, a) * s->c;
5172 } else {
5173 *a = PTR_SIZE;
5174 return PTR_SIZE;
5176 } else if (bt == VT_LDOUBLE) {
5177 *a = LDOUBLE_ALIGN;
5178 return LDOUBLE_SIZE;
5179 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5180 *a = 8;
5181 return 8;
5182 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5183 *a = 4;
5184 return 4;
5185 } else if (bt == VT_SHORT) {
5186 *a = 2;
5187 return 2;
5188 } else {
5189 /* char, void, function, _Bool */
5190 *a = 1;
5191 return 1;
5195 /* return the pointed type of t */
5196 static inline CType *pointed_type(CType *type)
5198 return &type->ref->type;
5201 /* modify type so that its it is a pointer to type. */
5202 static void mk_pointer(CType *type)
5204 Sym *s;
5205 s = sym_push(SYM_FIELD, type, 0, -1);
5206 type->t = VT_PTR | (type->t & ~VT_TYPE);
5207 type->ref = s;
5210 static int is_compatible_types(CType *type1, CType *type2)
5212 Sym *s1, *s2;
5213 int bt1, bt2, t1, t2;
5215 t1 = type1->t & VT_TYPE;
5216 t2 = type2->t & VT_TYPE;
5217 bt1 = t1 & VT_BTYPE;
5218 bt2 = t2 & VT_BTYPE;
5219 if (bt1 == VT_PTR) {
5220 type1 = pointed_type(type1);
5221 /* if function, then convert implicitely to function pointer */
5222 if (bt2 != VT_FUNC) {
5223 if (bt2 != VT_PTR)
5224 return 0;
5225 type2 = pointed_type(type2);
5227 /* void matches everything */
5228 /* XXX: not fully compliant */
5229 if ((type1->t & VT_TYPE) == VT_VOID || (type2->t & VT_TYPE) == VT_VOID)
5230 return 1;
5231 return is_compatible_types(type1, type2);
5232 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
5233 return (t2 == t1);
5234 } else if (bt1 == VT_FUNC) {
5235 if (bt2 != VT_FUNC)
5236 return 0;
5237 s1 = type1->ref;
5238 s2 = type2->ref;
5239 if (!is_compatible_types(&s1->type, &s2->type))
5240 return 0;
5241 /* XXX: not complete */
5242 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5243 return 1;
5244 if (s1->c != s2->c)
5245 return 0;
5246 while (s1 != NULL) {
5247 if (s2 == NULL)
5248 return 0;
5249 if (!is_compatible_types(&s1->type, &s2->type))
5250 return 0;
5251 s1 = s1->next;
5252 s2 = s2->next;
5254 if (s2)
5255 return 0;
5256 return 1;
5257 } else {
5258 /* XXX: not complete */
5259 return 1;
5263 /* print a type. If 'varstr' is not NULL, then the variable is also
5264 printed in the type */
5265 /* XXX: union */
5266 /* XXX: add array and function pointers */
5267 void type_to_str(char *buf, int buf_size,
5268 CType *type, const char *varstr)
5270 int bt, v, t;
5271 Sym *s, *sa;
5272 char buf1[256];
5273 const char *tstr;
5275 t = type->t & VT_TYPE;
5276 bt = t & VT_BTYPE;
5277 buf[0] = '\0';
5278 if (t & VT_UNSIGNED)
5279 pstrcat(buf, buf_size, "unsigned ");
5280 switch(bt) {
5281 case VT_VOID:
5282 tstr = "void";
5283 goto add_tstr;
5284 case VT_BOOL:
5285 tstr = "_Bool";
5286 goto add_tstr;
5287 case VT_BYTE:
5288 tstr = "char";
5289 goto add_tstr;
5290 case VT_SHORT:
5291 tstr = "short";
5292 goto add_tstr;
5293 case VT_INT:
5294 tstr = "int";
5295 goto add_tstr;
5296 case VT_LONG:
5297 tstr = "long";
5298 goto add_tstr;
5299 case VT_LLONG:
5300 tstr = "long long";
5301 goto add_tstr;
5302 case VT_FLOAT:
5303 tstr = "float";
5304 goto add_tstr;
5305 case VT_DOUBLE:
5306 tstr = "double";
5307 goto add_tstr;
5308 case VT_LDOUBLE:
5309 tstr = "long double";
5310 add_tstr:
5311 pstrcat(buf, buf_size, tstr);
5312 break;
5313 case VT_ENUM:
5314 case VT_STRUCT:
5315 if (bt == VT_STRUCT)
5316 tstr = "struct ";
5317 else
5318 tstr = "enum ";
5319 pstrcat(buf, buf_size, tstr);
5320 v = type->ref->v;
5321 if (v >= SYM_FIRST_ANOM)
5322 pstrcat(buf, buf_size, "<anonymous>");
5323 else
5324 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5325 break;
5326 case VT_FUNC:
5327 s = type->ref;
5328 type_to_str(buf, buf_size, &s->type, varstr);
5329 pstrcat(buf, buf_size, "(");
5330 sa = s->next;
5331 while (sa != NULL) {
5332 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5333 pstrcat(buf, buf_size, buf1);
5334 sa = sa->next;
5335 if (sa)
5336 pstrcat(buf, buf_size, ", ");
5338 pstrcat(buf, buf_size, ")");
5339 goto no_var;
5340 case VT_PTR:
5341 s = type->ref;
5342 pstrcpy(buf1, sizeof(buf1), "*");
5343 if (varstr)
5344 pstrcat(buf1, sizeof(buf1), varstr);
5345 type_to_str(buf, buf_size, &s->type, buf1);
5346 goto no_var;
5348 if (varstr) {
5349 pstrcat(buf, buf_size, " ");
5350 pstrcat(buf, buf_size, varstr);
5352 no_var: ;
5355 /* verify type compatibility to store vtop in 'dt' type, and generate
5356 casts if needed. */
5357 void gen_assign_cast(CType *dt)
5359 CType *st;
5360 char buf1[256], buf2[256];
5362 st = &vtop->type; /* source type */
5363 if ((dt->t & VT_BTYPE) == VT_PTR) {
5364 /* special cases for pointers */
5365 /* a function is implicitely a function pointer */
5366 if ((st->t & VT_BTYPE) == VT_FUNC) {
5367 if (!is_compatible_types(pointed_type(dt), st))
5368 goto error;
5369 else
5370 goto type_ok;
5372 /* '0' can also be a pointer */
5373 if ((st->t & VT_BTYPE) == VT_INT &&
5374 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) &&
5375 vtop->c.i == 0)
5376 goto type_ok;
5378 if (!is_compatible_types(dt, st)) {
5379 error:
5380 type_to_str(buf1, sizeof(buf1), st, NULL);
5381 type_to_str(buf2, sizeof(buf2), dt, NULL);
5382 error("cannot cast '%s' to '%s'", buf1, buf2);
5384 type_ok:
5385 gen_cast(dt);
5388 /* store vtop in lvalue pushed on stack */
5389 void vstore(void)
5391 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5392 GFuncContext gf;
5394 ft = vtop[-1].type.t;
5395 sbt = vtop->type.t & VT_BTYPE;
5396 dbt = ft & VT_BTYPE;
5397 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5398 (sbt == VT_INT && dbt == VT_SHORT)) {
5399 /* optimize char/short casts */
5400 delayed_cast = VT_MUSTCAST;
5401 vtop->type.t = ft & VT_TYPE;
5402 } else {
5403 delayed_cast = 0;
5404 gen_assign_cast(&vtop[-1].type);
5407 if (sbt == VT_STRUCT) {
5408 /* if structure, only generate pointer */
5409 /* structure assignment : generate memcpy */
5410 /* XXX: optimize if small size */
5411 if (!nocode_wanted) {
5412 vdup();
5413 gfunc_start(&gf, FUNC_CDECL);
5414 /* type size */
5415 size = type_size(&vtop->type, &align);
5416 vpushi(size);
5417 gfunc_param(&gf);
5418 /* source */
5419 vtop->type.t = VT_INT;
5420 gaddrof();
5421 gfunc_param(&gf);
5422 /* destination */
5423 vswap();
5424 vtop->type.t = VT_INT;
5425 gaddrof();
5426 gfunc_param(&gf);
5428 save_regs(0);
5429 vpush_global_sym(&func_old_type, TOK_memcpy);
5430 gfunc_call(&gf);
5431 } else {
5432 vswap();
5433 vpop();
5435 /* leave source on stack */
5436 } else if (ft & VT_BITFIELD) {
5437 /* bitfield store handling */
5438 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5439 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5440 /* remove bit field info to avoid loops */
5441 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5443 /* duplicate destination */
5444 vdup();
5445 vtop[-1] = vtop[-2];
5447 /* mask and shift source */
5448 vpushi((1 << bit_size) - 1);
5449 gen_op('&');
5450 vpushi(bit_pos);
5451 gen_op(TOK_SHL);
5452 /* load destination, mask and or with source */
5453 vswap();
5454 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5455 gen_op('&');
5456 gen_op('|');
5457 /* store result */
5458 vstore();
5459 } else {
5460 #ifdef CONFIG_TCC_BCHECK
5461 /* bound check case */
5462 if (vtop[-1].r & VT_MUSTBOUND) {
5463 vswap();
5464 gbound();
5465 vswap();
5467 #endif
5468 if (!nocode_wanted) {
5469 rc = RC_INT;
5470 if (is_float(ft))
5471 rc = RC_FLOAT;
5472 r = gv(rc); /* generate value */
5473 /* if lvalue was saved on stack, must read it */
5474 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5475 SValue sv;
5476 t = get_reg(RC_INT);
5477 sv.type.t = VT_INT;
5478 sv.r = VT_LOCAL | VT_LVAL;
5479 sv.c.ul = vtop[-1].c.ul;
5480 load(t, &sv);
5481 vtop[-1].r = t | VT_LVAL;
5483 store(r, vtop - 1);
5484 /* two word case handling : store second register at word + 4 */
5485 if ((ft & VT_BTYPE) == VT_LLONG) {
5486 vswap();
5487 /* convert to int to increment easily */
5488 vtop->type.t = VT_INT;
5489 gaddrof();
5490 vpushi(4);
5491 gen_op('+');
5492 vtop->r |= VT_LVAL;
5493 vswap();
5494 /* XXX: it works because r2 is spilled last ! */
5495 store(vtop->r2, vtop - 1);
5498 vswap();
5499 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5500 vtop->r |= delayed_cast;
5504 /* post defines POST/PRE add. c is the token ++ or -- */
5505 void inc(int post, int c)
5507 test_lvalue();
5508 vdup(); /* save lvalue */
5509 if (post) {
5510 gv_dup(); /* duplicate value */
5511 vrotb(3);
5512 vrotb(3);
5514 /* add constant */
5515 vpushi(c - TOK_MID);
5516 gen_op('+');
5517 vstore(); /* store value */
5518 if (post)
5519 vpop(); /* if post op, return saved value */
5522 /* Parse GNUC __attribute__ extension. Currently, the following
5523 extensions are recognized:
5524 - aligned(n) : set data/function alignment.
5525 - section(x) : generate data/code in this section.
5526 - unused : currently ignored, but may be used someday.
5528 void parse_attribute(AttributeDef *ad)
5530 int t, n;
5532 next();
5533 skip('(');
5534 skip('(');
5535 while (tok != ')') {
5536 if (tok < TOK_IDENT)
5537 expect("attribute name");
5538 t = tok;
5539 next();
5540 switch(t) {
5541 case TOK_SECTION:
5542 case TOK___SECTION__:
5543 skip('(');
5544 if (tok != TOK_STR)
5545 expect("section name");
5546 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
5547 next();
5548 skip(')');
5549 break;
5550 case TOK_ALIGNED:
5551 case TOK___ALIGNED__:
5552 skip('(');
5553 n = expr_const();
5554 if (n <= 0 || (n & (n - 1)) != 0)
5555 error("alignment must be a positive power of two");
5556 ad->aligned = n;
5557 skip(')');
5558 break;
5559 case TOK_UNUSED:
5560 case TOK___UNUSED__:
5561 /* currently, no need to handle it because tcc does not
5562 track unused objects */
5563 break;
5564 case TOK_NORETURN:
5565 case TOK___NORETURN__:
5566 /* currently, no need to handle it because tcc does not
5567 track unused objects */
5568 break;
5569 case TOK_CDECL:
5570 case TOK___CDECL:
5571 case TOK___CDECL__:
5572 ad->func_call = FUNC_CDECL;
5573 break;
5574 case TOK_STDCALL:
5575 case TOK___STDCALL:
5576 case TOK___STDCALL__:
5577 ad->func_call = FUNC_STDCALL;
5578 break;
5579 default:
5580 warning("'%s' attribute ignored", get_tok_str(t, NULL));
5581 /* skip parameters */
5582 /* XXX: skip parenthesis too */
5583 if (tok == '(') {
5584 next();
5585 while (tok != ')' && tok != -1)
5586 next();
5587 next();
5589 break;
5591 if (tok != ',')
5592 break;
5593 next();
5595 skip(')');
5596 skip(')');
5599 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
5600 static void struct_decl(CType *type, int u)
5602 int a, v, size, align, maxalign, c, offset;
5603 int bit_size, bit_pos, bsize, bt, lbit_pos;
5604 Sym *s, *ss, **ps;
5605 AttributeDef ad;
5606 CType type1, btype;
5608 a = tok; /* save decl type */
5609 next();
5610 if (tok != '{') {
5611 v = tok;
5612 next();
5613 /* struct already defined ? return it */
5614 /* XXX: check consistency */
5615 s = struct_find(v);
5616 if (s) {
5617 if (s->type.t != a)
5618 error("invalid type");
5619 goto do_decl;
5621 } else {
5622 v = anon_sym++;
5624 type1.t = a;
5625 s = sym_push(v | SYM_STRUCT, &type1, 0, 0);
5626 /* put struct/union/enum name in type */
5627 do_decl:
5628 type->t = u;
5629 type->ref = s;
5631 if (tok == '{') {
5632 next();
5633 if (s->c)
5634 error("struct/union/enum already defined");
5635 /* cannot be empty */
5636 c = 0;
5637 maxalign = 0;
5638 ps = &s->next;
5639 bit_pos = 0;
5640 offset = 0;
5641 while (1) {
5642 if (a == TOK_ENUM) {
5643 v = tok;
5644 next();
5645 if (tok == '=') {
5646 next();
5647 c = expr_const();
5649 /* enum symbols have static storage */
5650 ss = sym_push(v, &int_type, VT_CONST, c);
5651 ss->type.t |= VT_STATIC;
5652 if (tok == ',')
5653 next();
5654 c++;
5655 } else {
5656 parse_btype(&btype, &ad);
5657 while (1) {
5658 bit_size = -1;
5659 v = 0;
5660 type1 = btype;
5661 if (tok != ':') {
5662 type_decl(&type1, &ad, &v, TYPE_DIRECT);
5663 if ((type1.t & VT_BTYPE) == VT_FUNC ||
5664 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
5665 error("invalid type for '%s'",
5666 get_tok_str(v, NULL));
5668 if (tok == ':') {
5669 next();
5670 bit_size = expr_const();
5671 /* XXX: handle v = 0 case for messages */
5672 if (bit_size < 0)
5673 error("negative width in bit-field '%s'",
5674 get_tok_str(v, NULL));
5675 if (v && bit_size == 0)
5676 error("zero width for bit-field '%s'",
5677 get_tok_str(v, NULL));
5679 size = type_size(&type1, &align);
5680 lbit_pos = 0;
5681 if (bit_size >= 0) {
5682 bt = type1.t & VT_BTYPE;
5683 if (bt != VT_INT &&
5684 bt != VT_BYTE &&
5685 bt != VT_SHORT)
5686 error("bitfields must have scalar type");
5687 bsize = size * 8;
5688 if (bit_size > bsize) {
5689 error("width of '%s' exceeds its type",
5690 get_tok_str(v, NULL));
5691 } else if (bit_size == bsize) {
5692 /* no need for bit fields */
5693 bit_pos = 0;
5694 } else if (bit_size == 0) {
5695 /* XXX: what to do if only padding in a
5696 structure ? */
5697 /* zero size: means to pad */
5698 if (bit_pos > 0)
5699 bit_pos = bsize;
5700 } else {
5701 /* we do not have enough room ? */
5702 if ((bit_pos + bit_size) > bsize)
5703 bit_pos = 0;
5704 lbit_pos = bit_pos;
5705 /* XXX: handle LSB first */
5706 type1.t |= VT_BITFIELD |
5707 (bit_pos << VT_STRUCT_SHIFT) |
5708 (bit_size << (VT_STRUCT_SHIFT + 6));
5709 bit_pos += bit_size;
5711 } else {
5712 bit_pos = 0;
5714 if (v) {
5715 /* add new memory data only if starting
5716 bit field */
5717 if (lbit_pos == 0) {
5718 if (a == TOK_STRUCT) {
5719 c = (c + align - 1) & -align;
5720 offset = c;
5721 c += size;
5722 } else {
5723 offset = 0;
5724 if (size > c)
5725 c = size;
5727 if (align > maxalign)
5728 maxalign = align;
5730 #if 0
5731 printf("add field %s offset=%d",
5732 get_tok_str(v, NULL), offset);
5733 if (type1.t & VT_BITFIELD) {
5734 printf(" pos=%d size=%d",
5735 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
5736 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
5738 printf("\n");
5739 #endif
5740 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
5741 *ps = ss;
5742 ps = &ss->next;
5744 if (tok == ';' || tok == -1)
5745 break;
5746 skip(',');
5748 skip(';');
5750 if (tok == '}')
5751 break;
5753 skip('}');
5754 /* size for struct/union, dummy for enum */
5755 s->c = (c + maxalign - 1) & -maxalign;
5759 /* return 0 if no type declaration. otherwise, return the basic type
5760 and skip it.
5762 static int parse_btype(CType *type, AttributeDef *ad)
5764 int t, u, type_found;
5765 Sym *s;
5766 CType type1;
5768 memset(ad, 0, sizeof(AttributeDef));
5769 type_found = 0;
5770 t = 0;
5771 while(1) {
5772 switch(tok) {
5773 /* basic types */
5774 case TOK_CHAR:
5775 u = VT_BYTE;
5776 basic_type:
5777 next();
5778 basic_type1:
5779 if ((t & VT_BTYPE) != 0)
5780 error("too many basic types");
5781 t |= u;
5782 break;
5783 case TOK_VOID:
5784 u = VT_VOID;
5785 goto basic_type;
5786 case TOK_SHORT:
5787 u = VT_SHORT;
5788 goto basic_type;
5789 case TOK_INT:
5790 next();
5791 break;
5792 case TOK_LONG:
5793 next();
5794 if ((t & VT_BTYPE) == VT_DOUBLE) {
5795 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
5796 } else if ((t & VT_BTYPE) == VT_LONG) {
5797 t = (t & ~VT_BTYPE) | VT_LLONG;
5798 } else {
5799 u = VT_LONG;
5800 goto basic_type1;
5802 break;
5803 case TOK_BOOL:
5804 u = VT_BOOL;
5805 goto basic_type;
5806 case TOK_FLOAT:
5807 u = VT_FLOAT;
5808 goto basic_type;
5809 case TOK_DOUBLE:
5810 next();
5811 if ((t & VT_BTYPE) == VT_LONG) {
5812 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
5813 } else {
5814 u = VT_DOUBLE;
5815 goto basic_type1;
5817 break;
5818 case TOK_ENUM:
5819 struct_decl(&type1, VT_ENUM);
5820 basic_type2:
5821 u = type1.t;
5822 type->ref = type1.ref;
5823 goto basic_type1;
5824 case TOK_STRUCT:
5825 case TOK_UNION:
5826 struct_decl(&type1, VT_STRUCT);
5827 goto basic_type2;
5829 /* type modifiers */
5830 case TOK_CONST:
5831 case TOK_VOLATILE:
5832 case TOK_REGISTER:
5833 case TOK_SIGNED:
5834 case TOK___SIGNED__:
5835 case TOK_AUTO:
5836 case TOK_INLINE:
5837 case TOK___INLINE__:
5838 case TOK_RESTRICT:
5839 next();
5840 break;
5841 case TOK_UNSIGNED:
5842 t |= VT_UNSIGNED;
5843 next();
5844 break;
5846 /* storage */
5847 case TOK_EXTERN:
5848 t |= VT_EXTERN;
5849 next();
5850 break;
5851 case TOK_STATIC:
5852 t |= VT_STATIC;
5853 next();
5854 break;
5855 case TOK_TYPEDEF:
5856 t |= VT_TYPEDEF;
5857 next();
5858 break;
5859 /* GNUC attribute */
5860 case TOK___ATTRIBUTE__:
5861 parse_attribute(ad);
5862 break;
5863 /* GNUC typeof */
5864 case TOK_TYPEOF:
5865 next();
5866 parse_expr_type(&type1);
5867 goto basic_type2;
5868 default:
5869 s = sym_find(tok);
5870 if (!s || !(s->type.t & VT_TYPEDEF))
5871 goto the_end;
5872 t |= (s->type.t & ~VT_TYPEDEF);
5873 type->ref = s->type.ref;
5874 next();
5875 break;
5877 type_found = 1;
5879 the_end:
5880 /* long is never used as type */
5881 if ((t & VT_BTYPE) == VT_LONG)
5882 t = (t & ~VT_BTYPE) | VT_INT;
5883 type->t = t;
5884 return type_found;
5887 static void post_type(CType *type, AttributeDef *ad)
5889 int n, l, t1;
5890 Sym **plast, *s, *first;
5891 AttributeDef ad1;
5892 CType pt;
5894 if (tok == '(') {
5895 /* function declaration */
5896 next();
5897 l = 0;
5898 first = NULL;
5899 plast = &first;
5900 while (tok != ')') {
5901 /* read param name and compute offset */
5902 if (l != FUNC_OLD) {
5903 if (!parse_btype(&pt, &ad1)) {
5904 if (l) {
5905 error("invalid type");
5906 } else {
5907 l = FUNC_OLD;
5908 goto old_proto;
5911 l = FUNC_NEW;
5912 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
5913 break;
5914 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
5915 if ((pt.t & VT_BTYPE) == VT_VOID)
5916 error("parameter declared as void");
5917 } else {
5918 old_proto:
5919 n = tok;
5920 pt.t = VT_INT;
5921 next();
5923 /* array must be transformed to pointer according to ANSI C */
5924 pt.t &= ~VT_ARRAY;
5925 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
5926 *plast = s;
5927 plast = &s->next;
5928 if (tok == ',') {
5929 next();
5930 if (l == FUNC_NEW && tok == TOK_DOTS) {
5931 l = FUNC_ELLIPSIS;
5932 next();
5933 break;
5937 /* if no parameters, then old type prototype */
5938 if (l == 0)
5939 l = FUNC_OLD;
5940 skip(')');
5941 t1 = type->t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5942 type->t &= ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5943 post_type(type, ad);
5944 /* we push a anonymous symbol which will contain the function prototype */
5945 s = sym_push(SYM_FIELD, type, ad->func_call, l);
5946 s->next = first;
5947 type->t = t1 | VT_FUNC;
5948 type->ref = s;
5949 } else if (tok == '[') {
5950 /* array definition */
5951 next();
5952 n = -1;
5953 if (tok != ']') {
5954 n = expr_const();
5955 if (n < 0)
5956 error("invalid array size");
5958 skip(']');
5959 /* parse next post type */
5960 t1 = type->t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5961 type->t &= ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5962 post_type(type, ad);
5964 /* we push a anonymous symbol which will contain the array
5965 element type */
5966 s = sym_push(SYM_FIELD, type, 0, n);
5967 type->t = t1 | VT_ARRAY | VT_PTR;
5968 type->ref = s;
5972 /* Parse a type declaration (except basic type), and return the type
5973 in 'type'. 'td' is a bitmask indicating which kind of type decl is
5974 expected. 'type' should contain the basic type. 'ad' is the
5975 attribute definition of the basic type. It can be modified by
5976 type_decl().
5978 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
5980 Sym *s;
5981 CType type1, *type2;
5983 while (tok == '*') {
5984 next();
5985 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
5986 next();
5987 mk_pointer(type);
5990 /* recursive type */
5991 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
5992 type1.t = 0; /* XXX: same as int */
5993 if (tok == '(') {
5994 next();
5995 /* XXX: this is not correct to modify 'ad' at this point, but
5996 the syntax is not clear */
5997 if (tok == TOK___ATTRIBUTE__)
5998 parse_attribute(ad);
5999 type_decl(&type1, ad, v, td);
6000 skip(')');
6001 } else {
6002 /* type identifier */
6003 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6004 *v = tok;
6005 next();
6006 } else {
6007 if (!(td & TYPE_ABSTRACT))
6008 expect("identifier");
6009 *v = 0;
6012 post_type(type, ad);
6013 if (tok == TOK___ATTRIBUTE__)
6014 parse_attribute(ad);
6015 if (!type1.t)
6016 return;
6017 /* append type at the end of type1 */
6018 type2 = &type1;
6019 for(;;) {
6020 s = type2->ref;
6021 type2 = &s->type;
6022 if (!type2->t) {
6023 *type2 = *type;
6024 break;
6027 *type = type1;
6030 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6031 static int lvalue_type(int t)
6033 int bt, r;
6034 r = VT_LVAL;
6035 bt = t & VT_BTYPE;
6036 if (bt == VT_BYTE)
6037 r |= VT_LVAL_BYTE;
6038 else if (bt == VT_SHORT)
6039 r |= VT_LVAL_SHORT;
6040 else
6041 return r;
6042 if (t & VT_UNSIGNED)
6043 r |= VT_LVAL_UNSIGNED;
6044 return r;
6047 /* indirection with full error checking and bound check */
6048 static void indir(void)
6050 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6051 expect("pointer");
6052 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6053 gv(RC_INT);
6054 vtop->type = *pointed_type(&vtop->type);
6055 /* an array is never an lvalue */
6056 if (!(vtop->type.t & VT_ARRAY)) {
6057 vtop->r |= lvalue_type(vtop->type.t);
6058 /* if bound checking, the referenced pointer must be checked */
6059 if (do_bounds_check)
6060 vtop->r |= VT_MUSTBOUND;
6064 /* pass a parameter to a function and do type checking and casting */
6065 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
6067 int func_type;
6068 CType type;
6070 func_type = func->c;
6071 if (func_type == FUNC_OLD ||
6072 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6073 /* default casting : only need to convert float to double */
6074 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6075 type.t = VT_DOUBLE;
6076 gen_cast(&type);
6078 } else if (arg == NULL) {
6079 error("too many arguments to function");
6080 } else {
6081 gen_assign_cast(&arg->type);
6083 if (!nocode_wanted) {
6084 gfunc_param(gf);
6085 } else {
6086 vpop();
6090 /* parse an expression of the form '(type)' or '(expr)' and return its
6091 type */
6092 static void parse_expr_type(CType *type)
6094 int n;
6095 AttributeDef ad;
6097 skip('(');
6098 if (parse_btype(type, &ad)) {
6099 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6100 } else {
6101 expr_type(type);
6103 skip(')');
6106 static void vpush_tokc(int t)
6108 CType type;
6109 type.t = t;
6110 vsetc(&type, VT_CONST, &tokc);
6113 static void unary(void)
6115 int n, t, align, size, r;
6116 CType type;
6117 Sym *s;
6118 GFuncContext gf;
6119 AttributeDef ad;
6121 /* XXX: GCC 2.95.3 does not generate a table although it should be
6122 better here */
6123 switch(tok) {
6124 case TOK_CINT:
6125 case TOK_CCHAR:
6126 case TOK_LCHAR:
6127 vpushi(tokc.i);
6128 next();
6129 break;
6130 case TOK_CUINT:
6131 vpush_tokc(VT_INT | VT_UNSIGNED);
6132 next();
6133 break;
6134 case TOK_CLLONG:
6135 vpush_tokc(VT_LLONG);
6136 next();
6137 break;
6138 case TOK_CULLONG:
6139 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6140 next();
6141 break;
6142 case TOK_CFLOAT:
6143 vpush_tokc(VT_FLOAT);
6144 next();
6145 break;
6146 case TOK_CDOUBLE:
6147 vpush_tokc(VT_DOUBLE);
6148 next();
6149 break;
6150 case TOK_CLDOUBLE:
6151 vpush_tokc(VT_LDOUBLE);
6152 next();
6153 break;
6154 case TOK___FUNCTION__:
6155 if (!gnu_ext)
6156 goto tok_identifier;
6157 /* fall thru */
6158 case TOK___FUNC__:
6160 void *ptr;
6161 int len;
6162 /* special function name identifier */
6163 len = strlen(funcname) + 1;
6164 /* generate char[len] type */
6165 type.t = VT_BYTE;
6166 mk_pointer(&type);
6167 type.t |= VT_ARRAY;
6168 type.ref->c = len;
6169 vpush_ref(&type, data_section, data_section->data_offset, len);
6170 ptr = section_ptr_add(data_section, len);
6171 memcpy(ptr, funcname, len);
6172 next();
6174 break;
6175 case TOK_LSTR:
6176 t = VT_INT;
6177 goto str_init;
6178 case TOK_STR:
6179 /* string parsing */
6180 t = VT_BYTE;
6181 str_init:
6182 type.t = t;
6183 mk_pointer(&type);
6184 type.t |= VT_ARRAY;
6185 memset(&ad, 0, sizeof(AttributeDef));
6186 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6187 break;
6188 case '(':
6189 next();
6190 /* cast ? */
6191 if (parse_btype(&type, &ad)) {
6192 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6193 skip(')');
6194 /* check ISOC99 compound literal */
6195 if (tok == '{') {
6196 /* data is allocated locally by default */
6197 if (global_expr)
6198 r = VT_CONST;
6199 else
6200 r = VT_LOCAL;
6201 /* all except arrays are lvalues */
6202 if (!(type.t & VT_ARRAY))
6203 r |= lvalue_type(type.t);
6204 memset(&ad, 0, sizeof(AttributeDef));
6205 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6206 } else {
6207 unary();
6208 gen_cast(&type);
6210 } else {
6211 gexpr();
6212 skip(')');
6214 break;
6215 case '*':
6216 next();
6217 unary();
6218 indir();
6219 break;
6220 case '&':
6221 next();
6222 unary();
6223 /* functions names must be treated as function pointers,
6224 except for unary '&' and sizeof. Since we consider that
6225 functions are not lvalues, we only have to handle it
6226 there and in function calls. */
6227 /* arrays can also be used although they are not lvalues */
6228 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6229 !(vtop->type.t & VT_ARRAY))
6230 test_lvalue();
6231 mk_pointer(&vtop->type);
6232 gaddrof();
6233 break;
6234 case '!':
6235 next();
6236 unary();
6237 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6238 vtop->c.i = !vtop->c.i;
6239 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6240 vtop->c.i = vtop->c.i ^ 1;
6241 else
6242 vseti(VT_JMP, gtst(1, 0));
6243 break;
6244 case '~':
6245 next();
6246 unary();
6247 vpushi(-1);
6248 gen_op('^');
6249 break;
6250 case '+':
6251 next();
6252 /* in order to force cast, we add zero */
6253 unary();
6254 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6255 error("pointer not accepted for unary plus");
6256 vpushi(0);
6257 gen_op('+');
6258 break;
6259 case TOK_SIZEOF:
6260 case TOK_ALIGNOF:
6261 t = tok;
6262 next();
6263 if (tok == '(') {
6264 parse_expr_type(&type);
6265 } else {
6266 unary_type(&type);
6268 size = type_size(&type, &align);
6269 if (t == TOK_SIZEOF)
6270 vpushi(size);
6271 else
6272 vpushi(align);
6273 break;
6275 case TOK_INC:
6276 case TOK_DEC:
6277 t = tok;
6278 next();
6279 unary();
6280 inc(0, t);
6281 break;
6282 case '-':
6283 next();
6284 vpushi(0);
6285 unary();
6286 gen_op('-');
6287 break;
6288 case TOK_LAND:
6289 if (!gnu_ext)
6290 goto tok_identifier;
6291 next();
6292 /* allow to take the address of a label */
6293 if (tok < TOK_UIDENT)
6294 expect("label identifier");
6295 s = label_find(tok);
6296 if (!s) {
6297 s = label_push(tok, LABEL_FORWARD);
6299 if (!s->type.t) {
6300 s->type.t = VT_VOID;
6301 mk_pointer(&s->type);
6302 s->type.t |= VT_STATIC;
6304 vset(&s->type, VT_CONST | VT_SYM, 0);
6305 vtop->sym = s;
6306 next();
6307 break;
6308 default:
6309 tok_identifier:
6310 t = tok;
6311 next();
6312 if (t < TOK_UIDENT)
6313 expect("identifier");
6314 s = sym_find(t);
6315 if (!s) {
6316 if (tok != '(')
6317 error("'%s' undeclared", get_tok_str(t, NULL));
6318 /* for simple function calls, we tolerate undeclared
6319 external reference to int() function */
6320 s = external_global_sym(t, &func_old_type, 0);
6322 vset(&s->type, s->r, s->c);
6323 /* if forward reference, we must point to s */
6324 if (vtop->r & VT_SYM) {
6325 vtop->sym = s;
6326 vtop->c.ul = 0;
6328 break;
6331 /* post operations */
6332 while (1) {
6333 if (tok == TOK_INC || tok == TOK_DEC) {
6334 inc(1, tok);
6335 next();
6336 } else if (tok == '.' || tok == TOK_ARROW) {
6337 /* field */
6338 if (tok == TOK_ARROW)
6339 indir();
6340 test_lvalue();
6341 gaddrof();
6342 next();
6343 /* expect pointer on structure */
6344 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6345 expect("struct or union");
6346 s = vtop->type.ref;
6347 /* find field */
6348 tok |= SYM_FIELD;
6349 while ((s = s->next) != NULL) {
6350 if (s->v == tok)
6351 break;
6353 if (!s)
6354 error("field not found");
6355 /* add field offset to pointer */
6356 vtop->type = char_pointer_type; /* change type to 'char *' */
6357 vpushi(s->c);
6358 gen_op('+');
6359 /* change type to field type, and set to lvalue */
6360 vtop->type = s->type;
6361 /* an array is never an lvalue */
6362 if (!(vtop->type.t & VT_ARRAY)) {
6363 vtop->r |= lvalue_type(vtop->type.t);
6364 /* if bound checking, the referenced pointer must be checked */
6365 if (do_bounds_check)
6366 vtop->r |= VT_MUSTBOUND;
6368 next();
6369 } else if (tok == '[') {
6370 next();
6371 gexpr();
6372 gen_op('+');
6373 indir();
6374 skip(']');
6375 } else if (tok == '(') {
6376 SValue ret;
6377 Sym *sa;
6379 /* function call */
6380 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
6381 /* pointer test (no array accepted) */
6382 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
6383 vtop->type = *pointed_type(&vtop->type);
6384 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
6385 goto error_func;
6386 } else {
6387 error_func:
6388 expect("function pointer");
6390 } else {
6391 vtop->r &= ~VT_LVAL; /* no lvalue */
6393 /* get return type */
6394 s = vtop->type.ref;
6395 if (!nocode_wanted) {
6396 save_regs(0); /* save used temporary registers */
6397 gfunc_start(&gf, s->r);
6399 next();
6400 sa = s->next; /* first parameter */
6401 #ifdef INVERT_FUNC_PARAMS
6403 int parlevel;
6404 Sym *args, *s1;
6405 ParseState saved_parse_state;
6406 TokenString str;
6408 /* read each argument and store it on a stack */
6409 args = NULL;
6410 if (tok != ')') {
6411 for(;;) {
6412 tok_str_new(&str);
6413 parlevel = 0;
6414 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
6415 tok != TOK_EOF) {
6416 if (tok == '(')
6417 parlevel++;
6418 else if (tok == ')')
6419 parlevel--;
6420 tok_str_add_tok(&str);
6421 next();
6423 tok_str_add(&str, -1); /* end of file added */
6424 tok_str_add(&str, 0);
6425 s1 = sym_push2(&args, 0, 0, (int)str.str);
6426 s1->next = sa; /* add reference to argument */
6427 if (sa)
6428 sa = sa->next;
6429 if (tok == ')')
6430 break;
6431 skip(',');
6435 /* now generate code in reverse order by reading the stack */
6436 save_parse_state(&saved_parse_state);
6437 while (args) {
6438 macro_ptr = (int *)args->c;
6439 next();
6440 expr_eq();
6441 if (tok != -1)
6442 expect("',' or ')'");
6443 gfunc_param_typed(&gf, s, args->next);
6444 s1 = args->prev;
6445 tok_str_free((int *)args->c);
6446 tcc_free(args);
6447 args = s1;
6449 restore_parse_state(&saved_parse_state);
6451 #endif
6452 /* compute first implicit argument if a structure is returned */
6453 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
6454 /* get some space for the returned structure */
6455 size = type_size(&s->type, &align);
6456 loc = (loc - size) & -align;
6457 ret.type = s->type;
6458 ret.r = VT_LOCAL | VT_LVAL;
6459 /* pass it as 'int' to avoid structure arg passing
6460 problems */
6461 vseti(VT_LOCAL, loc);
6462 ret.c = vtop->c;
6463 if (!nocode_wanted)
6464 gfunc_param(&gf);
6465 else
6466 vtop--;
6467 } else {
6468 ret.type = s->type;
6469 ret.r2 = VT_CONST;
6470 /* return in register */
6471 if (is_float(ret.type.t)) {
6472 ret.r = REG_FRET;
6473 } else {
6474 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
6475 ret.r2 = REG_LRET;
6476 ret.r = REG_IRET;
6478 ret.c.i = 0;
6480 #ifndef INVERT_FUNC_PARAMS
6481 if (tok != ')') {
6482 for(;;) {
6483 expr_eq();
6484 gfunc_param_typed(&gf, s, sa);
6485 if (sa)
6486 sa = sa->next;
6487 if (tok == ')')
6488 break;
6489 skip(',');
6492 #endif
6493 if (sa)
6494 error("too few arguments to function");
6495 skip(')');
6496 if (!nocode_wanted)
6497 gfunc_call(&gf);
6498 else
6499 vtop--;
6500 /* return value */
6501 vsetc(&ret.type, ret.r, &ret.c);
6502 vtop->r2 = ret.r2;
6503 } else {
6504 break;
6509 static void uneq(void)
6511 int t;
6513 unary();
6514 if (tok == '=' ||
6515 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
6516 tok == TOK_A_XOR || tok == TOK_A_OR ||
6517 tok == TOK_A_SHL || tok == TOK_A_SAR) {
6518 test_lvalue();
6519 t = tok;
6520 next();
6521 if (t == '=') {
6522 expr_eq();
6523 } else {
6524 vdup();
6525 expr_eq();
6526 gen_op(t & 0x7f);
6528 vstore();
6532 static void expr_prod(void)
6534 int t;
6536 uneq();
6537 while (tok == '*' || tok == '/' || tok == '%') {
6538 t = tok;
6539 next();
6540 uneq();
6541 gen_op(t);
6545 static void expr_sum(void)
6547 int t;
6549 expr_prod();
6550 while (tok == '+' || tok == '-') {
6551 t = tok;
6552 next();
6553 expr_prod();
6554 gen_op(t);
6558 static void expr_shift(void)
6560 int t;
6562 expr_sum();
6563 while (tok == TOK_SHL || tok == TOK_SAR) {
6564 t = tok;
6565 next();
6566 expr_sum();
6567 gen_op(t);
6571 static void expr_cmp(void)
6573 int t;
6575 expr_shift();
6576 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
6577 tok == TOK_ULT || tok == TOK_UGE) {
6578 t = tok;
6579 next();
6580 expr_shift();
6581 gen_op(t);
6585 static void expr_cmpeq(void)
6587 int t;
6589 expr_cmp();
6590 while (tok == TOK_EQ || tok == TOK_NE) {
6591 t = tok;
6592 next();
6593 expr_cmp();
6594 gen_op(t);
6598 static void expr_and(void)
6600 expr_cmpeq();
6601 while (tok == '&') {
6602 next();
6603 expr_cmpeq();
6604 gen_op('&');
6608 static void expr_xor(void)
6610 expr_and();
6611 while (tok == '^') {
6612 next();
6613 expr_and();
6614 gen_op('^');
6618 static void expr_or(void)
6620 expr_xor();
6621 while (tok == '|') {
6622 next();
6623 expr_xor();
6624 gen_op('|');
6628 /* XXX: suppress this mess */
6629 static void expr_land_const(void)
6631 expr_or();
6632 while (tok == TOK_LAND) {
6633 next();
6634 expr_or();
6635 gen_op(TOK_LAND);
6639 /* XXX: suppress this mess */
6640 static void expr_lor_const(void)
6642 expr_land_const();
6643 while (tok == TOK_LOR) {
6644 next();
6645 expr_land_const();
6646 gen_op(TOK_LOR);
6650 /* only used if non constant */
6651 static void expr_land(void)
6653 int t;
6655 expr_or();
6656 t = 0;
6657 while (1) {
6658 if (tok != TOK_LAND) {
6659 if (t) {
6660 t = gtst(1, t);
6661 vseti(VT_JMPI, t);
6663 break;
6665 t = gtst(1, t);
6666 next();
6667 expr_or();
6671 static void expr_lor(void)
6673 int t;
6675 expr_land();
6676 t = 0;
6677 while (1) {
6678 if (tok != TOK_LOR) {
6679 if (t) {
6680 t = gtst(0, t);
6681 vseti(VT_JMP, t);
6683 break;
6685 t = gtst(0, t);
6686 next();
6687 expr_land();
6691 /* XXX: better constant handling */
6692 static void expr_eq(void)
6694 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
6695 SValue sv;
6696 CType type, type1, type2;
6698 if (const_wanted) {
6699 int c1, c;
6700 expr_lor_const();
6701 if (tok == '?') {
6702 c = vtop->c.i;
6703 vpop();
6704 next();
6705 gexpr();
6706 c1 = vtop->c.i;
6707 vpop();
6708 skip(':');
6709 expr_eq();
6710 if (c)
6711 vtop->c.i = c1;
6713 } else {
6714 expr_lor();
6715 if (tok == '?') {
6716 next();
6717 save_regs(1); /* we need to save all registers here except
6718 at the top because it is a branch point */
6719 tt = gtst(1, 0);
6720 gexpr();
6721 type1 = vtop->type;
6722 sv = *vtop; /* save value to handle it later */
6723 vtop--; /* no vpop so that FP stack is not flushed */
6724 skip(':');
6725 u = gjmp(0);
6727 gsym(tt);
6728 expr_eq();
6729 type2 = vtop->type;
6731 t1 = type1.t;
6732 bt1 = t1 & VT_BTYPE;
6733 t2 = type2.t;
6734 bt2 = t2 & VT_BTYPE;
6735 /* cast operands to correct type according to ISOC rules */
6736 if (is_float(bt1) || is_float(bt2)) {
6737 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
6738 type.t = VT_LDOUBLE;
6739 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
6740 type.t = VT_DOUBLE;
6741 } else {
6742 type.t = VT_FLOAT;
6744 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
6745 /* cast to biggest op */
6746 type.t = VT_LLONG;
6747 /* convert to unsigned if it does not fit in a long long */
6748 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
6749 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
6750 type.t |= VT_UNSIGNED;
6751 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
6752 /* XXX: test pointer compatibility */
6753 type = type1;
6754 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
6755 /* XXX: test structure compatibility */
6756 type = type1;
6757 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
6758 /* NOTE: as an extension, we accept void on only one side */
6759 type.t = VT_VOID;
6760 } else {
6761 /* integer operations */
6762 type.t = VT_INT;
6763 /* convert to unsigned if it does not fit in an integer */
6764 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
6765 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
6766 type.t |= VT_UNSIGNED;
6769 /* now we convert second operand */
6770 gen_cast(&type);
6771 rc = RC_INT;
6772 if (is_float(type.t)) {
6773 rc = RC_FLOAT;
6774 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
6775 /* for long longs, we use fixed registers to avoid having
6776 to handle a complicated move */
6777 rc = RC_IRET;
6779 r2 = gv(rc);
6780 /* this is horrible, but we must also convert first
6781 operand */
6782 tt = gjmp(0);
6783 gsym(u);
6784 /* put again first value and cast it */
6785 *vtop = sv;
6786 gen_cast(&type);
6787 r1 = gv(rc);
6788 move_reg(r2, r1);
6789 vtop->r = r2;
6790 gsym(tt);
6795 static void gexpr(void)
6797 while (1) {
6798 expr_eq();
6799 if (tok != ',')
6800 break;
6801 vpop();
6802 next();
6806 /* parse an expression and return its type without any side effect. */
6807 static void expr_type(CType *type)
6809 int a;
6811 a = nocode_wanted;
6812 nocode_wanted = 1;
6813 gexpr();
6814 *type = vtop->type;
6815 vpop();
6816 nocode_wanted = a;
6819 /* parse a unary expression and return its type without any side
6820 effect. */
6821 static void unary_type(CType *type)
6823 int a;
6825 a = nocode_wanted;
6826 nocode_wanted = 1;
6827 unary();
6828 *type = vtop->type;
6829 vpop();
6830 nocode_wanted = a;
6833 /* parse a constant expression and return value in vtop. */
6834 static void expr_const1(void)
6836 int a;
6837 a = const_wanted;
6838 const_wanted = 1;
6839 expr_eq();
6840 const_wanted = a;
6843 /* parse an integer constant and return its value. */
6844 static int expr_const(void)
6846 int c;
6847 expr_const1();
6848 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
6849 expect("constant expression");
6850 c = vtop->c.i;
6851 vpop();
6852 return c;
6855 /* return the label token if current token is a label, otherwise
6856 return zero */
6857 static int is_label(void)
6859 int t;
6860 CValue c;
6862 /* fast test first */
6863 if (tok < TOK_UIDENT)
6864 return 0;
6865 /* no need to save tokc since we expect an identifier */
6866 t = tok;
6867 c = tokc;
6868 next();
6869 if (tok == ':') {
6870 next();
6871 return t;
6872 } else {
6873 /* XXX: may not work in all cases (macros ?) */
6874 tok1 = tok;
6875 tok1c = tokc;
6876 tok = t;
6877 tokc = c;
6878 return 0;
6882 static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
6884 int a, b, c, d;
6885 Sym *s;
6887 /* generate line number info */
6888 if (do_debug &&
6889 (last_line_num != file->line_num || last_ind != ind)) {
6890 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
6891 last_ind = ind;
6892 last_line_num = file->line_num;
6895 if (tok == TOK_IF) {
6896 /* if test */
6897 next();
6898 skip('(');
6899 gexpr();
6900 skip(')');
6901 a = gtst(1, 0);
6902 block(bsym, csym, case_sym, def_sym, case_reg);
6903 c = tok;
6904 if (c == TOK_ELSE) {
6905 next();
6906 d = gjmp(0);
6907 gsym(a);
6908 block(bsym, csym, case_sym, def_sym, case_reg);
6909 gsym(d); /* patch else jmp */
6910 } else
6911 gsym(a);
6912 } else if (tok == TOK_WHILE) {
6913 next();
6914 d = ind;
6915 skip('(');
6916 gexpr();
6917 skip(')');
6918 a = gtst(1, 0);
6919 b = 0;
6920 block(&a, &b, case_sym, def_sym, case_reg);
6921 gjmp_addr(d);
6922 gsym(a);
6923 gsym_addr(b, d);
6924 } else if (tok == '{') {
6925 next();
6926 /* declarations */
6927 s = local_stack;
6928 while (tok != '}') {
6929 decl(VT_LOCAL);
6930 if (tok != '}')
6931 block(bsym, csym, case_sym, def_sym, case_reg);
6933 /* pop locally defined symbols */
6934 sym_pop(&local_stack, s);
6935 next();
6936 } else if (tok == TOK_RETURN) {
6937 next();
6938 if (tok != ';') {
6939 gexpr();
6940 gen_assign_cast(&func_vt);
6941 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
6942 CType type;
6943 /* if returning structure, must copy it to implicit
6944 first pointer arg location */
6945 type = func_vt;
6946 mk_pointer(&type);
6947 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
6948 indir();
6949 vswap();
6950 /* copy structure value to pointer */
6951 vstore();
6952 } else if (is_float(func_vt.t)) {
6953 gv(RC_FRET);
6954 } else {
6955 gv(RC_IRET);
6957 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6959 skip(';');
6960 rsym = gjmp(rsym); /* jmp */
6961 } else if (tok == TOK_BREAK) {
6962 /* compute jump */
6963 if (!bsym)
6964 error("cannot break");
6965 *bsym = gjmp(*bsym);
6966 next();
6967 skip(';');
6968 } else if (tok == TOK_CONTINUE) {
6969 /* compute jump */
6970 if (!csym)
6971 error("cannot continue");
6972 *csym = gjmp(*csym);
6973 next();
6974 skip(';');
6975 } else if (tok == TOK_FOR) {
6976 int e;
6977 next();
6978 skip('(');
6979 if (tok != ';') {
6980 gexpr();
6981 vpop();
6983 skip(';');
6984 d = ind;
6985 c = ind;
6986 a = 0;
6987 b = 0;
6988 if (tok != ';') {
6989 gexpr();
6990 a = gtst(1, 0);
6992 skip(';');
6993 if (tok != ')') {
6994 e = gjmp(0);
6995 c = ind;
6996 gexpr();
6997 vpop();
6998 gjmp_addr(d);
6999 gsym(e);
7001 skip(')');
7002 block(&a, &b, case_sym, def_sym, case_reg);
7003 gjmp_addr(c);
7004 gsym(a);
7005 gsym_addr(b, c);
7006 } else
7007 if (tok == TOK_DO) {
7008 next();
7009 a = 0;
7010 b = 0;
7011 d = ind;
7012 block(&a, &b, case_sym, def_sym, case_reg);
7013 skip(TOK_WHILE);
7014 skip('(');
7015 gsym(b);
7016 gexpr();
7017 c = gtst(0, 0);
7018 gsym_addr(c, d);
7019 skip(')');
7020 gsym(a);
7021 skip(';');
7022 } else
7023 if (tok == TOK_SWITCH) {
7024 next();
7025 skip('(');
7026 gexpr();
7027 /* XXX: other types than integer */
7028 case_reg = gv(RC_INT);
7029 vpop();
7030 skip(')');
7031 a = 0;
7032 b = gjmp(0); /* jump to first case */
7033 c = 0;
7034 block(&a, csym, &b, &c, case_reg);
7035 /* if no default, jmp after switch */
7036 if (c == 0)
7037 c = ind;
7038 /* default label */
7039 gsym_addr(b, c);
7040 /* break label */
7041 gsym(a);
7042 } else
7043 if (tok == TOK_CASE) {
7044 int v1, v2;
7045 if (!case_sym)
7046 expect("switch");
7047 next();
7048 v1 = expr_const();
7049 v2 = v1;
7050 if (gnu_ext && tok == TOK_DOTS) {
7051 next();
7052 v2 = expr_const();
7053 if (v2 < v1)
7054 warning("empty case range");
7056 /* since a case is like a label, we must skip it with a jmp */
7057 b = gjmp(0);
7058 gsym(*case_sym);
7059 vseti(case_reg, 0);
7060 vpushi(v1);
7061 if (v1 == v2) {
7062 gen_op(TOK_EQ);
7063 *case_sym = gtst(1, 0);
7064 } else {
7065 gen_op(TOK_GE);
7066 *case_sym = gtst(1, 0);
7067 vseti(case_reg, 0);
7068 vpushi(v2);
7069 gen_op(TOK_LE);
7070 *case_sym = gtst(1, *case_sym);
7072 gsym(b);
7073 skip(':');
7074 block(bsym, csym, case_sym, def_sym, case_reg);
7075 } else
7076 if (tok == TOK_DEFAULT) {
7077 next();
7078 skip(':');
7079 if (!def_sym)
7080 expect("switch");
7081 if (*def_sym)
7082 error("too many 'default'");
7083 *def_sym = ind;
7084 block(bsym, csym, case_sym, def_sym, case_reg);
7085 } else
7086 if (tok == TOK_GOTO) {
7087 next();
7088 if (tok == '*' && gnu_ext) {
7089 /* computed goto */
7090 next();
7091 gexpr();
7092 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7093 expect("pointer");
7094 ggoto();
7095 } else if (tok >= TOK_UIDENT) {
7096 s = label_find(tok);
7097 /* put forward definition if needed */
7098 if (!s) {
7099 s = label_push(tok, LABEL_FORWARD);
7101 /* label already defined */
7102 if (s->r & LABEL_FORWARD)
7103 s->next = (void *)gjmp((long)s->next);
7104 else
7105 gjmp_addr((long)s->next);
7106 next();
7107 } else {
7108 expect("label identifier");
7110 skip(';');
7111 } else {
7112 b = is_label();
7113 if (b) {
7114 /* label case */
7115 s = label_find(b);
7116 if (s) {
7117 if (!(s->r & LABEL_FORWARD))
7118 error("multiple defined label");
7119 gsym((long)s->next);
7120 } else {
7121 s = label_push(b, 0);
7123 s->next = (void *)ind;
7124 s->r = 0;
7125 /* we accept this, but it is a mistake */
7126 if (tok == '}')
7127 warning("deprecated use of label at end of compound statement");
7128 else
7129 block(bsym, csym, case_sym, def_sym, case_reg);
7130 } else {
7131 /* expression case */
7132 if (tok != ';') {
7133 gexpr();
7134 vpop();
7136 skip(';');
7141 /* t is the array or struct type. c is the array or struct
7142 address. cur_index/cur_field is the pointer to the current
7143 value. 'size_only' is true if only size info is needed (only used
7144 in arrays) */
7145 static void decl_designator(CType *type, Section *sec, unsigned long c,
7146 int *cur_index, Sym **cur_field,
7147 int size_only)
7149 Sym *s, *f;
7150 int notfirst, index, align, l;
7151 CType type1;
7153 notfirst = 0;
7154 if (gnu_ext && (l = is_label()) != 0)
7155 goto struct_field;
7157 while (tok == '[' || tok == '.') {
7158 if (tok == '[') {
7159 if (!(type->t & VT_ARRAY))
7160 expect("array type");
7161 s = type->ref;
7162 next();
7163 index = expr_const();
7164 if (index < 0 || (s->c >= 0 && index >= s->c))
7165 expect("invalid index");
7166 skip(']');
7167 if (!notfirst)
7168 *cur_index = index;
7169 type = pointed_type(type);
7170 c += index * type_size(type, &align);
7171 } else {
7172 next();
7173 l = tok;
7174 next();
7175 struct_field:
7176 if ((type->t & VT_BTYPE) != VT_STRUCT)
7177 expect("struct/union type");
7178 s = type->ref;
7179 l |= SYM_FIELD;
7180 f = s->next;
7181 while (f) {
7182 if (f->v == l)
7183 break;
7184 f = f->next;
7186 if (!f)
7187 expect("field");
7188 if (!notfirst)
7189 *cur_field = f;
7190 /* XXX: suppress this mess by using explicit storage field */
7191 type1 = f->type;
7192 type1.t |= (type->t & ~VT_TYPE);
7193 type = &type1;
7194 c += f->c;
7196 notfirst = 1;
7198 if (notfirst) {
7199 if (tok == '=') {
7200 next();
7201 } else {
7202 if (!gnu_ext)
7203 expect("=");
7205 } else {
7206 if (type->t & VT_ARRAY) {
7207 index = *cur_index;
7208 type = pointed_type(type);
7209 c += index * type_size(type, &align);
7210 } else {
7211 f = *cur_field;
7212 if (!f)
7213 error("too many field init");
7214 /* XXX: suppress this mess by using explicit storage field */
7215 type1 = f->type;
7216 type1.t |= (type->t & ~VT_TYPE);
7217 type = &type1;
7218 c += f->c;
7221 decl_initializer(type, sec, c, 0, size_only);
7224 #define EXPR_VAL 0
7225 #define EXPR_CONST 1
7226 #define EXPR_ANY 2
7228 /* store a value or an expression directly in global data or in local array */
7229 static void init_putv(CType *type, Section *sec, unsigned long c,
7230 int v, int expr_type)
7232 int saved_global_expr, bt;
7233 void *ptr;
7235 switch(expr_type) {
7236 case EXPR_VAL:
7237 vpushi(v);
7238 break;
7239 case EXPR_CONST:
7240 /* compound literals must be allocated globally in this case */
7241 saved_global_expr = global_expr;
7242 global_expr = 1;
7243 expr_const1();
7244 global_expr = saved_global_expr;
7245 /* NOTE: symbols are accepted */
7246 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
7247 error("initializer element is not constant");
7248 break;
7249 case EXPR_ANY:
7250 expr_eq();
7251 break;
7254 if (sec) {
7255 /* XXX: not portable */
7256 /* XXX: generate error if incorrect relocation */
7257 gen_assign_cast(type);
7258 bt = type->t & VT_BTYPE;
7259 ptr = sec->data + c;
7260 if ((vtop->r & VT_SYM) &&
7261 (bt == VT_BYTE ||
7262 bt == VT_SHORT ||
7263 bt == VT_DOUBLE ||
7264 bt == VT_LDOUBLE ||
7265 bt == VT_LLONG))
7266 error("initializer element is not computable at load time");
7267 switch(bt) {
7268 case VT_BYTE:
7269 *(char *)ptr = vtop->c.i;
7270 break;
7271 case VT_SHORT:
7272 *(short *)ptr = vtop->c.i;
7273 break;
7274 case VT_DOUBLE:
7275 *(double *)ptr = vtop->c.d;
7276 break;
7277 case VT_LDOUBLE:
7278 *(long double *)ptr = vtop->c.ld;
7279 break;
7280 case VT_LLONG:
7281 *(long long *)ptr = vtop->c.ll;
7282 break;
7283 default:
7284 if (vtop->r & VT_SYM) {
7285 greloc(sec, vtop->sym, c, R_DATA_32);
7287 *(int *)ptr = vtop->c.i;
7288 break;
7290 vtop--;
7291 } else {
7292 vset(type, VT_LOCAL, c);
7293 vswap();
7294 vstore();
7295 vpop();
7299 /* put zeros for variable based init */
7300 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
7302 GFuncContext gf;
7304 if (sec) {
7305 /* nothing to do because globals are already set to zero */
7306 } else {
7307 gfunc_start(&gf, FUNC_CDECL);
7308 vpushi(size);
7309 gfunc_param(&gf);
7310 vpushi(0);
7311 gfunc_param(&gf);
7312 vseti(VT_LOCAL, c);
7313 gfunc_param(&gf);
7314 vpush_global_sym(&func_old_type, TOK_memset);
7315 gfunc_call(&gf);
7319 /* 't' contains the type and storage info. 'c' is the offset of the
7320 object in section 'sec'. If 'sec' is NULL, it means stack based
7321 allocation. 'first' is true if array '{' must be read (multi
7322 dimension implicit array init handling). 'size_only' is true if
7323 size only evaluation is wanted (only for arrays). */
7324 static void decl_initializer(CType *type, Section *sec, unsigned long c,
7325 int first, int size_only)
7327 int index, array_length, n, no_oblock, nb, parlevel, i;
7328 int size1, align1, expr_type;
7329 Sym *s, *f;
7330 CType *t1;
7332 if (type->t & VT_ARRAY) {
7333 s = type->ref;
7334 n = s->c;
7335 array_length = 0;
7336 t1 = pointed_type(type);
7337 size1 = type_size(t1, &align1);
7339 no_oblock = 1;
7340 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
7341 tok == '{') {
7342 skip('{');
7343 no_oblock = 0;
7346 /* only parse strings here if correct type (otherwise: handle
7347 them as ((w)char *) expressions */
7348 if ((tok == TOK_LSTR &&
7349 (t1->t & VT_BTYPE) == VT_INT) ||
7350 (tok == TOK_STR &&
7351 (t1->t & VT_BTYPE) == VT_BYTE)) {
7352 while (tok == TOK_STR || tok == TOK_LSTR) {
7353 int cstr_len, ch;
7354 CString *cstr;
7356 cstr = tokc.cstr;
7357 /* compute maximum number of chars wanted */
7358 if (tok == TOK_STR)
7359 cstr_len = cstr->size;
7360 else
7361 cstr_len = cstr->size / sizeof(int);
7362 cstr_len--;
7363 nb = cstr_len;
7364 if (n >= 0 && nb > (n - array_length))
7365 nb = n - array_length;
7366 if (!size_only) {
7367 if (cstr_len > nb)
7368 warning("initializer-string for array is too long");
7369 /* in order to go faster for common case (char
7370 string in global variable, we handle it
7371 specifically */
7372 if (sec && tok == TOK_STR && size1 == 1) {
7373 memcpy(sec->data + c + array_length, cstr->data, nb);
7374 } else {
7375 for(i=0;i<nb;i++) {
7376 if (tok == TOK_STR)
7377 ch = ((unsigned char *)cstr->data)[i];
7378 else
7379 ch = ((int *)cstr->data)[i];
7380 init_putv(t1, sec, c + (array_length + i) * size1,
7381 ch, EXPR_VAL);
7385 array_length += nb;
7386 next();
7388 /* only add trailing zero if enough storage (no
7389 warning in this case since it is standard) */
7390 if (n < 0 || array_length < n) {
7391 if (!size_only) {
7392 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
7394 array_length++;
7396 } else {
7397 index = 0;
7398 while (tok != '}') {
7399 decl_designator(type, sec, c, &index, NULL, size_only);
7400 if (n >= 0 && index >= n)
7401 error("index too large");
7402 /* must put zero in holes (note that doing it that way
7403 ensures that it even works with designators) */
7404 if (!size_only && array_length < index) {
7405 init_putz(t1, sec, c + array_length * size1,
7406 (index - array_length) * size1);
7408 index++;
7409 if (index > array_length)
7410 array_length = index;
7411 /* special test for multi dimensional arrays (may not
7412 be strictly correct if designators are used at the
7413 same time) */
7414 if (index >= n && no_oblock)
7415 break;
7416 if (tok == '}')
7417 break;
7418 skip(',');
7421 if (!no_oblock)
7422 skip('}');
7423 /* put zeros at the end */
7424 if (!size_only && n >= 0 && array_length < n) {
7425 init_putz(t1, sec, c + array_length * size1,
7426 (n - array_length) * size1);
7428 /* patch type size if needed */
7429 if (n < 0)
7430 s->c = array_length;
7431 } else if ((type->t & VT_BTYPE) == VT_STRUCT && tok == '{') {
7432 /* XXX: union needs only one init */
7433 next();
7434 s = type->ref;
7435 f = s->next;
7436 array_length = 0;
7437 index = 0;
7438 n = s->c;
7439 while (tok != '}') {
7440 decl_designator(type, sec, c, NULL, &f, size_only);
7441 /* fill with zero between fields */
7442 index = f->c;
7443 if (!size_only && array_length < index) {
7444 init_putz(type, sec, c + array_length,
7445 index - array_length);
7447 index = index + type_size(&f->type, &align1);
7448 if (index > array_length)
7449 array_length = index;
7450 if (tok == '}')
7451 break;
7452 skip(',');
7453 f = f->next;
7455 /* put zeros at the end */
7456 if (!size_only && array_length < n) {
7457 init_putz(type, sec, c + array_length,
7458 n - array_length);
7460 skip('}');
7461 } else if (tok == '{') {
7462 next();
7463 decl_initializer(type, sec, c, first, size_only);
7464 skip('}');
7465 } else if (size_only) {
7466 /* just skip expression */
7467 parlevel = 0;
7468 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
7469 tok != -1) {
7470 if (tok == '(')
7471 parlevel++;
7472 else if (tok == ')')
7473 parlevel--;
7474 next();
7476 } else {
7477 /* currently, we always use constant expression for globals
7478 (may change for scripting case) */
7479 expr_type = EXPR_CONST;
7480 if (!sec)
7481 expr_type = EXPR_ANY;
7482 init_putv(type, sec, c, 0, expr_type);
7486 /* parse an initializer for type 't' if 'has_init' is non zero, and
7487 allocate space in local or global data space ('r' is either
7488 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
7489 variable 'v' of scope 'scope' is declared before initializers are
7490 parsed. If 'v' is zero, then a reference to the new object is put
7491 in the value stack. If 'has_init' is 2, a special parsing is done
7492 to handle string constants. */
7493 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
7494 int has_init, int v, int scope)
7496 int size, align, addr, data_offset;
7497 int level;
7498 ParseState saved_parse_state;
7499 TokenString init_str;
7500 Section *sec;
7502 size = type_size(type, &align);
7503 /* If unknown size, we must evaluate it before
7504 evaluating initializers because
7505 initializers can generate global data too
7506 (e.g. string pointers or ISOC99 compound
7507 literals). It also simplifies local
7508 initializers handling */
7509 tok_str_new(&init_str);
7510 if (size < 0) {
7511 if (!has_init)
7512 error("unknown type size");
7513 /* get all init string */
7514 if (has_init == 2) {
7515 /* only get strings */
7516 while (tok == TOK_STR || tok == TOK_LSTR) {
7517 tok_str_add_tok(&init_str);
7518 next();
7520 } else {
7521 level = 0;
7522 while (level > 0 || (tok != ',' && tok != ';')) {
7523 if (tok < 0)
7524 error("unexpected end of file in initializer");
7525 tok_str_add_tok(&init_str);
7526 if (tok == '{')
7527 level++;
7528 else if (tok == '}') {
7529 if (level == 0)
7530 break;
7531 level--;
7533 next();
7536 tok_str_add(&init_str, -1);
7537 tok_str_add(&init_str, 0);
7539 /* compute size */
7540 save_parse_state(&saved_parse_state);
7542 macro_ptr = init_str.str;
7543 next();
7544 decl_initializer(type, NULL, 0, 1, 1);
7545 /* prepare second initializer parsing */
7546 macro_ptr = init_str.str;
7547 next();
7549 /* if still unknown size, error */
7550 size = type_size(type, &align);
7551 if (size < 0)
7552 error("unknown type size");
7554 /* take into account specified alignment if bigger */
7555 if (ad->aligned > align)
7556 align = ad->aligned;
7557 if ((r & VT_VALMASK) == VT_LOCAL) {
7558 sec = NULL;
7559 if (do_bounds_check && (type->t & VT_ARRAY))
7560 loc--;
7561 #ifdef TCC_TARGET_IL
7562 /* XXX: ugly patch to allocate local variables for IL, just
7563 for testing */
7564 addr = loc;
7565 loc++;
7566 #else
7567 loc = (loc - size) & -align;
7568 addr = loc;
7569 #endif
7570 /* handles bounds */
7571 /* XXX: currently, since we do only one pass, we cannot track
7572 '&' operators, so we add only arrays */
7573 if (do_bounds_check && (type->t & VT_ARRAY)) {
7574 unsigned long *bounds_ptr;
7575 /* add padding between regions */
7576 loc--;
7577 /* then add local bound info */
7578 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
7579 bounds_ptr[0] = addr;
7580 bounds_ptr[1] = size;
7582 } else {
7583 /* compute section */
7584 sec = ad->section;
7585 if (!sec) {
7586 if (has_init)
7587 sec = data_section;
7588 else
7589 sec = bss_section;
7591 data_offset = sec->data_offset;
7592 data_offset = (data_offset + align - 1) & -align;
7593 addr = data_offset;
7594 /* very important to increment global pointer at this time
7595 because initializers themselves can create new initializers */
7596 data_offset += size;
7597 /* add padding if bound check */
7598 if (do_bounds_check)
7599 data_offset++;
7600 sec->data_offset = data_offset;
7601 /* allocate section space to put the data */
7602 if (sec->sh_type != SHT_NOBITS &&
7603 data_offset > sec->data_allocated)
7604 section_realloc(sec, data_offset);
7606 if (!sec) {
7607 if (v) {
7608 /* local variable */
7609 sym_push(v, type, r, addr);
7610 } else {
7611 /* push local reference */
7612 vset(type, r, addr);
7614 } else {
7615 Sym *sym;
7617 if (v) {
7618 if (scope == VT_CONST) {
7619 /* global scope: see if already defined */
7620 sym = sym_find(v);
7621 if (!sym)
7622 goto do_def;
7623 if (!is_compatible_types(&sym->type, type))
7624 error("incompatible types for redefinition of '%s'",
7625 get_tok_str(v, NULL));
7626 if (!(sym->type.t & VT_EXTERN))
7627 error("redefinition of '%s'", get_tok_str(v, NULL));
7628 sym->type.t &= ~VT_EXTERN;
7629 } else {
7630 do_def:
7631 sym = sym_push(v, type, r | VT_SYM, 0);
7633 put_extern_sym(sym, sec, addr, size);
7634 } else {
7635 CValue cval;
7637 /* push global reference */
7638 sym = get_sym_ref(type, sec, addr, size);
7639 cval.ul = 0;
7640 vsetc(type, VT_CONST | VT_SYM, &cval);
7641 vtop->sym = sym;
7644 /* handles bounds now because the symbol must be defined
7645 before for the relocation */
7646 if (do_bounds_check) {
7647 unsigned long *bounds_ptr;
7649 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
7650 /* then add global bound info */
7651 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
7652 bounds_ptr[0] = 0; /* relocated */
7653 bounds_ptr[1] = size;
7656 if (has_init) {
7657 decl_initializer(type, sec, addr, 1, 0);
7658 /* restore parse state if needed */
7659 if (init_str.str) {
7660 tok_str_free(init_str.str);
7661 restore_parse_state(&saved_parse_state);
7666 void put_func_debug(Sym *sym)
7668 char buf[512];
7670 /* stabs info */
7671 /* XXX: we put here a dummy type */
7672 snprintf(buf, sizeof(buf), "%s:%c1",
7673 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
7674 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
7675 cur_text_section, sym->c);
7676 last_ind = 0;
7677 last_line_num = 0;
7680 /* not finished : try to put some local vars in registers */
7681 //#define CONFIG_REG_VARS
7683 #ifdef CONFIG_REG_VARS
7684 void add_var_ref(int t)
7686 printf("%s:%d: &%s\n",
7687 file->filename, file->line_num,
7688 get_tok_str(t, NULL));
7691 /* first pass on a function with heuristic to extract variable usage
7692 and pointer references to local variables for register allocation */
7693 void analyse_function(void)
7695 int level, t;
7697 for(;;) {
7698 if (tok == -1)
7699 break;
7700 /* any symbol coming after '&' is considered as being a
7701 variable whose reference is taken. It is highly unaccurate
7702 but it is difficult to do better without a complete parse */
7703 if (tok == '&') {
7704 next();
7705 /* if '& number', then no need to examine next tokens */
7706 if (tok == TOK_CINT ||
7707 tok == TOK_CUINT ||
7708 tok == TOK_CLLONG ||
7709 tok == TOK_CULLONG) {
7710 continue;
7711 } else if (tok >= TOK_UIDENT) {
7712 /* if '& ident [' or '& ident ->', then ident address
7713 is not needed */
7714 t = tok;
7715 next();
7716 if (tok != '[' && tok != TOK_ARROW)
7717 add_var_ref(t);
7718 } else {
7719 level = 0;
7720 while (tok != '}' && tok != ';' &&
7721 !((tok == ',' || tok == ')') && level == 0)) {
7722 if (tok >= TOK_UIDENT) {
7723 add_var_ref(tok);
7724 } else if (tok == '(') {
7725 level++;
7726 } else if (tok == ')') {
7727 level--;
7729 next();
7732 } else {
7733 next();
7737 #endif
7739 /* parse an old style function declaration list */
7740 /* XXX: check multiple parameter */
7741 static void func_decl_list(Sym *func_sym)
7743 AttributeDef ad;
7744 int v;
7745 Sym *s;
7746 CType btype, type;
7748 /* parse each declaration */
7749 while (tok != '{' && tok != ';' && tok != TOK_EOF) {
7750 if (!parse_btype(&btype, &ad))
7751 expect("declaration list");
7752 if (((btype.t & VT_BTYPE) == VT_ENUM ||
7753 (btype.t & VT_BTYPE) == VT_STRUCT) &&
7754 tok == ';') {
7755 /* we accept no variable after */
7756 } else {
7757 for(;;) {
7758 type = btype;
7759 type_decl(&type, &ad, &v, TYPE_DIRECT);
7760 /* find parameter in function parameter list */
7761 s = func_sym->next;
7762 while (s != NULL) {
7763 if ((s->v & ~SYM_FIELD) == v)
7764 goto found;
7765 s = s->next;
7767 error("declaration for parameter '%s' but no such parameter",
7768 get_tok_str(v, NULL));
7769 found:
7770 /* check that no storage specifier except 'register' was given */
7771 if (type.t & (VT_EXTERN | VT_STATIC | VT_TYPEDEF))
7772 error("storage class specified for '%s'", get_tok_str(v, NULL));
7773 /* we can add the type (NOTE: it could be local to the function) */
7774 s->type = type;
7775 /* accept other parameters */
7776 if (tok == ',')
7777 next();
7778 else
7779 break;
7782 skip(';');
7786 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
7787 static void decl(int l)
7789 int v, has_init, r;
7790 CType type, btype;
7791 Sym *sym;
7792 AttributeDef ad;
7794 while (1) {
7795 if (!parse_btype(&btype, &ad)) {
7796 /* skip redundant ';' */
7797 /* XXX: find more elegant solution */
7798 if (tok == ';') {
7799 next();
7800 continue;
7802 /* special test for old K&R protos without explicit int
7803 type. Only accepted when defining global data */
7804 if (l == VT_LOCAL || tok < TOK_DEFINE)
7805 break;
7806 btype.t = VT_INT;
7808 if (((btype.t & VT_BTYPE) == VT_ENUM ||
7809 (btype.t & VT_BTYPE) == VT_STRUCT) &&
7810 tok == ';') {
7811 /* we accept no variable after */
7812 next();
7813 continue;
7815 while (1) { /* iterate thru each declaration */
7816 type = btype;
7817 type_decl(&type, &ad, &v, TYPE_DIRECT);
7818 #if 0
7820 char buf[500];
7821 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
7822 printf("type = '%s'\n", buf);
7824 #endif
7825 if ((type.t & VT_BTYPE) == VT_FUNC) {
7826 /* if old style function prototype, we accept a
7827 declaration list */
7828 sym = type.ref;
7829 if (sym->c == FUNC_OLD)
7830 func_decl_list(sym);
7833 if (tok == '{') {
7834 #ifdef CONFIG_REG_VARS
7835 TokenString func_str;
7836 ParseState saved_parse_state;
7837 int block_level;
7838 #endif
7840 if (l == VT_LOCAL)
7841 error("cannot use local functions");
7842 if (!(type.t & VT_FUNC))
7843 expect("function definition");
7845 #ifdef CONFIG_REG_VARS
7846 /* parse all function code and record it */
7848 tok_str_new(&func_str);
7850 block_level = 0;
7851 for(;;) {
7852 int t;
7853 if (tok == -1)
7854 error("unexpected end of file");
7855 tok_str_add_tok(&func_str);
7856 t = tok;
7857 next();
7858 if (t == '{') {
7859 block_level++;
7860 } else if (t == '}') {
7861 block_level--;
7862 if (block_level == 0)
7863 break;
7866 tok_str_add(&func_str, -1);
7867 tok_str_add(&func_str, 0);
7869 save_parse_state(&saved_parse_state);
7871 macro_ptr = func_str.str;
7872 next();
7873 analyse_function();
7874 #endif
7876 /* compute text section */
7877 cur_text_section = ad.section;
7878 if (!cur_text_section)
7879 cur_text_section = text_section;
7880 ind = cur_text_section->data_offset;
7881 funcname = get_tok_str(v, NULL);
7882 sym = sym_find(v);
7883 if (sym) {
7884 /* if symbol is already defined, then put complete type */
7885 sym->type = type;
7886 } else {
7887 /* put function symbol */
7888 sym = global_identifier_push(v, type.t, 0);
7889 sym->type.ref = type.ref;
7891 /* NOTE: we patch the symbol size later */
7892 put_extern_sym(sym, cur_text_section, ind, 0);
7893 func_ind = ind;
7894 sym->r = VT_SYM | VT_CONST;
7895 /* put debug symbol */
7896 if (do_debug)
7897 put_func_debug(sym);
7898 /* push a dummy symbol to enable local sym storage */
7899 sym_push2(&local_stack, SYM_FIELD, 0, 0);
7900 gfunc_prolog(&type);
7901 loc = 0;
7902 rsym = 0;
7903 #ifdef CONFIG_REG_VARS
7904 macro_ptr = func_str.str;
7905 next();
7906 #endif
7907 block(NULL, NULL, NULL, NULL, 0);
7908 gsym(rsym);
7909 gfunc_epilog();
7910 cur_text_section->data_offset = ind;
7911 /* look if any labels are undefined. Define symbols if
7912 '&&label' was used. */
7914 Sym *s, *s1;
7915 for(s = label_stack; s != NULL; s = s1) {
7916 s1 = s->prev;
7917 if (s->r & LABEL_FORWARD) {
7918 error("label '%s' used but not defined",
7919 get_tok_str(s->v, NULL));
7921 if (s->c) {
7922 /* define corresponding symbol. A size of
7923 1 is put. */
7924 put_extern_sym(s, cur_text_section, (long)s->next, 1);
7926 /* remove label */
7927 table_ident[s->v - TOK_IDENT]->sym_label = NULL;
7928 tcc_free(s);
7930 label_stack = NULL;
7932 sym_pop(&local_stack, NULL); /* reset local stack */
7933 /* end of function */
7934 /* patch symbol size */
7935 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
7936 ind - func_ind;
7937 if (do_debug) {
7938 put_stabn(N_FUN, 0, 0, ind - func_ind);
7940 funcname = ""; /* for safety */
7941 func_vt.t = VT_VOID; /* for safety */
7942 ind = 0; /* for safety */
7944 #ifdef CONFIG_REG_VARS
7945 tok_str_free(func_str.str);
7946 restore_parse_state(&saved_parse_state);
7947 #endif
7948 break;
7949 } else {
7950 if (btype.t & VT_TYPEDEF) {
7951 /* save typedefed type */
7952 /* XXX: test storage specifiers ? */
7953 sym = sym_push(v, &type, 0, 0);
7954 sym->type.t |= VT_TYPEDEF;
7955 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
7956 /* external function definition */
7957 external_sym(v, &type, 0);
7958 } else {
7959 /* not lvalue if array */
7960 r = 0;
7961 if (!(type.t & VT_ARRAY))
7962 r |= lvalue_type(type.t);
7963 if (btype.t & VT_EXTERN) {
7964 /* external variable */
7965 external_sym(v, &type, r);
7966 } else {
7967 if (type.t & VT_STATIC)
7968 r |= VT_CONST;
7969 else
7970 r |= l;
7971 has_init = (tok == '=');
7972 if (has_init)
7973 next();
7974 decl_initializer_alloc(&type, &ad, r,
7975 has_init, v, l);
7978 if (tok != ',') {
7979 skip(';');
7980 break;
7982 next();
7988 /* compile the C file opened in 'file'. Return non zero if errors. */
7989 static int tcc_compile(TCCState *s1)
7991 Sym *define_start;
7992 char buf[512];
7993 volatile int section_sym;
7995 #ifdef INC_DEBUG
7996 printf("%s: **** new file\n", file->filename);
7997 #endif
7998 funcname = "";
7999 s1->include_stack_ptr = s1->include_stack;
8000 /* XXX: move that before to avoid having to initialize
8001 file->ifdef_stack_ptr ? */
8002 s1->ifdef_stack_ptr = s1->ifdef_stack;
8003 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8005 /* XXX: not ANSI compliant: bound checking says error */
8006 vtop = vstack - 1;
8007 anon_sym = SYM_FIRST_ANOM;
8009 /* file info: full path + filename */
8010 section_sym = 0; /* avoid warning */
8011 if (do_debug) {
8012 section_sym = put_elf_sym(symtab_section, 0, 0,
8013 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8014 text_section->sh_num, NULL);
8015 getcwd(buf, sizeof(buf));
8016 pstrcat(buf, sizeof(buf), "/");
8017 put_stabs_r(buf, N_SO, 0, 0,
8018 text_section->data_offset, text_section, section_sym);
8019 put_stabs_r(file->filename, N_SO, 0, 0,
8020 text_section->data_offset, text_section, section_sym);
8022 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8023 symbols can be safely used */
8024 put_elf_sym(symtab_section, 0, 0,
8025 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8026 SHN_ABS, file->filename);
8028 /* define some often used types */
8029 int_type.t = VT_INT;
8031 char_pointer_type.t = VT_BYTE;
8032 mk_pointer(&char_pointer_type);
8034 func_old_type.t = VT_FUNC;
8035 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8037 #if 0
8038 /* define 'void *alloca(unsigned int)' builtin function */
8040 Sym *s1;
8042 p = anon_sym++;
8043 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8044 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8045 s1->next = NULL;
8046 sym->next = s1;
8047 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8049 #endif
8051 define_start = define_stack;
8053 if (setjmp(s1->error_jmp_buf) == 0) {
8054 s1->nb_errors = 0;
8055 s1->error_set_jmp_enabled = 1;
8057 ch = file->buf_ptr[0];
8058 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8059 next();
8060 decl(VT_CONST);
8061 if (tok != -1)
8062 expect("declaration");
8064 /* end of translation unit info */
8065 if (do_debug) {
8066 put_stabs_r(NULL, N_SO, 0, 0,
8067 text_section->data_offset, text_section, section_sym);
8070 s1->error_set_jmp_enabled = 0;
8072 /* reset define stack, but leave -Dsymbols (may be incorrect if
8073 they are undefined) */
8074 free_defines(define_start);
8076 sym_pop(&global_stack, NULL);
8078 return s1->nb_errors != 0 ? -1 : 0;
8081 #ifdef LIBTCC
8082 int tcc_compile_string(TCCState *s, const char *str)
8084 BufferedFile bf1, *bf = &bf1;
8085 int ret, len;
8086 char *buf;
8088 /* init file structure */
8089 bf->fd = -1;
8090 /* XXX: avoid copying */
8091 len = strlen(str);
8092 buf = tcc_malloc(len + 1);
8093 if (!buf)
8094 return -1;
8095 buf[len] = CH_EOB;
8096 bf->buf_ptr = buf;
8097 bf->buf_end = buf + len;
8098 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8099 bf->line_num = 1;
8100 file = bf;
8102 ret = tcc_compile(s);
8104 tcc_free(buf);
8106 /* currently, no need to close */
8107 return ret;
8109 #endif
8111 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8112 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8114 BufferedFile bf1, *bf = &bf1;
8116 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8117 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8118 /* default value */
8119 if (!value)
8120 value = "1";
8121 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8123 /* init file structure */
8124 bf->fd = -1;
8125 bf->buf_ptr = bf->buffer;
8126 bf->buf_end = bf->buffer + strlen(bf->buffer);
8127 *bf->buf_end = CH_EOB;
8128 bf->filename[0] = '\0';
8129 bf->line_num = 1;
8130 file = bf;
8132 s1->include_stack_ptr = s1->include_stack;
8134 /* parse with define parser */
8135 ch = file->buf_ptr[0];
8136 next_nomacro();
8137 parse_define();
8138 file = NULL;
8141 /* undefine a preprocessor symbol */
8142 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8144 TokenSym *ts;
8145 Sym *s;
8146 ts = tok_alloc(sym, strlen(sym));
8147 s = define_find(ts->tok);
8148 /* undefine symbol by putting an invalid name */
8149 if (s)
8150 define_undef(s);
8153 #include "tccelf.c"
8155 /* print the position in the source file of PC value 'pc' by reading
8156 the stabs debug information */
8157 static void rt_printline(unsigned long wanted_pc)
8159 Stab_Sym *sym, *sym_end;
8160 char func_name[128], last_func_name[128];
8161 unsigned long func_addr, last_pc, pc;
8162 const char *incl_files[INCLUDE_STACK_SIZE];
8163 int incl_index, len, last_line_num, i;
8164 const char *str, *p;
8166 fprintf(stderr, "0x%08lx:", wanted_pc);
8168 func_name[0] = '\0';
8169 func_addr = 0;
8170 incl_index = 0;
8171 last_func_name[0] = '\0';
8172 last_pc = 0xffffffff;
8173 last_line_num = 1;
8174 sym = (Stab_Sym *)stab_section->data + 1;
8175 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
8176 while (sym < sym_end) {
8177 switch(sym->n_type) {
8178 /* function start or end */
8179 case N_FUN:
8180 if (sym->n_strx == 0) {
8181 /* we test if between last line and end of function */
8182 pc = sym->n_value + func_addr;
8183 if (wanted_pc >= last_pc && wanted_pc < pc)
8184 goto found;
8185 func_name[0] = '\0';
8186 func_addr = 0;
8187 } else {
8188 str = stabstr_section->data + sym->n_strx;
8189 p = strchr(str, ':');
8190 if (!p) {
8191 pstrcpy(func_name, sizeof(func_name), str);
8192 } else {
8193 len = p - str;
8194 if (len > sizeof(func_name) - 1)
8195 len = sizeof(func_name) - 1;
8196 memcpy(func_name, str, len);
8197 func_name[len] = '\0';
8199 func_addr = sym->n_value;
8201 break;
8202 /* line number info */
8203 case N_SLINE:
8204 pc = sym->n_value + func_addr;
8205 if (wanted_pc >= last_pc && wanted_pc < pc)
8206 goto found;
8207 last_pc = pc;
8208 last_line_num = sym->n_desc;
8209 /* XXX: slow! */
8210 strcpy(last_func_name, func_name);
8211 break;
8212 /* include files */
8213 case N_BINCL:
8214 str = stabstr_section->data + sym->n_strx;
8215 add_incl:
8216 if (incl_index < INCLUDE_STACK_SIZE) {
8217 incl_files[incl_index++] = str;
8219 break;
8220 case N_EINCL:
8221 if (incl_index > 1)
8222 incl_index--;
8223 break;
8224 case N_SO:
8225 if (sym->n_strx == 0) {
8226 incl_index = 0; /* end of translation unit */
8227 } else {
8228 str = stabstr_section->data + sym->n_strx;
8229 /* do not add path */
8230 len = strlen(str);
8231 if (len > 0 && str[len - 1] != '/')
8232 goto add_incl;
8234 break;
8236 sym++;
8239 /* second pass: we try symtab symbols (no line number info) */
8240 incl_index = 0;
8242 Elf32_Sym *sym, *sym_end;
8243 int type;
8245 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
8246 for(sym = (Elf32_Sym *)symtab_section->data + 1;
8247 sym < sym_end;
8248 sym++) {
8249 type = ELF32_ST_TYPE(sym->st_info);
8250 if (type == STT_FUNC) {
8251 if (wanted_pc >= sym->st_value &&
8252 wanted_pc < sym->st_value + sym->st_size) {
8253 pstrcpy(last_func_name, sizeof(last_func_name),
8254 strtab_section->data + sym->st_name);
8255 goto found;
8260 /* did not find any info: */
8261 fprintf(stderr, " ???\n");
8262 return;
8263 found:
8264 if (last_func_name[0] != '\0') {
8265 fprintf(stderr, " %s()", last_func_name);
8267 if (incl_index > 0) {
8268 fprintf(stderr, " (%s:%d",
8269 incl_files[incl_index - 1], last_line_num);
8270 for(i = incl_index - 2; i >= 0; i--)
8271 fprintf(stderr, ", included from %s", incl_files[i]);
8272 fprintf(stderr, ")");
8274 fprintf(stderr, "\n");
8277 #ifndef WIN32
8279 #ifdef __i386__
8281 #ifndef EIP
8282 #define EIP 14
8283 #define EBP 6
8284 #endif
8286 /* return the PC at frame level 'level'. Return non zero if not found */
8287 static int rt_get_caller_pc(unsigned long *paddr,
8288 struct ucontext *uc, int level)
8290 unsigned long fp;
8291 int i;
8293 if (level == 0) {
8294 *paddr = uc->uc_mcontext.gregs[EIP];
8295 return 0;
8296 } else {
8297 fp = uc->uc_mcontext.gregs[EBP];
8298 for(i=1;i<level;i++) {
8299 /* XXX: check address validity with program info */
8300 if (fp <= 0x1000 || fp >= 0xc0000000)
8301 return -1;
8302 fp = ((unsigned long *)fp)[0];
8304 *paddr = ((unsigned long *)fp)[1];
8305 return 0;
8308 #else
8309 #error add arch specific rt_get_caller_pc()
8310 #endif
8312 /* emit a run time error at position 'pc' */
8313 void rt_error(struct ucontext *uc, const char *fmt, ...)
8315 va_list ap;
8316 unsigned long pc;
8317 int i;
8319 va_start(ap, fmt);
8320 fprintf(stderr, "Runtime error: ");
8321 vfprintf(stderr, fmt, ap);
8322 fprintf(stderr, "\n");
8323 for(i=0;i<num_callers;i++) {
8324 if (rt_get_caller_pc(&pc, uc, i) < 0)
8325 break;
8326 if (i == 0)
8327 fprintf(stderr, "at ");
8328 else
8329 fprintf(stderr, "by ");
8330 rt_printline(pc);
8332 exit(255);
8333 va_end(ap);
8336 /* signal handler for fatal errors */
8337 static void sig_error(int signum, siginfo_t *siginf, void *puc)
8339 struct ucontext *uc = puc;
8341 switch(signum) {
8342 case SIGFPE:
8343 switch(siginf->si_code) {
8344 case FPE_INTDIV:
8345 case FPE_FLTDIV:
8346 rt_error(uc, "division by zero");
8347 break;
8348 default:
8349 rt_error(uc, "floating point exception");
8350 break;
8352 break;
8353 case SIGBUS:
8354 case SIGSEGV:
8355 if (rt_bound_error_msg && *rt_bound_error_msg)
8356 rt_error(uc, *rt_bound_error_msg);
8357 else
8358 rt_error(uc, "dereferencing invalid pointer");
8359 break;
8360 case SIGILL:
8361 rt_error(uc, "illegal instruction");
8362 break;
8363 case SIGABRT:
8364 rt_error(uc, "abort() called");
8365 break;
8366 default:
8367 rt_error(uc, "caught signal %d", signum);
8368 break;
8370 exit(255);
8372 #endif
8374 /* do all relocations (needed before using tcc_get_symbol()) */
8375 int tcc_relocate(TCCState *s1)
8377 Section *s;
8378 int i;
8380 s1->nb_errors = 0;
8382 tcc_add_runtime(s1);
8384 relocate_common_syms();
8386 /* compute relocation address : section are relocated in place. We
8387 also alloc the bss space */
8388 for(i = 1; i < s1->nb_sections; i++) {
8389 s = s1->sections[i];
8390 if (s->sh_flags & SHF_ALLOC) {
8391 if (s->sh_type == SHT_NOBITS)
8392 s->data = tcc_mallocz(s->data_offset);
8393 s->sh_addr = (unsigned long)s->data;
8397 relocate_syms(s1, 1);
8399 if (s1->nb_errors != 0)
8400 return -1;
8402 /* relocate each section */
8403 for(i = 1; i < s1->nb_sections; i++) {
8404 s = s1->sections[i];
8405 if (s->reloc)
8406 relocate_section(s1, s);
8408 return 0;
8411 /* launch the compiled program with the given arguments */
8412 int tcc_run(TCCState *s1, int argc, char **argv)
8414 int (*prog_main)(int, char **);
8416 if (tcc_relocate(s1) < 0)
8417 return -1;
8419 prog_main = tcc_get_symbol(s1, "main");
8421 if (do_debug) {
8422 #ifdef WIN32
8423 error("debug mode currently not available for Windows");
8424 #else
8425 struct sigaction sigact;
8426 /* install TCC signal handlers to print debug info on fatal
8427 runtime errors */
8428 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
8429 sigact.sa_sigaction = sig_error;
8430 sigemptyset(&sigact.sa_mask);
8431 sigaction(SIGFPE, &sigact, NULL);
8432 sigaction(SIGILL, &sigact, NULL);
8433 sigaction(SIGSEGV, &sigact, NULL);
8434 sigaction(SIGBUS, &sigact, NULL);
8435 sigaction(SIGABRT, &sigact, NULL);
8436 #endif
8439 #ifdef CONFIG_TCC_BCHECK
8440 if (do_bounds_check) {
8441 void (*bound_init)(void);
8443 /* set error function */
8444 rt_bound_error_msg = (void *)tcc_get_symbol(s1, "__bound_error_msg");
8446 /* XXX: use .init section so that it also work in binary ? */
8447 bound_init = (void *)tcc_get_symbol(s1, "__bound_init");
8448 bound_init();
8450 #endif
8451 return (*prog_main)(argc, argv);
8454 TCCState *tcc_new(void)
8456 const char *p, *r;
8457 TCCState *s;
8459 s = tcc_mallocz(sizeof(TCCState));
8460 if (!s)
8461 return NULL;
8462 tcc_state = s;
8463 s->output_type = TCC_OUTPUT_MEMORY;
8465 /* default include paths */
8466 tcc_add_sysinclude_path(s, "/usr/local/include");
8467 tcc_add_sysinclude_path(s, "/usr/include");
8468 tcc_add_sysinclude_path(s, CONFIG_TCC_PREFIX "/lib/tcc/include");
8470 /* add all tokens */
8471 table_ident = NULL;
8472 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
8474 tok_ident = TOK_IDENT;
8475 p = tcc_keywords;
8476 while (*p) {
8477 r = p;
8478 while (*r++);
8479 tok_alloc(p, r - p - 1);
8480 p = r;
8483 /* we add dummy defines for some special macros to speed up tests
8484 and to have working defined() */
8485 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
8486 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
8487 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
8488 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
8490 /* standard defines */
8491 tcc_define_symbol(s, "__STDC__", NULL);
8492 #if defined(TCC_TARGET_I386)
8493 tcc_define_symbol(s, "__i386__", NULL);
8494 #endif
8495 #if defined(linux)
8496 tcc_define_symbol(s, "linux", NULL);
8497 #endif
8498 /* tiny C specific defines */
8499 tcc_define_symbol(s, "__TINYC__", NULL);
8501 /* default library paths */
8502 tcc_add_library_path(s, "/usr/local/lib");
8503 tcc_add_library_path(s, "/usr/lib");
8504 tcc_add_library_path(s, "/lib");
8506 /* no section zero */
8507 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
8509 /* create standard sections */
8510 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
8511 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
8512 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
8514 /* symbols are always generated for linking stage */
8515 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
8516 ".strtab",
8517 ".hashtab", SHF_PRIVATE);
8518 strtab_section = symtab_section->link;
8520 /* private symbol table for dynamic symbols */
8521 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
8522 ".dynstrtab",
8523 ".dynhashtab", SHF_PRIVATE);
8524 return s;
8527 void tcc_delete(TCCState *s1)
8529 int i, n;
8531 /* free -D defines */
8532 free_defines(NULL);
8534 /* free tokens */
8535 n = tok_ident - TOK_IDENT;
8536 for(i = 0; i < n; i++)
8537 tcc_free(table_ident[i]);
8538 tcc_free(table_ident);
8540 /* free all sections */
8542 free_section(symtab_section->hash);
8544 free_section(s1->dynsymtab_section->hash);
8545 free_section(s1->dynsymtab_section->link);
8546 free_section(s1->dynsymtab_section);
8548 for(i = 1; i < s1->nb_sections; i++)
8549 free_section(s1->sections[i]);
8550 tcc_free(s1->sections);
8552 /* free loaded dlls array */
8553 for(i = 0; i < s1->nb_loaded_dlls; i++)
8554 tcc_free(s1->loaded_dlls[i]);
8555 tcc_free(s1->loaded_dlls);
8557 /* library paths */
8558 for(i = 0; i < s1->nb_library_paths; i++)
8559 tcc_free(s1->library_paths[i]);
8560 tcc_free(s1->library_paths);
8562 /* cached includes */
8563 for(i = 0; i < s1->nb_cached_includes; i++)
8564 tcc_free(s1->cached_includes[i]);
8565 tcc_free(s1->cached_includes);
8567 for(i = 0; i < s1->nb_include_paths; i++)
8568 tcc_free(s1->include_paths[i]);
8569 tcc_free(s1->include_paths);
8571 for(i = 0; i < s1->nb_sysinclude_paths; i++)
8572 tcc_free(s1->sysinclude_paths[i]);
8573 tcc_free(s1->sysinclude_paths);
8575 tcc_free(s1);
8578 int tcc_add_include_path(TCCState *s1, const char *pathname)
8580 char *pathname1;
8582 pathname1 = tcc_strdup(pathname);
8583 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
8584 return 0;
8587 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
8589 char *pathname1;
8591 pathname1 = tcc_strdup(pathname);
8592 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
8593 return 0;
8596 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
8598 const char *ext;
8599 Elf32_Ehdr ehdr;
8600 int fd, ret;
8601 BufferedFile *saved_file;
8603 /* find source file type with extension */
8604 ext = strrchr(filename, '.');
8605 if (ext)
8606 ext++;
8608 /* open the file */
8609 saved_file = file;
8610 file = tcc_open(s1, filename);
8611 if (!file) {
8612 if (flags & AFF_PRINT_ERROR) {
8613 error_noabort("file '%s' not found", filename);
8615 ret = -1;
8616 goto fail1;
8619 if (!ext || !strcmp(ext, "c")) {
8620 /* C file assumed */
8621 ret = tcc_compile(s1);
8622 } else {
8623 fd = file->fd;
8624 /* assume executable format: auto guess file type */
8625 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
8626 error_noabort("could not read header");
8627 goto fail;
8629 lseek(fd, 0, SEEK_SET);
8631 if (ehdr.e_ident[0] == ELFMAG0 &&
8632 ehdr.e_ident[1] == ELFMAG1 &&
8633 ehdr.e_ident[2] == ELFMAG2 &&
8634 ehdr.e_ident[3] == ELFMAG3) {
8635 file->line_num = 0; /* do not display line number if error */
8636 if (ehdr.e_type == ET_REL) {
8637 ret = tcc_load_object_file(s1, fd, 0);
8638 } else if (ehdr.e_type == ET_DYN) {
8639 ret = tcc_load_dll(s1, fd, filename,
8640 (flags & AFF_REFERENCED_DLL) != 0);
8641 } else {
8642 error_noabort("unrecognized ELF file");
8643 goto fail;
8645 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
8646 file->line_num = 0; /* do not display line number if error */
8647 ret = tcc_load_archive(s1, fd);
8648 } else {
8649 /* as GNU ld, consider it is an ld script if not recognized */
8650 ret = tcc_load_ldscript(s1);
8651 if (ret < 0) {
8652 error_noabort("unrecognized file type");
8653 goto fail;
8657 the_end:
8658 tcc_close(file);
8659 fail1:
8660 file = saved_file;
8661 return ret;
8662 fail:
8663 ret = -1;
8664 goto the_end;
8667 int tcc_add_file(TCCState *s, const char *filename)
8669 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
8672 int tcc_add_library_path(TCCState *s, const char *pathname)
8674 char *pathname1;
8676 pathname1 = tcc_strdup(pathname);
8677 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
8678 return 0;
8681 /* find and load a dll. Return non zero if not found */
8682 /* XXX: add '-rpath' option support ? */
8683 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
8685 char buf[1024];
8686 int i;
8688 for(i = 0; i < s->nb_library_paths; i++) {
8689 snprintf(buf, sizeof(buf), "%s/%s",
8690 s->library_paths[i], filename);
8691 if (tcc_add_file_internal(s, buf, flags) == 0)
8692 return 0;
8694 return -1;
8697 /* the library name is the same as the argument of the '-l' option */
8698 int tcc_add_library(TCCState *s, const char *libraryname)
8700 char buf[1024];
8701 int i;
8702 void *h;
8704 /* first we look for the dynamic library if not static linking */
8705 if (!s->static_link) {
8706 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
8707 /* if we output to memory, then we simply we dlopen(). */
8708 if (s->output_type == TCC_OUTPUT_MEMORY) {
8709 /* Since the libc is already loaded, we don't need to load it again */
8710 if (!strcmp(libraryname, "c"))
8711 return 0;
8712 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
8713 if (h)
8714 return 0;
8715 } else {
8716 if (tcc_add_dll(s, buf, 0) == 0)
8717 return 0;
8721 /* then we look for the static library */
8722 for(i = 0; i < s->nb_library_paths; i++) {
8723 snprintf(buf, sizeof(buf), "%s/lib%s.a",
8724 s->library_paths[i], libraryname);
8725 if (tcc_add_file_internal(s, buf, 0) == 0)
8726 return 0;
8728 return -1;
8731 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
8733 add_elf_sym(symtab_section, val, 0,
8734 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
8735 SHN_ABS, name);
8736 return 0;
8739 int tcc_set_output_type(TCCState *s, int output_type)
8741 s->output_type = output_type;
8743 /* if bound checking, then add corresponding sections */
8744 #ifdef CONFIG_TCC_BCHECK
8745 if (do_bounds_check) {
8746 /* define symbol */
8747 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
8748 /* create bounds sections */
8749 bounds_section = new_section(s, ".bounds",
8750 SHT_PROGBITS, SHF_ALLOC);
8751 lbounds_section = new_section(s, ".lbounds",
8752 SHT_PROGBITS, SHF_ALLOC);
8754 #endif
8756 /* add debug sections */
8757 if (do_debug) {
8758 /* stab symbols */
8759 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
8760 stab_section->sh_entsize = sizeof(Stab_Sym);
8761 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
8762 put_elf_str(stabstr_section, "");
8763 stab_section->link = stabstr_section;
8764 /* put first entry */
8765 put_stabs("", 0, 0, 0, 0);
8768 /* add libc crt1/crti objects */
8769 if (output_type == TCC_OUTPUT_EXE ||
8770 output_type == TCC_OUTPUT_DLL) {
8771 if (output_type != TCC_OUTPUT_DLL)
8772 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
8773 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
8775 return 0;
8778 #if !defined(LIBTCC)
8780 static int64_t getclock_us(void)
8782 #ifdef WIN32
8783 struct _timeb tb;
8784 _ftime(&tb);
8785 return (tb.time * 1000LL + tb.millitm) * 1000LL;
8786 #else
8787 struct timeval tv;
8788 gettimeofday(&tv, NULL);
8789 return tv.tv_sec * 1000000LL + tv.tv_usec;
8790 #endif
8793 void help(void)
8795 printf("tcc version 0.9.13 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
8796 "usage: tcc [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
8797 " [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
8798 " [--] infile1 [infile2... --] [infile_args...]\n"
8799 "\n"
8800 "General options:\n"
8801 " -c compile only - generate an object file\n"
8802 " -o outfile set output filename\n"
8803 " -- allows multiples input files if no -o option given. Also\n"
8804 " separate input files from runtime arguments\n"
8805 " -Bdir set tcc internal library path\n"
8806 " -bench output compilation statistics\n"
8807 "Preprocessor options:\n"
8808 " -Idir add include path 'dir'\n"
8809 " -Dsym[=val] define 'sym' with value 'val'\n"
8810 " -Usym undefine 'sym'\n"
8811 "Linker options:\n"
8812 " -Ldir add library path 'dir'\n"
8813 " -llib link with dynamic or static library 'lib'\n"
8814 " -shared generate a shared library\n"
8815 " -static static linking\n"
8816 " -r relocatable output\n"
8817 "Debugger options:\n"
8818 " -g generate runtime debug info\n"
8819 #ifdef CONFIG_TCC_BCHECK
8820 " -b compile with built-in memory and bounds checker (implies -g)\n"
8821 #endif
8822 " -bt N show N callers in stack traces\n"
8826 int main(int argc, char **argv)
8828 char *r, *outfile;
8829 int optind, output_type, multiple_files, i, reloc_output;
8830 TCCState *s;
8831 char **files;
8832 int nb_files, nb_libraries, nb_objfiles, dminus, ret;
8833 char objfilename[1024];
8834 int64_t start_time = 0;
8836 s = tcc_new();
8837 output_type = TCC_OUTPUT_MEMORY;
8839 optind = 1;
8840 outfile = NULL;
8841 multiple_files = 0;
8842 dminus = 0;
8843 files = NULL;
8844 nb_files = 0;
8845 nb_libraries = 0;
8846 reloc_output = 0;
8847 while (1) {
8848 if (optind >= argc) {
8849 if (nb_files == 0)
8850 goto show_help;
8851 else
8852 break;
8854 r = argv[optind++];
8855 if (r[0] != '-') {
8856 /* add a new file */
8857 dynarray_add((void ***)&files, &nb_files, r);
8858 if (!multiple_files) {
8859 optind--;
8860 /* argv[0] will be this file */
8861 break;
8863 } else if (r[1] == '-') {
8864 /* '--' enables multiple files input and also ends several file input */
8865 if (dminus && multiple_files) {
8866 optind--; /* argv[0] will be '--' */
8867 break;
8869 dminus = 1;
8870 multiple_files = 1;
8871 } else if (r[1] == 'h' || r[1] == '?') {
8872 show_help:
8873 help();
8874 return 1;
8875 } else if (r[1] == 'I') {
8876 if (tcc_add_include_path(s, r + 2) < 0)
8877 error("too many include paths");
8878 } else if (r[1] == 'D') {
8879 char *sym, *value;
8880 sym = r + 2;
8881 value = strchr(sym, '=');
8882 if (value) {
8883 *value = '\0';
8884 value++;
8886 tcc_define_symbol(s, sym, value);
8887 } else if (r[1] == 'U') {
8888 tcc_undefine_symbol(s, r + 2);
8889 } else if (r[1] == 'L') {
8890 tcc_add_library_path(s, r + 2);
8891 } else if (r[1] == 'B') {
8892 /* set tcc utilities path (mainly for tcc development) */
8893 tcc_lib_path = r + 2;
8894 } else if (r[1] == 'l') {
8895 dynarray_add((void ***)&files, &nb_files, r);
8896 nb_libraries++;
8897 } else if (!strcmp(r + 1, "bench")) {
8898 do_bench = 1;
8899 } else if (!strcmp(r + 1, "bt")) {
8900 num_callers = atoi(argv[optind++]);
8901 } else
8902 #ifdef CONFIG_TCC_BCHECK
8903 if (r[1] == 'b') {
8904 do_bounds_check = 1;
8905 do_debug = 1;
8906 } else
8907 #endif
8908 if (r[1] == 'g') {
8909 do_debug = 1;
8910 } else if (r[1] == 'c') {
8911 multiple_files = 1;
8912 output_type = TCC_OUTPUT_OBJ;
8913 } else if (!strcmp(r + 1, "static")) {
8914 s->static_link = 1;
8915 } else if (!strcmp(r + 1, "shared")) {
8916 output_type = TCC_OUTPUT_DLL;
8917 } else if (r[1] == 'o') {
8918 if (optind >= argc)
8919 goto show_help;
8920 multiple_files = 1;
8921 outfile = argv[optind++];
8922 } else if (r[1] == 'r') {
8923 /* generate a .o merging several output files */
8924 reloc_output = 1;
8925 output_type = TCC_OUTPUT_OBJ;
8926 } else if (r[1] == 'W' || r[1] == 'O' || r[1] == 'm' || r[1] == 'f') {
8927 /* ignore those options to be a drop-in replacement for gcc */
8928 } else {
8929 error("invalid option -- '%s'", r);
8933 nb_objfiles = nb_files - nb_libraries;
8935 /* if outfile provided without other options, we output an
8936 executable */
8937 if (outfile && output_type == TCC_OUTPUT_MEMORY)
8938 output_type = TCC_OUTPUT_EXE;
8940 /* check -c consistency : only single file handled. XXX: checks file type */
8941 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
8942 /* accepts only a single input file */
8943 if (nb_objfiles != 1)
8944 error("cannot specify multiple files with -c");
8945 if (nb_libraries != 0)
8946 error("cannot specify libraries with -c");
8949 /* compute default outfile name */
8950 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
8951 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
8952 char *ext;
8953 /* add .o extension */
8954 pstrcpy(objfilename, sizeof(objfilename) - 1, files[0]);
8955 ext = strrchr(objfilename, '.');
8956 if (!ext)
8957 goto default_outfile;
8958 strcpy(ext + 1, "o");
8959 } else {
8960 default_outfile:
8961 pstrcpy(objfilename, sizeof(objfilename), "a.out");
8963 outfile = objfilename;
8966 if (do_bench) {
8967 start_time = getclock_us();
8970 tcc_set_output_type(s, output_type);
8972 /* compile or add each files or library */
8973 for(i = 0;i < nb_files; i++) {
8974 const char *filename;
8976 filename = files[i];
8977 if (filename[0] == '-') {
8978 if (tcc_add_library(s, filename + 2) < 0)
8979 error("cannot find %s", filename);
8980 } else {
8981 if (tcc_add_file(s, filename) < 0) {
8982 ret = 1;
8983 goto the_end;
8988 /* free all files */
8989 tcc_free(files);
8991 if (do_bench) {
8992 double total_time;
8993 total_time = (double)(getclock_us() - start_time) / 1000000.0;
8994 if (total_time < 0.001)
8995 total_time = 0.001;
8996 if (total_bytes < 1)
8997 total_bytes = 1;
8998 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
8999 tok_ident - TOK_IDENT, total_lines, total_bytes,
9000 total_time, (int)(total_lines / total_time),
9001 total_bytes / total_time / 1000000.0);
9004 if (s->output_type != TCC_OUTPUT_MEMORY) {
9005 tcc_output_file(s, outfile);
9006 ret = 0;
9007 } else {
9008 ret = tcc_run(s, argc - optind, argv + optind);
9010 the_end:
9011 /* XXX: cannot do it with bound checking because of the malloc hooks */
9012 if (!do_bounds_check)
9013 tcc_delete(s);
9015 #ifdef MEM_DEBUG
9016 if (do_bench) {
9017 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
9019 #endif
9020 return ret;
9023 #endif