update
[tinycc.git] / tcc.c
blob145b6f489b376b99df75afbe351b4e2477072386
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 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 #ifdef CONFIG_TCCBOOT
25 #include "tccboot.h"
26 #define CONFIG_TCC_STATIC
28 #else
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <math.h>
36 #include <unistd.h>
37 #include <signal.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 #include <setjmp.h>
41 #include <time.h>
42 #ifdef WIN32
43 #include <sys/timeb.h>
44 #define CONFIG_TCC_STATIC
45 #endif
46 #ifndef WIN32
47 #include <sys/time.h>
48 #include <sys/ucontext.h>
49 #endif
51 #endif /* !CONFIG_TCCBOOT */
53 #include "elf.h"
54 #include "stab.h"
55 #ifndef CONFIG_TCC_STATIC
56 #include <dlfcn.h>
57 #endif
58 #ifndef O_BINARY
59 #define O_BINARY 0
60 #endif
62 #include "libtcc.h"
64 /* parser debug */
65 //#define PARSE_DEBUG
66 /* preprocessor debug */
67 //#define PP_DEBUG
68 /* include file debug */
69 //#define INC_DEBUG
71 //#define MEM_DEBUG
73 /* assembler debug */
74 //#define ASM_DEBUG
76 /* target selection */
77 //#define TCC_TARGET_I386 /* i386 code generator */
78 //#define TCC_TARGET_ARM /* ARMv4 code generator */
79 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
81 /* default target is I386 */
82 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
83 !defined(TCC_TARGET_C67)
84 #define TCC_TARGET_I386
85 #endif
87 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
88 !defined(TCC_TARGET_C67)
89 #define CONFIG_TCC_BCHECK /* enable bound checking code */
90 #endif
92 /* define it to include assembler support */
93 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
94 #define CONFIG_TCC_ASM
95 #endif
97 /* object format selection */
98 #if defined(TCC_TARGET_C67)
99 #define TCC_TARGET_COFF
100 #endif
102 #define FALSE 0
103 #define false 0
104 #define TRUE 1
105 #define true 1
106 typedef int BOOL;
108 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
109 executables or dlls */
110 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
112 #define INCLUDE_STACK_SIZE 32
113 #define IFDEF_STACK_SIZE 64
114 #define VSTACK_SIZE 256
115 #define STRING_MAX_SIZE 1024
117 #define TOK_HASH_SIZE 8192 /* must be a power of two */
118 #define TOK_ALLOC_INCR 512 /* must be a power of two */
119 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
121 /* token symbol management */
122 typedef struct TokenSym {
123 struct TokenSym *hash_next;
124 struct Sym *sym_define; /* direct pointer to define */
125 struct Sym *sym_label; /* direct pointer to label */
126 struct Sym *sym_struct; /* direct pointer to structure */
127 struct Sym *sym_identifier; /* direct pointer to identifier */
128 int tok; /* token number */
129 int len;
130 char str[1];
131 } TokenSym;
133 typedef struct CString {
134 int size; /* size in bytes */
135 void *data; /* either 'char *' or 'int *' */
136 int size_allocated;
137 void *data_allocated; /* if non NULL, data has been malloced */
138 } CString;
140 /* type definition */
141 typedef struct CType {
142 int t;
143 struct Sym *ref;
144 } CType;
146 /* constant value */
147 typedef union CValue {
148 long double ld;
149 double d;
150 float f;
151 int i;
152 unsigned int ui;
153 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
154 long long ll;
155 unsigned long long ull;
156 struct CString *cstr;
157 void *ptr;
158 int tab[1];
159 } CValue;
161 /* value on stack */
162 typedef struct SValue {
163 CType type; /* type */
164 unsigned short r; /* register + flags */
165 unsigned short r2; /* second register, used for 'long long'
166 type. If not used, set to VT_CONST */
167 CValue c; /* constant, if VT_CONST */
168 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
169 } SValue;
171 /* symbol management */
172 typedef struct Sym {
173 int v; /* symbol token */
174 int r; /* associated register */
175 int c; /* associated number */
176 CType type; /* associated type */
177 struct Sym *next; /* next related symbol */
178 struct Sym *prev; /* prev symbol in stack */
179 struct Sym *prev_tok; /* previous symbol for this token */
180 } Sym;
182 /* section definition */
183 /* XXX: use directly ELF structure for parameters ? */
184 /* special flag to indicate that the section should not be linked to
185 the other ones */
186 #define SHF_PRIVATE 0x80000000
188 typedef struct Section {
189 unsigned long data_offset; /* current data offset */
190 unsigned char *data; /* section data */
191 unsigned long data_allocated; /* used for realloc() handling */
192 int sh_name; /* elf section name (only used during output) */
193 int sh_num; /* elf section number */
194 int sh_type; /* elf section type */
195 int sh_flags; /* elf section flags */
196 int sh_info; /* elf section info */
197 int sh_addralign; /* elf section alignment */
198 int sh_entsize; /* elf entry size */
199 unsigned long sh_size; /* section size (only used during output) */
200 unsigned long sh_addr; /* address at which the section is relocated */
201 unsigned long sh_offset; /* address at which the section is relocated */
202 int nb_hashed_syms; /* used to resize the hash table */
203 struct Section *link; /* link to another section */
204 struct Section *reloc; /* corresponding section for relocation, if any */
205 struct Section *hash; /* hash table for symbols */
206 struct Section *next;
207 char name[1]; /* section name */
208 } Section;
210 typedef struct DLLReference {
211 int level;
212 char name[1];
213 } DLLReference;
215 /* GNUC attribute definition */
216 typedef struct AttributeDef {
217 int aligned;
218 int packed;
219 Section *section;
220 unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
221 } AttributeDef;
223 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
224 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
225 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
227 /* stored in 'Sym.c' field */
228 #define FUNC_NEW 1 /* ansi function prototype */
229 #define FUNC_OLD 2 /* old function prototype */
230 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
232 /* stored in 'Sym.r' field */
233 #define FUNC_CDECL 0 /* standard c call */
234 #define FUNC_STDCALL 1 /* pascal c call */
235 #define FUNC_FASTCALL1 2 /* first param in %eax */
236 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
237 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
239 /* field 'Sym.t' for macros */
240 #define MACRO_OBJ 0 /* object like macro */
241 #define MACRO_FUNC 1 /* function like macro */
243 /* field 'Sym.r' for C labels */
244 #define LABEL_DEFINED 0 /* label is defined */
245 #define LABEL_FORWARD 1 /* label is forward defined */
246 #define LABEL_DECLARED 2 /* label is declared but never used */
248 /* type_decl() types */
249 #define TYPE_ABSTRACT 1 /* type without variable */
250 #define TYPE_DIRECT 2 /* type with variable */
252 #define IO_BUF_SIZE 8192
254 typedef struct BufferedFile {
255 uint8_t *buf_ptr;
256 uint8_t *buf_end;
257 int fd;
258 int line_num; /* current line number - here to simplify code */
259 int ifndef_macro; /* #ifndef macro / #endif search */
260 int ifndef_macro_saved; /* saved ifndef_macro */
261 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
262 char inc_type; /* type of include */
263 char inc_filename[512]; /* filename specified by the user */
264 char filename[1024]; /* current filename - here to simplify code */
265 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
266 } BufferedFile;
268 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
269 #define CH_EOF (-1) /* end of file */
271 /* parsing state (used to save parser state to reparse part of the
272 source several times) */
273 typedef struct ParseState {
274 int *macro_ptr;
275 int line_num;
276 int tok;
277 CValue tokc;
278 } ParseState;
280 /* used to record tokens */
281 typedef struct TokenString {
282 int *str;
283 int len;
284 int allocated_len;
285 int last_line_num;
286 } TokenString;
288 /* include file cache, used to find files faster and also to eliminate
289 inclusion if the include file is protected by #ifndef ... #endif */
290 typedef struct CachedInclude {
291 int ifndef_macro;
292 int hash_next; /* -1 if none */
293 char type; /* '"' or '>' to give include type */
294 char filename[1]; /* path specified in #include */
295 } CachedInclude;
297 #define CACHED_INCLUDES_HASH_SIZE 512
299 /* parser */
300 static struct BufferedFile *file;
301 static int ch, tok;
302 static CValue tokc;
303 static CString tokcstr; /* current parsed string, if any */
304 /* additional informations about token */
305 static int tok_flags;
306 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
307 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
308 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
310 static int *macro_ptr, *macro_ptr_allocated;
311 static int *unget_saved_macro_ptr;
312 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
313 static int unget_buffer_enabled;
314 static int parse_flags;
315 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
316 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
317 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
318 token. line feed is also
319 returned at eof */
320 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
322 static Section *text_section, *data_section, *bss_section; /* predefined sections */
323 static Section *cur_text_section; /* current section where function code is
324 generated */
325 #ifdef CONFIG_TCC_ASM
326 static Section *last_text_section; /* to handle .previous asm directive */
327 #endif
328 /* bound check related sections */
329 static Section *bounds_section; /* contains global data bound description */
330 static Section *lbounds_section; /* contains local data bound description */
331 /* symbol sections */
332 static Section *symtab_section, *strtab_section;
334 /* debug sections */
335 static Section *stab_section, *stabstr_section;
337 /* loc : local variable index
338 ind : output code index
339 rsym: return symbol
340 anon_sym: anonymous symbol index
342 static int rsym, anon_sym, ind, loc;
343 /* expression generation modifiers */
344 static int const_wanted; /* true if constant wanted */
345 static int nocode_wanted; /* true if no code generation wanted for an expression */
346 static int global_expr; /* true if compound literals must be allocated
347 globally (used during initializers parsing */
348 static CType func_vt; /* current function return type (used by return
349 instruction) */
350 static int func_vc;
351 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
352 static int tok_ident;
353 static TokenSym **table_ident;
354 static TokenSym *hash_ident[TOK_HASH_SIZE];
355 static char token_buf[STRING_MAX_SIZE + 1];
356 static char *funcname;
357 static Sym *global_stack, *local_stack;
358 static Sym *define_stack;
359 static Sym *global_label_stack, *local_label_stack;
360 /* symbol allocator */
361 #define SYM_POOL_NB (8192 / sizeof(Sym))
362 static Sym *sym_free_first;
364 static SValue vstack[VSTACK_SIZE], *vtop;
365 /* some predefined types */
366 static CType char_pointer_type, func_old_type, int_type;
367 /* true if isid(c) || isnum(c) */
368 static unsigned char isidnum_table[256];
370 /* compile with debug symbol (and use them if error during execution) */
371 static int do_debug = 0;
373 /* compile with built-in memory and bounds checker */
374 static int do_bounds_check = 0;
376 /* display benchmark infos */
377 #if !defined(LIBTCC)
378 static int do_bench = 0;
379 #endif
380 static int total_lines;
381 static int total_bytes;
383 /* use GNU C extensions */
384 static int gnu_ext = 1;
386 /* use Tiny C extensions */
387 static int tcc_ext = 1;
389 /* max number of callers shown if error */
390 static int num_callers = 6;
391 static const char **rt_bound_error_msg;
393 /* XXX: get rid of this ASAP */
394 static struct TCCState *tcc_state;
396 /* give the path of the tcc libraries */
397 static const char *tcc_lib_path = CONFIG_TCC_LIBDIR "/tcc";
399 struct TCCState {
400 int output_type;
402 BufferedFile **include_stack_ptr;
403 int *ifdef_stack_ptr;
405 /* include file handling */
406 char **include_paths;
407 int nb_include_paths;
408 char **sysinclude_paths;
409 int nb_sysinclude_paths;
410 CachedInclude **cached_includes;
411 int nb_cached_includes;
413 char **library_paths;
414 int nb_library_paths;
416 /* array of all loaded dlls (including those referenced by loaded
417 dlls) */
418 DLLReference **loaded_dlls;
419 int nb_loaded_dlls;
421 /* sections */
422 Section **sections;
423 int nb_sections; /* number of sections, including first dummy section */
425 /* got handling */
426 Section *got;
427 Section *plt;
428 unsigned long *got_offsets;
429 int nb_got_offsets;
430 /* give the correspondance from symtab indexes to dynsym indexes */
431 int *symtab_to_dynsym;
433 /* temporary dynamic symbol sections (for dll loading) */
434 Section *dynsymtab_section;
435 /* exported dynamic symbol section */
436 Section *dynsym;
438 int nostdinc; /* if true, no standard headers are added */
439 int nostdlib; /* if true, no standard libraries are added */
441 int nocommon; /* if true, do not use common symbols for .bss data */
443 /* if true, static linking is performed */
444 int static_link;
446 /* if true, all symbols are exported */
447 int rdynamic;
449 /* if true, only link in referenced objects from archive */
450 int alacarte_link;
452 /* address of text section */
453 unsigned long text_addr;
454 int has_text_addr;
456 /* output format, see TCC_OUTPUT_FORMAT_xxx */
457 int output_format;
459 /* C language options */
460 int char_is_unsigned;
462 /* warning switches */
463 int warn_write_strings;
464 int warn_unsupported;
465 int warn_error;
466 int warn_none;
467 int warn_implicit_function_declaration;
469 /* error handling */
470 void *error_opaque;
471 void (*error_func)(void *opaque, const char *msg);
472 int error_set_jmp_enabled;
473 jmp_buf error_jmp_buf;
474 int nb_errors;
476 /* tiny assembler state */
477 Sym *asm_labels;
479 /* see include_stack_ptr */
480 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
482 /* see ifdef_stack_ptr */
483 int ifdef_stack[IFDEF_STACK_SIZE];
485 /* see cached_includes */
486 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
489 /* The current value can be: */
490 #define VT_VALMASK 0x00ff
491 #define VT_CONST 0x00f0 /* constant in vc
492 (must be first non register value) */
493 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
494 #define VT_LOCAL 0x00f2 /* offset on stack */
495 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
496 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
497 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
498 #define VT_LVAL 0x0100 /* var is an lvalue */
499 #define VT_SYM 0x0200 /* a symbol value is added */
500 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
501 char/short stored in integer registers) */
502 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
503 dereferencing value */
504 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
505 bounding function call point is in vc */
506 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
507 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
508 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
509 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
511 /* types */
512 #define VT_INT 0 /* integer type */
513 #define VT_BYTE 1 /* signed byte type */
514 #define VT_SHORT 2 /* short type */
515 #define VT_VOID 3 /* void type */
516 #define VT_PTR 4 /* pointer */
517 #define VT_ENUM 5 /* enum definition */
518 #define VT_FUNC 6 /* function type */
519 #define VT_STRUCT 7 /* struct/union definition */
520 #define VT_FLOAT 8 /* IEEE float */
521 #define VT_DOUBLE 9 /* IEEE double */
522 #define VT_LDOUBLE 10 /* IEEE long double */
523 #define VT_BOOL 11 /* ISOC99 boolean type */
524 #define VT_LLONG 12 /* 64 bit integer */
525 #define VT_LONG 13 /* long integer (NEVER USED as type, only
526 during parsing) */
527 #define VT_BTYPE 0x000f /* mask for basic type */
528 #define VT_UNSIGNED 0x0010 /* unsigned type */
529 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
530 #define VT_BITFIELD 0x0040 /* bitfield modifier */
531 #define VT_CONSTANT 0x0800 /* const modifier */
532 #define VT_VOLATILE 0x1000 /* volatile modifier */
533 #define VT_SIGNED 0x2000 /* signed type */
535 /* storage */
536 #define VT_EXTERN 0x00000080 /* extern definition */
537 #define VT_STATIC 0x00000100 /* static variable */
538 #define VT_TYPEDEF 0x00000200 /* typedef definition */
539 #define VT_INLINE 0x00000400 /* inline definition */
541 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
543 /* type mask (except storage) */
544 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
545 #define VT_TYPE (~(VT_STORAGE))
547 /* token values */
549 /* warning: the following compare tokens depend on i386 asm code */
550 #define TOK_ULT 0x92
551 #define TOK_UGE 0x93
552 #define TOK_EQ 0x94
553 #define TOK_NE 0x95
554 #define TOK_ULE 0x96
555 #define TOK_UGT 0x97
556 #define TOK_LT 0x9c
557 #define TOK_GE 0x9d
558 #define TOK_LE 0x9e
559 #define TOK_GT 0x9f
561 #define TOK_LAND 0xa0
562 #define TOK_LOR 0xa1
564 #define TOK_DEC 0xa2
565 #define TOK_MID 0xa3 /* inc/dec, to void constant */
566 #define TOK_INC 0xa4
567 #define TOK_UDIV 0xb0 /* unsigned division */
568 #define TOK_UMOD 0xb1 /* unsigned modulo */
569 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
570 #define TOK_CINT 0xb3 /* number in tokc */
571 #define TOK_CCHAR 0xb4 /* char constant in tokc */
572 #define TOK_STR 0xb5 /* pointer to string in tokc */
573 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
574 #define TOK_LCHAR 0xb7
575 #define TOK_LSTR 0xb8
576 #define TOK_CFLOAT 0xb9 /* float constant */
577 #define TOK_LINENUM 0xba /* line number info */
578 #define TOK_CDOUBLE 0xc0 /* double constant */
579 #define TOK_CLDOUBLE 0xc1 /* long double constant */
580 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
581 #define TOK_ADDC1 0xc3 /* add with carry generation */
582 #define TOK_ADDC2 0xc4 /* add with carry use */
583 #define TOK_SUBC1 0xc5 /* add with carry generation */
584 #define TOK_SUBC2 0xc6 /* add with carry use */
585 #define TOK_CUINT 0xc8 /* unsigned int constant */
586 #define TOK_CLLONG 0xc9 /* long long constant */
587 #define TOK_CULLONG 0xca /* unsigned long long constant */
588 #define TOK_ARROW 0xcb
589 #define TOK_DOTS 0xcc /* three dots */
590 #define TOK_SHR 0xcd /* unsigned shift right */
591 #define TOK_PPNUM 0xce /* preprocessor number */
593 #define TOK_SHL 0x01 /* shift left */
594 #define TOK_SAR 0x02 /* signed shift right */
596 /* assignement operators : normal operator or 0x80 */
597 #define TOK_A_MOD 0xa5
598 #define TOK_A_AND 0xa6
599 #define TOK_A_MUL 0xaa
600 #define TOK_A_ADD 0xab
601 #define TOK_A_SUB 0xad
602 #define TOK_A_DIV 0xaf
603 #define TOK_A_XOR 0xde
604 #define TOK_A_OR 0xfc
605 #define TOK_A_SHL 0x81
606 #define TOK_A_SAR 0x82
608 #ifndef offsetof
609 #define offsetof(type, field) ((size_t) &((type *)0)->field)
610 #endif
612 #ifndef countof
613 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
614 #endif
616 /* WARNING: the content of this string encodes token numbers */
617 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";
619 #define TOK_EOF (-1) /* end of file */
620 #define TOK_LINEFEED 10 /* line feed */
622 /* all identificators and strings have token above that */
623 #define TOK_IDENT 256
625 /* only used for i386 asm opcodes definitions */
626 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
628 #define DEF_BWL(x) \
629 DEF(TOK_ASM_ ## x ## b, #x "b") \
630 DEF(TOK_ASM_ ## x ## w, #x "w") \
631 DEF(TOK_ASM_ ## x ## l, #x "l") \
632 DEF(TOK_ASM_ ## x, #x)
634 #define DEF_WL(x) \
635 DEF(TOK_ASM_ ## x ## w, #x "w") \
636 DEF(TOK_ASM_ ## x ## l, #x "l") \
637 DEF(TOK_ASM_ ## x, #x)
639 #define DEF_FP1(x) \
640 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
641 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
642 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
643 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
645 #define DEF_FP(x) \
646 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
647 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
648 DEF_FP1(x)
650 #define DEF_ASMTEST(x) \
651 DEF_ASM(x ## o) \
652 DEF_ASM(x ## no) \
653 DEF_ASM(x ## b) \
654 DEF_ASM(x ## c) \
655 DEF_ASM(x ## nae) \
656 DEF_ASM(x ## nb) \
657 DEF_ASM(x ## nc) \
658 DEF_ASM(x ## ae) \
659 DEF_ASM(x ## e) \
660 DEF_ASM(x ## z) \
661 DEF_ASM(x ## ne) \
662 DEF_ASM(x ## nz) \
663 DEF_ASM(x ## be) \
664 DEF_ASM(x ## na) \
665 DEF_ASM(x ## nbe) \
666 DEF_ASM(x ## a) \
667 DEF_ASM(x ## s) \
668 DEF_ASM(x ## ns) \
669 DEF_ASM(x ## p) \
670 DEF_ASM(x ## pe) \
671 DEF_ASM(x ## np) \
672 DEF_ASM(x ## po) \
673 DEF_ASM(x ## l) \
674 DEF_ASM(x ## nge) \
675 DEF_ASM(x ## nl) \
676 DEF_ASM(x ## ge) \
677 DEF_ASM(x ## le) \
678 DEF_ASM(x ## ng) \
679 DEF_ASM(x ## nle) \
680 DEF_ASM(x ## g)
682 #define TOK_ASM_int TOK_INT
684 enum tcc_token {
685 TOK_LAST = TOK_IDENT - 1,
686 #define DEF(id, str) id,
687 #include "tcctok.h"
688 #undef DEF
691 static const char tcc_keywords[] =
692 #define DEF(id, str) str "\0"
693 #include "tcctok.h"
694 #undef DEF
697 #define TOK_UIDENT TOK_DEFINE
699 #ifdef WIN32
700 #define snprintf _snprintf
701 #define vsnprintf _vsnprintf
702 #endif
704 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
705 /* currently incorrect */
706 long double strtold(const char *nptr, char **endptr)
708 return (long double)strtod(nptr, endptr);
710 float strtof(const char *nptr, char **endptr)
712 return (float)strtod(nptr, endptr);
714 #else
715 /* XXX: need to define this to use them in non ISOC99 context */
716 extern float strtof (const char *__nptr, char **__endptr);
717 extern long double strtold (const char *__nptr, char **__endptr);
718 #endif
720 static char *pstrcpy(char *buf, int buf_size, const char *s);
721 static char *pstrcat(char *buf, int buf_size, const char *s);
723 static void next(void);
724 static void next_nomacro(void);
725 static void parse_expr_type(CType *type);
726 static void expr_type(CType *type);
727 static void unary_type(CType *type);
728 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
729 int case_reg, int is_expr);
730 static int expr_const(void);
731 static void expr_eq(void);
732 static void gexpr(void);
733 static void gen_inline_functions(void);
734 static void decl(int l);
735 static void decl_initializer(CType *type, Section *sec, unsigned long c,
736 int first, int size_only);
737 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
738 int has_init, int v, int scope);
739 int gv(int rc);
740 void gv2(int rc1, int rc2);
741 void move_reg(int r, int s);
742 void save_regs(int n);
743 void save_reg(int r);
744 void vpop(void);
745 void vswap(void);
746 void vdup(void);
747 int get_reg(int rc);
748 int get_reg_ex(int rc,int rc2);
750 static void macro_subst(TokenString *tok_str, Sym **nested_list,
751 const int *macro_str, int can_read_stream);
752 void gen_op(int op);
753 void force_charshort_cast(int t);
754 static void gen_cast(CType *type);
755 void vstore(void);
756 static Sym *sym_find(int v);
757 static Sym *sym_push(int v, CType *type, int r, int c);
759 /* type handling */
760 static int type_size(CType *type, int *a);
761 static inline CType *pointed_type(CType *type);
762 static int pointed_size(CType *type);
763 static int lvalue_type(int t);
764 static int parse_btype(CType *type, AttributeDef *ad);
765 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
766 static int is_compatible_types(CType *type1, CType *type2);
768 int ieee_finite(double d);
769 void error(const char *fmt, ...);
770 void vpushi(int v);
771 void vrott(int n);
772 void vnrott(int n);
773 void lexpand_nr(void);
774 static void vpush_global_sym(CType *type, int v);
775 void vset(CType *type, int r, int v);
776 void type_to_str(char *buf, int buf_size,
777 CType *type, const char *varstr);
778 char *get_tok_str(int v, CValue *cv);
779 static Sym *get_sym_ref(CType *type, Section *sec,
780 unsigned long offset, unsigned long size);
781 static Sym *external_global_sym(int v, CType *type, int r);
783 /* section generation */
784 static void section_realloc(Section *sec, unsigned long new_size);
785 static void *section_ptr_add(Section *sec, unsigned long size);
786 static void put_extern_sym(Sym *sym, Section *section,
787 unsigned long value, unsigned long size);
788 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
789 static int put_elf_str(Section *s, const char *sym);
790 static int put_elf_sym(Section *s,
791 unsigned long value, unsigned long size,
792 int info, int other, int shndx, const char *name);
793 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
794 int info, int sh_num, const char *name);
795 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
796 int type, int symbol);
797 static void put_stabs(const char *str, int type, int other, int desc,
798 unsigned long value);
799 static void put_stabs_r(const char *str, int type, int other, int desc,
800 unsigned long value, Section *sec, int sym_index);
801 static void put_stabn(int type, int other, int desc, int value);
802 static void put_stabd(int type, int other, int desc);
803 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
805 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
806 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
807 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
809 /* tcccoff.c */
810 int tcc_output_coff(TCCState *s1, FILE *f);
812 /* tccasm.c */
814 #ifdef CONFIG_TCC_ASM
816 typedef struct ExprValue {
817 uint32_t v;
818 Sym *sym;
819 } ExprValue;
821 #define MAX_ASM_OPERANDS 30
823 typedef struct ASMOperand {
824 int id; /* GCC 3 optionnal identifier (0 if number only supported */
825 char *constraint;
826 char asm_str[16]; /* computed asm string for operand */
827 SValue *vt; /* C value of the expression */
828 int ref_index; /* if >= 0, gives reference to a output constraint */
829 int input_index; /* if >= 0, gives reference to an input constraint */
830 int priority; /* priority, used to assign registers */
831 int reg; /* if >= 0, register number used for this operand */
832 int is_llong; /* true if double register value */
833 int is_memory; /* true if memory operand */
834 int is_rw; /* for '+' modifier */
835 } ASMOperand;
837 static void asm_expr(TCCState *s1, ExprValue *pe);
838 static int asm_int_expr(TCCState *s1);
839 static int find_constraint(ASMOperand *operands, int nb_operands,
840 const char *name, const char **pp);
842 static int tcc_assemble(TCCState *s1, int do_preprocess);
844 #endif
846 static void asm_instr(void);
847 static void asm_global_instr(void);
849 /* true if float/double/long double type */
850 static inline int is_float(int t)
852 int bt;
853 bt = t & VT_BTYPE;
854 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
857 #ifdef TCC_TARGET_I386
858 #include "i386-gen.c"
859 #endif
861 #ifdef TCC_TARGET_ARM
862 #include "arm-gen.c"
863 #endif
865 #ifdef TCC_TARGET_C67
866 #include "c67-gen.c"
867 #endif
869 #ifdef CONFIG_TCC_STATIC
871 #define RTLD_LAZY 0x001
872 #define RTLD_NOW 0x002
873 #define RTLD_GLOBAL 0x100
874 #define RTLD_DEFAULT NULL
876 /* dummy function for profiling */
877 void *dlopen(const char *filename, int flag)
879 return NULL;
882 const char *dlerror(void)
884 return "error";
887 typedef struct TCCSyms {
888 char *str;
889 void *ptr;
890 } TCCSyms;
892 #define TCCSYM(a) { #a, &a, },
894 /* add the symbol you want here if no dynamic linking is done */
895 static TCCSyms tcc_syms[] = {
896 #if !defined(CONFIG_TCCBOOT)
897 TCCSYM(printf)
898 TCCSYM(fprintf)
899 TCCSYM(fopen)
900 TCCSYM(fclose)
901 #endif
902 { NULL, NULL },
905 void *dlsym(void *handle, const char *symbol)
907 TCCSyms *p;
908 p = tcc_syms;
909 while (p->str != NULL) {
910 if (!strcmp(p->str, symbol))
911 return p->ptr;
912 p++;
914 return NULL;
917 #endif
919 /********************************************************/
921 /* we use our own 'finite' function to avoid potential problems with
922 non standard math libs */
923 /* XXX: endianness dependent */
924 int ieee_finite(double d)
926 int *p = (int *)&d;
927 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
930 /* copy a string and truncate it. */
931 static char *pstrcpy(char *buf, int buf_size, const char *s)
933 char *q, *q_end;
934 int c;
936 if (buf_size > 0) {
937 q = buf;
938 q_end = buf + buf_size - 1;
939 while (q < q_end) {
940 c = *s++;
941 if (c == '\0')
942 break;
943 *q++ = c;
945 *q = '\0';
947 return buf;
950 /* strcat and truncate. */
951 static char *pstrcat(char *buf, int buf_size, const char *s)
953 int len;
954 len = strlen(buf);
955 if (len < buf_size)
956 pstrcpy(buf + len, buf_size - len, s);
957 return buf;
960 static int strstart(const char *str, const char *val, const char **ptr)
962 const char *p, *q;
963 p = str;
964 q = val;
965 while (*q != '\0') {
966 if (*p != *q)
967 return 0;
968 p++;
969 q++;
971 if (ptr)
972 *ptr = p;
973 return 1;
976 /* memory management */
977 #ifdef MEM_DEBUG
978 int mem_cur_size;
979 int mem_max_size;
980 #endif
982 static inline void tcc_free(void *ptr)
984 #ifdef MEM_DEBUG
985 mem_cur_size -= malloc_usable_size(ptr);
986 #endif
987 free(ptr);
990 static void *tcc_malloc(unsigned long size)
992 void *ptr;
993 ptr = malloc(size);
994 if (!ptr && size)
995 error("memory full");
996 #ifdef MEM_DEBUG
997 mem_cur_size += malloc_usable_size(ptr);
998 if (mem_cur_size > mem_max_size)
999 mem_max_size = mem_cur_size;
1000 #endif
1001 return ptr;
1004 static void *tcc_mallocz(unsigned long size)
1006 void *ptr;
1007 ptr = tcc_malloc(size);
1008 memset(ptr, 0, size);
1009 return ptr;
1012 static inline void *tcc_realloc(void *ptr, unsigned long size)
1014 void *ptr1;
1015 #ifdef MEM_DEBUG
1016 mem_cur_size -= malloc_usable_size(ptr);
1017 #endif
1018 ptr1 = realloc(ptr, size);
1019 #ifdef MEM_DEBUG
1020 /* NOTE: count not correct if alloc error, but not critical */
1021 mem_cur_size += malloc_usable_size(ptr1);
1022 if (mem_cur_size > mem_max_size)
1023 mem_max_size = mem_cur_size;
1024 #endif
1025 return ptr1;
1028 static char *tcc_strdup(const char *str)
1030 char *ptr;
1031 ptr = tcc_malloc(strlen(str) + 1);
1032 strcpy(ptr, str);
1033 return ptr;
1036 #define free(p) use_tcc_free(p)
1037 #define malloc(s) use_tcc_malloc(s)
1038 #define realloc(p, s) use_tcc_realloc(p, s)
1040 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1042 int nb, nb_alloc;
1043 void **pp;
1045 nb = *nb_ptr;
1046 pp = *ptab;
1047 /* every power of two we double array size */
1048 if ((nb & (nb - 1)) == 0) {
1049 if (!nb)
1050 nb_alloc = 1;
1051 else
1052 nb_alloc = nb * 2;
1053 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1054 if (!pp)
1055 error("memory full");
1056 *ptab = pp;
1058 pp[nb++] = data;
1059 *nb_ptr = nb;
1062 /* symbol allocator */
1063 static Sym *__sym_malloc(void)
1065 Sym *sym_pool, *sym, *last_sym;
1066 int i;
1068 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1070 last_sym = sym_free_first;
1071 sym = sym_pool;
1072 for(i = 0; i < SYM_POOL_NB; i++) {
1073 sym->next = last_sym;
1074 last_sym = sym;
1075 sym++;
1077 sym_free_first = last_sym;
1078 return last_sym;
1081 static inline Sym *sym_malloc(void)
1083 Sym *sym;
1084 sym = sym_free_first;
1085 if (!sym)
1086 sym = __sym_malloc();
1087 sym_free_first = sym->next;
1088 return sym;
1091 static inline void sym_free(Sym *sym)
1093 sym->next = sym_free_first;
1094 sym_free_first = sym;
1097 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1099 Section *sec;
1101 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1102 strcpy(sec->name, name);
1103 sec->sh_type = sh_type;
1104 sec->sh_flags = sh_flags;
1105 switch(sh_type) {
1106 case SHT_HASH:
1107 case SHT_REL:
1108 case SHT_DYNSYM:
1109 case SHT_SYMTAB:
1110 case SHT_DYNAMIC:
1111 sec->sh_addralign = 4;
1112 break;
1113 case SHT_STRTAB:
1114 sec->sh_addralign = 1;
1115 break;
1116 default:
1117 sec->sh_addralign = 32; /* default conservative alignment */
1118 break;
1121 /* only add section if not private */
1122 if (!(sh_flags & SHF_PRIVATE)) {
1123 sec->sh_num = s1->nb_sections;
1124 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1126 return sec;
1129 static void free_section(Section *s)
1131 tcc_free(s->data);
1132 tcc_free(s);
1135 /* realloc section and set its content to zero */
1136 static void section_realloc(Section *sec, unsigned long new_size)
1138 unsigned long size;
1139 unsigned char *data;
1141 size = sec->data_allocated;
1142 if (size == 0)
1143 size = 1;
1144 while (size < new_size)
1145 size = size * 2;
1146 data = tcc_realloc(sec->data, size);
1147 if (!data)
1148 error("memory full");
1149 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1150 sec->data = data;
1151 sec->data_allocated = size;
1154 /* reserve at least 'size' bytes in section 'sec' from
1155 sec->data_offset. */
1156 static void *section_ptr_add(Section *sec, unsigned long size)
1158 unsigned long offset, offset1;
1160 offset = sec->data_offset;
1161 offset1 = offset + size;
1162 if (offset1 > sec->data_allocated)
1163 section_realloc(sec, offset1);
1164 sec->data_offset = offset1;
1165 return sec->data + offset;
1168 /* return a reference to a section, and create it if it does not
1169 exists */
1170 Section *find_section(TCCState *s1, const char *name)
1172 Section *sec;
1173 int i;
1174 for(i = 1; i < s1->nb_sections; i++) {
1175 sec = s1->sections[i];
1176 if (!strcmp(name, sec->name))
1177 return sec;
1179 /* sections are created as PROGBITS */
1180 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1183 #define SECTION_ABS ((void *)1)
1185 /* update sym->c so that it points to an external symbol in section
1186 'section' with value 'value' */
1187 static void put_extern_sym(Sym *sym, Section *section,
1188 unsigned long value, unsigned long size)
1190 int sym_type, sym_bind, sh_num, info;
1191 Elf32_Sym *esym;
1192 const char *name;
1194 if (section == NULL)
1195 sh_num = SHN_UNDEF;
1196 else if (section == SECTION_ABS)
1197 sh_num = SHN_ABS;
1198 else
1199 sh_num = section->sh_num;
1200 if (!sym->c) {
1201 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1202 sym_type = STT_FUNC;
1203 else
1204 sym_type = STT_OBJECT;
1205 if (sym->type.t & VT_STATIC)
1206 sym_bind = STB_LOCAL;
1207 else
1208 sym_bind = STB_GLOBAL;
1210 name = get_tok_str(sym->v, NULL);
1211 #ifdef CONFIG_TCC_BCHECK
1212 if (do_bounds_check) {
1213 char buf[32];
1215 /* XXX: avoid doing that for statics ? */
1216 /* if bound checking is activated, we change some function
1217 names by adding the "__bound" prefix */
1218 switch(sym->v) {
1219 #if 0
1220 /* XXX: we rely only on malloc hooks */
1221 case TOK_malloc:
1222 case TOK_free:
1223 case TOK_realloc:
1224 case TOK_memalign:
1225 case TOK_calloc:
1226 #endif
1227 case TOK_memcpy:
1228 case TOK_memmove:
1229 case TOK_memset:
1230 case TOK_strlen:
1231 case TOK_strcpy:
1232 strcpy(buf, "__bound_");
1233 strcat(buf, name);
1234 name = buf;
1235 break;
1238 #endif
1239 info = ELF32_ST_INFO(sym_bind, sym_type);
1240 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1241 } else {
1242 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1243 esym->st_value = value;
1244 esym->st_size = size;
1245 esym->st_shndx = sh_num;
1249 /* add a new relocation entry to symbol 'sym' in section 's' */
1250 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1252 if (!sym->c)
1253 put_extern_sym(sym, NULL, 0, 0);
1254 /* now we can add ELF relocation info */
1255 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1258 static inline int isid(int c)
1260 return (c >= 'a' && c <= 'z') ||
1261 (c >= 'A' && c <= 'Z') ||
1262 c == '_';
1265 static inline int isnum(int c)
1267 return c >= '0' && c <= '9';
1270 static inline int isoct(int c)
1272 return c >= '0' && c <= '7';
1275 static inline int toup(int c)
1277 if (c >= 'a' && c <= 'z')
1278 return c - 'a' + 'A';
1279 else
1280 return c;
1283 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1285 int len;
1286 len = strlen(buf);
1287 vsnprintf(buf + len, buf_size - len, fmt, ap);
1290 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1292 va_list ap;
1293 va_start(ap, fmt);
1294 strcat_vprintf(buf, buf_size, fmt, ap);
1295 va_end(ap);
1298 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1300 char buf[2048];
1301 BufferedFile **f;
1303 buf[0] = '\0';
1304 if (file) {
1305 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1306 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1307 (*f)->filename, (*f)->line_num);
1308 if (file->line_num > 0) {
1309 strcat_printf(buf, sizeof(buf),
1310 "%s:%d: ", file->filename, file->line_num);
1311 } else {
1312 strcat_printf(buf, sizeof(buf),
1313 "%s: ", file->filename);
1315 } else {
1316 strcat_printf(buf, sizeof(buf),
1317 "tcc: ");
1319 if (is_warning)
1320 strcat_printf(buf, sizeof(buf), "warning: ");
1321 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1323 if (!s1->error_func) {
1324 /* default case: stderr */
1325 fprintf(stderr, "%s\n", buf);
1326 } else {
1327 s1->error_func(s1->error_opaque, buf);
1329 if (!is_warning || s1->warn_error)
1330 s1->nb_errors++;
1333 #ifdef LIBTCC
1334 void tcc_set_error_func(TCCState *s, void *error_opaque,
1335 void (*error_func)(void *opaque, const char *msg))
1337 s->error_opaque = error_opaque;
1338 s->error_func = error_func;
1340 #endif
1342 /* error without aborting current compilation */
1343 void error_noabort(const char *fmt, ...)
1345 TCCState *s1 = tcc_state;
1346 va_list ap;
1348 va_start(ap, fmt);
1349 error1(s1, 0, fmt, ap);
1350 va_end(ap);
1353 void error(const char *fmt, ...)
1355 TCCState *s1 = tcc_state;
1356 va_list ap;
1358 va_start(ap, fmt);
1359 error1(s1, 0, fmt, ap);
1360 va_end(ap);
1361 /* better than nothing: in some cases, we accept to handle errors */
1362 if (s1->error_set_jmp_enabled) {
1363 longjmp(s1->error_jmp_buf, 1);
1364 } else {
1365 /* XXX: eliminate this someday */
1366 exit(1);
1370 void expect(const char *msg)
1372 error("%s expected", msg);
1375 void warning(const char *fmt, ...)
1377 TCCState *s1 = tcc_state;
1378 va_list ap;
1380 if (s1->warn_none)
1381 return;
1383 va_start(ap, fmt);
1384 error1(s1, 1, fmt, ap);
1385 va_end(ap);
1388 void skip(int c)
1390 if (tok != c)
1391 error("'%c' expected", c);
1392 next();
1395 static void test_lvalue(void)
1397 if (!(vtop->r & VT_LVAL))
1398 expect("lvalue");
1401 /* allocate a new token */
1402 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1404 TokenSym *ts, **ptable;
1405 int i;
1407 if (tok_ident >= SYM_FIRST_ANOM)
1408 error("memory full");
1410 /* expand token table if needed */
1411 i = tok_ident - TOK_IDENT;
1412 if ((i % TOK_ALLOC_INCR) == 0) {
1413 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1414 if (!ptable)
1415 error("memory full");
1416 table_ident = ptable;
1419 ts = tcc_malloc(sizeof(TokenSym) + len);
1420 table_ident[i] = ts;
1421 ts->tok = tok_ident++;
1422 ts->sym_define = NULL;
1423 ts->sym_label = NULL;
1424 ts->sym_struct = NULL;
1425 ts->sym_identifier = NULL;
1426 ts->len = len;
1427 ts->hash_next = NULL;
1428 memcpy(ts->str, str, len);
1429 ts->str[len] = '\0';
1430 *pts = ts;
1431 return ts;
1434 #define TOK_HASH_INIT 1
1435 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1437 /* find a token and add it if not found */
1438 static TokenSym *tok_alloc(const char *str, int len)
1440 TokenSym *ts, **pts;
1441 int i;
1442 unsigned int h;
1444 h = TOK_HASH_INIT;
1445 for(i=0;i<len;i++)
1446 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1447 h &= (TOK_HASH_SIZE - 1);
1449 pts = &hash_ident[h];
1450 for(;;) {
1451 ts = *pts;
1452 if (!ts)
1453 break;
1454 if (ts->len == len && !memcmp(ts->str, str, len))
1455 return ts;
1456 pts = &(ts->hash_next);
1458 return tok_alloc_new(pts, str, len);
1461 /* CString handling */
1463 static void cstr_realloc(CString *cstr, int new_size)
1465 int size;
1466 void *data;
1468 size = cstr->size_allocated;
1469 if (size == 0)
1470 size = 8; /* no need to allocate a too small first string */
1471 while (size < new_size)
1472 size = size * 2;
1473 data = tcc_realloc(cstr->data_allocated, size);
1474 if (!data)
1475 error("memory full");
1476 cstr->data_allocated = data;
1477 cstr->size_allocated = size;
1478 cstr->data = data;
1481 /* add a byte */
1482 static inline void cstr_ccat(CString *cstr, int ch)
1484 int size;
1485 size = cstr->size + 1;
1486 if (size > cstr->size_allocated)
1487 cstr_realloc(cstr, size);
1488 ((unsigned char *)cstr->data)[size - 1] = ch;
1489 cstr->size = size;
1492 static void cstr_cat(CString *cstr, const char *str)
1494 int c;
1495 for(;;) {
1496 c = *str;
1497 if (c == '\0')
1498 break;
1499 cstr_ccat(cstr, c);
1500 str++;
1504 /* add a wide char */
1505 static void cstr_wccat(CString *cstr, int ch)
1507 int size;
1508 size = cstr->size + sizeof(int);
1509 if (size > cstr->size_allocated)
1510 cstr_realloc(cstr, size);
1511 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1512 cstr->size = size;
1515 static void cstr_new(CString *cstr)
1517 memset(cstr, 0, sizeof(CString));
1520 /* free string and reset it to NULL */
1521 static void cstr_free(CString *cstr)
1523 tcc_free(cstr->data_allocated);
1524 cstr_new(cstr);
1527 #define cstr_reset(cstr) cstr_free(cstr)
1529 /* XXX: unicode ? */
1530 static void add_char(CString *cstr, int c)
1532 if (c == '\'' || c == '\"' || c == '\\') {
1533 /* XXX: could be more precise if char or string */
1534 cstr_ccat(cstr, '\\');
1536 if (c >= 32 && c <= 126) {
1537 cstr_ccat(cstr, c);
1538 } else {
1539 cstr_ccat(cstr, '\\');
1540 if (c == '\n') {
1541 cstr_ccat(cstr, 'n');
1542 } else {
1543 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1544 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1545 cstr_ccat(cstr, '0' + (c & 7));
1550 /* XXX: buffer overflow */
1551 /* XXX: float tokens */
1552 char *get_tok_str(int v, CValue *cv)
1554 static char buf[STRING_MAX_SIZE + 1];
1555 static CString cstr_buf;
1556 CString *cstr;
1557 unsigned char *q;
1558 char *p;
1559 int i, len;
1561 /* NOTE: to go faster, we give a fixed buffer for small strings */
1562 cstr_reset(&cstr_buf);
1563 cstr_buf.data = buf;
1564 cstr_buf.size_allocated = sizeof(buf);
1565 p = buf;
1567 switch(v) {
1568 case TOK_CINT:
1569 case TOK_CUINT:
1570 /* XXX: not quite exact, but only useful for testing */
1571 sprintf(p, "%u", cv->ui);
1572 break;
1573 case TOK_CLLONG:
1574 case TOK_CULLONG:
1575 /* XXX: not quite exact, but only useful for testing */
1576 sprintf(p, "%Lu", cv->ull);
1577 break;
1578 case TOK_CCHAR:
1579 case TOK_LCHAR:
1580 cstr_ccat(&cstr_buf, '\'');
1581 add_char(&cstr_buf, cv->i);
1582 cstr_ccat(&cstr_buf, '\'');
1583 cstr_ccat(&cstr_buf, '\0');
1584 break;
1585 case TOK_PPNUM:
1586 cstr = cv->cstr;
1587 len = cstr->size - 1;
1588 for(i=0;i<len;i++)
1589 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1590 cstr_ccat(&cstr_buf, '\0');
1591 break;
1592 case TOK_STR:
1593 case TOK_LSTR:
1594 cstr = cv->cstr;
1595 cstr_ccat(&cstr_buf, '\"');
1596 if (v == TOK_STR) {
1597 len = cstr->size - 1;
1598 for(i=0;i<len;i++)
1599 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1600 } else {
1601 len = (cstr->size / sizeof(int)) - 1;
1602 for(i=0;i<len;i++)
1603 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1605 cstr_ccat(&cstr_buf, '\"');
1606 cstr_ccat(&cstr_buf, '\0');
1607 break;
1608 case TOK_LT:
1609 v = '<';
1610 goto addv;
1611 case TOK_GT:
1612 v = '>';
1613 goto addv;
1614 case TOK_A_SHL:
1615 return strcpy(p, "<<=");
1616 case TOK_A_SAR:
1617 return strcpy(p, ">>=");
1618 default:
1619 if (v < TOK_IDENT) {
1620 /* search in two bytes table */
1621 q = tok_two_chars;
1622 while (*q) {
1623 if (q[2] == v) {
1624 *p++ = q[0];
1625 *p++ = q[1];
1626 *p = '\0';
1627 return buf;
1629 q += 3;
1631 addv:
1632 *p++ = v;
1633 *p = '\0';
1634 } else if (v < tok_ident) {
1635 return table_ident[v - TOK_IDENT]->str;
1636 } else if (v >= SYM_FIRST_ANOM) {
1637 /* special name for anonymous symbol */
1638 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1639 } else {
1640 /* should never happen */
1641 return NULL;
1643 break;
1645 return cstr_buf.data;
1648 /* push, without hashing */
1649 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1651 Sym *s;
1652 s = sym_malloc();
1653 s->v = v;
1654 s->type.t = t;
1655 s->c = c;
1656 s->next = NULL;
1657 /* add in stack */
1658 s->prev = *ps;
1659 *ps = s;
1660 return s;
1663 /* find a symbol and return its associated structure. 's' is the top
1664 of the symbol stack */
1665 static Sym *sym_find2(Sym *s, int v)
1667 while (s) {
1668 if (s->v == v)
1669 return s;
1670 s = s->prev;
1672 return NULL;
1675 /* structure lookup */
1676 static inline Sym *struct_find(int v)
1678 v -= TOK_IDENT;
1679 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1680 return NULL;
1681 return table_ident[v]->sym_struct;
1684 /* find an identifier */
1685 static inline Sym *sym_find(int v)
1687 v -= TOK_IDENT;
1688 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1689 return NULL;
1690 return table_ident[v]->sym_identifier;
1693 /* push a given symbol on the symbol stack */
1694 static Sym *sym_push(int v, CType *type, int r, int c)
1696 Sym *s, **ps;
1697 TokenSym *ts;
1699 if (local_stack)
1700 ps = &local_stack;
1701 else
1702 ps = &global_stack;
1703 s = sym_push2(ps, v, type->t, c);
1704 s->type.ref = type->ref;
1705 s->r = r;
1706 /* don't record fields or anonymous symbols */
1707 /* XXX: simplify */
1708 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1709 /* record symbol in token array */
1710 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1711 if (v & SYM_STRUCT)
1712 ps = &ts->sym_struct;
1713 else
1714 ps = &ts->sym_identifier;
1715 s->prev_tok = *ps;
1716 *ps = s;
1718 return s;
1721 /* push a global identifier */
1722 static Sym *global_identifier_push(int v, int t, int c)
1724 Sym *s, **ps;
1725 s = sym_push2(&global_stack, v, t, c);
1726 /* don't record anonymous symbol */
1727 if (v < SYM_FIRST_ANOM) {
1728 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1729 /* modify the top most local identifier, so that
1730 sym_identifier will point to 's' when popped */
1731 while (*ps != NULL)
1732 ps = &(*ps)->prev_tok;
1733 s->prev_tok = NULL;
1734 *ps = s;
1736 return s;
1739 /* pop symbols until top reaches 'b' */
1740 static void sym_pop(Sym **ptop, Sym *b)
1742 Sym *s, *ss, **ps;
1743 TokenSym *ts;
1744 int v;
1746 s = *ptop;
1747 while(s != b) {
1748 ss = s->prev;
1749 v = s->v;
1750 /* remove symbol in token array */
1751 /* XXX: simplify */
1752 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1753 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1754 if (v & SYM_STRUCT)
1755 ps = &ts->sym_struct;
1756 else
1757 ps = &ts->sym_identifier;
1758 *ps = s->prev_tok;
1760 sym_free(s);
1761 s = ss;
1763 *ptop = b;
1766 /* I/O layer */
1768 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1770 int fd;
1771 BufferedFile *bf;
1773 fd = open(filename, O_RDONLY | O_BINARY);
1774 if (fd < 0)
1775 return NULL;
1776 bf = tcc_malloc(sizeof(BufferedFile));
1777 if (!bf) {
1778 close(fd);
1779 return NULL;
1781 bf->fd = fd;
1782 bf->buf_ptr = bf->buffer;
1783 bf->buf_end = bf->buffer;
1784 bf->buffer[0] = CH_EOB; /* put eob symbol */
1785 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1786 bf->line_num = 1;
1787 bf->ifndef_macro = 0;
1788 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1789 // printf("opening '%s'\n", filename);
1790 return bf;
1793 void tcc_close(BufferedFile *bf)
1795 total_lines += bf->line_num;
1796 close(bf->fd);
1797 tcc_free(bf);
1800 /* fill input buffer and peek next char */
1801 static int tcc_peekc_slow(BufferedFile *bf)
1803 int len;
1804 /* only tries to read if really end of buffer */
1805 if (bf->buf_ptr >= bf->buf_end) {
1806 if (bf->fd != -1) {
1807 #if defined(PARSE_DEBUG)
1808 len = 8;
1809 #else
1810 len = IO_BUF_SIZE;
1811 #endif
1812 len = read(bf->fd, bf->buffer, len);
1813 if (len < 0)
1814 len = 0;
1815 } else {
1816 len = 0;
1818 total_bytes += len;
1819 bf->buf_ptr = bf->buffer;
1820 bf->buf_end = bf->buffer + len;
1821 *bf->buf_end = CH_EOB;
1823 if (bf->buf_ptr < bf->buf_end) {
1824 return bf->buf_ptr[0];
1825 } else {
1826 bf->buf_ptr = bf->buf_end;
1827 return CH_EOF;
1831 /* return the current character, handling end of block if necessary
1832 (but not stray) */
1833 static int handle_eob(void)
1835 return tcc_peekc_slow(file);
1838 /* read next char from current input file and handle end of input buffer */
1839 static inline void inp(void)
1841 ch = *(++(file->buf_ptr));
1842 /* end of buffer/file handling */
1843 if (ch == CH_EOB)
1844 ch = handle_eob();
1847 /* handle '\[\r]\n' */
1848 static void handle_stray(void)
1850 while (ch == '\\') {
1851 inp();
1852 if (ch == '\n') {
1853 file->line_num++;
1854 inp();
1855 } else if (ch == '\r') {
1856 inp();
1857 if (ch != '\n')
1858 goto fail;
1859 file->line_num++;
1860 inp();
1861 } else {
1862 fail:
1863 error("stray '\\' in program");
1868 /* skip the stray and handle the \\n case. Output an error if
1869 incorrect char after the stray */
1870 static int handle_stray1(uint8_t *p)
1872 int c;
1874 if (p >= file->buf_end) {
1875 file->buf_ptr = p;
1876 c = handle_eob();
1877 p = file->buf_ptr;
1878 if (c == '\\')
1879 goto parse_stray;
1880 } else {
1881 parse_stray:
1882 file->buf_ptr = p;
1883 ch = *p;
1884 handle_stray();
1885 p = file->buf_ptr;
1886 c = *p;
1888 return c;
1891 /* handle just the EOB case, but not stray */
1892 #define PEEKC_EOB(c, p)\
1894 p++;\
1895 c = *p;\
1896 if (c == '\\') {\
1897 file->buf_ptr = p;\
1898 c = handle_eob();\
1899 p = file->buf_ptr;\
1903 /* handle the complicated stray case */
1904 #define PEEKC(c, p)\
1906 p++;\
1907 c = *p;\
1908 if (c == '\\') {\
1909 c = handle_stray1(p);\
1910 p = file->buf_ptr;\
1914 /* input with '\[\r]\n' handling. Note that this function cannot
1915 handle other characters after '\', so you cannot call it inside
1916 strings or comments */
1917 static void minp(void)
1919 inp();
1920 if (ch == '\\')
1921 handle_stray();
1925 /* single line C++ comments */
1926 static uint8_t *parse_line_comment(uint8_t *p)
1928 int c;
1930 p++;
1931 for(;;) {
1932 c = *p;
1933 redo:
1934 if (c == '\n' || c == CH_EOF) {
1935 break;
1936 } else if (c == '\\') {
1937 file->buf_ptr = p;
1938 c = handle_eob();
1939 p = file->buf_ptr;
1940 if (c == '\\') {
1941 PEEKC_EOB(c, p);
1942 if (c == '\n') {
1943 file->line_num++;
1944 PEEKC_EOB(c, p);
1945 } else if (c == '\r') {
1946 PEEKC_EOB(c, p);
1947 if (c == '\n') {
1948 file->line_num++;
1949 PEEKC_EOB(c, p);
1952 } else {
1953 goto redo;
1955 } else {
1956 p++;
1959 return p;
1962 /* C comments */
1963 static uint8_t *parse_comment(uint8_t *p)
1965 int c;
1967 p++;
1968 for(;;) {
1969 /* fast skip loop */
1970 for(;;) {
1971 c = *p;
1972 if (c == '\n' || c == '*' || c == '\\')
1973 break;
1974 p++;
1975 c = *p;
1976 if (c == '\n' || c == '*' || c == '\\')
1977 break;
1978 p++;
1980 /* now we can handle all the cases */
1981 if (c == '\n') {
1982 file->line_num++;
1983 p++;
1984 } else if (c == '*') {
1985 p++;
1986 for(;;) {
1987 c = *p;
1988 if (c == '*') {
1989 p++;
1990 } else if (c == '/') {
1991 goto end_of_comment;
1992 } else if (c == '\\') {
1993 file->buf_ptr = p;
1994 c = handle_eob();
1995 p = file->buf_ptr;
1996 if (c == '\\') {
1997 /* skip '\[\r]\n', otherwise just skip the stray */
1998 while (c == '\\') {
1999 PEEKC_EOB(c, p);
2000 if (c == '\n') {
2001 file->line_num++;
2002 PEEKC_EOB(c, p);
2003 } else if (c == '\r') {
2004 PEEKC_EOB(c, p);
2005 if (c == '\n') {
2006 file->line_num++;
2007 PEEKC_EOB(c, p);
2009 } else {
2010 goto after_star;
2014 } else {
2015 break;
2018 after_star: ;
2019 } else {
2020 /* stray, eob or eof */
2021 file->buf_ptr = p;
2022 c = handle_eob();
2023 p = file->buf_ptr;
2024 if (c == CH_EOF) {
2025 error("unexpected end of file in comment");
2026 } else if (c == '\\') {
2027 p++;
2031 end_of_comment:
2032 p++;
2033 return p;
2036 #define cinp minp
2038 /* space exlcuding newline */
2039 static inline int is_space(int ch)
2041 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2044 static inline void skip_spaces(void)
2046 while (is_space(ch))
2047 cinp();
2050 /* parse a string without interpreting escapes */
2051 static uint8_t *parse_pp_string(uint8_t *p,
2052 int sep, CString *str)
2054 int c;
2055 p++;
2056 for(;;) {
2057 c = *p;
2058 if (c == sep) {
2059 break;
2060 } else if (c == '\\') {
2061 file->buf_ptr = p;
2062 c = handle_eob();
2063 p = file->buf_ptr;
2064 if (c == CH_EOF) {
2065 unterminated_string:
2066 /* XXX: indicate line number of start of string */
2067 error("missing terminating %c character", sep);
2068 } else if (c == '\\') {
2069 /* escape : just skip \[\r]\n */
2070 PEEKC_EOB(c, p);
2071 if (c == '\n') {
2072 file->line_num++;
2073 p++;
2074 } else if (c == '\r') {
2075 PEEKC_EOB(c, p);
2076 if (c != '\n')
2077 expect("'\n' after '\r'");
2078 file->line_num++;
2079 p++;
2080 } else if (c == CH_EOF) {
2081 goto unterminated_string;
2082 } else {
2083 if (str) {
2084 cstr_ccat(str, '\\');
2085 cstr_ccat(str, c);
2087 p++;
2090 } else if (c == '\n') {
2091 file->line_num++;
2092 goto add_char;
2093 } else if (c == '\r') {
2094 PEEKC_EOB(c, p);
2095 if (c != '\n') {
2096 if (str)
2097 cstr_ccat(str, '\r');
2098 } else {
2099 file->line_num++;
2100 goto add_char;
2102 } else {
2103 add_char:
2104 if (str)
2105 cstr_ccat(str, c);
2106 p++;
2109 p++;
2110 return p;
2113 /* skip block of text until #else, #elif or #endif. skip also pairs of
2114 #if/#endif */
2115 void preprocess_skip(void)
2117 int a, start_of_line, c;
2118 uint8_t *p;
2120 p = file->buf_ptr;
2121 start_of_line = 1;
2122 a = 0;
2123 for(;;) {
2124 redo_no_start:
2125 c = *p;
2126 switch(c) {
2127 case ' ':
2128 case '\t':
2129 case '\f':
2130 case '\v':
2131 case '\r':
2132 p++;
2133 goto redo_no_start;
2134 case '\n':
2135 start_of_line = 1;
2136 file->line_num++;
2137 p++;
2138 goto redo_no_start;
2139 case '\\':
2140 file->buf_ptr = p;
2141 c = handle_eob();
2142 if (c == CH_EOF) {
2143 expect("#endif");
2144 } else if (c == '\\') {
2145 /* XXX: incorrect: should not give an error */
2146 ch = file->buf_ptr[0];
2147 handle_stray();
2149 p = file->buf_ptr;
2150 goto redo_no_start;
2151 /* skip strings */
2152 case '\"':
2153 case '\'':
2154 p = parse_pp_string(p, c, NULL);
2155 break;
2156 /* skip comments */
2157 case '/':
2158 file->buf_ptr = p;
2159 ch = *p;
2160 minp();
2161 p = file->buf_ptr;
2162 if (ch == '*') {
2163 p = parse_comment(p);
2164 } else if (ch == '/') {
2165 p = parse_line_comment(p);
2167 break;
2169 case '#':
2170 p++;
2171 if (start_of_line) {
2172 file->buf_ptr = p;
2173 next_nomacro();
2174 p = file->buf_ptr;
2175 if (a == 0 &&
2176 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2177 goto the_end;
2178 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2179 a++;
2180 else if (tok == TOK_ENDIF)
2181 a--;
2183 break;
2184 default:
2185 p++;
2186 break;
2188 start_of_line = 0;
2190 the_end: ;
2191 file->buf_ptr = p;
2194 /* ParseState handling */
2196 /* XXX: currently, no include file info is stored. Thus, we cannot display
2197 accurate messages if the function or data definition spans multiple
2198 files */
2200 /* save current parse state in 's' */
2201 void save_parse_state(ParseState *s)
2203 s->line_num = file->line_num;
2204 s->macro_ptr = macro_ptr;
2205 s->tok = tok;
2206 s->tokc = tokc;
2209 /* restore parse state from 's' */
2210 void restore_parse_state(ParseState *s)
2212 file->line_num = s->line_num;
2213 macro_ptr = s->macro_ptr;
2214 tok = s->tok;
2215 tokc = s->tokc;
2218 /* return the number of additional 'ints' necessary to store the
2219 token */
2220 static inline int tok_ext_size(int t)
2222 switch(t) {
2223 /* 4 bytes */
2224 case TOK_CINT:
2225 case TOK_CUINT:
2226 case TOK_CCHAR:
2227 case TOK_LCHAR:
2228 case TOK_CFLOAT:
2229 case TOK_LINENUM:
2230 return 1;
2231 case TOK_STR:
2232 case TOK_LSTR:
2233 case TOK_PPNUM:
2234 error("unsupported token");
2235 return 1;
2236 case TOK_CDOUBLE:
2237 case TOK_CLLONG:
2238 case TOK_CULLONG:
2239 return 2;
2240 case TOK_CLDOUBLE:
2241 return LDOUBLE_SIZE / 4;
2242 default:
2243 return 0;
2247 /* token string handling */
2249 static inline void tok_str_new(TokenString *s)
2251 s->str = NULL;
2252 s->len = 0;
2253 s->allocated_len = 0;
2254 s->last_line_num = -1;
2257 static void tok_str_free(int *str)
2259 tcc_free(str);
2262 static int *tok_str_realloc(TokenString *s)
2264 int *str, len;
2266 if (s->allocated_len == 0) {
2267 len = 8;
2268 } else {
2269 len = s->allocated_len * 2;
2271 str = tcc_realloc(s->str, len * sizeof(int));
2272 if (!str)
2273 error("memory full");
2274 s->allocated_len = len;
2275 s->str = str;
2276 return str;
2279 static void tok_str_add(TokenString *s, int t)
2281 int len, *str;
2283 len = s->len;
2284 str = s->str;
2285 if (len >= s->allocated_len)
2286 str = tok_str_realloc(s);
2287 str[len++] = t;
2288 s->len = len;
2291 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2293 int len, *str;
2295 len = s->len;
2296 str = s->str;
2298 /* allocate space for worst case */
2299 if (len + TOK_MAX_SIZE > s->allocated_len)
2300 str = tok_str_realloc(s);
2301 str[len++] = t;
2302 switch(t) {
2303 case TOK_CINT:
2304 case TOK_CUINT:
2305 case TOK_CCHAR:
2306 case TOK_LCHAR:
2307 case TOK_CFLOAT:
2308 case TOK_LINENUM:
2309 str[len++] = cv->tab[0];
2310 break;
2311 case TOK_PPNUM:
2312 case TOK_STR:
2313 case TOK_LSTR:
2315 int nb_words;
2316 CString *cstr;
2318 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2319 while ((len + nb_words) > s->allocated_len)
2320 str = tok_str_realloc(s);
2321 cstr = (CString *)(str + len);
2322 cstr->data = NULL;
2323 cstr->size = cv->cstr->size;
2324 cstr->data_allocated = NULL;
2325 cstr->size_allocated = cstr->size;
2326 memcpy((char *)cstr + sizeof(CString),
2327 cv->cstr->data, cstr->size);
2328 len += nb_words;
2330 break;
2331 case TOK_CDOUBLE:
2332 case TOK_CLLONG:
2333 case TOK_CULLONG:
2334 #if LDOUBLE_SIZE == 8
2335 case TOK_CLDOUBLE:
2336 #endif
2337 str[len++] = cv->tab[0];
2338 str[len++] = cv->tab[1];
2339 break;
2340 #if LDOUBLE_SIZE == 12
2341 case TOK_CLDOUBLE:
2342 str[len++] = cv->tab[0];
2343 str[len++] = cv->tab[1];
2344 str[len++] = cv->tab[2];
2345 #elif LDOUBLE_SIZE != 8
2346 #error add long double size support
2347 #endif
2348 break;
2349 default:
2350 break;
2352 s->len = len;
2355 /* add the current parse token in token string 's' */
2356 static void tok_str_add_tok(TokenString *s)
2358 CValue cval;
2360 /* save line number info */
2361 if (file->line_num != s->last_line_num) {
2362 s->last_line_num = file->line_num;
2363 cval.i = s->last_line_num;
2364 tok_str_add2(s, TOK_LINENUM, &cval);
2366 tok_str_add2(s, tok, &tokc);
2369 #if LDOUBLE_SIZE == 12
2370 #define LDOUBLE_GET(p, cv) \
2371 cv.tab[0] = p[0]; \
2372 cv.tab[1] = p[1]; \
2373 cv.tab[2] = p[2];
2374 #elif LDOUBLE_SIZE == 8
2375 #define LDOUBLE_GET(p, cv) \
2376 cv.tab[0] = p[0]; \
2377 cv.tab[1] = p[1];
2378 #else
2379 #error add long double size support
2380 #endif
2383 /* get a token from an integer array and increment pointer
2384 accordingly. we code it as a macro to avoid pointer aliasing. */
2385 #define TOK_GET(t, p, cv) \
2387 t = *p++; \
2388 switch(t) { \
2389 case TOK_CINT: \
2390 case TOK_CUINT: \
2391 case TOK_CCHAR: \
2392 case TOK_LCHAR: \
2393 case TOK_CFLOAT: \
2394 case TOK_LINENUM: \
2395 cv.tab[0] = *p++; \
2396 break; \
2397 case TOK_STR: \
2398 case TOK_LSTR: \
2399 case TOK_PPNUM: \
2400 cv.cstr = (CString *)p; \
2401 cv.cstr->data = (char *)p + sizeof(CString);\
2402 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2403 break; \
2404 case TOK_CDOUBLE: \
2405 case TOK_CLLONG: \
2406 case TOK_CULLONG: \
2407 cv.tab[0] = p[0]; \
2408 cv.tab[1] = p[1]; \
2409 p += 2; \
2410 break; \
2411 case TOK_CLDOUBLE: \
2412 LDOUBLE_GET(p, cv); \
2413 p += LDOUBLE_SIZE / 4; \
2414 break; \
2415 default: \
2416 break; \
2420 /* defines handling */
2421 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2423 Sym *s;
2425 s = sym_push2(&define_stack, v, macro_type, (int)str);
2426 s->next = first_arg;
2427 table_ident[v - TOK_IDENT]->sym_define = s;
2430 /* undefined a define symbol. Its name is just set to zero */
2431 static void define_undef(Sym *s)
2433 int v;
2434 v = s->v;
2435 if (v >= TOK_IDENT && v < tok_ident)
2436 table_ident[v - TOK_IDENT]->sym_define = NULL;
2437 s->v = 0;
2440 static inline Sym *define_find(int v)
2442 v -= TOK_IDENT;
2443 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2444 return NULL;
2445 return table_ident[v]->sym_define;
2448 /* free define stack until top reaches 'b' */
2449 static void free_defines(Sym *b)
2451 Sym *top, *top1;
2452 int v;
2454 top = define_stack;
2455 while (top != b) {
2456 top1 = top->prev;
2457 /* do not free args or predefined defines */
2458 if (top->c)
2459 tok_str_free((int *)top->c);
2460 v = top->v;
2461 if (v >= TOK_IDENT && v < tok_ident)
2462 table_ident[v - TOK_IDENT]->sym_define = NULL;
2463 sym_free(top);
2464 top = top1;
2466 define_stack = b;
2469 /* label lookup */
2470 static Sym *label_find(int v)
2472 v -= TOK_IDENT;
2473 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2474 return NULL;
2475 return table_ident[v]->sym_label;
2478 static Sym *label_push(Sym **ptop, int v, int flags)
2480 Sym *s, **ps;
2481 s = sym_push2(ptop, v, 0, 0);
2482 s->r = flags;
2483 ps = &table_ident[v - TOK_IDENT]->sym_label;
2484 if (ptop == &global_label_stack) {
2485 /* modify the top most local identifier, so that
2486 sym_identifier will point to 's' when popped */
2487 while (*ps != NULL)
2488 ps = &(*ps)->prev_tok;
2490 s->prev_tok = *ps;
2491 *ps = s;
2492 return s;
2495 /* pop labels until element last is reached. Look if any labels are
2496 undefined. Define symbols if '&&label' was used. */
2497 static void label_pop(Sym **ptop, Sym *slast)
2499 Sym *s, *s1;
2500 for(s = *ptop; s != slast; s = s1) {
2501 s1 = s->prev;
2502 if (s->r == LABEL_DECLARED) {
2503 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2504 } else if (s->r == LABEL_FORWARD) {
2505 error("label '%s' used but not defined",
2506 get_tok_str(s->v, NULL));
2507 } else {
2508 if (s->c) {
2509 /* define corresponding symbol. A size of
2510 1 is put. */
2511 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2514 /* remove label */
2515 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2516 sym_free(s);
2518 *ptop = slast;
2521 /* eval an expression for #if/#elif */
2522 static int expr_preprocess(void)
2524 int c, t;
2525 TokenString str;
2527 tok_str_new(&str);
2528 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2529 next(); /* do macro subst */
2530 if (tok == TOK_DEFINED) {
2531 next_nomacro();
2532 t = tok;
2533 if (t == '(')
2534 next_nomacro();
2535 c = define_find(tok) != 0;
2536 if (t == '(')
2537 next_nomacro();
2538 tok = TOK_CINT;
2539 tokc.i = c;
2540 } else if (tok >= TOK_IDENT) {
2541 /* if undefined macro */
2542 tok = TOK_CINT;
2543 tokc.i = 0;
2545 tok_str_add_tok(&str);
2547 tok_str_add(&str, -1); /* simulate end of file */
2548 tok_str_add(&str, 0);
2549 /* now evaluate C constant expression */
2550 macro_ptr = str.str;
2551 next();
2552 c = expr_const();
2553 macro_ptr = NULL;
2554 tok_str_free(str.str);
2555 return c != 0;
2558 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2559 static void tok_print(int *str)
2561 int t;
2562 CValue cval;
2564 while (1) {
2565 TOK_GET(t, str, cval);
2566 if (!t)
2567 break;
2568 printf(" %s", get_tok_str(t, &cval));
2570 printf("\n");
2572 #endif
2574 /* parse after #define */
2575 static void parse_define(void)
2577 Sym *s, *first, **ps;
2578 int v, t, varg, is_vaargs, c;
2579 TokenString str;
2581 v = tok;
2582 if (v < TOK_IDENT)
2583 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2584 /* XXX: should check if same macro (ANSI) */
2585 first = NULL;
2586 t = MACRO_OBJ;
2587 /* '(' must be just after macro definition for MACRO_FUNC */
2588 c = file->buf_ptr[0];
2589 if (c == '\\')
2590 c = handle_stray1(file->buf_ptr);
2591 if (c == '(') {
2592 next_nomacro();
2593 next_nomacro();
2594 ps = &first;
2595 while (tok != ')') {
2596 varg = tok;
2597 next_nomacro();
2598 is_vaargs = 0;
2599 if (varg == TOK_DOTS) {
2600 varg = TOK___VA_ARGS__;
2601 is_vaargs = 1;
2602 } else if (tok == TOK_DOTS && gnu_ext) {
2603 is_vaargs = 1;
2604 next_nomacro();
2606 if (varg < TOK_IDENT)
2607 error("badly punctuated parameter list");
2608 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2609 *ps = s;
2610 ps = &s->next;
2611 if (tok != ',')
2612 break;
2613 next_nomacro();
2615 t = MACRO_FUNC;
2617 tok_str_new(&str);
2618 next_nomacro();
2619 /* EOF testing necessary for '-D' handling */
2620 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2621 tok_str_add2(&str, tok, &tokc);
2622 next_nomacro();
2624 tok_str_add(&str, 0);
2625 #ifdef PP_DEBUG
2626 printf("define %s %d: ", get_tok_str(v, NULL), t);
2627 tok_print(str.str);
2628 #endif
2629 define_push(v, t, str.str, first);
2632 static inline int hash_cached_include(int type, const char *filename)
2634 const unsigned char *s;
2635 unsigned int h;
2637 h = TOK_HASH_INIT;
2638 h = TOK_HASH_FUNC(h, type);
2639 s = filename;
2640 while (*s) {
2641 h = TOK_HASH_FUNC(h, *s);
2642 s++;
2644 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2645 return h;
2648 /* XXX: use a token or a hash table to accelerate matching ? */
2649 static CachedInclude *search_cached_include(TCCState *s1,
2650 int type, const char *filename)
2652 CachedInclude *e;
2653 int i, h;
2654 h = hash_cached_include(type, filename);
2655 i = s1->cached_includes_hash[h];
2656 for(;;) {
2657 if (i == 0)
2658 break;
2659 e = s1->cached_includes[i - 1];
2660 if (e->type == type && !strcmp(e->filename, filename))
2661 return e;
2662 i = e->hash_next;
2664 return NULL;
2667 static inline void add_cached_include(TCCState *s1, int type,
2668 const char *filename, int ifndef_macro)
2670 CachedInclude *e;
2671 int h;
2673 if (search_cached_include(s1, type, filename))
2674 return;
2675 #ifdef INC_DEBUG
2676 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2677 #endif
2678 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2679 if (!e)
2680 return;
2681 e->type = type;
2682 strcpy(e->filename, filename);
2683 e->ifndef_macro = ifndef_macro;
2684 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2685 /* add in hash table */
2686 h = hash_cached_include(type, filename);
2687 e->hash_next = s1->cached_includes_hash[h];
2688 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2691 /* is_bof is true if first non space token at beginning of file */
2692 static void preprocess(int is_bof)
2694 TCCState *s1 = tcc_state;
2695 int size, i, c, n, saved_parse_flags;
2696 char buf[1024], *q, *p;
2697 char buf1[1024];
2698 BufferedFile *f;
2699 Sym *s;
2700 CachedInclude *e;
2702 saved_parse_flags = parse_flags;
2703 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2704 PARSE_FLAG_LINEFEED;
2705 next_nomacro();
2706 redo:
2707 switch(tok) {
2708 case TOK_DEFINE:
2709 next_nomacro();
2710 parse_define();
2711 break;
2712 case TOK_UNDEF:
2713 next_nomacro();
2714 s = define_find(tok);
2715 /* undefine symbol by putting an invalid name */
2716 if (s)
2717 define_undef(s);
2718 break;
2719 case TOK_INCLUDE:
2720 ch = file->buf_ptr[0];
2721 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2722 skip_spaces();
2723 if (ch == '<') {
2724 c = '>';
2725 goto read_name;
2726 } else if (ch == '\"') {
2727 c = ch;
2728 read_name:
2729 /* XXX: better stray handling */
2730 minp();
2731 q = buf;
2732 while (ch != c && ch != '\n' && ch != CH_EOF) {
2733 if ((q - buf) < sizeof(buf) - 1)
2734 *q++ = ch;
2735 minp();
2737 *q = '\0';
2738 minp();
2739 #if 0
2740 /* eat all spaces and comments after include */
2741 /* XXX: slightly incorrect */
2742 while (ch1 != '\n' && ch1 != CH_EOF)
2743 inp();
2744 #endif
2745 } else {
2746 /* computed #include : either we have only strings or
2747 we have anything enclosed in '<>' */
2748 next();
2749 buf[0] = '\0';
2750 if (tok == TOK_STR) {
2751 while (tok != TOK_LINEFEED) {
2752 if (tok != TOK_STR) {
2753 include_syntax:
2754 error("'#include' expects \"FILENAME\" or <FILENAME>");
2756 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2757 next();
2759 c = '\"';
2760 } else {
2761 int len;
2762 while (tok != TOK_LINEFEED) {
2763 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2764 next();
2766 len = strlen(buf);
2767 /* check syntax and remove '<>' */
2768 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2769 goto include_syntax;
2770 memmove(buf, buf + 1, len - 2);
2771 buf[len - 2] = '\0';
2772 c = '>';
2776 e = search_cached_include(s1, c, buf);
2777 if (e && define_find(e->ifndef_macro)) {
2778 /* no need to parse the include because the 'ifndef macro'
2779 is defined */
2780 #ifdef INC_DEBUG
2781 printf("%s: skipping %s\n", file->filename, buf);
2782 #endif
2783 } else {
2784 if (c == '\"') {
2785 /* first search in current dir if "header.h" */
2786 size = 0;
2787 p = strrchr(file->filename, '/');
2788 if (p)
2789 size = p + 1 - file->filename;
2790 if (size > sizeof(buf1) - 1)
2791 size = sizeof(buf1) - 1;
2792 memcpy(buf1, file->filename, size);
2793 buf1[size] = '\0';
2794 pstrcat(buf1, sizeof(buf1), buf);
2795 f = tcc_open(s1, buf1);
2796 if (f)
2797 goto found;
2799 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2800 error("#include recursion too deep");
2801 /* now search in all the include paths */
2802 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2803 for(i = 0; i < n; i++) {
2804 const char *path;
2805 if (i < s1->nb_include_paths)
2806 path = s1->include_paths[i];
2807 else
2808 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2809 pstrcpy(buf1, sizeof(buf1), path);
2810 pstrcat(buf1, sizeof(buf1), "/");
2811 pstrcat(buf1, sizeof(buf1), buf);
2812 f = tcc_open(s1, buf1);
2813 if (f)
2814 goto found;
2816 error("include file '%s' not found", buf);
2817 f = NULL;
2818 found:
2819 #ifdef INC_DEBUG
2820 printf("%s: including %s\n", file->filename, buf1);
2821 #endif
2822 f->inc_type = c;
2823 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2824 /* push current file in stack */
2825 /* XXX: fix current line init */
2826 *s1->include_stack_ptr++ = file;
2827 file = f;
2828 /* add include file debug info */
2829 if (do_debug) {
2830 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2832 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2833 ch = file->buf_ptr[0];
2834 goto the_end;
2836 break;
2837 case TOK_IFNDEF:
2838 c = 1;
2839 goto do_ifdef;
2840 case TOK_IF:
2841 c = expr_preprocess();
2842 goto do_if;
2843 case TOK_IFDEF:
2844 c = 0;
2845 do_ifdef:
2846 next_nomacro();
2847 if (tok < TOK_IDENT)
2848 error("invalid argument for '#if%sdef'", c ? "n" : "");
2849 if (is_bof) {
2850 if (c) {
2851 #ifdef INC_DEBUG
2852 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2853 #endif
2854 file->ifndef_macro = tok;
2857 c = (define_find(tok) != 0) ^ c;
2858 do_if:
2859 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2860 error("memory full");
2861 *s1->ifdef_stack_ptr++ = c;
2862 goto test_skip;
2863 case TOK_ELSE:
2864 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2865 error("#else without matching #if");
2866 if (s1->ifdef_stack_ptr[-1] & 2)
2867 error("#else after #else");
2868 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2869 goto test_skip;
2870 case TOK_ELIF:
2871 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2872 error("#elif without matching #if");
2873 c = s1->ifdef_stack_ptr[-1];
2874 if (c > 1)
2875 error("#elif after #else");
2876 /* last #if/#elif expression was true: we skip */
2877 if (c == 1)
2878 goto skip;
2879 c = expr_preprocess();
2880 s1->ifdef_stack_ptr[-1] = c;
2881 test_skip:
2882 if (!(c & 1)) {
2883 skip:
2884 preprocess_skip();
2885 is_bof = 0;
2886 goto redo;
2888 break;
2889 case TOK_ENDIF:
2890 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2891 error("#endif without matching #if");
2892 s1->ifdef_stack_ptr--;
2893 /* '#ifndef macro' was at the start of file. Now we check if
2894 an '#endif' is exactly at the end of file */
2895 if (file->ifndef_macro &&
2896 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2897 file->ifndef_macro_saved = file->ifndef_macro;
2898 /* need to set to zero to avoid false matches if another
2899 #ifndef at middle of file */
2900 file->ifndef_macro = 0;
2901 while (tok != TOK_LINEFEED)
2902 next_nomacro();
2903 tok_flags |= TOK_FLAG_ENDIF;
2904 goto the_end;
2906 break;
2907 case TOK_LINE:
2908 next();
2909 if (tok != TOK_CINT)
2910 error("#line");
2911 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2912 next();
2913 if (tok != TOK_LINEFEED) {
2914 if (tok != TOK_STR)
2915 error("#line");
2916 pstrcpy(file->filename, sizeof(file->filename),
2917 (char *)tokc.cstr->data);
2919 break;
2920 case TOK_ERROR:
2921 case TOK_WARNING:
2922 c = tok;
2923 ch = file->buf_ptr[0];
2924 skip_spaces();
2925 q = buf;
2926 while (ch != '\n' && ch != CH_EOF) {
2927 if ((q - buf) < sizeof(buf) - 1)
2928 *q++ = ch;
2929 minp();
2931 *q = '\0';
2932 if (c == TOK_ERROR)
2933 error("#error %s", buf);
2934 else
2935 warning("#warning %s", buf);
2936 break;
2937 case TOK_PRAGMA:
2938 /* ignored */
2939 break;
2940 default:
2941 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2942 /* '!' is ignored to allow C scripts. numbers are ignored
2943 to emulate cpp behaviour */
2944 } else {
2945 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
2946 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2948 break;
2950 /* ignore other preprocess commands or #! for C scripts */
2951 while (tok != TOK_LINEFEED)
2952 next_nomacro();
2953 the_end:
2954 parse_flags = saved_parse_flags;
2957 /* evaluate escape codes in a string. */
2958 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2960 int c, n;
2961 const uint8_t *p;
2963 p = buf;
2964 for(;;) {
2965 c = *p;
2966 if (c == '\0')
2967 break;
2968 if (c == '\\') {
2969 p++;
2970 /* escape */
2971 c = *p;
2972 switch(c) {
2973 case '0': case '1': case '2': case '3':
2974 case '4': case '5': case '6': case '7':
2975 /* at most three octal digits */
2976 n = c - '0';
2977 p++;
2978 c = *p;
2979 if (isoct(c)) {
2980 n = n * 8 + c - '0';
2981 p++;
2982 c = *p;
2983 if (isoct(c)) {
2984 n = n * 8 + c - '0';
2985 p++;
2988 c = n;
2989 goto add_char_nonext;
2990 case 'x':
2991 p++;
2992 n = 0;
2993 for(;;) {
2994 c = *p;
2995 if (c >= 'a' && c <= 'f')
2996 c = c - 'a' + 10;
2997 else if (c >= 'A' && c <= 'F')
2998 c = c - 'A' + 10;
2999 else if (isnum(c))
3000 c = c - '0';
3001 else
3002 break;
3003 n = n * 16 + c;
3004 p++;
3006 c = n;
3007 goto add_char_nonext;
3008 case 'a':
3009 c = '\a';
3010 break;
3011 case 'b':
3012 c = '\b';
3013 break;
3014 case 'f':
3015 c = '\f';
3016 break;
3017 case 'n':
3018 c = '\n';
3019 break;
3020 case 'r':
3021 c = '\r';
3022 break;
3023 case 't':
3024 c = '\t';
3025 break;
3026 case 'v':
3027 c = '\v';
3028 break;
3029 case 'e':
3030 if (!gnu_ext)
3031 goto invalid_escape;
3032 c = 27;
3033 break;
3034 case '\'':
3035 case '\"':
3036 case '\\':
3037 case '?':
3038 break;
3039 default:
3040 invalid_escape:
3041 if (c >= '!' && c <= '~')
3042 warning("unknown escape sequence: \'\\%c\'", c);
3043 else
3044 warning("unknown escape sequence: \'\\x%x\'", c);
3045 break;
3048 p++;
3049 add_char_nonext:
3050 if (!is_long)
3051 cstr_ccat(outstr, c);
3052 else
3053 cstr_wccat(outstr, c);
3055 /* add a trailing '\0' */
3056 if (!is_long)
3057 cstr_ccat(outstr, '\0');
3058 else
3059 cstr_wccat(outstr, '\0');
3062 /* we use 64 bit numbers */
3063 #define BN_SIZE 2
3065 /* bn = (bn << shift) | or_val */
3066 void bn_lshift(unsigned int *bn, int shift, int or_val)
3068 int i;
3069 unsigned int v;
3070 for(i=0;i<BN_SIZE;i++) {
3071 v = bn[i];
3072 bn[i] = (v << shift) | or_val;
3073 or_val = v >> (32 - shift);
3077 void bn_zero(unsigned int *bn)
3079 int i;
3080 for(i=0;i<BN_SIZE;i++) {
3081 bn[i] = 0;
3085 /* parse number in null terminated string 'p' and return it in the
3086 current token */
3087 void parse_number(const char *p)
3089 int b, t, shift, frac_bits, s, exp_val, ch;
3090 char *q;
3091 unsigned int bn[BN_SIZE];
3092 double d;
3094 /* number */
3095 q = token_buf;
3096 ch = *p++;
3097 t = ch;
3098 ch = *p++;
3099 *q++ = t;
3100 b = 10;
3101 if (t == '.') {
3102 goto float_frac_parse;
3103 } else if (t == '0') {
3104 if (ch == 'x' || ch == 'X') {
3105 q--;
3106 ch = *p++;
3107 b = 16;
3108 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3109 q--;
3110 ch = *p++;
3111 b = 2;
3114 /* parse all digits. cannot check octal numbers at this stage
3115 because of floating point constants */
3116 while (1) {
3117 if (ch >= 'a' && ch <= 'f')
3118 t = ch - 'a' + 10;
3119 else if (ch >= 'A' && ch <= 'F')
3120 t = ch - 'A' + 10;
3121 else if (isnum(ch))
3122 t = ch - '0';
3123 else
3124 break;
3125 if (t >= b)
3126 break;
3127 if (q >= token_buf + STRING_MAX_SIZE) {
3128 num_too_long:
3129 error("number too long");
3131 *q++ = ch;
3132 ch = *p++;
3134 if (ch == '.' ||
3135 ((ch == 'e' || ch == 'E') && b == 10) ||
3136 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3137 if (b != 10) {
3138 /* NOTE: strtox should support that for hexa numbers, but
3139 non ISOC99 libcs do not support it, so we prefer to do
3140 it by hand */
3141 /* hexadecimal or binary floats */
3142 /* XXX: handle overflows */
3143 *q = '\0';
3144 if (b == 16)
3145 shift = 4;
3146 else
3147 shift = 2;
3148 bn_zero(bn);
3149 q = token_buf;
3150 while (1) {
3151 t = *q++;
3152 if (t == '\0') {
3153 break;
3154 } else if (t >= 'a') {
3155 t = t - 'a' + 10;
3156 } else if (t >= 'A') {
3157 t = t - 'A' + 10;
3158 } else {
3159 t = t - '0';
3161 bn_lshift(bn, shift, t);
3163 frac_bits = 0;
3164 if (ch == '.') {
3165 ch = *p++;
3166 while (1) {
3167 t = ch;
3168 if (t >= 'a' && t <= 'f') {
3169 t = t - 'a' + 10;
3170 } else if (t >= 'A' && t <= 'F') {
3171 t = t - 'A' + 10;
3172 } else if (t >= '0' && t <= '9') {
3173 t = t - '0';
3174 } else {
3175 break;
3177 if (t >= b)
3178 error("invalid digit");
3179 bn_lshift(bn, shift, t);
3180 frac_bits += shift;
3181 ch = *p++;
3184 if (ch != 'p' && ch != 'P')
3185 expect("exponent");
3186 ch = *p++;
3187 s = 1;
3188 exp_val = 0;
3189 if (ch == '+') {
3190 ch = *p++;
3191 } else if (ch == '-') {
3192 s = -1;
3193 ch = *p++;
3195 if (ch < '0' || ch > '9')
3196 expect("exponent digits");
3197 while (ch >= '0' && ch <= '9') {
3198 exp_val = exp_val * 10 + ch - '0';
3199 ch = *p++;
3201 exp_val = exp_val * s;
3203 /* now we can generate the number */
3204 /* XXX: should patch directly float number */
3205 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3206 d = ldexp(d, exp_val - frac_bits);
3207 t = toup(ch);
3208 if (t == 'F') {
3209 ch = *p++;
3210 tok = TOK_CFLOAT;
3211 /* float : should handle overflow */
3212 tokc.f = (float)d;
3213 } else if (t == 'L') {
3214 ch = *p++;
3215 tok = TOK_CLDOUBLE;
3216 /* XXX: not large enough */
3217 tokc.ld = (long double)d;
3218 } else {
3219 tok = TOK_CDOUBLE;
3220 tokc.d = d;
3222 } else {
3223 /* decimal floats */
3224 if (ch == '.') {
3225 if (q >= token_buf + STRING_MAX_SIZE)
3226 goto num_too_long;
3227 *q++ = ch;
3228 ch = *p++;
3229 float_frac_parse:
3230 while (ch >= '0' && ch <= '9') {
3231 if (q >= token_buf + STRING_MAX_SIZE)
3232 goto num_too_long;
3233 *q++ = ch;
3234 ch = *p++;
3237 if (ch == 'e' || ch == 'E') {
3238 if (q >= token_buf + STRING_MAX_SIZE)
3239 goto num_too_long;
3240 *q++ = ch;
3241 ch = *p++;
3242 if (ch == '-' || ch == '+') {
3243 if (q >= token_buf + STRING_MAX_SIZE)
3244 goto num_too_long;
3245 *q++ = ch;
3246 ch = *p++;
3248 if (ch < '0' || ch > '9')
3249 expect("exponent digits");
3250 while (ch >= '0' && ch <= '9') {
3251 if (q >= token_buf + STRING_MAX_SIZE)
3252 goto num_too_long;
3253 *q++ = ch;
3254 ch = *p++;
3257 *q = '\0';
3258 t = toup(ch);
3259 errno = 0;
3260 if (t == 'F') {
3261 ch = *p++;
3262 tok = TOK_CFLOAT;
3263 tokc.f = strtof(token_buf, NULL);
3264 } else if (t == 'L') {
3265 ch = *p++;
3266 tok = TOK_CLDOUBLE;
3267 tokc.ld = strtold(token_buf, NULL);
3268 } else {
3269 tok = TOK_CDOUBLE;
3270 tokc.d = strtod(token_buf, NULL);
3273 } else {
3274 unsigned long long n, n1;
3275 int lcount, ucount;
3277 /* integer number */
3278 *q = '\0';
3279 q = token_buf;
3280 if (b == 10 && *q == '0') {
3281 b = 8;
3282 q++;
3284 n = 0;
3285 while(1) {
3286 t = *q++;
3287 /* no need for checks except for base 10 / 8 errors */
3288 if (t == '\0') {
3289 break;
3290 } else if (t >= 'a') {
3291 t = t - 'a' + 10;
3292 } else if (t >= 'A') {
3293 t = t - 'A' + 10;
3294 } else {
3295 t = t - '0';
3296 if (t >= b)
3297 error("invalid digit");
3299 n1 = n;
3300 n = n * b + t;
3301 /* detect overflow */
3302 /* XXX: this test is not reliable */
3303 if (n < n1)
3304 error("integer constant overflow");
3307 /* XXX: not exactly ANSI compliant */
3308 if ((n & 0xffffffff00000000LL) != 0) {
3309 if ((n >> 63) != 0)
3310 tok = TOK_CULLONG;
3311 else
3312 tok = TOK_CLLONG;
3313 } else if (n > 0x7fffffff) {
3314 tok = TOK_CUINT;
3315 } else {
3316 tok = TOK_CINT;
3318 lcount = 0;
3319 ucount = 0;
3320 for(;;) {
3321 t = toup(ch);
3322 if (t == 'L') {
3323 if (lcount >= 2)
3324 error("three 'l's in integer constant");
3325 lcount++;
3326 if (lcount == 2) {
3327 if (tok == TOK_CINT)
3328 tok = TOK_CLLONG;
3329 else if (tok == TOK_CUINT)
3330 tok = TOK_CULLONG;
3332 ch = *p++;
3333 } else if (t == 'U') {
3334 if (ucount >= 1)
3335 error("two 'u's in integer constant");
3336 ucount++;
3337 if (tok == TOK_CINT)
3338 tok = TOK_CUINT;
3339 else if (tok == TOK_CLLONG)
3340 tok = TOK_CULLONG;
3341 ch = *p++;
3342 } else {
3343 break;
3346 if (tok == TOK_CINT || tok == TOK_CUINT)
3347 tokc.ui = n;
3348 else
3349 tokc.ull = n;
3354 #define PARSE2(c1, tok1, c2, tok2) \
3355 case c1: \
3356 PEEKC(c, p); \
3357 if (c == c2) { \
3358 p++; \
3359 tok = tok2; \
3360 } else { \
3361 tok = tok1; \
3363 break;
3365 /* return next token without macro substitution */
3366 static inline void next_nomacro1(void)
3368 int t, c, is_long;
3369 TokenSym *ts;
3370 uint8_t *p, *p1;
3371 unsigned int h;
3373 p = file->buf_ptr;
3374 redo_no_start:
3375 c = *p;
3376 switch(c) {
3377 case ' ':
3378 case '\t':
3379 case '\f':
3380 case '\v':
3381 case '\r':
3382 p++;
3383 goto redo_no_start;
3385 case '\\':
3386 /* first look if it is in fact an end of buffer */
3387 if (p >= file->buf_end) {
3388 file->buf_ptr = p;
3389 handle_eob();
3390 p = file->buf_ptr;
3391 if (p >= file->buf_end)
3392 goto parse_eof;
3393 else
3394 goto redo_no_start;
3395 } else {
3396 file->buf_ptr = p;
3397 ch = *p;
3398 handle_stray();
3399 p = file->buf_ptr;
3400 goto redo_no_start;
3402 parse_eof:
3404 TCCState *s1 = tcc_state;
3405 if (parse_flags & PARSE_FLAG_LINEFEED) {
3406 tok = TOK_LINEFEED;
3407 } else if (s1->include_stack_ptr == s1->include_stack ||
3408 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3409 /* no include left : end of file. */
3410 tok = TOK_EOF;
3411 } else {
3412 /* pop include file */
3414 /* test if previous '#endif' was after a #ifdef at
3415 start of file */
3416 if (tok_flags & TOK_FLAG_ENDIF) {
3417 #ifdef INC_DEBUG
3418 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3419 #endif
3420 add_cached_include(s1, file->inc_type, file->inc_filename,
3421 file->ifndef_macro_saved);
3424 /* add end of include file debug info */
3425 if (do_debug) {
3426 put_stabd(N_EINCL, 0, 0);
3428 /* pop include stack */
3429 tcc_close(file);
3430 s1->include_stack_ptr--;
3431 file = *s1->include_stack_ptr;
3432 p = file->buf_ptr;
3433 goto redo_no_start;
3436 break;
3438 case '\n':
3439 if (parse_flags & PARSE_FLAG_LINEFEED) {
3440 tok = TOK_LINEFEED;
3441 } else {
3442 file->line_num++;
3443 tok_flags |= TOK_FLAG_BOL;
3444 p++;
3445 goto redo_no_start;
3447 break;
3449 case '#':
3450 /* XXX: simplify */
3451 PEEKC(c, p);
3452 if ((tok_flags & TOK_FLAG_BOL) &&
3453 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3454 file->buf_ptr = p;
3455 preprocess(tok_flags & TOK_FLAG_BOF);
3456 p = file->buf_ptr;
3457 goto redo_no_start;
3458 } else {
3459 if (c == '#') {
3460 p++;
3461 tok = TOK_TWOSHARPS;
3462 } else {
3463 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3464 p = parse_line_comment(p - 1);
3465 goto redo_no_start;
3466 } else {
3467 tok = '#';
3471 break;
3473 case 'a': case 'b': case 'c': case 'd':
3474 case 'e': case 'f': case 'g': case 'h':
3475 case 'i': case 'j': case 'k': case 'l':
3476 case 'm': case 'n': case 'o': case 'p':
3477 case 'q': case 'r': case 's': case 't':
3478 case 'u': case 'v': case 'w': case 'x':
3479 case 'y': case 'z':
3480 case 'A': case 'B': case 'C': case 'D':
3481 case 'E': case 'F': case 'G': case 'H':
3482 case 'I': case 'J': case 'K':
3483 case 'M': case 'N': case 'O': case 'P':
3484 case 'Q': case 'R': case 'S': case 'T':
3485 case 'U': case 'V': case 'W': case 'X':
3486 case 'Y': case 'Z':
3487 case '_':
3488 parse_ident_fast:
3489 p1 = p;
3490 h = TOK_HASH_INIT;
3491 h = TOK_HASH_FUNC(h, c);
3492 p++;
3493 for(;;) {
3494 c = *p;
3495 if (!isidnum_table[c])
3496 break;
3497 h = TOK_HASH_FUNC(h, c);
3498 p++;
3500 if (c != '\\') {
3501 TokenSym **pts;
3502 int len;
3504 /* fast case : no stray found, so we have the full token
3505 and we have already hashed it */
3506 len = p - p1;
3507 h &= (TOK_HASH_SIZE - 1);
3508 pts = &hash_ident[h];
3509 for(;;) {
3510 ts = *pts;
3511 if (!ts)
3512 break;
3513 if (ts->len == len && !memcmp(ts->str, p1, len))
3514 goto token_found;
3515 pts = &(ts->hash_next);
3517 ts = tok_alloc_new(pts, p1, len);
3518 token_found: ;
3519 } else {
3520 /* slower case */
3521 cstr_reset(&tokcstr);
3523 while (p1 < p) {
3524 cstr_ccat(&tokcstr, *p1);
3525 p1++;
3527 p--;
3528 PEEKC(c, p);
3529 parse_ident_slow:
3530 while (isidnum_table[c]) {
3531 cstr_ccat(&tokcstr, c);
3532 PEEKC(c, p);
3534 ts = tok_alloc(tokcstr.data, tokcstr.size);
3536 tok = ts->tok;
3537 break;
3538 case 'L':
3539 t = p[1];
3540 if (t != '\\' && t != '\'' && t != '\"') {
3541 /* fast case */
3542 goto parse_ident_fast;
3543 } else {
3544 PEEKC(c, p);
3545 if (c == '\'' || c == '\"') {
3546 is_long = 1;
3547 goto str_const;
3548 } else {
3549 cstr_reset(&tokcstr);
3550 cstr_ccat(&tokcstr, 'L');
3551 goto parse_ident_slow;
3554 break;
3555 case '0': case '1': case '2': case '3':
3556 case '4': case '5': case '6': case '7':
3557 case '8': case '9':
3559 cstr_reset(&tokcstr);
3560 /* after the first digit, accept digits, alpha, '.' or sign if
3561 prefixed by 'eEpP' */
3562 parse_num:
3563 for(;;) {
3564 t = c;
3565 cstr_ccat(&tokcstr, c);
3566 PEEKC(c, p);
3567 if (!(isnum(c) || isid(c) || c == '.' ||
3568 ((c == '+' || c == '-') &&
3569 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3570 break;
3572 /* We add a trailing '\0' to ease parsing */
3573 cstr_ccat(&tokcstr, '\0');
3574 tokc.cstr = &tokcstr;
3575 tok = TOK_PPNUM;
3576 break;
3577 case '.':
3578 /* special dot handling because it can also start a number */
3579 PEEKC(c, p);
3580 if (isnum(c)) {
3581 cstr_reset(&tokcstr);
3582 cstr_ccat(&tokcstr, '.');
3583 goto parse_num;
3584 } else if (c == '.') {
3585 PEEKC(c, p);
3586 if (c != '.')
3587 expect("'.'");
3588 PEEKC(c, p);
3589 tok = TOK_DOTS;
3590 } else {
3591 tok = '.';
3593 break;
3594 case '\'':
3595 case '\"':
3596 is_long = 0;
3597 str_const:
3599 CString str;
3600 int sep;
3602 sep = c;
3604 /* parse the string */
3605 cstr_new(&str);
3606 p = parse_pp_string(p, sep, &str);
3607 cstr_ccat(&str, '\0');
3609 /* eval the escape (should be done as TOK_PPNUM) */
3610 cstr_reset(&tokcstr);
3611 parse_escape_string(&tokcstr, str.data, is_long);
3612 cstr_free(&str);
3614 if (sep == '\'') {
3615 int char_size;
3616 /* XXX: make it portable */
3617 if (!is_long)
3618 char_size = 1;
3619 else
3620 char_size = sizeof(int);
3621 if (tokcstr.size <= char_size)
3622 error("empty character constant");
3623 if (tokcstr.size > 2 * char_size)
3624 warning("multi-character character constant");
3625 if (!is_long) {
3626 tokc.i = *(int8_t *)tokcstr.data;
3627 tok = TOK_CCHAR;
3628 } else {
3629 tokc.i = *(int *)tokcstr.data;
3630 tok = TOK_LCHAR;
3632 } else {
3633 tokc.cstr = &tokcstr;
3634 if (!is_long)
3635 tok = TOK_STR;
3636 else
3637 tok = TOK_LSTR;
3640 break;
3642 case '<':
3643 PEEKC(c, p);
3644 if (c == '=') {
3645 p++;
3646 tok = TOK_LE;
3647 } else if (c == '<') {
3648 PEEKC(c, p);
3649 if (c == '=') {
3650 p++;
3651 tok = TOK_A_SHL;
3652 } else {
3653 tok = TOK_SHL;
3655 } else {
3656 tok = TOK_LT;
3658 break;
3660 case '>':
3661 PEEKC(c, p);
3662 if (c == '=') {
3663 p++;
3664 tok = TOK_GE;
3665 } else if (c == '>') {
3666 PEEKC(c, p);
3667 if (c == '=') {
3668 p++;
3669 tok = TOK_A_SAR;
3670 } else {
3671 tok = TOK_SAR;
3673 } else {
3674 tok = TOK_GT;
3676 break;
3678 case '&':
3679 PEEKC(c, p);
3680 if (c == '&') {
3681 p++;
3682 tok = TOK_LAND;
3683 } else if (c == '=') {
3684 p++;
3685 tok = TOK_A_AND;
3686 } else {
3687 tok = '&';
3689 break;
3691 case '|':
3692 PEEKC(c, p);
3693 if (c == '|') {
3694 p++;
3695 tok = TOK_LOR;
3696 } else if (c == '=') {
3697 p++;
3698 tok = TOK_A_OR;
3699 } else {
3700 tok = '|';
3702 break;
3704 case '+':
3705 PEEKC(c, p);
3706 if (c == '+') {
3707 p++;
3708 tok = TOK_INC;
3709 } else if (c == '=') {
3710 p++;
3711 tok = TOK_A_ADD;
3712 } else {
3713 tok = '+';
3715 break;
3717 case '-':
3718 PEEKC(c, p);
3719 if (c == '-') {
3720 p++;
3721 tok = TOK_DEC;
3722 } else if (c == '=') {
3723 p++;
3724 tok = TOK_A_SUB;
3725 } else if (c == '>') {
3726 p++;
3727 tok = TOK_ARROW;
3728 } else {
3729 tok = '-';
3731 break;
3733 PARSE2('!', '!', '=', TOK_NE)
3734 PARSE2('=', '=', '=', TOK_EQ)
3735 PARSE2('*', '*', '=', TOK_A_MUL)
3736 PARSE2('%', '%', '=', TOK_A_MOD)
3737 PARSE2('^', '^', '=', TOK_A_XOR)
3739 /* comments or operator */
3740 case '/':
3741 PEEKC(c, p);
3742 if (c == '*') {
3743 p = parse_comment(p);
3744 goto redo_no_start;
3745 } else if (c == '/') {
3746 p = parse_line_comment(p);
3747 goto redo_no_start;
3748 } else if (c == '=') {
3749 p++;
3750 tok = TOK_A_DIV;
3751 } else {
3752 tok = '/';
3754 break;
3756 /* simple tokens */
3757 case '(':
3758 case ')':
3759 case '[':
3760 case ']':
3761 case '{':
3762 case '}':
3763 case ',':
3764 case ';':
3765 case ':':
3766 case '?':
3767 case '~':
3768 case '$': /* only used in assembler */
3769 tok = c;
3770 p++;
3771 break;
3772 default:
3773 error("unrecognized character \\x%02x", c);
3774 break;
3776 file->buf_ptr = p;
3777 tok_flags = 0;
3778 #if defined(PARSE_DEBUG)
3779 printf("token = %s\n", get_tok_str(tok, &tokc));
3780 #endif
3783 /* return next token without macro substitution. Can read input from
3784 macro_ptr buffer */
3785 static void next_nomacro(void)
3787 if (macro_ptr) {
3788 redo:
3789 tok = *macro_ptr;
3790 if (tok) {
3791 TOK_GET(tok, macro_ptr, tokc);
3792 if (tok == TOK_LINENUM) {
3793 file->line_num = tokc.i;
3794 goto redo;
3797 } else {
3798 next_nomacro1();
3802 /* substitute args in macro_str and return allocated string */
3803 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3805 int *st, last_tok, t, notfirst;
3806 Sym *s;
3807 CValue cval;
3808 TokenString str;
3809 CString cstr;
3811 tok_str_new(&str);
3812 last_tok = 0;
3813 while(1) {
3814 TOK_GET(t, macro_str, cval);
3815 if (!t)
3816 break;
3817 if (t == '#') {
3818 /* stringize */
3819 TOK_GET(t, macro_str, cval);
3820 if (!t)
3821 break;
3822 s = sym_find2(args, t);
3823 if (s) {
3824 cstr_new(&cstr);
3825 st = (int *)s->c;
3826 notfirst = 0;
3827 while (*st) {
3828 if (notfirst)
3829 cstr_ccat(&cstr, ' ');
3830 TOK_GET(t, st, cval);
3831 cstr_cat(&cstr, get_tok_str(t, &cval));
3832 notfirst = 1;
3834 cstr_ccat(&cstr, '\0');
3835 #ifdef PP_DEBUG
3836 printf("stringize: %s\n", (char *)cstr.data);
3837 #endif
3838 /* add string */
3839 cval.cstr = &cstr;
3840 tok_str_add2(&str, TOK_STR, &cval);
3841 cstr_free(&cstr);
3842 } else {
3843 tok_str_add2(&str, t, &cval);
3845 } else if (t >= TOK_IDENT) {
3846 s = sym_find2(args, t);
3847 if (s) {
3848 st = (int *)s->c;
3849 /* if '##' is present before or after, no arg substitution */
3850 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3851 /* special case for var arg macros : ## eats the
3852 ',' if empty VA_ARGS variable. */
3853 /* XXX: test of the ',' is not 100%
3854 reliable. should fix it to avoid security
3855 problems */
3856 if (gnu_ext && s->type.t &&
3857 last_tok == TOK_TWOSHARPS &&
3858 str.len >= 2 && str.str[str.len - 2] == ',') {
3859 if (*st == 0) {
3860 /* suppress ',' '##' */
3861 str.len -= 2;
3862 } else {
3863 /* suppress '##' and add variable */
3864 str.len--;
3865 goto add_var;
3867 } else {
3868 int t1;
3869 add_var:
3870 for(;;) {
3871 TOK_GET(t1, st, cval);
3872 if (!t1)
3873 break;
3874 tok_str_add2(&str, t1, &cval);
3877 } else {
3878 /* NOTE: the stream cannot be read when macro
3879 substituing an argument */
3880 macro_subst(&str, nested_list, st, 0);
3882 } else {
3883 tok_str_add(&str, t);
3885 } else {
3886 tok_str_add2(&str, t, &cval);
3888 last_tok = t;
3890 tok_str_add(&str, 0);
3891 return str.str;
3894 static char const ab_month_name[12][4] =
3896 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3897 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3900 /* do macro substitution of current token with macro 's' and add
3901 result to (tok_str,tok_len). 'nested_list' is the list of all
3902 macros we got inside to avoid recursing. Return non zero if no
3903 substitution needs to be done */
3904 static int macro_subst_tok(TokenString *tok_str,
3905 Sym **nested_list, Sym *s, int can_read_stream)
3907 Sym *args, *sa, *sa1;
3908 int mstr_allocated, parlevel, *mstr, t, t1;
3909 TokenString str;
3910 char *cstrval;
3911 CValue cval;
3912 CString cstr;
3913 char buf[32];
3915 /* if symbol is a macro, prepare substitution */
3916 /* special macros */
3917 if (tok == TOK___LINE__) {
3918 snprintf(buf, sizeof(buf), "%d", file->line_num);
3919 cstrval = buf;
3920 t1 = TOK_PPNUM;
3921 goto add_cstr1;
3922 } else if (tok == TOK___FILE__) {
3923 cstrval = file->filename;
3924 goto add_cstr;
3925 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3926 time_t ti;
3927 struct tm *tm;
3929 time(&ti);
3930 tm = localtime(&ti);
3931 if (tok == TOK___DATE__) {
3932 snprintf(buf, sizeof(buf), "%s %2d %d",
3933 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3934 } else {
3935 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3936 tm->tm_hour, tm->tm_min, tm->tm_sec);
3938 cstrval = buf;
3939 add_cstr:
3940 t1 = TOK_STR;
3941 add_cstr1:
3942 cstr_new(&cstr);
3943 cstr_cat(&cstr, cstrval);
3944 cstr_ccat(&cstr, '\0');
3945 cval.cstr = &cstr;
3946 tok_str_add2(tok_str, t1, &cval);
3947 cstr_free(&cstr);
3948 } else {
3949 mstr = (int *)s->c;
3950 mstr_allocated = 0;
3951 if (s->type.t == MACRO_FUNC) {
3952 /* NOTE: we do not use next_nomacro to avoid eating the
3953 next token. XXX: find better solution */
3954 if (macro_ptr) {
3955 t = *macro_ptr;
3956 if (t == 0 && can_read_stream) {
3957 /* end of macro stream: we must look at the token
3958 after in the file */
3959 macro_ptr = NULL;
3960 goto parse_stream;
3962 } else {
3963 parse_stream:
3964 /* XXX: incorrect with comments */
3965 ch = file->buf_ptr[0];
3966 while (is_space(ch) || ch == '\n')
3967 cinp();
3968 t = ch;
3970 if (t != '(') /* no macro subst */
3971 return -1;
3973 /* argument macro */
3974 next_nomacro();
3975 next_nomacro();
3976 args = NULL;
3977 sa = s->next;
3978 /* NOTE: empty args are allowed, except if no args */
3979 for(;;) {
3980 /* handle '()' case */
3981 if (!args && !sa && tok == ')')
3982 break;
3983 if (!sa)
3984 error("macro '%s' used with too many args",
3985 get_tok_str(s->v, 0));
3986 tok_str_new(&str);
3987 parlevel = 0;
3988 /* NOTE: non zero sa->t indicates VA_ARGS */
3989 while ((parlevel > 0 ||
3990 (tok != ')' &&
3991 (tok != ',' || sa->type.t))) &&
3992 tok != -1) {
3993 if (tok == '(')
3994 parlevel++;
3995 else if (tok == ')')
3996 parlevel--;
3997 tok_str_add2(&str, tok, &tokc);
3998 next_nomacro();
4000 tok_str_add(&str, 0);
4001 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4002 sa = sa->next;
4003 if (tok == ')') {
4004 /* special case for gcc var args: add an empty
4005 var arg argument if it is omitted */
4006 if (sa && sa->type.t && gnu_ext)
4007 continue;
4008 else
4009 break;
4011 if (tok != ',')
4012 expect(",");
4013 next_nomacro();
4015 if (sa) {
4016 error("macro '%s' used with too few args",
4017 get_tok_str(s->v, 0));
4020 /* now subst each arg */
4021 mstr = macro_arg_subst(nested_list, mstr, args);
4022 /* free memory */
4023 sa = args;
4024 while (sa) {
4025 sa1 = sa->prev;
4026 tok_str_free((int *)sa->c);
4027 sym_free(sa);
4028 sa = sa1;
4030 mstr_allocated = 1;
4032 sym_push2(nested_list, s->v, 0, 0);
4033 macro_subst(tok_str, nested_list, mstr, 1);
4034 /* pop nested defined symbol */
4035 sa1 = *nested_list;
4036 *nested_list = sa1->prev;
4037 sym_free(sa1);
4038 if (mstr_allocated)
4039 tok_str_free(mstr);
4041 return 0;
4044 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4045 return the resulting string (which must be freed). */
4046 static inline int *macro_twosharps(const int *macro_str)
4048 TokenSym *ts;
4049 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4050 int t;
4051 const char *p1, *p2;
4052 CValue cval;
4053 TokenString macro_str1;
4054 CString cstr;
4056 start_macro_ptr = macro_str;
4057 /* we search the first '##' */
4058 for(;;) {
4059 macro_ptr1 = macro_str;
4060 TOK_GET(t, macro_str, cval);
4061 /* nothing more to do if end of string */
4062 if (t == 0)
4063 return NULL;
4064 if (*macro_str == TOK_TWOSHARPS)
4065 break;
4068 /* we saw '##', so we need more processing to handle it */
4069 cstr_new(&cstr);
4070 tok_str_new(&macro_str1);
4071 tok = t;
4072 tokc = cval;
4074 /* add all tokens seen so far */
4075 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4076 TOK_GET(t, ptr, cval);
4077 tok_str_add2(&macro_str1, t, &cval);
4079 saved_macro_ptr = macro_ptr;
4080 /* XXX: get rid of the use of macro_ptr here */
4081 macro_ptr = (int *)macro_str;
4082 for(;;) {
4083 while (*macro_ptr == TOK_TWOSHARPS) {
4084 macro_ptr++;
4085 macro_ptr1 = macro_ptr;
4086 t = *macro_ptr;
4087 if (t) {
4088 TOK_GET(t, macro_ptr, cval);
4089 /* We concatenate the two tokens if we have an
4090 identifier or a preprocessing number */
4091 cstr_reset(&cstr);
4092 p1 = get_tok_str(tok, &tokc);
4093 cstr_cat(&cstr, p1);
4094 p2 = get_tok_str(t, &cval);
4095 cstr_cat(&cstr, p2);
4096 cstr_ccat(&cstr, '\0');
4098 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4099 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4100 if (tok == TOK_PPNUM) {
4101 /* if number, then create a number token */
4102 /* NOTE: no need to allocate because
4103 tok_str_add2() does it */
4104 tokc.cstr = &cstr;
4105 } else {
4106 /* if identifier, we must do a test to
4107 validate we have a correct identifier */
4108 if (t == TOK_PPNUM) {
4109 const char *p;
4110 int c;
4112 p = p2;
4113 for(;;) {
4114 c = *p;
4115 if (c == '\0')
4116 break;
4117 p++;
4118 if (!isnum(c) && !isid(c))
4119 goto error_pasting;
4122 ts = tok_alloc(cstr.data, strlen(cstr.data));
4123 tok = ts->tok; /* modify current token */
4125 } else {
4126 const char *str = cstr.data;
4127 const unsigned char *q;
4129 /* we look for a valid token */
4130 /* XXX: do more extensive checks */
4131 if (!strcmp(str, ">>=")) {
4132 tok = TOK_A_SAR;
4133 } else if (!strcmp(str, "<<=")) {
4134 tok = TOK_A_SHL;
4135 } else if (strlen(str) == 2) {
4136 /* search in two bytes table */
4137 q = tok_two_chars;
4138 for(;;) {
4139 if (!*q)
4140 goto error_pasting;
4141 if (q[0] == str[0] && q[1] == str[1])
4142 break;
4143 q += 3;
4145 tok = q[2];
4146 } else {
4147 error_pasting:
4148 /* NOTE: because get_tok_str use a static buffer,
4149 we must save it */
4150 cstr_reset(&cstr);
4151 p1 = get_tok_str(tok, &tokc);
4152 cstr_cat(&cstr, p1);
4153 cstr_ccat(&cstr, '\0');
4154 p2 = get_tok_str(t, &cval);
4155 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4156 /* cannot merge tokens: just add them separately */
4157 tok_str_add2(&macro_str1, tok, &tokc);
4158 /* XXX: free associated memory ? */
4159 tok = t;
4160 tokc = cval;
4165 tok_str_add2(&macro_str1, tok, &tokc);
4166 next_nomacro();
4167 if (tok == 0)
4168 break;
4170 macro_ptr = (int *)saved_macro_ptr;
4171 cstr_free(&cstr);
4172 tok_str_add(&macro_str1, 0);
4173 return macro_str1.str;
4177 /* do macro substitution of macro_str and add result to
4178 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4179 inside to avoid recursing. */
4180 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4181 const int *macro_str, int can_read_stream)
4183 Sym *s;
4184 int *saved_macro_ptr, *macro_str1;
4185 const int *ptr;
4186 int t, ret;
4187 CValue cval;
4189 /* first scan for '##' operator handling */
4190 ptr = macro_str;
4191 macro_str1 = macro_twosharps(ptr);
4192 if (macro_str1)
4193 ptr = macro_str1;
4194 while (1) {
4195 /* NOTE: ptr == NULL can only happen if tokens are read from
4196 file stream due to a macro function call */
4197 if (ptr == NULL)
4198 break;
4199 TOK_GET(t, ptr, cval);
4200 if (t == 0)
4201 break;
4202 s = define_find(t);
4203 if (s != NULL) {
4204 /* if nested substitution, do nothing */
4205 if (sym_find2(*nested_list, t))
4206 goto no_subst;
4207 saved_macro_ptr = macro_ptr;
4208 macro_ptr = (int *)ptr;
4209 tok = t;
4210 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4211 ptr = (int *)macro_ptr;
4212 macro_ptr = saved_macro_ptr;
4213 if (ret != 0)
4214 goto no_subst;
4215 } else {
4216 no_subst:
4217 tok_str_add2(tok_str, t, &cval);
4220 if (macro_str1)
4221 tok_str_free(macro_str1);
4224 /* return next token with macro substitution */
4225 static void next(void)
4227 Sym *nested_list, *s;
4228 TokenString str;
4230 redo:
4231 next_nomacro();
4232 if (!macro_ptr) {
4233 /* if not reading from macro substituted string, then try
4234 to substitute macros */
4235 if (tok >= TOK_IDENT &&
4236 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4237 s = define_find(tok);
4238 if (s) {
4239 /* we have a macro: we try to substitute */
4240 tok_str_new(&str);
4241 nested_list = NULL;
4242 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4243 /* substitution done, NOTE: maybe empty */
4244 tok_str_add(&str, 0);
4245 macro_ptr = str.str;
4246 macro_ptr_allocated = str.str;
4247 goto redo;
4251 } else {
4252 if (tok == 0) {
4253 /* end of macro or end of unget buffer */
4254 if (unget_buffer_enabled) {
4255 macro_ptr = unget_saved_macro_ptr;
4256 unget_buffer_enabled = 0;
4257 } else {
4258 /* end of macro string: free it */
4259 tok_str_free(macro_ptr_allocated);
4260 macro_ptr = NULL;
4262 goto redo;
4266 /* convert preprocessor tokens into C tokens */
4267 if (tok == TOK_PPNUM &&
4268 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4269 parse_number((char *)tokc.cstr->data);
4273 /* push back current token and set current token to 'last_tok'. Only
4274 identifier case handled for labels. */
4275 static inline void unget_tok(int last_tok)
4277 int i, n;
4278 int *q;
4279 unget_saved_macro_ptr = macro_ptr;
4280 unget_buffer_enabled = 1;
4281 q = unget_saved_buffer;
4282 macro_ptr = q;
4283 *q++ = tok;
4284 n = tok_ext_size(tok) - 1;
4285 for(i=0;i<n;i++)
4286 *q++ = tokc.tab[i];
4287 *q = 0; /* end of token string */
4288 tok = last_tok;
4292 void swap(int *p, int *q)
4294 int t;
4295 t = *p;
4296 *p = *q;
4297 *q = t;
4300 void vsetc(CType *type, int r, CValue *vc)
4302 int v;
4304 if (vtop >= vstack + (VSTACK_SIZE - 1))
4305 error("memory full");
4306 /* cannot let cpu flags if other instruction are generated. Also
4307 avoid leaving VT_JMP anywhere except on the top of the stack
4308 because it would complicate the code generator. */
4309 if (vtop >= vstack) {
4310 v = vtop->r & VT_VALMASK;
4311 if (v == VT_CMP || (v & ~1) == VT_JMP)
4312 gv(RC_INT);
4314 vtop++;
4315 vtop->type = *type;
4316 vtop->r = r;
4317 vtop->r2 = VT_CONST;
4318 vtop->c = *vc;
4321 /* push integer constant */
4322 void vpushi(int v)
4324 CValue cval;
4325 cval.i = v;
4326 vsetc(&int_type, VT_CONST, &cval);
4329 /* Return a static symbol pointing to a section */
4330 static Sym *get_sym_ref(CType *type, Section *sec,
4331 unsigned long offset, unsigned long size)
4333 int v;
4334 Sym *sym;
4336 v = anon_sym++;
4337 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4338 sym->type.ref = type->ref;
4339 sym->r = VT_CONST | VT_SYM;
4340 put_extern_sym(sym, sec, offset, size);
4341 return sym;
4344 /* push a reference to a section offset by adding a dummy symbol */
4345 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4347 CValue cval;
4349 cval.ul = 0;
4350 vsetc(type, VT_CONST | VT_SYM, &cval);
4351 vtop->sym = get_sym_ref(type, sec, offset, size);
4354 /* define a new external reference to a symbol 'v' of type 'u' */
4355 static Sym *external_global_sym(int v, CType *type, int r)
4357 Sym *s;
4359 s = sym_find(v);
4360 if (!s) {
4361 /* push forward reference */
4362 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4363 s->type.ref = type->ref;
4364 s->r = r | VT_CONST | VT_SYM;
4366 return s;
4369 /* define a new external reference to a symbol 'v' of type 'u' */
4370 static Sym *external_sym(int v, CType *type, int r)
4372 Sym *s;
4374 s = sym_find(v);
4375 if (!s) {
4376 /* push forward reference */
4377 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4378 s->type.t |= VT_EXTERN;
4379 } else {
4380 if (!is_compatible_types(&s->type, type))
4381 error("incompatible types for redefinition of '%s'",
4382 get_tok_str(v, NULL));
4384 return s;
4387 /* push a reference to global symbol v */
4388 static void vpush_global_sym(CType *type, int v)
4390 Sym *sym;
4391 CValue cval;
4393 sym = external_global_sym(v, type, 0);
4394 cval.ul = 0;
4395 vsetc(type, VT_CONST | VT_SYM, &cval);
4396 vtop->sym = sym;
4399 void vset(CType *type, int r, int v)
4401 CValue cval;
4403 cval.i = v;
4404 vsetc(type, r, &cval);
4407 void vseti(int r, int v)
4409 CType type;
4410 type.t = VT_INT;
4411 vset(&type, r, v);
4414 void vswap(void)
4416 SValue tmp;
4418 tmp = vtop[0];
4419 vtop[0] = vtop[-1];
4420 vtop[-1] = tmp;
4423 void vpushv(SValue *v)
4425 if (vtop >= vstack + (VSTACK_SIZE - 1))
4426 error("memory full");
4427 vtop++;
4428 *vtop = *v;
4431 void vdup(void)
4433 vpushv(vtop);
4436 /* save r to the memory stack, and mark it as being free */
4437 void save_reg(int r)
4439 int l, saved, size, align;
4440 SValue *p, sv;
4441 CType *type;
4443 /* modify all stack values */
4444 saved = 0;
4445 l = 0;
4446 for(p=vstack;p<=vtop;p++) {
4447 if ((p->r & VT_VALMASK) == r ||
4448 (p->r2 & VT_VALMASK) == r) {
4449 /* must save value on stack if not already done */
4450 if (!saved) {
4451 /* NOTE: must reload 'r' because r might be equal to r2 */
4452 r = p->r & VT_VALMASK;
4453 /* store register in the stack */
4454 type = &p->type;
4455 if ((p->r & VT_LVAL) ||
4456 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4457 type = &int_type;
4458 size = type_size(type, &align);
4459 loc = (loc - size) & -align;
4460 sv.type.t = type->t;
4461 sv.r = VT_LOCAL | VT_LVAL;
4462 sv.c.ul = loc;
4463 store(r, &sv);
4464 #ifdef TCC_TARGET_I386
4465 /* x86 specific: need to pop fp register ST0 if saved */
4466 if (r == TREG_ST0) {
4467 o(0xd9dd); /* fstp %st(1) */
4469 #endif
4470 /* special long long case */
4471 if ((type->t & VT_BTYPE) == VT_LLONG) {
4472 sv.c.ul += 4;
4473 store(p->r2, &sv);
4475 l = loc;
4476 saved = 1;
4478 /* mark that stack entry as being saved on the stack */
4479 if (p->r & VT_LVAL) {
4480 /* also clear the bounded flag because the
4481 relocation address of the function was stored in
4482 p->c.ul */
4483 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4484 } else {
4485 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4487 p->r2 = VT_CONST;
4488 p->c.ul = l;
4493 /* find a register of class 'rc2' with at most one reference on stack.
4494 * If none, call get_reg(rc) */
4495 int get_reg_ex(int rc, int rc2)
4497 int r;
4498 SValue *p;
4500 for(r=0;r<NB_REGS;r++) {
4501 if (reg_classes[r] & rc2) {
4502 int n;
4503 n=0;
4504 for(p = vstack; p <= vtop; p++) {
4505 if ((p->r & VT_VALMASK) == r ||
4506 (p->r2 & VT_VALMASK) == r)
4507 n++;
4509 if (n <= 1)
4510 return r;
4513 return get_reg(rc);
4516 /* find a free register of class 'rc'. If none, save one register */
4517 int get_reg(int rc)
4519 int r;
4520 SValue *p;
4522 /* find a free register */
4523 for(r=0;r<NB_REGS;r++) {
4524 if (reg_classes[r] & rc) {
4525 for(p=vstack;p<=vtop;p++) {
4526 if ((p->r & VT_VALMASK) == r ||
4527 (p->r2 & VT_VALMASK) == r)
4528 goto notfound;
4530 return r;
4532 notfound: ;
4535 /* no register left : free the first one on the stack (VERY
4536 IMPORTANT to start from the bottom to ensure that we don't
4537 spill registers used in gen_opi()) */
4538 for(p=vstack;p<=vtop;p++) {
4539 r = p->r & VT_VALMASK;
4540 if (r < VT_CONST && (reg_classes[r] & rc))
4541 goto save_found;
4542 /* also look at second register (if long long) */
4543 r = p->r2 & VT_VALMASK;
4544 if (r < VT_CONST && (reg_classes[r] & rc)) {
4545 save_found:
4546 save_reg(r);
4547 return r;
4550 /* Should never comes here */
4551 return -1;
4554 /* save registers up to (vtop - n) stack entry */
4555 void save_regs(int n)
4557 int r;
4558 SValue *p, *p1;
4559 p1 = vtop - n;
4560 for(p = vstack;p <= p1; p++) {
4561 r = p->r & VT_VALMASK;
4562 if (r < VT_CONST) {
4563 save_reg(r);
4568 /* move register 's' to 'r', and flush previous value of r to memory
4569 if needed */
4570 void move_reg(int r, int s)
4572 SValue sv;
4574 if (r != s) {
4575 save_reg(r);
4576 sv.type.t = VT_INT;
4577 sv.r = s;
4578 sv.c.ul = 0;
4579 load(r, &sv);
4583 /* get address of vtop (vtop MUST BE an lvalue) */
4584 void gaddrof(void)
4586 vtop->r &= ~VT_LVAL;
4587 /* tricky: if saved lvalue, then we can go back to lvalue */
4588 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4589 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4592 #ifdef CONFIG_TCC_BCHECK
4593 /* generate lvalue bound code */
4594 void gbound(void)
4596 int lval_type;
4597 CType type1;
4599 vtop->r &= ~VT_MUSTBOUND;
4600 /* if lvalue, then use checking code before dereferencing */
4601 if (vtop->r & VT_LVAL) {
4602 /* if not VT_BOUNDED value, then make one */
4603 if (!(vtop->r & VT_BOUNDED)) {
4604 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4605 /* must save type because we must set it to int to get pointer */
4606 type1 = vtop->type;
4607 vtop->type.t = VT_INT;
4608 gaddrof();
4609 vpushi(0);
4610 gen_bounded_ptr_add();
4611 vtop->r |= lval_type;
4612 vtop->type = type1;
4614 /* then check for dereferencing */
4615 gen_bounded_ptr_deref();
4618 #endif
4620 /* store vtop a register belonging to class 'rc'. lvalues are
4621 converted to values. Cannot be used if cannot be converted to
4622 register value (such as structures). */
4623 int gv(int rc)
4625 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4626 unsigned long long ll;
4628 /* NOTE: get_reg can modify vstack[] */
4629 if (vtop->type.t & VT_BITFIELD) {
4630 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4631 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4632 /* remove bit field info to avoid loops */
4633 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4634 /* generate shifts */
4635 vpushi(32 - (bit_pos + bit_size));
4636 gen_op(TOK_SHL);
4637 vpushi(32 - bit_size);
4638 /* NOTE: transformed to SHR if unsigned */
4639 gen_op(TOK_SAR);
4640 r = gv(rc);
4641 } else {
4642 if (is_float(vtop->type.t) &&
4643 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4644 Sym *sym;
4645 int *ptr;
4646 unsigned long offset;
4648 /* XXX: unify with initializers handling ? */
4649 /* CPUs usually cannot use float constants, so we store them
4650 generically in data segment */
4651 size = type_size(&vtop->type, &align);
4652 offset = (data_section->data_offset + align - 1) & -align;
4653 data_section->data_offset = offset;
4654 /* XXX: not portable yet */
4655 ptr = section_ptr_add(data_section, size);
4656 size = size >> 2;
4657 for(i=0;i<size;i++)
4658 ptr[i] = vtop->c.tab[i];
4659 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4660 vtop->r |= VT_LVAL | VT_SYM;
4661 vtop->sym = sym;
4662 vtop->c.ul = 0;
4664 #ifdef CONFIG_TCC_BCHECK
4665 if (vtop->r & VT_MUSTBOUND)
4666 gbound();
4667 #endif
4669 r = vtop->r & VT_VALMASK;
4670 /* need to reload if:
4671 - constant
4672 - lvalue (need to dereference pointer)
4673 - already a register, but not in the right class */
4674 if (r >= VT_CONST ||
4675 (vtop->r & VT_LVAL) ||
4676 !(reg_classes[r] & rc) ||
4677 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4678 !(reg_classes[vtop->r2] & rc))) {
4679 r = get_reg(rc);
4680 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4681 /* two register type load : expand to two words
4682 temporarily */
4683 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4684 /* load constant */
4685 ll = vtop->c.ull;
4686 vtop->c.ui = ll; /* first word */
4687 load(r, vtop);
4688 vtop->r = r; /* save register value */
4689 vpushi(ll >> 32); /* second word */
4690 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4691 (vtop->r & VT_LVAL)) {
4692 /* We do not want to modifier the long long
4693 pointer here, so the safest (and less
4694 efficient) is to save all the other registers
4695 in the stack. XXX: totally inefficient. */
4696 save_regs(1);
4697 /* load from memory */
4698 load(r, vtop);
4699 vdup();
4700 vtop[-1].r = r; /* save register value */
4701 /* increment pointer to get second word */
4702 vtop->type.t = VT_INT;
4703 gaddrof();
4704 vpushi(4);
4705 gen_op('+');
4706 vtop->r |= VT_LVAL;
4707 } else {
4708 /* move registers */
4709 load(r, vtop);
4710 vdup();
4711 vtop[-1].r = r; /* save register value */
4712 vtop->r = vtop[-1].r2;
4714 /* allocate second register */
4715 rc2 = RC_INT;
4716 if (rc == RC_IRET)
4717 rc2 = RC_LRET;
4718 r2 = get_reg(rc2);
4719 load(r2, vtop);
4720 vpop();
4721 /* write second register */
4722 vtop->r2 = r2;
4723 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4724 int t1, t;
4725 /* lvalue of scalar type : need to use lvalue type
4726 because of possible cast */
4727 t = vtop->type.t;
4728 t1 = t;
4729 /* compute memory access type */
4730 if (vtop->r & VT_LVAL_BYTE)
4731 t = VT_BYTE;
4732 else if (vtop->r & VT_LVAL_SHORT)
4733 t = VT_SHORT;
4734 if (vtop->r & VT_LVAL_UNSIGNED)
4735 t |= VT_UNSIGNED;
4736 vtop->type.t = t;
4737 load(r, vtop);
4738 /* restore wanted type */
4739 vtop->type.t = t1;
4740 } else {
4741 /* one register type load */
4742 load(r, vtop);
4745 vtop->r = r;
4746 #ifdef TCC_TARGET_C67
4747 /* uses register pairs for doubles */
4748 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4749 vtop->r2 = r+1;
4750 #endif
4752 return r;
4755 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4756 void gv2(int rc1, int rc2)
4758 int v;
4760 /* generate more generic register first. But VT_JMP or VT_CMP
4761 values must be generated first in all cases to avoid possible
4762 reload errors */
4763 v = vtop[0].r & VT_VALMASK;
4764 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4765 vswap();
4766 gv(rc1);
4767 vswap();
4768 gv(rc2);
4769 /* test if reload is needed for first register */
4770 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4771 vswap();
4772 gv(rc1);
4773 vswap();
4775 } else {
4776 gv(rc2);
4777 vswap();
4778 gv(rc1);
4779 vswap();
4780 /* test if reload is needed for first register */
4781 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4782 gv(rc2);
4787 /* expand long long on stack in two int registers */
4788 void lexpand(void)
4790 int u;
4792 u = vtop->type.t & VT_UNSIGNED;
4793 gv(RC_INT);
4794 vdup();
4795 vtop[0].r = vtop[-1].r2;
4796 vtop[0].r2 = VT_CONST;
4797 vtop[-1].r2 = VT_CONST;
4798 vtop[0].type.t = VT_INT | u;
4799 vtop[-1].type.t = VT_INT | u;
4802 #ifdef TCC_TARGET_ARM
4803 /* expand long long on stack */
4804 void lexpand_nr(void)
4806 int u,v;
4808 u = vtop->type.t & VT_UNSIGNED;
4809 vdup();
4810 vtop->r2 = VT_CONST;
4811 vtop->type.t = VT_INT | u;
4812 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4813 if (v == VT_CONST) {
4814 vtop[-1].c.ui = vtop->c.ull;
4815 vtop->c.ui = vtop->c.ull >> 32;
4816 vtop->r = VT_CONST;
4817 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4818 vtop->c.ui += 4;
4819 vtop->r = vtop[-1].r;
4820 } else if (v > VT_CONST) {
4821 vtop--;
4822 lexpand();
4823 } else
4824 vtop->r = vtop[-1].r2;
4825 vtop[-1].r2 = VT_CONST;
4826 vtop[-1].type.t = VT_INT | u;
4828 #endif
4830 /* build a long long from two ints */
4831 void lbuild(int t)
4833 gv2(RC_INT, RC_INT);
4834 vtop[-1].r2 = vtop[0].r;
4835 vtop[-1].type.t = t;
4836 vpop();
4839 /* rotate n first stack elements to the bottom
4840 I1 ... In -> I2 ... In I1 [top is right]
4842 void vrotb(int n)
4844 int i;
4845 SValue tmp;
4847 tmp = vtop[-n + 1];
4848 for(i=-n+1;i!=0;i++)
4849 vtop[i] = vtop[i+1];
4850 vtop[0] = tmp;
4853 /* rotate n first stack elements to the top
4854 I1 ... In -> In I1 ... I(n-1) [top is right]
4856 void vrott(int n)
4858 int i;
4859 SValue tmp;
4861 tmp = vtop[0];
4862 for(i = 0;i < n - 1; i++)
4863 vtop[-i] = vtop[-i - 1];
4864 vtop[-n + 1] = tmp;
4867 #ifdef TCC_TARGET_ARM
4868 /* like vrott but in other direction
4869 In ... I1 -> I(n-1) ... I1 In [top is right]
4871 void vnrott(int n)
4873 int i;
4874 SValue tmp;
4876 tmp = vtop[-n + 1];
4877 for(i = n - 1; i > 0; i--)
4878 vtop[-i] = vtop[-i + 1];
4879 vtop[0] = tmp;
4881 #endif
4883 /* pop stack value */
4884 void vpop(void)
4886 int v;
4887 v = vtop->r & VT_VALMASK;
4888 #ifdef TCC_TARGET_I386
4889 /* for x86, we need to pop the FP stack */
4890 if (v == TREG_ST0 && !nocode_wanted) {
4891 o(0xd9dd); /* fstp %st(1) */
4892 } else
4893 #endif
4894 if (v == VT_JMP || v == VT_JMPI) {
4895 /* need to put correct jump if && or || without test */
4896 gsym(vtop->c.ul);
4898 vtop--;
4901 /* convert stack entry to register and duplicate its value in another
4902 register */
4903 void gv_dup(void)
4905 int rc, t, r, r1;
4906 SValue sv;
4908 t = vtop->type.t;
4909 if ((t & VT_BTYPE) == VT_LLONG) {
4910 lexpand();
4911 gv_dup();
4912 vswap();
4913 vrotb(3);
4914 gv_dup();
4915 vrotb(4);
4916 /* stack: H L L1 H1 */
4917 lbuild(t);
4918 vrotb(3);
4919 vrotb(3);
4920 vswap();
4921 lbuild(t);
4922 vswap();
4923 } else {
4924 /* duplicate value */
4925 rc = RC_INT;
4926 sv.type.t = VT_INT;
4927 if (is_float(t)) {
4928 rc = RC_FLOAT;
4929 sv.type.t = t;
4931 r = gv(rc);
4932 r1 = get_reg(rc);
4933 sv.r = r;
4934 sv.c.ul = 0;
4935 load(r1, &sv); /* move r to r1 */
4936 vdup();
4937 /* duplicates value */
4938 vtop->r = r1;
4942 /* generate CPU independent (unsigned) long long operations */
4943 void gen_opl(int op)
4945 int t, a, b, op1, c, i;
4946 int func;
4947 SValue tmp;
4949 switch(op) {
4950 case '/':
4951 case TOK_PDIV:
4952 func = TOK___divdi3;
4953 goto gen_func;
4954 case TOK_UDIV:
4955 func = TOK___udivdi3;
4956 goto gen_func;
4957 case '%':
4958 func = TOK___moddi3;
4959 goto gen_func;
4960 case TOK_UMOD:
4961 func = TOK___umoddi3;
4962 gen_func:
4963 /* call generic long long function */
4964 vpush_global_sym(&func_old_type, func);
4965 vrott(3);
4966 gfunc_call(2);
4967 vpushi(0);
4968 vtop->r = REG_IRET;
4969 vtop->r2 = REG_LRET;
4970 break;
4971 case '^':
4972 case '&':
4973 case '|':
4974 case '*':
4975 case '+':
4976 case '-':
4977 t = vtop->type.t;
4978 vswap();
4979 lexpand();
4980 vrotb(3);
4981 lexpand();
4982 /* stack: L1 H1 L2 H2 */
4983 tmp = vtop[0];
4984 vtop[0] = vtop[-3];
4985 vtop[-3] = tmp;
4986 tmp = vtop[-2];
4987 vtop[-2] = vtop[-3];
4988 vtop[-3] = tmp;
4989 vswap();
4990 /* stack: H1 H2 L1 L2 */
4991 if (op == '*') {
4992 vpushv(vtop - 1);
4993 vpushv(vtop - 1);
4994 gen_op(TOK_UMULL);
4995 lexpand();
4996 /* stack: H1 H2 L1 L2 ML MH */
4997 for(i=0;i<4;i++)
4998 vrotb(6);
4999 /* stack: ML MH H1 H2 L1 L2 */
5000 tmp = vtop[0];
5001 vtop[0] = vtop[-2];
5002 vtop[-2] = tmp;
5003 /* stack: ML MH H1 L2 H2 L1 */
5004 gen_op('*');
5005 vrotb(3);
5006 vrotb(3);
5007 gen_op('*');
5008 /* stack: ML MH M1 M2 */
5009 gen_op('+');
5010 gen_op('+');
5011 } else if (op == '+' || op == '-') {
5012 /* XXX: add non carry method too (for MIPS or alpha) */
5013 if (op == '+')
5014 op1 = TOK_ADDC1;
5015 else
5016 op1 = TOK_SUBC1;
5017 gen_op(op1);
5018 /* stack: H1 H2 (L1 op L2) */
5019 vrotb(3);
5020 vrotb(3);
5021 gen_op(op1 + 1); /* TOK_xxxC2 */
5022 } else {
5023 gen_op(op);
5024 /* stack: H1 H2 (L1 op L2) */
5025 vrotb(3);
5026 vrotb(3);
5027 /* stack: (L1 op L2) H1 H2 */
5028 gen_op(op);
5029 /* stack: (L1 op L2) (H1 op H2) */
5031 /* stack: L H */
5032 lbuild(t);
5033 break;
5034 case TOK_SAR:
5035 case TOK_SHR:
5036 case TOK_SHL:
5037 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5038 t = vtop[-1].type.t;
5039 vswap();
5040 lexpand();
5041 vrotb(3);
5042 /* stack: L H shift */
5043 c = (int)vtop->c.i;
5044 /* constant: simpler */
5045 /* NOTE: all comments are for SHL. the other cases are
5046 done by swaping words */
5047 vpop();
5048 if (op != TOK_SHL)
5049 vswap();
5050 if (c >= 32) {
5051 /* stack: L H */
5052 vpop();
5053 if (c > 32) {
5054 vpushi(c - 32);
5055 gen_op(op);
5057 if (op != TOK_SAR) {
5058 vpushi(0);
5059 } else {
5060 gv_dup();
5061 vpushi(31);
5062 gen_op(TOK_SAR);
5064 vswap();
5065 } else {
5066 vswap();
5067 gv_dup();
5068 /* stack: H L L */
5069 vpushi(c);
5070 gen_op(op);
5071 vswap();
5072 vpushi(32 - c);
5073 if (op == TOK_SHL)
5074 gen_op(TOK_SHR);
5075 else
5076 gen_op(TOK_SHL);
5077 vrotb(3);
5078 /* stack: L L H */
5079 vpushi(c);
5080 if (op == TOK_SHL)
5081 gen_op(TOK_SHL);
5082 else
5083 gen_op(TOK_SHR);
5084 gen_op('|');
5086 if (op != TOK_SHL)
5087 vswap();
5088 lbuild(t);
5089 } else {
5090 /* XXX: should provide a faster fallback on x86 ? */
5091 switch(op) {
5092 case TOK_SAR:
5093 func = TOK___sardi3;
5094 goto gen_func;
5095 case TOK_SHR:
5096 func = TOK___shrdi3;
5097 goto gen_func;
5098 case TOK_SHL:
5099 func = TOK___shldi3;
5100 goto gen_func;
5103 break;
5104 default:
5105 /* compare operations */
5106 t = vtop->type.t;
5107 vswap();
5108 lexpand();
5109 vrotb(3);
5110 lexpand();
5111 /* stack: L1 H1 L2 H2 */
5112 tmp = vtop[-1];
5113 vtop[-1] = vtop[-2];
5114 vtop[-2] = tmp;
5115 /* stack: L1 L2 H1 H2 */
5116 /* compare high */
5117 op1 = op;
5118 /* when values are equal, we need to compare low words. since
5119 the jump is inverted, we invert the test too. */
5120 if (op1 == TOK_LT)
5121 op1 = TOK_LE;
5122 else if (op1 == TOK_GT)
5123 op1 = TOK_GE;
5124 else if (op1 == TOK_ULT)
5125 op1 = TOK_ULE;
5126 else if (op1 == TOK_UGT)
5127 op1 = TOK_UGE;
5128 a = 0;
5129 b = 0;
5130 gen_op(op1);
5131 if (op1 != TOK_NE) {
5132 a = gtst(1, 0);
5134 if (op != TOK_EQ) {
5135 /* generate non equal test */
5136 /* XXX: NOT PORTABLE yet */
5137 if (a == 0) {
5138 b = gtst(0, 0);
5139 } else {
5140 #if defined(TCC_TARGET_I386)
5141 b = psym(0x850f, 0);
5142 #elif defined(TCC_TARGET_ARM)
5143 b = ind;
5144 o(0x1A000000 | encbranch(ind, 0, 1));
5145 #elif defined(TCC_TARGET_C67)
5146 error("not implemented");
5147 #else
5148 #error not supported
5149 #endif
5152 /* compare low. Always unsigned */
5153 op1 = op;
5154 if (op1 == TOK_LT)
5155 op1 = TOK_ULT;
5156 else if (op1 == TOK_LE)
5157 op1 = TOK_ULE;
5158 else if (op1 == TOK_GT)
5159 op1 = TOK_UGT;
5160 else if (op1 == TOK_GE)
5161 op1 = TOK_UGE;
5162 gen_op(op1);
5163 a = gtst(1, a);
5164 gsym(b);
5165 vseti(VT_JMPI, a);
5166 break;
5170 /* handle integer constant optimizations and various machine
5171 independent opt */
5172 void gen_opic(int op)
5174 int fc, c1, c2, n;
5175 SValue *v1, *v2;
5177 v1 = vtop - 1;
5178 v2 = vtop;
5179 /* currently, we cannot do computations with forward symbols */
5180 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5181 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5182 if (c1 && c2) {
5183 fc = v2->c.i;
5184 switch(op) {
5185 case '+': v1->c.i += fc; break;
5186 case '-': v1->c.i -= fc; break;
5187 case '&': v1->c.i &= fc; break;
5188 case '^': v1->c.i ^= fc; break;
5189 case '|': v1->c.i |= fc; break;
5190 case '*': v1->c.i *= fc; break;
5192 case TOK_PDIV:
5193 case '/':
5194 case '%':
5195 case TOK_UDIV:
5196 case TOK_UMOD:
5197 /* if division by zero, generate explicit division */
5198 if (fc == 0) {
5199 if (const_wanted)
5200 error("division by zero in constant");
5201 goto general_case;
5203 switch(op) {
5204 default: v1->c.i /= fc; break;
5205 case '%': v1->c.i %= fc; break;
5206 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5207 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5209 break;
5210 case TOK_SHL: v1->c.i <<= fc; break;
5211 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5212 case TOK_SAR: v1->c.i >>= fc; break;
5213 /* tests */
5214 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5215 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5216 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5217 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5218 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5219 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5220 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5221 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5222 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5223 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5224 /* logical */
5225 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5226 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5227 default:
5228 goto general_case;
5230 vtop--;
5231 } else {
5232 /* if commutative ops, put c2 as constant */
5233 if (c1 && (op == '+' || op == '&' || op == '^' ||
5234 op == '|' || op == '*')) {
5235 vswap();
5236 swap(&c1, &c2);
5238 fc = vtop->c.i;
5239 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5240 op == TOK_PDIV) &&
5241 fc == 1) ||
5242 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5243 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5244 fc == 0) ||
5245 (op == '&' &&
5246 fc == -1))) {
5247 /* nothing to do */
5248 vtop--;
5249 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5250 /* try to use shifts instead of muls or divs */
5251 if (fc > 0 && (fc & (fc - 1)) == 0) {
5252 n = -1;
5253 while (fc) {
5254 fc >>= 1;
5255 n++;
5257 vtop->c.i = n;
5258 if (op == '*')
5259 op = TOK_SHL;
5260 else if (op == TOK_PDIV)
5261 op = TOK_SAR;
5262 else
5263 op = TOK_SHR;
5265 goto general_case;
5266 } else if (c2 && (op == '+' || op == '-') &&
5267 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5268 (VT_CONST | VT_SYM)) {
5269 /* symbol + constant case */
5270 if (op == '-')
5271 fc = -fc;
5272 vtop--;
5273 vtop->c.i += fc;
5274 } else {
5275 general_case:
5276 if (!nocode_wanted) {
5277 /* call low level op generator */
5278 gen_opi(op);
5279 } else {
5280 vtop--;
5286 /* generate a floating point operation with constant propagation */
5287 void gen_opif(int op)
5289 int c1, c2;
5290 SValue *v1, *v2;
5291 long double f1, f2;
5293 v1 = vtop - 1;
5294 v2 = vtop;
5295 /* currently, we cannot do computations with forward symbols */
5296 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5297 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5298 if (c1 && c2) {
5299 if (v1->type.t == VT_FLOAT) {
5300 f1 = v1->c.f;
5301 f2 = v2->c.f;
5302 } else if (v1->type.t == VT_DOUBLE) {
5303 f1 = v1->c.d;
5304 f2 = v2->c.d;
5305 } else {
5306 f1 = v1->c.ld;
5307 f2 = v2->c.ld;
5310 /* NOTE: we only do constant propagation if finite number (not
5311 NaN or infinity) (ANSI spec) */
5312 if (!ieee_finite(f1) || !ieee_finite(f2))
5313 goto general_case;
5315 switch(op) {
5316 case '+': f1 += f2; break;
5317 case '-': f1 -= f2; break;
5318 case '*': f1 *= f2; break;
5319 case '/':
5320 if (f2 == 0.0) {
5321 if (const_wanted)
5322 error("division by zero in constant");
5323 goto general_case;
5325 f1 /= f2;
5326 break;
5327 /* XXX: also handles tests ? */
5328 default:
5329 goto general_case;
5331 /* XXX: overflow test ? */
5332 if (v1->type.t == VT_FLOAT) {
5333 v1->c.f = f1;
5334 } else if (v1->type.t == VT_DOUBLE) {
5335 v1->c.d = f1;
5336 } else {
5337 v1->c.ld = f1;
5339 vtop--;
5340 } else {
5341 general_case:
5342 if (!nocode_wanted) {
5343 gen_opf(op);
5344 } else {
5345 vtop--;
5350 static int pointed_size(CType *type)
5352 int align;
5353 return type_size(pointed_type(type), &align);
5356 static inline int is_null_pointer(SValue *p)
5358 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5359 return 0;
5360 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5361 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5364 static inline int is_integer_btype(int bt)
5366 return (bt == VT_BYTE || bt == VT_SHORT ||
5367 bt == VT_INT || bt == VT_LLONG);
5370 /* check types for comparison or substraction of pointers */
5371 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5373 CType *type1, *type2, tmp_type1, tmp_type2;
5374 int bt1, bt2;
5376 /* null pointers are accepted for all comparisons as gcc */
5377 if (is_null_pointer(p1) || is_null_pointer(p2))
5378 return;
5379 type1 = &p1->type;
5380 type2 = &p2->type;
5381 bt1 = type1->t & VT_BTYPE;
5382 bt2 = type2->t & VT_BTYPE;
5383 /* accept comparison between pointer and integer with a warning */
5384 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5385 warning("comparison between pointer and integer");
5386 return;
5389 /* both must be pointers or implicit function pointers */
5390 if (bt1 == VT_PTR) {
5391 type1 = pointed_type(type1);
5392 } else if (bt1 != VT_FUNC)
5393 goto invalid_operands;
5395 if (bt2 == VT_PTR) {
5396 type2 = pointed_type(type2);
5397 } else if (bt2 != VT_FUNC) {
5398 invalid_operands:
5399 error("invalid operands to binary %s", get_tok_str(op, NULL));
5401 if ((type1->t & VT_BTYPE) == VT_VOID ||
5402 (type2->t & VT_BTYPE) == VT_VOID)
5403 return;
5404 tmp_type1 = *type1;
5405 tmp_type2 = *type2;
5406 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5407 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5408 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5409 /* gcc-like error if '-' is used */
5410 if (op == '-')
5411 goto invalid_operands;
5412 else
5413 warning("comparison of distinct pointer types lacks a cast");
5417 /* generic gen_op: handles types problems */
5418 void gen_op(int op)
5420 int u, t1, t2, bt1, bt2, t;
5421 CType type1;
5423 t1 = vtop[-1].type.t;
5424 t2 = vtop[0].type.t;
5425 bt1 = t1 & VT_BTYPE;
5426 bt2 = t2 & VT_BTYPE;
5428 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5429 /* at least one operand is a pointer */
5430 /* relationnal op: must be both pointers */
5431 if (op >= TOK_ULT && op <= TOK_GT) {
5432 check_comparison_pointer_types(vtop - 1, vtop, op);
5433 /* pointers are handled are unsigned */
5434 t = VT_INT | VT_UNSIGNED;
5435 goto std_op;
5437 /* if both pointers, then it must be the '-' op */
5438 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5439 if (op != '-')
5440 error("cannot use pointers here");
5441 check_comparison_pointer_types(vtop - 1, vtop, op);
5442 /* XXX: check that types are compatible */
5443 u = pointed_size(&vtop[-1].type);
5444 gen_opic(op);
5445 /* set to integer type */
5446 vtop->type.t = VT_INT;
5447 vpushi(u);
5448 gen_op(TOK_PDIV);
5449 } else {
5450 /* exactly one pointer : must be '+' or '-'. */
5451 if (op != '-' && op != '+')
5452 error("cannot use pointers here");
5453 /* Put pointer as first operand */
5454 if (bt2 == VT_PTR) {
5455 vswap();
5456 swap(&t1, &t2);
5458 type1 = vtop[-1].type;
5459 /* XXX: cast to int ? (long long case) */
5460 vpushi(pointed_size(&vtop[-1].type));
5461 gen_op('*');
5462 #ifdef CONFIG_TCC_BCHECK
5463 /* if evaluating constant expression, no code should be
5464 generated, so no bound check */
5465 if (do_bounds_check && !const_wanted) {
5466 /* if bounded pointers, we generate a special code to
5467 test bounds */
5468 if (op == '-') {
5469 vpushi(0);
5470 vswap();
5471 gen_op('-');
5473 gen_bounded_ptr_add();
5474 } else
5475 #endif
5477 gen_opic(op);
5479 /* put again type if gen_opic() swaped operands */
5480 vtop->type = type1;
5482 } else if (is_float(bt1) || is_float(bt2)) {
5483 /* compute bigger type and do implicit casts */
5484 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5485 t = VT_LDOUBLE;
5486 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5487 t = VT_DOUBLE;
5488 } else {
5489 t = VT_FLOAT;
5491 /* floats can only be used for a few operations */
5492 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5493 (op < TOK_ULT || op > TOK_GT))
5494 error("invalid operands for binary operation");
5495 goto std_op;
5496 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5497 /* cast to biggest op */
5498 t = VT_LLONG;
5499 /* convert to unsigned if it does not fit in a long long */
5500 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5501 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5502 t |= VT_UNSIGNED;
5503 goto std_op;
5504 } else {
5505 /* integer operations */
5506 t = VT_INT;
5507 /* convert to unsigned if it does not fit in an integer */
5508 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5509 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5510 t |= VT_UNSIGNED;
5511 std_op:
5512 /* XXX: currently, some unsigned operations are explicit, so
5513 we modify them here */
5514 if (t & VT_UNSIGNED) {
5515 if (op == TOK_SAR)
5516 op = TOK_SHR;
5517 else if (op == '/')
5518 op = TOK_UDIV;
5519 else if (op == '%')
5520 op = TOK_UMOD;
5521 else if (op == TOK_LT)
5522 op = TOK_ULT;
5523 else if (op == TOK_GT)
5524 op = TOK_UGT;
5525 else if (op == TOK_LE)
5526 op = TOK_ULE;
5527 else if (op == TOK_GE)
5528 op = TOK_UGE;
5530 vswap();
5531 type1.t = t;
5532 gen_cast(&type1);
5533 vswap();
5534 /* special case for shifts and long long: we keep the shift as
5535 an integer */
5536 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5537 type1.t = VT_INT;
5538 gen_cast(&type1);
5539 if (is_float(t))
5540 gen_opif(op);
5541 else if ((t & VT_BTYPE) == VT_LLONG)
5542 gen_opl(op);
5543 else
5544 gen_opic(op);
5545 if (op >= TOK_ULT && op <= TOK_GT) {
5546 /* relationnal op: the result is an int */
5547 vtop->type.t = VT_INT;
5548 } else {
5549 vtop->type.t = t;
5554 /* generic itof for unsigned long long case */
5555 void gen_cvt_itof1(int t)
5557 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5558 (VT_LLONG | VT_UNSIGNED)) {
5560 if (t == VT_FLOAT)
5561 vpush_global_sym(&func_old_type, TOK___ulltof);
5562 else if (t == VT_DOUBLE)
5563 vpush_global_sym(&func_old_type, TOK___ulltod);
5564 else
5565 vpush_global_sym(&func_old_type, TOK___ulltold);
5566 vrott(2);
5567 gfunc_call(1);
5568 vpushi(0);
5569 vtop->r = REG_FRET;
5570 } else {
5571 gen_cvt_itof(t);
5575 /* generic ftoi for unsigned long long case */
5576 void gen_cvt_ftoi1(int t)
5578 int st;
5580 if (t == (VT_LLONG | VT_UNSIGNED)) {
5581 /* not handled natively */
5582 st = vtop->type.t & VT_BTYPE;
5583 if (st == VT_FLOAT)
5584 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5585 else if (st == VT_DOUBLE)
5586 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5587 else
5588 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5589 vrott(2);
5590 gfunc_call(1);
5591 vpushi(0);
5592 vtop->r = REG_IRET;
5593 vtop->r2 = REG_LRET;
5594 } else {
5595 gen_cvt_ftoi(t);
5599 /* force char or short cast */
5600 void force_charshort_cast(int t)
5602 int bits, dbt;
5603 dbt = t & VT_BTYPE;
5604 /* XXX: add optimization if lvalue : just change type and offset */
5605 if (dbt == VT_BYTE)
5606 bits = 8;
5607 else
5608 bits = 16;
5609 if (t & VT_UNSIGNED) {
5610 vpushi((1 << bits) - 1);
5611 gen_op('&');
5612 } else {
5613 bits = 32 - bits;
5614 vpushi(bits);
5615 gen_op(TOK_SHL);
5616 vpushi(bits);
5617 gen_op(TOK_SAR);
5621 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5622 static void gen_cast(CType *type)
5624 int sbt, dbt, sf, df, c;
5626 /* special delayed cast for char/short */
5627 /* XXX: in some cases (multiple cascaded casts), it may still
5628 be incorrect */
5629 if (vtop->r & VT_MUSTCAST) {
5630 vtop->r &= ~VT_MUSTCAST;
5631 force_charshort_cast(vtop->type.t);
5634 /* bitfields first get cast to ints */
5635 if (vtop->type.t & VT_BITFIELD) {
5636 gv(RC_INT);
5639 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5640 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5642 if (sbt != dbt && !nocode_wanted) {
5643 sf = is_float(sbt);
5644 df = is_float(dbt);
5645 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5646 if (sf && df) {
5647 /* convert from fp to fp */
5648 if (c) {
5649 /* constant case: we can do it now */
5650 /* XXX: in ISOC, cannot do it if error in convert */
5651 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5652 vtop->c.f = (float)vtop->c.d;
5653 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5654 vtop->c.f = (float)vtop->c.ld;
5655 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5656 vtop->c.d = (double)vtop->c.f;
5657 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5658 vtop->c.d = (double)vtop->c.ld;
5659 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5660 vtop->c.ld = (long double)vtop->c.f;
5661 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5662 vtop->c.ld = (long double)vtop->c.d;
5663 } else {
5664 /* non constant case: generate code */
5665 gen_cvt_ftof(dbt);
5667 } else if (df) {
5668 /* convert int to fp */
5669 if (c) {
5670 switch(sbt) {
5671 case VT_LLONG | VT_UNSIGNED:
5672 case VT_LLONG:
5673 /* XXX: add const cases for long long */
5674 goto do_itof;
5675 case VT_INT | VT_UNSIGNED:
5676 switch(dbt) {
5677 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5678 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5679 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5681 break;
5682 default:
5683 switch(dbt) {
5684 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5685 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5686 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5688 break;
5690 } else {
5691 do_itof:
5692 #if !defined(TCC_TARGET_ARM)
5693 gen_cvt_itof1(dbt);
5694 #else
5695 gen_cvt_itof(dbt);
5696 #endif
5698 } else if (sf) {
5699 /* convert fp to int */
5700 /* we handle char/short/etc... with generic code */
5701 if (dbt != (VT_INT | VT_UNSIGNED) &&
5702 dbt != (VT_LLONG | VT_UNSIGNED) &&
5703 dbt != VT_LLONG)
5704 dbt = VT_INT;
5705 if (c) {
5706 switch(dbt) {
5707 case VT_LLONG | VT_UNSIGNED:
5708 case VT_LLONG:
5709 /* XXX: add const cases for long long */
5710 goto do_ftoi;
5711 case VT_INT | VT_UNSIGNED:
5712 switch(sbt) {
5713 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5714 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5715 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5717 break;
5718 default:
5719 /* int case */
5720 switch(sbt) {
5721 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5722 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5723 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5725 break;
5727 } else {
5728 do_ftoi:
5729 gen_cvt_ftoi1(dbt);
5731 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5732 /* additional cast for char/short/bool... */
5733 vtop->type.t = dbt;
5734 gen_cast(type);
5736 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5737 if ((sbt & VT_BTYPE) != VT_LLONG) {
5738 /* scalar to long long */
5739 if (c) {
5740 if (sbt == (VT_INT | VT_UNSIGNED))
5741 vtop->c.ll = vtop->c.ui;
5742 else
5743 vtop->c.ll = vtop->c.i;
5744 } else {
5745 /* machine independent conversion */
5746 gv(RC_INT);
5747 /* generate high word */
5748 if (sbt == (VT_INT | VT_UNSIGNED)) {
5749 vpushi(0);
5750 gv(RC_INT);
5751 } else {
5752 gv_dup();
5753 vpushi(31);
5754 gen_op(TOK_SAR);
5756 /* patch second register */
5757 vtop[-1].r2 = vtop->r;
5758 vpop();
5761 } else if (dbt == VT_BOOL) {
5762 /* scalar to bool */
5763 vpushi(0);
5764 gen_op(TOK_NE);
5765 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5766 (dbt & VT_BTYPE) == VT_SHORT) {
5767 force_charshort_cast(dbt);
5768 } else if ((dbt & VT_BTYPE) == VT_INT) {
5769 /* scalar to int */
5770 if (sbt == VT_LLONG) {
5771 /* from long long: just take low order word */
5772 lexpand();
5773 vpop();
5775 /* if lvalue and single word type, nothing to do because
5776 the lvalue already contains the real type size (see
5777 VT_LVAL_xxx constants) */
5780 vtop->type = *type;
5783 /* return type size. Put alignment at 'a' */
5784 static int type_size(CType *type, int *a)
5786 Sym *s;
5787 int bt;
5789 bt = type->t & VT_BTYPE;
5790 if (bt == VT_STRUCT) {
5791 /* struct/union */
5792 s = type->ref;
5793 *a = s->r;
5794 return s->c;
5795 } else if (bt == VT_PTR) {
5796 if (type->t & VT_ARRAY) {
5797 s = type->ref;
5798 return type_size(&s->type, a) * s->c;
5799 } else {
5800 *a = PTR_SIZE;
5801 return PTR_SIZE;
5803 } else if (bt == VT_LDOUBLE) {
5804 *a = LDOUBLE_ALIGN;
5805 return LDOUBLE_SIZE;
5806 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5807 #ifdef TCC_TARGET_I386
5808 *a = 4;
5809 #else
5810 *a = 8;
5811 #endif
5812 return 8;
5813 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5814 *a = 4;
5815 return 4;
5816 } else if (bt == VT_SHORT) {
5817 *a = 2;
5818 return 2;
5819 } else {
5820 /* char, void, function, _Bool */
5821 *a = 1;
5822 return 1;
5826 /* return the pointed type of t */
5827 static inline CType *pointed_type(CType *type)
5829 return &type->ref->type;
5832 /* modify type so that its it is a pointer to type. */
5833 static void mk_pointer(CType *type)
5835 Sym *s;
5836 s = sym_push(SYM_FIELD, type, 0, -1);
5837 type->t = VT_PTR | (type->t & ~VT_TYPE);
5838 type->ref = s;
5841 /* compare function types. OLD functions match any new functions */
5842 static int is_compatible_func(CType *type1, CType *type2)
5844 Sym *s1, *s2;
5846 s1 = type1->ref;
5847 s2 = type2->ref;
5848 if (!is_compatible_types(&s1->type, &s2->type))
5849 return 0;
5850 /* check func_call */
5851 if (s1->r != s2->r)
5852 return 0;
5853 /* XXX: not complete */
5854 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5855 return 1;
5856 if (s1->c != s2->c)
5857 return 0;
5858 while (s1 != NULL) {
5859 if (s2 == NULL)
5860 return 0;
5861 if (!is_compatible_types(&s1->type, &s2->type))
5862 return 0;
5863 s1 = s1->next;
5864 s2 = s2->next;
5866 if (s2)
5867 return 0;
5868 return 1;
5871 /* return true if type1 and type2 are exactly the same (including
5872 qualifiers).
5874 - enums are not checked as gcc __builtin_types_compatible_p ()
5876 static int is_compatible_types(CType *type1, CType *type2)
5878 int bt1, t1, t2;
5880 t1 = type1->t & VT_TYPE;
5881 t2 = type2->t & VT_TYPE;
5882 /* XXX: bitfields ? */
5883 if (t1 != t2)
5884 return 0;
5885 /* test more complicated cases */
5886 bt1 = t1 & VT_BTYPE;
5887 if (bt1 == VT_PTR) {
5888 type1 = pointed_type(type1);
5889 type2 = pointed_type(type2);
5890 return is_compatible_types(type1, type2);
5891 } else if (bt1 == VT_STRUCT) {
5892 return (type1->ref == type2->ref);
5893 } else if (bt1 == VT_FUNC) {
5894 return is_compatible_func(type1, type2);
5895 } else {
5896 return 1;
5900 /* print a type. If 'varstr' is not NULL, then the variable is also
5901 printed in the type */
5902 /* XXX: union */
5903 /* XXX: add array and function pointers */
5904 void type_to_str(char *buf, int buf_size,
5905 CType *type, const char *varstr)
5907 int bt, v, t;
5908 Sym *s, *sa;
5909 char buf1[256];
5910 const char *tstr;
5912 t = type->t & VT_TYPE;
5913 bt = t & VT_BTYPE;
5914 buf[0] = '\0';
5915 if (t & VT_CONSTANT)
5916 pstrcat(buf, buf_size, "const ");
5917 if (t & VT_VOLATILE)
5918 pstrcat(buf, buf_size, "volatile ");
5919 if (t & VT_UNSIGNED)
5920 pstrcat(buf, buf_size, "unsigned ");
5921 switch(bt) {
5922 case VT_VOID:
5923 tstr = "void";
5924 goto add_tstr;
5925 case VT_BOOL:
5926 tstr = "_Bool";
5927 goto add_tstr;
5928 case VT_BYTE:
5929 tstr = "char";
5930 goto add_tstr;
5931 case VT_SHORT:
5932 tstr = "short";
5933 goto add_tstr;
5934 case VT_INT:
5935 tstr = "int";
5936 goto add_tstr;
5937 case VT_LONG:
5938 tstr = "long";
5939 goto add_tstr;
5940 case VT_LLONG:
5941 tstr = "long long";
5942 goto add_tstr;
5943 case VT_FLOAT:
5944 tstr = "float";
5945 goto add_tstr;
5946 case VT_DOUBLE:
5947 tstr = "double";
5948 goto add_tstr;
5949 case VT_LDOUBLE:
5950 tstr = "long double";
5951 add_tstr:
5952 pstrcat(buf, buf_size, tstr);
5953 break;
5954 case VT_ENUM:
5955 case VT_STRUCT:
5956 if (bt == VT_STRUCT)
5957 tstr = "struct ";
5958 else
5959 tstr = "enum ";
5960 pstrcat(buf, buf_size, tstr);
5961 v = type->ref->v & ~SYM_STRUCT;
5962 if (v >= SYM_FIRST_ANOM)
5963 pstrcat(buf, buf_size, "<anonymous>");
5964 else
5965 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5966 break;
5967 case VT_FUNC:
5968 s = type->ref;
5969 type_to_str(buf, buf_size, &s->type, varstr);
5970 pstrcat(buf, buf_size, "(");
5971 sa = s->next;
5972 while (sa != NULL) {
5973 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5974 pstrcat(buf, buf_size, buf1);
5975 sa = sa->next;
5976 if (sa)
5977 pstrcat(buf, buf_size, ", ");
5979 pstrcat(buf, buf_size, ")");
5980 goto no_var;
5981 case VT_PTR:
5982 s = type->ref;
5983 pstrcpy(buf1, sizeof(buf1), "*");
5984 if (varstr)
5985 pstrcat(buf1, sizeof(buf1), varstr);
5986 type_to_str(buf, buf_size, &s->type, buf1);
5987 goto no_var;
5989 if (varstr) {
5990 pstrcat(buf, buf_size, " ");
5991 pstrcat(buf, buf_size, varstr);
5993 no_var: ;
5996 /* verify type compatibility to store vtop in 'dt' type, and generate
5997 casts if needed. */
5998 static void gen_assign_cast(CType *dt)
6000 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6001 char buf1[256], buf2[256];
6002 int dbt, sbt;
6004 st = &vtop->type; /* source type */
6005 dbt = dt->t & VT_BTYPE;
6006 sbt = st->t & VT_BTYPE;
6007 if (dt->t & VT_CONSTANT)
6008 warning("assignment of read-only location");
6009 switch(dbt) {
6010 case VT_PTR:
6011 /* special cases for pointers */
6012 /* '0' can also be a pointer */
6013 if (is_null_pointer(vtop))
6014 goto type_ok;
6015 /* accept implicit pointer to integer cast with warning */
6016 if (is_integer_btype(sbt)) {
6017 warning("assignment makes pointer from integer without a cast");
6018 goto type_ok;
6020 type1 = pointed_type(dt);
6021 /* a function is implicitely a function pointer */
6022 if (sbt == VT_FUNC) {
6023 if ((type1->t & VT_BTYPE) != VT_VOID &&
6024 !is_compatible_types(pointed_type(dt), st))
6025 goto error;
6026 else
6027 goto type_ok;
6029 if (sbt != VT_PTR)
6030 goto error;
6031 type2 = pointed_type(st);
6032 if ((type1->t & VT_BTYPE) == VT_VOID ||
6033 (type2->t & VT_BTYPE) == VT_VOID) {
6034 /* void * can match anything */
6035 } else {
6036 /* exact type match, except for unsigned */
6037 tmp_type1 = *type1;
6038 tmp_type2 = *type2;
6039 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6040 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6041 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6042 goto error;
6044 /* check const and volatile */
6045 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6046 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6047 warning("assignment discards qualifiers from pointer target type");
6048 break;
6049 case VT_BYTE:
6050 case VT_SHORT:
6051 case VT_INT:
6052 case VT_LLONG:
6053 if (sbt == VT_PTR || sbt == VT_FUNC) {
6054 warning("assignment makes integer from pointer without a cast");
6056 /* XXX: more tests */
6057 break;
6058 case VT_STRUCT:
6059 tmp_type1 = *dt;
6060 tmp_type2 = *st;
6061 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6062 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6063 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6064 error:
6065 type_to_str(buf1, sizeof(buf1), st, NULL);
6066 type_to_str(buf2, sizeof(buf2), dt, NULL);
6067 error("cannot cast '%s' to '%s'", buf1, buf2);
6069 break;
6071 type_ok:
6072 gen_cast(dt);
6075 /* store vtop in lvalue pushed on stack */
6076 void vstore(void)
6078 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6080 ft = vtop[-1].type.t;
6081 sbt = vtop->type.t & VT_BTYPE;
6082 dbt = ft & VT_BTYPE;
6083 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6084 (sbt == VT_INT && dbt == VT_SHORT)) {
6085 /* optimize char/short casts */
6086 delayed_cast = VT_MUSTCAST;
6087 vtop->type.t = ft & VT_TYPE;
6088 /* XXX: factorize */
6089 if (ft & VT_CONSTANT)
6090 warning("assignment of read-only location");
6091 } else {
6092 delayed_cast = 0;
6093 if (!(ft & VT_BITFIELD))
6094 gen_assign_cast(&vtop[-1].type);
6097 if (sbt == VT_STRUCT) {
6098 /* if structure, only generate pointer */
6099 /* structure assignment : generate memcpy */
6100 /* XXX: optimize if small size */
6101 if (!nocode_wanted) {
6102 size = type_size(&vtop->type, &align);
6104 vpush_global_sym(&func_old_type, TOK_memcpy);
6106 /* destination */
6107 vpushv(vtop - 2);
6108 vtop->type.t = VT_INT;
6109 gaddrof();
6110 /* source */
6111 vpushv(vtop - 2);
6112 vtop->type.t = VT_INT;
6113 gaddrof();
6114 /* type size */
6115 vpushi(size);
6116 gfunc_call(3);
6118 vswap();
6119 vpop();
6120 } else {
6121 vswap();
6122 vpop();
6124 /* leave source on stack */
6125 } else if (ft & VT_BITFIELD) {
6126 /* bitfield store handling */
6127 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6128 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6129 /* remove bit field info to avoid loops */
6130 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6132 /* duplicate destination */
6133 vdup();
6134 vtop[-1] = vtop[-2];
6136 /* mask and shift source */
6137 vpushi((1 << bit_size) - 1);
6138 gen_op('&');
6139 vpushi(bit_pos);
6140 gen_op(TOK_SHL);
6141 /* load destination, mask and or with source */
6142 vswap();
6143 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6144 gen_op('&');
6145 gen_op('|');
6146 /* store result */
6147 vstore();
6148 } else {
6149 #ifdef CONFIG_TCC_BCHECK
6150 /* bound check case */
6151 if (vtop[-1].r & VT_MUSTBOUND) {
6152 vswap();
6153 gbound();
6154 vswap();
6156 #endif
6157 if (!nocode_wanted) {
6158 rc = RC_INT;
6159 if (is_float(ft))
6160 rc = RC_FLOAT;
6161 r = gv(rc); /* generate value */
6162 /* if lvalue was saved on stack, must read it */
6163 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6164 SValue sv;
6165 t = get_reg(RC_INT);
6166 sv.type.t = VT_INT;
6167 sv.r = VT_LOCAL | VT_LVAL;
6168 sv.c.ul = vtop[-1].c.ul;
6169 load(t, &sv);
6170 vtop[-1].r = t | VT_LVAL;
6172 store(r, vtop - 1);
6173 /* two word case handling : store second register at word + 4 */
6174 if ((ft & VT_BTYPE) == VT_LLONG) {
6175 vswap();
6176 /* convert to int to increment easily */
6177 vtop->type.t = VT_INT;
6178 gaddrof();
6179 vpushi(4);
6180 gen_op('+');
6181 vtop->r |= VT_LVAL;
6182 vswap();
6183 /* XXX: it works because r2 is spilled last ! */
6184 store(vtop->r2, vtop - 1);
6187 vswap();
6188 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6189 vtop->r |= delayed_cast;
6193 /* post defines POST/PRE add. c is the token ++ or -- */
6194 void inc(int post, int c)
6196 test_lvalue();
6197 vdup(); /* save lvalue */
6198 if (post) {
6199 gv_dup(); /* duplicate value */
6200 vrotb(3);
6201 vrotb(3);
6203 /* add constant */
6204 vpushi(c - TOK_MID);
6205 gen_op('+');
6206 vstore(); /* store value */
6207 if (post)
6208 vpop(); /* if post op, return saved value */
6211 /* Parse GNUC __attribute__ extension. Currently, the following
6212 extensions are recognized:
6213 - aligned(n) : set data/function alignment.
6214 - packed : force data alignment to 1
6215 - section(x) : generate data/code in this section.
6216 - unused : currently ignored, but may be used someday.
6217 - regparm(n) : pass function parameters in registers (i386 only)
6219 static void parse_attribute(AttributeDef *ad)
6221 int t, n;
6223 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6224 next();
6225 skip('(');
6226 skip('(');
6227 while (tok != ')') {
6228 if (tok < TOK_IDENT)
6229 expect("attribute name");
6230 t = tok;
6231 next();
6232 switch(t) {
6233 case TOK_SECTION1:
6234 case TOK_SECTION2:
6235 skip('(');
6236 if (tok != TOK_STR)
6237 expect("section name");
6238 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6239 next();
6240 skip(')');
6241 break;
6242 case TOK_ALIGNED1:
6243 case TOK_ALIGNED2:
6244 if (tok == '(') {
6245 next();
6246 n = expr_const();
6247 if (n <= 0 || (n & (n - 1)) != 0)
6248 error("alignment must be a positive power of two");
6249 skip(')');
6250 } else {
6251 n = MAX_ALIGN;
6253 ad->aligned = n;
6254 break;
6255 case TOK_PACKED1:
6256 case TOK_PACKED2:
6257 ad->packed = 1;
6258 break;
6259 case TOK_UNUSED1:
6260 case TOK_UNUSED2:
6261 /* currently, no need to handle it because tcc does not
6262 track unused objects */
6263 break;
6264 case TOK_NORETURN1:
6265 case TOK_NORETURN2:
6266 /* currently, no need to handle it because tcc does not
6267 track unused objects */
6268 break;
6269 case TOK_CDECL1:
6270 case TOK_CDECL2:
6271 case TOK_CDECL3:
6272 ad->func_call = FUNC_CDECL;
6273 break;
6274 case TOK_STDCALL1:
6275 case TOK_STDCALL2:
6276 case TOK_STDCALL3:
6277 ad->func_call = FUNC_STDCALL;
6278 break;
6279 #ifdef TCC_TARGET_I386
6280 case TOK_REGPARM1:
6281 case TOK_REGPARM2:
6282 skip('(');
6283 n = expr_const();
6284 if (n > 3)
6285 n = 3;
6286 else if (n < 0)
6287 n = 0;
6288 if (n > 0)
6289 ad->func_call = FUNC_FASTCALL1 + n - 1;
6290 skip(')');
6291 break;
6292 #endif
6293 default:
6294 if (tcc_state->warn_unsupported)
6295 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6296 /* skip parameters */
6297 /* XXX: skip parenthesis too */
6298 if (tok == '(') {
6299 next();
6300 while (tok != ')' && tok != -1)
6301 next();
6302 next();
6304 break;
6306 if (tok != ',')
6307 break;
6308 next();
6310 skip(')');
6311 skip(')');
6315 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6316 static void struct_decl(CType *type, int u)
6318 int a, v, size, align, maxalign, c, offset;
6319 int bit_size, bit_pos, bsize, bt, lbit_pos;
6320 Sym *s, *ss, **ps;
6321 AttributeDef ad;
6322 CType type1, btype;
6324 a = tok; /* save decl type */
6325 next();
6326 if (tok != '{') {
6327 v = tok;
6328 next();
6329 /* struct already defined ? return it */
6330 if (v < TOK_IDENT)
6331 expect("struct/union/enum name");
6332 s = struct_find(v);
6333 if (s) {
6334 if (s->type.t != a)
6335 error("invalid type");
6336 goto do_decl;
6338 } else {
6339 v = anon_sym++;
6341 type1.t = a;
6342 /* we put an undefined size for struct/union */
6343 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6344 s->r = 0; /* default alignment is zero as gcc */
6345 /* put struct/union/enum name in type */
6346 do_decl:
6347 type->t = u;
6348 type->ref = s;
6350 if (tok == '{') {
6351 next();
6352 if (s->c != -1)
6353 error("struct/union/enum already defined");
6354 /* cannot be empty */
6355 c = 0;
6356 /* non empty enums are not allowed */
6357 if (a == TOK_ENUM) {
6358 for(;;) {
6359 v = tok;
6360 if (v < TOK_UIDENT)
6361 expect("identifier");
6362 next();
6363 if (tok == '=') {
6364 next();
6365 c = expr_const();
6367 /* enum symbols have static storage */
6368 ss = sym_push(v, &int_type, VT_CONST, c);
6369 ss->type.t |= VT_STATIC;
6370 if (tok != ',')
6371 break;
6372 next();
6373 c++;
6374 /* NOTE: we accept a trailing comma */
6375 if (tok == '}')
6376 break;
6378 skip('}');
6379 } else {
6380 maxalign = 1;
6381 ps = &s->next;
6382 bit_pos = 0;
6383 offset = 0;
6384 while (tok != '}') {
6385 parse_btype(&btype, &ad);
6386 while (1) {
6387 bit_size = -1;
6388 v = 0;
6389 type1 = btype;
6390 if (tok != ':') {
6391 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6392 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6393 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6394 error("invalid type for '%s'",
6395 get_tok_str(v, NULL));
6397 if (tok == ':') {
6398 next();
6399 bit_size = expr_const();
6400 /* XXX: handle v = 0 case for messages */
6401 if (bit_size < 0)
6402 error("negative width in bit-field '%s'",
6403 get_tok_str(v, NULL));
6404 if (v && bit_size == 0)
6405 error("zero width for bit-field '%s'",
6406 get_tok_str(v, NULL));
6408 size = type_size(&type1, &align);
6409 if (ad.aligned) {
6410 if (align < ad.aligned)
6411 align = ad.aligned;
6412 } else if (ad.packed) {
6413 align = 1;
6415 lbit_pos = 0;
6416 if (bit_size >= 0) {
6417 bt = type1.t & VT_BTYPE;
6418 if (bt != VT_INT &&
6419 bt != VT_BYTE &&
6420 bt != VT_SHORT &&
6421 bt != VT_BOOL &&
6422 bt != VT_ENUM)
6423 error("bitfields must have scalar type");
6424 bsize = size * 8;
6425 if (bit_size > bsize) {
6426 error("width of '%s' exceeds its type",
6427 get_tok_str(v, NULL));
6428 } else if (bit_size == bsize) {
6429 /* no need for bit fields */
6430 bit_pos = 0;
6431 } else if (bit_size == 0) {
6432 /* XXX: what to do if only padding in a
6433 structure ? */
6434 /* zero size: means to pad */
6435 if (bit_pos > 0)
6436 bit_pos = bsize;
6437 } else {
6438 /* we do not have enough room ? */
6439 if ((bit_pos + bit_size) > bsize)
6440 bit_pos = 0;
6441 lbit_pos = bit_pos;
6442 /* XXX: handle LSB first */
6443 type1.t |= VT_BITFIELD |
6444 (bit_pos << VT_STRUCT_SHIFT) |
6445 (bit_size << (VT_STRUCT_SHIFT + 6));
6446 bit_pos += bit_size;
6448 } else {
6449 bit_pos = 0;
6451 if (v) {
6452 /* add new memory data only if starting
6453 bit field */
6454 if (lbit_pos == 0) {
6455 if (a == TOK_STRUCT) {
6456 c = (c + align - 1) & -align;
6457 offset = c;
6458 c += size;
6459 } else {
6460 offset = 0;
6461 if (size > c)
6462 c = size;
6464 if (align > maxalign)
6465 maxalign = align;
6467 #if 0
6468 printf("add field %s offset=%d",
6469 get_tok_str(v, NULL), offset);
6470 if (type1.t & VT_BITFIELD) {
6471 printf(" pos=%d size=%d",
6472 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6473 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6475 printf("\n");
6476 #endif
6477 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6478 *ps = ss;
6479 ps = &ss->next;
6481 if (tok == ';' || tok == TOK_EOF)
6482 break;
6483 skip(',');
6485 skip(';');
6487 skip('}');
6488 /* store size and alignment */
6489 s->c = (c + maxalign - 1) & -maxalign;
6490 s->r = maxalign;
6495 /* return 0 if no type declaration. otherwise, return the basic type
6496 and skip it.
6498 static int parse_btype(CType *type, AttributeDef *ad)
6500 int t, u, type_found, typespec_found;
6501 Sym *s;
6502 CType type1;
6504 memset(ad, 0, sizeof(AttributeDef));
6505 type_found = 0;
6506 typespec_found = 0;
6507 t = 0;
6508 while(1) {
6509 switch(tok) {
6510 case TOK_EXTENSION:
6511 /* currently, we really ignore extension */
6512 next();
6513 continue;
6515 /* basic types */
6516 case TOK_CHAR:
6517 u = VT_BYTE;
6518 basic_type:
6519 next();
6520 basic_type1:
6521 if ((t & VT_BTYPE) != 0)
6522 error("too many basic types");
6523 t |= u;
6524 typespec_found = 1;
6525 break;
6526 case TOK_VOID:
6527 u = VT_VOID;
6528 goto basic_type;
6529 case TOK_SHORT:
6530 u = VT_SHORT;
6531 goto basic_type;
6532 case TOK_INT:
6533 next();
6534 typespec_found = 1;
6535 break;
6536 case TOK_LONG:
6537 next();
6538 if ((t & VT_BTYPE) == VT_DOUBLE) {
6539 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6540 } else if ((t & VT_BTYPE) == VT_LONG) {
6541 t = (t & ~VT_BTYPE) | VT_LLONG;
6542 } else {
6543 u = VT_LONG;
6544 goto basic_type1;
6546 break;
6547 case TOK_BOOL:
6548 u = VT_BOOL;
6549 goto basic_type;
6550 case TOK_FLOAT:
6551 u = VT_FLOAT;
6552 goto basic_type;
6553 case TOK_DOUBLE:
6554 next();
6555 if ((t & VT_BTYPE) == VT_LONG) {
6556 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6557 } else {
6558 u = VT_DOUBLE;
6559 goto basic_type1;
6561 break;
6562 case TOK_ENUM:
6563 struct_decl(&type1, VT_ENUM);
6564 basic_type2:
6565 u = type1.t;
6566 type->ref = type1.ref;
6567 goto basic_type1;
6568 case TOK_STRUCT:
6569 case TOK_UNION:
6570 struct_decl(&type1, VT_STRUCT);
6571 goto basic_type2;
6573 /* type modifiers */
6574 case TOK_CONST1:
6575 case TOK_CONST2:
6576 case TOK_CONST3:
6577 t |= VT_CONSTANT;
6578 next();
6579 break;
6580 case TOK_VOLATILE1:
6581 case TOK_VOLATILE2:
6582 case TOK_VOLATILE3:
6583 t |= VT_VOLATILE;
6584 next();
6585 break;
6586 case TOK_SIGNED1:
6587 case TOK_SIGNED2:
6588 case TOK_SIGNED3:
6589 typespec_found = 1;
6590 t |= VT_SIGNED;
6591 next();
6592 break;
6593 case TOK_REGISTER:
6594 case TOK_AUTO:
6595 case TOK_RESTRICT1:
6596 case TOK_RESTRICT2:
6597 case TOK_RESTRICT3:
6598 next();
6599 break;
6600 case TOK_UNSIGNED:
6601 t |= VT_UNSIGNED;
6602 next();
6603 typespec_found = 1;
6604 break;
6606 /* storage */
6607 case TOK_EXTERN:
6608 t |= VT_EXTERN;
6609 next();
6610 break;
6611 case TOK_STATIC:
6612 t |= VT_STATIC;
6613 next();
6614 break;
6615 case TOK_TYPEDEF:
6616 t |= VT_TYPEDEF;
6617 next();
6618 break;
6619 case TOK_INLINE1:
6620 case TOK_INLINE2:
6621 case TOK_INLINE3:
6622 t |= VT_INLINE;
6623 next();
6624 break;
6626 /* GNUC attribute */
6627 case TOK_ATTRIBUTE1:
6628 case TOK_ATTRIBUTE2:
6629 parse_attribute(ad);
6630 break;
6631 /* GNUC typeof */
6632 case TOK_TYPEOF1:
6633 case TOK_TYPEOF2:
6634 case TOK_TYPEOF3:
6635 next();
6636 parse_expr_type(&type1);
6637 goto basic_type2;
6638 default:
6639 if (typespec_found)
6640 goto the_end;
6641 s = sym_find(tok);
6642 if (!s || !(s->type.t & VT_TYPEDEF))
6643 goto the_end;
6644 t |= (s->type.t & ~VT_TYPEDEF);
6645 type->ref = s->type.ref;
6646 next();
6647 break;
6649 type_found = 1;
6651 the_end:
6652 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6653 error("signed and unsigned modifier");
6654 if (tcc_state->char_is_unsigned) {
6655 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6656 t |= VT_UNSIGNED;
6658 t &= ~VT_SIGNED;
6660 /* long is never used as type */
6661 if ((t & VT_BTYPE) == VT_LONG)
6662 t = (t & ~VT_BTYPE) | VT_INT;
6663 type->t = t;
6664 return type_found;
6667 /* convert a function parameter type (array to pointer and function to
6668 function pointer) */
6669 static inline void convert_parameter_type(CType *pt)
6671 /* remove const and volatile qualifiers (XXX: const could be used
6672 to indicate a const function parameter */
6673 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6674 /* array must be transformed to pointer according to ANSI C */
6675 pt->t &= ~VT_ARRAY;
6676 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6677 mk_pointer(pt);
6681 static void post_type(CType *type, AttributeDef *ad)
6683 int n, l, t1;
6684 Sym **plast, *s, *first;
6685 AttributeDef ad1;
6686 CType pt;
6688 if (tok == '(') {
6689 /* function declaration */
6690 next();
6691 l = 0;
6692 first = NULL;
6693 plast = &first;
6694 while (tok != ')') {
6695 /* read param name and compute offset */
6696 if (l != FUNC_OLD) {
6697 if (!parse_btype(&pt, &ad1)) {
6698 if (l) {
6699 error("invalid type");
6700 } else {
6701 l = FUNC_OLD;
6702 goto old_proto;
6705 l = FUNC_NEW;
6706 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6707 break;
6708 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6709 if ((pt.t & VT_BTYPE) == VT_VOID)
6710 error("parameter declared as void");
6711 } else {
6712 old_proto:
6713 n = tok;
6714 pt.t = VT_INT;
6715 next();
6717 convert_parameter_type(&pt);
6718 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6719 *plast = s;
6720 plast = &s->next;
6721 if (tok == ',') {
6722 next();
6723 if (l == FUNC_NEW && tok == TOK_DOTS) {
6724 l = FUNC_ELLIPSIS;
6725 next();
6726 break;
6730 /* if no parameters, then old type prototype */
6731 if (l == 0)
6732 l = FUNC_OLD;
6733 skip(')');
6734 t1 = type->t & VT_STORAGE;
6735 /* NOTE: const is ignored in returned type as it has a special
6736 meaning in gcc / C++ */
6737 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6738 post_type(type, ad);
6739 /* we push a anonymous symbol which will contain the function prototype */
6740 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6741 s->next = first;
6742 type->t = t1 | VT_FUNC;
6743 type->ref = s;
6744 } else if (tok == '[') {
6745 /* array definition */
6746 next();
6747 n = -1;
6748 if (tok != ']') {
6749 n = expr_const();
6750 if (n < 0)
6751 error("invalid array size");
6753 skip(']');
6754 /* parse next post type */
6755 t1 = type->t & VT_STORAGE;
6756 type->t &= ~VT_STORAGE;
6757 post_type(type, ad);
6759 /* we push a anonymous symbol which will contain the array
6760 element type */
6761 s = sym_push(SYM_FIELD, type, 0, n);
6762 type->t = t1 | VT_ARRAY | VT_PTR;
6763 type->ref = s;
6767 /* Parse a type declaration (except basic type), and return the type
6768 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6769 expected. 'type' should contain the basic type. 'ad' is the
6770 attribute definition of the basic type. It can be modified by
6771 type_decl().
6773 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6775 Sym *s;
6776 CType type1, *type2;
6777 int qualifiers;
6779 while (tok == '*') {
6780 qualifiers = 0;
6781 redo:
6782 next();
6783 switch(tok) {
6784 case TOK_CONST1:
6785 case TOK_CONST2:
6786 case TOK_CONST3:
6787 qualifiers |= VT_CONSTANT;
6788 goto redo;
6789 case TOK_VOLATILE1:
6790 case TOK_VOLATILE2:
6791 case TOK_VOLATILE3:
6792 qualifiers |= VT_VOLATILE;
6793 goto redo;
6794 case TOK_RESTRICT1:
6795 case TOK_RESTRICT2:
6796 case TOK_RESTRICT3:
6797 goto redo;
6799 mk_pointer(type);
6800 type->t |= qualifiers;
6803 /* XXX: clarify attribute handling */
6804 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6805 parse_attribute(ad);
6807 /* recursive type */
6808 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6809 type1.t = 0; /* XXX: same as int */
6810 if (tok == '(') {
6811 next();
6812 /* XXX: this is not correct to modify 'ad' at this point, but
6813 the syntax is not clear */
6814 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6815 parse_attribute(ad);
6816 type_decl(&type1, ad, v, td);
6817 skip(')');
6818 } else {
6819 /* type identifier */
6820 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6821 *v = tok;
6822 next();
6823 } else {
6824 if (!(td & TYPE_ABSTRACT))
6825 expect("identifier");
6826 *v = 0;
6829 post_type(type, ad);
6830 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6831 parse_attribute(ad);
6832 if (!type1.t)
6833 return;
6834 /* append type at the end of type1 */
6835 type2 = &type1;
6836 for(;;) {
6837 s = type2->ref;
6838 type2 = &s->type;
6839 if (!type2->t) {
6840 *type2 = *type;
6841 break;
6844 *type = type1;
6847 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6848 static int lvalue_type(int t)
6850 int bt, r;
6851 r = VT_LVAL;
6852 bt = t & VT_BTYPE;
6853 if (bt == VT_BYTE || bt == VT_BOOL)
6854 r |= VT_LVAL_BYTE;
6855 else if (bt == VT_SHORT)
6856 r |= VT_LVAL_SHORT;
6857 else
6858 return r;
6859 if (t & VT_UNSIGNED)
6860 r |= VT_LVAL_UNSIGNED;
6861 return r;
6864 /* indirection with full error checking and bound check */
6865 static void indir(void)
6867 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6868 expect("pointer");
6869 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6870 gv(RC_INT);
6871 vtop->type = *pointed_type(&vtop->type);
6872 /* an array is never an lvalue */
6873 if (!(vtop->type.t & VT_ARRAY)) {
6874 vtop->r |= lvalue_type(vtop->type.t);
6875 /* if bound checking, the referenced pointer must be checked */
6876 if (do_bounds_check)
6877 vtop->r |= VT_MUSTBOUND;
6881 /* pass a parameter to a function and do type checking and casting */
6882 static void gfunc_param_typed(Sym *func, Sym *arg)
6884 int func_type;
6885 CType type;
6887 func_type = func->c;
6888 if (func_type == FUNC_OLD ||
6889 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6890 /* default casting : only need to convert float to double */
6891 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6892 type.t = VT_DOUBLE;
6893 gen_cast(&type);
6895 } else if (arg == NULL) {
6896 error("too many arguments to function");
6897 } else {
6898 type = arg->type;
6899 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6900 gen_assign_cast(&type);
6904 /* parse an expression of the form '(type)' or '(expr)' and return its
6905 type */
6906 static void parse_expr_type(CType *type)
6908 int n;
6909 AttributeDef ad;
6911 skip('(');
6912 if (parse_btype(type, &ad)) {
6913 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6914 } else {
6915 expr_type(type);
6917 skip(')');
6920 static void parse_type(CType *type)
6922 AttributeDef ad;
6923 int n;
6925 if (!parse_btype(type, &ad)) {
6926 expect("type");
6928 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6931 static void vpush_tokc(int t)
6933 CType type;
6934 type.t = t;
6935 vsetc(&type, VT_CONST, &tokc);
6938 static void unary(void)
6940 int n, t, align, size, r;
6941 CType type;
6942 Sym *s;
6943 AttributeDef ad;
6945 /* XXX: GCC 2.95.3 does not generate a table although it should be
6946 better here */
6947 tok_next:
6948 switch(tok) {
6949 case TOK_EXTENSION:
6950 next();
6951 goto tok_next;
6952 case TOK_CINT:
6953 case TOK_CCHAR:
6954 case TOK_LCHAR:
6955 vpushi(tokc.i);
6956 next();
6957 break;
6958 case TOK_CUINT:
6959 vpush_tokc(VT_INT | VT_UNSIGNED);
6960 next();
6961 break;
6962 case TOK_CLLONG:
6963 vpush_tokc(VT_LLONG);
6964 next();
6965 break;
6966 case TOK_CULLONG:
6967 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6968 next();
6969 break;
6970 case TOK_CFLOAT:
6971 vpush_tokc(VT_FLOAT);
6972 next();
6973 break;
6974 case TOK_CDOUBLE:
6975 vpush_tokc(VT_DOUBLE);
6976 next();
6977 break;
6978 case TOK_CLDOUBLE:
6979 vpush_tokc(VT_LDOUBLE);
6980 next();
6981 break;
6982 case TOK___FUNCTION__:
6983 if (!gnu_ext)
6984 goto tok_identifier;
6985 /* fall thru */
6986 case TOK___FUNC__:
6988 void *ptr;
6989 int len;
6990 /* special function name identifier */
6991 len = strlen(funcname) + 1;
6992 /* generate char[len] type */
6993 type.t = VT_BYTE;
6994 mk_pointer(&type);
6995 type.t |= VT_ARRAY;
6996 type.ref->c = len;
6997 vpush_ref(&type, data_section, data_section->data_offset, len);
6998 ptr = section_ptr_add(data_section, len);
6999 memcpy(ptr, funcname, len);
7000 next();
7002 break;
7003 case TOK_LSTR:
7004 t = VT_INT;
7005 goto str_init;
7006 case TOK_STR:
7007 /* string parsing */
7008 t = VT_BYTE;
7009 str_init:
7010 if (tcc_state->warn_write_strings)
7011 t |= VT_CONSTANT;
7012 type.t = t;
7013 mk_pointer(&type);
7014 type.t |= VT_ARRAY;
7015 memset(&ad, 0, sizeof(AttributeDef));
7016 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7017 break;
7018 case '(':
7019 next();
7020 /* cast ? */
7021 if (parse_btype(&type, &ad)) {
7022 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7023 skip(')');
7024 /* check ISOC99 compound literal */
7025 if (tok == '{') {
7026 /* data is allocated locally by default */
7027 if (global_expr)
7028 r = VT_CONST;
7029 else
7030 r = VT_LOCAL;
7031 /* all except arrays are lvalues */
7032 if (!(type.t & VT_ARRAY))
7033 r |= lvalue_type(type.t);
7034 memset(&ad, 0, sizeof(AttributeDef));
7035 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7036 } else {
7037 unary();
7038 gen_cast(&type);
7040 } else if (tok == '{') {
7041 /* save all registers */
7042 save_regs(0);
7043 /* statement expression : we do not accept break/continue
7044 inside as GCC does */
7045 block(NULL, NULL, NULL, NULL, 0, 1);
7046 skip(')');
7047 } else {
7048 gexpr();
7049 skip(')');
7051 break;
7052 case '*':
7053 next();
7054 unary();
7055 indir();
7056 break;
7057 case '&':
7058 next();
7059 unary();
7060 /* functions names must be treated as function pointers,
7061 except for unary '&' and sizeof. Since we consider that
7062 functions are not lvalues, we only have to handle it
7063 there and in function calls. */
7064 /* arrays can also be used although they are not lvalues */
7065 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7066 !(vtop->type.t & VT_ARRAY))
7067 test_lvalue();
7068 mk_pointer(&vtop->type);
7069 gaddrof();
7070 break;
7071 case '!':
7072 next();
7073 unary();
7074 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7075 vtop->c.i = !vtop->c.i;
7076 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7077 vtop->c.i = vtop->c.i ^ 1;
7078 else
7079 vseti(VT_JMP, gtst(1, 0));
7080 break;
7081 case '~':
7082 next();
7083 unary();
7084 vpushi(-1);
7085 gen_op('^');
7086 break;
7087 case '+':
7088 next();
7089 /* in order to force cast, we add zero */
7090 unary();
7091 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7092 error("pointer not accepted for unary plus");
7093 vpushi(0);
7094 gen_op('+');
7095 break;
7096 case TOK_SIZEOF:
7097 case TOK_ALIGNOF1:
7098 case TOK_ALIGNOF2:
7099 t = tok;
7100 next();
7101 if (tok == '(') {
7102 parse_expr_type(&type);
7103 } else {
7104 unary_type(&type);
7106 size = type_size(&type, &align);
7107 if (t == TOK_SIZEOF) {
7108 if (size < 0)
7109 error("sizeof applied to an incomplete type");
7110 vpushi(size);
7111 } else {
7112 vpushi(align);
7114 break;
7116 case TOK_builtin_types_compatible_p:
7118 CType type1, type2;
7119 next();
7120 skip('(');
7121 parse_type(&type1);
7122 skip(',');
7123 parse_type(&type2);
7124 skip(')');
7125 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7126 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7127 vpushi(is_compatible_types(&type1, &type2));
7129 break;
7130 case TOK_builtin_constant_p:
7132 int saved_nocode_wanted, res;
7133 next();
7134 skip('(');
7135 saved_nocode_wanted = nocode_wanted;
7136 nocode_wanted = 1;
7137 gexpr();
7138 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7139 vpop();
7140 nocode_wanted = saved_nocode_wanted;
7141 skip(')');
7142 vpushi(res);
7144 break;
7145 case TOK_INC:
7146 case TOK_DEC:
7147 t = tok;
7148 next();
7149 unary();
7150 inc(0, t);
7151 break;
7152 case '-':
7153 next();
7154 vpushi(0);
7155 unary();
7156 gen_op('-');
7157 break;
7158 case TOK_LAND:
7159 if (!gnu_ext)
7160 goto tok_identifier;
7161 next();
7162 /* allow to take the address of a label */
7163 if (tok < TOK_UIDENT)
7164 expect("label identifier");
7165 s = label_find(tok);
7166 if (!s) {
7167 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7168 } else {
7169 if (s->r == LABEL_DECLARED)
7170 s->r = LABEL_FORWARD;
7172 if (!s->type.t) {
7173 s->type.t = VT_VOID;
7174 mk_pointer(&s->type);
7175 s->type.t |= VT_STATIC;
7177 vset(&s->type, VT_CONST | VT_SYM, 0);
7178 vtop->sym = s;
7179 next();
7180 break;
7181 default:
7182 tok_identifier:
7183 t = tok;
7184 next();
7185 if (t < TOK_UIDENT)
7186 expect("identifier");
7187 s = sym_find(t);
7188 if (!s) {
7189 if (tok != '(')
7190 error("'%s' undeclared", get_tok_str(t, NULL));
7191 /* for simple function calls, we tolerate undeclared
7192 external reference to int() function */
7193 if (tcc_state->warn_implicit_function_declaration)
7194 warning("implicit declaration of function '%s'",
7195 get_tok_str(t, NULL));
7196 s = external_global_sym(t, &func_old_type, 0);
7198 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7199 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7200 /* if referencing an inline function, then we generate a
7201 symbol to it if not already done. It will have the
7202 effect to generate code for it at the end of the
7203 compilation unit. Inline function as always
7204 generated in the text section. */
7205 if (!s->c)
7206 put_extern_sym(s, text_section, 0, 0);
7207 r = VT_SYM | VT_CONST;
7208 } else {
7209 r = s->r;
7211 vset(&s->type, r, s->c);
7212 /* if forward reference, we must point to s */
7213 if (vtop->r & VT_SYM) {
7214 vtop->sym = s;
7215 vtop->c.ul = 0;
7217 break;
7220 /* post operations */
7221 while (1) {
7222 if (tok == TOK_INC || tok == TOK_DEC) {
7223 inc(1, tok);
7224 next();
7225 } else if (tok == '.' || tok == TOK_ARROW) {
7226 /* field */
7227 if (tok == TOK_ARROW)
7228 indir();
7229 test_lvalue();
7230 gaddrof();
7231 next();
7232 /* expect pointer on structure */
7233 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7234 expect("struct or union");
7235 s = vtop->type.ref;
7236 /* find field */
7237 tok |= SYM_FIELD;
7238 while ((s = s->next) != NULL) {
7239 if (s->v == tok)
7240 break;
7242 if (!s)
7243 error("field not found");
7244 /* add field offset to pointer */
7245 vtop->type = char_pointer_type; /* change type to 'char *' */
7246 vpushi(s->c);
7247 gen_op('+');
7248 /* change type to field type, and set to lvalue */
7249 vtop->type = s->type;
7250 /* an array is never an lvalue */
7251 if (!(vtop->type.t & VT_ARRAY)) {
7252 vtop->r |= lvalue_type(vtop->type.t);
7253 /* if bound checking, the referenced pointer must be checked */
7254 if (do_bounds_check)
7255 vtop->r |= VT_MUSTBOUND;
7257 next();
7258 } else if (tok == '[') {
7259 next();
7260 gexpr();
7261 gen_op('+');
7262 indir();
7263 skip(']');
7264 } else if (tok == '(') {
7265 SValue ret;
7266 Sym *sa;
7267 int nb_args;
7269 /* function call */
7270 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7271 /* pointer test (no array accepted) */
7272 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7273 vtop->type = *pointed_type(&vtop->type);
7274 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7275 goto error_func;
7276 } else {
7277 error_func:
7278 expect("function pointer");
7280 } else {
7281 vtop->r &= ~VT_LVAL; /* no lvalue */
7283 /* get return type */
7284 s = vtop->type.ref;
7285 next();
7286 sa = s->next; /* first parameter */
7287 nb_args = 0;
7288 /* compute first implicit argument if a structure is returned */
7289 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7290 /* get some space for the returned structure */
7291 size = type_size(&s->type, &align);
7292 loc = (loc - size) & -align;
7293 ret.type = s->type;
7294 ret.r = VT_LOCAL | VT_LVAL;
7295 /* pass it as 'int' to avoid structure arg passing
7296 problems */
7297 vseti(VT_LOCAL, loc);
7298 ret.c = vtop->c;
7299 nb_args++;
7300 } else {
7301 ret.type = s->type;
7302 ret.r2 = VT_CONST;
7303 /* return in register */
7304 if (is_float(ret.type.t)) {
7305 ret.r = REG_FRET;
7306 } else {
7307 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7308 ret.r2 = REG_LRET;
7309 ret.r = REG_IRET;
7311 ret.c.i = 0;
7313 if (tok != ')') {
7314 for(;;) {
7315 expr_eq();
7316 gfunc_param_typed(s, sa);
7317 nb_args++;
7318 if (sa)
7319 sa = sa->next;
7320 if (tok == ')')
7321 break;
7322 skip(',');
7325 if (sa)
7326 error("too few arguments to function");
7327 skip(')');
7328 if (!nocode_wanted) {
7329 gfunc_call(nb_args);
7330 } else {
7331 vtop -= (nb_args + 1);
7333 /* return value */
7334 vsetc(&ret.type, ret.r, &ret.c);
7335 vtop->r2 = ret.r2;
7336 } else {
7337 break;
7342 static void uneq(void)
7344 int t;
7346 unary();
7347 if (tok == '=' ||
7348 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7349 tok == TOK_A_XOR || tok == TOK_A_OR ||
7350 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7351 test_lvalue();
7352 t = tok;
7353 next();
7354 if (t == '=') {
7355 expr_eq();
7356 } else {
7357 vdup();
7358 expr_eq();
7359 gen_op(t & 0x7f);
7361 vstore();
7365 static void expr_prod(void)
7367 int t;
7369 uneq();
7370 while (tok == '*' || tok == '/' || tok == '%') {
7371 t = tok;
7372 next();
7373 uneq();
7374 gen_op(t);
7378 static void expr_sum(void)
7380 int t;
7382 expr_prod();
7383 while (tok == '+' || tok == '-') {
7384 t = tok;
7385 next();
7386 expr_prod();
7387 gen_op(t);
7391 static void expr_shift(void)
7393 int t;
7395 expr_sum();
7396 while (tok == TOK_SHL || tok == TOK_SAR) {
7397 t = tok;
7398 next();
7399 expr_sum();
7400 gen_op(t);
7404 static void expr_cmp(void)
7406 int t;
7408 expr_shift();
7409 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7410 tok == TOK_ULT || tok == TOK_UGE) {
7411 t = tok;
7412 next();
7413 expr_shift();
7414 gen_op(t);
7418 static void expr_cmpeq(void)
7420 int t;
7422 expr_cmp();
7423 while (tok == TOK_EQ || tok == TOK_NE) {
7424 t = tok;
7425 next();
7426 expr_cmp();
7427 gen_op(t);
7431 static void expr_and(void)
7433 expr_cmpeq();
7434 while (tok == '&') {
7435 next();
7436 expr_cmpeq();
7437 gen_op('&');
7441 static void expr_xor(void)
7443 expr_and();
7444 while (tok == '^') {
7445 next();
7446 expr_and();
7447 gen_op('^');
7451 static void expr_or(void)
7453 expr_xor();
7454 while (tok == '|') {
7455 next();
7456 expr_xor();
7457 gen_op('|');
7461 /* XXX: fix this mess */
7462 static void expr_land_const(void)
7464 expr_or();
7465 while (tok == TOK_LAND) {
7466 next();
7467 expr_or();
7468 gen_op(TOK_LAND);
7472 /* XXX: fix this mess */
7473 static void expr_lor_const(void)
7475 expr_land_const();
7476 while (tok == TOK_LOR) {
7477 next();
7478 expr_land_const();
7479 gen_op(TOK_LOR);
7483 /* only used if non constant */
7484 static void expr_land(void)
7486 int t;
7488 expr_or();
7489 if (tok == TOK_LAND) {
7490 t = 0;
7491 for(;;) {
7492 t = gtst(1, t);
7493 if (tok != TOK_LAND) {
7494 vseti(VT_JMPI, t);
7495 break;
7497 next();
7498 expr_or();
7503 static void expr_lor(void)
7505 int t;
7507 expr_land();
7508 if (tok == TOK_LOR) {
7509 t = 0;
7510 for(;;) {
7511 t = gtst(0, t);
7512 if (tok != TOK_LOR) {
7513 vseti(VT_JMP, t);
7514 break;
7516 next();
7517 expr_land();
7522 /* XXX: better constant handling */
7523 static void expr_eq(void)
7525 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7526 SValue sv;
7527 CType type, type1, type2;
7529 if (const_wanted) {
7530 int c1, c;
7531 expr_lor_const();
7532 if (tok == '?') {
7533 c = vtop->c.i;
7534 vpop();
7535 next();
7536 if (tok == ':' && gnu_ext) {
7537 c1 = c;
7538 } else {
7539 gexpr();
7540 c1 = vtop->c.i;
7541 vpop();
7543 skip(':');
7544 expr_eq();
7545 if (c)
7546 vtop->c.i = c1;
7548 } else {
7549 expr_lor();
7550 if (tok == '?') {
7551 next();
7552 if (vtop != vstack) {
7553 /* needed to avoid having different registers saved in
7554 each branch */
7555 if (is_float(vtop->type.t))
7556 rc = RC_FLOAT;
7557 else
7558 rc = RC_INT;
7559 gv(rc);
7560 save_regs(1);
7562 if (tok == ':' && gnu_ext) {
7563 gv_dup();
7564 tt = gtst(1, 0);
7565 } else {
7566 tt = gtst(1, 0);
7567 gexpr();
7569 type1 = vtop->type;
7570 sv = *vtop; /* save value to handle it later */
7571 vtop--; /* no vpop so that FP stack is not flushed */
7572 skip(':');
7573 u = gjmp(0);
7574 gsym(tt);
7575 expr_eq();
7576 type2 = vtop->type;
7578 t1 = type1.t;
7579 bt1 = t1 & VT_BTYPE;
7580 t2 = type2.t;
7581 bt2 = t2 & VT_BTYPE;
7582 /* cast operands to correct type according to ISOC rules */
7583 if (is_float(bt1) || is_float(bt2)) {
7584 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7585 type.t = VT_LDOUBLE;
7586 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7587 type.t = VT_DOUBLE;
7588 } else {
7589 type.t = VT_FLOAT;
7591 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7592 /* cast to biggest op */
7593 type.t = VT_LLONG;
7594 /* convert to unsigned if it does not fit in a long long */
7595 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7596 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7597 type.t |= VT_UNSIGNED;
7598 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7599 /* XXX: test pointer compatibility */
7600 type = type1;
7601 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7602 /* XXX: test structure compatibility */
7603 type = type1;
7604 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7605 /* NOTE: as an extension, we accept void on only one side */
7606 type.t = VT_VOID;
7607 } else {
7608 /* integer operations */
7609 type.t = VT_INT;
7610 /* convert to unsigned if it does not fit in an integer */
7611 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7612 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7613 type.t |= VT_UNSIGNED;
7616 /* now we convert second operand */
7617 gen_cast(&type);
7618 rc = RC_INT;
7619 if (is_float(type.t)) {
7620 rc = RC_FLOAT;
7621 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7622 /* for long longs, we use fixed registers to avoid having
7623 to handle a complicated move */
7624 rc = RC_IRET;
7627 r2 = gv(rc);
7628 /* this is horrible, but we must also convert first
7629 operand */
7630 tt = gjmp(0);
7631 gsym(u);
7632 /* put again first value and cast it */
7633 *vtop = sv;
7634 gen_cast(&type);
7635 r1 = gv(rc);
7636 move_reg(r2, r1);
7637 vtop->r = r2;
7638 gsym(tt);
7643 static void gexpr(void)
7645 while (1) {
7646 expr_eq();
7647 if (tok != ',')
7648 break;
7649 vpop();
7650 next();
7654 /* parse an expression and return its type without any side effect. */
7655 static void expr_type(CType *type)
7657 int saved_nocode_wanted;
7659 saved_nocode_wanted = nocode_wanted;
7660 nocode_wanted = 1;
7661 gexpr();
7662 *type = vtop->type;
7663 vpop();
7664 nocode_wanted = saved_nocode_wanted;
7667 /* parse a unary expression and return its type without any side
7668 effect. */
7669 static void unary_type(CType *type)
7671 int a;
7673 a = nocode_wanted;
7674 nocode_wanted = 1;
7675 unary();
7676 *type = vtop->type;
7677 vpop();
7678 nocode_wanted = a;
7681 /* parse a constant expression and return value in vtop. */
7682 static void expr_const1(void)
7684 int a;
7685 a = const_wanted;
7686 const_wanted = 1;
7687 expr_eq();
7688 const_wanted = a;
7691 /* parse an integer constant and return its value. */
7692 static int expr_const(void)
7694 int c;
7695 expr_const1();
7696 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7697 expect("constant expression");
7698 c = vtop->c.i;
7699 vpop();
7700 return c;
7703 /* return the label token if current token is a label, otherwise
7704 return zero */
7705 static int is_label(void)
7707 int last_tok;
7709 /* fast test first */
7710 if (tok < TOK_UIDENT)
7711 return 0;
7712 /* no need to save tokc because tok is an identifier */
7713 last_tok = tok;
7714 next();
7715 if (tok == ':') {
7716 next();
7717 return last_tok;
7718 } else {
7719 unget_tok(last_tok);
7720 return 0;
7724 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7725 int case_reg, int is_expr)
7727 int a, b, c, d;
7728 Sym *s;
7730 /* generate line number info */
7731 if (do_debug &&
7732 (last_line_num != file->line_num || last_ind != ind)) {
7733 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7734 last_ind = ind;
7735 last_line_num = file->line_num;
7738 if (is_expr) {
7739 /* default return value is (void) */
7740 vpushi(0);
7741 vtop->type.t = VT_VOID;
7744 if (tok == TOK_IF) {
7745 /* if test */
7746 next();
7747 skip('(');
7748 gexpr();
7749 skip(')');
7750 a = gtst(1, 0);
7751 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7752 c = tok;
7753 if (c == TOK_ELSE) {
7754 next();
7755 d = gjmp(0);
7756 gsym(a);
7757 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7758 gsym(d); /* patch else jmp */
7759 } else
7760 gsym(a);
7761 } else if (tok == TOK_WHILE) {
7762 next();
7763 d = ind;
7764 skip('(');
7765 gexpr();
7766 skip(')');
7767 a = gtst(1, 0);
7768 b = 0;
7769 block(&a, &b, case_sym, def_sym, case_reg, 0);
7770 gjmp_addr(d);
7771 gsym(a);
7772 gsym_addr(b, d);
7773 } else if (tok == '{') {
7774 Sym *llabel;
7776 next();
7777 /* record local declaration stack position */
7778 s = local_stack;
7779 llabel = local_label_stack;
7780 /* handle local labels declarations */
7781 if (tok == TOK_LABEL) {
7782 next();
7783 for(;;) {
7784 if (tok < TOK_UIDENT)
7785 expect("label identifier");
7786 label_push(&local_label_stack, tok, LABEL_DECLARED);
7787 next();
7788 if (tok == ',') {
7789 next();
7790 } else {
7791 skip(';');
7792 break;
7796 while (tok != '}') {
7797 decl(VT_LOCAL);
7798 if (tok != '}') {
7799 if (is_expr)
7800 vpop();
7801 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7804 /* pop locally defined labels */
7805 label_pop(&local_label_stack, llabel);
7806 /* pop locally defined symbols */
7807 sym_pop(&local_stack, s);
7808 next();
7809 } else if (tok == TOK_RETURN) {
7810 next();
7811 if (tok != ';') {
7812 gexpr();
7813 gen_assign_cast(&func_vt);
7814 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7815 CType type;
7816 /* if returning structure, must copy it to implicit
7817 first pointer arg location */
7818 type = func_vt;
7819 mk_pointer(&type);
7820 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7821 indir();
7822 vswap();
7823 /* copy structure value to pointer */
7824 vstore();
7825 } else if (is_float(func_vt.t)) {
7826 gv(RC_FRET);
7827 } else {
7828 gv(RC_IRET);
7830 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7832 skip(';');
7833 rsym = gjmp(rsym); /* jmp */
7834 } else if (tok == TOK_BREAK) {
7835 /* compute jump */
7836 if (!bsym)
7837 error("cannot break");
7838 *bsym = gjmp(*bsym);
7839 next();
7840 skip(';');
7841 } else if (tok == TOK_CONTINUE) {
7842 /* compute jump */
7843 if (!csym)
7844 error("cannot continue");
7845 *csym = gjmp(*csym);
7846 next();
7847 skip(';');
7848 } else if (tok == TOK_FOR) {
7849 int e;
7850 next();
7851 skip('(');
7852 if (tok != ';') {
7853 gexpr();
7854 vpop();
7856 skip(';');
7857 d = ind;
7858 c = ind;
7859 a = 0;
7860 b = 0;
7861 if (tok != ';') {
7862 gexpr();
7863 a = gtst(1, 0);
7865 skip(';');
7866 if (tok != ')') {
7867 e = gjmp(0);
7868 c = ind;
7869 gexpr();
7870 vpop();
7871 gjmp_addr(d);
7872 gsym(e);
7874 skip(')');
7875 block(&a, &b, case_sym, def_sym, case_reg, 0);
7876 gjmp_addr(c);
7877 gsym(a);
7878 gsym_addr(b, c);
7879 } else
7880 if (tok == TOK_DO) {
7881 next();
7882 a = 0;
7883 b = 0;
7884 d = ind;
7885 block(&a, &b, case_sym, def_sym, case_reg, 0);
7886 skip(TOK_WHILE);
7887 skip('(');
7888 gsym(b);
7889 gexpr();
7890 c = gtst(0, 0);
7891 gsym_addr(c, d);
7892 skip(')');
7893 gsym(a);
7894 skip(';');
7895 } else
7896 if (tok == TOK_SWITCH) {
7897 next();
7898 skip('(');
7899 gexpr();
7900 /* XXX: other types than integer */
7901 case_reg = gv(RC_INT);
7902 vpop();
7903 skip(')');
7904 a = 0;
7905 b = gjmp(0); /* jump to first case */
7906 c = 0;
7907 block(&a, csym, &b, &c, case_reg, 0);
7908 /* if no default, jmp after switch */
7909 if (c == 0)
7910 c = ind;
7911 /* default label */
7912 gsym_addr(b, c);
7913 /* break label */
7914 gsym(a);
7915 } else
7916 if (tok == TOK_CASE) {
7917 int v1, v2;
7918 if (!case_sym)
7919 expect("switch");
7920 next();
7921 v1 = expr_const();
7922 v2 = v1;
7923 if (gnu_ext && tok == TOK_DOTS) {
7924 next();
7925 v2 = expr_const();
7926 if (v2 < v1)
7927 warning("empty case range");
7929 /* since a case is like a label, we must skip it with a jmp */
7930 b = gjmp(0);
7931 gsym(*case_sym);
7932 vseti(case_reg, 0);
7933 vpushi(v1);
7934 if (v1 == v2) {
7935 gen_op(TOK_EQ);
7936 *case_sym = gtst(1, 0);
7937 } else {
7938 gen_op(TOK_GE);
7939 *case_sym = gtst(1, 0);
7940 vseti(case_reg, 0);
7941 vpushi(v2);
7942 gen_op(TOK_LE);
7943 *case_sym = gtst(1, *case_sym);
7945 gsym(b);
7946 skip(':');
7947 is_expr = 0;
7948 goto block_after_label;
7949 } else
7950 if (tok == TOK_DEFAULT) {
7951 next();
7952 skip(':');
7953 if (!def_sym)
7954 expect("switch");
7955 if (*def_sym)
7956 error("too many 'default'");
7957 *def_sym = ind;
7958 is_expr = 0;
7959 goto block_after_label;
7960 } else
7961 if (tok == TOK_GOTO) {
7962 next();
7963 if (tok == '*' && gnu_ext) {
7964 /* computed goto */
7965 next();
7966 gexpr();
7967 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7968 expect("pointer");
7969 ggoto();
7970 } else if (tok >= TOK_UIDENT) {
7971 s = label_find(tok);
7972 /* put forward definition if needed */
7973 if (!s) {
7974 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7975 } else {
7976 if (s->r == LABEL_DECLARED)
7977 s->r = LABEL_FORWARD;
7979 /* label already defined */
7980 if (s->r & LABEL_FORWARD)
7981 s->next = (void *)gjmp((long)s->next);
7982 else
7983 gjmp_addr((long)s->next);
7984 next();
7985 } else {
7986 expect("label identifier");
7988 skip(';');
7989 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7990 asm_instr();
7991 } else {
7992 b = is_label();
7993 if (b) {
7994 /* label case */
7995 s = label_find(b);
7996 if (s) {
7997 if (s->r == LABEL_DEFINED)
7998 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7999 gsym((long)s->next);
8000 s->r = LABEL_DEFINED;
8001 } else {
8002 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8004 s->next = (void *)ind;
8005 /* we accept this, but it is a mistake */
8006 block_after_label:
8007 if (tok == '}') {
8008 warning("deprecated use of label at end of compound statement");
8009 } else {
8010 if (is_expr)
8011 vpop();
8012 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8014 } else {
8015 /* expression case */
8016 if (tok != ';') {
8017 if (is_expr) {
8018 vpop();
8019 gexpr();
8020 } else {
8021 gexpr();
8022 vpop();
8025 skip(';');
8030 /* t is the array or struct type. c is the array or struct
8031 address. cur_index/cur_field is the pointer to the current
8032 value. 'size_only' is true if only size info is needed (only used
8033 in arrays) */
8034 static void decl_designator(CType *type, Section *sec, unsigned long c,
8035 int *cur_index, Sym **cur_field,
8036 int size_only)
8038 Sym *s, *f;
8039 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8040 CType type1;
8042 notfirst = 0;
8043 elem_size = 0;
8044 nb_elems = 1;
8045 if (gnu_ext && (l = is_label()) != 0)
8046 goto struct_field;
8047 while (tok == '[' || tok == '.') {
8048 if (tok == '[') {
8049 if (!(type->t & VT_ARRAY))
8050 expect("array type");
8051 s = type->ref;
8052 next();
8053 index = expr_const();
8054 if (index < 0 || (s->c >= 0 && index >= s->c))
8055 expect("invalid index");
8056 if (tok == TOK_DOTS && gnu_ext) {
8057 next();
8058 index_last = expr_const();
8059 if (index_last < 0 ||
8060 (s->c >= 0 && index_last >= s->c) ||
8061 index_last < index)
8062 expect("invalid index");
8063 } else {
8064 index_last = index;
8066 skip(']');
8067 if (!notfirst)
8068 *cur_index = index_last;
8069 type = pointed_type(type);
8070 elem_size = type_size(type, &align);
8071 c += index * elem_size;
8072 /* NOTE: we only support ranges for last designator */
8073 nb_elems = index_last - index + 1;
8074 if (nb_elems != 1) {
8075 notfirst = 1;
8076 break;
8078 } else {
8079 next();
8080 l = tok;
8081 next();
8082 struct_field:
8083 if ((type->t & VT_BTYPE) != VT_STRUCT)
8084 expect("struct/union type");
8085 s = type->ref;
8086 l |= SYM_FIELD;
8087 f = s->next;
8088 while (f) {
8089 if (f->v == l)
8090 break;
8091 f = f->next;
8093 if (!f)
8094 expect("field");
8095 if (!notfirst)
8096 *cur_field = f;
8097 /* XXX: fix this mess by using explicit storage field */
8098 type1 = f->type;
8099 type1.t |= (type->t & ~VT_TYPE);
8100 type = &type1;
8101 c += f->c;
8103 notfirst = 1;
8105 if (notfirst) {
8106 if (tok == '=') {
8107 next();
8108 } else {
8109 if (!gnu_ext)
8110 expect("=");
8112 } else {
8113 if (type->t & VT_ARRAY) {
8114 index = *cur_index;
8115 type = pointed_type(type);
8116 c += index * type_size(type, &align);
8117 } else {
8118 f = *cur_field;
8119 if (!f)
8120 error("too many field init");
8121 /* XXX: fix this mess by using explicit storage field */
8122 type1 = f->type;
8123 type1.t |= (type->t & ~VT_TYPE);
8124 type = &type1;
8125 c += f->c;
8128 decl_initializer(type, sec, c, 0, size_only);
8130 /* XXX: make it more general */
8131 if (!size_only && nb_elems > 1) {
8132 unsigned long c_end;
8133 uint8_t *src, *dst;
8134 int i;
8136 if (!sec)
8137 error("range init not supported yet for dynamic storage");
8138 c_end = c + nb_elems * elem_size;
8139 if (c_end > sec->data_allocated)
8140 section_realloc(sec, c_end);
8141 src = sec->data + c;
8142 dst = src;
8143 for(i = 1; i < nb_elems; i++) {
8144 dst += elem_size;
8145 memcpy(dst, src, elem_size);
8150 #define EXPR_VAL 0
8151 #define EXPR_CONST 1
8152 #define EXPR_ANY 2
8154 /* store a value or an expression directly in global data or in local array */
8155 static void init_putv(CType *type, Section *sec, unsigned long c,
8156 int v, int expr_type)
8158 int saved_global_expr, bt, bit_pos, bit_size;
8159 void *ptr;
8160 unsigned long long bit_mask;
8161 CType dtype;
8163 switch(expr_type) {
8164 case EXPR_VAL:
8165 vpushi(v);
8166 break;
8167 case EXPR_CONST:
8168 /* compound literals must be allocated globally in this case */
8169 saved_global_expr = global_expr;
8170 global_expr = 1;
8171 expr_const1();
8172 global_expr = saved_global_expr;
8173 /* NOTE: symbols are accepted */
8174 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8175 error("initializer element is not constant");
8176 break;
8177 case EXPR_ANY:
8178 expr_eq();
8179 break;
8182 dtype = *type;
8183 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8185 if (sec) {
8186 /* XXX: not portable */
8187 /* XXX: generate error if incorrect relocation */
8188 gen_assign_cast(&dtype);
8189 bt = type->t & VT_BTYPE;
8190 ptr = sec->data + c;
8191 /* XXX: make code faster ? */
8192 if (!(type->t & VT_BITFIELD)) {
8193 bit_pos = 0;
8194 bit_size = 32;
8195 bit_mask = -1LL;
8196 } else {
8197 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8198 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8199 bit_mask = (1LL << bit_size) - 1;
8201 if ((vtop->r & VT_SYM) &&
8202 (bt == VT_BYTE ||
8203 bt == VT_SHORT ||
8204 bt == VT_DOUBLE ||
8205 bt == VT_LDOUBLE ||
8206 bt == VT_LLONG ||
8207 (bt == VT_INT && bit_size != 32)))
8208 error("initializer element is not computable at load time");
8209 switch(bt) {
8210 case VT_BYTE:
8211 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8212 break;
8213 case VT_SHORT:
8214 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8215 break;
8216 case VT_DOUBLE:
8217 *(double *)ptr = vtop->c.d;
8218 break;
8219 case VT_LDOUBLE:
8220 *(long double *)ptr = vtop->c.ld;
8221 break;
8222 case VT_LLONG:
8223 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8224 break;
8225 default:
8226 if (vtop->r & VT_SYM) {
8227 greloc(sec, vtop->sym, c, R_DATA_32);
8229 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8230 break;
8232 vtop--;
8233 } else {
8234 vset(&dtype, VT_LOCAL, c);
8235 vswap();
8236 vstore();
8237 vpop();
8241 /* put zeros for variable based init */
8242 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8244 if (sec) {
8245 /* nothing to do because globals are already set to zero */
8246 } else {
8247 vpush_global_sym(&func_old_type, TOK_memset);
8248 vseti(VT_LOCAL, c);
8249 vpushi(0);
8250 vpushi(size);
8251 gfunc_call(3);
8255 /* 't' contains the type and storage info. 'c' is the offset of the
8256 object in section 'sec'. If 'sec' is NULL, it means stack based
8257 allocation. 'first' is true if array '{' must be read (multi
8258 dimension implicit array init handling). 'size_only' is true if
8259 size only evaluation is wanted (only for arrays). */
8260 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8261 int first, int size_only)
8263 int index, array_length, n, no_oblock, nb, parlevel, i;
8264 int size1, align1, expr_type;
8265 Sym *s, *f;
8266 CType *t1;
8268 if (type->t & VT_ARRAY) {
8269 s = type->ref;
8270 n = s->c;
8271 array_length = 0;
8272 t1 = pointed_type(type);
8273 size1 = type_size(t1, &align1);
8275 no_oblock = 1;
8276 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8277 tok == '{') {
8278 skip('{');
8279 no_oblock = 0;
8282 /* only parse strings here if correct type (otherwise: handle
8283 them as ((w)char *) expressions */
8284 if ((tok == TOK_LSTR &&
8285 (t1->t & VT_BTYPE) == VT_INT) ||
8286 (tok == TOK_STR &&
8287 (t1->t & VT_BTYPE) == VT_BYTE)) {
8288 while (tok == TOK_STR || tok == TOK_LSTR) {
8289 int cstr_len, ch;
8290 CString *cstr;
8292 cstr = tokc.cstr;
8293 /* compute maximum number of chars wanted */
8294 if (tok == TOK_STR)
8295 cstr_len = cstr->size;
8296 else
8297 cstr_len = cstr->size / sizeof(int);
8298 cstr_len--;
8299 nb = cstr_len;
8300 if (n >= 0 && nb > (n - array_length))
8301 nb = n - array_length;
8302 if (!size_only) {
8303 if (cstr_len > nb)
8304 warning("initializer-string for array is too long");
8305 /* in order to go faster for common case (char
8306 string in global variable, we handle it
8307 specifically */
8308 if (sec && tok == TOK_STR && size1 == 1) {
8309 memcpy(sec->data + c + array_length, cstr->data, nb);
8310 } else {
8311 for(i=0;i<nb;i++) {
8312 if (tok == TOK_STR)
8313 ch = ((unsigned char *)cstr->data)[i];
8314 else
8315 ch = ((int *)cstr->data)[i];
8316 init_putv(t1, sec, c + (array_length + i) * size1,
8317 ch, EXPR_VAL);
8321 array_length += nb;
8322 next();
8324 /* only add trailing zero if enough storage (no
8325 warning in this case since it is standard) */
8326 if (n < 0 || array_length < n) {
8327 if (!size_only) {
8328 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8330 array_length++;
8332 } else {
8333 index = 0;
8334 while (tok != '}') {
8335 decl_designator(type, sec, c, &index, NULL, size_only);
8336 if (n >= 0 && index >= n)
8337 error("index too large");
8338 /* must put zero in holes (note that doing it that way
8339 ensures that it even works with designators) */
8340 if (!size_only && array_length < index) {
8341 init_putz(t1, sec, c + array_length * size1,
8342 (index - array_length) * size1);
8344 index++;
8345 if (index > array_length)
8346 array_length = index;
8347 /* special test for multi dimensional arrays (may not
8348 be strictly correct if designators are used at the
8349 same time) */
8350 if (index >= n && no_oblock)
8351 break;
8352 if (tok == '}')
8353 break;
8354 skip(',');
8357 if (!no_oblock)
8358 skip('}');
8359 /* put zeros at the end */
8360 if (!size_only && n >= 0 && array_length < n) {
8361 init_putz(t1, sec, c + array_length * size1,
8362 (n - array_length) * size1);
8364 /* patch type size if needed */
8365 if (n < 0)
8366 s->c = array_length;
8367 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8368 (sec || !first || tok == '{')) {
8369 int par_count;
8371 /* NOTE: the previous test is a specific case for automatic
8372 struct/union init */
8373 /* XXX: union needs only one init */
8375 /* XXX: this test is incorrect for local initializers
8376 beginning with ( without {. It would be much more difficult
8377 to do it correctly (ideally, the expression parser should
8378 be used in all cases) */
8379 par_count = 0;
8380 if (tok == '(') {
8381 AttributeDef ad1;
8382 CType type1;
8383 next();
8384 while (tok == '(') {
8385 par_count++;
8386 next();
8388 if (!parse_btype(&type1, &ad1))
8389 expect("cast");
8390 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8391 #if 0
8392 if (!is_assignable_types(type, &type1))
8393 error("invalid type for cast");
8394 #endif
8395 skip(')');
8397 no_oblock = 1;
8398 if (first || tok == '{') {
8399 skip('{');
8400 no_oblock = 0;
8402 s = type->ref;
8403 f = s->next;
8404 array_length = 0;
8405 index = 0;
8406 n = s->c;
8407 while (tok != '}') {
8408 decl_designator(type, sec, c, NULL, &f, size_only);
8409 index = f->c;
8410 if (!size_only && array_length < index) {
8411 init_putz(type, sec, c + array_length,
8412 index - array_length);
8414 index = index + type_size(&f->type, &align1);
8415 if (index > array_length)
8416 array_length = index;
8417 f = f->next;
8418 if (no_oblock && f == NULL)
8419 break;
8420 if (tok == '}')
8421 break;
8422 skip(',');
8424 /* put zeros at the end */
8425 if (!size_only && array_length < n) {
8426 init_putz(type, sec, c + array_length,
8427 n - array_length);
8429 if (!no_oblock)
8430 skip('}');
8431 while (par_count) {
8432 skip(')');
8433 par_count--;
8435 } else if (tok == '{') {
8436 next();
8437 decl_initializer(type, sec, c, first, size_only);
8438 skip('}');
8439 } else if (size_only) {
8440 /* just skip expression */
8441 parlevel = 0;
8442 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8443 tok != -1) {
8444 if (tok == '(')
8445 parlevel++;
8446 else if (tok == ')')
8447 parlevel--;
8448 next();
8450 } else {
8451 /* currently, we always use constant expression for globals
8452 (may change for scripting case) */
8453 expr_type = EXPR_CONST;
8454 if (!sec)
8455 expr_type = EXPR_ANY;
8456 init_putv(type, sec, c, 0, expr_type);
8460 /* parse an initializer for type 't' if 'has_init' is non zero, and
8461 allocate space in local or global data space ('r' is either
8462 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8463 variable 'v' of scope 'scope' is declared before initializers are
8464 parsed. If 'v' is zero, then a reference to the new object is put
8465 in the value stack. If 'has_init' is 2, a special parsing is done
8466 to handle string constants. */
8467 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8468 int has_init, int v, int scope)
8470 int size, align, addr, data_offset;
8471 int level;
8472 ParseState saved_parse_state;
8473 TokenString init_str;
8474 Section *sec;
8476 size = type_size(type, &align);
8477 /* If unknown size, we must evaluate it before
8478 evaluating initializers because
8479 initializers can generate global data too
8480 (e.g. string pointers or ISOC99 compound
8481 literals). It also simplifies local
8482 initializers handling */
8483 tok_str_new(&init_str);
8484 if (size < 0) {
8485 if (!has_init)
8486 error("unknown type size");
8487 /* get all init string */
8488 if (has_init == 2) {
8489 /* only get strings */
8490 while (tok == TOK_STR || tok == TOK_LSTR) {
8491 tok_str_add_tok(&init_str);
8492 next();
8494 } else {
8495 level = 0;
8496 while (level > 0 || (tok != ',' && tok != ';')) {
8497 if (tok < 0)
8498 error("unexpected end of file in initializer");
8499 tok_str_add_tok(&init_str);
8500 if (tok == '{')
8501 level++;
8502 else if (tok == '}') {
8503 if (level == 0)
8504 break;
8505 level--;
8507 next();
8510 tok_str_add(&init_str, -1);
8511 tok_str_add(&init_str, 0);
8513 /* compute size */
8514 save_parse_state(&saved_parse_state);
8516 macro_ptr = init_str.str;
8517 next();
8518 decl_initializer(type, NULL, 0, 1, 1);
8519 /* prepare second initializer parsing */
8520 macro_ptr = init_str.str;
8521 next();
8523 /* if still unknown size, error */
8524 size = type_size(type, &align);
8525 if (size < 0)
8526 error("unknown type size");
8528 /* take into account specified alignment if bigger */
8529 if (ad->aligned) {
8530 if (ad->aligned > align)
8531 align = ad->aligned;
8532 } else if (ad->packed) {
8533 align = 1;
8535 if ((r & VT_VALMASK) == VT_LOCAL) {
8536 sec = NULL;
8537 if (do_bounds_check && (type->t & VT_ARRAY))
8538 loc--;
8539 loc = (loc - size) & -align;
8540 addr = loc;
8541 /* handles bounds */
8542 /* XXX: currently, since we do only one pass, we cannot track
8543 '&' operators, so we add only arrays */
8544 if (do_bounds_check && (type->t & VT_ARRAY)) {
8545 unsigned long *bounds_ptr;
8546 /* add padding between regions */
8547 loc--;
8548 /* then add local bound info */
8549 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8550 bounds_ptr[0] = addr;
8551 bounds_ptr[1] = size;
8553 if (v) {
8554 /* local variable */
8555 sym_push(v, type, r, addr);
8556 } else {
8557 /* push local reference */
8558 vset(type, r, addr);
8560 } else {
8561 Sym *sym;
8563 sym = NULL;
8564 if (v && scope == VT_CONST) {
8565 /* see if the symbol was already defined */
8566 sym = sym_find(v);
8567 if (sym) {
8568 if (!is_compatible_types(&sym->type, type))
8569 error("incompatible types for redefinition of '%s'",
8570 get_tok_str(v, NULL));
8571 if (sym->type.t & VT_EXTERN) {
8572 /* if the variable is extern, it was not allocated */
8573 sym->type.t &= ~VT_EXTERN;
8574 /* set array size if it was ommited in extern
8575 declaration */
8576 if ((sym->type.t & VT_ARRAY) &&
8577 sym->type.ref->c < 0 &&
8578 type->ref->c >= 0)
8579 sym->type.ref->c = type->ref->c;
8580 } else {
8581 /* we accept several definitions of the same
8582 global variable. this is tricky, because we
8583 must play with the SHN_COMMON type of the symbol */
8584 /* XXX: should check if the variable was already
8585 initialized. It is incorrect to initialized it
8586 twice */
8587 /* no init data, we won't add more to the symbol */
8588 if (!has_init)
8589 goto no_alloc;
8594 /* allocate symbol in corresponding section */
8595 sec = ad->section;
8596 if (!sec) {
8597 if (has_init)
8598 sec = data_section;
8599 else if (tcc_state->nocommon)
8600 sec = bss_section;
8602 if (sec) {
8603 data_offset = sec->data_offset;
8604 data_offset = (data_offset + align - 1) & -align;
8605 addr = data_offset;
8606 /* very important to increment global pointer at this time
8607 because initializers themselves can create new initializers */
8608 data_offset += size;
8609 /* add padding if bound check */
8610 if (do_bounds_check)
8611 data_offset++;
8612 sec->data_offset = data_offset;
8613 /* allocate section space to put the data */
8614 if (sec->sh_type != SHT_NOBITS &&
8615 data_offset > sec->data_allocated)
8616 section_realloc(sec, data_offset);
8617 /* align section if needed */
8618 if (align > sec->sh_addralign)
8619 sec->sh_addralign = align;
8620 } else {
8621 addr = 0; /* avoid warning */
8624 if (v) {
8625 if (scope == VT_CONST) {
8626 if (!sym)
8627 goto do_def;
8628 } else {
8629 do_def:
8630 sym = sym_push(v, type, r | VT_SYM, 0);
8632 /* update symbol definition */
8633 if (sec) {
8634 put_extern_sym(sym, sec, addr, size);
8635 } else {
8636 Elf32_Sym *esym;
8637 /* put a common area */
8638 put_extern_sym(sym, NULL, align, size);
8639 /* XXX: find a nicer way */
8640 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8641 esym->st_shndx = SHN_COMMON;
8643 } else {
8644 CValue cval;
8646 /* push global reference */
8647 sym = get_sym_ref(type, sec, addr, size);
8648 cval.ul = 0;
8649 vsetc(type, VT_CONST | VT_SYM, &cval);
8650 vtop->sym = sym;
8653 /* handles bounds now because the symbol must be defined
8654 before for the relocation */
8655 if (do_bounds_check) {
8656 unsigned long *bounds_ptr;
8658 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8659 /* then add global bound info */
8660 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8661 bounds_ptr[0] = 0; /* relocated */
8662 bounds_ptr[1] = size;
8665 if (has_init) {
8666 decl_initializer(type, sec, addr, 1, 0);
8667 /* restore parse state if needed */
8668 if (init_str.str) {
8669 tok_str_free(init_str.str);
8670 restore_parse_state(&saved_parse_state);
8673 no_alloc: ;
8676 void put_func_debug(Sym *sym)
8678 char buf[512];
8680 /* stabs info */
8681 /* XXX: we put here a dummy type */
8682 snprintf(buf, sizeof(buf), "%s:%c1",
8683 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8684 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8685 cur_text_section, sym->c);
8686 last_ind = 0;
8687 last_line_num = 0;
8690 /* parse an old style function declaration list */
8691 /* XXX: check multiple parameter */
8692 static void func_decl_list(Sym *func_sym)
8694 AttributeDef ad;
8695 int v;
8696 Sym *s;
8697 CType btype, type;
8699 /* parse each declaration */
8700 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8701 if (!parse_btype(&btype, &ad))
8702 expect("declaration list");
8703 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8704 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8705 tok == ';') {
8706 /* we accept no variable after */
8707 } else {
8708 for(;;) {
8709 type = btype;
8710 type_decl(&type, &ad, &v, TYPE_DIRECT);
8711 /* find parameter in function parameter list */
8712 s = func_sym->next;
8713 while (s != NULL) {
8714 if ((s->v & ~SYM_FIELD) == v)
8715 goto found;
8716 s = s->next;
8718 error("declaration for parameter '%s' but no such parameter",
8719 get_tok_str(v, NULL));
8720 found:
8721 /* check that no storage specifier except 'register' was given */
8722 if (type.t & VT_STORAGE)
8723 error("storage class specified for '%s'", get_tok_str(v, NULL));
8724 convert_parameter_type(&type);
8725 /* we can add the type (NOTE: it could be local to the function) */
8726 s->type = type;
8727 /* accept other parameters */
8728 if (tok == ',')
8729 next();
8730 else
8731 break;
8734 skip(';');
8738 /* parse a function defined by symbol 'sym' and generate its code in
8739 'cur_text_section' */
8740 static void gen_function(Sym *sym)
8742 ind = cur_text_section->data_offset;
8743 /* NOTE: we patch the symbol size later */
8744 put_extern_sym(sym, cur_text_section, ind, 0);
8745 funcname = get_tok_str(sym->v, NULL);
8746 func_ind = ind;
8747 /* put debug symbol */
8748 if (do_debug)
8749 put_func_debug(sym);
8750 /* push a dummy symbol to enable local sym storage */
8751 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8752 gfunc_prolog(&sym->type);
8753 rsym = 0;
8754 block(NULL, NULL, NULL, NULL, 0, 0);
8755 gsym(rsym);
8756 gfunc_epilog();
8757 cur_text_section->data_offset = ind;
8758 label_pop(&global_label_stack, NULL);
8759 sym_pop(&local_stack, NULL); /* reset local stack */
8760 /* end of function */
8761 /* patch symbol size */
8762 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8763 ind - func_ind;
8764 if (do_debug) {
8765 put_stabn(N_FUN, 0, 0, ind - func_ind);
8767 funcname = ""; /* for safety */
8768 func_vt.t = VT_VOID; /* for safety */
8769 ind = 0; /* for safety */
8772 static void gen_inline_functions(void)
8774 Sym *sym;
8775 CType *type;
8776 int *str, inline_generated;
8778 /* iterate while inline function are referenced */
8779 for(;;) {
8780 inline_generated = 0;
8781 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8782 type = &sym->type;
8783 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8784 (type->t & (VT_STATIC | VT_INLINE)) ==
8785 (VT_STATIC | VT_INLINE) &&
8786 sym->c != 0) {
8787 /* the function was used: generate its code and
8788 convert it to a normal function */
8789 str = (int *)sym->r;
8790 sym->r = VT_SYM | VT_CONST;
8791 type->t &= ~VT_INLINE;
8793 macro_ptr = str;
8794 next();
8795 cur_text_section = text_section;
8796 gen_function(sym);
8797 macro_ptr = NULL; /* fail safe */
8799 tok_str_free(str);
8800 inline_generated = 1;
8803 if (!inline_generated)
8804 break;
8807 /* free all remaining inline function tokens */
8808 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8809 type = &sym->type;
8810 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8811 (type->t & (VT_STATIC | VT_INLINE)) ==
8812 (VT_STATIC | VT_INLINE)) {
8813 str = (int *)sym->r;
8814 tok_str_free(str);
8815 sym->r = 0; /* fail safe */
8820 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8821 static void decl(int l)
8823 int v, has_init, r;
8824 CType type, btype;
8825 Sym *sym;
8826 AttributeDef ad;
8828 while (1) {
8829 if (!parse_btype(&btype, &ad)) {
8830 /* skip redundant ';' */
8831 /* XXX: find more elegant solution */
8832 if (tok == ';') {
8833 next();
8834 continue;
8836 if (l == VT_CONST &&
8837 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
8838 /* global asm block */
8839 asm_global_instr();
8840 continue;
8842 /* special test for old K&R protos without explicit int
8843 type. Only accepted when defining global data */
8844 if (l == VT_LOCAL || tok < TOK_DEFINE)
8845 break;
8846 btype.t = VT_INT;
8848 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8849 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8850 tok == ';') {
8851 /* we accept no variable after */
8852 next();
8853 continue;
8855 while (1) { /* iterate thru each declaration */
8856 type = btype;
8857 type_decl(&type, &ad, &v, TYPE_DIRECT);
8858 #if 0
8860 char buf[500];
8861 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8862 printf("type = '%s'\n", buf);
8864 #endif
8865 if ((type.t & VT_BTYPE) == VT_FUNC) {
8866 /* if old style function prototype, we accept a
8867 declaration list */
8868 sym = type.ref;
8869 if (sym->c == FUNC_OLD)
8870 func_decl_list(sym);
8873 if (tok == '{') {
8874 if (l == VT_LOCAL)
8875 error("cannot use local functions");
8876 if (!(type.t & VT_FUNC))
8877 expect("function definition");
8879 /* reject abstract declarators in function definition */
8880 sym = type.ref;
8881 while ((sym = sym->next) != NULL)
8882 if (!(sym->v & ~SYM_FIELD))
8883 expect("identifier");
8885 /* XXX: cannot do better now: convert extern line to static inline */
8886 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8887 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8889 sym = sym_find(v);
8890 if (sym) {
8891 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
8892 goto func_error1;
8893 /* specific case: if not func_call defined, we put
8894 the one of the prototype */
8895 /* XXX: should have default value */
8896 if (sym->type.ref->r != FUNC_CDECL &&
8897 type.ref->r == FUNC_CDECL)
8898 type.ref->r = sym->type.ref->r;
8899 if (!is_compatible_types(&sym->type, &type)) {
8900 func_error1:
8901 error("incompatible types for redefinition of '%s'",
8902 get_tok_str(v, NULL));
8904 /* if symbol is already defined, then put complete type */
8905 sym->type = type;
8906 } else {
8907 /* put function symbol */
8908 sym = global_identifier_push(v, type.t, 0);
8909 sym->type.ref = type.ref;
8912 /* static inline functions are just recorded as a kind
8913 of macro. Their code will be emitted at the end of
8914 the compilation unit only if they are used */
8915 if ((type.t & (VT_INLINE | VT_STATIC)) ==
8916 (VT_INLINE | VT_STATIC)) {
8917 TokenString func_str;
8918 int block_level;
8920 tok_str_new(&func_str);
8922 block_level = 0;
8923 for(;;) {
8924 int t;
8925 if (tok == TOK_EOF)
8926 error("unexpected end of file");
8927 tok_str_add_tok(&func_str);
8928 t = tok;
8929 next();
8930 if (t == '{') {
8931 block_level++;
8932 } else if (t == '}') {
8933 block_level--;
8934 if (block_level == 0)
8935 break;
8938 tok_str_add(&func_str, -1);
8939 tok_str_add(&func_str, 0);
8940 sym->r = (int)func_str.str;
8941 } else {
8942 /* compute text section */
8943 cur_text_section = ad.section;
8944 if (!cur_text_section)
8945 cur_text_section = text_section;
8946 sym->r = VT_SYM | VT_CONST;
8947 gen_function(sym);
8949 break;
8950 } else {
8951 if (btype.t & VT_TYPEDEF) {
8952 /* save typedefed type */
8953 /* XXX: test storage specifiers ? */
8954 sym = sym_push(v, &type, 0, 0);
8955 sym->type.t |= VT_TYPEDEF;
8956 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8957 /* external function definition */
8958 /* specific case for func_call attribute */
8959 if (ad.func_call)
8960 type.ref->r = ad.func_call;
8961 external_sym(v, &type, 0);
8962 } else {
8963 /* not lvalue if array */
8964 r = 0;
8965 if (!(type.t & VT_ARRAY))
8966 r |= lvalue_type(type.t);
8967 has_init = (tok == '=');
8968 if ((btype.t & VT_EXTERN) ||
8969 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8970 !has_init && l == VT_CONST && type.ref->c < 0)) {
8971 /* external variable */
8972 /* NOTE: as GCC, uninitialized global static
8973 arrays of null size are considered as
8974 extern */
8975 external_sym(v, &type, r);
8976 } else {
8977 if (type.t & VT_STATIC)
8978 r |= VT_CONST;
8979 else
8980 r |= l;
8981 if (has_init)
8982 next();
8983 decl_initializer_alloc(&type, &ad, r,
8984 has_init, v, l);
8987 if (tok != ',') {
8988 skip(';');
8989 break;
8991 next();
8997 /* better than nothing, but needs extension to handle '-E' option
8998 correctly too */
8999 static void preprocess_init(TCCState *s1)
9001 s1->include_stack_ptr = s1->include_stack;
9002 /* XXX: move that before to avoid having to initialize
9003 file->ifdef_stack_ptr ? */
9004 s1->ifdef_stack_ptr = s1->ifdef_stack;
9005 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9007 /* XXX: not ANSI compliant: bound checking says error */
9008 vtop = vstack - 1;
9011 /* compile the C file opened in 'file'. Return non zero if errors. */
9012 static int tcc_compile(TCCState *s1)
9014 Sym *define_start;
9015 char buf[512];
9016 volatile int section_sym;
9018 #ifdef INC_DEBUG
9019 printf("%s: **** new file\n", file->filename);
9020 #endif
9021 preprocess_init(s1);
9023 funcname = "";
9024 anon_sym = SYM_FIRST_ANOM;
9026 /* file info: full path + filename */
9027 section_sym = 0; /* avoid warning */
9028 if (do_debug) {
9029 section_sym = put_elf_sym(symtab_section, 0, 0,
9030 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9031 text_section->sh_num, NULL);
9032 getcwd(buf, sizeof(buf));
9033 pstrcat(buf, sizeof(buf), "/");
9034 put_stabs_r(buf, N_SO, 0, 0,
9035 text_section->data_offset, text_section, section_sym);
9036 put_stabs_r(file->filename, N_SO, 0, 0,
9037 text_section->data_offset, text_section, section_sym);
9039 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9040 symbols can be safely used */
9041 put_elf_sym(symtab_section, 0, 0,
9042 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9043 SHN_ABS, file->filename);
9045 /* define some often used types */
9046 int_type.t = VT_INT;
9048 char_pointer_type.t = VT_BYTE;
9049 mk_pointer(&char_pointer_type);
9051 func_old_type.t = VT_FUNC;
9052 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9054 #if 0
9055 /* define 'void *alloca(unsigned int)' builtin function */
9057 Sym *s1;
9059 p = anon_sym++;
9060 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9061 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9062 s1->next = NULL;
9063 sym->next = s1;
9064 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9066 #endif
9068 define_start = define_stack;
9070 if (setjmp(s1->error_jmp_buf) == 0) {
9071 s1->nb_errors = 0;
9072 s1->error_set_jmp_enabled = 1;
9074 ch = file->buf_ptr[0];
9075 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9076 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9077 next();
9078 decl(VT_CONST);
9079 if (tok != TOK_EOF)
9080 expect("declaration");
9082 /* end of translation unit info */
9083 if (do_debug) {
9084 put_stabs_r(NULL, N_SO, 0, 0,
9085 text_section->data_offset, text_section, section_sym);
9088 s1->error_set_jmp_enabled = 0;
9090 /* reset define stack, but leave -Dsymbols (may be incorrect if
9091 they are undefined) */
9092 free_defines(define_start);
9094 gen_inline_functions();
9096 sym_pop(&global_stack, NULL);
9098 return s1->nb_errors != 0 ? -1 : 0;
9101 #ifdef LIBTCC
9102 int tcc_compile_string(TCCState *s, const char *str)
9104 BufferedFile bf1, *bf = &bf1;
9105 int ret, len;
9106 char *buf;
9108 /* init file structure */
9109 bf->fd = -1;
9110 /* XXX: avoid copying */
9111 len = strlen(str);
9112 buf = tcc_malloc(len + 1);
9113 if (!buf)
9114 return -1;
9115 memcpy(buf, str, len);
9116 buf[len] = CH_EOB;
9117 bf->buf_ptr = buf;
9118 bf->buf_end = buf + len;
9119 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9120 bf->line_num = 1;
9121 file = bf;
9123 ret = tcc_compile(s);
9125 tcc_free(buf);
9127 /* currently, no need to close */
9128 return ret;
9130 #endif
9132 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9133 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9135 BufferedFile bf1, *bf = &bf1;
9137 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9138 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9139 /* default value */
9140 if (!value)
9141 value = "1";
9142 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9144 /* init file structure */
9145 bf->fd = -1;
9146 bf->buf_ptr = bf->buffer;
9147 bf->buf_end = bf->buffer + strlen(bf->buffer);
9148 *bf->buf_end = CH_EOB;
9149 bf->filename[0] = '\0';
9150 bf->line_num = 1;
9151 file = bf;
9153 s1->include_stack_ptr = s1->include_stack;
9155 /* parse with define parser */
9156 ch = file->buf_ptr[0];
9157 next_nomacro();
9158 parse_define();
9159 file = NULL;
9162 /* undefine a preprocessor symbol */
9163 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9165 TokenSym *ts;
9166 Sym *s;
9167 ts = tok_alloc(sym, strlen(sym));
9168 s = define_find(ts->tok);
9169 /* undefine symbol by putting an invalid name */
9170 if (s)
9171 define_undef(s);
9174 #ifdef CONFIG_TCC_ASM
9176 #ifdef TCC_TARGET_I386
9177 #include "i386-asm.c"
9178 #endif
9179 #include "tccasm.c"
9181 #else
9182 static void asm_instr(void)
9184 error("inline asm() not supported");
9186 static void asm_global_instr(void)
9188 error("inline asm() not supported");
9190 #endif
9192 #include "tccelf.c"
9194 #ifdef TCC_TARGET_COFF
9195 #include "tcccoff.c"
9196 #endif
9198 /* print the position in the source file of PC value 'pc' by reading
9199 the stabs debug information */
9200 static void rt_printline(unsigned long wanted_pc)
9202 Stab_Sym *sym, *sym_end;
9203 char func_name[128], last_func_name[128];
9204 unsigned long func_addr, last_pc, pc;
9205 const char *incl_files[INCLUDE_STACK_SIZE];
9206 int incl_index, len, last_line_num, i;
9207 const char *str, *p;
9209 fprintf(stderr, "0x%08lx:", wanted_pc);
9211 func_name[0] = '\0';
9212 func_addr = 0;
9213 incl_index = 0;
9214 last_func_name[0] = '\0';
9215 last_pc = 0xffffffff;
9216 last_line_num = 1;
9217 sym = (Stab_Sym *)stab_section->data + 1;
9218 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9219 while (sym < sym_end) {
9220 switch(sym->n_type) {
9221 /* function start or end */
9222 case N_FUN:
9223 if (sym->n_strx == 0) {
9224 /* we test if between last line and end of function */
9225 pc = sym->n_value + func_addr;
9226 if (wanted_pc >= last_pc && wanted_pc < pc)
9227 goto found;
9228 func_name[0] = '\0';
9229 func_addr = 0;
9230 } else {
9231 str = stabstr_section->data + sym->n_strx;
9232 p = strchr(str, ':');
9233 if (!p) {
9234 pstrcpy(func_name, sizeof(func_name), str);
9235 } else {
9236 len = p - str;
9237 if (len > sizeof(func_name) - 1)
9238 len = sizeof(func_name) - 1;
9239 memcpy(func_name, str, len);
9240 func_name[len] = '\0';
9242 func_addr = sym->n_value;
9244 break;
9245 /* line number info */
9246 case N_SLINE:
9247 pc = sym->n_value + func_addr;
9248 if (wanted_pc >= last_pc && wanted_pc < pc)
9249 goto found;
9250 last_pc = pc;
9251 last_line_num = sym->n_desc;
9252 /* XXX: slow! */
9253 strcpy(last_func_name, func_name);
9254 break;
9255 /* include files */
9256 case N_BINCL:
9257 str = stabstr_section->data + sym->n_strx;
9258 add_incl:
9259 if (incl_index < INCLUDE_STACK_SIZE) {
9260 incl_files[incl_index++] = str;
9262 break;
9263 case N_EINCL:
9264 if (incl_index > 1)
9265 incl_index--;
9266 break;
9267 case N_SO:
9268 if (sym->n_strx == 0) {
9269 incl_index = 0; /* end of translation unit */
9270 } else {
9271 str = stabstr_section->data + sym->n_strx;
9272 /* do not add path */
9273 len = strlen(str);
9274 if (len > 0 && str[len - 1] != '/')
9275 goto add_incl;
9277 break;
9279 sym++;
9282 /* second pass: we try symtab symbols (no line number info) */
9283 incl_index = 0;
9285 Elf32_Sym *sym, *sym_end;
9286 int type;
9288 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9289 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9290 sym < sym_end;
9291 sym++) {
9292 type = ELF32_ST_TYPE(sym->st_info);
9293 if (type == STT_FUNC) {
9294 if (wanted_pc >= sym->st_value &&
9295 wanted_pc < sym->st_value + sym->st_size) {
9296 pstrcpy(last_func_name, sizeof(last_func_name),
9297 strtab_section->data + sym->st_name);
9298 goto found;
9303 /* did not find any info: */
9304 fprintf(stderr, " ???\n");
9305 return;
9306 found:
9307 if (last_func_name[0] != '\0') {
9308 fprintf(stderr, " %s()", last_func_name);
9310 if (incl_index > 0) {
9311 fprintf(stderr, " (%s:%d",
9312 incl_files[incl_index - 1], last_line_num);
9313 for(i = incl_index - 2; i >= 0; i--)
9314 fprintf(stderr, ", included from %s", incl_files[i]);
9315 fprintf(stderr, ")");
9317 fprintf(stderr, "\n");
9320 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9322 #ifdef __i386__
9324 /* fix for glibc 2.1 */
9325 #ifndef REG_EIP
9326 #define REG_EIP EIP
9327 #define REG_EBP EBP
9328 #endif
9330 /* return the PC at frame level 'level'. Return non zero if not found */
9331 static int rt_get_caller_pc(unsigned long *paddr,
9332 ucontext_t *uc, int level)
9334 unsigned long fp;
9335 int i;
9337 if (level == 0) {
9338 #if defined(__FreeBSD__)
9339 *paddr = uc->uc_mcontext.mc_eip;
9340 #elif defined(__dietlibc__)
9341 *paddr = uc->uc_mcontext.eip;
9342 #else
9343 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9344 #endif
9345 return 0;
9346 } else {
9347 #if defined(__FreeBSD__)
9348 fp = uc->uc_mcontext.mc_ebp;
9349 #elif defined(__dietlibc__)
9350 fp = uc->uc_mcontext.ebp;
9351 #else
9352 fp = uc->uc_mcontext.gregs[REG_EBP];
9353 #endif
9354 for(i=1;i<level;i++) {
9355 /* XXX: check address validity with program info */
9356 if (fp <= 0x1000 || fp >= 0xc0000000)
9357 return -1;
9358 fp = ((unsigned long *)fp)[0];
9360 *paddr = ((unsigned long *)fp)[1];
9361 return 0;
9364 #else
9366 #warning add arch specific rt_get_caller_pc()
9368 static int rt_get_caller_pc(unsigned long *paddr,
9369 ucontext_t *uc, int level)
9371 return -1;
9373 #endif
9375 /* emit a run time error at position 'pc' */
9376 void rt_error(ucontext_t *uc, const char *fmt, ...)
9378 va_list ap;
9379 unsigned long pc;
9380 int i;
9382 va_start(ap, fmt);
9383 fprintf(stderr, "Runtime error: ");
9384 vfprintf(stderr, fmt, ap);
9385 fprintf(stderr, "\n");
9386 for(i=0;i<num_callers;i++) {
9387 if (rt_get_caller_pc(&pc, uc, i) < 0)
9388 break;
9389 if (i == 0)
9390 fprintf(stderr, "at ");
9391 else
9392 fprintf(stderr, "by ");
9393 rt_printline(pc);
9395 exit(255);
9396 va_end(ap);
9399 /* signal handler for fatal errors */
9400 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9402 ucontext_t *uc = puc;
9404 switch(signum) {
9405 case SIGFPE:
9406 switch(siginf->si_code) {
9407 case FPE_INTDIV:
9408 case FPE_FLTDIV:
9409 rt_error(uc, "division by zero");
9410 break;
9411 default:
9412 rt_error(uc, "floating point exception");
9413 break;
9415 break;
9416 case SIGBUS:
9417 case SIGSEGV:
9418 if (rt_bound_error_msg && *rt_bound_error_msg)
9419 rt_error(uc, *rt_bound_error_msg);
9420 else
9421 rt_error(uc, "dereferencing invalid pointer");
9422 break;
9423 case SIGILL:
9424 rt_error(uc, "illegal instruction");
9425 break;
9426 case SIGABRT:
9427 rt_error(uc, "abort() called");
9428 break;
9429 default:
9430 rt_error(uc, "caught signal %d", signum);
9431 break;
9433 exit(255);
9435 #endif
9437 /* do all relocations (needed before using tcc_get_symbol()) */
9438 int tcc_relocate(TCCState *s1)
9440 Section *s;
9441 int i;
9443 s1->nb_errors = 0;
9445 tcc_add_runtime(s1);
9447 relocate_common_syms();
9449 tcc_add_linker_symbols(s1);
9451 build_got_entries(s1);
9453 /* compute relocation address : section are relocated in place. We
9454 also alloc the bss space */
9455 for(i = 1; i < s1->nb_sections; i++) {
9456 s = s1->sections[i];
9457 if (s->sh_flags & SHF_ALLOC) {
9458 if (s->sh_type == SHT_NOBITS)
9459 s->data = tcc_mallocz(s->data_offset);
9460 s->sh_addr = (unsigned long)s->data;
9464 relocate_syms(s1, 1);
9466 if (s1->nb_errors != 0)
9467 return -1;
9469 /* relocate each section */
9470 for(i = 1; i < s1->nb_sections; i++) {
9471 s = s1->sections[i];
9472 if (s->reloc)
9473 relocate_section(s1, s);
9475 return 0;
9478 /* launch the compiled program with the given arguments */
9479 int tcc_run(TCCState *s1, int argc, char **argv)
9481 int (*prog_main)(int, char **);
9483 if (tcc_relocate(s1) < 0)
9484 return -1;
9486 prog_main = tcc_get_symbol_err(s1, "main");
9488 if (do_debug) {
9489 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9490 error("debug mode currently not available for Windows");
9491 #else
9492 struct sigaction sigact;
9493 /* install TCC signal handlers to print debug info on fatal
9494 runtime errors */
9495 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9496 sigact.sa_sigaction = sig_error;
9497 sigemptyset(&sigact.sa_mask);
9498 sigaction(SIGFPE, &sigact, NULL);
9499 sigaction(SIGILL, &sigact, NULL);
9500 sigaction(SIGSEGV, &sigact, NULL);
9501 sigaction(SIGBUS, &sigact, NULL);
9502 sigaction(SIGABRT, &sigact, NULL);
9503 #endif
9506 #ifdef CONFIG_TCC_BCHECK
9507 if (do_bounds_check) {
9508 void (*bound_init)(void);
9510 /* set error function */
9511 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9512 "__bound_error_msg");
9514 /* XXX: use .init section so that it also work in binary ? */
9515 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9516 bound_init();
9518 #endif
9519 return (*prog_main)(argc, argv);
9522 TCCState *tcc_new(void)
9524 const char *p, *r;
9525 TCCState *s;
9526 TokenSym *ts;
9527 int i, c;
9529 s = tcc_mallocz(sizeof(TCCState));
9530 if (!s)
9531 return NULL;
9532 tcc_state = s;
9533 s->output_type = TCC_OUTPUT_MEMORY;
9535 /* init isid table */
9536 for(i=0;i<256;i++)
9537 isidnum_table[i] = isid(i) || isnum(i);
9539 /* add all tokens */
9540 table_ident = NULL;
9541 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9543 tok_ident = TOK_IDENT;
9544 p = tcc_keywords;
9545 while (*p) {
9546 r = p;
9547 for(;;) {
9548 c = *r++;
9549 if (c == '\0')
9550 break;
9552 ts = tok_alloc(p, r - p - 1);
9553 p = r;
9556 /* we add dummy defines for some special macros to speed up tests
9557 and to have working defined() */
9558 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9559 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9560 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9561 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9563 /* standard defines */
9564 tcc_define_symbol(s, "__STDC__", NULL);
9565 #if defined(TCC_TARGET_I386)
9566 tcc_define_symbol(s, "__i386__", NULL);
9567 #endif
9568 #if defined(TCC_TARGET_ARM)
9569 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9570 tcc_define_symbol(s, "__arm_elf__", NULL);
9571 tcc_define_symbol(s, "__arm_elf", NULL);
9572 tcc_define_symbol(s, "arm_elf", NULL);
9573 tcc_define_symbol(s, "__arm__", NULL);
9574 tcc_define_symbol(s, "__arm", NULL);
9575 tcc_define_symbol(s, "arm", NULL);
9576 tcc_define_symbol(s, "__APCS_32__", NULL);
9577 #endif
9578 #if defined(linux)
9579 tcc_define_symbol(s, "__linux__", NULL);
9580 tcc_define_symbol(s, "linux", NULL);
9581 #endif
9582 /* tiny C specific defines */
9583 tcc_define_symbol(s, "__TINYC__", NULL);
9585 /* tiny C & gcc defines */
9586 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9587 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9588 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9590 /* default library paths */
9591 tcc_add_library_path(s, "/usr/local/lib");
9592 tcc_add_library_path(s, "/usr/lib");
9593 tcc_add_library_path(s, "/lib");
9595 /* no section zero */
9596 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9598 /* create standard sections */
9599 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9600 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9601 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9603 /* symbols are always generated for linking stage */
9604 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9605 ".strtab",
9606 ".hashtab", SHF_PRIVATE);
9607 strtab_section = symtab_section->link;
9609 /* private symbol table for dynamic symbols */
9610 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9611 ".dynstrtab",
9612 ".dynhashtab", SHF_PRIVATE);
9613 s->alacarte_link = 1;
9615 #ifdef CHAR_IS_UNSIGNED
9616 s->char_is_unsigned = 1;
9617 #endif
9618 return s;
9621 void tcc_delete(TCCState *s1)
9623 int i, n;
9625 /* free -D defines */
9626 free_defines(NULL);
9628 /* free tokens */
9629 n = tok_ident - TOK_IDENT;
9630 for(i = 0; i < n; i++)
9631 tcc_free(table_ident[i]);
9632 tcc_free(table_ident);
9634 /* free all sections */
9636 free_section(symtab_section->hash);
9638 free_section(s1->dynsymtab_section->hash);
9639 free_section(s1->dynsymtab_section->link);
9640 free_section(s1->dynsymtab_section);
9642 for(i = 1; i < s1->nb_sections; i++)
9643 free_section(s1->sections[i]);
9644 tcc_free(s1->sections);
9646 /* free loaded dlls array */
9647 for(i = 0; i < s1->nb_loaded_dlls; i++)
9648 tcc_free(s1->loaded_dlls[i]);
9649 tcc_free(s1->loaded_dlls);
9651 /* library paths */
9652 for(i = 0; i < s1->nb_library_paths; i++)
9653 tcc_free(s1->library_paths[i]);
9654 tcc_free(s1->library_paths);
9656 /* cached includes */
9657 for(i = 0; i < s1->nb_cached_includes; i++)
9658 tcc_free(s1->cached_includes[i]);
9659 tcc_free(s1->cached_includes);
9661 for(i = 0; i < s1->nb_include_paths; i++)
9662 tcc_free(s1->include_paths[i]);
9663 tcc_free(s1->include_paths);
9665 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9666 tcc_free(s1->sysinclude_paths[i]);
9667 tcc_free(s1->sysinclude_paths);
9669 tcc_free(s1);
9672 int tcc_add_include_path(TCCState *s1, const char *pathname)
9674 char *pathname1;
9676 pathname1 = tcc_strdup(pathname);
9677 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9678 return 0;
9681 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9683 char *pathname1;
9685 pathname1 = tcc_strdup(pathname);
9686 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9687 return 0;
9690 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9692 const char *ext, *filename1;
9693 Elf32_Ehdr ehdr;
9694 int fd, ret;
9695 BufferedFile *saved_file;
9697 /* find source file type with extension */
9698 filename1 = strrchr(filename, '/');
9699 if (filename1)
9700 filename1++;
9701 else
9702 filename1 = filename;
9703 ext = strrchr(filename1, '.');
9704 if (ext)
9705 ext++;
9707 /* open the file */
9708 saved_file = file;
9709 file = tcc_open(s1, filename);
9710 if (!file) {
9711 if (flags & AFF_PRINT_ERROR) {
9712 error_noabort("file '%s' not found", filename);
9714 ret = -1;
9715 goto fail1;
9718 if (!ext || !strcmp(ext, "c")) {
9719 /* C file assumed */
9720 ret = tcc_compile(s1);
9721 } else
9722 #ifdef CONFIG_TCC_ASM
9723 if (!strcmp(ext, "S")) {
9724 /* preprocessed assembler */
9725 ret = tcc_assemble(s1, 1);
9726 } else if (!strcmp(ext, "s")) {
9727 /* non preprocessed assembler */
9728 ret = tcc_assemble(s1, 0);
9729 } else
9730 #endif
9732 fd = file->fd;
9733 /* assume executable format: auto guess file type */
9734 ret = read(fd, &ehdr, sizeof(ehdr));
9735 lseek(fd, 0, SEEK_SET);
9736 if (ret <= 0) {
9737 error_noabort("could not read header");
9738 goto fail;
9739 } else if (ret != sizeof(ehdr)) {
9740 goto try_load_script;
9743 if (ehdr.e_ident[0] == ELFMAG0 &&
9744 ehdr.e_ident[1] == ELFMAG1 &&
9745 ehdr.e_ident[2] == ELFMAG2 &&
9746 ehdr.e_ident[3] == ELFMAG3) {
9747 file->line_num = 0; /* do not display line number if error */
9748 if (ehdr.e_type == ET_REL) {
9749 ret = tcc_load_object_file(s1, fd, 0);
9750 } else if (ehdr.e_type == ET_DYN) {
9751 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9752 void *h;
9753 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9754 if (h)
9755 ret = 0;
9756 else
9757 ret = -1;
9758 } else {
9759 ret = tcc_load_dll(s1, fd, filename,
9760 (flags & AFF_REFERENCED_DLL) != 0);
9762 } else {
9763 error_noabort("unrecognized ELF file");
9764 goto fail;
9766 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9767 file->line_num = 0; /* do not display line number if error */
9768 ret = tcc_load_archive(s1, fd);
9769 } else
9770 #ifdef TCC_TARGET_COFF
9771 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
9772 ret = tcc_load_coff(s1, fd);
9773 } else
9774 #endif
9776 /* as GNU ld, consider it is an ld script if not recognized */
9777 try_load_script:
9778 ret = tcc_load_ldscript(s1);
9779 if (ret < 0) {
9780 error_noabort("unrecognized file type");
9781 goto fail;
9785 the_end:
9786 tcc_close(file);
9787 fail1:
9788 file = saved_file;
9789 return ret;
9790 fail:
9791 ret = -1;
9792 goto the_end;
9795 int tcc_add_file(TCCState *s, const char *filename)
9797 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9800 int tcc_add_library_path(TCCState *s, const char *pathname)
9802 char *pathname1;
9804 pathname1 = tcc_strdup(pathname);
9805 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9806 return 0;
9809 /* find and load a dll. Return non zero if not found */
9810 /* XXX: add '-rpath' option support ? */
9811 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9813 char buf[1024];
9814 int i;
9816 for(i = 0; i < s->nb_library_paths; i++) {
9817 snprintf(buf, sizeof(buf), "%s/%s",
9818 s->library_paths[i], filename);
9819 if (tcc_add_file_internal(s, buf, flags) == 0)
9820 return 0;
9822 return -1;
9825 /* the library name is the same as the argument of the '-l' option */
9826 int tcc_add_library(TCCState *s, const char *libraryname)
9828 char buf[1024];
9829 int i;
9831 /* first we look for the dynamic library if not static linking */
9832 if (!s->static_link) {
9833 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9834 if (tcc_add_dll(s, buf, 0) == 0)
9835 return 0;
9838 /* then we look for the static library */
9839 for(i = 0; i < s->nb_library_paths; i++) {
9840 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9841 s->library_paths[i], libraryname);
9842 if (tcc_add_file_internal(s, buf, 0) == 0)
9843 return 0;
9845 return -1;
9848 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9850 add_elf_sym(symtab_section, val, 0,
9851 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9852 SHN_ABS, name);
9853 return 0;
9856 int tcc_set_output_type(TCCState *s, int output_type)
9858 char buf[1024];
9860 s->output_type = output_type;
9862 if (!s->nostdinc) {
9863 /* default include paths */
9864 /* XXX: reverse order needed if -isystem support */
9865 tcc_add_sysinclude_path(s, "/usr/local/include");
9866 tcc_add_sysinclude_path(s, "/usr/include");
9867 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9868 tcc_add_sysinclude_path(s, buf);
9871 /* if bound checking, then add corresponding sections */
9872 #ifdef CONFIG_TCC_BCHECK
9873 if (do_bounds_check) {
9874 /* define symbol */
9875 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9876 /* create bounds sections */
9877 bounds_section = new_section(s, ".bounds",
9878 SHT_PROGBITS, SHF_ALLOC);
9879 lbounds_section = new_section(s, ".lbounds",
9880 SHT_PROGBITS, SHF_ALLOC);
9882 #endif
9884 if (s->char_is_unsigned) {
9885 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
9888 /* add debug sections */
9889 if (do_debug) {
9890 /* stab symbols */
9891 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9892 stab_section->sh_entsize = sizeof(Stab_Sym);
9893 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9894 put_elf_str(stabstr_section, "");
9895 stab_section->link = stabstr_section;
9896 /* put first entry */
9897 put_stabs("", 0, 0, 0, 0);
9900 /* add libc crt1/crti objects */
9901 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9902 !s->nostdlib) {
9903 if (output_type != TCC_OUTPUT_DLL)
9904 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9905 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9907 return 0;
9910 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9911 #define FD_INVERT 0x0002 /* invert value before storing */
9913 typedef struct FlagDef {
9914 uint16_t offset;
9915 uint16_t flags;
9916 const char *name;
9917 } FlagDef;
9919 static const FlagDef warning_defs[] = {
9920 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9921 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9922 { offsetof(TCCState, warn_error), 0, "error" },
9923 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
9924 "implicit-function-declaration" },
9927 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
9928 const char *name, int value)
9930 int i;
9931 const FlagDef *p;
9932 const char *r;
9934 r = name;
9935 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
9936 r += 3;
9937 value = !value;
9939 for(i = 0, p = flags; i < nb_flags; i++, p++) {
9940 if (!strcmp(r, p->name))
9941 goto found;
9943 return -1;
9944 found:
9945 if (p->flags & FD_INVERT)
9946 value = !value;
9947 *(int *)((uint8_t *)s + p->offset) = value;
9948 return 0;
9952 /* set/reset a warning */
9953 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9955 int i;
9956 const FlagDef *p;
9958 if (!strcmp(warning_name, "all")) {
9959 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9960 if (p->flags & WD_ALL)
9961 *(int *)((uint8_t *)s + p->offset) = 1;
9963 return 0;
9964 } else {
9965 return set_flag(s, warning_defs, countof(warning_defs),
9966 warning_name, value);
9970 static const FlagDef flag_defs[] = {
9971 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
9972 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
9973 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
9976 /* set/reset a flag */
9977 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
9979 return set_flag(s, flag_defs, countof(flag_defs),
9980 flag_name, value);
9983 #if !defined(LIBTCC)
9985 /* extract the basename of a file */
9986 static const char *tcc_basename(const char *name)
9988 const char *p;
9989 p = strrchr(name, '/');
9990 #ifdef WIN32
9991 if (!p)
9992 p = strrchr(name, '\\');
9993 #endif
9994 if (!p)
9995 p = name;
9996 else
9997 p++;
9998 return p;
10001 static int64_t getclock_us(void)
10003 #ifdef WIN32
10004 struct _timeb tb;
10005 _ftime(&tb);
10006 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10007 #else
10008 struct timeval tv;
10009 gettimeofday(&tv, NULL);
10010 return tv.tv_sec * 1000000LL + tv.tv_usec;
10011 #endif
10014 void help(void)
10016 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2004 Fabrice Bellard\n"
10017 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10018 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10019 " [infile1 infile2...] [-run infile args...]\n"
10020 "\n"
10021 "General options:\n"
10022 " -v display current version\n"
10023 " -c compile only - generate an object file\n"
10024 " -o outfile set output filename\n"
10025 " -Bdir set tcc internal library path\n"
10026 " -bench output compilation statistics\n"
10027 " -run run compiled source\n"
10028 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10029 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10030 " -w disable all warnings\n"
10031 "Preprocessor options:\n"
10032 " -Idir add include path 'dir'\n"
10033 " -Dsym[=val] define 'sym' with value 'val'\n"
10034 " -Usym undefine 'sym'\n"
10035 "Linker options:\n"
10036 " -Ldir add library path 'dir'\n"
10037 " -llib link with dynamic or static library 'lib'\n"
10038 " -shared generate a shared library\n"
10039 " -static static linking\n"
10040 " -rdynamic export all global symbols to dynamic linker\n"
10041 " -r relocatable output\n"
10042 "Debugger options:\n"
10043 " -g generate runtime debug info\n"
10044 #ifdef CONFIG_TCC_BCHECK
10045 " -b compile with built-in memory and bounds checker (implies -g)\n"
10046 #endif
10047 " -bt N show N callers in stack traces\n"
10051 #define TCC_OPTION_HAS_ARG 0x0001
10052 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10054 typedef struct TCCOption {
10055 const char *name;
10056 uint16_t index;
10057 uint16_t flags;
10058 } TCCOption;
10060 enum {
10061 TCC_OPTION_HELP,
10062 TCC_OPTION_I,
10063 TCC_OPTION_D,
10064 TCC_OPTION_U,
10065 TCC_OPTION_L,
10066 TCC_OPTION_B,
10067 TCC_OPTION_l,
10068 TCC_OPTION_bench,
10069 TCC_OPTION_bt,
10070 TCC_OPTION_b,
10071 TCC_OPTION_g,
10072 TCC_OPTION_c,
10073 TCC_OPTION_static,
10074 TCC_OPTION_shared,
10075 TCC_OPTION_o,
10076 TCC_OPTION_r,
10077 TCC_OPTION_Wl,
10078 TCC_OPTION_W,
10079 TCC_OPTION_O,
10080 TCC_OPTION_m,
10081 TCC_OPTION_f,
10082 TCC_OPTION_nostdinc,
10083 TCC_OPTION_nostdlib,
10084 TCC_OPTION_print_search_dirs,
10085 TCC_OPTION_rdynamic,
10086 TCC_OPTION_run,
10087 TCC_OPTION_v,
10088 TCC_OPTION_w,
10091 static const TCCOption tcc_options[] = {
10092 { "h", TCC_OPTION_HELP, 0 },
10093 { "?", TCC_OPTION_HELP, 0 },
10094 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10095 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10096 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10097 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10098 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10099 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10100 { "bench", TCC_OPTION_bench, 0 },
10101 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10102 #ifdef CONFIG_TCC_BCHECK
10103 { "b", TCC_OPTION_b, 0 },
10104 #endif
10105 { "g", TCC_OPTION_g, 0 },
10106 { "c", TCC_OPTION_c, 0 },
10107 { "static", TCC_OPTION_static, 0 },
10108 { "shared", TCC_OPTION_shared, 0 },
10109 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10110 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10111 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10112 { "r", TCC_OPTION_r, 0 },
10113 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10114 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10115 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10116 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10117 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10118 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10119 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10120 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10121 { "v", TCC_OPTION_v, 0 },
10122 { "w", TCC_OPTION_w, 0 },
10123 { NULL },
10126 /* convert 'str' into an array of space separated strings */
10127 static int expand_args(char ***pargv, const char *str)
10129 const char *s1;
10130 char **argv, *arg;
10131 int argc, len;
10133 argc = 0;
10134 argv = NULL;
10135 for(;;) {
10136 while (is_space(*str))
10137 str++;
10138 if (*str == '\0')
10139 break;
10140 s1 = str;
10141 while (*str != '\0' && !is_space(*str))
10142 str++;
10143 len = str - s1;
10144 arg = tcc_malloc(len + 1);
10145 memcpy(arg, s1, len);
10146 arg[len] = '\0';
10147 dynarray_add((void ***)&argv, &argc, arg);
10149 *pargv = argv;
10150 return argc;
10153 static char **files;
10154 static int nb_files, nb_libraries;
10155 static int multiple_files;
10156 static int print_search_dirs;
10157 static int output_type;
10158 static int reloc_output;
10159 static const char *outfile;
10161 int parse_args(TCCState *s, int argc, char **argv)
10163 int optind;
10164 const TCCOption *popt;
10165 const char *optarg, *p1, *r1;
10166 char *r;
10168 optind = 0;
10169 while (1) {
10170 if (optind >= argc) {
10171 if (nb_files == 0 && !print_search_dirs)
10172 goto show_help;
10173 else
10174 break;
10176 r = argv[optind++];
10177 if (r[0] != '-') {
10178 /* add a new file */
10179 dynarray_add((void ***)&files, &nb_files, r);
10180 if (!multiple_files) {
10181 optind--;
10182 /* argv[0] will be this file */
10183 break;
10185 } else {
10186 /* find option in table (match only the first chars */
10187 popt = tcc_options;
10188 for(;;) {
10189 p1 = popt->name;
10190 if (p1 == NULL)
10191 error("invalid option -- '%s'", r);
10192 r1 = r + 1;
10193 for(;;) {
10194 if (*p1 == '\0')
10195 goto option_found;
10196 if (*r1 != *p1)
10197 break;
10198 p1++;
10199 r1++;
10201 popt++;
10203 option_found:
10204 if (popt->flags & TCC_OPTION_HAS_ARG) {
10205 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10206 optarg = r1;
10207 } else {
10208 if (optind >= argc)
10209 error("argument to '%s' is missing", r);
10210 optarg = argv[optind++];
10212 } else {
10213 if (*r1 != '\0')
10214 goto show_help;
10215 optarg = NULL;
10218 switch(popt->index) {
10219 case TCC_OPTION_HELP:
10220 show_help:
10221 help();
10222 exit(1);
10223 case TCC_OPTION_I:
10224 if (tcc_add_include_path(s, optarg) < 0)
10225 error("too many include paths");
10226 break;
10227 case TCC_OPTION_D:
10229 char *sym, *value;
10230 sym = (char *)optarg;
10231 value = strchr(sym, '=');
10232 if (value) {
10233 *value = '\0';
10234 value++;
10236 tcc_define_symbol(s, sym, value);
10238 break;
10239 case TCC_OPTION_U:
10240 tcc_undefine_symbol(s, optarg);
10241 break;
10242 case TCC_OPTION_L:
10243 tcc_add_library_path(s, optarg);
10244 break;
10245 case TCC_OPTION_B:
10246 /* set tcc utilities path (mainly for tcc development) */
10247 tcc_lib_path = optarg;
10248 break;
10249 case TCC_OPTION_l:
10250 dynarray_add((void ***)&files, &nb_files, r);
10251 nb_libraries++;
10252 break;
10253 case TCC_OPTION_bench:
10254 do_bench = 1;
10255 break;
10256 case TCC_OPTION_bt:
10257 num_callers = atoi(optarg);
10258 break;
10259 #ifdef CONFIG_TCC_BCHECK
10260 case TCC_OPTION_b:
10261 do_bounds_check = 1;
10262 do_debug = 1;
10263 break;
10264 #endif
10265 case TCC_OPTION_g:
10266 do_debug = 1;
10267 break;
10268 case TCC_OPTION_c:
10269 multiple_files = 1;
10270 output_type = TCC_OUTPUT_OBJ;
10271 break;
10272 case TCC_OPTION_static:
10273 s->static_link = 1;
10274 break;
10275 case TCC_OPTION_shared:
10276 output_type = TCC_OUTPUT_DLL;
10277 break;
10278 case TCC_OPTION_o:
10279 multiple_files = 1;
10280 outfile = optarg;
10281 break;
10282 case TCC_OPTION_r:
10283 /* generate a .o merging several output files */
10284 reloc_output = 1;
10285 output_type = TCC_OUTPUT_OBJ;
10286 break;
10287 case TCC_OPTION_nostdinc:
10288 s->nostdinc = 1;
10289 break;
10290 case TCC_OPTION_nostdlib:
10291 s->nostdlib = 1;
10292 break;
10293 case TCC_OPTION_print_search_dirs:
10294 print_search_dirs = 1;
10295 break;
10296 case TCC_OPTION_run:
10298 int argc1;
10299 char **argv1;
10300 argc1 = expand_args(&argv1, optarg);
10301 if (argc1 > 0) {
10302 parse_args(s, argc1, argv1);
10304 multiple_files = 0;
10305 output_type = TCC_OUTPUT_MEMORY;
10307 break;
10308 case TCC_OPTION_v:
10309 printf("tcc version %s\n", TCC_VERSION);
10310 exit(0);
10311 case TCC_OPTION_f:
10312 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10313 goto unsupported_option;
10314 break;
10315 case TCC_OPTION_W:
10316 if (tcc_set_warning(s, optarg, 1) < 0 &&
10317 s->warn_unsupported)
10318 goto unsupported_option;
10319 break;
10320 case TCC_OPTION_w:
10321 s->warn_none = 1;
10322 break;
10323 case TCC_OPTION_rdynamic:
10324 s->rdynamic = 1;
10325 break;
10326 case TCC_OPTION_Wl:
10328 const char *p;
10329 if (strstart(optarg, "-Ttext,", &p)) {
10330 s->text_addr = strtoul(p, NULL, 16);
10331 s->has_text_addr = 1;
10332 } else if (strstart(optarg, "--oformat,", &p)) {
10333 if (strstart(p, "elf32-", NULL)) {
10334 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10335 } else if (!strcmp(p, "binary")) {
10336 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10337 } else
10338 #ifdef TCC_TARGET_COFF
10339 if (!strcmp(p, "coff")) {
10340 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10341 } else
10342 #endif
10344 error("target %s not found", p);
10346 } else {
10347 error("unsupported linker option '%s'", optarg);
10350 break;
10351 default:
10352 if (s->warn_unsupported) {
10353 unsupported_option:
10354 warning("unsupported option '%s'", r);
10356 break;
10360 return optind;
10363 int main(int argc, char **argv)
10365 int i;
10366 TCCState *s;
10367 int nb_objfiles, ret, optind;
10368 char objfilename[1024];
10369 int64_t start_time = 0;
10371 s = tcc_new();
10372 output_type = TCC_OUTPUT_EXE;
10373 outfile = NULL;
10374 multiple_files = 1;
10375 files = NULL;
10376 nb_files = 0;
10377 nb_libraries = 0;
10378 reloc_output = 0;
10379 print_search_dirs = 0;
10381 optind = parse_args(s, argc - 1, argv + 1) + 1;
10383 if (print_search_dirs) {
10384 /* enough for Linux kernel */
10385 printf("install: %s/\n", tcc_lib_path);
10386 return 0;
10389 nb_objfiles = nb_files - nb_libraries;
10391 /* if outfile provided without other options, we output an
10392 executable */
10393 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10394 output_type = TCC_OUTPUT_EXE;
10396 /* check -c consistency : only single file handled. XXX: checks file type */
10397 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10398 /* accepts only a single input file */
10399 if (nb_objfiles != 1)
10400 error("cannot specify multiple files with -c");
10401 if (nb_libraries != 0)
10402 error("cannot specify libraries with -c");
10405 /* compute default outfile name */
10406 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
10407 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10408 char *ext;
10409 /* strip path */
10410 pstrcpy(objfilename, sizeof(objfilename) - 1,
10411 tcc_basename(files[0]));
10412 /* add .o extension */
10413 ext = strrchr(objfilename, '.');
10414 if (!ext)
10415 goto default_outfile;
10416 strcpy(ext + 1, "o");
10417 } else {
10418 default_outfile:
10419 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10421 outfile = objfilename;
10424 if (do_bench) {
10425 start_time = getclock_us();
10428 tcc_set_output_type(s, output_type);
10430 /* compile or add each files or library */
10431 for(i = 0;i < nb_files; i++) {
10432 const char *filename;
10434 filename = files[i];
10435 if (filename[0] == '-') {
10436 if (tcc_add_library(s, filename + 2) < 0)
10437 error("cannot find %s", filename);
10438 } else {
10439 if (tcc_add_file(s, filename) < 0) {
10440 ret = 1;
10441 goto the_end;
10446 /* free all files */
10447 tcc_free(files);
10449 if (do_bench) {
10450 double total_time;
10451 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10452 if (total_time < 0.001)
10453 total_time = 0.001;
10454 if (total_bytes < 1)
10455 total_bytes = 1;
10456 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10457 tok_ident - TOK_IDENT, total_lines, total_bytes,
10458 total_time, (int)(total_lines / total_time),
10459 total_bytes / total_time / 1000000.0);
10462 if (s->output_type != TCC_OUTPUT_MEMORY) {
10463 tcc_output_file(s, outfile);
10464 ret = 0;
10465 } else {
10466 ret = tcc_run(s, argc - optind, argv + optind);
10468 the_end:
10469 /* XXX: cannot do it with bound checking because of the malloc hooks */
10470 if (!do_bounds_check)
10471 tcc_delete(s);
10473 #ifdef MEM_DEBUG
10474 if (do_bench) {
10475 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10477 #endif
10478 return ret;
10481 #endif