const warning test
[tinycc.git] / tcc.c
blob16920eb1e8a35836299d2abdd9f016a1a301c5ef
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define _GNU_SOURCE
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <math.h>
29 #include <unistd.h>
30 #include <signal.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <setjmp.h>
34 #include <time.h>
35 #ifdef WIN32
36 #include <sys/timeb.h>
37 #endif
38 #ifndef WIN32
39 #include <sys/time.h>
40 #include <sys/ucontext.h>
41 #endif
42 #include "elf.h"
43 #include "stab.h"
44 #ifndef CONFIG_TCC_STATIC
45 #include <dlfcn.h>
46 #endif
48 #include "libtcc.h"
50 /* parser debug */
51 //#define PARSE_DEBUG
52 /* preprocessor debug */
53 //#define PP_DEBUG
54 /* include file debug */
55 //#define INC_DEBUG
57 //#define MEM_DEBUG
59 /* assembler debug */
60 //#define ASM_DEBUG
62 /* target selection */
63 //#define TCC_TARGET_I386 /* i386 code generator */
65 /* default target is I386 */
66 #if !defined(TCC_TARGET_I386)
67 #define TCC_TARGET_I386
68 #endif
70 #if !defined(WIN32) && !defined(TCC_UCLIBC)
71 #define CONFIG_TCC_BCHECK /* enable bound checking code */
72 #endif
74 /* define it to include assembler support */
75 #define CONFIG_TCC_ASM
77 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
78 executables or dlls */
79 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
81 #define INCLUDE_STACK_SIZE 32
82 #define IFDEF_STACK_SIZE 64
83 #define VSTACK_SIZE 64
84 #define STRING_MAX_SIZE 1024
86 #define TOK_HASH_SIZE 2048 /* must be a power of two */
87 #define TOK_ALLOC_INCR 512 /* must be a power of two */
88 #define TOK_STR_ALLOC_INCR_BITS 6
89 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
90 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
92 /* token symbol management */
93 typedef struct TokenSym {
94 struct TokenSym *hash_next;
95 struct Sym *sym_define; /* direct pointer to define */
96 struct Sym *sym_label; /* direct pointer to label */
97 struct Sym *sym_struct; /* direct pointer to structure */
98 struct Sym *sym_identifier; /* direct pointer to identifier */
99 int tok; /* token number */
100 int len;
101 char str[1];
102 } TokenSym;
104 typedef struct CString {
105 int size; /* size in bytes */
106 void *data; /* either 'char *' or 'int *' */
107 int size_allocated;
108 void *data_allocated; /* if non NULL, data has been malloced */
109 } CString;
111 /* type definition */
112 typedef struct CType {
113 int t;
114 struct Sym *ref;
115 } CType;
117 /* constant value */
118 typedef union CValue {
119 long double ld;
120 double d;
121 float f;
122 int i;
123 unsigned int ui;
124 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
125 long long ll;
126 unsigned long long ull;
127 struct CString *cstr;
128 void *ptr;
129 int tab[1];
130 } CValue;
132 /* value on stack */
133 typedef struct SValue {
134 CType type; /* type */
135 unsigned short r; /* register + flags */
136 unsigned short r2; /* second register, used for 'long long'
137 type. If not used, set to VT_CONST */
138 CValue c; /* constant, if VT_CONST */
139 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
140 } SValue;
142 /* symbol management */
143 typedef struct Sym {
144 int v; /* symbol token */
145 int r; /* associated register */
146 int c; /* associated number */
147 CType type; /* associated type */
148 struct Sym *next; /* next related symbol */
149 struct Sym *prev; /* prev symbol in stack */
150 struct Sym *prev_tok; /* previous symbol for this token */
151 } Sym;
153 /* section definition */
154 /* XXX: use directly ELF structure for parameters ? */
155 /* special flag to indicate that the section should not be linked to
156 the other ones */
157 #define SHF_PRIVATE 0x80000000
159 typedef struct Section {
160 unsigned long data_offset; /* current data offset */
161 unsigned char *data; /* section data */
162 unsigned long data_allocated; /* used for realloc() handling */
163 int sh_name; /* elf section name (only used during output) */
164 int sh_num; /* elf section number */
165 int sh_type; /* elf section type */
166 int sh_flags; /* elf section flags */
167 int sh_info; /* elf section info */
168 int sh_addralign; /* elf section alignment */
169 int sh_entsize; /* elf entry size */
170 unsigned long sh_size; /* section size (only used during output) */
171 unsigned long sh_addr; /* address at which the section is relocated */
172 unsigned long sh_offset; /* address at which the section is relocated */
173 int nb_hashed_syms; /* used to resize the hash table */
174 struct Section *link; /* link to another section */
175 struct Section *reloc; /* corresponding section for relocation, if any */
176 struct Section *hash; /* hash table for symbols */
177 struct Section *next;
178 char name[64]; /* section name */
179 } Section;
181 typedef struct DLLReference {
182 int level;
183 char name[1];
184 } DLLReference;
186 /* GNUC attribute definition */
187 typedef struct AttributeDef {
188 int aligned;
189 Section *section;
190 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
191 } AttributeDef;
193 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
194 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
195 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
197 /* stored in 'Sym.c' field */
198 #define FUNC_NEW 1 /* ansi function prototype */
199 #define FUNC_OLD 2 /* old function prototype */
200 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
202 /* stored in 'Sym.r' field */
203 #define FUNC_CDECL 0 /* standard c call */
204 #define FUNC_STDCALL 1 /* pascal c call */
206 /* field 'Sym.t' for macros */
207 #define MACRO_OBJ 0 /* object like macro */
208 #define MACRO_FUNC 1 /* function like macro */
210 /* field 'Sym.r' for C labels */
211 #define LABEL_DEFINED 0 /* label is defined */
212 #define LABEL_FORWARD 1 /* label is forward defined */
213 #define LABEL_DECLARED 2 /* label is declared but never used */
215 /* type_decl() types */
216 #define TYPE_ABSTRACT 1 /* type without variable */
217 #define TYPE_DIRECT 2 /* type with variable */
219 #define IO_BUF_SIZE 8192
221 typedef struct BufferedFile {
222 uint8_t *buf_ptr;
223 uint8_t *buf_end;
224 int fd;
225 int line_num; /* current line number - here to simplify code */
226 int ifndef_macro; /* #ifndef macro / #endif search */
227 int ifndef_macro_saved; /* saved ifndef_macro */
228 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
229 char inc_type; /* type of include */
230 char inc_filename[512]; /* filename specified by the user */
231 char filename[1024]; /* current filename - here to simplify code */
232 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
233 } BufferedFile;
235 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
236 #define CH_EOF (-1) /* end of file */
238 /* parsing state (used to save parser state to reparse part of the
239 source several times) */
240 typedef struct ParseState {
241 int *macro_ptr;
242 int line_num;
243 int tok;
244 CValue tokc;
245 } ParseState;
247 /* used to record tokens */
248 typedef struct TokenString {
249 int *str;
250 int len;
251 int allocated_len;
252 int last_line_num;
253 } TokenString;
255 /* include file cache, used to find files faster and also to eliminate
256 inclusion if the include file is protected by #ifndef ... #endif */
257 typedef struct CachedInclude {
258 int ifndef_macro;
259 char type; /* '"' or '>' to give include type */
260 char filename[1]; /* path specified in #include */
261 } CachedInclude;
263 /* parser */
264 static struct BufferedFile *file;
265 static int ch, tok;
266 static CValue tokc;
267 static CString tokcstr; /* current parsed string, if any */
268 /* additional informations about token */
269 static int tok_flags;
270 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
271 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
272 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
274 static int *macro_ptr, *macro_ptr_allocated;
275 static int *unget_saved_macro_ptr;
276 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
277 static int unget_buffer_enabled;
278 static int parse_flags;
279 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
280 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
281 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
282 token. line feed is also
283 returned at eof */
285 static Section *text_section, *data_section, *bss_section; /* predefined sections */
286 static Section *cur_text_section; /* current section where function code is
287 generated */
288 /* bound check related sections */
289 static Section *bounds_section; /* contains global data bound description */
290 static Section *lbounds_section; /* contains local data bound description */
291 /* symbol sections */
292 static Section *symtab_section, *strtab_section;
294 /* debug sections */
295 static Section *stab_section, *stabstr_section;
297 /* loc : local variable index
298 ind : output code index
299 rsym: return symbol
300 anon_sym: anonymous symbol index
302 static int rsym, anon_sym, ind, loc;
303 /* expression generation modifiers */
304 static int const_wanted; /* true if constant wanted */
305 static int nocode_wanted; /* true if no code generation wanted for an expression */
306 static int global_expr; /* true if compound literals must be allocated
307 globally (used during initializers parsing */
308 static CType func_vt; /* current function return type (used by return
309 instruction) */
310 static int func_vc;
311 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
312 static int tok_ident;
313 static TokenSym **table_ident;
314 static TokenSym *hash_ident[TOK_HASH_SIZE];
315 static char token_buf[STRING_MAX_SIZE + 1];
316 static char *funcname;
317 static Sym *global_stack, *local_stack;
318 static Sym *define_stack;
319 static Sym *global_label_stack, *local_label_stack;
321 static SValue vstack[VSTACK_SIZE], *vtop;
322 /* some predefined types */
323 static CType char_pointer_type, func_old_type, int_type;
324 /* true if isid(c) || isnum(c) */
325 static unsigned char isidnum_table[256];
327 /* compile with debug symbol (and use them if error during execution) */
328 static int do_debug = 0;
330 /* compile with built-in memory and bounds checker */
331 static int do_bounds_check = 0;
333 /* display benchmark infos */
334 #if !defined(LIBTCC)
335 static int do_bench = 0;
336 #endif
337 static int total_lines;
338 static int total_bytes;
340 /* use GNU C extensions */
341 static int gnu_ext = 1;
343 /* use Tiny C extensions */
344 static int tcc_ext = 1;
346 /* max number of callers shown if error */
347 static int num_callers = 6;
348 static const char **rt_bound_error_msg;
350 /* XXX: get rid of this ASAP */
351 static struct TCCState *tcc_state;
353 /* give the path of the tcc libraries */
354 static const char *tcc_lib_path = CONFIG_TCC_LIBDIR "/tcc";
356 struct TCCState {
357 int output_type;
359 BufferedFile **include_stack_ptr;
360 int *ifdef_stack_ptr;
362 /* include file handling */
363 char **include_paths;
364 int nb_include_paths;
365 char **sysinclude_paths;
366 int nb_sysinclude_paths;
367 CachedInclude **cached_includes;
368 int nb_cached_includes;
370 char **library_paths;
371 int nb_library_paths;
373 /* array of all loaded dlls (including those referenced by loaded
374 dlls) */
375 DLLReference **loaded_dlls;
376 int nb_loaded_dlls;
378 /* sections */
379 Section **sections;
380 int nb_sections; /* number of sections, including first dummy section */
382 /* got handling */
383 Section *got;
384 Section *plt;
385 unsigned long *got_offsets;
386 int nb_got_offsets;
387 /* give the correspondance from symtab indexes to dynsym indexes */
388 int *symtab_to_dynsym;
390 /* temporary dynamic symbol sections (for dll loading) */
391 Section *dynsymtab_section;
392 /* exported dynamic symbol section */
393 Section *dynsym;
395 int nostdinc; /* if true, no standard headers are added */
396 int nostdlib; /* if true, no standard libraries are added */
398 /* if true, static linking is performed */
399 int static_link;
401 /* if true, all symbols are exported */
402 int rdynamic;
404 /* if true, only link in referenced objects from archive */
405 int alacarte_link;
407 /* warning switches */
408 int warn_write_strings;
409 int warn_unsupported;
410 int warn_error;
412 /* error handling */
413 void *error_opaque;
414 void (*error_func)(void *opaque, const char *msg);
415 int error_set_jmp_enabled;
416 jmp_buf error_jmp_buf;
417 int nb_errors;
419 /* tiny assembler state */
420 Sym *asm_labels;
422 /* see include_stack_ptr */
423 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
425 /* see ifdef_stack_ptr */
426 int ifdef_stack[IFDEF_STACK_SIZE];
429 /* The current value can be: */
430 #define VT_VALMASK 0x00ff
431 #define VT_CONST 0x00f0 /* constant in vc
432 (must be first non register value) */
433 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
434 #define VT_LOCAL 0x00f2 /* offset on stack */
435 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
436 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
437 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
438 #define VT_LVAL 0x0100 /* var is an lvalue */
439 #define VT_SYM 0x0200 /* a symbol value is added */
440 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
441 char/short stored in integer registers) */
442 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
443 dereferencing value */
444 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
445 bounding function call point is in vc */
446 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
447 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
448 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
449 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
451 /* types */
452 #define VT_INT 0 /* integer type */
453 #define VT_BYTE 1 /* signed byte type */
454 #define VT_SHORT 2 /* short type */
455 #define VT_VOID 3 /* void type */
456 #define VT_PTR 4 /* pointer */
457 #define VT_ENUM 5 /* enum definition */
458 #define VT_FUNC 6 /* function type */
459 #define VT_STRUCT 7 /* struct/union definition */
460 #define VT_FLOAT 8 /* IEEE float */
461 #define VT_DOUBLE 9 /* IEEE double */
462 #define VT_LDOUBLE 10 /* IEEE long double */
463 #define VT_BOOL 11 /* ISOC99 boolean type */
464 #define VT_LLONG 12 /* 64 bit integer */
465 #define VT_LONG 13 /* long integer (NEVER USED as type, only
466 during parsing) */
467 #define VT_BTYPE 0x000f /* mask for basic type */
468 #define VT_UNSIGNED 0x0010 /* unsigned type */
469 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
470 #define VT_BITFIELD 0x0040 /* bitfield modifier */
471 #define VT_CONSTANT 0x0800 /* const modifier */
472 #define VT_VOLATILE 0x1000 /* volatile modifier */
474 /* storage */
475 #define VT_EXTERN 0x00000080 /* extern definition */
476 #define VT_STATIC 0x00000100 /* static variable */
477 #define VT_TYPEDEF 0x00000200 /* typedef definition */
478 #define VT_INLINE 0x00000400 /* inline definition */
480 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
482 /* type mask (except storage) */
483 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
484 #define VT_TYPE (~(VT_STORAGE))
486 /* token values */
488 /* warning: the following compare tokens depend on i386 asm code */
489 #define TOK_ULT 0x92
490 #define TOK_UGE 0x93
491 #define TOK_EQ 0x94
492 #define TOK_NE 0x95
493 #define TOK_ULE 0x96
494 #define TOK_UGT 0x97
495 #define TOK_LT 0x9c
496 #define TOK_GE 0x9d
497 #define TOK_LE 0x9e
498 #define TOK_GT 0x9f
500 #define TOK_LAND 0xa0
501 #define TOK_LOR 0xa1
503 #define TOK_DEC 0xa2
504 #define TOK_MID 0xa3 /* inc/dec, to void constant */
505 #define TOK_INC 0xa4
506 #define TOK_UDIV 0xb0 /* unsigned division */
507 #define TOK_UMOD 0xb1 /* unsigned modulo */
508 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
509 #define TOK_CINT 0xb3 /* number in tokc */
510 #define TOK_CCHAR 0xb4 /* char constant in tokc */
511 #define TOK_STR 0xb5 /* pointer to string in tokc */
512 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
513 #define TOK_LCHAR 0xb7
514 #define TOK_LSTR 0xb8
515 #define TOK_CFLOAT 0xb9 /* float constant */
516 #define TOK_LINENUM 0xba /* line number info */
517 #define TOK_CDOUBLE 0xc0 /* double constant */
518 #define TOK_CLDOUBLE 0xc1 /* long double constant */
519 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
520 #define TOK_ADDC1 0xc3 /* add with carry generation */
521 #define TOK_ADDC2 0xc4 /* add with carry use */
522 #define TOK_SUBC1 0xc5 /* add with carry generation */
523 #define TOK_SUBC2 0xc6 /* add with carry use */
524 #define TOK_CUINT 0xc8 /* unsigned int constant */
525 #define TOK_CLLONG 0xc9 /* long long constant */
526 #define TOK_CULLONG 0xca /* unsigned long long constant */
527 #define TOK_ARROW 0xcb
528 #define TOK_DOTS 0xcc /* three dots */
529 #define TOK_SHR 0xcd /* unsigned shift right */
530 #define TOK_PPNUM 0xce /* preprocessor number */
532 #define TOK_SHL 0x01 /* shift left */
533 #define TOK_SAR 0x02 /* signed shift right */
535 /* assignement operators : normal operator or 0x80 */
536 #define TOK_A_MOD 0xa5
537 #define TOK_A_AND 0xa6
538 #define TOK_A_MUL 0xaa
539 #define TOK_A_ADD 0xab
540 #define TOK_A_SUB 0xad
541 #define TOK_A_DIV 0xaf
542 #define TOK_A_XOR 0xde
543 #define TOK_A_OR 0xfc
544 #define TOK_A_SHL 0x81
545 #define TOK_A_SAR 0x82
547 #ifndef offsetof
548 #define offsetof(type, field) ((size_t) &((type *)0)->field)
549 #endif
551 #ifndef countof
552 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
553 #endif
555 /* WARNING: the content of this string encodes token numbers */
556 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";
558 #define TOK_EOF (-1) /* end of file */
559 #define TOK_LINEFEED 10 /* line feed */
561 /* all identificators and strings have token above that */
562 #define TOK_IDENT 256
564 /* only used for i386 asm opcodes definitions */
565 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
567 #define DEF_BWL(x) \
568 DEF(TOK_ASM_ ## x ## b, #x "b") \
569 DEF(TOK_ASM_ ## x ## w, #x "w") \
570 DEF(TOK_ASM_ ## x ## l, #x "l") \
571 DEF(TOK_ASM_ ## x, #x)
573 #define DEF_WL(x) \
574 DEF(TOK_ASM_ ## x ## w, #x "w") \
575 DEF(TOK_ASM_ ## x ## l, #x "l") \
576 DEF(TOK_ASM_ ## x, #x)
578 #define DEF_FP1(x) \
579 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
580 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
581 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
582 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
584 #define DEF_FP(x) \
585 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
586 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
587 DEF_FP1(x)
589 #define DEF_ASMTEST(x) \
590 DEF_ASM(x ## o) \
591 DEF_ASM(x ## no) \
592 DEF_ASM(x ## b) \
593 DEF_ASM(x ## c) \
594 DEF_ASM(x ## nae) \
595 DEF_ASM(x ## nb) \
596 DEF_ASM(x ## nc) \
597 DEF_ASM(x ## ae) \
598 DEF_ASM(x ## e) \
599 DEF_ASM(x ## z) \
600 DEF_ASM(x ## ne) \
601 DEF_ASM(x ## nz) \
602 DEF_ASM(x ## be) \
603 DEF_ASM(x ## na) \
604 DEF_ASM(x ## nbe) \
605 DEF_ASM(x ## a) \
606 DEF_ASM(x ## s) \
607 DEF_ASM(x ## ns) \
608 DEF_ASM(x ## p) \
609 DEF_ASM(x ## pe) \
610 DEF_ASM(x ## np) \
611 DEF_ASM(x ## po) \
612 DEF_ASM(x ## l) \
613 DEF_ASM(x ## nge) \
614 DEF_ASM(x ## nl) \
615 DEF_ASM(x ## ge) \
616 DEF_ASM(x ## le) \
617 DEF_ASM(x ## ng) \
618 DEF_ASM(x ## nle) \
619 DEF_ASM(x ## g)
621 #define TOK_ASM_int TOK_INT
623 enum {
624 TOK_LAST = TOK_IDENT - 1,
625 #define DEF(id, str) id,
626 #include "tcctok.h"
627 #undef DEF
630 static const char tcc_keywords[] =
631 #define DEF(id, str) str "\0"
632 #include "tcctok.h"
633 #undef DEF
636 #define TOK_UIDENT TOK_DEFINE
638 #ifdef WIN32
639 #define snprintf _snprintf
640 #define vsnprintf _vsnprintf
641 #endif
643 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
644 /* currently incorrect */
645 long double strtold(const char *nptr, char **endptr)
647 return (long double)strtod(nptr, endptr);
649 float strtof(const char *nptr, char **endptr)
651 return (float)strtod(nptr, endptr);
653 #else
654 /* XXX: need to define this to use them in non ISOC99 context */
655 extern float strtof (const char *__nptr, char **__endptr);
656 extern long double strtold (const char *__nptr, char **__endptr);
657 #endif
659 static char *pstrcpy(char *buf, int buf_size, const char *s);
660 static char *pstrcat(char *buf, int buf_size, const char *s);
662 static void next(void);
663 static void next_nomacro(void);
664 static void parse_expr_type(CType *type);
665 static void expr_type(CType *type);
666 static void unary_type(CType *type);
667 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
668 int case_reg, int is_expr);
669 static int expr_const(void);
670 static void expr_eq(void);
671 static void gexpr(void);
672 static void decl(int l);
673 static void decl_initializer(CType *type, Section *sec, unsigned long c,
674 int first, int size_only);
675 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
676 int has_init, int v, int scope);
677 int gv(int rc);
678 void gv2(int rc1, int rc2);
679 void move_reg(int r, int s);
680 void save_regs(int n);
681 void save_reg(int r);
682 void vpop(void);
683 void vswap(void);
684 void vdup(void);
685 int get_reg(int rc);
687 static void macro_subst(TokenString *tok_str, Sym **nested_list,
688 const int *macro_str, int can_read_stream);
689 int save_reg_forced(int r);
690 void gen_op(int op);
691 void force_charshort_cast(int t);
692 static void gen_cast(CType *type);
693 void vstore(void);
694 static Sym *sym_find(int v);
695 static Sym *sym_push(int v, CType *type, int r, int c);
697 /* type handling */
698 static int type_size(CType *type, int *a);
699 static inline CType *pointed_type(CType *type);
700 static int pointed_size(CType *type);
701 static int lvalue_type(int t);
702 static int parse_btype(CType *type, AttributeDef *ad);
703 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
704 static int is_compatible_types(CType *type1, CType *type2);
706 void error(const char *fmt, ...);
707 void vpushi(int v);
708 void vset(CType *type, int r, int v);
709 void type_to_str(char *buf, int buf_size,
710 CType *type, const char *varstr);
711 char *get_tok_str(int v, CValue *cv);
712 static Sym *get_sym_ref(CType *type, Section *sec,
713 unsigned long offset, unsigned long size);
714 static Sym *external_global_sym(int v, CType *type, int r);
716 /* section generation */
717 static void section_realloc(Section *sec, unsigned long new_size);
718 static void *section_ptr_add(Section *sec, unsigned long size);
719 static void put_extern_sym(Sym *sym, Section *section,
720 unsigned long value, unsigned long size);
721 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
722 static int put_elf_str(Section *s, const char *sym);
723 static int put_elf_sym(Section *s,
724 unsigned long value, unsigned long size,
725 int info, int other, int shndx, const char *name);
726 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
727 int info, int sh_num, const char *name);
728 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
729 int type, int symbol);
730 static void put_stabs(const char *str, int type, int other, int desc,
731 unsigned long value);
732 static void put_stabs_r(const char *str, int type, int other, int desc,
733 unsigned long value, Section *sec, int sym_index);
734 static void put_stabn(int type, int other, int desc, int value);
735 static void put_stabd(int type, int other, int desc);
736 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
738 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
739 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
740 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
742 /* tccasm.c */
744 #ifdef CONFIG_TCC_ASM
746 typedef struct ExprValue {
747 uint32_t v;
748 Sym *sym;
749 } ExprValue;
751 #define MAX_ASM_OPERANDS 30
753 typedef struct ASMOperand {
754 int id; /* GCC 3 optionnal identifier (0 if number only supported */
755 char *constraint;
756 char asm_str[16]; /* computed asm string for operand */
757 SValue *vt; /* C value of the expression */
758 int ref_index; /* if >= 0, gives reference to a output constraint */
759 int priority; /* priority, used to assign registers */
760 int reg; /* if >= 0, register number used for this operand */
761 int is_llong; /* true if double register value */
762 } ASMOperand;
764 static void asm_expr(TCCState *s1, ExprValue *pe);
765 static int asm_int_expr(TCCState *s1);
766 static int find_constraint(ASMOperand *operands, int nb_operands,
767 const char *name, const char **pp);
769 static int tcc_assemble(TCCState *s1, int do_preprocess);
771 #endif
773 static void asm_instr(void);
775 /* true if float/double/long double type */
776 static inline int is_float(int t)
778 int bt;
779 bt = t & VT_BTYPE;
780 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
783 #ifdef TCC_TARGET_I386
784 #include "i386-gen.c"
785 #endif
787 #ifdef CONFIG_TCC_STATIC
789 #define RTLD_LAZY 0x001
790 #define RTLD_NOW 0x002
791 #define RTLD_GLOBAL 0x100
792 #define RTLD_DEFAULT NULL
794 /* dummy function for profiling */
795 void *dlopen(const char *filename, int flag)
797 return NULL;
800 const char *dlerror(void)
802 return "error";
805 typedef struct TCCSyms {
806 char *str;
807 void *ptr;
808 } TCCSyms;
810 #define TCCSYM(a) { #a, &a, },
812 /* add the symbol you want here if no dynamic linking is done */
813 static TCCSyms tcc_syms[] = {
814 TCCSYM(printf)
815 TCCSYM(fprintf)
816 TCCSYM(fopen)
817 TCCSYM(fclose)
818 { NULL, NULL },
821 void *dlsym(void *handle, const char *symbol)
823 TCCSyms *p;
824 p = tcc_syms;
825 while (p->str != NULL) {
826 if (!strcmp(p->str, symbol))
827 return p->ptr;
828 p++;
830 return NULL;
833 #endif
835 /********************************************************/
837 /* we use our own 'finite' function to avoid potential problems with
838 non standard math libs */
839 /* XXX: endianness dependent */
840 int ieee_finite(double d)
842 int *p = (int *)&d;
843 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
846 /* copy a string and truncate it. */
847 static char *pstrcpy(char *buf, int buf_size, const char *s)
849 char *q, *q_end;
850 int c;
852 if (buf_size > 0) {
853 q = buf;
854 q_end = buf + buf_size - 1;
855 while (q < q_end) {
856 c = *s++;
857 if (c == '\0')
858 break;
859 *q++ = c;
861 *q = '\0';
863 return buf;
866 /* strcat and truncate. */
867 static char *pstrcat(char *buf, int buf_size, const char *s)
869 int len;
870 len = strlen(buf);
871 if (len < buf_size)
872 pstrcpy(buf + len, buf_size - len, s);
873 return buf;
876 /* memory management */
877 #ifdef MEM_DEBUG
878 int mem_cur_size;
879 int mem_max_size;
880 #endif
882 static inline void tcc_free(void *ptr)
884 #ifdef MEM_DEBUG
885 mem_cur_size -= malloc_usable_size(ptr);
886 #endif
887 free(ptr);
890 static void *tcc_malloc(unsigned long size)
892 void *ptr;
893 ptr = malloc(size);
894 if (!ptr && size)
895 error("memory full");
896 #ifdef MEM_DEBUG
897 mem_cur_size += malloc_usable_size(ptr);
898 if (mem_cur_size > mem_max_size)
899 mem_max_size = mem_cur_size;
900 #endif
901 return ptr;
904 static void *tcc_mallocz(unsigned long size)
906 void *ptr;
907 ptr = tcc_malloc(size);
908 memset(ptr, 0, size);
909 return ptr;
912 static inline void *tcc_realloc(void *ptr, unsigned long size)
914 void *ptr1;
915 #ifdef MEM_DEBUG
916 mem_cur_size -= malloc_usable_size(ptr);
917 #endif
918 ptr1 = realloc(ptr, size);
919 #ifdef MEM_DEBUG
920 /* NOTE: count not correct if alloc error, but not critical */
921 mem_cur_size += malloc_usable_size(ptr1);
922 if (mem_cur_size > mem_max_size)
923 mem_max_size = mem_cur_size;
924 #endif
925 return ptr1;
928 static char *tcc_strdup(const char *str)
930 char *ptr;
931 ptr = tcc_malloc(strlen(str) + 1);
932 strcpy(ptr, str);
933 return ptr;
936 #define free(p) use_tcc_free(p)
937 #define malloc(s) use_tcc_malloc(s)
938 #define realloc(p, s) use_tcc_realloc(p, s)
940 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
942 int nb, nb_alloc;
943 void **pp;
945 nb = *nb_ptr;
946 pp = *ptab;
947 /* every power of two we double array size */
948 if ((nb & (nb - 1)) == 0) {
949 if (!nb)
950 nb_alloc = 1;
951 else
952 nb_alloc = nb * 2;
953 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
954 if (!pp)
955 error("memory full");
956 *ptab = pp;
958 pp[nb++] = data;
959 *nb_ptr = nb;
962 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
964 Section *sec;
966 sec = tcc_mallocz(sizeof(Section));
967 pstrcpy(sec->name, sizeof(sec->name), name);
968 sec->sh_type = sh_type;
969 sec->sh_flags = sh_flags;
970 switch(sh_type) {
971 case SHT_HASH:
972 case SHT_REL:
973 case SHT_DYNSYM:
974 case SHT_SYMTAB:
975 case SHT_DYNAMIC:
976 sec->sh_addralign = 4;
977 break;
978 case SHT_STRTAB:
979 sec->sh_addralign = 1;
980 break;
981 default:
982 sec->sh_addralign = 32; /* default conservative alignment */
983 break;
986 /* only add section if not private */
987 if (!(sh_flags & SHF_PRIVATE)) {
988 sec->sh_num = s1->nb_sections;
989 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
991 return sec;
994 static void free_section(Section *s)
996 tcc_free(s->data);
997 tcc_free(s);
1000 /* realloc section and set its content to zero */
1001 static void section_realloc(Section *sec, unsigned long new_size)
1003 unsigned long size;
1004 unsigned char *data;
1006 size = sec->data_allocated;
1007 if (size == 0)
1008 size = 1;
1009 while (size < new_size)
1010 size = size * 2;
1011 data = tcc_realloc(sec->data, size);
1012 if (!data)
1013 error("memory full");
1014 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1015 sec->data = data;
1016 sec->data_allocated = size;
1019 /* reserve at least 'size' bytes in section 'sec' from
1020 sec->data_offset. */
1021 static void *section_ptr_add(Section *sec, unsigned long size)
1023 unsigned long offset, offset1;
1025 offset = sec->data_offset;
1026 offset1 = offset + size;
1027 if (offset1 > sec->data_allocated)
1028 section_realloc(sec, offset1);
1029 sec->data_offset = offset1;
1030 return sec->data + offset;
1033 /* return a reference to a section, and create it if it does not
1034 exists */
1035 Section *find_section(TCCState *s1, const char *name)
1037 Section *sec;
1038 int i;
1039 for(i = 1; i < s1->nb_sections; i++) {
1040 sec = s1->sections[i];
1041 if (!strcmp(name, sec->name))
1042 return sec;
1044 /* sections are created as PROGBITS */
1045 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1048 /* update sym->c so that it points to an external symbol in section
1049 'section' with value 'value' */
1050 static void put_extern_sym(Sym *sym, Section *section,
1051 unsigned long value, unsigned long size)
1053 int sym_type, sym_bind, sh_num, info;
1054 Elf32_Sym *esym;
1055 const char *name;
1057 if (section)
1058 sh_num = section->sh_num;
1059 else
1060 sh_num = SHN_UNDEF;
1061 if (!sym->c) {
1062 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1063 sym_type = STT_FUNC;
1064 else
1065 sym_type = STT_OBJECT;
1066 if (sym->type.t & VT_STATIC)
1067 sym_bind = STB_LOCAL;
1068 else
1069 sym_bind = STB_GLOBAL;
1071 name = get_tok_str(sym->v, NULL);
1072 #ifdef CONFIG_TCC_BCHECK
1073 if (do_bounds_check) {
1074 char buf[32];
1076 /* XXX: avoid doing that for statics ? */
1077 /* if bound checking is activated, we change some function
1078 names by adding the "__bound" prefix */
1079 switch(sym->v) {
1080 #if 0
1081 /* XXX: we rely only on malloc hooks */
1082 case TOK_malloc:
1083 case TOK_free:
1084 case TOK_realloc:
1085 case TOK_memalign:
1086 case TOK_calloc:
1087 #endif
1088 case TOK_memcpy:
1089 case TOK_memmove:
1090 case TOK_memset:
1091 case TOK_strlen:
1092 case TOK_strcpy:
1093 strcpy(buf, "__bound_");
1094 strcat(buf, name);
1095 name = buf;
1096 break;
1099 #endif
1100 info = ELF32_ST_INFO(sym_bind, sym_type);
1101 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1102 } else {
1103 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1104 esym->st_value = value;
1105 esym->st_size = size;
1106 esym->st_shndx = sh_num;
1110 /* add a new relocation entry to symbol 'sym' in section 's' */
1111 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1113 if (!sym->c)
1114 put_extern_sym(sym, NULL, 0, 0);
1115 /* now we can add ELF relocation info */
1116 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1119 static inline int isid(int c)
1121 return (c >= 'a' && c <= 'z') ||
1122 (c >= 'A' && c <= 'Z') ||
1123 c == '_';
1126 static inline int isnum(int c)
1128 return c >= '0' && c <= '9';
1131 static inline int isoct(int c)
1133 return c >= '0' && c <= '7';
1136 static inline int toup(int c)
1138 if (c >= 'a' && c <= 'z')
1139 return c - 'a' + 'A';
1140 else
1141 return c;
1144 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1146 int len;
1147 len = strlen(buf);
1148 vsnprintf(buf + len, buf_size - len, fmt, ap);
1151 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1153 va_list ap;
1154 va_start(ap, fmt);
1155 strcat_vprintf(buf, buf_size, fmt, ap);
1156 va_end(ap);
1159 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1161 char buf[2048];
1162 BufferedFile **f;
1164 buf[0] = '\0';
1165 if (file) {
1166 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1167 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1168 (*f)->filename, (*f)->line_num);
1169 if (file->line_num > 0) {
1170 strcat_printf(buf, sizeof(buf),
1171 "%s:%d: ", file->filename, file->line_num);
1172 } else {
1173 strcat_printf(buf, sizeof(buf),
1174 "%s: ", file->filename);
1176 } else {
1177 strcat_printf(buf, sizeof(buf),
1178 "tcc: ");
1180 if (is_warning)
1181 strcat_printf(buf, sizeof(buf), "warning: ");
1182 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1184 if (!s1->error_func) {
1185 /* default case: stderr */
1186 fprintf(stderr, "%s\n", buf);
1187 } else {
1188 s1->error_func(s1->error_opaque, buf);
1190 if (!is_warning || s1->warn_error)
1191 s1->nb_errors++;
1194 #ifdef LIBTCC
1195 void tcc_set_error_func(TCCState *s, void *error_opaque,
1196 void (*error_func)(void *opaque, const char *msg))
1198 s->error_opaque = error_opaque;
1199 s->error_func = error_func;
1201 #endif
1203 /* error without aborting current compilation */
1204 void error_noabort(const char *fmt, ...)
1206 TCCState *s1 = tcc_state;
1207 va_list ap;
1209 va_start(ap, fmt);
1210 error1(s1, 0, fmt, ap);
1211 va_end(ap);
1214 void error(const char *fmt, ...)
1216 TCCState *s1 = tcc_state;
1217 va_list ap;
1219 va_start(ap, fmt);
1220 error1(s1, 0, fmt, ap);
1221 va_end(ap);
1222 /* better than nothing: in some cases, we accept to handle errors */
1223 if (s1->error_set_jmp_enabled) {
1224 longjmp(s1->error_jmp_buf, 1);
1225 } else {
1226 /* XXX: eliminate this someday */
1227 exit(1);
1231 void expect(const char *msg)
1233 error("%s expected", msg);
1236 void warning(const char *fmt, ...)
1238 TCCState *s1 = tcc_state;
1239 va_list ap;
1241 va_start(ap, fmt);
1242 error1(s1, 1, fmt, ap);
1243 va_end(ap);
1246 void skip(int c)
1248 if (tok != c)
1249 error("'%c' expected", c);
1250 next();
1253 static void test_lvalue(void)
1255 if (!(vtop->r & VT_LVAL))
1256 expect("lvalue");
1259 /* allocate a new token */
1260 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1262 TokenSym *ts, **ptable;
1263 int i;
1265 if (tok_ident >= SYM_FIRST_ANOM)
1266 error("memory full");
1268 /* expand token table if needed */
1269 i = tok_ident - TOK_IDENT;
1270 if ((i % TOK_ALLOC_INCR) == 0) {
1271 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1272 if (!ptable)
1273 error("memory full");
1274 table_ident = ptable;
1277 ts = tcc_malloc(sizeof(TokenSym) + len);
1278 table_ident[i] = ts;
1279 ts->tok = tok_ident++;
1280 ts->sym_define = NULL;
1281 ts->sym_label = NULL;
1282 ts->sym_struct = NULL;
1283 ts->sym_identifier = NULL;
1284 ts->len = len;
1285 ts->hash_next = NULL;
1286 memcpy(ts->str, str, len);
1287 ts->str[len] = '\0';
1288 *pts = ts;
1289 return ts;
1292 #define TOK_HASH_INIT 1
1293 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1295 /* find a token and add it if not found */
1296 static TokenSym *tok_alloc(const char *str, int len)
1298 TokenSym *ts, **pts;
1299 int i;
1300 unsigned int h;
1302 h = TOK_HASH_INIT;
1303 for(i=0;i<len;i++)
1304 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1305 h &= (TOK_HASH_SIZE - 1);
1307 pts = &hash_ident[h];
1308 for(;;) {
1309 ts = *pts;
1310 if (!ts)
1311 break;
1312 if (ts->len == len && !memcmp(ts->str, str, len))
1313 return ts;
1314 pts = &(ts->hash_next);
1316 return tok_alloc_new(pts, str, len);
1319 /* CString handling */
1321 static void cstr_realloc(CString *cstr, int new_size)
1323 int size;
1324 void *data;
1326 size = cstr->size_allocated;
1327 if (size == 0)
1328 size = 8; /* no need to allocate a too small first string */
1329 while (size < new_size)
1330 size = size * 2;
1331 data = tcc_realloc(cstr->data_allocated, size);
1332 if (!data)
1333 error("memory full");
1334 cstr->data_allocated = data;
1335 cstr->size_allocated = size;
1336 cstr->data = data;
1339 /* add a byte */
1340 static void cstr_ccat(CString *cstr, int ch)
1342 int size;
1343 size = cstr->size + 1;
1344 if (size > cstr->size_allocated)
1345 cstr_realloc(cstr, size);
1346 ((unsigned char *)cstr->data)[size - 1] = ch;
1347 cstr->size = size;
1350 static void cstr_cat(CString *cstr, const char *str)
1352 int c;
1353 for(;;) {
1354 c = *str;
1355 if (c == '\0')
1356 break;
1357 cstr_ccat(cstr, c);
1358 str++;
1362 /* add a wide char */
1363 static void cstr_wccat(CString *cstr, int ch)
1365 int size;
1366 size = cstr->size + sizeof(int);
1367 if (size > cstr->size_allocated)
1368 cstr_realloc(cstr, size);
1369 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1370 cstr->size = size;
1373 static void cstr_new(CString *cstr)
1375 memset(cstr, 0, sizeof(CString));
1378 /* free string and reset it to NULL */
1379 static void cstr_free(CString *cstr)
1381 tcc_free(cstr->data_allocated);
1382 cstr_new(cstr);
1385 #define cstr_reset(cstr) cstr_free(cstr)
1387 static CString *cstr_dup(CString *cstr1)
1389 CString *cstr;
1390 int size;
1392 cstr = tcc_malloc(sizeof(CString));
1393 size = cstr1->size;
1394 cstr->size = size;
1395 cstr->size_allocated = size;
1396 cstr->data_allocated = tcc_malloc(size);
1397 cstr->data = cstr->data_allocated;
1398 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1399 return cstr;
1402 /* XXX: unicode ? */
1403 static void add_char(CString *cstr, int c)
1405 if (c == '\'' || c == '\"' || c == '\\') {
1406 /* XXX: could be more precise if char or string */
1407 cstr_ccat(cstr, '\\');
1409 if (c >= 32 && c <= 126) {
1410 cstr_ccat(cstr, c);
1411 } else {
1412 cstr_ccat(cstr, '\\');
1413 if (c == '\n') {
1414 cstr_ccat(cstr, 'n');
1415 } else {
1416 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1417 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1418 cstr_ccat(cstr, '0' + (c & 7));
1423 /* XXX: buffer overflow */
1424 /* XXX: float tokens */
1425 char *get_tok_str(int v, CValue *cv)
1427 static char buf[STRING_MAX_SIZE + 1];
1428 static CString cstr_buf;
1429 CString *cstr;
1430 unsigned char *q;
1431 char *p;
1432 int i, len;
1434 /* NOTE: to go faster, we give a fixed buffer for small strings */
1435 cstr_reset(&cstr_buf);
1436 cstr_buf.data = buf;
1437 cstr_buf.size_allocated = sizeof(buf);
1438 p = buf;
1440 switch(v) {
1441 case TOK_CINT:
1442 case TOK_CUINT:
1443 /* XXX: not quite exact, but only useful for testing */
1444 sprintf(p, "%u", cv->ui);
1445 break;
1446 case TOK_CLLONG:
1447 case TOK_CULLONG:
1448 /* XXX: not quite exact, but only useful for testing */
1449 sprintf(p, "%Lu", cv->ull);
1450 break;
1451 case TOK_CCHAR:
1452 case TOK_LCHAR:
1453 cstr_ccat(&cstr_buf, '\'');
1454 add_char(&cstr_buf, cv->i);
1455 cstr_ccat(&cstr_buf, '\'');
1456 cstr_ccat(&cstr_buf, '\0');
1457 break;
1458 case TOK_PPNUM:
1459 cstr = cv->cstr;
1460 len = cstr->size - 1;
1461 for(i=0;i<len;i++)
1462 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1463 cstr_ccat(&cstr_buf, '\0');
1464 break;
1465 case TOK_STR:
1466 case TOK_LSTR:
1467 cstr = cv->cstr;
1468 cstr_ccat(&cstr_buf, '\"');
1469 if (v == TOK_STR) {
1470 len = cstr->size - 1;
1471 for(i=0;i<len;i++)
1472 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1473 } else {
1474 len = (cstr->size / sizeof(int)) - 1;
1475 for(i=0;i<len;i++)
1476 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1478 cstr_ccat(&cstr_buf, '\"');
1479 cstr_ccat(&cstr_buf, '\0');
1480 break;
1481 case TOK_LT:
1482 v = '<';
1483 goto addv;
1484 case TOK_GT:
1485 v = '>';
1486 goto addv;
1487 case TOK_A_SHL:
1488 return strcpy(p, "<<=");
1489 case TOK_A_SAR:
1490 return strcpy(p, ">>=");
1491 default:
1492 if (v < TOK_IDENT) {
1493 /* search in two bytes table */
1494 q = tok_two_chars;
1495 while (*q) {
1496 if (q[2] == v) {
1497 *p++ = q[0];
1498 *p++ = q[1];
1499 *p = '\0';
1500 return buf;
1502 q += 3;
1504 addv:
1505 *p++ = v;
1506 *p = '\0';
1507 } else if (v < tok_ident) {
1508 return table_ident[v - TOK_IDENT]->str;
1509 } else if (v >= SYM_FIRST_ANOM) {
1510 /* special name for anonymous symbol */
1511 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1512 } else {
1513 /* should never happen */
1514 return NULL;
1516 break;
1518 return cstr_buf.data;
1521 /* push, without hashing */
1522 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1524 Sym *s;
1525 s = tcc_malloc(sizeof(Sym));
1526 s->v = v;
1527 s->type.t = t;
1528 s->c = c;
1529 s->next = NULL;
1530 /* add in stack */
1531 s->prev = *ps;
1532 *ps = s;
1533 return s;
1536 /* find a symbol and return its associated structure. 's' is the top
1537 of the symbol stack */
1538 static Sym *sym_find2(Sym *s, int v)
1540 while (s) {
1541 if (s->v == v)
1542 return s;
1543 s = s->prev;
1545 return NULL;
1548 /* structure lookup */
1549 static inline Sym *struct_find(int v)
1551 v -= TOK_IDENT;
1552 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1553 return NULL;
1554 return table_ident[v]->sym_struct;
1557 /* find an identifier */
1558 static inline Sym *sym_find(int v)
1560 v -= TOK_IDENT;
1561 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1562 return NULL;
1563 return table_ident[v]->sym_identifier;
1566 /* push a given symbol on the symbol stack */
1567 static Sym *sym_push(int v, CType *type, int r, int c)
1569 Sym *s, **ps;
1570 TokenSym *ts;
1572 if (local_stack)
1573 ps = &local_stack;
1574 else
1575 ps = &global_stack;
1576 s = sym_push2(ps, v, type->t, c);
1577 s->type.ref = type->ref;
1578 s->r = r;
1579 /* don't record fields or anonymous symbols */
1580 /* XXX: simplify */
1581 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1582 /* record symbol in token array */
1583 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1584 if (v & SYM_STRUCT)
1585 ps = &ts->sym_struct;
1586 else
1587 ps = &ts->sym_identifier;
1588 s->prev_tok = *ps;
1589 *ps = s;
1591 return s;
1594 /* push a global identifier */
1595 static Sym *global_identifier_push(int v, int t, int c)
1597 Sym *s, **ps;
1598 s = sym_push2(&global_stack, v, t, c);
1599 /* don't record anonymous symbol */
1600 if (v < SYM_FIRST_ANOM) {
1601 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1602 /* modify the top most local identifier, so that
1603 sym_identifier will point to 's' when popped */
1604 while (*ps != NULL)
1605 ps = &(*ps)->prev_tok;
1606 s->prev_tok = NULL;
1607 *ps = s;
1609 return s;
1612 /* pop symbols until top reaches 'b' */
1613 static void sym_pop(Sym **ptop, Sym *b)
1615 Sym *s, *ss, **ps;
1616 TokenSym *ts;
1617 int v;
1619 s = *ptop;
1620 while(s != b) {
1621 ss = s->prev;
1622 v = s->v;
1623 /* remove symbol in token array */
1624 /* XXX: simplify */
1625 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1626 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1627 if (v & SYM_STRUCT)
1628 ps = &ts->sym_struct;
1629 else
1630 ps = &ts->sym_identifier;
1631 *ps = s->prev_tok;
1633 tcc_free(s);
1634 s = ss;
1636 *ptop = b;
1639 /* I/O layer */
1641 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1643 int fd;
1644 BufferedFile *bf;
1646 fd = open(filename, O_RDONLY);
1647 if (fd < 0)
1648 return NULL;
1649 bf = tcc_malloc(sizeof(BufferedFile));
1650 if (!bf) {
1651 close(fd);
1652 return NULL;
1654 bf->fd = fd;
1655 bf->buf_ptr = bf->buffer;
1656 bf->buf_end = bf->buffer;
1657 bf->buffer[0] = CH_EOB; /* put eob symbol */
1658 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1659 bf->line_num = 1;
1660 bf->ifndef_macro = 0;
1661 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1662 // printf("opening '%s'\n", filename);
1663 return bf;
1666 void tcc_close(BufferedFile *bf)
1668 total_lines += bf->line_num;
1669 close(bf->fd);
1670 tcc_free(bf);
1673 /* fill input buffer and peek next char */
1674 static int tcc_peekc_slow(BufferedFile *bf)
1676 int len;
1677 /* only tries to read if really end of buffer */
1678 if (bf->buf_ptr >= bf->buf_end) {
1679 if (bf->fd != -1) {
1680 #if defined(PARSE_DEBUG)
1681 len = 8;
1682 #else
1683 len = IO_BUF_SIZE;
1684 #endif
1685 len = read(bf->fd, bf->buffer, len);
1686 if (len < 0)
1687 len = 0;
1688 } else {
1689 len = 0;
1691 total_bytes += len;
1692 bf->buf_ptr = bf->buffer;
1693 bf->buf_end = bf->buffer + len;
1694 *bf->buf_end = CH_EOB;
1696 if (bf->buf_ptr < bf->buf_end) {
1697 return bf->buf_ptr[0];
1698 } else {
1699 bf->buf_ptr = bf->buf_end;
1700 return CH_EOF;
1704 /* return the current character, handling end of block if necessary
1705 (but not stray) */
1706 static int handle_eob(void)
1708 return tcc_peekc_slow(file);
1711 /* read next char from current input file and handle end of input buffer */
1712 static inline void inp(void)
1714 ch = *(++(file->buf_ptr));
1715 /* end of buffer/file handling */
1716 if (ch == CH_EOB)
1717 ch = handle_eob();
1720 /* handle '\[\r]\n' */
1721 static void handle_stray(void)
1723 while (ch == '\\') {
1724 inp();
1725 if (ch == '\n') {
1726 file->line_num++;
1727 inp();
1728 } else if (ch == '\r') {
1729 inp();
1730 if (ch != '\n')
1731 goto fail;
1732 file->line_num++;
1733 inp();
1734 } else {
1735 fail:
1736 error("stray '\\' in program");
1741 /* skip the stray and handle the \\n case. Output an error if
1742 incorrect char after the stray */
1743 static int handle_stray1(uint8_t *p)
1745 int c;
1747 if (p >= file->buf_end) {
1748 file->buf_ptr = p;
1749 c = handle_eob();
1750 p = file->buf_ptr;
1751 if (c == '\\')
1752 goto parse_stray;
1753 } else {
1754 parse_stray:
1755 file->buf_ptr = p;
1756 ch = *p;
1757 handle_stray();
1758 p = file->buf_ptr;
1759 c = *p;
1761 return c;
1764 /* handle just the EOB case, but not stray */
1765 #define PEEKC_EOB(c, p)\
1767 p++;\
1768 c = *p;\
1769 if (c == '\\') {\
1770 file->buf_ptr = p;\
1771 c = handle_eob();\
1772 p = file->buf_ptr;\
1776 /* handle the complicated stray case */
1777 #define PEEKC(c, p)\
1779 p++;\
1780 c = *p;\
1781 if (c == '\\') {\
1782 c = handle_stray1(p);\
1783 p = file->buf_ptr;\
1787 /* input with '\[\r]\n' handling. Note that this function cannot
1788 handle other characters after '\', so you cannot call it inside
1789 strings or comments */
1790 static void minp(void)
1792 inp();
1793 if (ch == '\\')
1794 handle_stray();
1798 /* single line C++ comments */
1799 static uint8_t *parse_line_comment(uint8_t *p)
1801 int c;
1803 p++;
1804 for(;;) {
1805 c = *p;
1806 if (c == '\n' || c == CH_EOF) {
1807 break;
1808 } else if (c == '\\') {
1809 PEEKC_EOB(c, p);
1810 if (c == '\n') {
1811 file->line_num++;
1812 PEEKC_EOB(c, p);
1813 } else if (c == '\r') {
1814 PEEKC_EOB(c, p);
1815 if (c == '\n') {
1816 file->line_num++;
1817 PEEKC_EOB(c, p);
1820 } else {
1821 p++;
1824 return p;
1827 /* C comments */
1828 static uint8_t *parse_comment(uint8_t *p)
1830 int c;
1832 p++;
1833 for(;;) {
1834 /* fast skip loop */
1835 for(;;) {
1836 c = *p;
1837 if (c == '\n' || c == '*' || c == '\\')
1838 break;
1839 p++;
1840 c = *p;
1841 if (c == '\n' || c == '*' || c == '\\')
1842 break;
1843 p++;
1845 /* now we can handle all the cases */
1846 if (c == '\n') {
1847 file->line_num++;
1848 p++;
1849 } else if (c == '*') {
1850 p++;
1851 for(;;) {
1852 c = *p;
1853 if (c == '*') {
1854 p++;
1855 } else if (c == '/') {
1856 goto end_of_comment;
1857 } else if (c == '\\') {
1858 file->buf_ptr = p;
1859 c = handle_eob();
1860 p = file->buf_ptr;
1861 if (c == '\\') {
1862 /* skip '\[\r]\n', otherwise just skip the stray */
1863 while (c == '\\') {
1864 PEEKC_EOB(c, p);
1865 if (c == '\n') {
1866 file->line_num++;
1867 PEEKC_EOB(c, p);
1868 } else if (c == '\r') {
1869 PEEKC_EOB(c, p);
1870 if (c == '\n') {
1871 file->line_num++;
1872 PEEKC_EOB(c, p);
1874 } else {
1875 goto after_star;
1879 } else {
1880 break;
1883 after_star: ;
1884 } else {
1885 /* stray, eob or eof */
1886 file->buf_ptr = p;
1887 c = handle_eob();
1888 p = file->buf_ptr;
1889 if (c == CH_EOF) {
1890 error("unexpected end of file in comment");
1891 } else if (c == '\\') {
1892 p++;
1896 end_of_comment:
1897 p++;
1898 return p;
1901 #define cinp minp
1903 /* space exlcuding newline */
1904 static inline int is_space(int ch)
1906 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1909 static inline void skip_spaces(void)
1911 while (is_space(ch))
1912 cinp();
1915 /* parse a string without interpreting escapes */
1916 static uint8_t *parse_pp_string(uint8_t *p,
1917 int sep, CString *str)
1919 int c;
1920 p++;
1921 for(;;) {
1922 c = *p;
1923 if (c == sep) {
1924 break;
1925 } else if (c == '\\') {
1926 file->buf_ptr = p;
1927 c = handle_eob();
1928 p = file->buf_ptr;
1929 if (c == CH_EOF) {
1930 unterminated_string:
1931 /* XXX: indicate line number of start of string */
1932 error("missing terminating %c character", sep);
1933 } else if (c == '\\') {
1934 /* escape : just skip \[\r]\n */
1935 PEEKC_EOB(c, p);
1936 if (c == '\n') {
1937 file->line_num++;
1938 p++;
1939 } else if (c == '\r') {
1940 PEEKC_EOB(c, p);
1941 if (c != '\n')
1942 expect("'\n' after '\r'");
1943 file->line_num++;
1944 p++;
1945 } else if (c == CH_EOF) {
1946 goto unterminated_string;
1947 } else {
1948 if (str) {
1949 cstr_ccat(str, '\\');
1950 cstr_ccat(str, c);
1952 p++;
1955 } else if (c == '\n') {
1956 file->line_num++;
1957 goto add_char;
1958 } else if (c == '\r') {
1959 PEEKC_EOB(c, p);
1960 if (c != '\n') {
1961 cstr_ccat(str, '\r');
1962 } else {
1963 file->line_num++;
1964 goto add_char;
1966 } else {
1967 add_char:
1968 if (str)
1969 cstr_ccat(str, c);
1970 p++;
1973 p++;
1974 return p;
1977 /* skip block of text until #else, #elif or #endif. skip also pairs of
1978 #if/#endif */
1979 void preprocess_skip(void)
1981 int a, start_of_line, c;
1982 uint8_t *p;
1984 p = file->buf_ptr;
1985 start_of_line = 1;
1986 a = 0;
1987 for(;;) {
1988 redo_no_start:
1989 c = *p;
1990 switch(c) {
1991 case ' ':
1992 case '\t':
1993 case '\f':
1994 case '\v':
1995 case '\r':
1996 p++;
1997 goto redo_no_start;
1998 case '\n':
1999 start_of_line = 1;
2000 file->line_num++;
2001 p++;
2002 goto redo_no_start;
2003 case '\\':
2004 file->buf_ptr = p;
2005 c = handle_eob();
2006 if (c == CH_EOF) {
2007 expect("#endif");
2008 } else if (c == '\\') {
2009 /* XXX: incorrect: should not give an error */
2010 ch = file->buf_ptr[0];
2011 handle_stray();
2013 p = file->buf_ptr;
2014 goto redo_no_start;
2015 /* skip strings */
2016 case '\"':
2017 case '\'':
2018 p = parse_pp_string(p, c, NULL);
2019 break;
2020 /* skip comments */
2021 case '/':
2022 file->buf_ptr = p;
2023 ch = *p;
2024 minp();
2025 p = file->buf_ptr;
2026 if (ch == '*') {
2027 p = parse_comment(p);
2028 } else if (ch == '/') {
2029 p = parse_line_comment(p);
2031 break;
2033 case '#':
2034 p++;
2035 if (start_of_line) {
2036 file->buf_ptr = p;
2037 next_nomacro();
2038 p = file->buf_ptr;
2039 if (a == 0 &&
2040 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2041 goto the_end;
2042 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2043 a++;
2044 else if (tok == TOK_ENDIF)
2045 a--;
2047 break;
2048 default:
2049 p++;
2050 break;
2052 start_of_line = 0;
2054 the_end: ;
2055 file->buf_ptr = p;
2058 /* ParseState handling */
2060 /* XXX: currently, no include file info is stored. Thus, we cannot display
2061 accurate messages if the function or data definition spans multiple
2062 files */
2064 /* save current parse state in 's' */
2065 void save_parse_state(ParseState *s)
2067 s->line_num = file->line_num;
2068 s->macro_ptr = macro_ptr;
2069 s->tok = tok;
2070 s->tokc = tokc;
2073 /* restore parse state from 's' */
2074 void restore_parse_state(ParseState *s)
2076 file->line_num = s->line_num;
2077 macro_ptr = s->macro_ptr;
2078 tok = s->tok;
2079 tokc = s->tokc;
2082 /* return the number of additional 'ints' necessary to store the
2083 token */
2084 static inline int tok_ext_size(int t)
2086 switch(t) {
2087 /* 4 bytes */
2088 case TOK_CINT:
2089 case TOK_CUINT:
2090 case TOK_CCHAR:
2091 case TOK_LCHAR:
2092 case TOK_STR:
2093 case TOK_LSTR:
2094 case TOK_CFLOAT:
2095 case TOK_LINENUM:
2096 case TOK_PPNUM:
2097 return 1;
2098 case TOK_CDOUBLE:
2099 case TOK_CLLONG:
2100 case TOK_CULLONG:
2101 return 2;
2102 case TOK_CLDOUBLE:
2103 return LDOUBLE_SIZE / 4;
2104 default:
2105 return 0;
2109 /* token string handling */
2111 static inline void tok_str_new(TokenString *s)
2113 s->str = NULL;
2114 s->len = 0;
2115 s->allocated_len = 0;
2116 s->last_line_num = -1;
2119 static void tok_str_free(int *str)
2121 const int *p;
2122 CString *cstr;
2123 int t;
2125 p = str;
2126 for(;;) {
2127 t = *p;
2128 /* NOTE: we test zero separately so that GCC can generate a
2129 table for the following switch */
2130 if (t == 0)
2131 break;
2132 switch(t) {
2133 case TOK_CINT:
2134 case TOK_CUINT:
2135 case TOK_CCHAR:
2136 case TOK_LCHAR:
2137 case TOK_CFLOAT:
2138 case TOK_LINENUM:
2139 p += 2;
2140 break;
2141 case TOK_PPNUM:
2142 case TOK_STR:
2143 case TOK_LSTR:
2144 /* XXX: use a macro to be portable on 64 bit ? */
2145 cstr = (CString *)p[1];
2146 cstr_free(cstr);
2147 tcc_free(cstr);
2148 p += 2;
2149 break;
2150 case TOK_CDOUBLE:
2151 case TOK_CLLONG:
2152 case TOK_CULLONG:
2153 p += 3;
2154 break;
2155 case TOK_CLDOUBLE:
2156 p += 1 + (LDOUBLE_SIZE / 4);
2157 break;
2158 default:
2159 p++;
2160 break;
2163 tcc_free(str);
2166 static int *tok_str_realloc(TokenString *s)
2168 int *str, len;
2170 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2171 str = tcc_realloc(s->str, len * sizeof(int));
2172 if (!str)
2173 error("memory full");
2174 s->allocated_len = len;
2175 s->str = str;
2176 return str;
2179 static void tok_str_add(TokenString *s, int t)
2181 int len, *str;
2183 len = s->len;
2184 str = s->str;
2185 if (len >= s->allocated_len)
2186 str = tok_str_realloc(s);
2187 str[len++] = t;
2188 s->len = len;
2191 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2193 int len, *str;
2195 len = s->len;
2196 str = s->str;
2198 /* allocate space for worst case */
2199 if (len + TOK_MAX_SIZE > s->allocated_len)
2200 str = tok_str_realloc(s);
2201 str[len++] = t;
2202 switch(t) {
2203 case TOK_CINT:
2204 case TOK_CUINT:
2205 case TOK_CCHAR:
2206 case TOK_LCHAR:
2207 case TOK_CFLOAT:
2208 case TOK_LINENUM:
2209 str[len++] = cv->tab[0];
2210 break;
2211 case TOK_PPNUM:
2212 case TOK_STR:
2213 case TOK_LSTR:
2214 str[len++] = (int)cstr_dup(cv->cstr);
2215 break;
2216 case TOK_CDOUBLE:
2217 case TOK_CLLONG:
2218 case TOK_CULLONG:
2219 str[len++] = cv->tab[0];
2220 str[len++] = cv->tab[1];
2221 break;
2222 case TOK_CLDOUBLE:
2223 #if LDOUBLE_SIZE == 12
2224 str[len++] = cv->tab[0];
2225 str[len++] = cv->tab[1];
2226 str[len++] = cv->tab[2];
2227 #else
2228 #error add long double size support
2229 #endif
2230 break;
2231 default:
2232 break;
2234 s->len = len;
2237 /* add the current parse token in token string 's' */
2238 static void tok_str_add_tok(TokenString *s)
2240 CValue cval;
2242 /* save line number info */
2243 if (file->line_num != s->last_line_num) {
2244 s->last_line_num = file->line_num;
2245 cval.i = s->last_line_num;
2246 tok_str_add2(s, TOK_LINENUM, &cval);
2248 tok_str_add2(s, tok, &tokc);
2251 #if LDOUBLE_SIZE == 12
2252 #define LDOUBLE_GET(p, cv) \
2253 cv.tab[0] = p[0]; \
2254 cv.tab[1] = p[1]; \
2255 cv.tab[2] = p[2];
2256 #else
2257 #error add long double size support
2258 #endif
2261 /* get a token from an integer array and increment pointer
2262 accordingly. we code it as a macro to avoid pointer aliasing. */
2263 #define TOK_GET(t, p, cv) \
2265 t = *p++; \
2266 switch(t) { \
2267 case TOK_CINT: \
2268 case TOK_CUINT: \
2269 case TOK_CCHAR: \
2270 case TOK_LCHAR: \
2271 case TOK_CFLOAT: \
2272 case TOK_LINENUM: \
2273 case TOK_STR: \
2274 case TOK_LSTR: \
2275 case TOK_PPNUM: \
2276 cv.tab[0] = *p++; \
2277 break; \
2278 case TOK_CDOUBLE: \
2279 case TOK_CLLONG: \
2280 case TOK_CULLONG: \
2281 cv.tab[0] = p[0]; \
2282 cv.tab[1] = p[1]; \
2283 p += 2; \
2284 break; \
2285 case TOK_CLDOUBLE: \
2286 LDOUBLE_GET(p, cv); \
2287 p += LDOUBLE_SIZE / 4; \
2288 break; \
2289 default: \
2290 break; \
2294 /* defines handling */
2295 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2297 Sym *s;
2299 s = sym_push2(&define_stack, v, macro_type, (int)str);
2300 s->next = first_arg;
2301 table_ident[v - TOK_IDENT]->sym_define = s;
2304 /* undefined a define symbol. Its name is just set to zero */
2305 static void define_undef(Sym *s)
2307 int v;
2308 v = s->v;
2309 if (v >= TOK_IDENT && v < tok_ident)
2310 table_ident[v - TOK_IDENT]->sym_define = NULL;
2311 s->v = 0;
2314 static inline Sym *define_find(int v)
2316 v -= TOK_IDENT;
2317 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2318 return NULL;
2319 return table_ident[v]->sym_define;
2322 /* free define stack until top reaches 'b' */
2323 static void free_defines(Sym *b)
2325 Sym *top, *top1;
2326 int v;
2328 top = define_stack;
2329 while (top != b) {
2330 top1 = top->prev;
2331 /* do not free args or predefined defines */
2332 if (top->c)
2333 tok_str_free((int *)top->c);
2334 v = top->v;
2335 if (v >= TOK_IDENT && v < tok_ident)
2336 table_ident[v - TOK_IDENT]->sym_define = NULL;
2337 tcc_free(top);
2338 top = top1;
2340 define_stack = b;
2343 /* label lookup */
2344 static Sym *label_find(int v)
2346 v -= TOK_IDENT;
2347 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2348 return NULL;
2349 return table_ident[v]->sym_label;
2352 static Sym *label_push(Sym **ptop, int v, int flags)
2354 Sym *s, **ps;
2355 s = sym_push2(ptop, v, 0, 0);
2356 s->r = flags;
2357 ps = &table_ident[v - TOK_IDENT]->sym_label;
2358 if (ptop == &global_label_stack) {
2359 /* modify the top most local identifier, so that
2360 sym_identifier will point to 's' when popped */
2361 while (*ps != NULL)
2362 ps = &(*ps)->prev_tok;
2364 s->prev_tok = *ps;
2365 *ps = s;
2366 return s;
2369 /* pop labels until element last is reached. Look if any labels are
2370 undefined. Define symbols if '&&label' was used. */
2371 static void label_pop(Sym **ptop, Sym *slast)
2373 Sym *s, *s1;
2374 for(s = *ptop; s != slast; s = s1) {
2375 s1 = s->prev;
2376 if (s->r == LABEL_DECLARED) {
2377 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2378 } else if (s->r == LABEL_FORWARD) {
2379 error("label '%s' used but not defined",
2380 get_tok_str(s->v, NULL));
2381 } else {
2382 if (s->c) {
2383 /* define corresponding symbol. A size of
2384 1 is put. */
2385 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2388 /* remove label */
2389 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2390 tcc_free(s);
2392 *ptop = slast;
2395 /* eval an expression for #if/#elif */
2396 static int expr_preprocess(void)
2398 int c, t;
2399 TokenString str;
2401 tok_str_new(&str);
2402 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2403 next(); /* do macro subst */
2404 if (tok == TOK_DEFINED) {
2405 next_nomacro();
2406 t = tok;
2407 if (t == '(')
2408 next_nomacro();
2409 c = define_find(tok) != 0;
2410 if (t == '(')
2411 next_nomacro();
2412 tok = TOK_CINT;
2413 tokc.i = c;
2414 } else if (tok >= TOK_IDENT) {
2415 /* if undefined macro */
2416 tok = TOK_CINT;
2417 tokc.i = 0;
2419 tok_str_add_tok(&str);
2421 tok_str_add(&str, -1); /* simulate end of file */
2422 tok_str_add(&str, 0);
2423 /* now evaluate C constant expression */
2424 macro_ptr = str.str;
2425 next();
2426 c = expr_const();
2427 macro_ptr = NULL;
2428 tok_str_free(str.str);
2429 return c != 0;
2432 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2433 static void tok_print(int *str)
2435 int t;
2436 CValue cval;
2438 while (1) {
2439 TOK_GET(t, str, cval);
2440 if (!t)
2441 break;
2442 printf(" %s", get_tok_str(t, &cval));
2444 printf("\n");
2446 #endif
2448 /* parse after #define */
2449 static void parse_define(void)
2451 Sym *s, *first, **ps;
2452 int v, t, varg, is_vaargs, c;
2453 TokenString str;
2455 v = tok;
2456 if (v < TOK_IDENT)
2457 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2458 /* XXX: should check if same macro (ANSI) */
2459 first = NULL;
2460 t = MACRO_OBJ;
2461 /* '(' must be just after macro definition for MACRO_FUNC */
2462 c = file->buf_ptr[0];
2463 if (c == '\\')
2464 c = handle_stray1(file->buf_ptr);
2465 if (c == '(') {
2466 next_nomacro();
2467 next_nomacro();
2468 ps = &first;
2469 while (tok != ')') {
2470 varg = tok;
2471 next_nomacro();
2472 is_vaargs = 0;
2473 if (varg == TOK_DOTS) {
2474 varg = TOK___VA_ARGS__;
2475 is_vaargs = 1;
2476 } else if (tok == TOK_DOTS && gnu_ext) {
2477 is_vaargs = 1;
2478 next_nomacro();
2480 if (varg < TOK_IDENT)
2481 error("badly punctuated parameter list");
2482 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2483 *ps = s;
2484 ps = &s->next;
2485 if (tok != ',')
2486 break;
2487 next_nomacro();
2489 t = MACRO_FUNC;
2491 tok_str_new(&str);
2492 next_nomacro();
2493 /* EOF testing necessary for '-D' handling */
2494 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2495 tok_str_add2(&str, tok, &tokc);
2496 next_nomacro();
2498 tok_str_add(&str, 0);
2499 #ifdef PP_DEBUG
2500 printf("define %s %d: ", get_tok_str(v, NULL), t);
2501 tok_print(str.str);
2502 #endif
2503 define_push(v, t, str.str, first);
2506 /* XXX: use a token or a hash table to accelerate matching ? */
2507 static CachedInclude *search_cached_include(TCCState *s1,
2508 int type, const char *filename)
2510 CachedInclude *e;
2511 int i;
2513 for(i = 0;i < s1->nb_cached_includes; i++) {
2514 e = s1->cached_includes[i];
2515 if (e->type == type && !strcmp(e->filename, filename))
2516 return e;
2518 return NULL;
2521 static inline void add_cached_include(TCCState *s1, int type,
2522 const char *filename, int ifndef_macro)
2524 CachedInclude *e;
2526 if (search_cached_include(s1, type, filename))
2527 return;
2528 #ifdef INC_DEBUG
2529 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2530 #endif
2531 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2532 if (!e)
2533 return;
2534 e->type = type;
2535 strcpy(e->filename, filename);
2536 e->ifndef_macro = ifndef_macro;
2537 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2540 /* is_bof is true if first non space token at beginning of file */
2541 static void preprocess(int is_bof)
2543 TCCState *s1 = tcc_state;
2544 int size, i, c, n, saved_parse_flags;
2545 char buf[1024], *q, *p;
2546 char buf1[1024];
2547 BufferedFile *f;
2548 Sym *s;
2549 CachedInclude *e;
2551 saved_parse_flags = parse_flags;
2552 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2553 PARSE_FLAG_LINEFEED;
2554 next_nomacro();
2555 redo:
2556 switch(tok) {
2557 case TOK_DEFINE:
2558 next_nomacro();
2559 parse_define();
2560 break;
2561 case TOK_UNDEF:
2562 next_nomacro();
2563 s = define_find(tok);
2564 /* undefine symbol by putting an invalid name */
2565 if (s)
2566 define_undef(s);
2567 break;
2568 case TOK_INCLUDE:
2569 ch = file->buf_ptr[0];
2570 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2571 skip_spaces();
2572 if (ch == '<') {
2573 c = '>';
2574 goto read_name;
2575 } else if (ch == '\"') {
2576 c = ch;
2577 read_name:
2578 /* XXX: better stray handling */
2579 minp();
2580 q = buf;
2581 while (ch != c && ch != '\n' && ch != CH_EOF) {
2582 if ((q - buf) < sizeof(buf) - 1)
2583 *q++ = ch;
2584 minp();
2586 *q = '\0';
2587 minp();
2588 #if 0
2589 /* eat all spaces and comments after include */
2590 /* XXX: slightly incorrect */
2591 while (ch1 != '\n' && ch1 != CH_EOF)
2592 inp();
2593 #endif
2594 } else {
2595 /* computed #include : either we have only strings or
2596 we have anything enclosed in '<>' */
2597 next();
2598 buf[0] = '\0';
2599 if (tok == TOK_STR) {
2600 while (tok != TOK_LINEFEED) {
2601 if (tok != TOK_STR) {
2602 include_syntax:
2603 error("'#include' expects \"FILENAME\" or <FILENAME>");
2605 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2606 next();
2608 c = '\"';
2609 } else {
2610 int len;
2611 while (tok != TOK_LINEFEED) {
2612 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2613 next();
2615 len = strlen(buf);
2616 /* check syntax and remove '<>' */
2617 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2618 goto include_syntax;
2619 memmove(buf, buf + 1, len - 2);
2620 buf[len - 2] = '\0';
2621 c = '>';
2625 e = search_cached_include(s1, c, buf);
2626 if (e && define_find(e->ifndef_macro)) {
2627 /* no need to parse the include because the 'ifndef macro'
2628 is defined */
2629 #ifdef INC_DEBUG
2630 printf("%s: skipping %s\n", file->filename, buf);
2631 #endif
2632 } else {
2633 if (c == '\"') {
2634 /* first search in current dir if "header.h" */
2635 size = 0;
2636 p = strrchr(file->filename, '/');
2637 if (p)
2638 size = p + 1 - file->filename;
2639 if (size > sizeof(buf1) - 1)
2640 size = sizeof(buf1) - 1;
2641 memcpy(buf1, file->filename, size);
2642 buf1[size] = '\0';
2643 pstrcat(buf1, sizeof(buf1), buf);
2644 f = tcc_open(s1, buf1);
2645 if (f)
2646 goto found;
2648 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2649 error("#include recursion too deep");
2650 /* now search in all the include paths */
2651 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2652 for(i = 0; i < n; i++) {
2653 const char *path;
2654 if (i < s1->nb_include_paths)
2655 path = s1->include_paths[i];
2656 else
2657 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2658 pstrcpy(buf1, sizeof(buf1), path);
2659 pstrcat(buf1, sizeof(buf1), "/");
2660 pstrcat(buf1, sizeof(buf1), buf);
2661 f = tcc_open(s1, buf1);
2662 if (f)
2663 goto found;
2665 error("include file '%s' not found", buf);
2666 f = NULL;
2667 found:
2668 #ifdef INC_DEBUG
2669 printf("%s: including %s\n", file->filename, buf1);
2670 #endif
2671 f->inc_type = c;
2672 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2673 /* push current file in stack */
2674 /* XXX: fix current line init */
2675 *s1->include_stack_ptr++ = file;
2676 file = f;
2677 /* add include file debug info */
2678 if (do_debug) {
2679 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2681 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2682 ch = file->buf_ptr[0];
2683 goto the_end;
2685 break;
2686 case TOK_IFNDEF:
2687 c = 1;
2688 goto do_ifdef;
2689 case TOK_IF:
2690 c = expr_preprocess();
2691 goto do_if;
2692 case TOK_IFDEF:
2693 c = 0;
2694 do_ifdef:
2695 next_nomacro();
2696 if (tok < TOK_IDENT)
2697 error("invalid argument for '#if%sdef'", c ? "n" : "");
2698 if (is_bof) {
2699 if (c) {
2700 #ifdef INC_DEBUG
2701 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2702 #endif
2703 file->ifndef_macro = tok;
2706 c = (define_find(tok) != 0) ^ c;
2707 do_if:
2708 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2709 error("memory full");
2710 *s1->ifdef_stack_ptr++ = c;
2711 goto test_skip;
2712 case TOK_ELSE:
2713 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2714 error("#else without matching #if");
2715 if (s1->ifdef_stack_ptr[-1] & 2)
2716 error("#else after #else");
2717 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2718 goto test_skip;
2719 case TOK_ELIF:
2720 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2721 error("#elif without matching #if");
2722 c = s1->ifdef_stack_ptr[-1];
2723 if (c > 1)
2724 error("#elif after #else");
2725 /* last #if/#elif expression was true: we skip */
2726 if (c == 1)
2727 goto skip;
2728 c = expr_preprocess();
2729 s1->ifdef_stack_ptr[-1] = c;
2730 test_skip:
2731 if (!(c & 1)) {
2732 skip:
2733 preprocess_skip();
2734 is_bof = 0;
2735 goto redo;
2737 break;
2738 case TOK_ENDIF:
2739 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2740 error("#endif without matching #if");
2741 s1->ifdef_stack_ptr--;
2742 /* '#ifndef macro' was at the start of file. Now we check if
2743 an '#endif' is exactly at the end of file */
2744 if (file->ifndef_macro &&
2745 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2746 file->ifndef_macro_saved = file->ifndef_macro;
2747 /* need to set to zero to avoid false matches if another
2748 #ifndef at middle of file */
2749 file->ifndef_macro = 0;
2750 while (tok != TOK_LINEFEED)
2751 next_nomacro();
2752 tok_flags |= TOK_FLAG_ENDIF;
2753 goto the_end;
2755 break;
2756 case TOK_LINE:
2757 next();
2758 if (tok != TOK_CINT)
2759 error("#line");
2760 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2761 next();
2762 if (tok != TOK_LINEFEED) {
2763 if (tok != TOK_STR)
2764 error("#line");
2765 pstrcpy(file->filename, sizeof(file->filename),
2766 (char *)tokc.cstr->data);
2768 break;
2769 case TOK_ERROR:
2770 case TOK_WARNING:
2771 c = tok;
2772 ch = file->buf_ptr[0];
2773 skip_spaces();
2774 q = buf;
2775 while (ch != '\n' && ch != CH_EOF) {
2776 if ((q - buf) < sizeof(buf) - 1)
2777 *q++ = ch;
2778 minp();
2780 *q = '\0';
2781 if (c == TOK_ERROR)
2782 error("#error %s", buf);
2783 else
2784 warning("#warning %s", buf);
2785 break;
2786 case TOK_PRAGMA:
2787 /* ignored */
2788 break;
2789 default:
2790 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2791 /* '!' is ignored to allow C scripts. numbers are ignored
2792 to emulate cpp behaviour */
2793 } else {
2794 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2796 break;
2798 /* ignore other preprocess commands or #! for C scripts */
2799 while (tok != TOK_LINEFEED)
2800 next_nomacro();
2801 the_end:
2802 parse_flags = saved_parse_flags;
2805 /* evaluate escape codes in a string. */
2806 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2808 int c, n;
2809 const char *p;
2811 p = buf;
2812 for(;;) {
2813 c = *p;
2814 if (c == '\0')
2815 break;
2816 if (c == '\\') {
2817 p++;
2818 /* escape */
2819 c = *p;
2820 switch(c) {
2821 case '0': case '1': case '2': case '3':
2822 case '4': case '5': case '6': case '7':
2823 /* at most three octal digits */
2824 n = c - '0';
2825 p++;
2826 c = *p;
2827 if (isoct(c)) {
2828 n = n * 8 + c - '0';
2829 p++;
2830 c = *p;
2831 if (isoct(c)) {
2832 n = n * 8 + c - '0';
2833 p++;
2836 c = n;
2837 goto add_char_nonext;
2838 case 'x':
2839 p++;
2840 n = 0;
2841 for(;;) {
2842 c = *p;
2843 if (c >= 'a' && c <= 'f')
2844 c = c - 'a' + 10;
2845 else if (c >= 'A' && c <= 'F')
2846 c = c - 'A' + 10;
2847 else if (isnum(c))
2848 c = c - '0';
2849 else
2850 break;
2851 n = n * 16 + c;
2852 p++;
2854 c = n;
2855 goto add_char_nonext;
2856 case 'a':
2857 c = '\a';
2858 break;
2859 case 'b':
2860 c = '\b';
2861 break;
2862 case 'f':
2863 c = '\f';
2864 break;
2865 case 'n':
2866 c = '\n';
2867 break;
2868 case 'r':
2869 c = '\r';
2870 break;
2871 case 't':
2872 c = '\t';
2873 break;
2874 case 'v':
2875 c = '\v';
2876 break;
2877 case 'e':
2878 if (!gnu_ext)
2879 goto invalid_escape;
2880 c = 27;
2881 break;
2882 case '\'':
2883 case '\"':
2884 case '\\':
2885 case '?':
2886 break;
2887 default:
2888 invalid_escape:
2889 error("invalid escaped char");
2892 p++;
2893 add_char_nonext:
2894 if (!is_long)
2895 cstr_ccat(outstr, c);
2896 else
2897 cstr_wccat(outstr, c);
2899 /* add a trailing '\0' */
2900 if (!is_long)
2901 cstr_ccat(outstr, '\0');
2902 else
2903 cstr_wccat(outstr, '\0');
2906 /* we use 64 bit numbers */
2907 #define BN_SIZE 2
2909 /* bn = (bn << shift) | or_val */
2910 void bn_lshift(unsigned int *bn, int shift, int or_val)
2912 int i;
2913 unsigned int v;
2914 for(i=0;i<BN_SIZE;i++) {
2915 v = bn[i];
2916 bn[i] = (v << shift) | or_val;
2917 or_val = v >> (32 - shift);
2921 void bn_zero(unsigned int *bn)
2923 int i;
2924 for(i=0;i<BN_SIZE;i++) {
2925 bn[i] = 0;
2929 /* parse number in null terminated string 'p' and return it in the
2930 current token */
2931 void parse_number(const char *p)
2933 int b, t, shift, frac_bits, s, exp_val, ch;
2934 char *q;
2935 unsigned int bn[BN_SIZE];
2936 double d;
2938 /* number */
2939 q = token_buf;
2940 ch = *p++;
2941 t = ch;
2942 ch = *p++;
2943 *q++ = t;
2944 b = 10;
2945 if (t == '.') {
2946 goto float_frac_parse;
2947 } else if (t == '0') {
2948 if (ch == 'x' || ch == 'X') {
2949 q--;
2950 ch = *p++;
2951 b = 16;
2952 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2953 q--;
2954 ch = *p++;
2955 b = 2;
2958 /* parse all digits. cannot check octal numbers at this stage
2959 because of floating point constants */
2960 while (1) {
2961 if (ch >= 'a' && ch <= 'f')
2962 t = ch - 'a' + 10;
2963 else if (ch >= 'A' && ch <= 'F')
2964 t = ch - 'A' + 10;
2965 else if (isnum(ch))
2966 t = ch - '0';
2967 else
2968 break;
2969 if (t >= b)
2970 break;
2971 if (q >= token_buf + STRING_MAX_SIZE) {
2972 num_too_long:
2973 error("number too long");
2975 *q++ = ch;
2976 ch = *p++;
2978 if (ch == '.' ||
2979 ((ch == 'e' || ch == 'E') && b == 10) ||
2980 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
2981 if (b != 10) {
2982 /* NOTE: strtox should support that for hexa numbers, but
2983 non ISOC99 libcs do not support it, so we prefer to do
2984 it by hand */
2985 /* hexadecimal or binary floats */
2986 /* XXX: handle overflows */
2987 *q = '\0';
2988 if (b == 16)
2989 shift = 4;
2990 else
2991 shift = 2;
2992 bn_zero(bn);
2993 q = token_buf;
2994 while (1) {
2995 t = *q++;
2996 if (t == '\0') {
2997 break;
2998 } else if (t >= 'a') {
2999 t = t - 'a' + 10;
3000 } else if (t >= 'A') {
3001 t = t - 'A' + 10;
3002 } else {
3003 t = t - '0';
3005 bn_lshift(bn, shift, t);
3007 frac_bits = 0;
3008 if (ch == '.') {
3009 ch = *p++;
3010 while (1) {
3011 t = ch;
3012 if (t >= 'a' && t <= 'f') {
3013 t = t - 'a' + 10;
3014 } else if (t >= 'A' && t <= 'F') {
3015 t = t - 'A' + 10;
3016 } else if (t >= '0' && t <= '9') {
3017 t = t - '0';
3018 } else {
3019 break;
3021 if (t >= b)
3022 error("invalid digit");
3023 bn_lshift(bn, shift, t);
3024 frac_bits += shift;
3025 ch = *p++;
3028 if (ch != 'p' && ch != 'P')
3029 expect("exponent");
3030 ch = *p++;
3031 s = 1;
3032 exp_val = 0;
3033 if (ch == '+') {
3034 ch = *p++;
3035 } else if (ch == '-') {
3036 s = -1;
3037 ch = *p++;
3039 if (ch < '0' || ch > '9')
3040 expect("exponent digits");
3041 while (ch >= '0' && ch <= '9') {
3042 exp_val = exp_val * 10 + ch - '0';
3043 ch = *p++;
3045 exp_val = exp_val * s;
3047 /* now we can generate the number */
3048 /* XXX: should patch directly float number */
3049 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3050 d = ldexp(d, exp_val - frac_bits);
3051 t = toup(ch);
3052 if (t == 'F') {
3053 ch = *p++;
3054 tok = TOK_CFLOAT;
3055 /* float : should handle overflow */
3056 tokc.f = (float)d;
3057 } else if (t == 'L') {
3058 ch = *p++;
3059 tok = TOK_CLDOUBLE;
3060 /* XXX: not large enough */
3061 tokc.ld = (long double)d;
3062 } else {
3063 tok = TOK_CDOUBLE;
3064 tokc.d = d;
3066 } else {
3067 /* decimal floats */
3068 if (ch == '.') {
3069 if (q >= token_buf + STRING_MAX_SIZE)
3070 goto num_too_long;
3071 *q++ = ch;
3072 ch = *p++;
3073 float_frac_parse:
3074 while (ch >= '0' && ch <= '9') {
3075 if (q >= token_buf + STRING_MAX_SIZE)
3076 goto num_too_long;
3077 *q++ = ch;
3078 ch = *p++;
3081 if (ch == 'e' || ch == 'E') {
3082 if (q >= token_buf + STRING_MAX_SIZE)
3083 goto num_too_long;
3084 *q++ = ch;
3085 ch = *p++;
3086 if (ch == '-' || ch == '+') {
3087 if (q >= token_buf + STRING_MAX_SIZE)
3088 goto num_too_long;
3089 *q++ = ch;
3090 ch = *p++;
3092 if (ch < '0' || ch > '9')
3093 expect("exponent digits");
3094 while (ch >= '0' && ch <= '9') {
3095 if (q >= token_buf + STRING_MAX_SIZE)
3096 goto num_too_long;
3097 *q++ = ch;
3098 ch = *p++;
3101 *q = '\0';
3102 t = toup(ch);
3103 errno = 0;
3104 if (t == 'F') {
3105 ch = *p++;
3106 tok = TOK_CFLOAT;
3107 tokc.f = strtof(token_buf, NULL);
3108 } else if (t == 'L') {
3109 ch = *p++;
3110 tok = TOK_CLDOUBLE;
3111 tokc.ld = strtold(token_buf, NULL);
3112 } else {
3113 tok = TOK_CDOUBLE;
3114 tokc.d = strtod(token_buf, NULL);
3117 } else {
3118 unsigned long long n, n1;
3119 int lcount, ucount;
3121 /* integer number */
3122 *q = '\0';
3123 q = token_buf;
3124 if (b == 10 && *q == '0') {
3125 b = 8;
3126 q++;
3128 n = 0;
3129 while(1) {
3130 t = *q++;
3131 /* no need for checks except for base 10 / 8 errors */
3132 if (t == '\0') {
3133 break;
3134 } else if (t >= 'a') {
3135 t = t - 'a' + 10;
3136 } else if (t >= 'A') {
3137 t = t - 'A' + 10;
3138 } else {
3139 t = t - '0';
3140 if (t >= b)
3141 error("invalid digit");
3143 n1 = n;
3144 n = n * b + t;
3145 /* detect overflow */
3146 /* XXX: this test is not reliable */
3147 if (n < n1)
3148 error("integer constant overflow");
3151 /* XXX: not exactly ANSI compliant */
3152 if ((n & 0xffffffff00000000LL) != 0) {
3153 if ((n >> 63) != 0)
3154 tok = TOK_CULLONG;
3155 else
3156 tok = TOK_CLLONG;
3157 } else if (n > 0x7fffffff) {
3158 tok = TOK_CUINT;
3159 } else {
3160 tok = TOK_CINT;
3162 lcount = 0;
3163 ucount = 0;
3164 for(;;) {
3165 t = toup(ch);
3166 if (t == 'L') {
3167 if (lcount >= 2)
3168 error("three 'l's in integer constant");
3169 lcount++;
3170 if (lcount == 2) {
3171 if (tok == TOK_CINT)
3172 tok = TOK_CLLONG;
3173 else if (tok == TOK_CUINT)
3174 tok = TOK_CULLONG;
3176 ch = *p++;
3177 } else if (t == 'U') {
3178 if (ucount >= 1)
3179 error("two 'u's in integer constant");
3180 ucount++;
3181 if (tok == TOK_CINT)
3182 tok = TOK_CUINT;
3183 else if (tok == TOK_CLLONG)
3184 tok = TOK_CULLONG;
3185 ch = *p++;
3186 } else {
3187 break;
3190 if (tok == TOK_CINT || tok == TOK_CUINT)
3191 tokc.ui = n;
3192 else
3193 tokc.ull = n;
3198 #define PARSE2(c1, tok1, c2, tok2) \
3199 case c1: \
3200 PEEKC(c, p); \
3201 if (c == c2) { \
3202 p++; \
3203 tok = tok2; \
3204 } else { \
3205 tok = tok1; \
3207 break;
3209 /* return next token without macro substitution */
3210 static inline void next_nomacro1(void)
3212 int t, c, is_long;
3213 TokenSym *ts;
3214 uint8_t *p, *p1;
3215 unsigned int h;
3217 p = file->buf_ptr;
3218 redo_no_start:
3219 c = *p;
3220 switch(c) {
3221 case ' ':
3222 case '\t':
3223 case '\f':
3224 case '\v':
3225 case '\r':
3226 p++;
3227 goto redo_no_start;
3229 case '\\':
3230 /* first look if it is in fact an end of buffer */
3231 if (p >= file->buf_end) {
3232 file->buf_ptr = p;
3233 handle_eob();
3234 p = file->buf_ptr;
3235 if (p >= file->buf_end)
3236 goto parse_eof;
3237 else
3238 goto redo_no_start;
3239 } else {
3240 file->buf_ptr = p;
3241 ch = *p;
3242 handle_stray();
3243 p = file->buf_ptr;
3244 goto redo_no_start;
3246 parse_eof:
3248 TCCState *s1 = tcc_state;
3249 if (parse_flags & PARSE_FLAG_LINEFEED) {
3250 tok = TOK_LINEFEED;
3251 } else if (s1->include_stack_ptr == s1->include_stack ||
3252 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3253 /* no include left : end of file. */
3254 tok = TOK_EOF;
3255 } else {
3256 /* pop include file */
3258 /* test if previous '#endif' was after a #ifdef at
3259 start of file */
3260 if (tok_flags & TOK_FLAG_ENDIF) {
3261 #ifdef INC_DEBUG
3262 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3263 #endif
3264 add_cached_include(s1, file->inc_type, file->inc_filename,
3265 file->ifndef_macro_saved);
3268 /* add end of include file debug info */
3269 if (do_debug) {
3270 put_stabd(N_EINCL, 0, 0);
3272 /* pop include stack */
3273 tcc_close(file);
3274 s1->include_stack_ptr--;
3275 file = *s1->include_stack_ptr;
3276 p = file->buf_ptr;
3277 goto redo_no_start;
3280 break;
3282 case '\n':
3283 if (parse_flags & PARSE_FLAG_LINEFEED) {
3284 tok = TOK_LINEFEED;
3285 } else {
3286 file->line_num++;
3287 tok_flags |= TOK_FLAG_BOL;
3288 p++;
3289 goto redo_no_start;
3291 break;
3293 case '#':
3294 /* XXX: simplify */
3295 PEEKC(c, p);
3296 if ((tok_flags & TOK_FLAG_BOL) &&
3297 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3298 file->buf_ptr = p;
3299 preprocess(tok_flags & TOK_FLAG_BOF);
3300 p = file->buf_ptr;
3301 goto redo_no_start;
3302 } else {
3303 if (c == '#') {
3304 p++;
3305 tok = TOK_TWOSHARPS;
3306 } else {
3307 tok = '#';
3310 break;
3312 case 'a': case 'b': case 'c': case 'd':
3313 case 'e': case 'f': case 'g': case 'h':
3314 case 'i': case 'j': case 'k': case 'l':
3315 case 'm': case 'n': case 'o': case 'p':
3316 case 'q': case 'r': case 's': case 't':
3317 case 'u': case 'v': case 'w': case 'x':
3318 case 'y': case 'z':
3319 case 'A': case 'B': case 'C': case 'D':
3320 case 'E': case 'F': case 'G': case 'H':
3321 case 'I': case 'J': case 'K':
3322 case 'M': case 'N': case 'O': case 'P':
3323 case 'Q': case 'R': case 'S': case 'T':
3324 case 'U': case 'V': case 'W': case 'X':
3325 case 'Y': case 'Z':
3326 case '_':
3327 parse_ident_fast:
3328 p1 = p;
3329 h = TOK_HASH_INIT;
3330 h = TOK_HASH_FUNC(h, c);
3331 p++;
3332 for(;;) {
3333 c = *p;
3334 if (!isidnum_table[c])
3335 break;
3336 h = TOK_HASH_FUNC(h, c);
3337 p++;
3339 if (c != '\\') {
3340 TokenSym **pts;
3341 int len;
3343 /* fast case : no stray found, so we have the full token
3344 and we have already hashed it */
3345 len = p - p1;
3346 h &= (TOK_HASH_SIZE - 1);
3347 pts = &hash_ident[h];
3348 for(;;) {
3349 ts = *pts;
3350 if (!ts)
3351 break;
3352 if (ts->len == len && !memcmp(ts->str, p1, len))
3353 goto token_found;
3354 pts = &(ts->hash_next);
3356 ts = tok_alloc_new(pts, p1, len);
3357 token_found: ;
3358 } else {
3359 /* slower case */
3360 cstr_reset(&tokcstr);
3362 while (p1 < p) {
3363 cstr_ccat(&tokcstr, *p1);
3364 p1++;
3366 p--;
3367 PEEKC(c, p);
3368 parse_ident_slow:
3369 while (isidnum_table[c]) {
3370 cstr_ccat(&tokcstr, c);
3371 PEEKC(c, p);
3373 ts = tok_alloc(tokcstr.data, tokcstr.size);
3375 tok = ts->tok;
3376 break;
3377 case 'L':
3378 t = p[1];
3379 if (t != '\\' && t != '\'' && t != '\"') {
3380 /* fast case */
3381 goto parse_ident_fast;
3382 } else {
3383 PEEKC(c, p);
3384 if (c == '\'' || c == '\"') {
3385 is_long = 1;
3386 goto str_const;
3387 } else {
3388 cstr_reset(&tokcstr);
3389 cstr_ccat(&tokcstr, 'L');
3390 goto parse_ident_slow;
3393 break;
3394 case '0': case '1': case '2': case '3':
3395 case '4': case '5': case '6': case '7':
3396 case '8': case '9':
3398 cstr_reset(&tokcstr);
3399 /* after the first digit, accept digits, alpha, '.' or sign if
3400 prefixed by 'eEpP' */
3401 parse_num:
3402 for(;;) {
3403 t = c;
3404 cstr_ccat(&tokcstr, c);
3405 PEEKC(c, p);
3406 if (!(isnum(c) || isid(c) || c == '.' ||
3407 ((c == '+' || c == '-') &&
3408 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3409 break;
3411 /* We add a trailing '\0' to ease parsing */
3412 cstr_ccat(&tokcstr, '\0');
3413 tokc.cstr = &tokcstr;
3414 tok = TOK_PPNUM;
3415 break;
3416 case '.':
3417 /* special dot handling because it can also start a number */
3418 PEEKC(c, p);
3419 if (isnum(c)) {
3420 cstr_reset(&tokcstr);
3421 cstr_ccat(&tokcstr, '.');
3422 goto parse_num;
3423 } else if (c == '.') {
3424 PEEKC(c, p);
3425 if (c != '.')
3426 expect("'.'");
3427 PEEKC(c, p);
3428 tok = TOK_DOTS;
3429 } else {
3430 tok = '.';
3432 break;
3433 case '\'':
3434 case '\"':
3435 is_long = 0;
3436 str_const:
3438 CString str;
3439 int sep;
3441 sep = c;
3443 /* parse the string */
3444 cstr_new(&str);
3445 p = parse_pp_string(p, sep, &str);
3446 cstr_ccat(&str, '\0');
3448 /* eval the escape (should be done as TOK_PPNUM) */
3449 cstr_reset(&tokcstr);
3450 parse_escape_string(&tokcstr, str.data, is_long);
3451 cstr_free(&str);
3453 if (sep == '\'') {
3454 int char_size;
3455 /* XXX: make it portable */
3456 if (!is_long)
3457 char_size = 1;
3458 else
3459 char_size = sizeof(int);
3460 if (tokcstr.size <= char_size)
3461 error("empty character constant");
3462 if (tokcstr.size > 2 * char_size)
3463 warning("multi-character character constant");
3464 if (!is_long) {
3465 tokc.i = *(int8_t *)tokcstr.data;
3466 tok = TOK_CCHAR;
3467 } else {
3468 tokc.i = *(int *)tokcstr.data;
3469 tok = TOK_LCHAR;
3471 } else {
3472 tokc.cstr = &tokcstr;
3473 if (!is_long)
3474 tok = TOK_STR;
3475 else
3476 tok = TOK_LSTR;
3479 break;
3481 case '<':
3482 PEEKC(c, p);
3483 if (c == '=') {
3484 p++;
3485 tok = TOK_LE;
3486 } else if (c == '<') {
3487 PEEKC(c, p);
3488 if (c == '=') {
3489 p++;
3490 tok = TOK_A_SHL;
3491 } else {
3492 tok = TOK_SHL;
3494 } else {
3495 tok = TOK_LT;
3497 break;
3499 case '>':
3500 PEEKC(c, p);
3501 if (c == '=') {
3502 p++;
3503 tok = TOK_GE;
3504 } else if (c == '>') {
3505 PEEKC(c, p);
3506 if (c == '=') {
3507 p++;
3508 tok = TOK_A_SAR;
3509 } else {
3510 tok = TOK_SAR;
3512 } else {
3513 tok = TOK_GT;
3515 break;
3517 case '&':
3518 PEEKC(c, p);
3519 if (c == '&') {
3520 p++;
3521 tok = TOK_LAND;
3522 } else if (c == '=') {
3523 p++;
3524 tok = TOK_A_AND;
3525 } else {
3526 tok = '&';
3528 break;
3530 case '|':
3531 PEEKC(c, p);
3532 if (c == '|') {
3533 p++;
3534 tok = TOK_LOR;
3535 } else if (c == '=') {
3536 p++;
3537 tok = TOK_A_OR;
3538 } else {
3539 tok = '|';
3541 break;
3543 case '+':
3544 PEEKC(c, p);
3545 if (c == '+') {
3546 p++;
3547 tok = TOK_INC;
3548 } else if (c == '=') {
3549 p++;
3550 tok = TOK_A_ADD;
3551 } else {
3552 tok = '+';
3554 break;
3556 case '-':
3557 PEEKC(c, p);
3558 if (c == '-') {
3559 p++;
3560 tok = TOK_DEC;
3561 } else if (c == '=') {
3562 p++;
3563 tok = TOK_A_SUB;
3564 } else if (c == '>') {
3565 p++;
3566 tok = TOK_ARROW;
3567 } else {
3568 tok = '-';
3570 break;
3572 PARSE2('!', '!', '=', TOK_NE)
3573 PARSE2('=', '=', '=', TOK_EQ)
3574 PARSE2('*', '*', '=', TOK_A_MUL)
3575 PARSE2('%', '%', '=', TOK_A_MOD)
3576 PARSE2('^', '^', '=', TOK_A_XOR)
3578 /* comments or operator */
3579 case '/':
3580 PEEKC(c, p);
3581 if (c == '*') {
3582 p = parse_comment(p);
3583 goto redo_no_start;
3584 } else if (c == '/') {
3585 p = parse_line_comment(p);
3586 goto redo_no_start;
3587 } else if (c == '=') {
3588 p++;
3589 tok = TOK_A_DIV;
3590 } else {
3591 tok = '/';
3593 break;
3595 /* simple tokens */
3596 case '(':
3597 case ')':
3598 case '[':
3599 case ']':
3600 case '{':
3601 case '}':
3602 case ',':
3603 case ';':
3604 case ':':
3605 case '?':
3606 case '~':
3607 case '$': /* only used in assembler */
3608 tok = c;
3609 p++;
3610 break;
3611 default:
3612 error("unrecognized character \\x%02x", c);
3613 break;
3615 file->buf_ptr = p;
3616 tok_flags = 0;
3617 #if defined(PARSE_DEBUG)
3618 printf("token = %s\n", get_tok_str(tok, &tokc));
3619 #endif
3622 /* return next token without macro substitution. Can read input from
3623 macro_ptr buffer */
3624 static void next_nomacro(void)
3626 if (macro_ptr) {
3627 redo:
3628 tok = *macro_ptr;
3629 if (tok) {
3630 TOK_GET(tok, macro_ptr, tokc);
3631 if (tok == TOK_LINENUM) {
3632 file->line_num = tokc.i;
3633 goto redo;
3636 } else {
3637 next_nomacro1();
3641 /* substitute args in macro_str and return allocated string */
3642 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3644 int *st, last_tok, t, notfirst;
3645 Sym *s;
3646 CValue cval;
3647 TokenString str;
3648 CString cstr;
3650 tok_str_new(&str);
3651 last_tok = 0;
3652 while(1) {
3653 TOK_GET(t, macro_str, cval);
3654 if (!t)
3655 break;
3656 if (t == '#') {
3657 /* stringize */
3658 TOK_GET(t, macro_str, cval);
3659 if (!t)
3660 break;
3661 s = sym_find2(args, t);
3662 if (s) {
3663 cstr_new(&cstr);
3664 st = (int *)s->c;
3665 notfirst = 0;
3666 while (*st) {
3667 if (notfirst)
3668 cstr_ccat(&cstr, ' ');
3669 TOK_GET(t, st, cval);
3670 cstr_cat(&cstr, get_tok_str(t, &cval));
3671 notfirst = 1;
3673 cstr_ccat(&cstr, '\0');
3674 #ifdef PP_DEBUG
3675 printf("stringize: %s\n", (char *)cstr.data);
3676 #endif
3677 /* add string */
3678 cval.cstr = &cstr;
3679 tok_str_add2(&str, TOK_STR, &cval);
3680 cstr_free(&cstr);
3681 } else {
3682 tok_str_add2(&str, t, &cval);
3684 } else if (t >= TOK_IDENT) {
3685 s = sym_find2(args, t);
3686 if (s) {
3687 st = (int *)s->c;
3688 /* if '##' is present before or after, no arg substitution */
3689 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3690 /* special case for var arg macros : ## eats the
3691 ',' if empty VA_ARGS variable. */
3692 /* XXX: test of the ',' is not 100%
3693 reliable. should fix it to avoid security
3694 problems */
3695 if (gnu_ext && s->type.t &&
3696 last_tok == TOK_TWOSHARPS &&
3697 str.len >= 2 && str.str[str.len - 2] == ',') {
3698 if (*st == 0) {
3699 /* suppress ',' '##' */
3700 str.len -= 2;
3701 } else {
3702 /* suppress '##' and add variable */
3703 str.len--;
3704 goto add_var;
3706 } else {
3707 int t1;
3708 add_var:
3709 for(;;) {
3710 TOK_GET(t1, st, cval);
3711 if (!t1)
3712 break;
3713 tok_str_add2(&str, t1, &cval);
3716 } else {
3717 /* NOTE: the stream cannot be read when macro
3718 substituing an argument */
3719 macro_subst(&str, nested_list, st, 0);
3721 } else {
3722 tok_str_add(&str, t);
3724 } else {
3725 tok_str_add2(&str, t, &cval);
3727 last_tok = t;
3729 tok_str_add(&str, 0);
3730 return str.str;
3733 static char const ab_month_name[12][4] =
3735 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3736 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3739 /* do macro substitution of current token with macro 's' and add
3740 result to (tok_str,tok_len). 'nested_list' is the list of all
3741 macros we got inside to avoid recursing. Return non zero if no
3742 substitution needs to be done */
3743 static int macro_subst_tok(TokenString *tok_str,
3744 Sym **nested_list, Sym *s, int can_read_stream)
3746 Sym *args, *sa, *sa1;
3747 int mstr_allocated, parlevel, *mstr, t;
3748 TokenString str;
3749 char *cstrval;
3750 CValue cval;
3751 CString cstr;
3753 /* if symbol is a macro, prepare substitution */
3755 /* special macros */
3756 if (tok == TOK___LINE__) {
3757 cval.i = file->line_num;
3758 tok_str_add2(tok_str, TOK_CINT, &cval);
3759 } else if (tok == TOK___FILE__) {
3760 cstrval = file->filename;
3761 goto add_cstr;
3762 tok_str_add2(tok_str, TOK_STR, &cval);
3763 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3764 time_t ti;
3765 struct tm *tm;
3766 char buf[64];
3768 time(&ti);
3769 tm = localtime(&ti);
3770 if (tok == TOK___DATE__) {
3771 snprintf(buf, sizeof(buf), "%s %2d %d",
3772 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3773 } else {
3774 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3775 tm->tm_hour, tm->tm_min, tm->tm_sec);
3777 cstrval = buf;
3778 add_cstr:
3779 cstr_new(&cstr);
3780 cstr_cat(&cstr, cstrval);
3781 cstr_ccat(&cstr, '\0');
3782 cval.cstr = &cstr;
3783 tok_str_add2(tok_str, TOK_STR, &cval);
3784 cstr_free(&cstr);
3785 } else {
3786 mstr = (int *)s->c;
3787 mstr_allocated = 0;
3788 if (s->type.t == MACRO_FUNC) {
3789 /* NOTE: we do not use next_nomacro to avoid eating the
3790 next token. XXX: find better solution */
3791 if (macro_ptr) {
3792 t = *macro_ptr;
3793 if (t == 0 && can_read_stream) {
3794 /* end of macro stream: we must look at the token
3795 after in the file */
3796 macro_ptr = NULL;
3797 goto parse_stream;
3799 } else {
3800 parse_stream:
3801 /* XXX: incorrect with comments */
3802 ch = file->buf_ptr[0];
3803 while (is_space(ch) || ch == '\n')
3804 cinp();
3805 t = ch;
3807 if (t != '(') /* no macro subst */
3808 return -1;
3810 /* argument macro */
3811 next_nomacro();
3812 next_nomacro();
3813 args = NULL;
3814 sa = s->next;
3815 /* NOTE: empty args are allowed, except if no args */
3816 for(;;) {
3817 /* handle '()' case */
3818 if (!args && !sa && tok == ')')
3819 break;
3820 if (!sa)
3821 error("macro '%s' used with too many args",
3822 get_tok_str(s->v, 0));
3823 tok_str_new(&str);
3824 parlevel = 0;
3825 /* NOTE: non zero sa->t indicates VA_ARGS */
3826 while ((parlevel > 0 ||
3827 (tok != ')' &&
3828 (tok != ',' || sa->type.t))) &&
3829 tok != -1) {
3830 if (tok == '(')
3831 parlevel++;
3832 else if (tok == ')')
3833 parlevel--;
3834 tok_str_add2(&str, tok, &tokc);
3835 next_nomacro();
3837 tok_str_add(&str, 0);
3838 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3839 sa = sa->next;
3840 if (tok == ')') {
3841 /* special case for gcc var args: add an empty
3842 var arg argument if it is omitted */
3843 if (sa && sa->type.t && gnu_ext)
3844 continue;
3845 else
3846 break;
3848 if (tok != ',')
3849 expect(",");
3850 next_nomacro();
3852 if (sa) {
3853 error("macro '%s' used with too few args",
3854 get_tok_str(s->v, 0));
3857 /* now subst each arg */
3858 mstr = macro_arg_subst(nested_list, mstr, args);
3859 /* free memory */
3860 sa = args;
3861 while (sa) {
3862 sa1 = sa->prev;
3863 tok_str_free((int *)sa->c);
3864 tcc_free(sa);
3865 sa = sa1;
3867 mstr_allocated = 1;
3869 sym_push2(nested_list, s->v, 0, 0);
3870 macro_subst(tok_str, nested_list, mstr, 1);
3871 /* pop nested defined symbol */
3872 sa1 = *nested_list;
3873 *nested_list = sa1->prev;
3874 tcc_free(sa1);
3875 if (mstr_allocated)
3876 tok_str_free(mstr);
3878 return 0;
3881 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3882 return the resulting string (which must be freed). */
3883 static inline int *macro_twosharps(const int *macro_str)
3885 TokenSym *ts;
3886 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3887 int t;
3888 const char *p1, *p2;
3889 CValue cval;
3890 TokenString macro_str1;
3891 CString cstr;
3893 start_macro_ptr = macro_str;
3894 /* we search the first '##' */
3895 for(;;) {
3896 macro_ptr1 = macro_str;
3897 TOK_GET(t, macro_str, cval);
3898 /* nothing more to do if end of string */
3899 if (t == 0)
3900 return NULL;
3901 if (*macro_str == TOK_TWOSHARPS)
3902 break;
3905 /* we saw '##', so we need more processing to handle it */
3906 cstr_new(&cstr);
3907 tok_str_new(&macro_str1);
3908 tok = t;
3909 tokc = cval;
3911 /* add all tokens seen so far */
3912 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
3913 TOK_GET(t, ptr, cval);
3914 tok_str_add2(&macro_str1, t, &cval);
3916 saved_macro_ptr = macro_ptr;
3917 /* XXX: get rid of the use of macro_ptr here */
3918 macro_ptr = (int *)macro_str;
3919 for(;;) {
3920 while (*macro_ptr == TOK_TWOSHARPS) {
3921 macro_ptr++;
3922 macro_ptr1 = macro_ptr;
3923 t = *macro_ptr;
3924 if (t) {
3925 TOK_GET(t, macro_ptr, cval);
3926 /* We concatenate the two tokens if we have an
3927 identifier or a preprocessing number */
3928 cstr_reset(&cstr);
3929 p1 = get_tok_str(tok, &tokc);
3930 cstr_cat(&cstr, p1);
3931 p2 = get_tok_str(t, &cval);
3932 cstr_cat(&cstr, p2);
3933 cstr_ccat(&cstr, '\0');
3935 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3936 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3937 if (tok == TOK_PPNUM) {
3938 /* if number, then create a number token */
3939 /* NOTE: no need to allocate because
3940 tok_str_add2() does it */
3941 tokc.cstr = &cstr;
3942 } else {
3943 /* if identifier, we must do a test to
3944 validate we have a correct identifier */
3945 if (t == TOK_PPNUM) {
3946 const char *p;
3947 int c;
3949 p = p2;
3950 for(;;) {
3951 c = *p;
3952 if (c == '\0')
3953 break;
3954 p++;
3955 if (!isnum(c) && !isid(c))
3956 goto error_pasting;
3959 ts = tok_alloc(cstr.data, strlen(cstr.data));
3960 tok = ts->tok; /* modify current token */
3962 } else {
3963 const char *str = cstr.data;
3964 const unsigned char *q;
3966 /* we look for a valid token */
3967 /* XXX: do more extensive checks */
3968 if (!strcmp(str, ">>=")) {
3969 tok = TOK_A_SAR;
3970 } else if (!strcmp(str, "<<=")) {
3971 tok = TOK_A_SHL;
3972 } else if (strlen(str) == 2) {
3973 /* search in two bytes table */
3974 q = tok_two_chars;
3975 for(;;) {
3976 if (!*q)
3977 goto error_pasting;
3978 if (q[0] == str[0] && q[1] == str[1])
3979 break;
3980 q += 3;
3982 tok = q[2];
3983 } else {
3984 error_pasting:
3985 /* NOTE: because get_tok_str use a static buffer,
3986 we must save it */
3987 cstr_reset(&cstr);
3988 p1 = get_tok_str(tok, &tokc);
3989 cstr_cat(&cstr, p1);
3990 cstr_ccat(&cstr, '\0');
3991 p2 = get_tok_str(t, &cval);
3992 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
3993 /* cannot merge tokens: just add them separately */
3994 tok_str_add2(&macro_str1, tok, &tokc);
3995 /* XXX: free associated memory ? */
3996 tok = t;
3997 tokc = cval;
4002 tok_str_add2(&macro_str1, tok, &tokc);
4003 next_nomacro();
4004 if (tok == 0)
4005 break;
4007 macro_ptr = (int *)saved_macro_ptr;
4008 cstr_free(&cstr);
4009 tok_str_add(&macro_str1, 0);
4010 return macro_str1.str;
4014 /* do macro substitution of macro_str and add result to
4015 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4016 inside to avoid recursing. */
4017 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4018 const int *macro_str, int can_read_stream)
4020 Sym *s;
4021 int *saved_macro_ptr, *macro_str1;
4022 const int *ptr;
4023 int t, ret;
4024 CValue cval;
4026 /* first scan for '##' operator handling */
4027 ptr = macro_str;
4028 macro_str1 = macro_twosharps(ptr);
4029 if (macro_str1)
4030 ptr = macro_str1;
4031 while (1) {
4032 /* NOTE: ptr == NULL can only happen if tokens are read from
4033 file stream due to a macro function call */
4034 if (ptr == NULL)
4035 break;
4036 TOK_GET(t, ptr, cval);
4037 if (t == 0)
4038 break;
4039 s = define_find(t);
4040 if (s != NULL) {
4041 /* if nested substitution, do nothing */
4042 if (sym_find2(*nested_list, t))
4043 goto no_subst;
4044 saved_macro_ptr = macro_ptr;
4045 macro_ptr = (int *)ptr;
4046 tok = t;
4047 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4048 ptr = (int *)macro_ptr;
4049 macro_ptr = saved_macro_ptr;
4050 if (ret != 0)
4051 goto no_subst;
4052 } else {
4053 no_subst:
4054 tok_str_add2(tok_str, t, &cval);
4057 if (macro_str1)
4058 tok_str_free(macro_str1);
4061 /* return next token with macro substitution */
4062 static void next(void)
4064 Sym *nested_list, *s;
4065 TokenString str;
4067 redo:
4068 next_nomacro();
4069 if (!macro_ptr) {
4070 /* if not reading from macro substituted string, then try
4071 to substitute macros */
4072 if (tok >= TOK_IDENT &&
4073 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4074 s = define_find(tok);
4075 if (s) {
4076 /* we have a macro: we try to substitute */
4077 tok_str_new(&str);
4078 nested_list = NULL;
4079 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4080 /* substitution done, NOTE: maybe empty */
4081 tok_str_add(&str, 0);
4082 macro_ptr = str.str;
4083 macro_ptr_allocated = str.str;
4084 goto redo;
4088 } else {
4089 if (tok == 0) {
4090 /* end of macro or end of unget buffer */
4091 if (unget_buffer_enabled) {
4092 macro_ptr = unget_saved_macro_ptr;
4093 unget_buffer_enabled = 0;
4094 } else {
4095 /* end of macro string: free it */
4096 tok_str_free(macro_ptr_allocated);
4097 macro_ptr = NULL;
4099 goto redo;
4103 /* convert preprocessor tokens into C tokens */
4104 if (tok == TOK_PPNUM &&
4105 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4106 parse_number((char *)tokc.cstr->data);
4110 /* push back current token and set current token to 'last_tok'. Only
4111 identifier case handled for labels. */
4112 static inline void unget_tok(int last_tok)
4114 int i, n;
4115 int *q;
4116 unget_saved_macro_ptr = macro_ptr;
4117 unget_buffer_enabled = 1;
4118 q = unget_saved_buffer;
4119 macro_ptr = q;
4120 *q++ = tok;
4121 n = tok_ext_size(tok) - 1;
4122 for(i=0;i<n;i++)
4123 *q++ = tokc.tab[i];
4124 *q = 0; /* end of token string */
4125 tok = last_tok;
4129 void swap(int *p, int *q)
4131 int t;
4132 t = *p;
4133 *p = *q;
4134 *q = t;
4137 void vsetc(CType *type, int r, CValue *vc)
4139 int v;
4141 if (vtop >= vstack + VSTACK_SIZE)
4142 error("memory full");
4143 /* cannot let cpu flags if other instruction are generated. Also
4144 avoid leaving VT_JMP anywhere except on the top of the stack
4145 because it would complicate the code generator. */
4146 if (vtop >= vstack) {
4147 v = vtop->r & VT_VALMASK;
4148 if (v == VT_CMP || (v & ~1) == VT_JMP)
4149 gv(RC_INT);
4151 vtop++;
4152 vtop->type = *type;
4153 vtop->r = r;
4154 vtop->r2 = VT_CONST;
4155 vtop->c = *vc;
4158 /* push integer constant */
4159 void vpushi(int v)
4161 CValue cval;
4162 cval.i = v;
4163 vsetc(&int_type, VT_CONST, &cval);
4166 /* Return a static symbol pointing to a section */
4167 static Sym *get_sym_ref(CType *type, Section *sec,
4168 unsigned long offset, unsigned long size)
4170 int v;
4171 Sym *sym;
4173 v = anon_sym++;
4174 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4175 sym->type.ref = type->ref;
4176 sym->r = VT_CONST | VT_SYM;
4177 put_extern_sym(sym, sec, offset, size);
4178 return sym;
4181 /* push a reference to a section offset by adding a dummy symbol */
4182 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4184 CValue cval;
4186 cval.ul = 0;
4187 vsetc(type, VT_CONST | VT_SYM, &cval);
4188 vtop->sym = get_sym_ref(type, sec, offset, size);
4191 /* define a new external reference to a symbol 'v' of type 'u' */
4192 static Sym *external_global_sym(int v, CType *type, int r)
4194 Sym *s;
4196 s = sym_find(v);
4197 if (!s) {
4198 /* push forward reference */
4199 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4200 s->type.ref = type->ref;
4201 s->r = r | VT_CONST | VT_SYM;
4203 return s;
4206 /* define a new external reference to a symbol 'v' of type 'u' */
4207 static Sym *external_sym(int v, CType *type, int r)
4209 Sym *s;
4211 s = sym_find(v);
4212 if (!s) {
4213 /* push forward reference */
4214 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4215 s->type.t |= VT_EXTERN;
4216 } else {
4217 if (!is_compatible_types(&s->type, type))
4218 error("incompatible types for redefinition of '%s'",
4219 get_tok_str(v, NULL));
4221 return s;
4224 /* push a reference to global symbol v */
4225 static void vpush_global_sym(CType *type, int v)
4227 Sym *sym;
4228 CValue cval;
4230 sym = external_global_sym(v, type, 0);
4231 cval.ul = 0;
4232 vsetc(type, VT_CONST | VT_SYM, &cval);
4233 vtop->sym = sym;
4236 void vset(CType *type, int r, int v)
4238 CValue cval;
4240 cval.i = v;
4241 vsetc(type, r, &cval);
4244 void vseti(int r, int v)
4246 CType type;
4247 type.t = VT_INT;
4248 vset(&type, r, v);
4251 void vswap(void)
4253 SValue tmp;
4255 tmp = vtop[0];
4256 vtop[0] = vtop[-1];
4257 vtop[-1] = tmp;
4260 void vpushv(SValue *v)
4262 if (vtop >= vstack + VSTACK_SIZE)
4263 error("memory full");
4264 vtop++;
4265 *vtop = *v;
4268 void vdup(void)
4270 vpushv(vtop);
4273 /* save r to the memory stack, and mark it as being free */
4274 void save_reg(int r)
4276 int l, saved, size, align;
4277 SValue *p, sv;
4278 CType *type;
4280 /* modify all stack values */
4281 saved = 0;
4282 l = 0;
4283 for(p=vstack;p<=vtop;p++) {
4284 if ((p->r & VT_VALMASK) == r ||
4285 (p->r2 & VT_VALMASK) == r) {
4286 /* must save value on stack if not already done */
4287 if (!saved) {
4288 /* NOTE: must reload 'r' because r might be equal to r2 */
4289 r = p->r & VT_VALMASK;
4290 /* store register in the stack */
4291 type = &p->type;
4292 if ((p->r & VT_LVAL) ||
4293 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4294 type = &int_type;
4295 size = type_size(type, &align);
4296 loc = (loc - size) & -align;
4297 sv.type.t = type->t;
4298 sv.r = VT_LOCAL | VT_LVAL;
4299 sv.c.ul = loc;
4300 store(r, &sv);
4301 #ifdef TCC_TARGET_I386
4302 /* x86 specific: need to pop fp register ST0 if saved */
4303 if (r == TREG_ST0) {
4304 o(0xd9dd); /* fstp %st(1) */
4306 #endif
4307 /* special long long case */
4308 if ((type->t & VT_BTYPE) == VT_LLONG) {
4309 sv.c.ul += 4;
4310 store(p->r2, &sv);
4312 l = loc;
4313 saved = 1;
4315 /* mark that stack entry as being saved on the stack */
4316 if (p->r & VT_LVAL) {
4317 /* also clear the bounded flag because the
4318 relocation address of the function was stored in
4319 p->c.ul */
4320 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4321 } else {
4322 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4324 p->r2 = VT_CONST;
4325 p->c.ul = l;
4330 /* find a free register of class 'rc'. If none, save one register */
4331 int get_reg(int rc)
4333 int r;
4334 SValue *p;
4336 /* find a free register */
4337 for(r=0;r<NB_REGS;r++) {
4338 if (reg_classes[r] & rc) {
4339 for(p=vstack;p<=vtop;p++) {
4340 if ((p->r & VT_VALMASK) == r ||
4341 (p->r2 & VT_VALMASK) == r)
4342 goto notfound;
4344 return r;
4346 notfound: ;
4349 /* no register left : free the first one on the stack (VERY
4350 IMPORTANT to start from the bottom to ensure that we don't
4351 spill registers used in gen_opi()) */
4352 for(p=vstack;p<=vtop;p++) {
4353 r = p->r & VT_VALMASK;
4354 if (r < VT_CONST && (reg_classes[r] & rc))
4355 goto save_found;
4356 /* also look at second register (if long long) */
4357 r = p->r2 & VT_VALMASK;
4358 if (r < VT_CONST && (reg_classes[r] & rc)) {
4359 save_found:
4360 save_reg(r);
4361 return r;
4364 /* Should never comes here */
4365 return -1;
4368 /* save registers up to (vtop - n) stack entry */
4369 void save_regs(int n)
4371 int r;
4372 SValue *p, *p1;
4373 p1 = vtop - n;
4374 for(p = vstack;p <= p1; p++) {
4375 r = p->r & VT_VALMASK;
4376 if (r < VT_CONST) {
4377 save_reg(r);
4382 /* move register 's' to 'r', and flush previous value of r to memory
4383 if needed */
4384 void move_reg(int r, int s)
4386 SValue sv;
4388 if (r != s) {
4389 save_reg(r);
4390 sv.type.t = VT_INT;
4391 sv.r = s;
4392 sv.c.ul = 0;
4393 load(r, &sv);
4397 /* get address of vtop (vtop MUST BE an lvalue) */
4398 void gaddrof(void)
4400 vtop->r &= ~VT_LVAL;
4401 /* tricky: if saved lvalue, then we can go back to lvalue */
4402 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4403 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4406 #ifdef CONFIG_TCC_BCHECK
4407 /* generate lvalue bound code */
4408 void gbound(void)
4410 int lval_type;
4411 CType type1;
4413 vtop->r &= ~VT_MUSTBOUND;
4414 /* if lvalue, then use checking code before dereferencing */
4415 if (vtop->r & VT_LVAL) {
4416 /* if not VT_BOUNDED value, then make one */
4417 if (!(vtop->r & VT_BOUNDED)) {
4418 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4419 /* must save type because we must set it to int to get pointer */
4420 type1 = vtop->type;
4421 vtop->type.t = VT_INT;
4422 gaddrof();
4423 vpushi(0);
4424 gen_bounded_ptr_add();
4425 vtop->r |= lval_type;
4426 vtop->type = type1;
4428 /* then check for dereferencing */
4429 gen_bounded_ptr_deref();
4432 #endif
4434 /* store vtop a register belonging to class 'rc'. lvalues are
4435 converted to values. Cannot be used if cannot be converted to
4436 register value (such as structures). */
4437 int gv(int rc)
4439 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4440 unsigned long long ll;
4442 /* NOTE: get_reg can modify vstack[] */
4443 if (vtop->type.t & VT_BITFIELD) {
4444 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4445 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4446 /* remove bit field info to avoid loops */
4447 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4448 /* generate shifts */
4449 vpushi(32 - (bit_pos + bit_size));
4450 gen_op(TOK_SHL);
4451 vpushi(32 - bit_size);
4452 /* NOTE: transformed to SHR if unsigned */
4453 gen_op(TOK_SAR);
4454 r = gv(rc);
4455 } else {
4456 if (is_float(vtop->type.t) &&
4457 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4458 Sym *sym;
4459 int *ptr;
4460 unsigned long offset;
4462 /* XXX: unify with initializers handling ? */
4463 /* CPUs usually cannot use float constants, so we store them
4464 generically in data segment */
4465 size = type_size(&vtop->type, &align);
4466 offset = (data_section->data_offset + align - 1) & -align;
4467 data_section->data_offset = offset;
4468 /* XXX: not portable yet */
4469 ptr = section_ptr_add(data_section, size);
4470 size = size >> 2;
4471 for(i=0;i<size;i++)
4472 ptr[i] = vtop->c.tab[i];
4473 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4474 vtop->r |= VT_LVAL | VT_SYM;
4475 vtop->sym = sym;
4476 vtop->c.ul = 0;
4478 #ifdef CONFIG_TCC_BCHECK
4479 if (vtop->r & VT_MUSTBOUND)
4480 gbound();
4481 #endif
4483 r = vtop->r & VT_VALMASK;
4484 /* need to reload if:
4485 - constant
4486 - lvalue (need to dereference pointer)
4487 - already a register, but not in the right class */
4488 if (r >= VT_CONST ||
4489 (vtop->r & VT_LVAL) ||
4490 !(reg_classes[r] & rc) ||
4491 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4492 !(reg_classes[vtop->r2] & rc))) {
4493 r = get_reg(rc);
4494 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4495 /* two register type load : expand to two words
4496 temporarily */
4497 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4498 /* load constant */
4499 ll = vtop->c.ull;
4500 vtop->c.ui = ll; /* first word */
4501 load(r, vtop);
4502 vtop->r = r; /* save register value */
4503 vpushi(ll >> 32); /* second word */
4504 } else if (r >= VT_CONST ||
4505 (vtop->r & VT_LVAL)) {
4506 /* load from memory */
4507 load(r, vtop);
4508 vdup();
4509 vtop[-1].r = r; /* save register value */
4510 /* increment pointer to get second word */
4511 vtop->type.t = VT_INT;
4512 gaddrof();
4513 vpushi(4);
4514 gen_op('+');
4515 vtop->r |= VT_LVAL;
4516 } else {
4517 /* move registers */
4518 load(r, vtop);
4519 vdup();
4520 vtop[-1].r = r; /* save register value */
4521 vtop->r = vtop[-1].r2;
4523 /* allocate second register */
4524 rc2 = RC_INT;
4525 if (rc == RC_IRET)
4526 rc2 = RC_LRET;
4527 r2 = get_reg(rc2);
4528 load(r2, vtop);
4529 vpop();
4530 /* write second register */
4531 vtop->r2 = r2;
4532 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4533 int t1, t;
4534 /* lvalue of scalar type : need to use lvalue type
4535 because of possible cast */
4536 t = vtop->type.t;
4537 t1 = t;
4538 /* compute memory access type */
4539 if (vtop->r & VT_LVAL_BYTE)
4540 t = VT_BYTE;
4541 else if (vtop->r & VT_LVAL_SHORT)
4542 t = VT_SHORT;
4543 if (vtop->r & VT_LVAL_UNSIGNED)
4544 t |= VT_UNSIGNED;
4545 vtop->type.t = t;
4546 load(r, vtop);
4547 /* restore wanted type */
4548 vtop->type.t = t1;
4549 } else {
4550 /* one register type load */
4551 load(r, vtop);
4554 vtop->r = r;
4556 return r;
4559 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4560 void gv2(int rc1, int rc2)
4562 int v;
4564 /* generate more generic register first. But VT_JMP or VT_CMP
4565 values must be generated first in all cases to avoid possible
4566 reload errors */
4567 v = vtop[0].r & VT_VALMASK;
4568 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4569 vswap();
4570 gv(rc1);
4571 vswap();
4572 gv(rc2);
4573 /* test if reload is needed for first register */
4574 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4575 vswap();
4576 gv(rc1);
4577 vswap();
4579 } else {
4580 gv(rc2);
4581 vswap();
4582 gv(rc1);
4583 vswap();
4584 /* test if reload is needed for first register */
4585 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4586 gv(rc2);
4591 /* expand long long on stack in two int registers */
4592 void lexpand(void)
4594 int u;
4596 u = vtop->type.t & VT_UNSIGNED;
4597 gv(RC_INT);
4598 vdup();
4599 vtop[0].r = vtop[-1].r2;
4600 vtop[0].r2 = VT_CONST;
4601 vtop[-1].r2 = VT_CONST;
4602 vtop[0].type.t = VT_INT | u;
4603 vtop[-1].type.t = VT_INT | u;
4606 /* build a long long from two ints */
4607 void lbuild(int t)
4609 gv2(RC_INT, RC_INT);
4610 vtop[-1].r2 = vtop[0].r;
4611 vtop[-1].type.t = t;
4612 vpop();
4615 /* rotate n first stack elements to the bottom
4616 I1 ... In -> I2 ... In I1 [top is right]
4618 void vrotb(int n)
4620 int i;
4621 SValue tmp;
4623 tmp = vtop[-n + 1];
4624 for(i=-n+1;i!=0;i++)
4625 vtop[i] = vtop[i+1];
4626 vtop[0] = tmp;
4629 /* rotate n first stack elements to the top
4630 I1 ... In -> In I1 ... I(n-1) [top is right]
4632 void vrott(int n)
4634 int i;
4635 SValue tmp;
4637 tmp = vtop[0];
4638 for(i = 0;i < n - 1; i++)
4639 vtop[-i] = vtop[-i - 1];
4640 vtop[-n + 1] = tmp;
4643 /* pop stack value */
4644 void vpop(void)
4646 int v;
4647 v = vtop->r & VT_VALMASK;
4648 #ifdef TCC_TARGET_I386
4649 /* for x86, we need to pop the FP stack */
4650 if (v == TREG_ST0 && !nocode_wanted) {
4651 o(0xd9dd); /* fstp %st(1) */
4652 } else
4653 #endif
4654 if (v == VT_JMP || v == VT_JMPI) {
4655 /* need to put correct jump if && or || without test */
4656 gsym(vtop->c.ul);
4658 vtop--;
4661 /* convert stack entry to register and duplicate its value in another
4662 register */
4663 void gv_dup(void)
4665 int rc, t, r, r1;
4666 SValue sv;
4668 t = vtop->type.t;
4669 if ((t & VT_BTYPE) == VT_LLONG) {
4670 lexpand();
4671 gv_dup();
4672 vswap();
4673 vrotb(3);
4674 gv_dup();
4675 vrotb(4);
4676 /* stack: H L L1 H1 */
4677 lbuild(t);
4678 vrotb(3);
4679 vrotb(3);
4680 vswap();
4681 lbuild(t);
4682 vswap();
4683 } else {
4684 /* duplicate value */
4685 rc = RC_INT;
4686 sv.type.t = VT_INT;
4687 if (is_float(t)) {
4688 rc = RC_FLOAT;
4689 sv.type.t = t;
4691 r = gv(rc);
4692 r1 = get_reg(rc);
4693 sv.r = r;
4694 sv.c.ul = 0;
4695 load(r1, &sv); /* move r to r1 */
4696 vdup();
4697 /* duplicates value */
4698 vtop->r = r1;
4702 /* generate CPU independent (unsigned) long long operations */
4703 void gen_opl(int op)
4705 int t, a, b, op1, c, i;
4706 int func;
4707 SValue tmp;
4709 switch(op) {
4710 case '/':
4711 case TOK_PDIV:
4712 func = TOK___divdi3;
4713 goto gen_func;
4714 case TOK_UDIV:
4715 func = TOK___udivdi3;
4716 goto gen_func;
4717 case '%':
4718 func = TOK___moddi3;
4719 goto gen_func;
4720 case TOK_UMOD:
4721 func = TOK___umoddi3;
4722 gen_func:
4723 /* call generic long long function */
4724 vpush_global_sym(&func_old_type, func);
4725 vrott(3);
4726 gfunc_call(2);
4727 vpushi(0);
4728 vtop->r = REG_IRET;
4729 vtop->r2 = REG_LRET;
4730 break;
4731 case '^':
4732 case '&':
4733 case '|':
4734 case '*':
4735 case '+':
4736 case '-':
4737 t = vtop->type.t;
4738 vswap();
4739 lexpand();
4740 vrotb(3);
4741 lexpand();
4742 /* stack: L1 H1 L2 H2 */
4743 tmp = vtop[0];
4744 vtop[0] = vtop[-3];
4745 vtop[-3] = tmp;
4746 tmp = vtop[-2];
4747 vtop[-2] = vtop[-3];
4748 vtop[-3] = tmp;
4749 vswap();
4750 /* stack: H1 H2 L1 L2 */
4751 if (op == '*') {
4752 vpushv(vtop - 1);
4753 vpushv(vtop - 1);
4754 gen_op(TOK_UMULL);
4755 lexpand();
4756 /* stack: H1 H2 L1 L2 ML MH */
4757 for(i=0;i<4;i++)
4758 vrotb(6);
4759 /* stack: ML MH H1 H2 L1 L2 */
4760 tmp = vtop[0];
4761 vtop[0] = vtop[-2];
4762 vtop[-2] = tmp;
4763 /* stack: ML MH H1 L2 H2 L1 */
4764 gen_op('*');
4765 vrotb(3);
4766 vrotb(3);
4767 gen_op('*');
4768 /* stack: ML MH M1 M2 */
4769 gen_op('+');
4770 gen_op('+');
4771 } else if (op == '+' || op == '-') {
4772 /* XXX: add non carry method too (for MIPS or alpha) */
4773 if (op == '+')
4774 op1 = TOK_ADDC1;
4775 else
4776 op1 = TOK_SUBC1;
4777 gen_op(op1);
4778 /* stack: H1 H2 (L1 op L2) */
4779 vrotb(3);
4780 vrotb(3);
4781 gen_op(op1 + 1); /* TOK_xxxC2 */
4782 } else {
4783 gen_op(op);
4784 /* stack: H1 H2 (L1 op L2) */
4785 vrotb(3);
4786 vrotb(3);
4787 /* stack: (L1 op L2) H1 H2 */
4788 gen_op(op);
4789 /* stack: (L1 op L2) (H1 op H2) */
4791 /* stack: L H */
4792 lbuild(t);
4793 break;
4794 case TOK_SAR:
4795 case TOK_SHR:
4796 case TOK_SHL:
4797 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4798 t = vtop[-1].type.t;
4799 vswap();
4800 lexpand();
4801 vrotb(3);
4802 /* stack: L H shift */
4803 c = (int)vtop->c.i;
4804 /* constant: simpler */
4805 /* NOTE: all comments are for SHL. the other cases are
4806 done by swaping words */
4807 vpop();
4808 if (op != TOK_SHL)
4809 vswap();
4810 if (c >= 32) {
4811 /* stack: L H */
4812 vpop();
4813 if (c > 32) {
4814 vpushi(c - 32);
4815 gen_op(op);
4817 if (op != TOK_SAR) {
4818 vpushi(0);
4819 } else {
4820 gv_dup();
4821 vpushi(31);
4822 gen_op(TOK_SAR);
4824 vswap();
4825 } else {
4826 vswap();
4827 gv_dup();
4828 /* stack: H L L */
4829 vpushi(c);
4830 gen_op(op);
4831 vswap();
4832 vpushi(32 - c);
4833 if (op == TOK_SHL)
4834 gen_op(TOK_SHR);
4835 else
4836 gen_op(TOK_SHL);
4837 vrotb(3);
4838 /* stack: L L H */
4839 vpushi(c);
4840 if (op == TOK_SHL)
4841 gen_op(TOK_SHL);
4842 else
4843 gen_op(TOK_SHR);
4844 gen_op('|');
4846 if (op != TOK_SHL)
4847 vswap();
4848 lbuild(t);
4849 } else {
4850 /* XXX: should provide a faster fallback on x86 ? */
4851 switch(op) {
4852 case TOK_SAR:
4853 func = TOK___sardi3;
4854 goto gen_func;
4855 case TOK_SHR:
4856 func = TOK___shrdi3;
4857 goto gen_func;
4858 case TOK_SHL:
4859 func = TOK___shldi3;
4860 goto gen_func;
4863 break;
4864 default:
4865 /* compare operations */
4866 t = vtop->type.t;
4867 vswap();
4868 lexpand();
4869 vrotb(3);
4870 lexpand();
4871 /* stack: L1 H1 L2 H2 */
4872 tmp = vtop[-1];
4873 vtop[-1] = vtop[-2];
4874 vtop[-2] = tmp;
4875 /* stack: L1 L2 H1 H2 */
4876 /* compare high */
4877 op1 = op;
4878 /* when values are equal, we need to compare low words. since
4879 the jump is inverted, we invert the test too. */
4880 if (op1 == TOK_LT)
4881 op1 = TOK_LE;
4882 else if (op1 == TOK_GT)
4883 op1 = TOK_GE;
4884 else if (op1 == TOK_ULT)
4885 op1 = TOK_ULE;
4886 else if (op1 == TOK_UGT)
4887 op1 = TOK_UGE;
4888 a = 0;
4889 b = 0;
4890 gen_op(op1);
4891 if (op1 != TOK_NE) {
4892 a = gtst(1, 0);
4894 if (op != TOK_EQ) {
4895 /* generate non equal test */
4896 /* XXX: NOT PORTABLE yet */
4897 if (a == 0) {
4898 b = gtst(0, 0);
4899 } else {
4900 #ifdef TCC_TARGET_I386
4901 b = psym(0x850f, 0);
4902 #else
4903 error("not implemented");
4904 #endif
4907 /* compare low. Always unsigned */
4908 op1 = op;
4909 if (op1 == TOK_LT)
4910 op1 = TOK_ULT;
4911 else if (op1 == TOK_LE)
4912 op1 = TOK_ULE;
4913 else if (op1 == TOK_GT)
4914 op1 = TOK_UGT;
4915 else if (op1 == TOK_GE)
4916 op1 = TOK_UGE;
4917 gen_op(op1);
4918 a = gtst(1, a);
4919 gsym(b);
4920 vseti(VT_JMPI, a);
4921 break;
4925 /* handle integer constant optimizations and various machine
4926 independent opt */
4927 void gen_opic(int op)
4929 int fc, c1, c2, n;
4930 SValue *v1, *v2;
4932 v1 = vtop - 1;
4933 v2 = vtop;
4934 /* currently, we cannot do computations with forward symbols */
4935 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4936 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4937 if (c1 && c2) {
4938 fc = v2->c.i;
4939 switch(op) {
4940 case '+': v1->c.i += fc; break;
4941 case '-': v1->c.i -= fc; break;
4942 case '&': v1->c.i &= fc; break;
4943 case '^': v1->c.i ^= fc; break;
4944 case '|': v1->c.i |= fc; break;
4945 case '*': v1->c.i *= fc; break;
4947 case TOK_PDIV:
4948 case '/':
4949 case '%':
4950 case TOK_UDIV:
4951 case TOK_UMOD:
4952 /* if division by zero, generate explicit division */
4953 if (fc == 0) {
4954 if (const_wanted)
4955 error("division by zero in constant");
4956 goto general_case;
4958 switch(op) {
4959 default: v1->c.i /= fc; break;
4960 case '%': v1->c.i %= fc; break;
4961 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
4962 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
4964 break;
4965 case TOK_SHL: v1->c.i <<= fc; break;
4966 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
4967 case TOK_SAR: v1->c.i >>= fc; break;
4968 /* tests */
4969 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
4970 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
4971 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
4972 case TOK_NE: v1->c.i = v1->c.i != fc; break;
4973 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
4974 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
4975 case TOK_LT: v1->c.i = v1->c.i < fc; break;
4976 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
4977 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
4978 case TOK_GT: v1->c.i = v1->c.i > fc; break;
4979 /* logical */
4980 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
4981 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
4982 default:
4983 goto general_case;
4985 vtop--;
4986 } else {
4987 /* if commutative ops, put c2 as constant */
4988 if (c1 && (op == '+' || op == '&' || op == '^' ||
4989 op == '|' || op == '*')) {
4990 vswap();
4991 swap(&c1, &c2);
4993 fc = vtop->c.i;
4994 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
4995 op == TOK_PDIV) &&
4996 fc == 1) ||
4997 ((op == '+' || op == '-' || op == '|' || op == '^' ||
4998 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
4999 fc == 0) ||
5000 (op == '&' &&
5001 fc == -1))) {
5002 /* nothing to do */
5003 vtop--;
5004 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5005 /* try to use shifts instead of muls or divs */
5006 if (fc > 0 && (fc & (fc - 1)) == 0) {
5007 n = -1;
5008 while (fc) {
5009 fc >>= 1;
5010 n++;
5012 vtop->c.i = n;
5013 if (op == '*')
5014 op = TOK_SHL;
5015 else if (op == TOK_PDIV)
5016 op = TOK_SAR;
5017 else
5018 op = TOK_SHR;
5020 goto general_case;
5021 } else if (c2 && (op == '+' || op == '-') &&
5022 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5023 (VT_CONST | VT_SYM)) {
5024 /* symbol + constant case */
5025 if (op == '-')
5026 fc = -fc;
5027 vtop--;
5028 vtop->c.i += fc;
5029 } else {
5030 general_case:
5031 if (!nocode_wanted) {
5032 /* call low level op generator */
5033 gen_opi(op);
5034 } else {
5035 vtop--;
5041 /* generate a floating point operation with constant propagation */
5042 void gen_opif(int op)
5044 int c1, c2;
5045 SValue *v1, *v2;
5046 long double f1, f2;
5048 v1 = vtop - 1;
5049 v2 = vtop;
5050 /* currently, we cannot do computations with forward symbols */
5051 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5052 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5053 if (c1 && c2) {
5054 if (v1->type.t == VT_FLOAT) {
5055 f1 = v1->c.f;
5056 f2 = v2->c.f;
5057 } else if (v1->type.t == VT_DOUBLE) {
5058 f1 = v1->c.d;
5059 f2 = v2->c.d;
5060 } else {
5061 f1 = v1->c.ld;
5062 f2 = v2->c.ld;
5065 /* NOTE: we only do constant propagation if finite number (not
5066 NaN or infinity) (ANSI spec) */
5067 if (!ieee_finite(f1) || !ieee_finite(f2))
5068 goto general_case;
5070 switch(op) {
5071 case '+': f1 += f2; break;
5072 case '-': f1 -= f2; break;
5073 case '*': f1 *= f2; break;
5074 case '/':
5075 if (f2 == 0.0) {
5076 if (const_wanted)
5077 error("division by zero in constant");
5078 goto general_case;
5080 f1 /= f2;
5081 break;
5082 /* XXX: also handles tests ? */
5083 default:
5084 goto general_case;
5086 /* XXX: overflow test ? */
5087 if (v1->type.t == VT_FLOAT) {
5088 v1->c.f = f1;
5089 } else if (v1->type.t == VT_DOUBLE) {
5090 v1->c.d = f1;
5091 } else {
5092 v1->c.ld = f1;
5094 vtop--;
5095 } else {
5096 general_case:
5097 if (!nocode_wanted) {
5098 gen_opf(op);
5099 } else {
5100 vtop--;
5105 static int pointed_size(CType *type)
5107 int align;
5108 return type_size(pointed_type(type), &align);
5111 static inline int is_null_pointer(SValue *p)
5113 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5114 return 0;
5115 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5116 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5119 static inline int is_integer_btype(int bt)
5121 return (bt == VT_BYTE || bt == VT_SHORT ||
5122 bt == VT_INT || bt == VT_LLONG);
5125 /* check types for comparison or substraction of pointers */
5126 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5128 CType *type1, *type2, tmp_type1, tmp_type2;
5129 int bt1, bt2;
5131 /* null pointers are accepted for all comparisons as gcc */
5132 if (is_null_pointer(p1) || is_null_pointer(p2))
5133 return;
5134 type1 = &p1->type;
5135 type2 = &p2->type;
5136 bt1 = type1->t & VT_BTYPE;
5137 bt2 = type2->t & VT_BTYPE;
5138 /* accept comparison between pointer and integer with a warning */
5139 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5140 warning("comparison between pointer and integer");
5141 return;
5144 /* both must be pointers or implicit function pointers */
5145 if (bt1 == VT_PTR) {
5146 type1 = pointed_type(type1);
5147 } else if (bt1 != VT_FUNC)
5148 goto invalid_operands;
5150 if (bt2 == VT_PTR) {
5151 type2 = pointed_type(type2);
5152 } else if (bt2 != VT_FUNC) {
5153 invalid_operands:
5154 error("invalid operands to binary %s", get_tok_str(op, NULL));
5156 if ((type1->t & VT_BTYPE) == VT_VOID ||
5157 (type2->t & VT_BTYPE) == VT_VOID)
5158 return;
5159 tmp_type1 = *type1;
5160 tmp_type2 = *type2;
5161 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5162 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5163 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5164 /* gcc-like error if '-' is used */
5165 if (op == '-')
5166 goto invalid_operands;
5167 else
5168 warning("comparison of distinct pointer types lacks a cast");
5172 /* generic gen_op: handles types problems */
5173 void gen_op(int op)
5175 int u, t1, t2, bt1, bt2, t;
5176 CType type1;
5178 t1 = vtop[-1].type.t;
5179 t2 = vtop[0].type.t;
5180 bt1 = t1 & VT_BTYPE;
5181 bt2 = t2 & VT_BTYPE;
5183 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5184 /* at least one operand is a pointer */
5185 /* relationnal op: must be both pointers */
5186 if (op >= TOK_ULT && op <= TOK_GT) {
5187 check_comparison_pointer_types(vtop - 1, vtop, op);
5188 /* pointers are handled are unsigned */
5189 t = VT_INT | VT_UNSIGNED;
5190 goto std_op;
5192 /* if both pointers, then it must be the '-' op */
5193 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5194 if (op != '-')
5195 error("cannot use pointers here");
5196 check_comparison_pointer_types(vtop - 1, vtop, op);
5197 /* XXX: check that types are compatible */
5198 u = pointed_size(&vtop[-1].type);
5199 gen_opic(op);
5200 /* set to integer type */
5201 vtop->type.t = VT_INT;
5202 vpushi(u);
5203 gen_op(TOK_PDIV);
5204 } else {
5205 /* exactly one pointer : must be '+' or '-'. */
5206 if (op != '-' && op != '+')
5207 error("cannot use pointers here");
5208 /* Put pointer as first operand */
5209 if (bt2 == VT_PTR) {
5210 vswap();
5211 swap(&t1, &t2);
5213 type1 = vtop[-1].type;
5214 /* XXX: cast to int ? (long long case) */
5215 vpushi(pointed_size(&vtop[-1].type));
5216 gen_op('*');
5217 #ifdef CONFIG_TCC_BCHECK
5218 /* if evaluating constant expression, no code should be
5219 generated, so no bound check */
5220 if (do_bounds_check && !const_wanted) {
5221 /* if bounded pointers, we generate a special code to
5222 test bounds */
5223 if (op == '-') {
5224 vpushi(0);
5225 vswap();
5226 gen_op('-');
5228 gen_bounded_ptr_add();
5229 } else
5230 #endif
5232 gen_opic(op);
5234 /* put again type if gen_opic() swaped operands */
5235 vtop->type = type1;
5237 } else if (is_float(bt1) || is_float(bt2)) {
5238 /* compute bigger type and do implicit casts */
5239 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5240 t = VT_LDOUBLE;
5241 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5242 t = VT_DOUBLE;
5243 } else {
5244 t = VT_FLOAT;
5246 /* floats can only be used for a few operations */
5247 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5248 (op < TOK_ULT || op > TOK_GT))
5249 error("invalid operands for binary operation");
5250 goto std_op;
5251 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5252 /* cast to biggest op */
5253 t = VT_LLONG;
5254 /* convert to unsigned if it does not fit in a long long */
5255 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5256 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5257 t |= VT_UNSIGNED;
5258 goto std_op;
5259 } else {
5260 /* integer operations */
5261 t = VT_INT;
5262 /* convert to unsigned if it does not fit in an integer */
5263 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5264 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5265 t |= VT_UNSIGNED;
5266 std_op:
5267 /* XXX: currently, some unsigned operations are explicit, so
5268 we modify them here */
5269 if (t & VT_UNSIGNED) {
5270 if (op == TOK_SAR)
5271 op = TOK_SHR;
5272 else if (op == '/')
5273 op = TOK_UDIV;
5274 else if (op == '%')
5275 op = TOK_UMOD;
5276 else if (op == TOK_LT)
5277 op = TOK_ULT;
5278 else if (op == TOK_GT)
5279 op = TOK_UGT;
5280 else if (op == TOK_LE)
5281 op = TOK_ULE;
5282 else if (op == TOK_GE)
5283 op = TOK_UGE;
5285 vswap();
5286 type1.t = t;
5287 gen_cast(&type1);
5288 vswap();
5289 /* special case for shifts and long long: we keep the shift as
5290 an integer */
5291 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5292 type1.t = VT_INT;
5293 gen_cast(&type1);
5294 if (is_float(t))
5295 gen_opif(op);
5296 else if ((t & VT_BTYPE) == VT_LLONG)
5297 gen_opl(op);
5298 else
5299 gen_opic(op);
5300 if (op >= TOK_ULT && op <= TOK_GT) {
5301 /* relationnal op: the result is an int */
5302 vtop->type.t = VT_INT;
5303 } else {
5304 vtop->type.t = t;
5309 /* generic itof for unsigned long long case */
5310 void gen_cvt_itof1(int t)
5312 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5313 (VT_LLONG | VT_UNSIGNED)) {
5315 if (t == VT_FLOAT)
5316 vpush_global_sym(&func_old_type, TOK___ulltof);
5317 else if (t == VT_DOUBLE)
5318 vpush_global_sym(&func_old_type, TOK___ulltod);
5319 else
5320 vpush_global_sym(&func_old_type, TOK___ulltold);
5321 vrott(2);
5322 gfunc_call(1);
5323 vpushi(0);
5324 vtop->r = REG_FRET;
5325 } else {
5326 gen_cvt_itof(t);
5330 /* generic ftoi for unsigned long long case */
5331 void gen_cvt_ftoi1(int t)
5333 int st;
5335 if (t == (VT_LLONG | VT_UNSIGNED)) {
5336 /* not handled natively */
5337 st = vtop->type.t & VT_BTYPE;
5338 if (st == VT_FLOAT)
5339 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5340 else if (st == VT_DOUBLE)
5341 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5342 else
5343 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5344 vrott(2);
5345 gfunc_call(1);
5346 vpushi(0);
5347 vtop->r = REG_IRET;
5348 vtop->r2 = REG_LRET;
5349 } else {
5350 gen_cvt_ftoi(t);
5354 /* force char or short cast */
5355 void force_charshort_cast(int t)
5357 int bits, dbt;
5358 dbt = t & VT_BTYPE;
5359 /* XXX: add optimization if lvalue : just change type and offset */
5360 if (dbt == VT_BYTE)
5361 bits = 8;
5362 else
5363 bits = 16;
5364 if (t & VT_UNSIGNED) {
5365 vpushi((1 << bits) - 1);
5366 gen_op('&');
5367 } else {
5368 bits = 32 - bits;
5369 vpushi(bits);
5370 gen_op(TOK_SHL);
5371 vpushi(bits);
5372 gen_op(TOK_SAR);
5376 /* cast 'vtop' to 'type' */
5377 static void gen_cast(CType *type)
5379 int sbt, dbt, sf, df, c;
5381 /* special delayed cast for char/short */
5382 /* XXX: in some cases (multiple cascaded casts), it may still
5383 be incorrect */
5384 if (vtop->r & VT_MUSTCAST) {
5385 vtop->r &= ~VT_MUSTCAST;
5386 force_charshort_cast(vtop->type.t);
5389 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5390 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5392 if (sbt != dbt && !nocode_wanted) {
5393 sf = is_float(sbt);
5394 df = is_float(dbt);
5395 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5396 if (sf && df) {
5397 /* convert from fp to fp */
5398 if (c) {
5399 /* constant case: we can do it now */
5400 /* XXX: in ISOC, cannot do it if error in convert */
5401 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5402 vtop->c.f = (float)vtop->c.d;
5403 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5404 vtop->c.f = (float)vtop->c.ld;
5405 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5406 vtop->c.d = (double)vtop->c.f;
5407 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5408 vtop->c.d = (double)vtop->c.ld;
5409 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5410 vtop->c.ld = (long double)vtop->c.f;
5411 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5412 vtop->c.ld = (long double)vtop->c.d;
5413 } else {
5414 /* non constant case: generate code */
5415 gen_cvt_ftof(dbt);
5417 } else if (df) {
5418 /* convert int to fp */
5419 if (c) {
5420 switch(sbt) {
5421 case VT_LLONG | VT_UNSIGNED:
5422 case VT_LLONG:
5423 /* XXX: add const cases for long long */
5424 goto do_itof;
5425 case VT_INT | VT_UNSIGNED:
5426 switch(dbt) {
5427 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5428 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5429 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5431 break;
5432 default:
5433 switch(dbt) {
5434 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5435 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5436 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5438 break;
5440 } else {
5441 do_itof:
5442 gen_cvt_itof1(dbt);
5444 } else if (sf) {
5445 /* convert fp to int */
5446 /* we handle char/short/etc... with generic code */
5447 if (dbt != (VT_INT | VT_UNSIGNED) &&
5448 dbt != (VT_LLONG | VT_UNSIGNED) &&
5449 dbt != VT_LLONG)
5450 dbt = VT_INT;
5451 if (c) {
5452 switch(dbt) {
5453 case VT_LLONG | VT_UNSIGNED:
5454 case VT_LLONG:
5455 /* XXX: add const cases for long long */
5456 goto do_ftoi;
5457 case VT_INT | VT_UNSIGNED:
5458 switch(sbt) {
5459 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5460 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5461 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5463 break;
5464 default:
5465 /* int case */
5466 switch(sbt) {
5467 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5468 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5469 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5471 break;
5473 } else {
5474 do_ftoi:
5475 gen_cvt_ftoi1(dbt);
5477 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5478 /* additional cast for char/short/bool... */
5479 vtop->type.t = dbt;
5480 gen_cast(type);
5482 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5483 if ((sbt & VT_BTYPE) != VT_LLONG) {
5484 /* scalar to long long */
5485 if (c) {
5486 if (sbt == (VT_INT | VT_UNSIGNED))
5487 vtop->c.ll = vtop->c.ui;
5488 else
5489 vtop->c.ll = vtop->c.i;
5490 } else {
5491 /* machine independent conversion */
5492 gv(RC_INT);
5493 /* generate high word */
5494 if (sbt == (VT_INT | VT_UNSIGNED)) {
5495 vpushi(0);
5496 gv(RC_INT);
5497 } else {
5498 gv_dup();
5499 vpushi(31);
5500 gen_op(TOK_SAR);
5502 /* patch second register */
5503 vtop[-1].r2 = vtop->r;
5504 vpop();
5507 } else if (dbt == VT_BOOL) {
5508 /* scalar to bool */
5509 vpushi(0);
5510 gen_op(TOK_NE);
5511 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5512 (dbt & VT_BTYPE) == VT_SHORT) {
5513 force_charshort_cast(dbt);
5514 } else if ((dbt & VT_BTYPE) == VT_INT) {
5515 /* scalar to int */
5516 if (sbt == VT_LLONG) {
5517 /* from long long: just take low order word */
5518 lexpand();
5519 vpop();
5521 /* if lvalue and single word type, nothing to do because
5522 the lvalue already contains the real type size (see
5523 VT_LVAL_xxx constants) */
5526 vtop->type = *type;
5529 /* return type size. Put alignment at 'a' */
5530 static int type_size(CType *type, int *a)
5532 Sym *s;
5533 int bt;
5535 bt = type->t & VT_BTYPE;
5536 if (bt == VT_STRUCT) {
5537 /* struct/union */
5538 s = type->ref;
5539 *a = s->r;
5540 return s->c;
5541 } else if (bt == VT_PTR) {
5542 if (type->t & VT_ARRAY) {
5543 s = type->ref;
5544 return type_size(&s->type, a) * s->c;
5545 } else {
5546 *a = PTR_SIZE;
5547 return PTR_SIZE;
5549 } else if (bt == VT_LDOUBLE) {
5550 *a = LDOUBLE_ALIGN;
5551 return LDOUBLE_SIZE;
5552 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5553 *a = 4; /* XXX: i386 specific */
5554 return 8;
5555 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5556 *a = 4;
5557 return 4;
5558 } else if (bt == VT_SHORT) {
5559 *a = 2;
5560 return 2;
5561 } else {
5562 /* char, void, function, _Bool */
5563 *a = 1;
5564 return 1;
5568 /* return the pointed type of t */
5569 static inline CType *pointed_type(CType *type)
5571 return &type->ref->type;
5574 /* modify type so that its it is a pointer to type. */
5575 static void mk_pointer(CType *type)
5577 Sym *s;
5578 s = sym_push(SYM_FIELD, type, 0, -1);
5579 type->t = VT_PTR | (type->t & ~VT_TYPE);
5580 type->ref = s;
5583 /* compare function types. OLD functions match any new functions */
5584 static int is_compatible_func(CType *type1, CType *type2)
5586 Sym *s1, *s2;
5588 s1 = type1->ref;
5589 s2 = type2->ref;
5590 if (!is_compatible_types(&s1->type, &s2->type))
5591 return 0;
5592 /* XXX: not complete */
5593 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5594 return 1;
5595 if (s1->c != s2->c)
5596 return 0;
5597 while (s1 != NULL) {
5598 if (s2 == NULL)
5599 return 0;
5600 if (!is_compatible_types(&s1->type, &s2->type))
5601 return 0;
5602 s1 = s1->next;
5603 s2 = s2->next;
5605 if (s2)
5606 return 0;
5607 return 1;
5610 /* return true if type1 and type2 are exactly the same (including
5611 qualifiers).
5613 - enums are not checked as gcc __builtin_types_compatible_p ()
5615 static int is_compatible_types(CType *type1, CType *type2)
5617 int bt1, t1, t2;
5619 t1 = type1->t & VT_TYPE;
5620 t2 = type2->t & VT_TYPE;
5621 /* XXX: bitfields ? */
5622 if (t1 != t2)
5623 return 0;
5624 /* test more complicated cases */
5625 bt1 = t1 & VT_BTYPE;
5626 if (bt1 == VT_PTR) {
5627 type1 = pointed_type(type1);
5628 type2 = pointed_type(type2);
5629 return is_compatible_types(type1, type2);
5630 } else if (bt1 == VT_STRUCT) {
5631 return (type1->ref == type2->ref);
5632 } else if (bt1 == VT_FUNC) {
5633 return is_compatible_func(type1, type2);
5634 } else {
5635 return 1;
5639 /* print a type. If 'varstr' is not NULL, then the variable is also
5640 printed in the type */
5641 /* XXX: union */
5642 /* XXX: add array and function pointers */
5643 void type_to_str(char *buf, int buf_size,
5644 CType *type, const char *varstr)
5646 int bt, v, t;
5647 Sym *s, *sa;
5648 char buf1[256];
5649 const char *tstr;
5651 t = type->t & VT_TYPE;
5652 bt = t & VT_BTYPE;
5653 buf[0] = '\0';
5654 if (t & VT_CONSTANT)
5655 pstrcat(buf, buf_size, "const ");
5656 if (t & VT_VOLATILE)
5657 pstrcat(buf, buf_size, "volatile ");
5658 if (t & VT_UNSIGNED)
5659 pstrcat(buf, buf_size, "unsigned ");
5660 switch(bt) {
5661 case VT_VOID:
5662 tstr = "void";
5663 goto add_tstr;
5664 case VT_BOOL:
5665 tstr = "_Bool";
5666 goto add_tstr;
5667 case VT_BYTE:
5668 tstr = "char";
5669 goto add_tstr;
5670 case VT_SHORT:
5671 tstr = "short";
5672 goto add_tstr;
5673 case VT_INT:
5674 tstr = "int";
5675 goto add_tstr;
5676 case VT_LONG:
5677 tstr = "long";
5678 goto add_tstr;
5679 case VT_LLONG:
5680 tstr = "long long";
5681 goto add_tstr;
5682 case VT_FLOAT:
5683 tstr = "float";
5684 goto add_tstr;
5685 case VT_DOUBLE:
5686 tstr = "double";
5687 goto add_tstr;
5688 case VT_LDOUBLE:
5689 tstr = "long double";
5690 add_tstr:
5691 pstrcat(buf, buf_size, tstr);
5692 break;
5693 case VT_ENUM:
5694 case VT_STRUCT:
5695 if (bt == VT_STRUCT)
5696 tstr = "struct ";
5697 else
5698 tstr = "enum ";
5699 pstrcat(buf, buf_size, tstr);
5700 v = type->ref->v & ~SYM_STRUCT;
5701 if (v >= SYM_FIRST_ANOM)
5702 pstrcat(buf, buf_size, "<anonymous>");
5703 else
5704 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5705 break;
5706 case VT_FUNC:
5707 s = type->ref;
5708 type_to_str(buf, buf_size, &s->type, varstr);
5709 pstrcat(buf, buf_size, "(");
5710 sa = s->next;
5711 while (sa != NULL) {
5712 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5713 pstrcat(buf, buf_size, buf1);
5714 sa = sa->next;
5715 if (sa)
5716 pstrcat(buf, buf_size, ", ");
5718 pstrcat(buf, buf_size, ")");
5719 goto no_var;
5720 case VT_PTR:
5721 s = type->ref;
5722 pstrcpy(buf1, sizeof(buf1), "*");
5723 if (varstr)
5724 pstrcat(buf1, sizeof(buf1), varstr);
5725 type_to_str(buf, buf_size, &s->type, buf1);
5726 goto no_var;
5728 if (varstr) {
5729 pstrcat(buf, buf_size, " ");
5730 pstrcat(buf, buf_size, varstr);
5732 no_var: ;
5735 /* verify type compatibility to store vtop in 'dt' type, and generate
5736 casts if needed. */
5737 static void gen_assign_cast(CType *dt)
5739 CType *st, *type1, *type2, tmp_type1, tmp_type2;
5740 char buf1[256], buf2[256];
5741 int dbt, sbt;
5743 st = &vtop->type; /* source type */
5744 dbt = dt->t & VT_BTYPE;
5745 sbt = st->t & VT_BTYPE;
5746 if (dt->t & VT_CONSTANT)
5747 warning("assignment of read-only location");
5748 switch(dbt) {
5749 case VT_PTR:
5750 /* special cases for pointers */
5751 /* '0' can also be a pointer */
5752 if (is_null_pointer(vtop))
5753 goto type_ok;
5754 /* accept implicit pointer to integer cast with warning */
5755 if (is_integer_btype(sbt)) {
5756 warning("assignment makes pointer from integer without a cast");
5757 goto type_ok;
5759 type1 = pointed_type(dt);
5760 /* a function is implicitely a function pointer */
5761 if (sbt == VT_FUNC) {
5762 if ((type1->t & VT_BTYPE) != VT_VOID &&
5763 !is_compatible_types(pointed_type(dt), st))
5764 goto error;
5765 else
5766 goto type_ok;
5768 if (sbt != VT_PTR)
5769 goto error;
5770 type2 = pointed_type(st);
5771 if ((type1->t & VT_BTYPE) == VT_VOID ||
5772 (type2->t & VT_BTYPE) == VT_VOID) {
5773 /* void * can match anything */
5774 } else {
5775 /* exact type match, except for unsigned */
5776 tmp_type1 = *type1;
5777 tmp_type2 = *type2;
5778 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5779 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5780 if (!is_compatible_types(&tmp_type1, &tmp_type2))
5781 goto error;
5783 /* check const and volatile */
5784 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
5785 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
5786 warning("assignment discards qualifiers from pointer target type");
5787 break;
5788 case VT_BYTE:
5789 case VT_SHORT:
5790 case VT_INT:
5791 case VT_LLONG:
5792 if (sbt == VT_PTR || sbt == VT_FUNC) {
5793 warning("assignment makes integer from pointer without a cast");
5795 /* XXX: more tests */
5796 break;
5797 case VT_STRUCT:
5798 if (!is_compatible_types(dt, st)) {
5799 error:
5800 type_to_str(buf1, sizeof(buf1), st, NULL);
5801 type_to_str(buf2, sizeof(buf2), dt, NULL);
5802 error("cannot cast '%s' to '%s'", buf1, buf2);
5804 break;
5806 type_ok:
5807 gen_cast(dt);
5810 /* store vtop in lvalue pushed on stack */
5811 void vstore(void)
5813 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5815 ft = vtop[-1].type.t;
5816 sbt = vtop->type.t & VT_BTYPE;
5817 dbt = ft & VT_BTYPE;
5818 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5819 (sbt == VT_INT && dbt == VT_SHORT)) {
5820 /* optimize char/short casts */
5821 delayed_cast = VT_MUSTCAST;
5822 vtop->type.t = ft & VT_TYPE;
5823 /* XXX: factorize */
5824 if (ft & VT_CONSTANT)
5825 warning("assignment of read-only location");
5826 } else {
5827 delayed_cast = 0;
5828 gen_assign_cast(&vtop[-1].type);
5831 if (sbt == VT_STRUCT) {
5832 /* if structure, only generate pointer */
5833 /* structure assignment : generate memcpy */
5834 /* XXX: optimize if small size */
5835 if (!nocode_wanted) {
5836 size = type_size(&vtop->type, &align);
5838 vpush_global_sym(&func_old_type, TOK_memcpy);
5840 /* destination */
5841 vpushv(vtop - 2);
5842 vtop->type.t = VT_INT;
5843 gaddrof();
5844 /* source */
5845 vpushv(vtop - 2);
5846 vtop->type.t = VT_INT;
5847 gaddrof();
5848 /* type size */
5849 vpushi(size);
5850 gfunc_call(3);
5852 vswap();
5853 vpop();
5854 } else {
5855 vswap();
5856 vpop();
5858 /* leave source on stack */
5859 } else if (ft & VT_BITFIELD) {
5860 /* bitfield store handling */
5861 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5862 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5863 /* remove bit field info to avoid loops */
5864 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5866 /* duplicate destination */
5867 vdup();
5868 vtop[-1] = vtop[-2];
5870 /* mask and shift source */
5871 vpushi((1 << bit_size) - 1);
5872 gen_op('&');
5873 vpushi(bit_pos);
5874 gen_op(TOK_SHL);
5875 /* load destination, mask and or with source */
5876 vswap();
5877 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5878 gen_op('&');
5879 gen_op('|');
5880 /* store result */
5881 vstore();
5882 } else {
5883 #ifdef CONFIG_TCC_BCHECK
5884 /* bound check case */
5885 if (vtop[-1].r & VT_MUSTBOUND) {
5886 vswap();
5887 gbound();
5888 vswap();
5890 #endif
5891 if (!nocode_wanted) {
5892 rc = RC_INT;
5893 if (is_float(ft))
5894 rc = RC_FLOAT;
5895 r = gv(rc); /* generate value */
5896 /* if lvalue was saved on stack, must read it */
5897 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5898 SValue sv;
5899 t = get_reg(RC_INT);
5900 sv.type.t = VT_INT;
5901 sv.r = VT_LOCAL | VT_LVAL;
5902 sv.c.ul = vtop[-1].c.ul;
5903 load(t, &sv);
5904 vtop[-1].r = t | VT_LVAL;
5906 store(r, vtop - 1);
5907 /* two word case handling : store second register at word + 4 */
5908 if ((ft & VT_BTYPE) == VT_LLONG) {
5909 vswap();
5910 /* convert to int to increment easily */
5911 vtop->type.t = VT_INT;
5912 gaddrof();
5913 vpushi(4);
5914 gen_op('+');
5915 vtop->r |= VT_LVAL;
5916 vswap();
5917 /* XXX: it works because r2 is spilled last ! */
5918 store(vtop->r2, vtop - 1);
5921 vswap();
5922 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5923 vtop->r |= delayed_cast;
5927 /* post defines POST/PRE add. c is the token ++ or -- */
5928 void inc(int post, int c)
5930 test_lvalue();
5931 vdup(); /* save lvalue */
5932 if (post) {
5933 gv_dup(); /* duplicate value */
5934 vrotb(3);
5935 vrotb(3);
5937 /* add constant */
5938 vpushi(c - TOK_MID);
5939 gen_op('+');
5940 vstore(); /* store value */
5941 if (post)
5942 vpop(); /* if post op, return saved value */
5945 /* Parse GNUC __attribute__ extension. Currently, the following
5946 extensions are recognized:
5947 - aligned(n) : set data/function alignment.
5948 - section(x) : generate data/code in this section.
5949 - unused : currently ignored, but may be used someday.
5951 static void parse_attribute(AttributeDef *ad)
5953 int t, n;
5955 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
5956 next();
5957 skip('(');
5958 skip('(');
5959 while (tok != ')') {
5960 if (tok < TOK_IDENT)
5961 expect("attribute name");
5962 t = tok;
5963 next();
5964 switch(t) {
5965 case TOK_SECTION1:
5966 case TOK_SECTION2:
5967 skip('(');
5968 if (tok != TOK_STR)
5969 expect("section name");
5970 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
5971 next();
5972 skip(')');
5973 break;
5974 case TOK_ALIGNED1:
5975 case TOK_ALIGNED2:
5976 if (tok == '(') {
5977 next();
5978 n = expr_const();
5979 if (n <= 0 || (n & (n - 1)) != 0)
5980 error("alignment must be a positive power of two");
5981 skip(')');
5982 } else {
5983 n = MAX_ALIGN;
5985 ad->aligned = n;
5986 break;
5987 case TOK_UNUSED1:
5988 case TOK_UNUSED2:
5989 /* currently, no need to handle it because tcc does not
5990 track unused objects */
5991 break;
5992 case TOK_NORETURN1:
5993 case TOK_NORETURN2:
5994 /* currently, no need to handle it because tcc does not
5995 track unused objects */
5996 break;
5997 case TOK_CDECL1:
5998 case TOK_CDECL2:
5999 case TOK_CDECL3:
6000 ad->func_call = FUNC_CDECL;
6001 break;
6002 case TOK_STDCALL1:
6003 case TOK_STDCALL2:
6004 case TOK_STDCALL3:
6005 ad->func_call = FUNC_STDCALL;
6006 break;
6007 default:
6008 if (tcc_state->warn_unsupported)
6009 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6010 /* skip parameters */
6011 /* XXX: skip parenthesis too */
6012 if (tok == '(') {
6013 next();
6014 while (tok != ')' && tok != -1)
6015 next();
6016 next();
6018 break;
6020 if (tok != ',')
6021 break;
6022 next();
6024 skip(')');
6025 skip(')');
6029 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6030 static void struct_decl(CType *type, int u)
6032 int a, v, size, align, maxalign, c, offset;
6033 int bit_size, bit_pos, bsize, bt, lbit_pos;
6034 Sym *s, *ss, **ps;
6035 AttributeDef ad;
6036 CType type1, btype;
6038 a = tok; /* save decl type */
6039 next();
6040 if (tok != '{') {
6041 v = tok;
6042 next();
6043 /* struct already defined ? return it */
6044 if (v < TOK_IDENT)
6045 expect("struct/union/enum name");
6046 s = struct_find(v);
6047 if (s) {
6048 if (s->type.t != a)
6049 error("invalid type");
6050 goto do_decl;
6052 } else {
6053 v = anon_sym++;
6055 type1.t = a;
6056 /* we put an undefined size for struct/union */
6057 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6058 s->r = 0; /* default alignment is zero as gcc */
6059 /* put struct/union/enum name in type */
6060 do_decl:
6061 type->t = u;
6062 type->ref = s;
6064 if (tok == '{') {
6065 next();
6066 if (s->c != -1)
6067 error("struct/union/enum already defined");
6068 /* cannot be empty */
6069 c = 0;
6070 /* non empty enums are not allowed */
6071 if (a == TOK_ENUM) {
6072 for(;;) {
6073 v = tok;
6074 if (v < TOK_UIDENT)
6075 expect("identifier");
6076 next();
6077 if (tok == '=') {
6078 next();
6079 c = expr_const();
6081 /* enum symbols have static storage */
6082 ss = sym_push(v, &int_type, VT_CONST, c);
6083 ss->type.t |= VT_STATIC;
6084 if (tok != ',')
6085 break;
6086 next();
6087 c++;
6088 /* NOTE: we accept a trailing comma */
6089 if (tok == '}')
6090 break;
6092 skip('}');
6093 } else {
6094 maxalign = 1;
6095 ps = &s->next;
6096 bit_pos = 0;
6097 offset = 0;
6098 while (tok != '}') {
6099 parse_btype(&btype, &ad);
6100 while (1) {
6101 bit_size = -1;
6102 v = 0;
6103 type1 = btype;
6104 if (tok != ':') {
6105 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6106 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6107 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6108 error("invalid type for '%s'",
6109 get_tok_str(v, NULL));
6111 if (tok == ':') {
6112 next();
6113 bit_size = expr_const();
6114 /* XXX: handle v = 0 case for messages */
6115 if (bit_size < 0)
6116 error("negative width in bit-field '%s'",
6117 get_tok_str(v, NULL));
6118 if (v && bit_size == 0)
6119 error("zero width for bit-field '%s'",
6120 get_tok_str(v, NULL));
6122 size = type_size(&type1, &align);
6123 lbit_pos = 0;
6124 if (bit_size >= 0) {
6125 bt = type1.t & VT_BTYPE;
6126 if (bt != VT_INT &&
6127 bt != VT_BYTE &&
6128 bt != VT_SHORT &&
6129 bt != VT_ENUM)
6130 error("bitfields must have scalar type");
6131 bsize = size * 8;
6132 if (bit_size > bsize) {
6133 error("width of '%s' exceeds its type",
6134 get_tok_str(v, NULL));
6135 } else if (bit_size == bsize) {
6136 /* no need for bit fields */
6137 bit_pos = 0;
6138 } else if (bit_size == 0) {
6139 /* XXX: what to do if only padding in a
6140 structure ? */
6141 /* zero size: means to pad */
6142 if (bit_pos > 0)
6143 bit_pos = bsize;
6144 } else {
6145 /* we do not have enough room ? */
6146 if ((bit_pos + bit_size) > bsize)
6147 bit_pos = 0;
6148 lbit_pos = bit_pos;
6149 /* XXX: handle LSB first */
6150 type1.t |= VT_BITFIELD |
6151 (bit_pos << VT_STRUCT_SHIFT) |
6152 (bit_size << (VT_STRUCT_SHIFT + 6));
6153 bit_pos += bit_size;
6155 } else {
6156 bit_pos = 0;
6158 if (v) {
6159 /* add new memory data only if starting
6160 bit field */
6161 if (lbit_pos == 0) {
6162 if (a == TOK_STRUCT) {
6163 c = (c + align - 1) & -align;
6164 offset = c;
6165 c += size;
6166 } else {
6167 offset = 0;
6168 if (size > c)
6169 c = size;
6171 if (align > maxalign)
6172 maxalign = align;
6174 #if 0
6175 printf("add field %s offset=%d",
6176 get_tok_str(v, NULL), offset);
6177 if (type1.t & VT_BITFIELD) {
6178 printf(" pos=%d size=%d",
6179 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6180 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6182 printf("\n");
6183 #endif
6184 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6185 *ps = ss;
6186 ps = &ss->next;
6188 if (tok == ';' || tok == TOK_EOF)
6189 break;
6190 skip(',');
6192 skip(';');
6194 skip('}');
6195 /* store size and alignment */
6196 s->c = (c + maxalign - 1) & -maxalign;
6197 s->r = maxalign;
6202 /* return 0 if no type declaration. otherwise, return the basic type
6203 and skip it.
6205 static int parse_btype(CType *type, AttributeDef *ad)
6207 int t, u, type_found;
6208 Sym *s;
6209 CType type1;
6211 memset(ad, 0, sizeof(AttributeDef));
6212 type_found = 0;
6213 t = 0;
6214 while(1) {
6215 switch(tok) {
6216 case TOK_EXTENSION:
6217 /* currently, we really ignore extension */
6218 next();
6219 continue;
6221 /* basic types */
6222 case TOK_CHAR:
6223 u = VT_BYTE;
6224 basic_type:
6225 next();
6226 basic_type1:
6227 if ((t & VT_BTYPE) != 0)
6228 error("too many basic types");
6229 t |= u;
6230 break;
6231 case TOK_VOID:
6232 u = VT_VOID;
6233 goto basic_type;
6234 case TOK_SHORT:
6235 u = VT_SHORT;
6236 goto basic_type;
6237 case TOK_INT:
6238 next();
6239 break;
6240 case TOK_LONG:
6241 next();
6242 if ((t & VT_BTYPE) == VT_DOUBLE) {
6243 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6244 } else if ((t & VT_BTYPE) == VT_LONG) {
6245 t = (t & ~VT_BTYPE) | VT_LLONG;
6246 } else {
6247 u = VT_LONG;
6248 goto basic_type1;
6250 break;
6251 case TOK_BOOL:
6252 u = VT_BOOL;
6253 goto basic_type;
6254 case TOK_FLOAT:
6255 u = VT_FLOAT;
6256 goto basic_type;
6257 case TOK_DOUBLE:
6258 next();
6259 if ((t & VT_BTYPE) == VT_LONG) {
6260 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6261 } else {
6262 u = VT_DOUBLE;
6263 goto basic_type1;
6265 break;
6266 case TOK_ENUM:
6267 struct_decl(&type1, VT_ENUM);
6268 basic_type2:
6269 u = type1.t;
6270 type->ref = type1.ref;
6271 goto basic_type1;
6272 case TOK_STRUCT:
6273 case TOK_UNION:
6274 struct_decl(&type1, VT_STRUCT);
6275 goto basic_type2;
6277 /* type modifiers */
6278 case TOK_CONST1:
6279 case TOK_CONST2:
6280 case TOK_CONST3:
6281 t |= VT_CONSTANT;
6282 next();
6283 break;
6284 case TOK_VOLATILE1:
6285 case TOK_VOLATILE2:
6286 case TOK_VOLATILE3:
6287 t |= VT_VOLATILE;
6288 next();
6289 break;
6290 case TOK_REGISTER:
6291 case TOK_SIGNED1:
6292 case TOK_SIGNED2:
6293 case TOK_SIGNED3:
6294 case TOK_AUTO:
6295 case TOK_RESTRICT1:
6296 case TOK_RESTRICT2:
6297 case TOK_RESTRICT3:
6298 next();
6299 break;
6300 case TOK_UNSIGNED:
6301 t |= VT_UNSIGNED;
6302 next();
6303 break;
6305 /* storage */
6306 case TOK_EXTERN:
6307 t |= VT_EXTERN;
6308 next();
6309 break;
6310 case TOK_STATIC:
6311 t |= VT_STATIC;
6312 next();
6313 break;
6314 case TOK_TYPEDEF:
6315 t |= VT_TYPEDEF;
6316 next();
6317 break;
6318 case TOK_INLINE1:
6319 case TOK_INLINE2:
6320 case TOK_INLINE3:
6321 t |= VT_INLINE;
6322 next();
6323 break;
6325 /* GNUC attribute */
6326 case TOK_ATTRIBUTE1:
6327 case TOK_ATTRIBUTE2:
6328 parse_attribute(ad);
6329 break;
6330 /* GNUC typeof */
6331 case TOK_TYPEOF1:
6332 case TOK_TYPEOF2:
6333 case TOK_TYPEOF3:
6334 next();
6335 parse_expr_type(&type1);
6336 goto basic_type2;
6337 default:
6338 s = sym_find(tok);
6339 if (!s || !(s->type.t & VT_TYPEDEF))
6340 goto the_end;
6341 t |= (s->type.t & ~VT_TYPEDEF);
6342 type->ref = s->type.ref;
6343 next();
6344 break;
6346 type_found = 1;
6348 the_end:
6349 /* long is never used as type */
6350 if ((t & VT_BTYPE) == VT_LONG)
6351 t = (t & ~VT_BTYPE) | VT_INT;
6352 type->t = t;
6353 return type_found;
6356 /* convert a function parameter type (array to pointer and function to
6357 function pointer) */
6358 static inline void convert_parameter_type(CType *pt)
6360 /* array must be transformed to pointer according to ANSI C */
6361 pt->t &= ~VT_ARRAY;
6362 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6363 mk_pointer(pt);
6367 static void post_type(CType *type, AttributeDef *ad)
6369 int n, l, t1;
6370 Sym **plast, *s, *first;
6371 AttributeDef ad1;
6372 CType pt;
6374 if (tok == '(') {
6375 /* function declaration */
6376 next();
6377 l = 0;
6378 first = NULL;
6379 plast = &first;
6380 while (tok != ')') {
6381 /* read param name and compute offset */
6382 if (l != FUNC_OLD) {
6383 if (!parse_btype(&pt, &ad1)) {
6384 if (l) {
6385 error("invalid type");
6386 } else {
6387 l = FUNC_OLD;
6388 goto old_proto;
6391 l = FUNC_NEW;
6392 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6393 break;
6394 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6395 if ((pt.t & VT_BTYPE) == VT_VOID)
6396 error("parameter declared as void");
6397 } else {
6398 old_proto:
6399 n = tok;
6400 pt.t = VT_INT;
6401 next();
6403 convert_parameter_type(&pt);
6404 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6405 *plast = s;
6406 plast = &s->next;
6407 if (tok == ',') {
6408 next();
6409 if (l == FUNC_NEW && tok == TOK_DOTS) {
6410 l = FUNC_ELLIPSIS;
6411 next();
6412 break;
6416 /* if no parameters, then old type prototype */
6417 if (l == 0)
6418 l = FUNC_OLD;
6419 skip(')');
6420 t1 = type->t & VT_STORAGE;
6421 /* NOTE: const is ignored in returned type as it has a special
6422 meaning in gcc / C++ */
6423 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6424 post_type(type, ad);
6425 /* we push a anonymous symbol which will contain the function prototype */
6426 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6427 s->next = first;
6428 type->t = t1 | VT_FUNC;
6429 type->ref = s;
6430 } else if (tok == '[') {
6431 /* array definition */
6432 next();
6433 n = -1;
6434 if (tok != ']') {
6435 n = expr_const();
6436 if (n < 0)
6437 error("invalid array size");
6439 skip(']');
6440 /* parse next post type */
6441 t1 = type->t & VT_STORAGE;
6442 type->t &= ~VT_STORAGE;
6443 post_type(type, ad);
6445 /* we push a anonymous symbol which will contain the array
6446 element type */
6447 s = sym_push(SYM_FIELD, type, 0, n);
6448 type->t = t1 | VT_ARRAY | VT_PTR;
6449 type->ref = s;
6453 /* Parse a type declaration (except basic type), and return the type
6454 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6455 expected. 'type' should contain the basic type. 'ad' is the
6456 attribute definition of the basic type. It can be modified by
6457 type_decl().
6459 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6461 Sym *s;
6462 CType type1, *type2;
6463 int qualifiers;
6465 while (tok == '*') {
6466 qualifiers = 0;
6467 redo:
6468 next();
6469 switch(tok) {
6470 case TOK_CONST1:
6471 case TOK_CONST2:
6472 case TOK_CONST3:
6473 qualifiers |= VT_CONSTANT;
6474 goto redo;
6475 case TOK_VOLATILE1:
6476 case TOK_VOLATILE2:
6477 case TOK_VOLATILE3:
6478 qualifiers |= VT_VOLATILE;
6479 goto redo;
6480 case TOK_RESTRICT1:
6481 case TOK_RESTRICT2:
6482 case TOK_RESTRICT3:
6483 goto redo;
6485 mk_pointer(type);
6486 type->t |= qualifiers;
6489 /* XXX: clarify attribute handling */
6490 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6491 parse_attribute(ad);
6493 /* recursive type */
6494 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6495 type1.t = 0; /* XXX: same as int */
6496 if (tok == '(') {
6497 next();
6498 /* XXX: this is not correct to modify 'ad' at this point, but
6499 the syntax is not clear */
6500 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6501 parse_attribute(ad);
6502 type_decl(&type1, ad, v, td);
6503 skip(')');
6504 } else {
6505 /* type identifier */
6506 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6507 *v = tok;
6508 next();
6509 } else {
6510 if (!(td & TYPE_ABSTRACT))
6511 expect("identifier");
6512 *v = 0;
6515 post_type(type, ad);
6516 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6517 parse_attribute(ad);
6518 if (!type1.t)
6519 return;
6520 /* append type at the end of type1 */
6521 type2 = &type1;
6522 for(;;) {
6523 s = type2->ref;
6524 type2 = &s->type;
6525 if (!type2->t) {
6526 *type2 = *type;
6527 break;
6530 *type = type1;
6533 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6534 static int lvalue_type(int t)
6536 int bt, r;
6537 r = VT_LVAL;
6538 bt = t & VT_BTYPE;
6539 if (bt == VT_BYTE || bt == VT_BOOL)
6540 r |= VT_LVAL_BYTE;
6541 else if (bt == VT_SHORT)
6542 r |= VT_LVAL_SHORT;
6543 else
6544 return r;
6545 if (t & VT_UNSIGNED)
6546 r |= VT_LVAL_UNSIGNED;
6547 return r;
6550 /* indirection with full error checking and bound check */
6551 static void indir(void)
6553 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6554 expect("pointer");
6555 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6556 gv(RC_INT);
6557 vtop->type = *pointed_type(&vtop->type);
6558 /* an array is never an lvalue */
6559 if (!(vtop->type.t & VT_ARRAY)) {
6560 vtop->r |= lvalue_type(vtop->type.t);
6561 /* if bound checking, the referenced pointer must be checked */
6562 if (do_bounds_check)
6563 vtop->r |= VT_MUSTBOUND;
6567 /* pass a parameter to a function and do type checking and casting */
6568 static void gfunc_param_typed(Sym *func, Sym *arg)
6570 int func_type;
6571 CType type;
6573 func_type = func->c;
6574 if (func_type == FUNC_OLD ||
6575 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6576 /* default casting : only need to convert float to double */
6577 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6578 type.t = VT_DOUBLE;
6579 gen_cast(&type);
6581 } else if (arg == NULL) {
6582 error("too many arguments to function");
6583 } else {
6584 gen_assign_cast(&arg->type);
6588 /* parse an expression of the form '(type)' or '(expr)' and return its
6589 type */
6590 static void parse_expr_type(CType *type)
6592 int n;
6593 AttributeDef ad;
6595 skip('(');
6596 if (parse_btype(type, &ad)) {
6597 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6598 } else {
6599 expr_type(type);
6601 skip(')');
6604 static void parse_type(CType *type)
6606 AttributeDef ad;
6607 int n;
6609 if (!parse_btype(type, &ad)) {
6610 expect("type");
6612 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6615 static void vpush_tokc(int t)
6617 CType type;
6618 type.t = t;
6619 vsetc(&type, VT_CONST, &tokc);
6622 static void unary(void)
6624 int n, t, align, size, r;
6625 CType type;
6626 Sym *s;
6627 AttributeDef ad;
6629 /* XXX: GCC 2.95.3 does not generate a table although it should be
6630 better here */
6631 tok_next:
6632 switch(tok) {
6633 case TOK_EXTENSION:
6634 next();
6635 goto tok_next;
6636 case TOK_CINT:
6637 case TOK_CCHAR:
6638 case TOK_LCHAR:
6639 vpushi(tokc.i);
6640 next();
6641 break;
6642 case TOK_CUINT:
6643 vpush_tokc(VT_INT | VT_UNSIGNED);
6644 next();
6645 break;
6646 case TOK_CLLONG:
6647 vpush_tokc(VT_LLONG);
6648 next();
6649 break;
6650 case TOK_CULLONG:
6651 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6652 next();
6653 break;
6654 case TOK_CFLOAT:
6655 vpush_tokc(VT_FLOAT);
6656 next();
6657 break;
6658 case TOK_CDOUBLE:
6659 vpush_tokc(VT_DOUBLE);
6660 next();
6661 break;
6662 case TOK_CLDOUBLE:
6663 vpush_tokc(VT_LDOUBLE);
6664 next();
6665 break;
6666 case TOK___FUNCTION__:
6667 if (!gnu_ext)
6668 goto tok_identifier;
6669 /* fall thru */
6670 case TOK___FUNC__:
6672 void *ptr;
6673 int len;
6674 /* special function name identifier */
6675 len = strlen(funcname) + 1;
6676 /* generate char[len] type */
6677 type.t = VT_BYTE;
6678 mk_pointer(&type);
6679 type.t |= VT_ARRAY;
6680 type.ref->c = len;
6681 vpush_ref(&type, data_section, data_section->data_offset, len);
6682 ptr = section_ptr_add(data_section, len);
6683 memcpy(ptr, funcname, len);
6684 next();
6686 break;
6687 case TOK_LSTR:
6688 t = VT_INT;
6689 goto str_init;
6690 case TOK_STR:
6691 /* string parsing */
6692 t = VT_BYTE;
6693 str_init:
6694 if (tcc_state->warn_write_strings)
6695 t |= VT_CONSTANT;
6696 type.t = t;
6697 mk_pointer(&type);
6698 type.t |= VT_ARRAY;
6699 memset(&ad, 0, sizeof(AttributeDef));
6700 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6701 break;
6702 case '(':
6703 next();
6704 /* cast ? */
6705 if (parse_btype(&type, &ad)) {
6706 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6707 skip(')');
6708 /* check ISOC99 compound literal */
6709 if (tok == '{') {
6710 /* data is allocated locally by default */
6711 if (global_expr)
6712 r = VT_CONST;
6713 else
6714 r = VT_LOCAL;
6715 /* all except arrays are lvalues */
6716 if (!(type.t & VT_ARRAY))
6717 r |= lvalue_type(type.t);
6718 memset(&ad, 0, sizeof(AttributeDef));
6719 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6720 } else {
6721 unary();
6722 gen_cast(&type);
6724 } else if (tok == '{') {
6725 /* save all registers */
6726 save_regs(0);
6727 /* statement expression : we do not accept break/continue
6728 inside as GCC does */
6729 block(NULL, NULL, NULL, NULL, 0, 1);
6730 skip(')');
6731 } else {
6732 gexpr();
6733 skip(')');
6735 break;
6736 case '*':
6737 next();
6738 unary();
6739 indir();
6740 break;
6741 case '&':
6742 next();
6743 unary();
6744 /* functions names must be treated as function pointers,
6745 except for unary '&' and sizeof. Since we consider that
6746 functions are not lvalues, we only have to handle it
6747 there and in function calls. */
6748 /* arrays can also be used although they are not lvalues */
6749 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6750 !(vtop->type.t & VT_ARRAY))
6751 test_lvalue();
6752 mk_pointer(&vtop->type);
6753 gaddrof();
6754 break;
6755 case '!':
6756 next();
6757 unary();
6758 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6759 vtop->c.i = !vtop->c.i;
6760 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6761 vtop->c.i = vtop->c.i ^ 1;
6762 else
6763 vseti(VT_JMP, gtst(1, 0));
6764 break;
6765 case '~':
6766 next();
6767 unary();
6768 vpushi(-1);
6769 gen_op('^');
6770 break;
6771 case '+':
6772 next();
6773 /* in order to force cast, we add zero */
6774 unary();
6775 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6776 error("pointer not accepted for unary plus");
6777 vpushi(0);
6778 gen_op('+');
6779 break;
6780 case TOK_SIZEOF:
6781 case TOK_ALIGNOF1:
6782 case TOK_ALIGNOF2:
6783 t = tok;
6784 next();
6785 if (tok == '(') {
6786 parse_expr_type(&type);
6787 } else {
6788 unary_type(&type);
6790 size = type_size(&type, &align);
6791 if (t == TOK_SIZEOF) {
6792 if (size < 0)
6793 error("sizeof applied to an incomplete type");
6794 vpushi(size);
6795 } else {
6796 vpushi(align);
6798 break;
6800 case TOK_builtin_types_compatible_p:
6802 CType type1, type2;
6803 next();
6804 skip('(');
6805 parse_type(&type1);
6806 skip(',');
6807 parse_type(&type2);
6808 skip(')');
6809 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6810 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6811 vpushi(is_compatible_types(&type1, &type2));
6813 break;
6814 case TOK_builtin_constant_p:
6816 int saved_nocode_wanted, res;
6817 next();
6818 skip('(');
6819 saved_nocode_wanted = nocode_wanted;
6820 nocode_wanted = 1;
6821 gexpr();
6822 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6823 vpop();
6824 nocode_wanted = saved_nocode_wanted;
6825 skip(')');
6826 vpushi(res);
6828 break;
6829 case TOK_INC:
6830 case TOK_DEC:
6831 t = tok;
6832 next();
6833 unary();
6834 inc(0, t);
6835 break;
6836 case '-':
6837 next();
6838 vpushi(0);
6839 unary();
6840 gen_op('-');
6841 break;
6842 case TOK_LAND:
6843 if (!gnu_ext)
6844 goto tok_identifier;
6845 next();
6846 /* allow to take the address of a label */
6847 if (tok < TOK_UIDENT)
6848 expect("label identifier");
6849 s = label_find(tok);
6850 if (!s) {
6851 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6852 } else {
6853 if (s->r == LABEL_DECLARED)
6854 s->r = LABEL_FORWARD;
6856 if (!s->type.t) {
6857 s->type.t = VT_VOID;
6858 mk_pointer(&s->type);
6859 s->type.t |= VT_STATIC;
6861 vset(&s->type, VT_CONST | VT_SYM, 0);
6862 vtop->sym = s;
6863 next();
6864 break;
6865 default:
6866 tok_identifier:
6867 t = tok;
6868 next();
6869 if (t < TOK_UIDENT)
6870 expect("identifier");
6871 s = sym_find(t);
6872 if (!s) {
6873 if (tok != '(')
6874 error("'%s' undeclared", get_tok_str(t, NULL));
6875 /* for simple function calls, we tolerate undeclared
6876 external reference to int() function */
6877 s = external_global_sym(t, &func_old_type, 0);
6879 vset(&s->type, s->r, s->c);
6880 /* if forward reference, we must point to s */
6881 if (vtop->r & VT_SYM) {
6882 vtop->sym = s;
6883 vtop->c.ul = 0;
6885 break;
6888 /* post operations */
6889 while (1) {
6890 if (tok == TOK_INC || tok == TOK_DEC) {
6891 inc(1, tok);
6892 next();
6893 } else if (tok == '.' || tok == TOK_ARROW) {
6894 /* field */
6895 if (tok == TOK_ARROW)
6896 indir();
6897 test_lvalue();
6898 gaddrof();
6899 next();
6900 /* expect pointer on structure */
6901 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6902 expect("struct or union");
6903 s = vtop->type.ref;
6904 /* find field */
6905 tok |= SYM_FIELD;
6906 while ((s = s->next) != NULL) {
6907 if (s->v == tok)
6908 break;
6910 if (!s)
6911 error("field not found");
6912 /* add field offset to pointer */
6913 vtop->type = char_pointer_type; /* change type to 'char *' */
6914 vpushi(s->c);
6915 gen_op('+');
6916 /* change type to field type, and set to lvalue */
6917 vtop->type = s->type;
6918 /* an array is never an lvalue */
6919 if (!(vtop->type.t & VT_ARRAY)) {
6920 vtop->r |= lvalue_type(vtop->type.t);
6921 /* if bound checking, the referenced pointer must be checked */
6922 if (do_bounds_check)
6923 vtop->r |= VT_MUSTBOUND;
6925 next();
6926 } else if (tok == '[') {
6927 next();
6928 gexpr();
6929 gen_op('+');
6930 indir();
6931 skip(']');
6932 } else if (tok == '(') {
6933 SValue ret;
6934 Sym *sa;
6935 int nb_args;
6937 /* function call */
6938 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
6939 /* pointer test (no array accepted) */
6940 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
6941 vtop->type = *pointed_type(&vtop->type);
6942 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
6943 goto error_func;
6944 } else {
6945 error_func:
6946 expect("function pointer");
6948 } else {
6949 vtop->r &= ~VT_LVAL; /* no lvalue */
6951 /* get return type */
6952 s = vtop->type.ref;
6953 next();
6954 sa = s->next; /* first parameter */
6955 nb_args = 0;
6956 /* compute first implicit argument if a structure is returned */
6957 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
6958 /* get some space for the returned structure */
6959 size = type_size(&s->type, &align);
6960 loc = (loc - size) & -align;
6961 ret.type = s->type;
6962 ret.r = VT_LOCAL | VT_LVAL;
6963 /* pass it as 'int' to avoid structure arg passing
6964 problems */
6965 vseti(VT_LOCAL, loc);
6966 ret.c = vtop->c;
6967 nb_args++;
6968 } else {
6969 ret.type = s->type;
6970 ret.r2 = VT_CONST;
6971 /* return in register */
6972 if (is_float(ret.type.t)) {
6973 ret.r = REG_FRET;
6974 } else {
6975 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
6976 ret.r2 = REG_LRET;
6977 ret.r = REG_IRET;
6979 ret.c.i = 0;
6981 if (tok != ')') {
6982 for(;;) {
6983 expr_eq();
6984 gfunc_param_typed(s, sa);
6985 nb_args++;
6986 if (sa)
6987 sa = sa->next;
6988 if (tok == ')')
6989 break;
6990 skip(',');
6993 if (sa)
6994 error("too few arguments to function");
6995 skip(')');
6996 if (!nocode_wanted) {
6997 gfunc_call(nb_args);
6998 } else {
6999 vtop -= (nb_args + 1);
7001 /* return value */
7002 vsetc(&ret.type, ret.r, &ret.c);
7003 vtop->r2 = ret.r2;
7004 } else {
7005 break;
7010 static void uneq(void)
7012 int t;
7014 unary();
7015 if (tok == '=' ||
7016 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7017 tok == TOK_A_XOR || tok == TOK_A_OR ||
7018 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7019 test_lvalue();
7020 t = tok;
7021 next();
7022 if (t == '=') {
7023 expr_eq();
7024 } else {
7025 vdup();
7026 expr_eq();
7027 gen_op(t & 0x7f);
7029 vstore();
7033 static void expr_prod(void)
7035 int t;
7037 uneq();
7038 while (tok == '*' || tok == '/' || tok == '%') {
7039 t = tok;
7040 next();
7041 uneq();
7042 gen_op(t);
7046 static void expr_sum(void)
7048 int t;
7050 expr_prod();
7051 while (tok == '+' || tok == '-') {
7052 t = tok;
7053 next();
7054 expr_prod();
7055 gen_op(t);
7059 static void expr_shift(void)
7061 int t;
7063 expr_sum();
7064 while (tok == TOK_SHL || tok == TOK_SAR) {
7065 t = tok;
7066 next();
7067 expr_sum();
7068 gen_op(t);
7072 static void expr_cmp(void)
7074 int t;
7076 expr_shift();
7077 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7078 tok == TOK_ULT || tok == TOK_UGE) {
7079 t = tok;
7080 next();
7081 expr_shift();
7082 gen_op(t);
7086 static void expr_cmpeq(void)
7088 int t;
7090 expr_cmp();
7091 while (tok == TOK_EQ || tok == TOK_NE) {
7092 t = tok;
7093 next();
7094 expr_cmp();
7095 gen_op(t);
7099 static void expr_and(void)
7101 expr_cmpeq();
7102 while (tok == '&') {
7103 next();
7104 expr_cmpeq();
7105 gen_op('&');
7109 static void expr_xor(void)
7111 expr_and();
7112 while (tok == '^') {
7113 next();
7114 expr_and();
7115 gen_op('^');
7119 static void expr_or(void)
7121 expr_xor();
7122 while (tok == '|') {
7123 next();
7124 expr_xor();
7125 gen_op('|');
7129 /* XXX: fix this mess */
7130 static void expr_land_const(void)
7132 expr_or();
7133 while (tok == TOK_LAND) {
7134 next();
7135 expr_or();
7136 gen_op(TOK_LAND);
7140 /* XXX: fix this mess */
7141 static void expr_lor_const(void)
7143 expr_land_const();
7144 while (tok == TOK_LOR) {
7145 next();
7146 expr_land_const();
7147 gen_op(TOK_LOR);
7151 /* only used if non constant */
7152 static void expr_land(void)
7154 int t;
7156 expr_or();
7157 if (tok == TOK_LAND) {
7158 t = 0;
7159 for(;;) {
7160 t = gtst(1, t);
7161 if (tok != TOK_LAND) {
7162 vseti(VT_JMPI, t);
7163 break;
7165 next();
7166 expr_or();
7171 static void expr_lor(void)
7173 int t;
7175 expr_land();
7176 if (tok == TOK_LOR) {
7177 t = 0;
7178 for(;;) {
7179 t = gtst(0, t);
7180 if (tok != TOK_LOR) {
7181 vseti(VT_JMP, t);
7182 break;
7184 next();
7185 expr_land();
7190 /* XXX: better constant handling */
7191 static void expr_eq(void)
7193 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7194 SValue sv;
7195 CType type, type1, type2;
7197 if (const_wanted) {
7198 int c1, c;
7199 expr_lor_const();
7200 if (tok == '?') {
7201 c = vtop->c.i;
7202 vpop();
7203 next();
7204 if (tok == ':' && gnu_ext) {
7205 c1 = c;
7206 } else {
7207 gexpr();
7208 c1 = vtop->c.i;
7209 vpop();
7211 skip(':');
7212 expr_eq();
7213 if (c)
7214 vtop->c.i = c1;
7216 } else {
7217 expr_lor();
7218 if (tok == '?') {
7219 next();
7220 if (vtop != vstack) {
7221 /* needed to avoid having different registers saved in
7222 each branch */
7223 if (is_float(vtop->type.t))
7224 rc = RC_FLOAT;
7225 else
7226 rc = RC_INT;
7227 gv(rc);
7228 save_regs(1);
7230 if (tok == ':' && gnu_ext) {
7231 gv_dup();
7232 tt = gtst(1, 0);
7233 } else {
7234 tt = gtst(1, 0);
7235 gexpr();
7237 type1 = vtop->type;
7238 sv = *vtop; /* save value to handle it later */
7239 vtop--; /* no vpop so that FP stack is not flushed */
7240 skip(':');
7241 u = gjmp(0);
7242 gsym(tt);
7243 expr_eq();
7244 type2 = vtop->type;
7246 t1 = type1.t;
7247 bt1 = t1 & VT_BTYPE;
7248 t2 = type2.t;
7249 bt2 = t2 & VT_BTYPE;
7250 /* cast operands to correct type according to ISOC rules */
7251 if (is_float(bt1) || is_float(bt2)) {
7252 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7253 type.t = VT_LDOUBLE;
7254 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7255 type.t = VT_DOUBLE;
7256 } else {
7257 type.t = VT_FLOAT;
7259 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7260 /* cast to biggest op */
7261 type.t = VT_LLONG;
7262 /* convert to unsigned if it does not fit in a long long */
7263 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7264 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7265 type.t |= VT_UNSIGNED;
7266 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7267 /* XXX: test pointer compatibility */
7268 type = type1;
7269 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7270 /* XXX: test structure compatibility */
7271 type = type1;
7272 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7273 /* NOTE: as an extension, we accept void on only one side */
7274 type.t = VT_VOID;
7275 } else {
7276 /* integer operations */
7277 type.t = VT_INT;
7278 /* convert to unsigned if it does not fit in an integer */
7279 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7280 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7281 type.t |= VT_UNSIGNED;
7284 /* now we convert second operand */
7285 gen_cast(&type);
7286 rc = RC_INT;
7287 if (is_float(type.t)) {
7288 rc = RC_FLOAT;
7289 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7290 /* for long longs, we use fixed registers to avoid having
7291 to handle a complicated move */
7292 rc = RC_IRET;
7295 r2 = gv(rc);
7296 /* this is horrible, but we must also convert first
7297 operand */
7298 tt = gjmp(0);
7299 gsym(u);
7300 /* put again first value and cast it */
7301 *vtop = sv;
7302 gen_cast(&type);
7303 r1 = gv(rc);
7304 move_reg(r2, r1);
7305 vtop->r = r2;
7306 gsym(tt);
7311 static void gexpr(void)
7313 while (1) {
7314 expr_eq();
7315 if (tok != ',')
7316 break;
7317 vpop();
7318 next();
7322 /* parse an expression and return its type without any side effect. */
7323 static void expr_type(CType *type)
7325 int saved_nocode_wanted;
7327 saved_nocode_wanted = nocode_wanted;
7328 nocode_wanted = 1;
7329 gexpr();
7330 *type = vtop->type;
7331 vpop();
7332 nocode_wanted = saved_nocode_wanted;
7335 /* parse a unary expression and return its type without any side
7336 effect. */
7337 static void unary_type(CType *type)
7339 int a;
7341 a = nocode_wanted;
7342 nocode_wanted = 1;
7343 unary();
7344 *type = vtop->type;
7345 vpop();
7346 nocode_wanted = a;
7349 /* parse a constant expression and return value in vtop. */
7350 static void expr_const1(void)
7352 int a;
7353 a = const_wanted;
7354 const_wanted = 1;
7355 expr_eq();
7356 const_wanted = a;
7359 /* parse an integer constant and return its value. */
7360 static int expr_const(void)
7362 int c;
7363 expr_const1();
7364 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7365 expect("constant expression");
7366 c = vtop->c.i;
7367 vpop();
7368 return c;
7371 /* return the label token if current token is a label, otherwise
7372 return zero */
7373 static int is_label(void)
7375 int last_tok;
7377 /* fast test first */
7378 if (tok < TOK_UIDENT)
7379 return 0;
7380 /* no need to save tokc because tok is an identifier */
7381 last_tok = tok;
7382 next();
7383 if (tok == ':') {
7384 next();
7385 return last_tok;
7386 } else {
7387 unget_tok(last_tok);
7388 return 0;
7392 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7393 int case_reg, int is_expr)
7395 int a, b, c, d;
7396 Sym *s;
7398 /* generate line number info */
7399 if (do_debug &&
7400 (last_line_num != file->line_num || last_ind != ind)) {
7401 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7402 last_ind = ind;
7403 last_line_num = file->line_num;
7406 if (is_expr) {
7407 /* default return value is (void) */
7408 vpushi(0);
7409 vtop->type.t = VT_VOID;
7412 if (tok == TOK_IF) {
7413 /* if test */
7414 next();
7415 skip('(');
7416 gexpr();
7417 skip(')');
7418 a = gtst(1, 0);
7419 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7420 c = tok;
7421 if (c == TOK_ELSE) {
7422 next();
7423 d = gjmp(0);
7424 gsym(a);
7425 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7426 gsym(d); /* patch else jmp */
7427 } else
7428 gsym(a);
7429 } else if (tok == TOK_WHILE) {
7430 next();
7431 d = ind;
7432 skip('(');
7433 gexpr();
7434 skip(')');
7435 a = gtst(1, 0);
7436 b = 0;
7437 block(&a, &b, case_sym, def_sym, case_reg, 0);
7438 gjmp_addr(d);
7439 gsym(a);
7440 gsym_addr(b, d);
7441 } else if (tok == '{') {
7442 Sym *llabel;
7444 next();
7445 /* record local declaration stack position */
7446 s = local_stack;
7447 llabel = local_label_stack;
7448 /* handle local labels declarations */
7449 if (tok == TOK_LABEL) {
7450 next();
7451 for(;;) {
7452 if (tok < TOK_UIDENT)
7453 expect("label identifier");
7454 label_push(&local_label_stack, tok, LABEL_DECLARED);
7455 next();
7456 if (tok == ',') {
7457 next();
7458 } else {
7459 skip(';');
7460 break;
7464 while (tok != '}') {
7465 decl(VT_LOCAL);
7466 if (tok != '}') {
7467 if (is_expr)
7468 vpop();
7469 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7472 /* pop locally defined labels */
7473 label_pop(&local_label_stack, llabel);
7474 /* pop locally defined symbols */
7475 sym_pop(&local_stack, s);
7476 next();
7477 } else if (tok == TOK_RETURN) {
7478 next();
7479 if (tok != ';') {
7480 gexpr();
7481 gen_assign_cast(&func_vt);
7482 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7483 CType type;
7484 /* if returning structure, must copy it to implicit
7485 first pointer arg location */
7486 type = func_vt;
7487 mk_pointer(&type);
7488 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7489 indir();
7490 vswap();
7491 /* copy structure value to pointer */
7492 vstore();
7493 } else if (is_float(func_vt.t)) {
7494 gv(RC_FRET);
7495 } else {
7496 gv(RC_IRET);
7498 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7500 skip(';');
7501 rsym = gjmp(rsym); /* jmp */
7502 } else if (tok == TOK_BREAK) {
7503 /* compute jump */
7504 if (!bsym)
7505 error("cannot break");
7506 *bsym = gjmp(*bsym);
7507 next();
7508 skip(';');
7509 } else if (tok == TOK_CONTINUE) {
7510 /* compute jump */
7511 if (!csym)
7512 error("cannot continue");
7513 *csym = gjmp(*csym);
7514 next();
7515 skip(';');
7516 } else if (tok == TOK_FOR) {
7517 int e;
7518 next();
7519 skip('(');
7520 if (tok != ';') {
7521 gexpr();
7522 vpop();
7524 skip(';');
7525 d = ind;
7526 c = ind;
7527 a = 0;
7528 b = 0;
7529 if (tok != ';') {
7530 gexpr();
7531 a = gtst(1, 0);
7533 skip(';');
7534 if (tok != ')') {
7535 e = gjmp(0);
7536 c = ind;
7537 gexpr();
7538 vpop();
7539 gjmp_addr(d);
7540 gsym(e);
7542 skip(')');
7543 block(&a, &b, case_sym, def_sym, case_reg, 0);
7544 gjmp_addr(c);
7545 gsym(a);
7546 gsym_addr(b, c);
7547 } else
7548 if (tok == TOK_DO) {
7549 next();
7550 a = 0;
7551 b = 0;
7552 d = ind;
7553 block(&a, &b, case_sym, def_sym, case_reg, 0);
7554 skip(TOK_WHILE);
7555 skip('(');
7556 gsym(b);
7557 gexpr();
7558 c = gtst(0, 0);
7559 gsym_addr(c, d);
7560 skip(')');
7561 gsym(a);
7562 skip(';');
7563 } else
7564 if (tok == TOK_SWITCH) {
7565 next();
7566 skip('(');
7567 gexpr();
7568 /* XXX: other types than integer */
7569 case_reg = gv(RC_INT);
7570 vpop();
7571 skip(')');
7572 a = 0;
7573 b = gjmp(0); /* jump to first case */
7574 c = 0;
7575 block(&a, csym, &b, &c, case_reg, 0);
7576 /* if no default, jmp after switch */
7577 if (c == 0)
7578 c = ind;
7579 /* default label */
7580 gsym_addr(b, c);
7581 /* break label */
7582 gsym(a);
7583 } else
7584 if (tok == TOK_CASE) {
7585 int v1, v2;
7586 if (!case_sym)
7587 expect("switch");
7588 next();
7589 v1 = expr_const();
7590 v2 = v1;
7591 if (gnu_ext && tok == TOK_DOTS) {
7592 next();
7593 v2 = expr_const();
7594 if (v2 < v1)
7595 warning("empty case range");
7597 /* since a case is like a label, we must skip it with a jmp */
7598 b = gjmp(0);
7599 gsym(*case_sym);
7600 vseti(case_reg, 0);
7601 vpushi(v1);
7602 if (v1 == v2) {
7603 gen_op(TOK_EQ);
7604 *case_sym = gtst(1, 0);
7605 } else {
7606 gen_op(TOK_GE);
7607 *case_sym = gtst(1, 0);
7608 vseti(case_reg, 0);
7609 vpushi(v2);
7610 gen_op(TOK_LE);
7611 *case_sym = gtst(1, *case_sym);
7613 gsym(b);
7614 skip(':');
7615 is_expr = 0;
7616 goto block_after_label;
7617 } else
7618 if (tok == TOK_DEFAULT) {
7619 next();
7620 skip(':');
7621 if (!def_sym)
7622 expect("switch");
7623 if (*def_sym)
7624 error("too many 'default'");
7625 *def_sym = ind;
7626 is_expr = 0;
7627 goto block_after_label;
7628 } else
7629 if (tok == TOK_GOTO) {
7630 next();
7631 if (tok == '*' && gnu_ext) {
7632 /* computed goto */
7633 next();
7634 gexpr();
7635 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7636 expect("pointer");
7637 ggoto();
7638 } else if (tok >= TOK_UIDENT) {
7639 s = label_find(tok);
7640 /* put forward definition if needed */
7641 if (!s) {
7642 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7643 } else {
7644 if (s->r == LABEL_DECLARED)
7645 s->r = LABEL_FORWARD;
7647 /* label already defined */
7648 if (s->r & LABEL_FORWARD)
7649 s->next = (void *)gjmp((long)s->next);
7650 else
7651 gjmp_addr((long)s->next);
7652 next();
7653 } else {
7654 expect("label identifier");
7656 skip(';');
7657 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7658 asm_instr();
7659 } else {
7660 b = is_label();
7661 if (b) {
7662 /* label case */
7663 s = label_find(b);
7664 if (s) {
7665 if (s->r == LABEL_DEFINED)
7666 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7667 gsym((long)s->next);
7668 s->r = LABEL_DEFINED;
7669 } else {
7670 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7672 s->next = (void *)ind;
7673 /* we accept this, but it is a mistake */
7674 block_after_label:
7675 if (tok == '}') {
7676 warning("deprecated use of label at end of compound statement");
7677 } else {
7678 if (is_expr)
7679 vpop();
7680 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7682 } else {
7683 /* expression case */
7684 if (tok != ';') {
7685 if (is_expr) {
7686 vpop();
7687 gexpr();
7688 } else {
7689 gexpr();
7690 vpop();
7693 skip(';');
7698 /* t is the array or struct type. c is the array or struct
7699 address. cur_index/cur_field is the pointer to the current
7700 value. 'size_only' is true if only size info is needed (only used
7701 in arrays) */
7702 static void decl_designator(CType *type, Section *sec, unsigned long c,
7703 int *cur_index, Sym **cur_field,
7704 int size_only)
7706 Sym *s, *f;
7707 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7708 CType type1;
7710 notfirst = 0;
7711 elem_size = 0;
7712 nb_elems = 1;
7713 if (gnu_ext && (l = is_label()) != 0)
7714 goto struct_field;
7715 while (tok == '[' || tok == '.') {
7716 if (tok == '[') {
7717 if (!(type->t & VT_ARRAY))
7718 expect("array type");
7719 s = type->ref;
7720 next();
7721 index = expr_const();
7722 if (index < 0 || (s->c >= 0 && index >= s->c))
7723 expect("invalid index");
7724 if (tok == TOK_DOTS && gnu_ext) {
7725 next();
7726 index_last = expr_const();
7727 if (index_last < 0 ||
7728 (s->c >= 0 && index_last >= s->c) ||
7729 index_last < index)
7730 expect("invalid index");
7731 } else {
7732 index_last = index;
7734 skip(']');
7735 if (!notfirst)
7736 *cur_index = index_last;
7737 type = pointed_type(type);
7738 elem_size = type_size(type, &align);
7739 c += index * elem_size;
7740 /* NOTE: we only support ranges for last designator */
7741 nb_elems = index_last - index + 1;
7742 if (nb_elems != 1) {
7743 notfirst = 1;
7744 break;
7746 } else {
7747 next();
7748 l = tok;
7749 next();
7750 struct_field:
7751 if ((type->t & VT_BTYPE) != VT_STRUCT)
7752 expect("struct/union type");
7753 s = type->ref;
7754 l |= SYM_FIELD;
7755 f = s->next;
7756 while (f) {
7757 if (f->v == l)
7758 break;
7759 f = f->next;
7761 if (!f)
7762 expect("field");
7763 if (!notfirst)
7764 *cur_field = f;
7765 /* XXX: fix this mess by using explicit storage field */
7766 type1 = f->type;
7767 type1.t |= (type->t & ~VT_TYPE);
7768 type = &type1;
7769 c += f->c;
7771 notfirst = 1;
7773 if (notfirst) {
7774 if (tok == '=') {
7775 next();
7776 } else {
7777 if (!gnu_ext)
7778 expect("=");
7780 } else {
7781 if (type->t & VT_ARRAY) {
7782 index = *cur_index;
7783 type = pointed_type(type);
7784 c += index * type_size(type, &align);
7785 } else {
7786 f = *cur_field;
7787 if (!f)
7788 error("too many field init");
7789 /* XXX: fix this mess by using explicit storage field */
7790 type1 = f->type;
7791 type1.t |= (type->t & ~VT_TYPE);
7792 type = &type1;
7793 c += f->c;
7796 decl_initializer(type, sec, c, 0, size_only);
7798 /* XXX: make it more general */
7799 if (!size_only && nb_elems > 1) {
7800 unsigned long c_end;
7801 uint8_t *src, *dst;
7802 int i;
7804 if (!sec)
7805 error("range init not supported yet for dynamic storage");
7806 c_end = c + nb_elems * elem_size;
7807 if (c_end > sec->data_allocated)
7808 section_realloc(sec, c_end);
7809 src = sec->data + c;
7810 dst = src;
7811 for(i = 1; i < nb_elems; i++) {
7812 dst += elem_size;
7813 memcpy(dst, src, elem_size);
7818 #define EXPR_VAL 0
7819 #define EXPR_CONST 1
7820 #define EXPR_ANY 2
7822 /* store a value or an expression directly in global data or in local array */
7823 static void init_putv(CType *type, Section *sec, unsigned long c,
7824 int v, int expr_type)
7826 int saved_global_expr, bt, bit_pos, bit_size;
7827 void *ptr;
7828 unsigned long long bit_mask;
7829 CType dtype;
7831 switch(expr_type) {
7832 case EXPR_VAL:
7833 vpushi(v);
7834 break;
7835 case EXPR_CONST:
7836 /* compound literals must be allocated globally in this case */
7837 saved_global_expr = global_expr;
7838 global_expr = 1;
7839 expr_const1();
7840 global_expr = saved_global_expr;
7841 /* NOTE: symbols are accepted */
7842 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
7843 error("initializer element is not constant");
7844 break;
7845 case EXPR_ANY:
7846 expr_eq();
7847 break;
7850 dtype = *type;
7851 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7853 if (sec) {
7854 /* XXX: not portable */
7855 /* XXX: generate error if incorrect relocation */
7856 gen_assign_cast(&dtype);
7857 bt = type->t & VT_BTYPE;
7858 ptr = sec->data + c;
7859 /* XXX: make code faster ? */
7860 if (!(type->t & VT_BITFIELD)) {
7861 bit_pos = 0;
7862 bit_size = 32;
7863 bit_mask = -1LL;
7864 } else {
7865 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
7866 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
7867 bit_mask = (1LL << bit_size) - 1;
7869 if ((vtop->r & VT_SYM) &&
7870 (bt == VT_BYTE ||
7871 bt == VT_SHORT ||
7872 bt == VT_DOUBLE ||
7873 bt == VT_LDOUBLE ||
7874 bt == VT_LLONG ||
7875 (bt == VT_INT && bit_size != 32)))
7876 error("initializer element is not computable at load time");
7877 switch(bt) {
7878 case VT_BYTE:
7879 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7880 break;
7881 case VT_SHORT:
7882 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7883 break;
7884 case VT_DOUBLE:
7885 *(double *)ptr = vtop->c.d;
7886 break;
7887 case VT_LDOUBLE:
7888 *(long double *)ptr = vtop->c.ld;
7889 break;
7890 case VT_LLONG:
7891 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
7892 break;
7893 default:
7894 if (vtop->r & VT_SYM) {
7895 greloc(sec, vtop->sym, c, R_DATA_32);
7897 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7898 break;
7900 vtop--;
7901 } else {
7902 vset(&dtype, VT_LOCAL, c);
7903 vswap();
7904 vstore();
7905 vpop();
7909 /* put zeros for variable based init */
7910 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
7912 if (sec) {
7913 /* nothing to do because globals are already set to zero */
7914 } else {
7915 vpush_global_sym(&func_old_type, TOK_memset);
7916 vseti(VT_LOCAL, c);
7917 vpushi(0);
7918 vpushi(size);
7919 gfunc_call(3);
7923 /* 't' contains the type and storage info. 'c' is the offset of the
7924 object in section 'sec'. If 'sec' is NULL, it means stack based
7925 allocation. 'first' is true if array '{' must be read (multi
7926 dimension implicit array init handling). 'size_only' is true if
7927 size only evaluation is wanted (only for arrays). */
7928 static void decl_initializer(CType *type, Section *sec, unsigned long c,
7929 int first, int size_only)
7931 int index, array_length, n, no_oblock, nb, parlevel, i;
7932 int size1, align1, expr_type;
7933 Sym *s, *f;
7934 CType *t1;
7936 if (type->t & VT_ARRAY) {
7937 s = type->ref;
7938 n = s->c;
7939 array_length = 0;
7940 t1 = pointed_type(type);
7941 size1 = type_size(t1, &align1);
7943 no_oblock = 1;
7944 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
7945 tok == '{') {
7946 skip('{');
7947 no_oblock = 0;
7950 /* only parse strings here if correct type (otherwise: handle
7951 them as ((w)char *) expressions */
7952 if ((tok == TOK_LSTR &&
7953 (t1->t & VT_BTYPE) == VT_INT) ||
7954 (tok == TOK_STR &&
7955 (t1->t & VT_BTYPE) == VT_BYTE)) {
7956 while (tok == TOK_STR || tok == TOK_LSTR) {
7957 int cstr_len, ch;
7958 CString *cstr;
7960 cstr = tokc.cstr;
7961 /* compute maximum number of chars wanted */
7962 if (tok == TOK_STR)
7963 cstr_len = cstr->size;
7964 else
7965 cstr_len = cstr->size / sizeof(int);
7966 cstr_len--;
7967 nb = cstr_len;
7968 if (n >= 0 && nb > (n - array_length))
7969 nb = n - array_length;
7970 if (!size_only) {
7971 if (cstr_len > nb)
7972 warning("initializer-string for array is too long");
7973 /* in order to go faster for common case (char
7974 string in global variable, we handle it
7975 specifically */
7976 if (sec && tok == TOK_STR && size1 == 1) {
7977 memcpy(sec->data + c + array_length, cstr->data, nb);
7978 } else {
7979 for(i=0;i<nb;i++) {
7980 if (tok == TOK_STR)
7981 ch = ((unsigned char *)cstr->data)[i];
7982 else
7983 ch = ((int *)cstr->data)[i];
7984 init_putv(t1, sec, c + (array_length + i) * size1,
7985 ch, EXPR_VAL);
7989 array_length += nb;
7990 next();
7992 /* only add trailing zero if enough storage (no
7993 warning in this case since it is standard) */
7994 if (n < 0 || array_length < n) {
7995 if (!size_only) {
7996 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
7998 array_length++;
8000 } else {
8001 index = 0;
8002 while (tok != '}') {
8003 decl_designator(type, sec, c, &index, NULL, size_only);
8004 if (n >= 0 && index >= n)
8005 error("index too large");
8006 /* must put zero in holes (note that doing it that way
8007 ensures that it even works with designators) */
8008 if (!size_only && array_length < index) {
8009 init_putz(t1, sec, c + array_length * size1,
8010 (index - array_length) * size1);
8012 index++;
8013 if (index > array_length)
8014 array_length = index;
8015 /* special test for multi dimensional arrays (may not
8016 be strictly correct if designators are used at the
8017 same time) */
8018 if (index >= n && no_oblock)
8019 break;
8020 if (tok == '}')
8021 break;
8022 skip(',');
8025 if (!no_oblock)
8026 skip('}');
8027 /* put zeros at the end */
8028 if (!size_only && n >= 0 && array_length < n) {
8029 init_putz(t1, sec, c + array_length * size1,
8030 (n - array_length) * size1);
8032 /* patch type size if needed */
8033 if (n < 0)
8034 s->c = array_length;
8035 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8036 (sec || !first || tok == '{')) {
8037 int par_count;
8039 /* NOTE: the previous test is a specific case for automatic
8040 struct/union init */
8041 /* XXX: union needs only one init */
8043 /* XXX: this test is incorrect for local initializers
8044 beginning with ( without {. It would be much more difficult
8045 to do it correctly (ideally, the expression parser should
8046 be used in all cases) */
8047 par_count = 0;
8048 if (tok == '(') {
8049 AttributeDef ad1;
8050 CType type1;
8051 next();
8052 while (tok == '(') {
8053 par_count++;
8054 next();
8056 if (!parse_btype(&type1, &ad1))
8057 expect("cast");
8058 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8059 #if 0
8060 if (!is_assignable_types(type, &type1))
8061 error("invalid type for cast");
8062 #endif
8063 skip(')');
8065 no_oblock = 1;
8066 if (first || tok == '{') {
8067 skip('{');
8068 no_oblock = 0;
8070 s = type->ref;
8071 f = s->next;
8072 array_length = 0;
8073 index = 0;
8074 n = s->c;
8075 while (tok != '}') {
8076 decl_designator(type, sec, c, NULL, &f, size_only);
8077 index = f->c;
8078 if (!size_only && array_length < index) {
8079 init_putz(type, sec, c + array_length,
8080 index - array_length);
8082 index = index + type_size(&f->type, &align1);
8083 if (index > array_length)
8084 array_length = index;
8085 f = f->next;
8086 if (no_oblock && f == NULL)
8087 break;
8088 if (tok == '}')
8089 break;
8090 skip(',');
8092 /* put zeros at the end */
8093 if (!size_only && array_length < n) {
8094 init_putz(type, sec, c + array_length,
8095 n - array_length);
8097 if (!no_oblock)
8098 skip('}');
8099 while (par_count) {
8100 skip(')');
8101 par_count--;
8103 } else if (tok == '{') {
8104 next();
8105 decl_initializer(type, sec, c, first, size_only);
8106 skip('}');
8107 } else if (size_only) {
8108 /* just skip expression */
8109 parlevel = 0;
8110 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8111 tok != -1) {
8112 if (tok == '(')
8113 parlevel++;
8114 else if (tok == ')')
8115 parlevel--;
8116 next();
8118 } else {
8119 /* currently, we always use constant expression for globals
8120 (may change for scripting case) */
8121 expr_type = EXPR_CONST;
8122 if (!sec)
8123 expr_type = EXPR_ANY;
8124 init_putv(type, sec, c, 0, expr_type);
8128 /* parse an initializer for type 't' if 'has_init' is non zero, and
8129 allocate space in local or global data space ('r' is either
8130 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8131 variable 'v' of scope 'scope' is declared before initializers are
8132 parsed. If 'v' is zero, then a reference to the new object is put
8133 in the value stack. If 'has_init' is 2, a special parsing is done
8134 to handle string constants. */
8135 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8136 int has_init, int v, int scope)
8138 int size, align, addr, data_offset;
8139 int level;
8140 ParseState saved_parse_state;
8141 TokenString init_str;
8142 Section *sec;
8144 size = type_size(type, &align);
8145 /* If unknown size, we must evaluate it before
8146 evaluating initializers because
8147 initializers can generate global data too
8148 (e.g. string pointers or ISOC99 compound
8149 literals). It also simplifies local
8150 initializers handling */
8151 tok_str_new(&init_str);
8152 if (size < 0) {
8153 if (!has_init)
8154 error("unknown type size");
8155 /* get all init string */
8156 if (has_init == 2) {
8157 /* only get strings */
8158 while (tok == TOK_STR || tok == TOK_LSTR) {
8159 tok_str_add_tok(&init_str);
8160 next();
8162 } else {
8163 level = 0;
8164 while (level > 0 || (tok != ',' && tok != ';')) {
8165 if (tok < 0)
8166 error("unexpected end of file in initializer");
8167 tok_str_add_tok(&init_str);
8168 if (tok == '{')
8169 level++;
8170 else if (tok == '}') {
8171 if (level == 0)
8172 break;
8173 level--;
8175 next();
8178 tok_str_add(&init_str, -1);
8179 tok_str_add(&init_str, 0);
8181 /* compute size */
8182 save_parse_state(&saved_parse_state);
8184 macro_ptr = init_str.str;
8185 next();
8186 decl_initializer(type, NULL, 0, 1, 1);
8187 /* prepare second initializer parsing */
8188 macro_ptr = init_str.str;
8189 next();
8191 /* if still unknown size, error */
8192 size = type_size(type, &align);
8193 if (size < 0)
8194 error("unknown type size");
8196 /* take into account specified alignment if bigger */
8197 if (ad->aligned > align)
8198 align = ad->aligned;
8199 if ((r & VT_VALMASK) == VT_LOCAL) {
8200 sec = NULL;
8201 if (do_bounds_check && (type->t & VT_ARRAY))
8202 loc--;
8203 loc = (loc - size) & -align;
8204 addr = loc;
8205 /* handles bounds */
8206 /* XXX: currently, since we do only one pass, we cannot track
8207 '&' operators, so we add only arrays */
8208 if (do_bounds_check && (type->t & VT_ARRAY)) {
8209 unsigned long *bounds_ptr;
8210 /* add padding between regions */
8211 loc--;
8212 /* then add local bound info */
8213 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8214 bounds_ptr[0] = addr;
8215 bounds_ptr[1] = size;
8217 if (v) {
8218 /* local variable */
8219 sym_push(v, type, r, addr);
8220 } else {
8221 /* push local reference */
8222 vset(type, r, addr);
8224 } else {
8225 Sym *sym;
8227 sym = NULL;
8228 if (v && scope == VT_CONST) {
8229 /* see if the symbol was already defined */
8230 sym = sym_find(v);
8231 if (sym) {
8232 if (!is_compatible_types(&sym->type, type))
8233 error("incompatible types for redefinition of '%s'",
8234 get_tok_str(v, NULL));
8235 if (sym->type.t & VT_EXTERN) {
8236 /* if the variable is extern, it was not allocated */
8237 sym->type.t &= ~VT_EXTERN;
8238 } else {
8239 /* we accept several definitions of the same
8240 global variable. this is tricky, because we
8241 must play with the SHN_COMMON type of the symbol */
8242 /* XXX: should check if the variable was already
8243 initialized. It is incorrect to initialized it
8244 twice */
8245 /* no init data, we won't add more to the symbol */
8246 if (!has_init)
8247 goto no_alloc;
8252 /* allocate symbol in corresponding section */
8253 sec = ad->section;
8254 if (!sec) {
8255 if (has_init)
8256 sec = data_section;
8258 if (sec) {
8259 data_offset = sec->data_offset;
8260 data_offset = (data_offset + align - 1) & -align;
8261 addr = data_offset;
8262 /* very important to increment global pointer at this time
8263 because initializers themselves can create new initializers */
8264 data_offset += size;
8265 /* add padding if bound check */
8266 if (do_bounds_check)
8267 data_offset++;
8268 sec->data_offset = data_offset;
8269 /* allocate section space to put the data */
8270 if (sec->sh_type != SHT_NOBITS &&
8271 data_offset > sec->data_allocated)
8272 section_realloc(sec, data_offset);
8273 } else {
8274 addr = 0; /* avoid warning */
8277 if (v) {
8278 if (scope == VT_CONST) {
8279 if (!sym)
8280 goto do_def;
8281 } else {
8282 do_def:
8283 sym = sym_push(v, type, r | VT_SYM, 0);
8285 /* update symbol definition */
8286 if (sec) {
8287 put_extern_sym(sym, sec, addr, size);
8288 } else {
8289 Elf32_Sym *esym;
8290 /* put a common area */
8291 put_extern_sym(sym, NULL, align, size);
8292 /* XXX: find a nicer way */
8293 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8294 esym->st_shndx = SHN_COMMON;
8296 } else {
8297 CValue cval;
8299 /* push global reference */
8300 sym = get_sym_ref(type, sec, addr, size);
8301 cval.ul = 0;
8302 vsetc(type, VT_CONST | VT_SYM, &cval);
8303 vtop->sym = sym;
8306 /* handles bounds now because the symbol must be defined
8307 before for the relocation */
8308 if (do_bounds_check) {
8309 unsigned long *bounds_ptr;
8311 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8312 /* then add global bound info */
8313 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8314 bounds_ptr[0] = 0; /* relocated */
8315 bounds_ptr[1] = size;
8318 if (has_init) {
8319 decl_initializer(type, sec, addr, 1, 0);
8320 /* restore parse state if needed */
8321 if (init_str.str) {
8322 tok_str_free(init_str.str);
8323 restore_parse_state(&saved_parse_state);
8326 no_alloc: ;
8329 void put_func_debug(Sym *sym)
8331 char buf[512];
8333 /* stabs info */
8334 /* XXX: we put here a dummy type */
8335 snprintf(buf, sizeof(buf), "%s:%c1",
8336 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8337 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8338 cur_text_section, sym->c);
8339 last_ind = 0;
8340 last_line_num = 0;
8343 /* not finished : try to put some local vars in registers */
8344 //#define CONFIG_REG_VARS
8346 #ifdef CONFIG_REG_VARS
8347 void add_var_ref(int t)
8349 printf("%s:%d: &%s\n",
8350 file->filename, file->line_num,
8351 get_tok_str(t, NULL));
8354 /* first pass on a function with heuristic to extract variable usage
8355 and pointer references to local variables for register allocation */
8356 void analyse_function(void)
8358 int level, t;
8360 for(;;) {
8361 if (tok == -1)
8362 break;
8363 /* any symbol coming after '&' is considered as being a
8364 variable whose reference is taken. It is highly unaccurate
8365 but it is difficult to do better without a complete parse */
8366 if (tok == '&') {
8367 next();
8368 /* if '& number', then no need to examine next tokens */
8369 if (tok == TOK_CINT ||
8370 tok == TOK_CUINT ||
8371 tok == TOK_CLLONG ||
8372 tok == TOK_CULLONG) {
8373 continue;
8374 } else if (tok >= TOK_UIDENT) {
8375 /* if '& ident [' or '& ident ->', then ident address
8376 is not needed */
8377 t = tok;
8378 next();
8379 if (tok != '[' && tok != TOK_ARROW)
8380 add_var_ref(t);
8381 } else {
8382 level = 0;
8383 while (tok != '}' && tok != ';' &&
8384 !((tok == ',' || tok == ')') && level == 0)) {
8385 if (tok >= TOK_UIDENT) {
8386 add_var_ref(tok);
8387 } else if (tok == '(') {
8388 level++;
8389 } else if (tok == ')') {
8390 level--;
8392 next();
8395 } else {
8396 next();
8400 #endif
8402 /* parse an old style function declaration list */
8403 /* XXX: check multiple parameter */
8404 static void func_decl_list(Sym *func_sym)
8406 AttributeDef ad;
8407 int v;
8408 Sym *s;
8409 CType btype, type;
8411 /* parse each declaration */
8412 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8413 if (!parse_btype(&btype, &ad))
8414 expect("declaration list");
8415 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8416 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8417 tok == ';') {
8418 /* we accept no variable after */
8419 } else {
8420 for(;;) {
8421 type = btype;
8422 type_decl(&type, &ad, &v, TYPE_DIRECT);
8423 /* find parameter in function parameter list */
8424 s = func_sym->next;
8425 while (s != NULL) {
8426 if ((s->v & ~SYM_FIELD) == v)
8427 goto found;
8428 s = s->next;
8430 error("declaration for parameter '%s' but no such parameter",
8431 get_tok_str(v, NULL));
8432 found:
8433 /* check that no storage specifier except 'register' was given */
8434 if (type.t & VT_STORAGE)
8435 error("storage class specified for '%s'", get_tok_str(v, NULL));
8436 convert_parameter_type(&type);
8437 /* we can add the type (NOTE: it could be local to the function) */
8438 s->type = type;
8439 /* accept other parameters */
8440 if (tok == ',')
8441 next();
8442 else
8443 break;
8446 skip(';');
8450 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8451 static void decl(int l)
8453 int v, has_init, r;
8454 CType type, btype;
8455 Sym *sym;
8456 AttributeDef ad;
8458 while (1) {
8459 if (!parse_btype(&btype, &ad)) {
8460 /* skip redundant ';' */
8461 /* XXX: find more elegant solution */
8462 if (tok == ';') {
8463 next();
8464 continue;
8466 /* special test for old K&R protos without explicit int
8467 type. Only accepted when defining global data */
8468 if (l == VT_LOCAL || tok < TOK_DEFINE)
8469 break;
8470 btype.t = VT_INT;
8472 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8473 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8474 tok == ';') {
8475 /* we accept no variable after */
8476 next();
8477 continue;
8479 while (1) { /* iterate thru each declaration */
8480 type = btype;
8481 type_decl(&type, &ad, &v, TYPE_DIRECT);
8482 #if 0
8484 char buf[500];
8485 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8486 printf("type = '%s'\n", buf);
8488 #endif
8489 if ((type.t & VT_BTYPE) == VT_FUNC) {
8490 /* if old style function prototype, we accept a
8491 declaration list */
8492 sym = type.ref;
8493 if (sym->c == FUNC_OLD)
8494 func_decl_list(sym);
8497 if (tok == '{') {
8498 #ifdef CONFIG_REG_VARS
8499 TokenString func_str;
8500 ParseState saved_parse_state;
8501 int block_level;
8502 #endif
8504 if (l == VT_LOCAL)
8505 error("cannot use local functions");
8506 if (!(type.t & VT_FUNC))
8507 expect("function definition");
8508 /* XXX: cannot do better now: convert extern line to static inline */
8509 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8510 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8512 #ifdef CONFIG_REG_VARS
8513 /* parse all function code and record it */
8515 tok_str_new(&func_str);
8517 block_level = 0;
8518 for(;;) {
8519 int t;
8520 if (tok == -1)
8521 error("unexpected end of file");
8522 tok_str_add_tok(&func_str);
8523 t = tok;
8524 next();
8525 if (t == '{') {
8526 block_level++;
8527 } else if (t == '}') {
8528 block_level--;
8529 if (block_level == 0)
8530 break;
8533 tok_str_add(&func_str, -1);
8534 tok_str_add(&func_str, 0);
8536 save_parse_state(&saved_parse_state);
8538 macro_ptr = func_str.str;
8539 next();
8540 analyse_function();
8541 #endif
8543 /* compute text section */
8544 cur_text_section = ad.section;
8545 if (!cur_text_section)
8546 cur_text_section = text_section;
8547 ind = cur_text_section->data_offset;
8548 funcname = get_tok_str(v, NULL);
8549 sym = sym_find(v);
8550 if (sym) {
8551 /* if symbol is already defined, then put complete type */
8552 sym->type = type;
8553 } else {
8554 /* put function symbol */
8555 sym = global_identifier_push(v, type.t, 0);
8556 sym->type.ref = type.ref;
8558 /* NOTE: we patch the symbol size later */
8559 put_extern_sym(sym, cur_text_section, ind, 0);
8560 func_ind = ind;
8561 sym->r = VT_SYM | VT_CONST;
8562 /* put debug symbol */
8563 if (do_debug)
8564 put_func_debug(sym);
8565 /* push a dummy symbol to enable local sym storage */
8566 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8567 gfunc_prolog(&type);
8568 loc = 0;
8569 rsym = 0;
8570 #ifdef CONFIG_REG_VARS
8571 macro_ptr = func_str.str;
8572 next();
8573 #endif
8574 block(NULL, NULL, NULL, NULL, 0, 0);
8575 gsym(rsym);
8576 gfunc_epilog();
8577 cur_text_section->data_offset = ind;
8578 label_pop(&global_label_stack, NULL);
8579 sym_pop(&local_stack, NULL); /* reset local stack */
8580 /* end of function */
8581 /* patch symbol size */
8582 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8583 ind - func_ind;
8584 if (do_debug) {
8585 put_stabn(N_FUN, 0, 0, ind - func_ind);
8587 funcname = ""; /* for safety */
8588 func_vt.t = VT_VOID; /* for safety */
8589 ind = 0; /* for safety */
8591 #ifdef CONFIG_REG_VARS
8592 tok_str_free(func_str.str);
8593 restore_parse_state(&saved_parse_state);
8594 #endif
8595 break;
8596 } else {
8597 if (btype.t & VT_TYPEDEF) {
8598 /* save typedefed type */
8599 /* XXX: test storage specifiers ? */
8600 sym = sym_push(v, &type, 0, 0);
8601 sym->type.t |= VT_TYPEDEF;
8602 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8603 /* external function definition */
8604 external_sym(v, &type, 0);
8605 } else {
8606 /* not lvalue if array */
8607 r = 0;
8608 if (!(type.t & VT_ARRAY))
8609 r |= lvalue_type(type.t);
8610 has_init = (tok == '=');
8611 if ((btype.t & VT_EXTERN) ||
8612 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8613 !has_init && l == VT_CONST && type.ref->c < 0)) {
8614 /* external variable */
8615 /* NOTE: as GCC, uninitialized global static
8616 arrays of null size are considered as
8617 extern */
8618 external_sym(v, &type, r);
8619 } else {
8620 if (type.t & VT_STATIC)
8621 r |= VT_CONST;
8622 else
8623 r |= l;
8624 if (has_init)
8625 next();
8626 decl_initializer_alloc(&type, &ad, r,
8627 has_init, v, l);
8630 if (tok != ',') {
8631 skip(';');
8632 break;
8634 next();
8640 /* better than nothing, but needs extension to handle '-E' option
8641 correctly too */
8642 static void preprocess_init(TCCState *s1)
8644 s1->include_stack_ptr = s1->include_stack;
8645 /* XXX: move that before to avoid having to initialize
8646 file->ifdef_stack_ptr ? */
8647 s1->ifdef_stack_ptr = s1->ifdef_stack;
8648 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8650 /* XXX: not ANSI compliant: bound checking says error */
8651 vtop = vstack - 1;
8654 /* compile the C file opened in 'file'. Return non zero if errors. */
8655 static int tcc_compile(TCCState *s1)
8657 Sym *define_start;
8658 char buf[512];
8659 volatile int section_sym;
8661 #ifdef INC_DEBUG
8662 printf("%s: **** new file\n", file->filename);
8663 #endif
8664 preprocess_init(s1);
8666 funcname = "";
8667 anon_sym = SYM_FIRST_ANOM;
8669 /* file info: full path + filename */
8670 section_sym = 0; /* avoid warning */
8671 if (do_debug) {
8672 section_sym = put_elf_sym(symtab_section, 0, 0,
8673 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8674 text_section->sh_num, NULL);
8675 getcwd(buf, sizeof(buf));
8676 pstrcat(buf, sizeof(buf), "/");
8677 put_stabs_r(buf, N_SO, 0, 0,
8678 text_section->data_offset, text_section, section_sym);
8679 put_stabs_r(file->filename, N_SO, 0, 0,
8680 text_section->data_offset, text_section, section_sym);
8682 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8683 symbols can be safely used */
8684 put_elf_sym(symtab_section, 0, 0,
8685 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8686 SHN_ABS, file->filename);
8688 /* define some often used types */
8689 int_type.t = VT_INT;
8691 char_pointer_type.t = VT_BYTE;
8692 mk_pointer(&char_pointer_type);
8694 func_old_type.t = VT_FUNC;
8695 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8697 #if 0
8698 /* define 'void *alloca(unsigned int)' builtin function */
8700 Sym *s1;
8702 p = anon_sym++;
8703 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8704 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8705 s1->next = NULL;
8706 sym->next = s1;
8707 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8709 #endif
8711 define_start = define_stack;
8713 if (setjmp(s1->error_jmp_buf) == 0) {
8714 s1->nb_errors = 0;
8715 s1->error_set_jmp_enabled = 1;
8717 ch = file->buf_ptr[0];
8718 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8719 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8720 next();
8721 decl(VT_CONST);
8722 if (tok != TOK_EOF)
8723 expect("declaration");
8725 /* end of translation unit info */
8726 if (do_debug) {
8727 put_stabs_r(NULL, N_SO, 0, 0,
8728 text_section->data_offset, text_section, section_sym);
8731 s1->error_set_jmp_enabled = 0;
8733 /* reset define stack, but leave -Dsymbols (may be incorrect if
8734 they are undefined) */
8735 free_defines(define_start);
8737 sym_pop(&global_stack, NULL);
8739 return s1->nb_errors != 0 ? -1 : 0;
8742 #ifdef LIBTCC
8743 int tcc_compile_string(TCCState *s, const char *str)
8745 BufferedFile bf1, *bf = &bf1;
8746 int ret, len;
8747 char *buf;
8749 /* init file structure */
8750 bf->fd = -1;
8751 /* XXX: avoid copying */
8752 len = strlen(str);
8753 buf = tcc_malloc(len + 1);
8754 if (!buf)
8755 return -1;
8756 memcpy(buf, str, len);
8757 buf[len] = CH_EOB;
8758 bf->buf_ptr = buf;
8759 bf->buf_end = buf + len;
8760 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8761 bf->line_num = 1;
8762 file = bf;
8764 ret = tcc_compile(s);
8766 tcc_free(buf);
8768 /* currently, no need to close */
8769 return ret;
8771 #endif
8773 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8774 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8776 BufferedFile bf1, *bf = &bf1;
8778 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8779 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8780 /* default value */
8781 if (!value)
8782 value = "1";
8783 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8785 /* init file structure */
8786 bf->fd = -1;
8787 bf->buf_ptr = bf->buffer;
8788 bf->buf_end = bf->buffer + strlen(bf->buffer);
8789 *bf->buf_end = CH_EOB;
8790 bf->filename[0] = '\0';
8791 bf->line_num = 1;
8792 file = bf;
8794 s1->include_stack_ptr = s1->include_stack;
8796 /* parse with define parser */
8797 ch = file->buf_ptr[0];
8798 next_nomacro();
8799 parse_define();
8800 file = NULL;
8803 /* undefine a preprocessor symbol */
8804 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8806 TokenSym *ts;
8807 Sym *s;
8808 ts = tok_alloc(sym, strlen(sym));
8809 s = define_find(ts->tok);
8810 /* undefine symbol by putting an invalid name */
8811 if (s)
8812 define_undef(s);
8815 #ifdef CONFIG_TCC_ASM
8817 #include "i386-asm.c"
8818 #include "tccasm.c"
8820 #else
8821 static void asm_instr(void)
8823 error("inline asm() not supported");
8825 #endif
8827 #include "tccelf.c"
8829 /* print the position in the source file of PC value 'pc' by reading
8830 the stabs debug information */
8831 static void rt_printline(unsigned long wanted_pc)
8833 Stab_Sym *sym, *sym_end;
8834 char func_name[128], last_func_name[128];
8835 unsigned long func_addr, last_pc, pc;
8836 const char *incl_files[INCLUDE_STACK_SIZE];
8837 int incl_index, len, last_line_num, i;
8838 const char *str, *p;
8840 fprintf(stderr, "0x%08lx:", wanted_pc);
8842 func_name[0] = '\0';
8843 func_addr = 0;
8844 incl_index = 0;
8845 last_func_name[0] = '\0';
8846 last_pc = 0xffffffff;
8847 last_line_num = 1;
8848 sym = (Stab_Sym *)stab_section->data + 1;
8849 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
8850 while (sym < sym_end) {
8851 switch(sym->n_type) {
8852 /* function start or end */
8853 case N_FUN:
8854 if (sym->n_strx == 0) {
8855 /* we test if between last line and end of function */
8856 pc = sym->n_value + func_addr;
8857 if (wanted_pc >= last_pc && wanted_pc < pc)
8858 goto found;
8859 func_name[0] = '\0';
8860 func_addr = 0;
8861 } else {
8862 str = stabstr_section->data + sym->n_strx;
8863 p = strchr(str, ':');
8864 if (!p) {
8865 pstrcpy(func_name, sizeof(func_name), str);
8866 } else {
8867 len = p - str;
8868 if (len > sizeof(func_name) - 1)
8869 len = sizeof(func_name) - 1;
8870 memcpy(func_name, str, len);
8871 func_name[len] = '\0';
8873 func_addr = sym->n_value;
8875 break;
8876 /* line number info */
8877 case N_SLINE:
8878 pc = sym->n_value + func_addr;
8879 if (wanted_pc >= last_pc && wanted_pc < pc)
8880 goto found;
8881 last_pc = pc;
8882 last_line_num = sym->n_desc;
8883 /* XXX: slow! */
8884 strcpy(last_func_name, func_name);
8885 break;
8886 /* include files */
8887 case N_BINCL:
8888 str = stabstr_section->data + sym->n_strx;
8889 add_incl:
8890 if (incl_index < INCLUDE_STACK_SIZE) {
8891 incl_files[incl_index++] = str;
8893 break;
8894 case N_EINCL:
8895 if (incl_index > 1)
8896 incl_index--;
8897 break;
8898 case N_SO:
8899 if (sym->n_strx == 0) {
8900 incl_index = 0; /* end of translation unit */
8901 } else {
8902 str = stabstr_section->data + sym->n_strx;
8903 /* do not add path */
8904 len = strlen(str);
8905 if (len > 0 && str[len - 1] != '/')
8906 goto add_incl;
8908 break;
8910 sym++;
8913 /* second pass: we try symtab symbols (no line number info) */
8914 incl_index = 0;
8916 Elf32_Sym *sym, *sym_end;
8917 int type;
8919 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
8920 for(sym = (Elf32_Sym *)symtab_section->data + 1;
8921 sym < sym_end;
8922 sym++) {
8923 type = ELF32_ST_TYPE(sym->st_info);
8924 if (type == STT_FUNC) {
8925 if (wanted_pc >= sym->st_value &&
8926 wanted_pc < sym->st_value + sym->st_size) {
8927 pstrcpy(last_func_name, sizeof(last_func_name),
8928 strtab_section->data + sym->st_name);
8929 goto found;
8934 /* did not find any info: */
8935 fprintf(stderr, " ???\n");
8936 return;
8937 found:
8938 if (last_func_name[0] != '\0') {
8939 fprintf(stderr, " %s()", last_func_name);
8941 if (incl_index > 0) {
8942 fprintf(stderr, " (%s:%d",
8943 incl_files[incl_index - 1], last_line_num);
8944 for(i = incl_index - 2; i >= 0; i--)
8945 fprintf(stderr, ", included from %s", incl_files[i]);
8946 fprintf(stderr, ")");
8948 fprintf(stderr, "\n");
8951 #ifndef WIN32
8953 #ifdef __i386__
8955 /* fix for glibc 2.1 */
8956 #ifndef REG_EIP
8957 #define REG_EIP EIP
8958 #define REG_EBP EBP
8959 #endif
8961 /* return the PC at frame level 'level'. Return non zero if not found */
8962 static int rt_get_caller_pc(unsigned long *paddr,
8963 ucontext_t *uc, int level)
8965 unsigned long fp;
8966 int i;
8968 if (level == 0) {
8969 #ifdef __FreeBSD__
8970 *paddr = uc->uc_mcontext.mc_eip;
8971 #else
8972 *paddr = uc->uc_mcontext.gregs[REG_EIP];
8973 #endif
8974 return 0;
8975 } else {
8976 #ifdef __FreeBSD__
8977 fp = uc->uc_mcontext.mc_ebp;
8978 #else
8979 fp = uc->uc_mcontext.gregs[REG_EBP];
8980 #endif
8981 for(i=1;i<level;i++) {
8982 /* XXX: check address validity with program info */
8983 if (fp <= 0x1000 || fp >= 0xc0000000)
8984 return -1;
8985 fp = ((unsigned long *)fp)[0];
8987 *paddr = ((unsigned long *)fp)[1];
8988 return 0;
8991 #else
8992 #error add arch specific rt_get_caller_pc()
8993 #endif
8995 /* emit a run time error at position 'pc' */
8996 void rt_error(ucontext_t *uc, const char *fmt, ...)
8998 va_list ap;
8999 unsigned long pc;
9000 int i;
9002 va_start(ap, fmt);
9003 fprintf(stderr, "Runtime error: ");
9004 vfprintf(stderr, fmt, ap);
9005 fprintf(stderr, "\n");
9006 for(i=0;i<num_callers;i++) {
9007 if (rt_get_caller_pc(&pc, uc, i) < 0)
9008 break;
9009 if (i == 0)
9010 fprintf(stderr, "at ");
9011 else
9012 fprintf(stderr, "by ");
9013 rt_printline(pc);
9015 exit(255);
9016 va_end(ap);
9019 /* signal handler for fatal errors */
9020 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9022 ucontext_t *uc = puc;
9024 switch(signum) {
9025 case SIGFPE:
9026 switch(siginf->si_code) {
9027 case FPE_INTDIV:
9028 case FPE_FLTDIV:
9029 rt_error(uc, "division by zero");
9030 break;
9031 default:
9032 rt_error(uc, "floating point exception");
9033 break;
9035 break;
9036 case SIGBUS:
9037 case SIGSEGV:
9038 if (rt_bound_error_msg && *rt_bound_error_msg)
9039 rt_error(uc, *rt_bound_error_msg);
9040 else
9041 rt_error(uc, "dereferencing invalid pointer");
9042 break;
9043 case SIGILL:
9044 rt_error(uc, "illegal instruction");
9045 break;
9046 case SIGABRT:
9047 rt_error(uc, "abort() called");
9048 break;
9049 default:
9050 rt_error(uc, "caught signal %d", signum);
9051 break;
9053 exit(255);
9055 #endif
9057 /* do all relocations (needed before using tcc_get_symbol()) */
9058 int tcc_relocate(TCCState *s1)
9060 Section *s;
9061 int i;
9063 s1->nb_errors = 0;
9065 tcc_add_runtime(s1);
9067 relocate_common_syms();
9069 /* compute relocation address : section are relocated in place. We
9070 also alloc the bss space */
9071 for(i = 1; i < s1->nb_sections; i++) {
9072 s = s1->sections[i];
9073 if (s->sh_flags & SHF_ALLOC) {
9074 if (s->sh_type == SHT_NOBITS)
9075 s->data = tcc_mallocz(s->data_offset);
9076 s->sh_addr = (unsigned long)s->data;
9080 relocate_syms(s1, 1);
9082 if (s1->nb_errors != 0)
9083 return -1;
9085 /* relocate each section */
9086 for(i = 1; i < s1->nb_sections; i++) {
9087 s = s1->sections[i];
9088 if (s->reloc)
9089 relocate_section(s1, s);
9091 return 0;
9094 /* launch the compiled program with the given arguments */
9095 int tcc_run(TCCState *s1, int argc, char **argv)
9097 int (*prog_main)(int, char **);
9099 if (tcc_relocate(s1) < 0)
9100 return -1;
9102 prog_main = tcc_get_symbol(s1, "main");
9104 if (do_debug) {
9105 #ifdef WIN32
9106 error("debug mode currently not available for Windows");
9107 #else
9108 struct sigaction sigact;
9109 /* install TCC signal handlers to print debug info on fatal
9110 runtime errors */
9111 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9112 sigact.sa_sigaction = sig_error;
9113 sigemptyset(&sigact.sa_mask);
9114 sigaction(SIGFPE, &sigact, NULL);
9115 sigaction(SIGILL, &sigact, NULL);
9116 sigaction(SIGSEGV, &sigact, NULL);
9117 sigaction(SIGBUS, &sigact, NULL);
9118 sigaction(SIGABRT, &sigact, NULL);
9119 #endif
9122 #ifdef CONFIG_TCC_BCHECK
9123 if (do_bounds_check) {
9124 void (*bound_init)(void);
9126 /* set error function */
9127 rt_bound_error_msg = (void *)tcc_get_symbol(s1, "__bound_error_msg");
9129 /* XXX: use .init section so that it also work in binary ? */
9130 bound_init = (void *)tcc_get_symbol(s1, "__bound_init");
9131 bound_init();
9133 #endif
9134 return (*prog_main)(argc, argv);
9137 TCCState *tcc_new(void)
9139 const char *p, *r;
9140 TCCState *s;
9141 TokenSym *ts;
9142 int i, c;
9144 s = tcc_mallocz(sizeof(TCCState));
9145 if (!s)
9146 return NULL;
9147 tcc_state = s;
9148 s->output_type = TCC_OUTPUT_MEMORY;
9150 /* init isid table */
9151 for(i=0;i<256;i++)
9152 isidnum_table[i] = isid(i) || isnum(i);
9154 /* add all tokens */
9155 table_ident = NULL;
9156 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9158 tok_ident = TOK_IDENT;
9159 p = tcc_keywords;
9160 while (*p) {
9161 r = p;
9162 for(;;) {
9163 c = *r++;
9164 if (c == '\0')
9165 break;
9167 ts = tok_alloc(p, r - p - 1);
9168 p = r;
9171 /* we add dummy defines for some special macros to speed up tests
9172 and to have working defined() */
9173 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9174 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9175 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9176 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9178 /* standard defines */
9179 tcc_define_symbol(s, "__STDC__", NULL);
9180 #if defined(TCC_TARGET_I386)
9181 tcc_define_symbol(s, "__i386__", NULL);
9182 #endif
9183 #if defined(linux)
9184 tcc_define_symbol(s, "__linux__", NULL);
9185 tcc_define_symbol(s, "linux", NULL);
9186 #endif
9187 /* tiny C specific defines */
9188 tcc_define_symbol(s, "__TINYC__", NULL);
9190 /* tiny C & gcc defines */
9191 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9192 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9193 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9195 /* default library paths */
9196 tcc_add_library_path(s, "/usr/local/lib");
9197 tcc_add_library_path(s, "/usr/lib");
9198 tcc_add_library_path(s, "/lib");
9200 /* no section zero */
9201 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9203 /* create standard sections */
9204 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9205 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9206 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9208 /* symbols are always generated for linking stage */
9209 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9210 ".strtab",
9211 ".hashtab", SHF_PRIVATE);
9212 strtab_section = symtab_section->link;
9214 /* private symbol table for dynamic symbols */
9215 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9216 ".dynstrtab",
9217 ".dynhashtab", SHF_PRIVATE);
9218 s->alacarte_link = 1;
9219 return s;
9222 void tcc_delete(TCCState *s1)
9224 int i, n;
9226 /* free -D defines */
9227 free_defines(NULL);
9229 /* free tokens */
9230 n = tok_ident - TOK_IDENT;
9231 for(i = 0; i < n; i++)
9232 tcc_free(table_ident[i]);
9233 tcc_free(table_ident);
9235 /* free all sections */
9237 free_section(symtab_section->hash);
9239 free_section(s1->dynsymtab_section->hash);
9240 free_section(s1->dynsymtab_section->link);
9241 free_section(s1->dynsymtab_section);
9243 for(i = 1; i < s1->nb_sections; i++)
9244 free_section(s1->sections[i]);
9245 tcc_free(s1->sections);
9247 /* free loaded dlls array */
9248 for(i = 0; i < s1->nb_loaded_dlls; i++)
9249 tcc_free(s1->loaded_dlls[i]);
9250 tcc_free(s1->loaded_dlls);
9252 /* library paths */
9253 for(i = 0; i < s1->nb_library_paths; i++)
9254 tcc_free(s1->library_paths[i]);
9255 tcc_free(s1->library_paths);
9257 /* cached includes */
9258 for(i = 0; i < s1->nb_cached_includes; i++)
9259 tcc_free(s1->cached_includes[i]);
9260 tcc_free(s1->cached_includes);
9262 for(i = 0; i < s1->nb_include_paths; i++)
9263 tcc_free(s1->include_paths[i]);
9264 tcc_free(s1->include_paths);
9266 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9267 tcc_free(s1->sysinclude_paths[i]);
9268 tcc_free(s1->sysinclude_paths);
9270 tcc_free(s1);
9273 int tcc_add_include_path(TCCState *s1, const char *pathname)
9275 char *pathname1;
9277 pathname1 = tcc_strdup(pathname);
9278 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9279 return 0;
9282 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9284 char *pathname1;
9286 pathname1 = tcc_strdup(pathname);
9287 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9288 return 0;
9291 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9293 const char *ext, *filename1;
9294 Elf32_Ehdr ehdr;
9295 int fd, ret;
9296 BufferedFile *saved_file;
9298 /* find source file type with extension */
9299 filename1 = strrchr(filename, '/');
9300 if (filename1)
9301 filename1++;
9302 else
9303 filename1 = filename;
9304 ext = strrchr(filename1, '.');
9305 if (ext)
9306 ext++;
9308 /* open the file */
9309 saved_file = file;
9310 file = tcc_open(s1, filename);
9311 if (!file) {
9312 if (flags & AFF_PRINT_ERROR) {
9313 error_noabort("file '%s' not found", filename);
9315 ret = -1;
9316 goto fail1;
9319 if (!ext || !strcmp(ext, "c")) {
9320 /* C file assumed */
9321 ret = tcc_compile(s1);
9322 } else
9323 #ifdef CONFIG_TCC_ASM
9324 if (!strcmp(ext, "S")) {
9325 /* preprocessed assembler */
9326 ret = tcc_assemble(s1, 1);
9327 } else if (!strcmp(ext, "s")) {
9328 /* non preprocessed assembler */
9329 ret = tcc_assemble(s1, 0);
9330 } else
9331 #endif
9333 fd = file->fd;
9334 /* assume executable format: auto guess file type */
9335 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
9336 error_noabort("could not read header");
9337 goto fail;
9339 lseek(fd, 0, SEEK_SET);
9341 if (ehdr.e_ident[0] == ELFMAG0 &&
9342 ehdr.e_ident[1] == ELFMAG1 &&
9343 ehdr.e_ident[2] == ELFMAG2 &&
9344 ehdr.e_ident[3] == ELFMAG3) {
9345 file->line_num = 0; /* do not display line number if error */
9346 if (ehdr.e_type == ET_REL) {
9347 ret = tcc_load_object_file(s1, fd, 0);
9348 } else if (ehdr.e_type == ET_DYN) {
9349 ret = tcc_load_dll(s1, fd, filename,
9350 (flags & AFF_REFERENCED_DLL) != 0);
9351 } else {
9352 error_noabort("unrecognized ELF file");
9353 goto fail;
9355 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9356 file->line_num = 0; /* do not display line number if error */
9357 ret = tcc_load_archive(s1, fd);
9358 } else {
9359 /* as GNU ld, consider it is an ld script if not recognized */
9360 ret = tcc_load_ldscript(s1);
9361 if (ret < 0) {
9362 error_noabort("unrecognized file type");
9363 goto fail;
9367 the_end:
9368 tcc_close(file);
9369 fail1:
9370 file = saved_file;
9371 return ret;
9372 fail:
9373 ret = -1;
9374 goto the_end;
9377 int tcc_add_file(TCCState *s, const char *filename)
9379 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9382 int tcc_add_library_path(TCCState *s, const char *pathname)
9384 char *pathname1;
9386 pathname1 = tcc_strdup(pathname);
9387 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9388 return 0;
9391 /* find and load a dll. Return non zero if not found */
9392 /* XXX: add '-rpath' option support ? */
9393 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9395 char buf[1024];
9396 int i;
9398 for(i = 0; i < s->nb_library_paths; i++) {
9399 snprintf(buf, sizeof(buf), "%s/%s",
9400 s->library_paths[i], filename);
9401 if (tcc_add_file_internal(s, buf, flags) == 0)
9402 return 0;
9404 return -1;
9407 /* the library name is the same as the argument of the '-l' option */
9408 int tcc_add_library(TCCState *s, const char *libraryname)
9410 char buf[1024];
9411 int i;
9412 void *h;
9414 /* first we look for the dynamic library if not static linking */
9415 if (!s->static_link) {
9416 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9417 /* if we output to memory, then we simply we dlopen(). */
9418 if (s->output_type == TCC_OUTPUT_MEMORY) {
9419 /* Since the libc is already loaded, we don't need to load it again */
9420 if (!strcmp(libraryname, "c"))
9421 return 0;
9422 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
9423 if (h)
9424 return 0;
9425 } else {
9426 if (tcc_add_dll(s, buf, 0) == 0)
9427 return 0;
9431 /* then we look for the static library */
9432 for(i = 0; i < s->nb_library_paths; i++) {
9433 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9434 s->library_paths[i], libraryname);
9435 if (tcc_add_file_internal(s, buf, 0) == 0)
9436 return 0;
9438 return -1;
9441 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9443 add_elf_sym(symtab_section, val, 0,
9444 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9445 SHN_ABS, name);
9446 return 0;
9449 int tcc_set_output_type(TCCState *s, int output_type)
9451 char buf[1024];
9453 s->output_type = output_type;
9455 if (!s->nostdinc) {
9456 /* default include paths */
9457 /* XXX: reverse order needed if -isystem support */
9458 tcc_add_sysinclude_path(s, "/usr/local/include");
9459 tcc_add_sysinclude_path(s, "/usr/include");
9460 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9461 tcc_add_sysinclude_path(s, buf);
9464 /* if bound checking, then add corresponding sections */
9465 #ifdef CONFIG_TCC_BCHECK
9466 if (do_bounds_check) {
9467 /* define symbol */
9468 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9469 /* create bounds sections */
9470 bounds_section = new_section(s, ".bounds",
9471 SHT_PROGBITS, SHF_ALLOC);
9472 lbounds_section = new_section(s, ".lbounds",
9473 SHT_PROGBITS, SHF_ALLOC);
9475 #endif
9477 /* add debug sections */
9478 if (do_debug) {
9479 /* stab symbols */
9480 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9481 stab_section->sh_entsize = sizeof(Stab_Sym);
9482 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9483 put_elf_str(stabstr_section, "");
9484 stab_section->link = stabstr_section;
9485 /* put first entry */
9486 put_stabs("", 0, 0, 0, 0);
9489 /* add libc crt1/crti objects */
9490 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9491 !s->nostdlib) {
9492 if (output_type != TCC_OUTPUT_DLL)
9493 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9494 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9496 return 0;
9499 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9501 typedef struct WarningDef {
9502 int offset;
9503 int flags;
9504 const char *name;
9505 } WarningDef;
9507 static const WarningDef warning_defs[] = {
9508 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9509 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9510 { offsetof(TCCState, warn_error), 0, "error" },
9513 /* set/reset a warning */
9514 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9516 int i;
9517 const WarningDef *p;
9518 if (!strcmp(warning_name, "all")) {
9519 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9520 if (p->flags & WD_ALL)
9521 *(int *)((uint8_t *)s + p->offset) = 1;
9523 } else {
9524 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9525 if (!strcmp(warning_name, p->name))
9526 goto found;
9528 return -1;
9529 found:
9530 *(int *)((uint8_t *)s + p->offset) = value;
9532 return 0;
9536 #if !defined(LIBTCC)
9538 /* extract the basename of a file */
9539 static const char *tcc_basename(const char *name)
9541 const char *p;
9542 p = strrchr(name, '/');
9543 #ifdef WIN32
9544 if (!p)
9545 p = strrchr(name, '\\');
9546 #endif
9547 if (!p)
9548 p = name;
9549 else
9550 p++;
9551 return p;
9554 static int64_t getclock_us(void)
9556 #ifdef WIN32
9557 struct _timeb tb;
9558 _ftime(&tb);
9559 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9560 #else
9561 struct timeval tv;
9562 gettimeofday(&tv, NULL);
9563 return tv.tv_sec * 1000000LL + tv.tv_usec;
9564 #endif
9567 void help(void)
9569 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2003 Fabrice Bellard\n"
9570 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9571 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9572 " [infile1 infile2...] [-run infile args...]\n"
9573 "\n"
9574 "General options:\n"
9575 " -v display current version\n"
9576 " -c compile only - generate an object file\n"
9577 " -o outfile set output filename\n"
9578 " -Bdir set tcc internal library path\n"
9579 " -bench output compilation statistics\n"
9580 " -run run compiled source\n"
9581 " -Wwarning set or reset (with 'no-' prefix) 'warning'\n"
9582 "Preprocessor options:\n"
9583 " -Idir add include path 'dir'\n"
9584 " -Dsym[=val] define 'sym' with value 'val'\n"
9585 " -Usym undefine 'sym'\n"
9586 "Linker options:\n"
9587 " -Ldir add library path 'dir'\n"
9588 " -llib link with dynamic or static library 'lib'\n"
9589 " -shared generate a shared library\n"
9590 " -static static linking\n"
9591 " -rdynamic export all global symbols to dynamic linker\n"
9592 " -r relocatable output\n"
9593 "Debugger options:\n"
9594 " -g generate runtime debug info\n"
9595 #ifdef CONFIG_TCC_BCHECK
9596 " -b compile with built-in memory and bounds checker (implies -g)\n"
9597 #endif
9598 " -bt N show N callers in stack traces\n"
9602 #define TCC_OPTION_HAS_ARG 0x0001
9603 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9605 typedef struct TCCOption {
9606 const char *name;
9607 uint16_t index;
9608 uint16_t flags;
9609 } TCCOption;
9611 enum {
9612 TCC_OPTION_HELP,
9613 TCC_OPTION_I,
9614 TCC_OPTION_D,
9615 TCC_OPTION_U,
9616 TCC_OPTION_L,
9617 TCC_OPTION_B,
9618 TCC_OPTION_l,
9619 TCC_OPTION_bench,
9620 TCC_OPTION_bt,
9621 TCC_OPTION_b,
9622 TCC_OPTION_g,
9623 TCC_OPTION_c,
9624 TCC_OPTION_static,
9625 TCC_OPTION_shared,
9626 TCC_OPTION_o,
9627 TCC_OPTION_r,
9628 TCC_OPTION_W,
9629 TCC_OPTION_O,
9630 TCC_OPTION_m,
9631 TCC_OPTION_f,
9632 TCC_OPTION_nostdinc,
9633 TCC_OPTION_nostdlib,
9634 TCC_OPTION_print_search_dirs,
9635 TCC_OPTION_rdynamic,
9636 TCC_OPTION_run,
9637 TCC_OPTION_v,
9640 static const TCCOption tcc_options[] = {
9641 { "h", TCC_OPTION_HELP, 0 },
9642 { "?", TCC_OPTION_HELP, 0 },
9643 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9644 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9645 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9646 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9647 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9648 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9649 { "bench", TCC_OPTION_bench, 0 },
9650 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9651 #ifdef CONFIG_TCC_BCHECK
9652 { "b", TCC_OPTION_b, 0 },
9653 #endif
9654 { "g", TCC_OPTION_g, 0 },
9655 { "c", TCC_OPTION_c, 0 },
9656 { "static", TCC_OPTION_static, 0 },
9657 { "shared", TCC_OPTION_shared, 0 },
9658 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9659 { "run", TCC_OPTION_run, 0 },
9660 { "rdynamic", TCC_OPTION_rdynamic, 0 },
9661 { "r", TCC_OPTION_r, 0 },
9662 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9663 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9664 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9665 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9666 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9667 { "nostdlib", TCC_OPTION_nostdlib, 0 },
9668 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9669 { "v", TCC_OPTION_v, 0 },
9670 { NULL },
9673 int main(int argc, char **argv)
9675 char *r;
9676 int optind, output_type, multiple_files, i, reloc_output;
9677 TCCState *s;
9678 char **files;
9679 int nb_files, nb_libraries, nb_objfiles, dminus, ret;
9680 char objfilename[1024];
9681 int64_t start_time = 0;
9682 const TCCOption *popt;
9683 const char *optarg, *p1, *r1, *outfile;
9684 int print_search_dirs;
9686 s = tcc_new();
9687 output_type = TCC_OUTPUT_EXE;
9689 optind = 1;
9690 outfile = NULL;
9691 multiple_files = 1;
9692 dminus = 0;
9693 files = NULL;
9694 nb_files = 0;
9695 nb_libraries = 0;
9696 reloc_output = 0;
9697 print_search_dirs = 0;
9698 while (1) {
9699 if (optind >= argc) {
9700 if (nb_files == 0 && !print_search_dirs)
9701 goto show_help;
9702 else
9703 break;
9705 r = argv[optind++];
9706 if (r[0] != '-') {
9707 /* add a new file */
9708 dynarray_add((void ***)&files, &nb_files, r);
9709 if (!multiple_files) {
9710 optind--;
9711 /* argv[0] will be this file */
9712 break;
9714 } else {
9715 /* find option in table (match only the first chars */
9716 popt = tcc_options;
9717 for(;;) {
9718 p1 = popt->name;
9719 if (p1 == NULL)
9720 error("invalid option -- '%s'", r);
9721 r1 = r + 1;
9722 for(;;) {
9723 if (*p1 == '\0')
9724 goto option_found;
9725 if (*r1 != *p1)
9726 break;
9727 p1++;
9728 r1++;
9730 popt++;
9732 option_found:
9733 if (popt->flags & TCC_OPTION_HAS_ARG) {
9734 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
9735 optarg = r1;
9736 } else {
9737 if (optind >= argc)
9738 error("argument to '%s' is missing", r);
9739 optarg = argv[optind++];
9741 } else {
9742 if (*r1 != '\0')
9743 goto show_help;
9744 optarg = NULL;
9747 switch(popt->index) {
9748 case TCC_OPTION_HELP:
9749 show_help:
9750 help();
9751 return 1;
9752 case TCC_OPTION_I:
9753 if (tcc_add_include_path(s, optarg) < 0)
9754 error("too many include paths");
9755 break;
9756 case TCC_OPTION_D:
9758 char *sym, *value;
9759 sym = (char *)optarg;
9760 value = strchr(sym, '=');
9761 if (value) {
9762 *value = '\0';
9763 value++;
9765 tcc_define_symbol(s, sym, value);
9767 break;
9768 case TCC_OPTION_U:
9769 tcc_undefine_symbol(s, optarg);
9770 break;
9771 case TCC_OPTION_L:
9772 tcc_add_library_path(s, optarg);
9773 break;
9774 case TCC_OPTION_B:
9775 /* set tcc utilities path (mainly for tcc development) */
9776 tcc_lib_path = optarg;
9777 break;
9778 case TCC_OPTION_l:
9779 dynarray_add((void ***)&files, &nb_files, r);
9780 nb_libraries++;
9781 break;
9782 case TCC_OPTION_bench:
9783 do_bench = 1;
9784 break;
9785 case TCC_OPTION_bt:
9786 num_callers = atoi(optarg);
9787 break;
9788 #ifdef CONFIG_TCC_BCHECK
9789 case TCC_OPTION_b:
9790 do_bounds_check = 1;
9791 do_debug = 1;
9792 break;
9793 #endif
9794 case TCC_OPTION_g:
9795 do_debug = 1;
9796 break;
9797 case TCC_OPTION_c:
9798 multiple_files = 1;
9799 output_type = TCC_OUTPUT_OBJ;
9800 break;
9801 case TCC_OPTION_static:
9802 s->static_link = 1;
9803 break;
9804 case TCC_OPTION_shared:
9805 output_type = TCC_OUTPUT_DLL;
9806 break;
9807 case TCC_OPTION_o:
9808 multiple_files = 1;
9809 outfile = optarg;
9810 break;
9811 case TCC_OPTION_r:
9812 /* generate a .o merging several output files */
9813 reloc_output = 1;
9814 output_type = TCC_OUTPUT_OBJ;
9815 break;
9816 case TCC_OPTION_nostdinc:
9817 s->nostdinc = 1;
9818 break;
9819 case TCC_OPTION_nostdlib:
9820 s->nostdlib = 1;
9821 break;
9822 case TCC_OPTION_print_search_dirs:
9823 print_search_dirs = 1;
9824 break;
9825 case TCC_OPTION_run:
9826 multiple_files = 0;
9827 output_type = TCC_OUTPUT_MEMORY;
9828 break;
9829 case TCC_OPTION_v:
9830 printf("tcc version %s\n", TCC_VERSION);
9831 return 0;
9832 case TCC_OPTION_W:
9834 const char *p = optarg;
9835 int value;
9836 value = 1;
9837 if (p[0] == 'n' && p[1] == 'o' && p[2] == '-') {
9838 p += 2;
9839 value = 0;
9841 if (tcc_set_warning(s, p, value) < 0 && s->warn_unsupported)
9842 goto unsupported_option;
9844 break;
9845 case TCC_OPTION_rdynamic:
9846 s->rdynamic = 1;
9847 break;
9848 default:
9849 if (s->warn_unsupported) {
9850 unsupported_option:
9851 warning("unsupported option '%s'", r);
9853 break;
9857 if (print_search_dirs) {
9858 /* enough for Linux kernel */
9859 printf("install: %s/\n", tcc_lib_path);
9860 return 0;
9863 nb_objfiles = nb_files - nb_libraries;
9865 /* if outfile provided without other options, we output an
9866 executable */
9867 if (outfile && output_type == TCC_OUTPUT_MEMORY)
9868 output_type = TCC_OUTPUT_EXE;
9870 /* check -c consistency : only single file handled. XXX: checks file type */
9871 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9872 /* accepts only a single input file */
9873 if (nb_objfiles != 1)
9874 error("cannot specify multiple files with -c");
9875 if (nb_libraries != 0)
9876 error("cannot specify libraries with -c");
9879 /* compute default outfile name */
9880 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
9881 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9882 char *ext;
9883 /* strip path */
9884 pstrcpy(objfilename, sizeof(objfilename) - 1,
9885 tcc_basename(files[0]));
9886 /* add .o extension */
9887 ext = strrchr(objfilename, '.');
9888 if (!ext)
9889 goto default_outfile;
9890 strcpy(ext + 1, "o");
9891 } else {
9892 default_outfile:
9893 pstrcpy(objfilename, sizeof(objfilename), "a.out");
9895 outfile = objfilename;
9898 if (do_bench) {
9899 start_time = getclock_us();
9902 tcc_set_output_type(s, output_type);
9904 /* compile or add each files or library */
9905 for(i = 0;i < nb_files; i++) {
9906 const char *filename;
9908 filename = files[i];
9909 if (filename[0] == '-') {
9910 if (tcc_add_library(s, filename + 2) < 0)
9911 error("cannot find %s", filename);
9912 } else {
9913 if (tcc_add_file(s, filename) < 0) {
9914 ret = 1;
9915 goto the_end;
9920 /* free all files */
9921 tcc_free(files);
9923 if (do_bench) {
9924 double total_time;
9925 total_time = (double)(getclock_us() - start_time) / 1000000.0;
9926 if (total_time < 0.001)
9927 total_time = 0.001;
9928 if (total_bytes < 1)
9929 total_bytes = 1;
9930 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
9931 tok_ident - TOK_IDENT, total_lines, total_bytes,
9932 total_time, (int)(total_lines / total_time),
9933 total_bytes / total_time / 1000000.0);
9936 if (s->output_type != TCC_OUTPUT_MEMORY) {
9937 tcc_output_file(s, outfile);
9938 ret = 0;
9939 } else {
9940 ret = tcc_run(s, argc - optind, argv + optind);
9942 the_end:
9943 /* XXX: cannot do it with bound checking because of the malloc hooks */
9944 if (!do_bounds_check)
9945 tcc_delete(s);
9947 #ifdef MEM_DEBUG
9948 if (do_bench) {
9949 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
9951 #endif
9952 return ret;
9955 #endif