primitive fastcall functions support - -fno-common option - -Ttext linker option...
[tinycc.git] / tcc.c
blob0d5d6307a835ad6a32c36b58fc9690cfc9af6715
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define _GNU_SOURCE
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <math.h>
29 #include <unistd.h>
30 #include <signal.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <setjmp.h>
34 #include <time.h>
35 #ifdef WIN32
36 #include <sys/timeb.h>
37 #define CONFIG_TCC_STATIC
38 #endif
39 #ifndef WIN32
40 #include <sys/time.h>
41 #include <sys/ucontext.h>
42 #endif
43 #include "elf.h"
44 #include "stab.h"
45 #ifndef CONFIG_TCC_STATIC
46 #include <dlfcn.h>
47 #endif
49 #include "libtcc.h"
51 /* parser debug */
52 //#define PARSE_DEBUG
53 /* preprocessor debug */
54 //#define PP_DEBUG
55 /* include file debug */
56 //#define INC_DEBUG
58 //#define MEM_DEBUG
60 /* assembler debug */
61 //#define ASM_DEBUG
63 /* target selection */
64 //#define TCC_TARGET_I386 /* i386 code generator */
65 //#define TCC_TARGET_ARM /* ARMv4 code generator */
66 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
68 /* default target is I386 */
69 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
70 !defined(TCC_TARGET_C67)
71 #define TCC_TARGET_I386
72 #endif
74 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
75 !defined(TCC_TARGET_C67)
76 #define CONFIG_TCC_BCHECK /* enable bound checking code */
77 #endif
79 /* define it to include assembler support */
80 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
81 #define CONFIG_TCC_ASM
82 #endif
84 /* object format selection */
85 #if defined(TCC_TARGET_C67)
86 #define TCC_TARGET_COFF
87 #endif
89 #define FALSE 0
90 #define false 0
91 #define TRUE 1
92 #define true 1
93 typedef int BOOL;
95 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
96 executables or dlls */
97 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
99 #define INCLUDE_STACK_SIZE 32
100 #define IFDEF_STACK_SIZE 64
101 #define VSTACK_SIZE 64
102 #define STRING_MAX_SIZE 1024
104 #define TOK_HASH_SIZE 2048 /* must be a power of two */
105 #define TOK_ALLOC_INCR 512 /* must be a power of two */
106 #define TOK_STR_ALLOC_INCR_BITS 6
107 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
108 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
110 /* token symbol management */
111 typedef struct TokenSym {
112 struct TokenSym *hash_next;
113 struct Sym *sym_define; /* direct pointer to define */
114 struct Sym *sym_label; /* direct pointer to label */
115 struct Sym *sym_struct; /* direct pointer to structure */
116 struct Sym *sym_identifier; /* direct pointer to identifier */
117 int tok; /* token number */
118 int len;
119 char str[1];
120 } TokenSym;
122 typedef struct CString {
123 int size; /* size in bytes */
124 void *data; /* either 'char *' or 'int *' */
125 int size_allocated;
126 void *data_allocated; /* if non NULL, data has been malloced */
127 } CString;
129 /* type definition */
130 typedef struct CType {
131 int t;
132 struct Sym *ref;
133 } CType;
135 /* constant value */
136 typedef union CValue {
137 long double ld;
138 double d;
139 float f;
140 int i;
141 unsigned int ui;
142 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
143 long long ll;
144 unsigned long long ull;
145 struct CString *cstr;
146 void *ptr;
147 int tab[1];
148 } CValue;
150 /* value on stack */
151 typedef struct SValue {
152 CType type; /* type */
153 unsigned short r; /* register + flags */
154 unsigned short r2; /* second register, used for 'long long'
155 type. If not used, set to VT_CONST */
156 CValue c; /* constant, if VT_CONST */
157 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
158 } SValue;
160 /* symbol management */
161 typedef struct Sym {
162 int v; /* symbol token */
163 int r; /* associated register */
164 int c; /* associated number */
165 CType type; /* associated type */
166 struct Sym *next; /* next related symbol */
167 struct Sym *prev; /* prev symbol in stack */
168 struct Sym *prev_tok; /* previous symbol for this token */
169 } Sym;
171 /* section definition */
172 /* XXX: use directly ELF structure for parameters ? */
173 /* special flag to indicate that the section should not be linked to
174 the other ones */
175 #define SHF_PRIVATE 0x80000000
177 typedef struct Section {
178 unsigned long data_offset; /* current data offset */
179 unsigned char *data; /* section data */
180 unsigned long data_allocated; /* used for realloc() handling */
181 int sh_name; /* elf section name (only used during output) */
182 int sh_num; /* elf section number */
183 int sh_type; /* elf section type */
184 int sh_flags; /* elf section flags */
185 int sh_info; /* elf section info */
186 int sh_addralign; /* elf section alignment */
187 int sh_entsize; /* elf entry size */
188 unsigned long sh_size; /* section size (only used during output) */
189 unsigned long sh_addr; /* address at which the section is relocated */
190 unsigned long sh_offset; /* address at which the section is relocated */
191 int nb_hashed_syms; /* used to resize the hash table */
192 struct Section *link; /* link to another section */
193 struct Section *reloc; /* corresponding section for relocation, if any */
194 struct Section *hash; /* hash table for symbols */
195 struct Section *next;
196 char name[1]; /* section name */
197 } Section;
199 typedef struct DLLReference {
200 int level;
201 char name[1];
202 } DLLReference;
204 /* GNUC attribute definition */
205 typedef struct AttributeDef {
206 int aligned;
207 Section *section;
208 unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
209 } AttributeDef;
211 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
212 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
213 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
215 /* stored in 'Sym.c' field */
216 #define FUNC_NEW 1 /* ansi function prototype */
217 #define FUNC_OLD 2 /* old function prototype */
218 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
220 /* stored in 'Sym.r' field */
221 #define FUNC_CDECL 0 /* standard c call */
222 #define FUNC_STDCALL 1 /* pascal c call */
223 #define FUNC_FASTCALL1 2 /* first param in %eax */
224 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
225 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
227 /* field 'Sym.t' for macros */
228 #define MACRO_OBJ 0 /* object like macro */
229 #define MACRO_FUNC 1 /* function like macro */
231 /* field 'Sym.r' for C labels */
232 #define LABEL_DEFINED 0 /* label is defined */
233 #define LABEL_FORWARD 1 /* label is forward defined */
234 #define LABEL_DECLARED 2 /* label is declared but never used */
236 /* type_decl() types */
237 #define TYPE_ABSTRACT 1 /* type without variable */
238 #define TYPE_DIRECT 2 /* type with variable */
240 #define IO_BUF_SIZE 8192
242 typedef struct BufferedFile {
243 uint8_t *buf_ptr;
244 uint8_t *buf_end;
245 int fd;
246 int line_num; /* current line number - here to simplify code */
247 int ifndef_macro; /* #ifndef macro / #endif search */
248 int ifndef_macro_saved; /* saved ifndef_macro */
249 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
250 char inc_type; /* type of include */
251 char inc_filename[512]; /* filename specified by the user */
252 char filename[1024]; /* current filename - here to simplify code */
253 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
254 } BufferedFile;
256 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
257 #define CH_EOF (-1) /* end of file */
259 /* parsing state (used to save parser state to reparse part of the
260 source several times) */
261 typedef struct ParseState {
262 int *macro_ptr;
263 int line_num;
264 int tok;
265 CValue tokc;
266 } ParseState;
268 /* used to record tokens */
269 typedef struct TokenString {
270 int *str;
271 int len;
272 int allocated_len;
273 int last_line_num;
274 } TokenString;
276 /* include file cache, used to find files faster and also to eliminate
277 inclusion if the include file is protected by #ifndef ... #endif */
278 typedef struct CachedInclude {
279 int ifndef_macro;
280 char type; /* '"' or '>' to give include type */
281 char filename[1]; /* path specified in #include */
282 } CachedInclude;
284 /* parser */
285 static struct BufferedFile *file;
286 static int ch, tok;
287 static CValue tokc;
288 static CString tokcstr; /* current parsed string, if any */
289 /* additional informations about token */
290 static int tok_flags;
291 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
292 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
293 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
295 static int *macro_ptr, *macro_ptr_allocated;
296 static int *unget_saved_macro_ptr;
297 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
298 static int unget_buffer_enabled;
299 static int parse_flags;
300 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
301 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
302 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
303 token. line feed is also
304 returned at eof */
305 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
307 static Section *text_section, *data_section, *bss_section; /* predefined sections */
308 static Section *cur_text_section; /* current section where function code is
309 generated */
310 static Section *last_text_section; /* to handle .previous asm directive */
311 /* bound check related sections */
312 static Section *bounds_section; /* contains global data bound description */
313 static Section *lbounds_section; /* contains local data bound description */
314 /* symbol sections */
315 static Section *symtab_section, *strtab_section;
317 /* debug sections */
318 static Section *stab_section, *stabstr_section;
320 /* loc : local variable index
321 ind : output code index
322 rsym: return symbol
323 anon_sym: anonymous symbol index
325 static int rsym, anon_sym, ind, loc;
326 /* expression generation modifiers */
327 static int const_wanted; /* true if constant wanted */
328 static int nocode_wanted; /* true if no code generation wanted for an expression */
329 static int global_expr; /* true if compound literals must be allocated
330 globally (used during initializers parsing */
331 static CType func_vt; /* current function return type (used by return
332 instruction) */
333 static int func_vc;
334 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
335 static int tok_ident;
336 static TokenSym **table_ident;
337 static TokenSym *hash_ident[TOK_HASH_SIZE];
338 static char token_buf[STRING_MAX_SIZE + 1];
339 static char *funcname;
340 static Sym *global_stack, *local_stack;
341 static Sym *define_stack;
342 static Sym *global_label_stack, *local_label_stack;
344 static SValue vstack[VSTACK_SIZE], *vtop;
345 /* some predefined types */
346 static CType char_pointer_type, func_old_type, int_type;
347 /* true if isid(c) || isnum(c) */
348 static unsigned char isidnum_table[256];
350 /* compile with debug symbol (and use them if error during execution) */
351 static int do_debug = 0;
353 /* compile with built-in memory and bounds checker */
354 static int do_bounds_check = 0;
356 /* display benchmark infos */
357 #if !defined(LIBTCC)
358 static int do_bench = 0;
359 #endif
360 static int total_lines;
361 static int total_bytes;
363 /* use GNU C extensions */
364 static int gnu_ext = 1;
366 /* use Tiny C extensions */
367 static int tcc_ext = 1;
369 /* max number of callers shown if error */
370 static int num_callers = 6;
371 static const char **rt_bound_error_msg;
373 /* XXX: get rid of this ASAP */
374 static struct TCCState *tcc_state;
376 /* give the path of the tcc libraries */
377 static const char *tcc_lib_path = CONFIG_TCC_LIBDIR "/tcc";
379 struct TCCState {
380 int output_type;
382 BufferedFile **include_stack_ptr;
383 int *ifdef_stack_ptr;
385 /* include file handling */
386 char **include_paths;
387 int nb_include_paths;
388 char **sysinclude_paths;
389 int nb_sysinclude_paths;
390 CachedInclude **cached_includes;
391 int nb_cached_includes;
393 char **library_paths;
394 int nb_library_paths;
396 /* array of all loaded dlls (including those referenced by loaded
397 dlls) */
398 DLLReference **loaded_dlls;
399 int nb_loaded_dlls;
401 /* sections */
402 Section **sections;
403 int nb_sections; /* number of sections, including first dummy section */
405 /* got handling */
406 Section *got;
407 Section *plt;
408 unsigned long *got_offsets;
409 int nb_got_offsets;
410 /* give the correspondance from symtab indexes to dynsym indexes */
411 int *symtab_to_dynsym;
413 /* temporary dynamic symbol sections (for dll loading) */
414 Section *dynsymtab_section;
415 /* exported dynamic symbol section */
416 Section *dynsym;
418 int nostdinc; /* if true, no standard headers are added */
419 int nostdlib; /* if true, no standard libraries are added */
421 int nocommon; /* if true, do not use common symbols for .bss data */
423 /* if true, static linking is performed */
424 int static_link;
426 /* if true, all symbols are exported */
427 int rdynamic;
429 /* if true, only link in referenced objects from archive */
430 int alacarte_link;
432 /* address of text section */
433 unsigned long text_addr;
434 int has_text_addr;
436 /* C language options */
437 int char_is_unsigned;
439 /* warning switches */
440 int warn_write_strings;
441 int warn_unsupported;
442 int warn_error;
443 int warn_none;
444 int warn_implicit_function_declaration;
446 /* error handling */
447 void *error_opaque;
448 void (*error_func)(void *opaque, const char *msg);
449 int error_set_jmp_enabled;
450 jmp_buf error_jmp_buf;
451 int nb_errors;
453 /* tiny assembler state */
454 Sym *asm_labels;
456 /* see include_stack_ptr */
457 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
459 /* see ifdef_stack_ptr */
460 int ifdef_stack[IFDEF_STACK_SIZE];
463 /* The current value can be: */
464 #define VT_VALMASK 0x00ff
465 #define VT_CONST 0x00f0 /* constant in vc
466 (must be first non register value) */
467 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
468 #define VT_LOCAL 0x00f2 /* offset on stack */
469 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
470 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
471 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
472 #define VT_LVAL 0x0100 /* var is an lvalue */
473 #define VT_SYM 0x0200 /* a symbol value is added */
474 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
475 char/short stored in integer registers) */
476 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
477 dereferencing value */
478 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
479 bounding function call point is in vc */
480 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
481 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
482 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
483 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
485 /* types */
486 #define VT_INT 0 /* integer type */
487 #define VT_BYTE 1 /* signed byte type */
488 #define VT_SHORT 2 /* short type */
489 #define VT_VOID 3 /* void type */
490 #define VT_PTR 4 /* pointer */
491 #define VT_ENUM 5 /* enum definition */
492 #define VT_FUNC 6 /* function type */
493 #define VT_STRUCT 7 /* struct/union definition */
494 #define VT_FLOAT 8 /* IEEE float */
495 #define VT_DOUBLE 9 /* IEEE double */
496 #define VT_LDOUBLE 10 /* IEEE long double */
497 #define VT_BOOL 11 /* ISOC99 boolean type */
498 #define VT_LLONG 12 /* 64 bit integer */
499 #define VT_LONG 13 /* long integer (NEVER USED as type, only
500 during parsing) */
501 #define VT_BTYPE 0x000f /* mask for basic type */
502 #define VT_UNSIGNED 0x0010 /* unsigned type */
503 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
504 #define VT_BITFIELD 0x0040 /* bitfield modifier */
505 #define VT_CONSTANT 0x0800 /* const modifier */
506 #define VT_VOLATILE 0x1000 /* volatile modifier */
507 #define VT_SIGNED 0x2000 /* signed type */
509 /* storage */
510 #define VT_EXTERN 0x00000080 /* extern definition */
511 #define VT_STATIC 0x00000100 /* static variable */
512 #define VT_TYPEDEF 0x00000200 /* typedef definition */
513 #define VT_INLINE 0x00000400 /* inline definition */
515 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
517 /* type mask (except storage) */
518 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
519 #define VT_TYPE (~(VT_STORAGE))
521 /* token values */
523 /* warning: the following compare tokens depend on i386 asm code */
524 #define TOK_ULT 0x92
525 #define TOK_UGE 0x93
526 #define TOK_EQ 0x94
527 #define TOK_NE 0x95
528 #define TOK_ULE 0x96
529 #define TOK_UGT 0x97
530 #define TOK_LT 0x9c
531 #define TOK_GE 0x9d
532 #define TOK_LE 0x9e
533 #define TOK_GT 0x9f
535 #define TOK_LAND 0xa0
536 #define TOK_LOR 0xa1
538 #define TOK_DEC 0xa2
539 #define TOK_MID 0xa3 /* inc/dec, to void constant */
540 #define TOK_INC 0xa4
541 #define TOK_UDIV 0xb0 /* unsigned division */
542 #define TOK_UMOD 0xb1 /* unsigned modulo */
543 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
544 #define TOK_CINT 0xb3 /* number in tokc */
545 #define TOK_CCHAR 0xb4 /* char constant in tokc */
546 #define TOK_STR 0xb5 /* pointer to string in tokc */
547 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
548 #define TOK_LCHAR 0xb7
549 #define TOK_LSTR 0xb8
550 #define TOK_CFLOAT 0xb9 /* float constant */
551 #define TOK_LINENUM 0xba /* line number info */
552 #define TOK_CDOUBLE 0xc0 /* double constant */
553 #define TOK_CLDOUBLE 0xc1 /* long double constant */
554 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
555 #define TOK_ADDC1 0xc3 /* add with carry generation */
556 #define TOK_ADDC2 0xc4 /* add with carry use */
557 #define TOK_SUBC1 0xc5 /* add with carry generation */
558 #define TOK_SUBC2 0xc6 /* add with carry use */
559 #define TOK_CUINT 0xc8 /* unsigned int constant */
560 #define TOK_CLLONG 0xc9 /* long long constant */
561 #define TOK_CULLONG 0xca /* unsigned long long constant */
562 #define TOK_ARROW 0xcb
563 #define TOK_DOTS 0xcc /* three dots */
564 #define TOK_SHR 0xcd /* unsigned shift right */
565 #define TOK_PPNUM 0xce /* preprocessor number */
567 #define TOK_SHL 0x01 /* shift left */
568 #define TOK_SAR 0x02 /* signed shift right */
570 /* assignement operators : normal operator or 0x80 */
571 #define TOK_A_MOD 0xa5
572 #define TOK_A_AND 0xa6
573 #define TOK_A_MUL 0xaa
574 #define TOK_A_ADD 0xab
575 #define TOK_A_SUB 0xad
576 #define TOK_A_DIV 0xaf
577 #define TOK_A_XOR 0xde
578 #define TOK_A_OR 0xfc
579 #define TOK_A_SHL 0x81
580 #define TOK_A_SAR 0x82
582 #ifndef offsetof
583 #define offsetof(type, field) ((size_t) &((type *)0)->field)
584 #endif
586 #ifndef countof
587 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
588 #endif
590 /* WARNING: the content of this string encodes token numbers */
591 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";
593 #define TOK_EOF (-1) /* end of file */
594 #define TOK_LINEFEED 10 /* line feed */
596 /* all identificators and strings have token above that */
597 #define TOK_IDENT 256
599 /* only used for i386 asm opcodes definitions */
600 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
602 #define DEF_BWL(x) \
603 DEF(TOK_ASM_ ## x ## b, #x "b") \
604 DEF(TOK_ASM_ ## x ## w, #x "w") \
605 DEF(TOK_ASM_ ## x ## l, #x "l") \
606 DEF(TOK_ASM_ ## x, #x)
608 #define DEF_WL(x) \
609 DEF(TOK_ASM_ ## x ## w, #x "w") \
610 DEF(TOK_ASM_ ## x ## l, #x "l") \
611 DEF(TOK_ASM_ ## x, #x)
613 #define DEF_FP1(x) \
614 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
615 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
616 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
617 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
619 #define DEF_FP(x) \
620 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
621 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
622 DEF_FP1(x)
624 #define DEF_ASMTEST(x) \
625 DEF_ASM(x ## o) \
626 DEF_ASM(x ## no) \
627 DEF_ASM(x ## b) \
628 DEF_ASM(x ## c) \
629 DEF_ASM(x ## nae) \
630 DEF_ASM(x ## nb) \
631 DEF_ASM(x ## nc) \
632 DEF_ASM(x ## ae) \
633 DEF_ASM(x ## e) \
634 DEF_ASM(x ## z) \
635 DEF_ASM(x ## ne) \
636 DEF_ASM(x ## nz) \
637 DEF_ASM(x ## be) \
638 DEF_ASM(x ## na) \
639 DEF_ASM(x ## nbe) \
640 DEF_ASM(x ## a) \
641 DEF_ASM(x ## s) \
642 DEF_ASM(x ## ns) \
643 DEF_ASM(x ## p) \
644 DEF_ASM(x ## pe) \
645 DEF_ASM(x ## np) \
646 DEF_ASM(x ## po) \
647 DEF_ASM(x ## l) \
648 DEF_ASM(x ## nge) \
649 DEF_ASM(x ## nl) \
650 DEF_ASM(x ## ge) \
651 DEF_ASM(x ## le) \
652 DEF_ASM(x ## ng) \
653 DEF_ASM(x ## nle) \
654 DEF_ASM(x ## g)
656 #define TOK_ASM_int TOK_INT
658 enum tcc_token {
659 TOK_LAST = TOK_IDENT - 1,
660 #define DEF(id, str) id,
661 #include "tcctok.h"
662 #undef DEF
665 static const char tcc_keywords[] =
666 #define DEF(id, str) str "\0"
667 #include "tcctok.h"
668 #undef DEF
671 #define TOK_UIDENT TOK_DEFINE
673 #ifdef WIN32
674 #define snprintf _snprintf
675 #define vsnprintf _vsnprintf
676 #endif
678 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
679 /* currently incorrect */
680 long double strtold(const char *nptr, char **endptr)
682 return (long double)strtod(nptr, endptr);
684 float strtof(const char *nptr, char **endptr)
686 return (float)strtod(nptr, endptr);
688 #else
689 /* XXX: need to define this to use them in non ISOC99 context */
690 extern float strtof (const char *__nptr, char **__endptr);
691 extern long double strtold (const char *__nptr, char **__endptr);
692 #endif
694 static char *pstrcpy(char *buf, int buf_size, const char *s);
695 static char *pstrcat(char *buf, int buf_size, const char *s);
697 static void next(void);
698 static void next_nomacro(void);
699 static void parse_expr_type(CType *type);
700 static void expr_type(CType *type);
701 static void unary_type(CType *type);
702 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
703 int case_reg, int is_expr);
704 static int expr_const(void);
705 static void expr_eq(void);
706 static void gexpr(void);
707 static void decl(int l);
708 static void decl_initializer(CType *type, Section *sec, unsigned long c,
709 int first, int size_only);
710 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
711 int has_init, int v, int scope);
712 int gv(int rc);
713 void gv2(int rc1, int rc2);
714 void move_reg(int r, int s);
715 void save_regs(int n);
716 void save_reg(int r);
717 void vpop(void);
718 void vswap(void);
719 void vdup(void);
720 int get_reg(int rc);
721 int get_reg_ex(int rc,int rc2);
723 static void macro_subst(TokenString *tok_str, Sym **nested_list,
724 const int *macro_str, int can_read_stream);
725 int save_reg_forced(int r);
726 void gen_op(int op);
727 void force_charshort_cast(int t);
728 static void gen_cast(CType *type);
729 void vstore(void);
730 static Sym *sym_find(int v);
731 static Sym *sym_push(int v, CType *type, int r, int c);
733 /* type handling */
734 static int type_size(CType *type, int *a);
735 static inline CType *pointed_type(CType *type);
736 static int pointed_size(CType *type);
737 static int lvalue_type(int t);
738 static int parse_btype(CType *type, AttributeDef *ad);
739 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
740 static int is_compatible_types(CType *type1, CType *type2);
742 int ieee_finite(double d);
743 void error(const char *fmt, ...);
744 void vpushi(int v);
745 void vrott(int n);
746 void vnrott(int n);
747 void lexpand_nr(void);
748 static void vpush_global_sym(CType *type, int v);
749 void vset(CType *type, int r, int v);
750 void type_to_str(char *buf, int buf_size,
751 CType *type, const char *varstr);
752 char *get_tok_str(int v, CValue *cv);
753 static Sym *get_sym_ref(CType *type, Section *sec,
754 unsigned long offset, unsigned long size);
755 static Sym *external_global_sym(int v, CType *type, int r);
757 /* section generation */
758 static void section_realloc(Section *sec, unsigned long new_size);
759 static void *section_ptr_add(Section *sec, unsigned long size);
760 static void put_extern_sym(Sym *sym, Section *section,
761 unsigned long value, unsigned long size);
762 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
763 static int put_elf_str(Section *s, const char *sym);
764 static int put_elf_sym(Section *s,
765 unsigned long value, unsigned long size,
766 int info, int other, int shndx, const char *name);
767 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
768 int info, int sh_num, const char *name);
769 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
770 int type, int symbol);
771 static void put_stabs(const char *str, int type, int other, int desc,
772 unsigned long value);
773 static void put_stabs_r(const char *str, int type, int other, int desc,
774 unsigned long value, Section *sec, int sym_index);
775 static void put_stabn(int type, int other, int desc, int value);
776 static void put_stabd(int type, int other, int desc);
777 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
779 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
780 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
781 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
783 /* tcccoff.c */
784 int tcc_output_coff(TCCState *s1, const char *OutFile);
786 /* tccasm.c */
788 #ifdef CONFIG_TCC_ASM
790 typedef struct ExprValue {
791 uint32_t v;
792 Sym *sym;
793 } ExprValue;
795 #define MAX_ASM_OPERANDS 30
797 typedef struct ASMOperand {
798 int id; /* GCC 3 optionnal identifier (0 if number only supported */
799 char *constraint;
800 char asm_str[16]; /* computed asm string for operand */
801 SValue *vt; /* C value of the expression */
802 int ref_index; /* if >= 0, gives reference to a output constraint */
803 int input_index; /* if >= 0, gives reference to an input constraint */
804 int priority; /* priority, used to assign registers */
805 int reg; /* if >= 0, register number used for this operand */
806 int is_llong; /* true if double register value */
807 int is_memory; /* true if memory operand */
808 int is_rw; /* for '+' modifier */
809 } ASMOperand;
811 static void asm_expr(TCCState *s1, ExprValue *pe);
812 static int asm_int_expr(TCCState *s1);
813 static int find_constraint(ASMOperand *operands, int nb_operands,
814 const char *name, const char **pp);
816 static int tcc_assemble(TCCState *s1, int do_preprocess);
818 #endif
820 static void asm_instr(void);
821 static void asm_global_instr(void);
823 /* true if float/double/long double type */
824 static inline int is_float(int t)
826 int bt;
827 bt = t & VT_BTYPE;
828 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
831 #ifdef TCC_TARGET_I386
832 #include "i386-gen.c"
833 #endif
835 #ifdef TCC_TARGET_ARM
836 #include "arm-gen.c"
837 #endif
839 #ifdef TCC_TARGET_C67
840 #include "c67-gen.c"
841 #endif
843 #ifdef CONFIG_TCC_STATIC
845 #define RTLD_LAZY 0x001
846 #define RTLD_NOW 0x002
847 #define RTLD_GLOBAL 0x100
848 #define RTLD_DEFAULT NULL
850 /* dummy function for profiling */
851 void *dlopen(const char *filename, int flag)
853 return NULL;
856 const char *dlerror(void)
858 return "error";
861 typedef struct TCCSyms {
862 char *str;
863 void *ptr;
864 } TCCSyms;
866 #define TCCSYM(a) { #a, &a, },
868 /* add the symbol you want here if no dynamic linking is done */
869 static TCCSyms tcc_syms[] = {
870 TCCSYM(printf)
871 TCCSYM(fprintf)
872 TCCSYM(fopen)
873 TCCSYM(fclose)
874 { NULL, NULL },
877 void *dlsym(void *handle, const char *symbol)
879 TCCSyms *p;
880 p = tcc_syms;
881 while (p->str != NULL) {
882 if (!strcmp(p->str, symbol))
883 return p->ptr;
884 p++;
886 return NULL;
889 #endif
891 /********************************************************/
893 /* we use our own 'finite' function to avoid potential problems with
894 non standard math libs */
895 /* XXX: endianness dependent */
896 int ieee_finite(double d)
898 int *p = (int *)&d;
899 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
902 /* copy a string and truncate it. */
903 static char *pstrcpy(char *buf, int buf_size, const char *s)
905 char *q, *q_end;
906 int c;
908 if (buf_size > 0) {
909 q = buf;
910 q_end = buf + buf_size - 1;
911 while (q < q_end) {
912 c = *s++;
913 if (c == '\0')
914 break;
915 *q++ = c;
917 *q = '\0';
919 return buf;
922 /* strcat and truncate. */
923 static char *pstrcat(char *buf, int buf_size, const char *s)
925 int len;
926 len = strlen(buf);
927 if (len < buf_size)
928 pstrcpy(buf + len, buf_size - len, s);
929 return buf;
932 static int strstart(const char *str, const char *val, const char **ptr)
934 const char *p, *q;
935 p = str;
936 q = val;
937 while (*q != '\0') {
938 if (*p != *q)
939 return 0;
940 p++;
941 q++;
943 if (ptr)
944 *ptr = p;
945 return 1;
948 /* memory management */
949 #ifdef MEM_DEBUG
950 int mem_cur_size;
951 int mem_max_size;
952 #endif
954 static inline void tcc_free(void *ptr)
956 #ifdef MEM_DEBUG
957 mem_cur_size -= malloc_usable_size(ptr);
958 #endif
959 free(ptr);
962 static void *tcc_malloc(unsigned long size)
964 void *ptr;
965 ptr = malloc(size);
966 if (!ptr && size)
967 error("memory full");
968 #ifdef MEM_DEBUG
969 mem_cur_size += malloc_usable_size(ptr);
970 if (mem_cur_size > mem_max_size)
971 mem_max_size = mem_cur_size;
972 #endif
973 return ptr;
976 static void *tcc_mallocz(unsigned long size)
978 void *ptr;
979 ptr = tcc_malloc(size);
980 memset(ptr, 0, size);
981 return ptr;
984 static inline void *tcc_realloc(void *ptr, unsigned long size)
986 void *ptr1;
987 #ifdef MEM_DEBUG
988 mem_cur_size -= malloc_usable_size(ptr);
989 #endif
990 ptr1 = realloc(ptr, size);
991 #ifdef MEM_DEBUG
992 /* NOTE: count not correct if alloc error, but not critical */
993 mem_cur_size += malloc_usable_size(ptr1);
994 if (mem_cur_size > mem_max_size)
995 mem_max_size = mem_cur_size;
996 #endif
997 return ptr1;
1000 static char *tcc_strdup(const char *str)
1002 char *ptr;
1003 ptr = tcc_malloc(strlen(str) + 1);
1004 strcpy(ptr, str);
1005 return ptr;
1008 #define free(p) use_tcc_free(p)
1009 #define malloc(s) use_tcc_malloc(s)
1010 #define realloc(p, s) use_tcc_realloc(p, s)
1012 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1014 int nb, nb_alloc;
1015 void **pp;
1017 nb = *nb_ptr;
1018 pp = *ptab;
1019 /* every power of two we double array size */
1020 if ((nb & (nb - 1)) == 0) {
1021 if (!nb)
1022 nb_alloc = 1;
1023 else
1024 nb_alloc = nb * 2;
1025 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1026 if (!pp)
1027 error("memory full");
1028 *ptab = pp;
1030 pp[nb++] = data;
1031 *nb_ptr = nb;
1034 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1036 Section *sec;
1038 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1039 strcpy(sec->name, name);
1040 sec->sh_type = sh_type;
1041 sec->sh_flags = sh_flags;
1042 switch(sh_type) {
1043 case SHT_HASH:
1044 case SHT_REL:
1045 case SHT_DYNSYM:
1046 case SHT_SYMTAB:
1047 case SHT_DYNAMIC:
1048 sec->sh_addralign = 4;
1049 break;
1050 case SHT_STRTAB:
1051 sec->sh_addralign = 1;
1052 break;
1053 default:
1054 sec->sh_addralign = 32; /* default conservative alignment */
1055 break;
1058 /* only add section if not private */
1059 if (!(sh_flags & SHF_PRIVATE)) {
1060 sec->sh_num = s1->nb_sections;
1061 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1063 return sec;
1066 static void free_section(Section *s)
1068 tcc_free(s->data);
1069 tcc_free(s);
1072 /* realloc section and set its content to zero */
1073 static void section_realloc(Section *sec, unsigned long new_size)
1075 unsigned long size;
1076 unsigned char *data;
1078 size = sec->data_allocated;
1079 if (size == 0)
1080 size = 1;
1081 while (size < new_size)
1082 size = size * 2;
1083 data = tcc_realloc(sec->data, size);
1084 if (!data)
1085 error("memory full");
1086 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1087 sec->data = data;
1088 sec->data_allocated = size;
1091 /* reserve at least 'size' bytes in section 'sec' from
1092 sec->data_offset. */
1093 static void *section_ptr_add(Section *sec, unsigned long size)
1095 unsigned long offset, offset1;
1097 offset = sec->data_offset;
1098 offset1 = offset + size;
1099 if (offset1 > sec->data_allocated)
1100 section_realloc(sec, offset1);
1101 sec->data_offset = offset1;
1102 return sec->data + offset;
1105 /* return a reference to a section, and create it if it does not
1106 exists */
1107 Section *find_section(TCCState *s1, const char *name)
1109 Section *sec;
1110 int i;
1111 for(i = 1; i < s1->nb_sections; i++) {
1112 sec = s1->sections[i];
1113 if (!strcmp(name, sec->name))
1114 return sec;
1116 /* sections are created as PROGBITS */
1117 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1120 #define SECTION_ABS ((void *)1)
1122 /* update sym->c so that it points to an external symbol in section
1123 'section' with value 'value' */
1124 static void put_extern_sym(Sym *sym, Section *section,
1125 unsigned long value, unsigned long size)
1127 int sym_type, sym_bind, sh_num, info;
1128 Elf32_Sym *esym;
1129 const char *name;
1131 if (section == NULL)
1132 sh_num = SHN_UNDEF;
1133 else if (section == SECTION_ABS)
1134 sh_num = SHN_ABS;
1135 else
1136 sh_num = section->sh_num;
1137 if (!sym->c) {
1138 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1139 sym_type = STT_FUNC;
1140 else
1141 sym_type = STT_OBJECT;
1142 if (sym->type.t & VT_STATIC)
1143 sym_bind = STB_LOCAL;
1144 else
1145 sym_bind = STB_GLOBAL;
1147 name = get_tok_str(sym->v, NULL);
1148 #ifdef CONFIG_TCC_BCHECK
1149 if (do_bounds_check) {
1150 char buf[32];
1152 /* XXX: avoid doing that for statics ? */
1153 /* if bound checking is activated, we change some function
1154 names by adding the "__bound" prefix */
1155 switch(sym->v) {
1156 #if 0
1157 /* XXX: we rely only on malloc hooks */
1158 case TOK_malloc:
1159 case TOK_free:
1160 case TOK_realloc:
1161 case TOK_memalign:
1162 case TOK_calloc:
1163 #endif
1164 case TOK_memcpy:
1165 case TOK_memmove:
1166 case TOK_memset:
1167 case TOK_strlen:
1168 case TOK_strcpy:
1169 strcpy(buf, "__bound_");
1170 strcat(buf, name);
1171 name = buf;
1172 break;
1175 #endif
1176 info = ELF32_ST_INFO(sym_bind, sym_type);
1177 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1178 } else {
1179 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1180 esym->st_value = value;
1181 esym->st_size = size;
1182 esym->st_shndx = sh_num;
1186 /* add a new relocation entry to symbol 'sym' in section 's' */
1187 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1189 if (!sym->c)
1190 put_extern_sym(sym, NULL, 0, 0);
1191 /* now we can add ELF relocation info */
1192 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1195 static inline int isid(int c)
1197 return (c >= 'a' && c <= 'z') ||
1198 (c >= 'A' && c <= 'Z') ||
1199 c == '_';
1202 static inline int isnum(int c)
1204 return c >= '0' && c <= '9';
1207 static inline int isoct(int c)
1209 return c >= '0' && c <= '7';
1212 static inline int toup(int c)
1214 if (c >= 'a' && c <= 'z')
1215 return c - 'a' + 'A';
1216 else
1217 return c;
1220 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1222 int len;
1223 len = strlen(buf);
1224 vsnprintf(buf + len, buf_size - len, fmt, ap);
1227 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1229 va_list ap;
1230 va_start(ap, fmt);
1231 strcat_vprintf(buf, buf_size, fmt, ap);
1232 va_end(ap);
1235 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1237 char buf[2048];
1238 BufferedFile **f;
1240 buf[0] = '\0';
1241 if (file) {
1242 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1243 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1244 (*f)->filename, (*f)->line_num);
1245 if (file->line_num > 0) {
1246 strcat_printf(buf, sizeof(buf),
1247 "%s:%d: ", file->filename, file->line_num);
1248 } else {
1249 strcat_printf(buf, sizeof(buf),
1250 "%s: ", file->filename);
1252 } else {
1253 strcat_printf(buf, sizeof(buf),
1254 "tcc: ");
1256 if (is_warning)
1257 strcat_printf(buf, sizeof(buf), "warning: ");
1258 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1260 if (!s1->error_func) {
1261 /* default case: stderr */
1262 fprintf(stderr, "%s\n", buf);
1263 } else {
1264 s1->error_func(s1->error_opaque, buf);
1266 if (!is_warning || s1->warn_error)
1267 s1->nb_errors++;
1270 #ifdef LIBTCC
1271 void tcc_set_error_func(TCCState *s, void *error_opaque,
1272 void (*error_func)(void *opaque, const char *msg))
1274 s->error_opaque = error_opaque;
1275 s->error_func = error_func;
1277 #endif
1279 /* error without aborting current compilation */
1280 void error_noabort(const char *fmt, ...)
1282 TCCState *s1 = tcc_state;
1283 va_list ap;
1285 va_start(ap, fmt);
1286 error1(s1, 0, fmt, ap);
1287 va_end(ap);
1290 void error(const char *fmt, ...)
1292 TCCState *s1 = tcc_state;
1293 va_list ap;
1295 va_start(ap, fmt);
1296 error1(s1, 0, fmt, ap);
1297 va_end(ap);
1298 /* better than nothing: in some cases, we accept to handle errors */
1299 if (s1->error_set_jmp_enabled) {
1300 longjmp(s1->error_jmp_buf, 1);
1301 } else {
1302 /* XXX: eliminate this someday */
1303 exit(1);
1307 void expect(const char *msg)
1309 error("%s expected", msg);
1312 void warning(const char *fmt, ...)
1314 TCCState *s1 = tcc_state;
1315 va_list ap;
1317 if (s1->warn_none)
1318 return;
1320 va_start(ap, fmt);
1321 error1(s1, 1, fmt, ap);
1322 va_end(ap);
1325 void skip(int c)
1327 if (tok != c)
1328 error("'%c' expected", c);
1329 next();
1332 static void test_lvalue(void)
1334 if (!(vtop->r & VT_LVAL))
1335 expect("lvalue");
1338 /* allocate a new token */
1339 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1341 TokenSym *ts, **ptable;
1342 int i;
1344 if (tok_ident >= SYM_FIRST_ANOM)
1345 error("memory full");
1347 /* expand token table if needed */
1348 i = tok_ident - TOK_IDENT;
1349 if ((i % TOK_ALLOC_INCR) == 0) {
1350 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1351 if (!ptable)
1352 error("memory full");
1353 table_ident = ptable;
1356 ts = tcc_malloc(sizeof(TokenSym) + len);
1357 table_ident[i] = ts;
1358 ts->tok = tok_ident++;
1359 ts->sym_define = NULL;
1360 ts->sym_label = NULL;
1361 ts->sym_struct = NULL;
1362 ts->sym_identifier = NULL;
1363 ts->len = len;
1364 ts->hash_next = NULL;
1365 memcpy(ts->str, str, len);
1366 ts->str[len] = '\0';
1367 *pts = ts;
1368 return ts;
1371 #define TOK_HASH_INIT 1
1372 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1374 /* find a token and add it if not found */
1375 static TokenSym *tok_alloc(const char *str, int len)
1377 TokenSym *ts, **pts;
1378 int i;
1379 unsigned int h;
1381 h = TOK_HASH_INIT;
1382 for(i=0;i<len;i++)
1383 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1384 h &= (TOK_HASH_SIZE - 1);
1386 pts = &hash_ident[h];
1387 for(;;) {
1388 ts = *pts;
1389 if (!ts)
1390 break;
1391 if (ts->len == len && !memcmp(ts->str, str, len))
1392 return ts;
1393 pts = &(ts->hash_next);
1395 return tok_alloc_new(pts, str, len);
1398 /* CString handling */
1400 static void cstr_realloc(CString *cstr, int new_size)
1402 int size;
1403 void *data;
1405 size = cstr->size_allocated;
1406 if (size == 0)
1407 size = 8; /* no need to allocate a too small first string */
1408 while (size < new_size)
1409 size = size * 2;
1410 data = tcc_realloc(cstr->data_allocated, size);
1411 if (!data)
1412 error("memory full");
1413 cstr->data_allocated = data;
1414 cstr->size_allocated = size;
1415 cstr->data = data;
1418 /* add a byte */
1419 static void cstr_ccat(CString *cstr, int ch)
1421 int size;
1422 size = cstr->size + 1;
1423 if (size > cstr->size_allocated)
1424 cstr_realloc(cstr, size);
1425 ((unsigned char *)cstr->data)[size - 1] = ch;
1426 cstr->size = size;
1429 static void cstr_cat(CString *cstr, const char *str)
1431 int c;
1432 for(;;) {
1433 c = *str;
1434 if (c == '\0')
1435 break;
1436 cstr_ccat(cstr, c);
1437 str++;
1441 /* add a wide char */
1442 static void cstr_wccat(CString *cstr, int ch)
1444 int size;
1445 size = cstr->size + sizeof(int);
1446 if (size > cstr->size_allocated)
1447 cstr_realloc(cstr, size);
1448 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1449 cstr->size = size;
1452 static void cstr_new(CString *cstr)
1454 memset(cstr, 0, sizeof(CString));
1457 /* free string and reset it to NULL */
1458 static void cstr_free(CString *cstr)
1460 tcc_free(cstr->data_allocated);
1461 cstr_new(cstr);
1464 #define cstr_reset(cstr) cstr_free(cstr)
1466 static CString *cstr_dup(CString *cstr1)
1468 CString *cstr;
1469 int size;
1471 cstr = tcc_malloc(sizeof(CString));
1472 size = cstr1->size;
1473 cstr->size = size;
1474 cstr->size_allocated = size;
1475 cstr->data_allocated = tcc_malloc(size);
1476 cstr->data = cstr->data_allocated;
1477 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1478 return cstr;
1481 /* XXX: unicode ? */
1482 static void add_char(CString *cstr, int c)
1484 if (c == '\'' || c == '\"' || c == '\\') {
1485 /* XXX: could be more precise if char or string */
1486 cstr_ccat(cstr, '\\');
1488 if (c >= 32 && c <= 126) {
1489 cstr_ccat(cstr, c);
1490 } else {
1491 cstr_ccat(cstr, '\\');
1492 if (c == '\n') {
1493 cstr_ccat(cstr, 'n');
1494 } else {
1495 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1496 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1497 cstr_ccat(cstr, '0' + (c & 7));
1502 /* XXX: buffer overflow */
1503 /* XXX: float tokens */
1504 char *get_tok_str(int v, CValue *cv)
1506 static char buf[STRING_MAX_SIZE + 1];
1507 static CString cstr_buf;
1508 CString *cstr;
1509 unsigned char *q;
1510 char *p;
1511 int i, len;
1513 /* NOTE: to go faster, we give a fixed buffer for small strings */
1514 cstr_reset(&cstr_buf);
1515 cstr_buf.data = buf;
1516 cstr_buf.size_allocated = sizeof(buf);
1517 p = buf;
1519 switch(v) {
1520 case TOK_CINT:
1521 case TOK_CUINT:
1522 /* XXX: not quite exact, but only useful for testing */
1523 sprintf(p, "%u", cv->ui);
1524 break;
1525 case TOK_CLLONG:
1526 case TOK_CULLONG:
1527 /* XXX: not quite exact, but only useful for testing */
1528 sprintf(p, "%Lu", cv->ull);
1529 break;
1530 case TOK_CCHAR:
1531 case TOK_LCHAR:
1532 cstr_ccat(&cstr_buf, '\'');
1533 add_char(&cstr_buf, cv->i);
1534 cstr_ccat(&cstr_buf, '\'');
1535 cstr_ccat(&cstr_buf, '\0');
1536 break;
1537 case TOK_PPNUM:
1538 cstr = cv->cstr;
1539 len = cstr->size - 1;
1540 for(i=0;i<len;i++)
1541 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1542 cstr_ccat(&cstr_buf, '\0');
1543 break;
1544 case TOK_STR:
1545 case TOK_LSTR:
1546 cstr = cv->cstr;
1547 cstr_ccat(&cstr_buf, '\"');
1548 if (v == TOK_STR) {
1549 len = cstr->size - 1;
1550 for(i=0;i<len;i++)
1551 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1552 } else {
1553 len = (cstr->size / sizeof(int)) - 1;
1554 for(i=0;i<len;i++)
1555 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1557 cstr_ccat(&cstr_buf, '\"');
1558 cstr_ccat(&cstr_buf, '\0');
1559 break;
1560 case TOK_LT:
1561 v = '<';
1562 goto addv;
1563 case TOK_GT:
1564 v = '>';
1565 goto addv;
1566 case TOK_A_SHL:
1567 return strcpy(p, "<<=");
1568 case TOK_A_SAR:
1569 return strcpy(p, ">>=");
1570 default:
1571 if (v < TOK_IDENT) {
1572 /* search in two bytes table */
1573 q = tok_two_chars;
1574 while (*q) {
1575 if (q[2] == v) {
1576 *p++ = q[0];
1577 *p++ = q[1];
1578 *p = '\0';
1579 return buf;
1581 q += 3;
1583 addv:
1584 *p++ = v;
1585 *p = '\0';
1586 } else if (v < tok_ident) {
1587 return table_ident[v - TOK_IDENT]->str;
1588 } else if (v >= SYM_FIRST_ANOM) {
1589 /* special name for anonymous symbol */
1590 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1591 } else {
1592 /* should never happen */
1593 return NULL;
1595 break;
1597 return cstr_buf.data;
1600 /* push, without hashing */
1601 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1603 Sym *s;
1604 s = tcc_malloc(sizeof(Sym));
1605 s->v = v;
1606 s->type.t = t;
1607 s->c = c;
1608 s->next = NULL;
1609 /* add in stack */
1610 s->prev = *ps;
1611 *ps = s;
1612 return s;
1615 /* find a symbol and return its associated structure. 's' is the top
1616 of the symbol stack */
1617 static Sym *sym_find2(Sym *s, int v)
1619 while (s) {
1620 if (s->v == v)
1621 return s;
1622 s = s->prev;
1624 return NULL;
1627 /* structure lookup */
1628 static inline Sym *struct_find(int v)
1630 v -= TOK_IDENT;
1631 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1632 return NULL;
1633 return table_ident[v]->sym_struct;
1636 /* find an identifier */
1637 static inline Sym *sym_find(int v)
1639 v -= TOK_IDENT;
1640 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1641 return NULL;
1642 return table_ident[v]->sym_identifier;
1645 /* push a given symbol on the symbol stack */
1646 static Sym *sym_push(int v, CType *type, int r, int c)
1648 Sym *s, **ps;
1649 TokenSym *ts;
1651 if (local_stack)
1652 ps = &local_stack;
1653 else
1654 ps = &global_stack;
1655 s = sym_push2(ps, v, type->t, c);
1656 s->type.ref = type->ref;
1657 s->r = r;
1658 /* don't record fields or anonymous symbols */
1659 /* XXX: simplify */
1660 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1661 /* record symbol in token array */
1662 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1663 if (v & SYM_STRUCT)
1664 ps = &ts->sym_struct;
1665 else
1666 ps = &ts->sym_identifier;
1667 s->prev_tok = *ps;
1668 *ps = s;
1670 return s;
1673 /* push a global identifier */
1674 static Sym *global_identifier_push(int v, int t, int c)
1676 Sym *s, **ps;
1677 s = sym_push2(&global_stack, v, t, c);
1678 /* don't record anonymous symbol */
1679 if (v < SYM_FIRST_ANOM) {
1680 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1681 /* modify the top most local identifier, so that
1682 sym_identifier will point to 's' when popped */
1683 while (*ps != NULL)
1684 ps = &(*ps)->prev_tok;
1685 s->prev_tok = NULL;
1686 *ps = s;
1688 return s;
1691 /* pop symbols until top reaches 'b' */
1692 static void sym_pop(Sym **ptop, Sym *b)
1694 Sym *s, *ss, **ps;
1695 TokenSym *ts;
1696 int v;
1698 s = *ptop;
1699 while(s != b) {
1700 ss = s->prev;
1701 v = s->v;
1702 /* remove symbol in token array */
1703 /* XXX: simplify */
1704 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1705 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1706 if (v & SYM_STRUCT)
1707 ps = &ts->sym_struct;
1708 else
1709 ps = &ts->sym_identifier;
1710 *ps = s->prev_tok;
1712 tcc_free(s);
1713 s = ss;
1715 *ptop = b;
1718 /* I/O layer */
1720 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1722 int fd;
1723 BufferedFile *bf;
1725 fd = open(filename, O_RDONLY);
1726 if (fd < 0)
1727 return NULL;
1728 bf = tcc_malloc(sizeof(BufferedFile));
1729 if (!bf) {
1730 close(fd);
1731 return NULL;
1733 bf->fd = fd;
1734 bf->buf_ptr = bf->buffer;
1735 bf->buf_end = bf->buffer;
1736 bf->buffer[0] = CH_EOB; /* put eob symbol */
1737 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1738 bf->line_num = 1;
1739 bf->ifndef_macro = 0;
1740 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1741 // printf("opening '%s'\n", filename);
1742 return bf;
1745 void tcc_close(BufferedFile *bf)
1747 total_lines += bf->line_num;
1748 close(bf->fd);
1749 tcc_free(bf);
1752 /* fill input buffer and peek next char */
1753 static int tcc_peekc_slow(BufferedFile *bf)
1755 int len;
1756 /* only tries to read if really end of buffer */
1757 if (bf->buf_ptr >= bf->buf_end) {
1758 if (bf->fd != -1) {
1759 #if defined(PARSE_DEBUG)
1760 len = 8;
1761 #else
1762 len = IO_BUF_SIZE;
1763 #endif
1764 len = read(bf->fd, bf->buffer, len);
1765 if (len < 0)
1766 len = 0;
1767 } else {
1768 len = 0;
1770 total_bytes += len;
1771 bf->buf_ptr = bf->buffer;
1772 bf->buf_end = bf->buffer + len;
1773 *bf->buf_end = CH_EOB;
1775 if (bf->buf_ptr < bf->buf_end) {
1776 return bf->buf_ptr[0];
1777 } else {
1778 bf->buf_ptr = bf->buf_end;
1779 return CH_EOF;
1783 /* return the current character, handling end of block if necessary
1784 (but not stray) */
1785 static int handle_eob(void)
1787 return tcc_peekc_slow(file);
1790 /* read next char from current input file and handle end of input buffer */
1791 static inline void inp(void)
1793 ch = *(++(file->buf_ptr));
1794 /* end of buffer/file handling */
1795 if (ch == CH_EOB)
1796 ch = handle_eob();
1799 /* handle '\[\r]\n' */
1800 static void handle_stray(void)
1802 while (ch == '\\') {
1803 inp();
1804 if (ch == '\n') {
1805 file->line_num++;
1806 inp();
1807 } else if (ch == '\r') {
1808 inp();
1809 if (ch != '\n')
1810 goto fail;
1811 file->line_num++;
1812 inp();
1813 } else {
1814 fail:
1815 error("stray '\\' in program");
1820 /* skip the stray and handle the \\n case. Output an error if
1821 incorrect char after the stray */
1822 static int handle_stray1(uint8_t *p)
1824 int c;
1826 if (p >= file->buf_end) {
1827 file->buf_ptr = p;
1828 c = handle_eob();
1829 p = file->buf_ptr;
1830 if (c == '\\')
1831 goto parse_stray;
1832 } else {
1833 parse_stray:
1834 file->buf_ptr = p;
1835 ch = *p;
1836 handle_stray();
1837 p = file->buf_ptr;
1838 c = *p;
1840 return c;
1843 /* handle just the EOB case, but not stray */
1844 #define PEEKC_EOB(c, p)\
1846 p++;\
1847 c = *p;\
1848 if (c == '\\') {\
1849 file->buf_ptr = p;\
1850 c = handle_eob();\
1851 p = file->buf_ptr;\
1855 /* handle the complicated stray case */
1856 #define PEEKC(c, p)\
1858 p++;\
1859 c = *p;\
1860 if (c == '\\') {\
1861 c = handle_stray1(p);\
1862 p = file->buf_ptr;\
1866 /* input with '\[\r]\n' handling. Note that this function cannot
1867 handle other characters after '\', so you cannot call it inside
1868 strings or comments */
1869 static void minp(void)
1871 inp();
1872 if (ch == '\\')
1873 handle_stray();
1877 /* single line C++ comments */
1878 static uint8_t *parse_line_comment(uint8_t *p)
1880 int c;
1882 p++;
1883 for(;;) {
1884 c = *p;
1885 redo:
1886 if (c == '\n' || c == CH_EOF) {
1887 break;
1888 } else if (c == '\\') {
1889 file->buf_ptr = p;
1890 c = handle_eob();
1891 p = file->buf_ptr;
1892 if (c == '\\') {
1893 PEEKC_EOB(c, p);
1894 if (c == '\n') {
1895 file->line_num++;
1896 PEEKC_EOB(c, p);
1897 } else if (c == '\r') {
1898 PEEKC_EOB(c, p);
1899 if (c == '\n') {
1900 file->line_num++;
1901 PEEKC_EOB(c, p);
1904 } else {
1905 goto redo;
1907 } else {
1908 p++;
1911 return p;
1914 /* C comments */
1915 static uint8_t *parse_comment(uint8_t *p)
1917 int c;
1919 p++;
1920 for(;;) {
1921 /* fast skip loop */
1922 for(;;) {
1923 c = *p;
1924 if (c == '\n' || c == '*' || c == '\\')
1925 break;
1926 p++;
1927 c = *p;
1928 if (c == '\n' || c == '*' || c == '\\')
1929 break;
1930 p++;
1932 /* now we can handle all the cases */
1933 if (c == '\n') {
1934 file->line_num++;
1935 p++;
1936 } else if (c == '*') {
1937 p++;
1938 for(;;) {
1939 c = *p;
1940 if (c == '*') {
1941 p++;
1942 } else if (c == '/') {
1943 goto end_of_comment;
1944 } else if (c == '\\') {
1945 file->buf_ptr = p;
1946 c = handle_eob();
1947 p = file->buf_ptr;
1948 if (c == '\\') {
1949 /* skip '\[\r]\n', otherwise just skip the stray */
1950 while (c == '\\') {
1951 PEEKC_EOB(c, p);
1952 if (c == '\n') {
1953 file->line_num++;
1954 PEEKC_EOB(c, p);
1955 } else if (c == '\r') {
1956 PEEKC_EOB(c, p);
1957 if (c == '\n') {
1958 file->line_num++;
1959 PEEKC_EOB(c, p);
1961 } else {
1962 goto after_star;
1966 } else {
1967 break;
1970 after_star: ;
1971 } else {
1972 /* stray, eob or eof */
1973 file->buf_ptr = p;
1974 c = handle_eob();
1975 p = file->buf_ptr;
1976 if (c == CH_EOF) {
1977 error("unexpected end of file in comment");
1978 } else if (c == '\\') {
1979 p++;
1983 end_of_comment:
1984 p++;
1985 return p;
1988 #define cinp minp
1990 /* space exlcuding newline */
1991 static inline int is_space(int ch)
1993 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1996 static inline void skip_spaces(void)
1998 while (is_space(ch))
1999 cinp();
2002 /* parse a string without interpreting escapes */
2003 static uint8_t *parse_pp_string(uint8_t *p,
2004 int sep, CString *str)
2006 int c;
2007 p++;
2008 for(;;) {
2009 c = *p;
2010 if (c == sep) {
2011 break;
2012 } else if (c == '\\') {
2013 file->buf_ptr = p;
2014 c = handle_eob();
2015 p = file->buf_ptr;
2016 if (c == CH_EOF) {
2017 unterminated_string:
2018 /* XXX: indicate line number of start of string */
2019 error("missing terminating %c character", sep);
2020 } else if (c == '\\') {
2021 /* escape : just skip \[\r]\n */
2022 PEEKC_EOB(c, p);
2023 if (c == '\n') {
2024 file->line_num++;
2025 p++;
2026 } else if (c == '\r') {
2027 PEEKC_EOB(c, p);
2028 if (c != '\n')
2029 expect("'\n' after '\r'");
2030 file->line_num++;
2031 p++;
2032 } else if (c == CH_EOF) {
2033 goto unterminated_string;
2034 } else {
2035 if (str) {
2036 cstr_ccat(str, '\\');
2037 cstr_ccat(str, c);
2039 p++;
2042 } else if (c == '\n') {
2043 file->line_num++;
2044 goto add_char;
2045 } else if (c == '\r') {
2046 PEEKC_EOB(c, p);
2047 if (c != '\n') {
2048 cstr_ccat(str, '\r');
2049 } else {
2050 file->line_num++;
2051 goto add_char;
2053 } else {
2054 add_char:
2055 if (str)
2056 cstr_ccat(str, c);
2057 p++;
2060 p++;
2061 return p;
2064 /* skip block of text until #else, #elif or #endif. skip also pairs of
2065 #if/#endif */
2066 void preprocess_skip(void)
2068 int a, start_of_line, c;
2069 uint8_t *p;
2071 p = file->buf_ptr;
2072 start_of_line = 1;
2073 a = 0;
2074 for(;;) {
2075 redo_no_start:
2076 c = *p;
2077 switch(c) {
2078 case ' ':
2079 case '\t':
2080 case '\f':
2081 case '\v':
2082 case '\r':
2083 p++;
2084 goto redo_no_start;
2085 case '\n':
2086 start_of_line = 1;
2087 file->line_num++;
2088 p++;
2089 goto redo_no_start;
2090 case '\\':
2091 file->buf_ptr = p;
2092 c = handle_eob();
2093 if (c == CH_EOF) {
2094 expect("#endif");
2095 } else if (c == '\\') {
2096 /* XXX: incorrect: should not give an error */
2097 ch = file->buf_ptr[0];
2098 handle_stray();
2100 p = file->buf_ptr;
2101 goto redo_no_start;
2102 /* skip strings */
2103 case '\"':
2104 case '\'':
2105 p = parse_pp_string(p, c, NULL);
2106 break;
2107 /* skip comments */
2108 case '/':
2109 file->buf_ptr = p;
2110 ch = *p;
2111 minp();
2112 p = file->buf_ptr;
2113 if (ch == '*') {
2114 p = parse_comment(p);
2115 } else if (ch == '/') {
2116 p = parse_line_comment(p);
2118 break;
2120 case '#':
2121 p++;
2122 if (start_of_line) {
2123 file->buf_ptr = p;
2124 next_nomacro();
2125 p = file->buf_ptr;
2126 if (a == 0 &&
2127 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2128 goto the_end;
2129 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2130 a++;
2131 else if (tok == TOK_ENDIF)
2132 a--;
2134 break;
2135 default:
2136 p++;
2137 break;
2139 start_of_line = 0;
2141 the_end: ;
2142 file->buf_ptr = p;
2145 /* ParseState handling */
2147 /* XXX: currently, no include file info is stored. Thus, we cannot display
2148 accurate messages if the function or data definition spans multiple
2149 files */
2151 /* save current parse state in 's' */
2152 void save_parse_state(ParseState *s)
2154 s->line_num = file->line_num;
2155 s->macro_ptr = macro_ptr;
2156 s->tok = tok;
2157 s->tokc = tokc;
2160 /* restore parse state from 's' */
2161 void restore_parse_state(ParseState *s)
2163 file->line_num = s->line_num;
2164 macro_ptr = s->macro_ptr;
2165 tok = s->tok;
2166 tokc = s->tokc;
2169 /* return the number of additional 'ints' necessary to store the
2170 token */
2171 static inline int tok_ext_size(int t)
2173 switch(t) {
2174 /* 4 bytes */
2175 case TOK_CINT:
2176 case TOK_CUINT:
2177 case TOK_CCHAR:
2178 case TOK_LCHAR:
2179 case TOK_STR:
2180 case TOK_LSTR:
2181 case TOK_CFLOAT:
2182 case TOK_LINENUM:
2183 case TOK_PPNUM:
2184 return 1;
2185 case TOK_CDOUBLE:
2186 case TOK_CLLONG:
2187 case TOK_CULLONG:
2188 return 2;
2189 case TOK_CLDOUBLE:
2190 return LDOUBLE_SIZE / 4;
2191 default:
2192 return 0;
2196 /* token string handling */
2198 static inline void tok_str_new(TokenString *s)
2200 s->str = NULL;
2201 s->len = 0;
2202 s->allocated_len = 0;
2203 s->last_line_num = -1;
2206 static void tok_str_free(int *str)
2208 const int *p;
2209 CString *cstr;
2210 int t;
2212 p = str;
2213 for(;;) {
2214 t = *p;
2215 /* NOTE: we test zero separately so that GCC can generate a
2216 table for the following switch */
2217 if (t == 0)
2218 break;
2219 switch(t) {
2220 case TOK_CINT:
2221 case TOK_CUINT:
2222 case TOK_CCHAR:
2223 case TOK_LCHAR:
2224 case TOK_CFLOAT:
2225 case TOK_LINENUM:
2226 p += 2;
2227 break;
2228 case TOK_PPNUM:
2229 case TOK_STR:
2230 case TOK_LSTR:
2231 /* XXX: use a macro to be portable on 64 bit ? */
2232 cstr = (CString *)p[1];
2233 cstr_free(cstr);
2234 tcc_free(cstr);
2235 p += 2;
2236 break;
2237 case TOK_CDOUBLE:
2238 case TOK_CLLONG:
2239 case TOK_CULLONG:
2240 p += 3;
2241 break;
2242 case TOK_CLDOUBLE:
2243 p += 1 + (LDOUBLE_SIZE / 4);
2244 break;
2245 default:
2246 p++;
2247 break;
2250 tcc_free(str);
2253 static int *tok_str_realloc(TokenString *s)
2255 int *str, len;
2257 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2258 str = tcc_realloc(s->str, len * sizeof(int));
2259 if (!str)
2260 error("memory full");
2261 s->allocated_len = len;
2262 s->str = str;
2263 return str;
2266 static void tok_str_add(TokenString *s, int t)
2268 int len, *str;
2270 len = s->len;
2271 str = s->str;
2272 if (len >= s->allocated_len)
2273 str = tok_str_realloc(s);
2274 str[len++] = t;
2275 s->len = len;
2278 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2280 int len, *str;
2282 len = s->len;
2283 str = s->str;
2285 /* allocate space for worst case */
2286 if (len + TOK_MAX_SIZE > s->allocated_len)
2287 str = tok_str_realloc(s);
2288 str[len++] = t;
2289 switch(t) {
2290 case TOK_CINT:
2291 case TOK_CUINT:
2292 case TOK_CCHAR:
2293 case TOK_LCHAR:
2294 case TOK_CFLOAT:
2295 case TOK_LINENUM:
2296 str[len++] = cv->tab[0];
2297 break;
2298 case TOK_PPNUM:
2299 case TOK_STR:
2300 case TOK_LSTR:
2301 str[len++] = (int)cstr_dup(cv->cstr);
2302 break;
2303 case TOK_CDOUBLE:
2304 case TOK_CLLONG:
2305 case TOK_CULLONG:
2306 #if LDOUBLE_SIZE == 8
2307 case TOK_CLDOUBLE:
2308 #endif
2309 str[len++] = cv->tab[0];
2310 str[len++] = cv->tab[1];
2311 break;
2312 #if LDOUBLE_SIZE == 12
2313 case TOK_CLDOUBLE:
2314 str[len++] = cv->tab[0];
2315 str[len++] = cv->tab[1];
2316 str[len++] = cv->tab[2];
2317 #elif LDOUBLE_SIZE != 8
2318 #error add long double size support
2319 #endif
2320 break;
2321 default:
2322 break;
2324 s->len = len;
2327 /* add the current parse token in token string 's' */
2328 static void tok_str_add_tok(TokenString *s)
2330 CValue cval;
2332 /* save line number info */
2333 if (file->line_num != s->last_line_num) {
2334 s->last_line_num = file->line_num;
2335 cval.i = s->last_line_num;
2336 tok_str_add2(s, TOK_LINENUM, &cval);
2338 tok_str_add2(s, tok, &tokc);
2341 #if LDOUBLE_SIZE == 12
2342 #define LDOUBLE_GET(p, cv) \
2343 cv.tab[0] = p[0]; \
2344 cv.tab[1] = p[1]; \
2345 cv.tab[2] = p[2];
2346 #elif LDOUBLE_SIZE == 8
2347 #define LDOUBLE_GET(p, cv) \
2348 cv.tab[0] = p[0]; \
2349 cv.tab[1] = p[1];
2350 #else
2351 #error add long double size support
2352 #endif
2355 /* get a token from an integer array and increment pointer
2356 accordingly. we code it as a macro to avoid pointer aliasing. */
2357 #define TOK_GET(t, p, cv) \
2359 t = *p++; \
2360 switch(t) { \
2361 case TOK_CINT: \
2362 case TOK_CUINT: \
2363 case TOK_CCHAR: \
2364 case TOK_LCHAR: \
2365 case TOK_CFLOAT: \
2366 case TOK_LINENUM: \
2367 case TOK_STR: \
2368 case TOK_LSTR: \
2369 case TOK_PPNUM: \
2370 cv.tab[0] = *p++; \
2371 break; \
2372 case TOK_CDOUBLE: \
2373 case TOK_CLLONG: \
2374 case TOK_CULLONG: \
2375 cv.tab[0] = p[0]; \
2376 cv.tab[1] = p[1]; \
2377 p += 2; \
2378 break; \
2379 case TOK_CLDOUBLE: \
2380 LDOUBLE_GET(p, cv); \
2381 p += LDOUBLE_SIZE / 4; \
2382 break; \
2383 default: \
2384 break; \
2388 /* defines handling */
2389 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2391 Sym *s;
2393 s = sym_push2(&define_stack, v, macro_type, (int)str);
2394 s->next = first_arg;
2395 table_ident[v - TOK_IDENT]->sym_define = s;
2398 /* undefined a define symbol. Its name is just set to zero */
2399 static void define_undef(Sym *s)
2401 int v;
2402 v = s->v;
2403 if (v >= TOK_IDENT && v < tok_ident)
2404 table_ident[v - TOK_IDENT]->sym_define = NULL;
2405 s->v = 0;
2408 static inline Sym *define_find(int v)
2410 v -= TOK_IDENT;
2411 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2412 return NULL;
2413 return table_ident[v]->sym_define;
2416 /* free define stack until top reaches 'b' */
2417 static void free_defines(Sym *b)
2419 Sym *top, *top1;
2420 int v;
2422 top = define_stack;
2423 while (top != b) {
2424 top1 = top->prev;
2425 /* do not free args or predefined defines */
2426 if (top->c)
2427 tok_str_free((int *)top->c);
2428 v = top->v;
2429 if (v >= TOK_IDENT && v < tok_ident)
2430 table_ident[v - TOK_IDENT]->sym_define = NULL;
2431 tcc_free(top);
2432 top = top1;
2434 define_stack = b;
2437 /* label lookup */
2438 static Sym *label_find(int v)
2440 v -= TOK_IDENT;
2441 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2442 return NULL;
2443 return table_ident[v]->sym_label;
2446 static Sym *label_push(Sym **ptop, int v, int flags)
2448 Sym *s, **ps;
2449 s = sym_push2(ptop, v, 0, 0);
2450 s->r = flags;
2451 ps = &table_ident[v - TOK_IDENT]->sym_label;
2452 if (ptop == &global_label_stack) {
2453 /* modify the top most local identifier, so that
2454 sym_identifier will point to 's' when popped */
2455 while (*ps != NULL)
2456 ps = &(*ps)->prev_tok;
2458 s->prev_tok = *ps;
2459 *ps = s;
2460 return s;
2463 /* pop labels until element last is reached. Look if any labels are
2464 undefined. Define symbols if '&&label' was used. */
2465 static void label_pop(Sym **ptop, Sym *slast)
2467 Sym *s, *s1;
2468 for(s = *ptop; s != slast; s = s1) {
2469 s1 = s->prev;
2470 if (s->r == LABEL_DECLARED) {
2471 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2472 } else if (s->r == LABEL_FORWARD) {
2473 error("label '%s' used but not defined",
2474 get_tok_str(s->v, NULL));
2475 } else {
2476 if (s->c) {
2477 /* define corresponding symbol. A size of
2478 1 is put. */
2479 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2482 /* remove label */
2483 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2484 tcc_free(s);
2486 *ptop = slast;
2489 /* eval an expression for #if/#elif */
2490 static int expr_preprocess(void)
2492 int c, t;
2493 TokenString str;
2495 tok_str_new(&str);
2496 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2497 next(); /* do macro subst */
2498 if (tok == TOK_DEFINED) {
2499 next_nomacro();
2500 t = tok;
2501 if (t == '(')
2502 next_nomacro();
2503 c = define_find(tok) != 0;
2504 if (t == '(')
2505 next_nomacro();
2506 tok = TOK_CINT;
2507 tokc.i = c;
2508 } else if (tok >= TOK_IDENT) {
2509 /* if undefined macro */
2510 tok = TOK_CINT;
2511 tokc.i = 0;
2513 tok_str_add_tok(&str);
2515 tok_str_add(&str, -1); /* simulate end of file */
2516 tok_str_add(&str, 0);
2517 /* now evaluate C constant expression */
2518 macro_ptr = str.str;
2519 next();
2520 c = expr_const();
2521 macro_ptr = NULL;
2522 tok_str_free(str.str);
2523 return c != 0;
2526 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2527 static void tok_print(int *str)
2529 int t;
2530 CValue cval;
2532 while (1) {
2533 TOK_GET(t, str, cval);
2534 if (!t)
2535 break;
2536 printf(" %s", get_tok_str(t, &cval));
2538 printf("\n");
2540 #endif
2542 /* parse after #define */
2543 static void parse_define(void)
2545 Sym *s, *first, **ps;
2546 int v, t, varg, is_vaargs, c;
2547 TokenString str;
2549 v = tok;
2550 if (v < TOK_IDENT)
2551 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2552 /* XXX: should check if same macro (ANSI) */
2553 first = NULL;
2554 t = MACRO_OBJ;
2555 /* '(' must be just after macro definition for MACRO_FUNC */
2556 c = file->buf_ptr[0];
2557 if (c == '\\')
2558 c = handle_stray1(file->buf_ptr);
2559 if (c == '(') {
2560 next_nomacro();
2561 next_nomacro();
2562 ps = &first;
2563 while (tok != ')') {
2564 varg = tok;
2565 next_nomacro();
2566 is_vaargs = 0;
2567 if (varg == TOK_DOTS) {
2568 varg = TOK___VA_ARGS__;
2569 is_vaargs = 1;
2570 } else if (tok == TOK_DOTS && gnu_ext) {
2571 is_vaargs = 1;
2572 next_nomacro();
2574 if (varg < TOK_IDENT)
2575 error("badly punctuated parameter list");
2576 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2577 *ps = s;
2578 ps = &s->next;
2579 if (tok != ',')
2580 break;
2581 next_nomacro();
2583 t = MACRO_FUNC;
2585 tok_str_new(&str);
2586 next_nomacro();
2587 /* EOF testing necessary for '-D' handling */
2588 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2589 tok_str_add2(&str, tok, &tokc);
2590 next_nomacro();
2592 tok_str_add(&str, 0);
2593 #ifdef PP_DEBUG
2594 printf("define %s %d: ", get_tok_str(v, NULL), t);
2595 tok_print(str.str);
2596 #endif
2597 define_push(v, t, str.str, first);
2600 /* XXX: use a token or a hash table to accelerate matching ? */
2601 static CachedInclude *search_cached_include(TCCState *s1,
2602 int type, const char *filename)
2604 CachedInclude *e;
2605 int i;
2607 for(i = 0;i < s1->nb_cached_includes; i++) {
2608 e = s1->cached_includes[i];
2609 if (e->type == type && !strcmp(e->filename, filename))
2610 return e;
2612 return NULL;
2615 static inline void add_cached_include(TCCState *s1, int type,
2616 const char *filename, int ifndef_macro)
2618 CachedInclude *e;
2620 if (search_cached_include(s1, type, filename))
2621 return;
2622 #ifdef INC_DEBUG
2623 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2624 #endif
2625 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2626 if (!e)
2627 return;
2628 e->type = type;
2629 strcpy(e->filename, filename);
2630 e->ifndef_macro = ifndef_macro;
2631 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2634 /* is_bof is true if first non space token at beginning of file */
2635 static void preprocess(int is_bof)
2637 TCCState *s1 = tcc_state;
2638 int size, i, c, n, saved_parse_flags;
2639 char buf[1024], *q, *p;
2640 char buf1[1024];
2641 BufferedFile *f;
2642 Sym *s;
2643 CachedInclude *e;
2645 saved_parse_flags = parse_flags;
2646 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2647 PARSE_FLAG_LINEFEED;
2648 next_nomacro();
2649 redo:
2650 switch(tok) {
2651 case TOK_DEFINE:
2652 next_nomacro();
2653 parse_define();
2654 break;
2655 case TOK_UNDEF:
2656 next_nomacro();
2657 s = define_find(tok);
2658 /* undefine symbol by putting an invalid name */
2659 if (s)
2660 define_undef(s);
2661 break;
2662 case TOK_INCLUDE:
2663 ch = file->buf_ptr[0];
2664 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2665 skip_spaces();
2666 if (ch == '<') {
2667 c = '>';
2668 goto read_name;
2669 } else if (ch == '\"') {
2670 c = ch;
2671 read_name:
2672 /* XXX: better stray handling */
2673 minp();
2674 q = buf;
2675 while (ch != c && ch != '\n' && ch != CH_EOF) {
2676 if ((q - buf) < sizeof(buf) - 1)
2677 *q++ = ch;
2678 minp();
2680 *q = '\0';
2681 minp();
2682 #if 0
2683 /* eat all spaces and comments after include */
2684 /* XXX: slightly incorrect */
2685 while (ch1 != '\n' && ch1 != CH_EOF)
2686 inp();
2687 #endif
2688 } else {
2689 /* computed #include : either we have only strings or
2690 we have anything enclosed in '<>' */
2691 next();
2692 buf[0] = '\0';
2693 if (tok == TOK_STR) {
2694 while (tok != TOK_LINEFEED) {
2695 if (tok != TOK_STR) {
2696 include_syntax:
2697 error("'#include' expects \"FILENAME\" or <FILENAME>");
2699 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2700 next();
2702 c = '\"';
2703 } else {
2704 int len;
2705 while (tok != TOK_LINEFEED) {
2706 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2707 next();
2709 len = strlen(buf);
2710 /* check syntax and remove '<>' */
2711 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2712 goto include_syntax;
2713 memmove(buf, buf + 1, len - 2);
2714 buf[len - 2] = '\0';
2715 c = '>';
2719 e = search_cached_include(s1, c, buf);
2720 if (e && define_find(e->ifndef_macro)) {
2721 /* no need to parse the include because the 'ifndef macro'
2722 is defined */
2723 #ifdef INC_DEBUG
2724 printf("%s: skipping %s\n", file->filename, buf);
2725 #endif
2726 } else {
2727 if (c == '\"') {
2728 /* first search in current dir if "header.h" */
2729 size = 0;
2730 p = strrchr(file->filename, '/');
2731 if (p)
2732 size = p + 1 - file->filename;
2733 if (size > sizeof(buf1) - 1)
2734 size = sizeof(buf1) - 1;
2735 memcpy(buf1, file->filename, size);
2736 buf1[size] = '\0';
2737 pstrcat(buf1, sizeof(buf1), buf);
2738 f = tcc_open(s1, buf1);
2739 if (f)
2740 goto found;
2742 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2743 error("#include recursion too deep");
2744 /* now search in all the include paths */
2745 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2746 for(i = 0; i < n; i++) {
2747 const char *path;
2748 if (i < s1->nb_include_paths)
2749 path = s1->include_paths[i];
2750 else
2751 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2752 pstrcpy(buf1, sizeof(buf1), path);
2753 pstrcat(buf1, sizeof(buf1), "/");
2754 pstrcat(buf1, sizeof(buf1), buf);
2755 f = tcc_open(s1, buf1);
2756 if (f)
2757 goto found;
2759 error("include file '%s' not found", buf);
2760 f = NULL;
2761 found:
2762 #ifdef INC_DEBUG
2763 printf("%s: including %s\n", file->filename, buf1);
2764 #endif
2765 f->inc_type = c;
2766 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2767 /* push current file in stack */
2768 /* XXX: fix current line init */
2769 *s1->include_stack_ptr++ = file;
2770 file = f;
2771 /* add include file debug info */
2772 if (do_debug) {
2773 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2775 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2776 ch = file->buf_ptr[0];
2777 goto the_end;
2779 break;
2780 case TOK_IFNDEF:
2781 c = 1;
2782 goto do_ifdef;
2783 case TOK_IF:
2784 c = expr_preprocess();
2785 goto do_if;
2786 case TOK_IFDEF:
2787 c = 0;
2788 do_ifdef:
2789 next_nomacro();
2790 if (tok < TOK_IDENT)
2791 error("invalid argument for '#if%sdef'", c ? "n" : "");
2792 if (is_bof) {
2793 if (c) {
2794 #ifdef INC_DEBUG
2795 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2796 #endif
2797 file->ifndef_macro = tok;
2800 c = (define_find(tok) != 0) ^ c;
2801 do_if:
2802 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2803 error("memory full");
2804 *s1->ifdef_stack_ptr++ = c;
2805 goto test_skip;
2806 case TOK_ELSE:
2807 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2808 error("#else without matching #if");
2809 if (s1->ifdef_stack_ptr[-1] & 2)
2810 error("#else after #else");
2811 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2812 goto test_skip;
2813 case TOK_ELIF:
2814 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2815 error("#elif without matching #if");
2816 c = s1->ifdef_stack_ptr[-1];
2817 if (c > 1)
2818 error("#elif after #else");
2819 /* last #if/#elif expression was true: we skip */
2820 if (c == 1)
2821 goto skip;
2822 c = expr_preprocess();
2823 s1->ifdef_stack_ptr[-1] = c;
2824 test_skip:
2825 if (!(c & 1)) {
2826 skip:
2827 preprocess_skip();
2828 is_bof = 0;
2829 goto redo;
2831 break;
2832 case TOK_ENDIF:
2833 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2834 error("#endif without matching #if");
2835 s1->ifdef_stack_ptr--;
2836 /* '#ifndef macro' was at the start of file. Now we check if
2837 an '#endif' is exactly at the end of file */
2838 if (file->ifndef_macro &&
2839 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2840 file->ifndef_macro_saved = file->ifndef_macro;
2841 /* need to set to zero to avoid false matches if another
2842 #ifndef at middle of file */
2843 file->ifndef_macro = 0;
2844 while (tok != TOK_LINEFEED)
2845 next_nomacro();
2846 tok_flags |= TOK_FLAG_ENDIF;
2847 goto the_end;
2849 break;
2850 case TOK_LINE:
2851 next();
2852 if (tok != TOK_CINT)
2853 error("#line");
2854 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2855 next();
2856 if (tok != TOK_LINEFEED) {
2857 if (tok != TOK_STR)
2858 error("#line");
2859 pstrcpy(file->filename, sizeof(file->filename),
2860 (char *)tokc.cstr->data);
2862 break;
2863 case TOK_ERROR:
2864 case TOK_WARNING:
2865 c = tok;
2866 ch = file->buf_ptr[0];
2867 skip_spaces();
2868 q = buf;
2869 while (ch != '\n' && ch != CH_EOF) {
2870 if ((q - buf) < sizeof(buf) - 1)
2871 *q++ = ch;
2872 minp();
2874 *q = '\0';
2875 if (c == TOK_ERROR)
2876 error("#error %s", buf);
2877 else
2878 warning("#warning %s", buf);
2879 break;
2880 case TOK_PRAGMA:
2881 /* ignored */
2882 break;
2883 default:
2884 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2885 /* '!' is ignored to allow C scripts. numbers are ignored
2886 to emulate cpp behaviour */
2887 } else {
2888 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
2889 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2891 break;
2893 /* ignore other preprocess commands or #! for C scripts */
2894 while (tok != TOK_LINEFEED)
2895 next_nomacro();
2896 the_end:
2897 parse_flags = saved_parse_flags;
2900 /* evaluate escape codes in a string. */
2901 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2903 int c, n;
2904 const uint8_t *p;
2906 p = buf;
2907 for(;;) {
2908 c = *p;
2909 if (c == '\0')
2910 break;
2911 if (c == '\\') {
2912 p++;
2913 /* escape */
2914 c = *p;
2915 switch(c) {
2916 case '0': case '1': case '2': case '3':
2917 case '4': case '5': case '6': case '7':
2918 /* at most three octal digits */
2919 n = c - '0';
2920 p++;
2921 c = *p;
2922 if (isoct(c)) {
2923 n = n * 8 + c - '0';
2924 p++;
2925 c = *p;
2926 if (isoct(c)) {
2927 n = n * 8 + c - '0';
2928 p++;
2931 c = n;
2932 goto add_char_nonext;
2933 case 'x':
2934 p++;
2935 n = 0;
2936 for(;;) {
2937 c = *p;
2938 if (c >= 'a' && c <= 'f')
2939 c = c - 'a' + 10;
2940 else if (c >= 'A' && c <= 'F')
2941 c = c - 'A' + 10;
2942 else if (isnum(c))
2943 c = c - '0';
2944 else
2945 break;
2946 n = n * 16 + c;
2947 p++;
2949 c = n;
2950 goto add_char_nonext;
2951 case 'a':
2952 c = '\a';
2953 break;
2954 case 'b':
2955 c = '\b';
2956 break;
2957 case 'f':
2958 c = '\f';
2959 break;
2960 case 'n':
2961 c = '\n';
2962 break;
2963 case 'r':
2964 c = '\r';
2965 break;
2966 case 't':
2967 c = '\t';
2968 break;
2969 case 'v':
2970 c = '\v';
2971 break;
2972 case 'e':
2973 if (!gnu_ext)
2974 goto invalid_escape;
2975 c = 27;
2976 break;
2977 case '\'':
2978 case '\"':
2979 case '\\':
2980 case '?':
2981 break;
2982 default:
2983 invalid_escape:
2984 if (c >= '!' && c <= '~')
2985 warning("unknown escape sequence: \'\\%c\'", c);
2986 else
2987 warning("unknown escape sequence: \'\\x%x\'", c);
2988 break;
2991 p++;
2992 add_char_nonext:
2993 if (!is_long)
2994 cstr_ccat(outstr, c);
2995 else
2996 cstr_wccat(outstr, c);
2998 /* add a trailing '\0' */
2999 if (!is_long)
3000 cstr_ccat(outstr, '\0');
3001 else
3002 cstr_wccat(outstr, '\0');
3005 /* we use 64 bit numbers */
3006 #define BN_SIZE 2
3008 /* bn = (bn << shift) | or_val */
3009 void bn_lshift(unsigned int *bn, int shift, int or_val)
3011 int i;
3012 unsigned int v;
3013 for(i=0;i<BN_SIZE;i++) {
3014 v = bn[i];
3015 bn[i] = (v << shift) | or_val;
3016 or_val = v >> (32 - shift);
3020 void bn_zero(unsigned int *bn)
3022 int i;
3023 for(i=0;i<BN_SIZE;i++) {
3024 bn[i] = 0;
3028 /* parse number in null terminated string 'p' and return it in the
3029 current token */
3030 void parse_number(const char *p)
3032 int b, t, shift, frac_bits, s, exp_val, ch;
3033 char *q;
3034 unsigned int bn[BN_SIZE];
3035 double d;
3037 /* number */
3038 q = token_buf;
3039 ch = *p++;
3040 t = ch;
3041 ch = *p++;
3042 *q++ = t;
3043 b = 10;
3044 if (t == '.') {
3045 goto float_frac_parse;
3046 } else if (t == '0') {
3047 if (ch == 'x' || ch == 'X') {
3048 q--;
3049 ch = *p++;
3050 b = 16;
3051 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3052 q--;
3053 ch = *p++;
3054 b = 2;
3057 /* parse all digits. cannot check octal numbers at this stage
3058 because of floating point constants */
3059 while (1) {
3060 if (ch >= 'a' && ch <= 'f')
3061 t = ch - 'a' + 10;
3062 else if (ch >= 'A' && ch <= 'F')
3063 t = ch - 'A' + 10;
3064 else if (isnum(ch))
3065 t = ch - '0';
3066 else
3067 break;
3068 if (t >= b)
3069 break;
3070 if (q >= token_buf + STRING_MAX_SIZE) {
3071 num_too_long:
3072 error("number too long");
3074 *q++ = ch;
3075 ch = *p++;
3077 if (ch == '.' ||
3078 ((ch == 'e' || ch == 'E') && b == 10) ||
3079 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3080 if (b != 10) {
3081 /* NOTE: strtox should support that for hexa numbers, but
3082 non ISOC99 libcs do not support it, so we prefer to do
3083 it by hand */
3084 /* hexadecimal or binary floats */
3085 /* XXX: handle overflows */
3086 *q = '\0';
3087 if (b == 16)
3088 shift = 4;
3089 else
3090 shift = 2;
3091 bn_zero(bn);
3092 q = token_buf;
3093 while (1) {
3094 t = *q++;
3095 if (t == '\0') {
3096 break;
3097 } else if (t >= 'a') {
3098 t = t - 'a' + 10;
3099 } else if (t >= 'A') {
3100 t = t - 'A' + 10;
3101 } else {
3102 t = t - '0';
3104 bn_lshift(bn, shift, t);
3106 frac_bits = 0;
3107 if (ch == '.') {
3108 ch = *p++;
3109 while (1) {
3110 t = ch;
3111 if (t >= 'a' && t <= 'f') {
3112 t = t - 'a' + 10;
3113 } else if (t >= 'A' && t <= 'F') {
3114 t = t - 'A' + 10;
3115 } else if (t >= '0' && t <= '9') {
3116 t = t - '0';
3117 } else {
3118 break;
3120 if (t >= b)
3121 error("invalid digit");
3122 bn_lshift(bn, shift, t);
3123 frac_bits += shift;
3124 ch = *p++;
3127 if (ch != 'p' && ch != 'P')
3128 expect("exponent");
3129 ch = *p++;
3130 s = 1;
3131 exp_val = 0;
3132 if (ch == '+') {
3133 ch = *p++;
3134 } else if (ch == '-') {
3135 s = -1;
3136 ch = *p++;
3138 if (ch < '0' || ch > '9')
3139 expect("exponent digits");
3140 while (ch >= '0' && ch <= '9') {
3141 exp_val = exp_val * 10 + ch - '0';
3142 ch = *p++;
3144 exp_val = exp_val * s;
3146 /* now we can generate the number */
3147 /* XXX: should patch directly float number */
3148 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3149 d = ldexp(d, exp_val - frac_bits);
3150 t = toup(ch);
3151 if (t == 'F') {
3152 ch = *p++;
3153 tok = TOK_CFLOAT;
3154 /* float : should handle overflow */
3155 tokc.f = (float)d;
3156 } else if (t == 'L') {
3157 ch = *p++;
3158 tok = TOK_CLDOUBLE;
3159 /* XXX: not large enough */
3160 tokc.ld = (long double)d;
3161 } else {
3162 tok = TOK_CDOUBLE;
3163 tokc.d = d;
3165 } else {
3166 /* decimal floats */
3167 if (ch == '.') {
3168 if (q >= token_buf + STRING_MAX_SIZE)
3169 goto num_too_long;
3170 *q++ = ch;
3171 ch = *p++;
3172 float_frac_parse:
3173 while (ch >= '0' && ch <= '9') {
3174 if (q >= token_buf + STRING_MAX_SIZE)
3175 goto num_too_long;
3176 *q++ = ch;
3177 ch = *p++;
3180 if (ch == 'e' || ch == 'E') {
3181 if (q >= token_buf + STRING_MAX_SIZE)
3182 goto num_too_long;
3183 *q++ = ch;
3184 ch = *p++;
3185 if (ch == '-' || ch == '+') {
3186 if (q >= token_buf + STRING_MAX_SIZE)
3187 goto num_too_long;
3188 *q++ = ch;
3189 ch = *p++;
3191 if (ch < '0' || ch > '9')
3192 expect("exponent digits");
3193 while (ch >= '0' && ch <= '9') {
3194 if (q >= token_buf + STRING_MAX_SIZE)
3195 goto num_too_long;
3196 *q++ = ch;
3197 ch = *p++;
3200 *q = '\0';
3201 t = toup(ch);
3202 errno = 0;
3203 if (t == 'F') {
3204 ch = *p++;
3205 tok = TOK_CFLOAT;
3206 tokc.f = strtof(token_buf, NULL);
3207 } else if (t == 'L') {
3208 ch = *p++;
3209 tok = TOK_CLDOUBLE;
3210 tokc.ld = strtold(token_buf, NULL);
3211 } else {
3212 tok = TOK_CDOUBLE;
3213 tokc.d = strtod(token_buf, NULL);
3216 } else {
3217 unsigned long long n, n1;
3218 int lcount, ucount;
3220 /* integer number */
3221 *q = '\0';
3222 q = token_buf;
3223 if (b == 10 && *q == '0') {
3224 b = 8;
3225 q++;
3227 n = 0;
3228 while(1) {
3229 t = *q++;
3230 /* no need for checks except for base 10 / 8 errors */
3231 if (t == '\0') {
3232 break;
3233 } else if (t >= 'a') {
3234 t = t - 'a' + 10;
3235 } else if (t >= 'A') {
3236 t = t - 'A' + 10;
3237 } else {
3238 t = t - '0';
3239 if (t >= b)
3240 error("invalid digit");
3242 n1 = n;
3243 n = n * b + t;
3244 /* detect overflow */
3245 /* XXX: this test is not reliable */
3246 if (n < n1)
3247 error("integer constant overflow");
3250 /* XXX: not exactly ANSI compliant */
3251 if ((n & 0xffffffff00000000LL) != 0) {
3252 if ((n >> 63) != 0)
3253 tok = TOK_CULLONG;
3254 else
3255 tok = TOK_CLLONG;
3256 } else if (n > 0x7fffffff) {
3257 tok = TOK_CUINT;
3258 } else {
3259 tok = TOK_CINT;
3261 lcount = 0;
3262 ucount = 0;
3263 for(;;) {
3264 t = toup(ch);
3265 if (t == 'L') {
3266 if (lcount >= 2)
3267 error("three 'l's in integer constant");
3268 lcount++;
3269 if (lcount == 2) {
3270 if (tok == TOK_CINT)
3271 tok = TOK_CLLONG;
3272 else if (tok == TOK_CUINT)
3273 tok = TOK_CULLONG;
3275 ch = *p++;
3276 } else if (t == 'U') {
3277 if (ucount >= 1)
3278 error("two 'u's in integer constant");
3279 ucount++;
3280 if (tok == TOK_CINT)
3281 tok = TOK_CUINT;
3282 else if (tok == TOK_CLLONG)
3283 tok = TOK_CULLONG;
3284 ch = *p++;
3285 } else {
3286 break;
3289 if (tok == TOK_CINT || tok == TOK_CUINT)
3290 tokc.ui = n;
3291 else
3292 tokc.ull = n;
3297 #define PARSE2(c1, tok1, c2, tok2) \
3298 case c1: \
3299 PEEKC(c, p); \
3300 if (c == c2) { \
3301 p++; \
3302 tok = tok2; \
3303 } else { \
3304 tok = tok1; \
3306 break;
3308 /* return next token without macro substitution */
3309 static inline void next_nomacro1(void)
3311 int t, c, is_long;
3312 TokenSym *ts;
3313 uint8_t *p, *p1;
3314 unsigned int h;
3316 p = file->buf_ptr;
3317 redo_no_start:
3318 c = *p;
3319 switch(c) {
3320 case ' ':
3321 case '\t':
3322 case '\f':
3323 case '\v':
3324 case '\r':
3325 p++;
3326 goto redo_no_start;
3328 case '\\':
3329 /* first look if it is in fact an end of buffer */
3330 if (p >= file->buf_end) {
3331 file->buf_ptr = p;
3332 handle_eob();
3333 p = file->buf_ptr;
3334 if (p >= file->buf_end)
3335 goto parse_eof;
3336 else
3337 goto redo_no_start;
3338 } else {
3339 file->buf_ptr = p;
3340 ch = *p;
3341 handle_stray();
3342 p = file->buf_ptr;
3343 goto redo_no_start;
3345 parse_eof:
3347 TCCState *s1 = tcc_state;
3348 if (parse_flags & PARSE_FLAG_LINEFEED) {
3349 tok = TOK_LINEFEED;
3350 } else if (s1->include_stack_ptr == s1->include_stack ||
3351 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3352 /* no include left : end of file. */
3353 tok = TOK_EOF;
3354 } else {
3355 /* pop include file */
3357 /* test if previous '#endif' was after a #ifdef at
3358 start of file */
3359 if (tok_flags & TOK_FLAG_ENDIF) {
3360 #ifdef INC_DEBUG
3361 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3362 #endif
3363 add_cached_include(s1, file->inc_type, file->inc_filename,
3364 file->ifndef_macro_saved);
3367 /* add end of include file debug info */
3368 if (do_debug) {
3369 put_stabd(N_EINCL, 0, 0);
3371 /* pop include stack */
3372 tcc_close(file);
3373 s1->include_stack_ptr--;
3374 file = *s1->include_stack_ptr;
3375 p = file->buf_ptr;
3376 goto redo_no_start;
3379 break;
3381 case '\n':
3382 if (parse_flags & PARSE_FLAG_LINEFEED) {
3383 tok = TOK_LINEFEED;
3384 } else {
3385 file->line_num++;
3386 tok_flags |= TOK_FLAG_BOL;
3387 p++;
3388 goto redo_no_start;
3390 break;
3392 case '#':
3393 /* XXX: simplify */
3394 PEEKC(c, p);
3395 if ((tok_flags & TOK_FLAG_BOL) &&
3396 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3397 file->buf_ptr = p;
3398 preprocess(tok_flags & TOK_FLAG_BOF);
3399 p = file->buf_ptr;
3400 goto redo_no_start;
3401 } else {
3402 if (c == '#') {
3403 p++;
3404 tok = TOK_TWOSHARPS;
3405 } else {
3406 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3407 p = parse_line_comment(p - 1);
3408 goto redo_no_start;
3409 } else {
3410 tok = '#';
3414 break;
3416 case 'a': case 'b': case 'c': case 'd':
3417 case 'e': case 'f': case 'g': case 'h':
3418 case 'i': case 'j': case 'k': case 'l':
3419 case 'm': case 'n': case 'o': case 'p':
3420 case 'q': case 'r': case 's': case 't':
3421 case 'u': case 'v': case 'w': case 'x':
3422 case 'y': case 'z':
3423 case 'A': case 'B': case 'C': case 'D':
3424 case 'E': case 'F': case 'G': case 'H':
3425 case 'I': case 'J': case 'K':
3426 case 'M': case 'N': case 'O': case 'P':
3427 case 'Q': case 'R': case 'S': case 'T':
3428 case 'U': case 'V': case 'W': case 'X':
3429 case 'Y': case 'Z':
3430 case '_':
3431 parse_ident_fast:
3432 p1 = p;
3433 h = TOK_HASH_INIT;
3434 h = TOK_HASH_FUNC(h, c);
3435 p++;
3436 for(;;) {
3437 c = *p;
3438 if (!isidnum_table[c])
3439 break;
3440 h = TOK_HASH_FUNC(h, c);
3441 p++;
3443 if (c != '\\') {
3444 TokenSym **pts;
3445 int len;
3447 /* fast case : no stray found, so we have the full token
3448 and we have already hashed it */
3449 len = p - p1;
3450 h &= (TOK_HASH_SIZE - 1);
3451 pts = &hash_ident[h];
3452 for(;;) {
3453 ts = *pts;
3454 if (!ts)
3455 break;
3456 if (ts->len == len && !memcmp(ts->str, p1, len))
3457 goto token_found;
3458 pts = &(ts->hash_next);
3460 ts = tok_alloc_new(pts, p1, len);
3461 token_found: ;
3462 } else {
3463 /* slower case */
3464 cstr_reset(&tokcstr);
3466 while (p1 < p) {
3467 cstr_ccat(&tokcstr, *p1);
3468 p1++;
3470 p--;
3471 PEEKC(c, p);
3472 parse_ident_slow:
3473 while (isidnum_table[c]) {
3474 cstr_ccat(&tokcstr, c);
3475 PEEKC(c, p);
3477 ts = tok_alloc(tokcstr.data, tokcstr.size);
3479 tok = ts->tok;
3480 break;
3481 case 'L':
3482 t = p[1];
3483 if (t != '\\' && t != '\'' && t != '\"') {
3484 /* fast case */
3485 goto parse_ident_fast;
3486 } else {
3487 PEEKC(c, p);
3488 if (c == '\'' || c == '\"') {
3489 is_long = 1;
3490 goto str_const;
3491 } else {
3492 cstr_reset(&tokcstr);
3493 cstr_ccat(&tokcstr, 'L');
3494 goto parse_ident_slow;
3497 break;
3498 case '0': case '1': case '2': case '3':
3499 case '4': case '5': case '6': case '7':
3500 case '8': case '9':
3502 cstr_reset(&tokcstr);
3503 /* after the first digit, accept digits, alpha, '.' or sign if
3504 prefixed by 'eEpP' */
3505 parse_num:
3506 for(;;) {
3507 t = c;
3508 cstr_ccat(&tokcstr, c);
3509 PEEKC(c, p);
3510 if (!(isnum(c) || isid(c) || c == '.' ||
3511 ((c == '+' || c == '-') &&
3512 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3513 break;
3515 /* We add a trailing '\0' to ease parsing */
3516 cstr_ccat(&tokcstr, '\0');
3517 tokc.cstr = &tokcstr;
3518 tok = TOK_PPNUM;
3519 break;
3520 case '.':
3521 /* special dot handling because it can also start a number */
3522 PEEKC(c, p);
3523 if (isnum(c)) {
3524 cstr_reset(&tokcstr);
3525 cstr_ccat(&tokcstr, '.');
3526 goto parse_num;
3527 } else if (c == '.') {
3528 PEEKC(c, p);
3529 if (c != '.')
3530 expect("'.'");
3531 PEEKC(c, p);
3532 tok = TOK_DOTS;
3533 } else {
3534 tok = '.';
3536 break;
3537 case '\'':
3538 case '\"':
3539 is_long = 0;
3540 str_const:
3542 CString str;
3543 int sep;
3545 sep = c;
3547 /* parse the string */
3548 cstr_new(&str);
3549 p = parse_pp_string(p, sep, &str);
3550 cstr_ccat(&str, '\0');
3552 /* eval the escape (should be done as TOK_PPNUM) */
3553 cstr_reset(&tokcstr);
3554 parse_escape_string(&tokcstr, str.data, is_long);
3555 cstr_free(&str);
3557 if (sep == '\'') {
3558 int char_size;
3559 /* XXX: make it portable */
3560 if (!is_long)
3561 char_size = 1;
3562 else
3563 char_size = sizeof(int);
3564 if (tokcstr.size <= char_size)
3565 error("empty character constant");
3566 if (tokcstr.size > 2 * char_size)
3567 warning("multi-character character constant");
3568 if (!is_long) {
3569 tokc.i = *(int8_t *)tokcstr.data;
3570 tok = TOK_CCHAR;
3571 } else {
3572 tokc.i = *(int *)tokcstr.data;
3573 tok = TOK_LCHAR;
3575 } else {
3576 tokc.cstr = &tokcstr;
3577 if (!is_long)
3578 tok = TOK_STR;
3579 else
3580 tok = TOK_LSTR;
3583 break;
3585 case '<':
3586 PEEKC(c, p);
3587 if (c == '=') {
3588 p++;
3589 tok = TOK_LE;
3590 } else if (c == '<') {
3591 PEEKC(c, p);
3592 if (c == '=') {
3593 p++;
3594 tok = TOK_A_SHL;
3595 } else {
3596 tok = TOK_SHL;
3598 } else {
3599 tok = TOK_LT;
3601 break;
3603 case '>':
3604 PEEKC(c, p);
3605 if (c == '=') {
3606 p++;
3607 tok = TOK_GE;
3608 } else if (c == '>') {
3609 PEEKC(c, p);
3610 if (c == '=') {
3611 p++;
3612 tok = TOK_A_SAR;
3613 } else {
3614 tok = TOK_SAR;
3616 } else {
3617 tok = TOK_GT;
3619 break;
3621 case '&':
3622 PEEKC(c, p);
3623 if (c == '&') {
3624 p++;
3625 tok = TOK_LAND;
3626 } else if (c == '=') {
3627 p++;
3628 tok = TOK_A_AND;
3629 } else {
3630 tok = '&';
3632 break;
3634 case '|':
3635 PEEKC(c, p);
3636 if (c == '|') {
3637 p++;
3638 tok = TOK_LOR;
3639 } else if (c == '=') {
3640 p++;
3641 tok = TOK_A_OR;
3642 } else {
3643 tok = '|';
3645 break;
3647 case '+':
3648 PEEKC(c, p);
3649 if (c == '+') {
3650 p++;
3651 tok = TOK_INC;
3652 } else if (c == '=') {
3653 p++;
3654 tok = TOK_A_ADD;
3655 } else {
3656 tok = '+';
3658 break;
3660 case '-':
3661 PEEKC(c, p);
3662 if (c == '-') {
3663 p++;
3664 tok = TOK_DEC;
3665 } else if (c == '=') {
3666 p++;
3667 tok = TOK_A_SUB;
3668 } else if (c == '>') {
3669 p++;
3670 tok = TOK_ARROW;
3671 } else {
3672 tok = '-';
3674 break;
3676 PARSE2('!', '!', '=', TOK_NE)
3677 PARSE2('=', '=', '=', TOK_EQ)
3678 PARSE2('*', '*', '=', TOK_A_MUL)
3679 PARSE2('%', '%', '=', TOK_A_MOD)
3680 PARSE2('^', '^', '=', TOK_A_XOR)
3682 /* comments or operator */
3683 case '/':
3684 PEEKC(c, p);
3685 if (c == '*') {
3686 p = parse_comment(p);
3687 goto redo_no_start;
3688 } else if (c == '/') {
3689 p = parse_line_comment(p);
3690 goto redo_no_start;
3691 } else if (c == '=') {
3692 p++;
3693 tok = TOK_A_DIV;
3694 } else {
3695 tok = '/';
3697 break;
3699 /* simple tokens */
3700 case '(':
3701 case ')':
3702 case '[':
3703 case ']':
3704 case '{':
3705 case '}':
3706 case ',':
3707 case ';':
3708 case ':':
3709 case '?':
3710 case '~':
3711 case '$': /* only used in assembler */
3712 tok = c;
3713 p++;
3714 break;
3715 default:
3716 error("unrecognized character \\x%02x", c);
3717 break;
3719 file->buf_ptr = p;
3720 tok_flags = 0;
3721 #if defined(PARSE_DEBUG)
3722 printf("token = %s\n", get_tok_str(tok, &tokc));
3723 #endif
3726 /* return next token without macro substitution. Can read input from
3727 macro_ptr buffer */
3728 static void next_nomacro(void)
3730 if (macro_ptr) {
3731 redo:
3732 tok = *macro_ptr;
3733 if (tok) {
3734 TOK_GET(tok, macro_ptr, tokc);
3735 if (tok == TOK_LINENUM) {
3736 file->line_num = tokc.i;
3737 goto redo;
3740 } else {
3741 next_nomacro1();
3745 /* substitute args in macro_str and return allocated string */
3746 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3748 int *st, last_tok, t, notfirst;
3749 Sym *s;
3750 CValue cval;
3751 TokenString str;
3752 CString cstr;
3754 tok_str_new(&str);
3755 last_tok = 0;
3756 while(1) {
3757 TOK_GET(t, macro_str, cval);
3758 if (!t)
3759 break;
3760 if (t == '#') {
3761 /* stringize */
3762 TOK_GET(t, macro_str, cval);
3763 if (!t)
3764 break;
3765 s = sym_find2(args, t);
3766 if (s) {
3767 cstr_new(&cstr);
3768 st = (int *)s->c;
3769 notfirst = 0;
3770 while (*st) {
3771 if (notfirst)
3772 cstr_ccat(&cstr, ' ');
3773 TOK_GET(t, st, cval);
3774 cstr_cat(&cstr, get_tok_str(t, &cval));
3775 notfirst = 1;
3777 cstr_ccat(&cstr, '\0');
3778 #ifdef PP_DEBUG
3779 printf("stringize: %s\n", (char *)cstr.data);
3780 #endif
3781 /* add string */
3782 cval.cstr = &cstr;
3783 tok_str_add2(&str, TOK_STR, &cval);
3784 cstr_free(&cstr);
3785 } else {
3786 tok_str_add2(&str, t, &cval);
3788 } else if (t >= TOK_IDENT) {
3789 s = sym_find2(args, t);
3790 if (s) {
3791 st = (int *)s->c;
3792 /* if '##' is present before or after, no arg substitution */
3793 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3794 /* special case for var arg macros : ## eats the
3795 ',' if empty VA_ARGS variable. */
3796 /* XXX: test of the ',' is not 100%
3797 reliable. should fix it to avoid security
3798 problems */
3799 if (gnu_ext && s->type.t &&
3800 last_tok == TOK_TWOSHARPS &&
3801 str.len >= 2 && str.str[str.len - 2] == ',') {
3802 if (*st == 0) {
3803 /* suppress ',' '##' */
3804 str.len -= 2;
3805 } else {
3806 /* suppress '##' and add variable */
3807 str.len--;
3808 goto add_var;
3810 } else {
3811 int t1;
3812 add_var:
3813 for(;;) {
3814 TOK_GET(t1, st, cval);
3815 if (!t1)
3816 break;
3817 tok_str_add2(&str, t1, &cval);
3820 } else {
3821 /* NOTE: the stream cannot be read when macro
3822 substituing an argument */
3823 macro_subst(&str, nested_list, st, 0);
3825 } else {
3826 tok_str_add(&str, t);
3828 } else {
3829 tok_str_add2(&str, t, &cval);
3831 last_tok = t;
3833 tok_str_add(&str, 0);
3834 return str.str;
3837 static char const ab_month_name[12][4] =
3839 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3840 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3843 /* do macro substitution of current token with macro 's' and add
3844 result to (tok_str,tok_len). 'nested_list' is the list of all
3845 macros we got inside to avoid recursing. Return non zero if no
3846 substitution needs to be done */
3847 static int macro_subst_tok(TokenString *tok_str,
3848 Sym **nested_list, Sym *s, int can_read_stream)
3850 Sym *args, *sa, *sa1;
3851 int mstr_allocated, parlevel, *mstr, t, t1;
3852 TokenString str;
3853 char *cstrval;
3854 CValue cval;
3855 CString cstr;
3856 char buf[32];
3858 /* if symbol is a macro, prepare substitution */
3859 /* special macros */
3860 if (tok == TOK___LINE__) {
3861 snprintf(buf, sizeof(buf), "%d", file->line_num);
3862 cstrval = buf;
3863 t1 = TOK_PPNUM;
3864 goto add_cstr1;
3865 } else if (tok == TOK___FILE__) {
3866 cstrval = file->filename;
3867 goto add_cstr;
3868 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3869 time_t ti;
3870 struct tm *tm;
3872 time(&ti);
3873 tm = localtime(&ti);
3874 if (tok == TOK___DATE__) {
3875 snprintf(buf, sizeof(buf), "%s %2d %d",
3876 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3877 } else {
3878 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3879 tm->tm_hour, tm->tm_min, tm->tm_sec);
3881 cstrval = buf;
3882 add_cstr:
3883 t1 = TOK_STR;
3884 add_cstr1:
3885 cstr_new(&cstr);
3886 cstr_cat(&cstr, cstrval);
3887 cstr_ccat(&cstr, '\0');
3888 cval.cstr = &cstr;
3889 tok_str_add2(tok_str, t1, &cval);
3890 cstr_free(&cstr);
3891 } else {
3892 mstr = (int *)s->c;
3893 mstr_allocated = 0;
3894 if (s->type.t == MACRO_FUNC) {
3895 /* NOTE: we do not use next_nomacro to avoid eating the
3896 next token. XXX: find better solution */
3897 if (macro_ptr) {
3898 t = *macro_ptr;
3899 if (t == 0 && can_read_stream) {
3900 /* end of macro stream: we must look at the token
3901 after in the file */
3902 macro_ptr = NULL;
3903 goto parse_stream;
3905 } else {
3906 parse_stream:
3907 /* XXX: incorrect with comments */
3908 ch = file->buf_ptr[0];
3909 while (is_space(ch) || ch == '\n')
3910 cinp();
3911 t = ch;
3913 if (t != '(') /* no macro subst */
3914 return -1;
3916 /* argument macro */
3917 next_nomacro();
3918 next_nomacro();
3919 args = NULL;
3920 sa = s->next;
3921 /* NOTE: empty args are allowed, except if no args */
3922 for(;;) {
3923 /* handle '()' case */
3924 if (!args && !sa && tok == ')')
3925 break;
3926 if (!sa)
3927 error("macro '%s' used with too many args",
3928 get_tok_str(s->v, 0));
3929 tok_str_new(&str);
3930 parlevel = 0;
3931 /* NOTE: non zero sa->t indicates VA_ARGS */
3932 while ((parlevel > 0 ||
3933 (tok != ')' &&
3934 (tok != ',' || sa->type.t))) &&
3935 tok != -1) {
3936 if (tok == '(')
3937 parlevel++;
3938 else if (tok == ')')
3939 parlevel--;
3940 tok_str_add2(&str, tok, &tokc);
3941 next_nomacro();
3943 tok_str_add(&str, 0);
3944 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3945 sa = sa->next;
3946 if (tok == ')') {
3947 /* special case for gcc var args: add an empty
3948 var arg argument if it is omitted */
3949 if (sa && sa->type.t && gnu_ext)
3950 continue;
3951 else
3952 break;
3954 if (tok != ',')
3955 expect(",");
3956 next_nomacro();
3958 if (sa) {
3959 error("macro '%s' used with too few args",
3960 get_tok_str(s->v, 0));
3963 /* now subst each arg */
3964 mstr = macro_arg_subst(nested_list, mstr, args);
3965 /* free memory */
3966 sa = args;
3967 while (sa) {
3968 sa1 = sa->prev;
3969 tok_str_free((int *)sa->c);
3970 tcc_free(sa);
3971 sa = sa1;
3973 mstr_allocated = 1;
3975 sym_push2(nested_list, s->v, 0, 0);
3976 macro_subst(tok_str, nested_list, mstr, 1);
3977 /* pop nested defined symbol */
3978 sa1 = *nested_list;
3979 *nested_list = sa1->prev;
3980 tcc_free(sa1);
3981 if (mstr_allocated)
3982 tok_str_free(mstr);
3984 return 0;
3987 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3988 return the resulting string (which must be freed). */
3989 static inline int *macro_twosharps(const int *macro_str)
3991 TokenSym *ts;
3992 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3993 int t;
3994 const char *p1, *p2;
3995 CValue cval;
3996 TokenString macro_str1;
3997 CString cstr;
3999 start_macro_ptr = macro_str;
4000 /* we search the first '##' */
4001 for(;;) {
4002 macro_ptr1 = macro_str;
4003 TOK_GET(t, macro_str, cval);
4004 /* nothing more to do if end of string */
4005 if (t == 0)
4006 return NULL;
4007 if (*macro_str == TOK_TWOSHARPS)
4008 break;
4011 /* we saw '##', so we need more processing to handle it */
4012 cstr_new(&cstr);
4013 tok_str_new(&macro_str1);
4014 tok = t;
4015 tokc = cval;
4017 /* add all tokens seen so far */
4018 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4019 TOK_GET(t, ptr, cval);
4020 tok_str_add2(&macro_str1, t, &cval);
4022 saved_macro_ptr = macro_ptr;
4023 /* XXX: get rid of the use of macro_ptr here */
4024 macro_ptr = (int *)macro_str;
4025 for(;;) {
4026 while (*macro_ptr == TOK_TWOSHARPS) {
4027 macro_ptr++;
4028 macro_ptr1 = macro_ptr;
4029 t = *macro_ptr;
4030 if (t) {
4031 TOK_GET(t, macro_ptr, cval);
4032 /* We concatenate the two tokens if we have an
4033 identifier or a preprocessing number */
4034 cstr_reset(&cstr);
4035 p1 = get_tok_str(tok, &tokc);
4036 cstr_cat(&cstr, p1);
4037 p2 = get_tok_str(t, &cval);
4038 cstr_cat(&cstr, p2);
4039 cstr_ccat(&cstr, '\0');
4041 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4042 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4043 if (tok == TOK_PPNUM) {
4044 /* if number, then create a number token */
4045 /* NOTE: no need to allocate because
4046 tok_str_add2() does it */
4047 tokc.cstr = &cstr;
4048 } else {
4049 /* if identifier, we must do a test to
4050 validate we have a correct identifier */
4051 if (t == TOK_PPNUM) {
4052 const char *p;
4053 int c;
4055 p = p2;
4056 for(;;) {
4057 c = *p;
4058 if (c == '\0')
4059 break;
4060 p++;
4061 if (!isnum(c) && !isid(c))
4062 goto error_pasting;
4065 ts = tok_alloc(cstr.data, strlen(cstr.data));
4066 tok = ts->tok; /* modify current token */
4068 } else {
4069 const char *str = cstr.data;
4070 const unsigned char *q;
4072 /* we look for a valid token */
4073 /* XXX: do more extensive checks */
4074 if (!strcmp(str, ">>=")) {
4075 tok = TOK_A_SAR;
4076 } else if (!strcmp(str, "<<=")) {
4077 tok = TOK_A_SHL;
4078 } else if (strlen(str) == 2) {
4079 /* search in two bytes table */
4080 q = tok_two_chars;
4081 for(;;) {
4082 if (!*q)
4083 goto error_pasting;
4084 if (q[0] == str[0] && q[1] == str[1])
4085 break;
4086 q += 3;
4088 tok = q[2];
4089 } else {
4090 error_pasting:
4091 /* NOTE: because get_tok_str use a static buffer,
4092 we must save it */
4093 cstr_reset(&cstr);
4094 p1 = get_tok_str(tok, &tokc);
4095 cstr_cat(&cstr, p1);
4096 cstr_ccat(&cstr, '\0');
4097 p2 = get_tok_str(t, &cval);
4098 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4099 /* cannot merge tokens: just add them separately */
4100 tok_str_add2(&macro_str1, tok, &tokc);
4101 /* XXX: free associated memory ? */
4102 tok = t;
4103 tokc = cval;
4108 tok_str_add2(&macro_str1, tok, &tokc);
4109 next_nomacro();
4110 if (tok == 0)
4111 break;
4113 macro_ptr = (int *)saved_macro_ptr;
4114 cstr_free(&cstr);
4115 tok_str_add(&macro_str1, 0);
4116 return macro_str1.str;
4120 /* do macro substitution of macro_str and add result to
4121 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4122 inside to avoid recursing. */
4123 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4124 const int *macro_str, int can_read_stream)
4126 Sym *s;
4127 int *saved_macro_ptr, *macro_str1;
4128 const int *ptr;
4129 int t, ret;
4130 CValue cval;
4132 /* first scan for '##' operator handling */
4133 ptr = macro_str;
4134 macro_str1 = macro_twosharps(ptr);
4135 if (macro_str1)
4136 ptr = macro_str1;
4137 while (1) {
4138 /* NOTE: ptr == NULL can only happen if tokens are read from
4139 file stream due to a macro function call */
4140 if (ptr == NULL)
4141 break;
4142 TOK_GET(t, ptr, cval);
4143 if (t == 0)
4144 break;
4145 s = define_find(t);
4146 if (s != NULL) {
4147 /* if nested substitution, do nothing */
4148 if (sym_find2(*nested_list, t))
4149 goto no_subst;
4150 saved_macro_ptr = macro_ptr;
4151 macro_ptr = (int *)ptr;
4152 tok = t;
4153 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4154 ptr = (int *)macro_ptr;
4155 macro_ptr = saved_macro_ptr;
4156 if (ret != 0)
4157 goto no_subst;
4158 } else {
4159 no_subst:
4160 tok_str_add2(tok_str, t, &cval);
4163 if (macro_str1)
4164 tok_str_free(macro_str1);
4167 /* return next token with macro substitution */
4168 static void next(void)
4170 Sym *nested_list, *s;
4171 TokenString str;
4173 redo:
4174 next_nomacro();
4175 if (!macro_ptr) {
4176 /* if not reading from macro substituted string, then try
4177 to substitute macros */
4178 if (tok >= TOK_IDENT &&
4179 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4180 s = define_find(tok);
4181 if (s) {
4182 /* we have a macro: we try to substitute */
4183 tok_str_new(&str);
4184 nested_list = NULL;
4185 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4186 /* substitution done, NOTE: maybe empty */
4187 tok_str_add(&str, 0);
4188 macro_ptr = str.str;
4189 macro_ptr_allocated = str.str;
4190 goto redo;
4194 } else {
4195 if (tok == 0) {
4196 /* end of macro or end of unget buffer */
4197 if (unget_buffer_enabled) {
4198 macro_ptr = unget_saved_macro_ptr;
4199 unget_buffer_enabled = 0;
4200 } else {
4201 /* end of macro string: free it */
4202 tok_str_free(macro_ptr_allocated);
4203 macro_ptr = NULL;
4205 goto redo;
4209 /* convert preprocessor tokens into C tokens */
4210 if (tok == TOK_PPNUM &&
4211 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4212 parse_number((char *)tokc.cstr->data);
4216 /* push back current token and set current token to 'last_tok'. Only
4217 identifier case handled for labels. */
4218 static inline void unget_tok(int last_tok)
4220 int i, n;
4221 int *q;
4222 unget_saved_macro_ptr = macro_ptr;
4223 unget_buffer_enabled = 1;
4224 q = unget_saved_buffer;
4225 macro_ptr = q;
4226 *q++ = tok;
4227 n = tok_ext_size(tok) - 1;
4228 for(i=0;i<n;i++)
4229 *q++ = tokc.tab[i];
4230 *q = 0; /* end of token string */
4231 tok = last_tok;
4235 void swap(int *p, int *q)
4237 int t;
4238 t = *p;
4239 *p = *q;
4240 *q = t;
4243 void vsetc(CType *type, int r, CValue *vc)
4245 int v;
4247 if (vtop >= vstack + VSTACK_SIZE)
4248 error("memory full");
4249 /* cannot let cpu flags if other instruction are generated. Also
4250 avoid leaving VT_JMP anywhere except on the top of the stack
4251 because it would complicate the code generator. */
4252 if (vtop >= vstack) {
4253 v = vtop->r & VT_VALMASK;
4254 if (v == VT_CMP || (v & ~1) == VT_JMP)
4255 gv(RC_INT);
4257 vtop++;
4258 vtop->type = *type;
4259 vtop->r = r;
4260 vtop->r2 = VT_CONST;
4261 vtop->c = *vc;
4264 /* push integer constant */
4265 void vpushi(int v)
4267 CValue cval;
4268 cval.i = v;
4269 vsetc(&int_type, VT_CONST, &cval);
4272 /* Return a static symbol pointing to a section */
4273 static Sym *get_sym_ref(CType *type, Section *sec,
4274 unsigned long offset, unsigned long size)
4276 int v;
4277 Sym *sym;
4279 v = anon_sym++;
4280 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4281 sym->type.ref = type->ref;
4282 sym->r = VT_CONST | VT_SYM;
4283 put_extern_sym(sym, sec, offset, size);
4284 return sym;
4287 /* push a reference to a section offset by adding a dummy symbol */
4288 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4290 CValue cval;
4292 cval.ul = 0;
4293 vsetc(type, VT_CONST | VT_SYM, &cval);
4294 vtop->sym = get_sym_ref(type, sec, offset, size);
4297 /* define a new external reference to a symbol 'v' of type 'u' */
4298 static Sym *external_global_sym(int v, CType *type, int r)
4300 Sym *s;
4302 s = sym_find(v);
4303 if (!s) {
4304 /* push forward reference */
4305 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4306 s->type.ref = type->ref;
4307 s->r = r | VT_CONST | VT_SYM;
4309 return s;
4312 /* define a new external reference to a symbol 'v' of type 'u' */
4313 static Sym *external_sym(int v, CType *type, int r)
4315 Sym *s;
4317 s = sym_find(v);
4318 if (!s) {
4319 /* push forward reference */
4320 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4321 s->type.t |= VT_EXTERN;
4322 } else {
4323 if (!is_compatible_types(&s->type, type))
4324 error("incompatible types for redefinition of '%s'",
4325 get_tok_str(v, NULL));
4327 return s;
4330 /* push a reference to global symbol v */
4331 static void vpush_global_sym(CType *type, int v)
4333 Sym *sym;
4334 CValue cval;
4336 sym = external_global_sym(v, type, 0);
4337 cval.ul = 0;
4338 vsetc(type, VT_CONST | VT_SYM, &cval);
4339 vtop->sym = sym;
4342 void vset(CType *type, int r, int v)
4344 CValue cval;
4346 cval.i = v;
4347 vsetc(type, r, &cval);
4350 void vseti(int r, int v)
4352 CType type;
4353 type.t = VT_INT;
4354 vset(&type, r, v);
4357 void vswap(void)
4359 SValue tmp;
4361 tmp = vtop[0];
4362 vtop[0] = vtop[-1];
4363 vtop[-1] = tmp;
4366 void vpushv(SValue *v)
4368 if (vtop >= vstack + VSTACK_SIZE)
4369 error("memory full");
4370 vtop++;
4371 *vtop = *v;
4374 void vdup(void)
4376 vpushv(vtop);
4379 /* save r to the memory stack, and mark it as being free */
4380 void save_reg(int r)
4382 int l, saved, size, align;
4383 SValue *p, sv;
4384 CType *type;
4386 /* modify all stack values */
4387 saved = 0;
4388 l = 0;
4389 for(p=vstack;p<=vtop;p++) {
4390 if ((p->r & VT_VALMASK) == r ||
4391 (p->r2 & VT_VALMASK) == r) {
4392 /* must save value on stack if not already done */
4393 if (!saved) {
4394 /* NOTE: must reload 'r' because r might be equal to r2 */
4395 r = p->r & VT_VALMASK;
4396 /* store register in the stack */
4397 type = &p->type;
4398 if ((p->r & VT_LVAL) ||
4399 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4400 type = &int_type;
4401 size = type_size(type, &align);
4402 loc = (loc - size) & -align;
4403 sv.type.t = type->t;
4404 sv.r = VT_LOCAL | VT_LVAL;
4405 sv.c.ul = loc;
4406 store(r, &sv);
4407 #ifdef TCC_TARGET_I386
4408 /* x86 specific: need to pop fp register ST0 if saved */
4409 if (r == TREG_ST0) {
4410 o(0xd9dd); /* fstp %st(1) */
4412 #endif
4413 /* special long long case */
4414 if ((type->t & VT_BTYPE) == VT_LLONG) {
4415 sv.c.ul += 4;
4416 store(p->r2, &sv);
4418 l = loc;
4419 saved = 1;
4421 /* mark that stack entry as being saved on the stack */
4422 if (p->r & VT_LVAL) {
4423 /* also clear the bounded flag because the
4424 relocation address of the function was stored in
4425 p->c.ul */
4426 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4427 } else {
4428 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4430 p->r2 = VT_CONST;
4431 p->c.ul = l;
4436 /* find a register of class 'rc2' with at most one reference on stack.
4437 * If none, call get_reg(rc) */
4438 int get_reg_ex(int rc, int rc2)
4440 int r;
4441 SValue *p;
4443 for(r=0;r<NB_REGS;r++) {
4444 if (reg_classes[r] & rc2) {
4445 int n;
4446 n=0;
4447 for(p = vstack; p <= vtop; p++) {
4448 if ((p->r & VT_VALMASK) == r ||
4449 (p->r2 & VT_VALMASK) == r)
4450 n++;
4452 if (n <= 1)
4453 return r;
4456 return get_reg(rc);
4459 /* find a free register of class 'rc'. If none, save one register */
4460 int get_reg(int rc)
4462 int r;
4463 SValue *p;
4465 /* find a free register */
4466 for(r=0;r<NB_REGS;r++) {
4467 if (reg_classes[r] & rc) {
4468 for(p=vstack;p<=vtop;p++) {
4469 if ((p->r & VT_VALMASK) == r ||
4470 (p->r2 & VT_VALMASK) == r)
4471 goto notfound;
4473 return r;
4475 notfound: ;
4478 /* no register left : free the first one on the stack (VERY
4479 IMPORTANT to start from the bottom to ensure that we don't
4480 spill registers used in gen_opi()) */
4481 for(p=vstack;p<=vtop;p++) {
4482 r = p->r & VT_VALMASK;
4483 if (r < VT_CONST && (reg_classes[r] & rc))
4484 goto save_found;
4485 /* also look at second register (if long long) */
4486 r = p->r2 & VT_VALMASK;
4487 if (r < VT_CONST && (reg_classes[r] & rc)) {
4488 save_found:
4489 save_reg(r);
4490 return r;
4493 /* Should never comes here */
4494 return -1;
4497 /* save registers up to (vtop - n) stack entry */
4498 void save_regs(int n)
4500 int r;
4501 SValue *p, *p1;
4502 p1 = vtop - n;
4503 for(p = vstack;p <= p1; p++) {
4504 r = p->r & VT_VALMASK;
4505 if (r < VT_CONST) {
4506 save_reg(r);
4511 /* move register 's' to 'r', and flush previous value of r to memory
4512 if needed */
4513 void move_reg(int r, int s)
4515 SValue sv;
4517 if (r != s) {
4518 save_reg(r);
4519 sv.type.t = VT_INT;
4520 sv.r = s;
4521 sv.c.ul = 0;
4522 load(r, &sv);
4526 /* get address of vtop (vtop MUST BE an lvalue) */
4527 void gaddrof(void)
4529 vtop->r &= ~VT_LVAL;
4530 /* tricky: if saved lvalue, then we can go back to lvalue */
4531 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4532 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4535 #ifdef CONFIG_TCC_BCHECK
4536 /* generate lvalue bound code */
4537 void gbound(void)
4539 int lval_type;
4540 CType type1;
4542 vtop->r &= ~VT_MUSTBOUND;
4543 /* if lvalue, then use checking code before dereferencing */
4544 if (vtop->r & VT_LVAL) {
4545 /* if not VT_BOUNDED value, then make one */
4546 if (!(vtop->r & VT_BOUNDED)) {
4547 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4548 /* must save type because we must set it to int to get pointer */
4549 type1 = vtop->type;
4550 vtop->type.t = VT_INT;
4551 gaddrof();
4552 vpushi(0);
4553 gen_bounded_ptr_add();
4554 vtop->r |= lval_type;
4555 vtop->type = type1;
4557 /* then check for dereferencing */
4558 gen_bounded_ptr_deref();
4561 #endif
4563 /* store vtop a register belonging to class 'rc'. lvalues are
4564 converted to values. Cannot be used if cannot be converted to
4565 register value (such as structures). */
4566 int gv(int rc)
4568 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4569 unsigned long long ll;
4571 /* NOTE: get_reg can modify vstack[] */
4572 if (vtop->type.t & VT_BITFIELD) {
4573 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4574 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4575 /* remove bit field info to avoid loops */
4576 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4577 /* generate shifts */
4578 vpushi(32 - (bit_pos + bit_size));
4579 gen_op(TOK_SHL);
4580 vpushi(32 - bit_size);
4581 /* NOTE: transformed to SHR if unsigned */
4582 gen_op(TOK_SAR);
4583 r = gv(rc);
4584 } else {
4585 if (is_float(vtop->type.t) &&
4586 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4587 Sym *sym;
4588 int *ptr;
4589 unsigned long offset;
4591 /* XXX: unify with initializers handling ? */
4592 /* CPUs usually cannot use float constants, so we store them
4593 generically in data segment */
4594 size = type_size(&vtop->type, &align);
4595 offset = (data_section->data_offset + align - 1) & -align;
4596 data_section->data_offset = offset;
4597 /* XXX: not portable yet */
4598 ptr = section_ptr_add(data_section, size);
4599 size = size >> 2;
4600 for(i=0;i<size;i++)
4601 ptr[i] = vtop->c.tab[i];
4602 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4603 vtop->r |= VT_LVAL | VT_SYM;
4604 vtop->sym = sym;
4605 vtop->c.ul = 0;
4607 #ifdef CONFIG_TCC_BCHECK
4608 if (vtop->r & VT_MUSTBOUND)
4609 gbound();
4610 #endif
4612 r = vtop->r & VT_VALMASK;
4613 /* need to reload if:
4614 - constant
4615 - lvalue (need to dereference pointer)
4616 - already a register, but not in the right class */
4617 if (r >= VT_CONST ||
4618 (vtop->r & VT_LVAL) ||
4619 !(reg_classes[r] & rc) ||
4620 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4621 !(reg_classes[vtop->r2] & rc))) {
4622 r = get_reg(rc);
4623 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4624 /* two register type load : expand to two words
4625 temporarily */
4626 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4627 /* load constant */
4628 ll = vtop->c.ull;
4629 vtop->c.ui = ll; /* first word */
4630 load(r, vtop);
4631 vtop->r = r; /* save register value */
4632 vpushi(ll >> 32); /* second word */
4633 } else if (r >= VT_CONST ||
4634 (vtop->r & VT_LVAL)) {
4635 /* load from memory */
4636 load(r, vtop);
4637 vdup();
4638 vtop[-1].r = r; /* save register value */
4639 /* increment pointer to get second word */
4640 vtop->type.t = VT_INT;
4641 gaddrof();
4642 vpushi(4);
4643 gen_op('+');
4644 vtop->r |= VT_LVAL;
4645 } else {
4646 /* move registers */
4647 load(r, vtop);
4648 vdup();
4649 vtop[-1].r = r; /* save register value */
4650 vtop->r = vtop[-1].r2;
4652 /* allocate second register */
4653 rc2 = RC_INT;
4654 if (rc == RC_IRET)
4655 rc2 = RC_LRET;
4656 r2 = get_reg(rc2);
4657 load(r2, vtop);
4658 vpop();
4659 /* write second register */
4660 vtop->r2 = r2;
4661 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4662 int t1, t;
4663 /* lvalue of scalar type : need to use lvalue type
4664 because of possible cast */
4665 t = vtop->type.t;
4666 t1 = t;
4667 /* compute memory access type */
4668 if (vtop->r & VT_LVAL_BYTE)
4669 t = VT_BYTE;
4670 else if (vtop->r & VT_LVAL_SHORT)
4671 t = VT_SHORT;
4672 if (vtop->r & VT_LVAL_UNSIGNED)
4673 t |= VT_UNSIGNED;
4674 vtop->type.t = t;
4675 load(r, vtop);
4676 /* restore wanted type */
4677 vtop->type.t = t1;
4678 } else {
4679 /* one register type load */
4680 load(r, vtop);
4683 vtop->r = r;
4684 #ifdef TCC_TARGET_C67
4685 /* uses register pairs for doubles */
4686 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4687 vtop->r2 = r+1;
4688 #endif
4690 return r;
4693 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4694 void gv2(int rc1, int rc2)
4696 int v;
4698 /* generate more generic register first. But VT_JMP or VT_CMP
4699 values must be generated first in all cases to avoid possible
4700 reload errors */
4701 v = vtop[0].r & VT_VALMASK;
4702 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4703 vswap();
4704 gv(rc1);
4705 vswap();
4706 gv(rc2);
4707 /* test if reload is needed for first register */
4708 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4709 vswap();
4710 gv(rc1);
4711 vswap();
4713 } else {
4714 gv(rc2);
4715 vswap();
4716 gv(rc1);
4717 vswap();
4718 /* test if reload is needed for first register */
4719 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4720 gv(rc2);
4725 /* expand long long on stack in two int registers */
4726 void lexpand(void)
4728 int u;
4730 u = vtop->type.t & VT_UNSIGNED;
4731 gv(RC_INT);
4732 vdup();
4733 vtop[0].r = vtop[-1].r2;
4734 vtop[0].r2 = VT_CONST;
4735 vtop[-1].r2 = VT_CONST;
4736 vtop[0].type.t = VT_INT | u;
4737 vtop[-1].type.t = VT_INT | u;
4740 #ifdef TCC_TARGET_ARM
4741 /* expand long long on stack */
4742 void lexpand_nr(void)
4744 int u,v;
4746 u = vtop->type.t & VT_UNSIGNED;
4747 vdup();
4748 vtop->r2 = VT_CONST;
4749 vtop->type.t = VT_INT | u;
4750 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4751 if (v == VT_CONST) {
4752 vtop[-1].c.ui = vtop->c.ull;
4753 vtop->c.ui = vtop->c.ull >> 32;
4754 vtop->r = VT_CONST;
4755 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4756 vtop->c.ui += 4;
4757 vtop->r = vtop[-1].r;
4758 } else if (v > VT_CONST) {
4759 vtop--;
4760 lexpand();
4761 } else
4762 vtop->r = vtop[-1].r2;
4763 vtop[-1].r2 = VT_CONST;
4764 vtop[-1].type.t = VT_INT | u;
4766 #endif
4768 /* build a long long from two ints */
4769 void lbuild(int t)
4771 gv2(RC_INT, RC_INT);
4772 vtop[-1].r2 = vtop[0].r;
4773 vtop[-1].type.t = t;
4774 vpop();
4777 /* rotate n first stack elements to the bottom
4778 I1 ... In -> I2 ... In I1 [top is right]
4780 void vrotb(int n)
4782 int i;
4783 SValue tmp;
4785 tmp = vtop[-n + 1];
4786 for(i=-n+1;i!=0;i++)
4787 vtop[i] = vtop[i+1];
4788 vtop[0] = tmp;
4791 /* rotate n first stack elements to the top
4792 I1 ... In -> In I1 ... I(n-1) [top is right]
4794 void vrott(int n)
4796 int i;
4797 SValue tmp;
4799 tmp = vtop[0];
4800 for(i = 0;i < n - 1; i++)
4801 vtop[-i] = vtop[-i - 1];
4802 vtop[-n + 1] = tmp;
4805 #ifdef TCC_TARGET_ARM
4806 /* like vrott but in other direction
4807 In ... I1 -> I(n-1) ... I1 In [top is right]
4809 void vnrott(int n)
4811 int i;
4812 SValue tmp;
4814 tmp = vtop[-n + 1];
4815 for(i = n - 1; i > 0; i--)
4816 vtop[-i] = vtop[-i + 1];
4817 vtop[0] = tmp;
4819 #endif
4821 /* pop stack value */
4822 void vpop(void)
4824 int v;
4825 v = vtop->r & VT_VALMASK;
4826 #ifdef TCC_TARGET_I386
4827 /* for x86, we need to pop the FP stack */
4828 if (v == TREG_ST0 && !nocode_wanted) {
4829 o(0xd9dd); /* fstp %st(1) */
4830 } else
4831 #endif
4832 if (v == VT_JMP || v == VT_JMPI) {
4833 /* need to put correct jump if && or || without test */
4834 gsym(vtop->c.ul);
4836 vtop--;
4839 /* convert stack entry to register and duplicate its value in another
4840 register */
4841 void gv_dup(void)
4843 int rc, t, r, r1;
4844 SValue sv;
4846 t = vtop->type.t;
4847 if ((t & VT_BTYPE) == VT_LLONG) {
4848 lexpand();
4849 gv_dup();
4850 vswap();
4851 vrotb(3);
4852 gv_dup();
4853 vrotb(4);
4854 /* stack: H L L1 H1 */
4855 lbuild(t);
4856 vrotb(3);
4857 vrotb(3);
4858 vswap();
4859 lbuild(t);
4860 vswap();
4861 } else {
4862 /* duplicate value */
4863 rc = RC_INT;
4864 sv.type.t = VT_INT;
4865 if (is_float(t)) {
4866 rc = RC_FLOAT;
4867 sv.type.t = t;
4869 r = gv(rc);
4870 r1 = get_reg(rc);
4871 sv.r = r;
4872 sv.c.ul = 0;
4873 load(r1, &sv); /* move r to r1 */
4874 vdup();
4875 /* duplicates value */
4876 vtop->r = r1;
4880 /* generate CPU independent (unsigned) long long operations */
4881 void gen_opl(int op)
4883 int t, a, b, op1, c, i;
4884 int func;
4885 SValue tmp;
4887 switch(op) {
4888 case '/':
4889 case TOK_PDIV:
4890 func = TOK___divdi3;
4891 goto gen_func;
4892 case TOK_UDIV:
4893 func = TOK___udivdi3;
4894 goto gen_func;
4895 case '%':
4896 func = TOK___moddi3;
4897 goto gen_func;
4898 case TOK_UMOD:
4899 func = TOK___umoddi3;
4900 gen_func:
4901 /* call generic long long function */
4902 vpush_global_sym(&func_old_type, func);
4903 vrott(3);
4904 gfunc_call(2);
4905 vpushi(0);
4906 vtop->r = REG_IRET;
4907 vtop->r2 = REG_LRET;
4908 break;
4909 case '^':
4910 case '&':
4911 case '|':
4912 case '*':
4913 case '+':
4914 case '-':
4915 t = vtop->type.t;
4916 vswap();
4917 lexpand();
4918 vrotb(3);
4919 lexpand();
4920 /* stack: L1 H1 L2 H2 */
4921 tmp = vtop[0];
4922 vtop[0] = vtop[-3];
4923 vtop[-3] = tmp;
4924 tmp = vtop[-2];
4925 vtop[-2] = vtop[-3];
4926 vtop[-3] = tmp;
4927 vswap();
4928 /* stack: H1 H2 L1 L2 */
4929 if (op == '*') {
4930 vpushv(vtop - 1);
4931 vpushv(vtop - 1);
4932 gen_op(TOK_UMULL);
4933 lexpand();
4934 /* stack: H1 H2 L1 L2 ML MH */
4935 for(i=0;i<4;i++)
4936 vrotb(6);
4937 /* stack: ML MH H1 H2 L1 L2 */
4938 tmp = vtop[0];
4939 vtop[0] = vtop[-2];
4940 vtop[-2] = tmp;
4941 /* stack: ML MH H1 L2 H2 L1 */
4942 gen_op('*');
4943 vrotb(3);
4944 vrotb(3);
4945 gen_op('*');
4946 /* stack: ML MH M1 M2 */
4947 gen_op('+');
4948 gen_op('+');
4949 } else if (op == '+' || op == '-') {
4950 /* XXX: add non carry method too (for MIPS or alpha) */
4951 if (op == '+')
4952 op1 = TOK_ADDC1;
4953 else
4954 op1 = TOK_SUBC1;
4955 gen_op(op1);
4956 /* stack: H1 H2 (L1 op L2) */
4957 vrotb(3);
4958 vrotb(3);
4959 gen_op(op1 + 1); /* TOK_xxxC2 */
4960 } else {
4961 gen_op(op);
4962 /* stack: H1 H2 (L1 op L2) */
4963 vrotb(3);
4964 vrotb(3);
4965 /* stack: (L1 op L2) H1 H2 */
4966 gen_op(op);
4967 /* stack: (L1 op L2) (H1 op H2) */
4969 /* stack: L H */
4970 lbuild(t);
4971 break;
4972 case TOK_SAR:
4973 case TOK_SHR:
4974 case TOK_SHL:
4975 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4976 t = vtop[-1].type.t;
4977 vswap();
4978 lexpand();
4979 vrotb(3);
4980 /* stack: L H shift */
4981 c = (int)vtop->c.i;
4982 /* constant: simpler */
4983 /* NOTE: all comments are for SHL. the other cases are
4984 done by swaping words */
4985 vpop();
4986 if (op != TOK_SHL)
4987 vswap();
4988 if (c >= 32) {
4989 /* stack: L H */
4990 vpop();
4991 if (c > 32) {
4992 vpushi(c - 32);
4993 gen_op(op);
4995 if (op != TOK_SAR) {
4996 vpushi(0);
4997 } else {
4998 gv_dup();
4999 vpushi(31);
5000 gen_op(TOK_SAR);
5002 vswap();
5003 } else {
5004 vswap();
5005 gv_dup();
5006 /* stack: H L L */
5007 vpushi(c);
5008 gen_op(op);
5009 vswap();
5010 vpushi(32 - c);
5011 if (op == TOK_SHL)
5012 gen_op(TOK_SHR);
5013 else
5014 gen_op(TOK_SHL);
5015 vrotb(3);
5016 /* stack: L L H */
5017 vpushi(c);
5018 if (op == TOK_SHL)
5019 gen_op(TOK_SHL);
5020 else
5021 gen_op(TOK_SHR);
5022 gen_op('|');
5024 if (op != TOK_SHL)
5025 vswap();
5026 lbuild(t);
5027 } else {
5028 /* XXX: should provide a faster fallback on x86 ? */
5029 switch(op) {
5030 case TOK_SAR:
5031 func = TOK___sardi3;
5032 goto gen_func;
5033 case TOK_SHR:
5034 func = TOK___shrdi3;
5035 goto gen_func;
5036 case TOK_SHL:
5037 func = TOK___shldi3;
5038 goto gen_func;
5041 break;
5042 default:
5043 /* compare operations */
5044 t = vtop->type.t;
5045 vswap();
5046 lexpand();
5047 vrotb(3);
5048 lexpand();
5049 /* stack: L1 H1 L2 H2 */
5050 tmp = vtop[-1];
5051 vtop[-1] = vtop[-2];
5052 vtop[-2] = tmp;
5053 /* stack: L1 L2 H1 H2 */
5054 /* compare high */
5055 op1 = op;
5056 /* when values are equal, we need to compare low words. since
5057 the jump is inverted, we invert the test too. */
5058 if (op1 == TOK_LT)
5059 op1 = TOK_LE;
5060 else if (op1 == TOK_GT)
5061 op1 = TOK_GE;
5062 else if (op1 == TOK_ULT)
5063 op1 = TOK_ULE;
5064 else if (op1 == TOK_UGT)
5065 op1 = TOK_UGE;
5066 a = 0;
5067 b = 0;
5068 gen_op(op1);
5069 if (op1 != TOK_NE) {
5070 a = gtst(1, 0);
5072 if (op != TOK_EQ) {
5073 /* generate non equal test */
5074 /* XXX: NOT PORTABLE yet */
5075 if (a == 0) {
5076 b = gtst(0, 0);
5077 } else {
5078 #if defined(TCC_TARGET_I386)
5079 b = psym(0x850f, 0);
5080 #elif defined(TCC_TARGET_ARM)
5081 b = ind;
5082 o(0x1A000000 | encbranch(ind, 0, 1));
5083 #elif defined(TCC_TARGET_C67)
5084 error("not implemented");
5085 #else
5086 #error not supported
5087 #endif
5090 /* compare low. Always unsigned */
5091 op1 = op;
5092 if (op1 == TOK_LT)
5093 op1 = TOK_ULT;
5094 else if (op1 == TOK_LE)
5095 op1 = TOK_ULE;
5096 else if (op1 == TOK_GT)
5097 op1 = TOK_UGT;
5098 else if (op1 == TOK_GE)
5099 op1 = TOK_UGE;
5100 gen_op(op1);
5101 a = gtst(1, a);
5102 gsym(b);
5103 vseti(VT_JMPI, a);
5104 break;
5108 /* handle integer constant optimizations and various machine
5109 independent opt */
5110 void gen_opic(int op)
5112 int fc, c1, c2, n;
5113 SValue *v1, *v2;
5115 v1 = vtop - 1;
5116 v2 = vtop;
5117 /* currently, we cannot do computations with forward symbols */
5118 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5119 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5120 if (c1 && c2) {
5121 fc = v2->c.i;
5122 switch(op) {
5123 case '+': v1->c.i += fc; break;
5124 case '-': v1->c.i -= fc; break;
5125 case '&': v1->c.i &= fc; break;
5126 case '^': v1->c.i ^= fc; break;
5127 case '|': v1->c.i |= fc; break;
5128 case '*': v1->c.i *= fc; break;
5130 case TOK_PDIV:
5131 case '/':
5132 case '%':
5133 case TOK_UDIV:
5134 case TOK_UMOD:
5135 /* if division by zero, generate explicit division */
5136 if (fc == 0) {
5137 if (const_wanted)
5138 error("division by zero in constant");
5139 goto general_case;
5141 switch(op) {
5142 default: v1->c.i /= fc; break;
5143 case '%': v1->c.i %= fc; break;
5144 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5145 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5147 break;
5148 case TOK_SHL: v1->c.i <<= fc; break;
5149 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5150 case TOK_SAR: v1->c.i >>= fc; break;
5151 /* tests */
5152 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5153 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5154 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5155 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5156 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5157 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5158 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5159 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5160 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5161 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5162 /* logical */
5163 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5164 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5165 default:
5166 goto general_case;
5168 vtop--;
5169 } else {
5170 /* if commutative ops, put c2 as constant */
5171 if (c1 && (op == '+' || op == '&' || op == '^' ||
5172 op == '|' || op == '*')) {
5173 vswap();
5174 swap(&c1, &c2);
5176 fc = vtop->c.i;
5177 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5178 op == TOK_PDIV) &&
5179 fc == 1) ||
5180 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5181 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5182 fc == 0) ||
5183 (op == '&' &&
5184 fc == -1))) {
5185 /* nothing to do */
5186 vtop--;
5187 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5188 /* try to use shifts instead of muls or divs */
5189 if (fc > 0 && (fc & (fc - 1)) == 0) {
5190 n = -1;
5191 while (fc) {
5192 fc >>= 1;
5193 n++;
5195 vtop->c.i = n;
5196 if (op == '*')
5197 op = TOK_SHL;
5198 else if (op == TOK_PDIV)
5199 op = TOK_SAR;
5200 else
5201 op = TOK_SHR;
5203 goto general_case;
5204 } else if (c2 && (op == '+' || op == '-') &&
5205 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5206 (VT_CONST | VT_SYM)) {
5207 /* symbol + constant case */
5208 if (op == '-')
5209 fc = -fc;
5210 vtop--;
5211 vtop->c.i += fc;
5212 } else {
5213 general_case:
5214 if (!nocode_wanted) {
5215 /* call low level op generator */
5216 gen_opi(op);
5217 } else {
5218 vtop--;
5224 /* generate a floating point operation with constant propagation */
5225 void gen_opif(int op)
5227 int c1, c2;
5228 SValue *v1, *v2;
5229 long double f1, f2;
5231 v1 = vtop - 1;
5232 v2 = vtop;
5233 /* currently, we cannot do computations with forward symbols */
5234 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5235 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5236 if (c1 && c2) {
5237 if (v1->type.t == VT_FLOAT) {
5238 f1 = v1->c.f;
5239 f2 = v2->c.f;
5240 } else if (v1->type.t == VT_DOUBLE) {
5241 f1 = v1->c.d;
5242 f2 = v2->c.d;
5243 } else {
5244 f1 = v1->c.ld;
5245 f2 = v2->c.ld;
5248 /* NOTE: we only do constant propagation if finite number (not
5249 NaN or infinity) (ANSI spec) */
5250 if (!ieee_finite(f1) || !ieee_finite(f2))
5251 goto general_case;
5253 switch(op) {
5254 case '+': f1 += f2; break;
5255 case '-': f1 -= f2; break;
5256 case '*': f1 *= f2; break;
5257 case '/':
5258 if (f2 == 0.0) {
5259 if (const_wanted)
5260 error("division by zero in constant");
5261 goto general_case;
5263 f1 /= f2;
5264 break;
5265 /* XXX: also handles tests ? */
5266 default:
5267 goto general_case;
5269 /* XXX: overflow test ? */
5270 if (v1->type.t == VT_FLOAT) {
5271 v1->c.f = f1;
5272 } else if (v1->type.t == VT_DOUBLE) {
5273 v1->c.d = f1;
5274 } else {
5275 v1->c.ld = f1;
5277 vtop--;
5278 } else {
5279 general_case:
5280 if (!nocode_wanted) {
5281 gen_opf(op);
5282 } else {
5283 vtop--;
5288 static int pointed_size(CType *type)
5290 int align;
5291 return type_size(pointed_type(type), &align);
5294 static inline int is_null_pointer(SValue *p)
5296 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5297 return 0;
5298 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5299 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5302 static inline int is_integer_btype(int bt)
5304 return (bt == VT_BYTE || bt == VT_SHORT ||
5305 bt == VT_INT || bt == VT_LLONG);
5308 /* check types for comparison or substraction of pointers */
5309 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5311 CType *type1, *type2, tmp_type1, tmp_type2;
5312 int bt1, bt2;
5314 /* null pointers are accepted for all comparisons as gcc */
5315 if (is_null_pointer(p1) || is_null_pointer(p2))
5316 return;
5317 type1 = &p1->type;
5318 type2 = &p2->type;
5319 bt1 = type1->t & VT_BTYPE;
5320 bt2 = type2->t & VT_BTYPE;
5321 /* accept comparison between pointer and integer with a warning */
5322 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5323 warning("comparison between pointer and integer");
5324 return;
5327 /* both must be pointers or implicit function pointers */
5328 if (bt1 == VT_PTR) {
5329 type1 = pointed_type(type1);
5330 } else if (bt1 != VT_FUNC)
5331 goto invalid_operands;
5333 if (bt2 == VT_PTR) {
5334 type2 = pointed_type(type2);
5335 } else if (bt2 != VT_FUNC) {
5336 invalid_operands:
5337 error("invalid operands to binary %s", get_tok_str(op, NULL));
5339 if ((type1->t & VT_BTYPE) == VT_VOID ||
5340 (type2->t & VT_BTYPE) == VT_VOID)
5341 return;
5342 tmp_type1 = *type1;
5343 tmp_type2 = *type2;
5344 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5345 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5346 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5347 /* gcc-like error if '-' is used */
5348 if (op == '-')
5349 goto invalid_operands;
5350 else
5351 warning("comparison of distinct pointer types lacks a cast");
5355 /* generic gen_op: handles types problems */
5356 void gen_op(int op)
5358 int u, t1, t2, bt1, bt2, t;
5359 CType type1;
5361 t1 = vtop[-1].type.t;
5362 t2 = vtop[0].type.t;
5363 bt1 = t1 & VT_BTYPE;
5364 bt2 = t2 & VT_BTYPE;
5366 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5367 /* at least one operand is a pointer */
5368 /* relationnal op: must be both pointers */
5369 if (op >= TOK_ULT && op <= TOK_GT) {
5370 check_comparison_pointer_types(vtop - 1, vtop, op);
5371 /* pointers are handled are unsigned */
5372 t = VT_INT | VT_UNSIGNED;
5373 goto std_op;
5375 /* if both pointers, then it must be the '-' op */
5376 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5377 if (op != '-')
5378 error("cannot use pointers here");
5379 check_comparison_pointer_types(vtop - 1, vtop, op);
5380 /* XXX: check that types are compatible */
5381 u = pointed_size(&vtop[-1].type);
5382 gen_opic(op);
5383 /* set to integer type */
5384 vtop->type.t = VT_INT;
5385 vpushi(u);
5386 gen_op(TOK_PDIV);
5387 } else {
5388 /* exactly one pointer : must be '+' or '-'. */
5389 if (op != '-' && op != '+')
5390 error("cannot use pointers here");
5391 /* Put pointer as first operand */
5392 if (bt2 == VT_PTR) {
5393 vswap();
5394 swap(&t1, &t2);
5396 type1 = vtop[-1].type;
5397 /* XXX: cast to int ? (long long case) */
5398 vpushi(pointed_size(&vtop[-1].type));
5399 gen_op('*');
5400 #ifdef CONFIG_TCC_BCHECK
5401 /* if evaluating constant expression, no code should be
5402 generated, so no bound check */
5403 if (do_bounds_check && !const_wanted) {
5404 /* if bounded pointers, we generate a special code to
5405 test bounds */
5406 if (op == '-') {
5407 vpushi(0);
5408 vswap();
5409 gen_op('-');
5411 gen_bounded_ptr_add();
5412 } else
5413 #endif
5415 gen_opic(op);
5417 /* put again type if gen_opic() swaped operands */
5418 vtop->type = type1;
5420 } else if (is_float(bt1) || is_float(bt2)) {
5421 /* compute bigger type and do implicit casts */
5422 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5423 t = VT_LDOUBLE;
5424 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5425 t = VT_DOUBLE;
5426 } else {
5427 t = VT_FLOAT;
5429 /* floats can only be used for a few operations */
5430 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5431 (op < TOK_ULT || op > TOK_GT))
5432 error("invalid operands for binary operation");
5433 goto std_op;
5434 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5435 /* cast to biggest op */
5436 t = VT_LLONG;
5437 /* convert to unsigned if it does not fit in a long long */
5438 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5439 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5440 t |= VT_UNSIGNED;
5441 goto std_op;
5442 } else {
5443 /* integer operations */
5444 t = VT_INT;
5445 /* convert to unsigned if it does not fit in an integer */
5446 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5447 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5448 t |= VT_UNSIGNED;
5449 std_op:
5450 /* XXX: currently, some unsigned operations are explicit, so
5451 we modify them here */
5452 if (t & VT_UNSIGNED) {
5453 if (op == TOK_SAR)
5454 op = TOK_SHR;
5455 else if (op == '/')
5456 op = TOK_UDIV;
5457 else if (op == '%')
5458 op = TOK_UMOD;
5459 else if (op == TOK_LT)
5460 op = TOK_ULT;
5461 else if (op == TOK_GT)
5462 op = TOK_UGT;
5463 else if (op == TOK_LE)
5464 op = TOK_ULE;
5465 else if (op == TOK_GE)
5466 op = TOK_UGE;
5468 vswap();
5469 type1.t = t;
5470 gen_cast(&type1);
5471 vswap();
5472 /* special case for shifts and long long: we keep the shift as
5473 an integer */
5474 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5475 type1.t = VT_INT;
5476 gen_cast(&type1);
5477 if (is_float(t))
5478 gen_opif(op);
5479 else if ((t & VT_BTYPE) == VT_LLONG)
5480 gen_opl(op);
5481 else
5482 gen_opic(op);
5483 if (op >= TOK_ULT && op <= TOK_GT) {
5484 /* relationnal op: the result is an int */
5485 vtop->type.t = VT_INT;
5486 } else {
5487 vtop->type.t = t;
5492 /* generic itof for unsigned long long case */
5493 void gen_cvt_itof1(int t)
5495 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5496 (VT_LLONG | VT_UNSIGNED)) {
5498 if (t == VT_FLOAT)
5499 vpush_global_sym(&func_old_type, TOK___ulltof);
5500 else if (t == VT_DOUBLE)
5501 vpush_global_sym(&func_old_type, TOK___ulltod);
5502 else
5503 vpush_global_sym(&func_old_type, TOK___ulltold);
5504 vrott(2);
5505 gfunc_call(1);
5506 vpushi(0);
5507 vtop->r = REG_FRET;
5508 } else {
5509 gen_cvt_itof(t);
5513 /* generic ftoi for unsigned long long case */
5514 void gen_cvt_ftoi1(int t)
5516 int st;
5518 if (t == (VT_LLONG | VT_UNSIGNED)) {
5519 /* not handled natively */
5520 st = vtop->type.t & VT_BTYPE;
5521 if (st == VT_FLOAT)
5522 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5523 else if (st == VT_DOUBLE)
5524 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5525 else
5526 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5527 vrott(2);
5528 gfunc_call(1);
5529 vpushi(0);
5530 vtop->r = REG_IRET;
5531 vtop->r2 = REG_LRET;
5532 } else {
5533 gen_cvt_ftoi(t);
5537 /* force char or short cast */
5538 void force_charshort_cast(int t)
5540 int bits, dbt;
5541 dbt = t & VT_BTYPE;
5542 /* XXX: add optimization if lvalue : just change type and offset */
5543 if (dbt == VT_BYTE)
5544 bits = 8;
5545 else
5546 bits = 16;
5547 if (t & VT_UNSIGNED) {
5548 vpushi((1 << bits) - 1);
5549 gen_op('&');
5550 } else {
5551 bits = 32 - bits;
5552 vpushi(bits);
5553 gen_op(TOK_SHL);
5554 vpushi(bits);
5555 gen_op(TOK_SAR);
5559 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5560 static void gen_cast(CType *type)
5562 int sbt, dbt, sf, df, c;
5564 /* special delayed cast for char/short */
5565 /* XXX: in some cases (multiple cascaded casts), it may still
5566 be incorrect */
5567 if (vtop->r & VT_MUSTCAST) {
5568 vtop->r &= ~VT_MUSTCAST;
5569 force_charshort_cast(vtop->type.t);
5572 /* bitfields first get cast to ints */
5573 if (vtop->type.t & VT_BITFIELD) {
5574 gv(RC_INT);
5577 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5578 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5580 if (sbt != dbt && !nocode_wanted) {
5581 sf = is_float(sbt);
5582 df = is_float(dbt);
5583 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5584 if (sf && df) {
5585 /* convert from fp to fp */
5586 if (c) {
5587 /* constant case: we can do it now */
5588 /* XXX: in ISOC, cannot do it if error in convert */
5589 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5590 vtop->c.f = (float)vtop->c.d;
5591 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5592 vtop->c.f = (float)vtop->c.ld;
5593 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5594 vtop->c.d = (double)vtop->c.f;
5595 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5596 vtop->c.d = (double)vtop->c.ld;
5597 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5598 vtop->c.ld = (long double)vtop->c.f;
5599 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5600 vtop->c.ld = (long double)vtop->c.d;
5601 } else {
5602 /* non constant case: generate code */
5603 gen_cvt_ftof(dbt);
5605 } else if (df) {
5606 /* convert int to fp */
5607 if (c) {
5608 switch(sbt) {
5609 case VT_LLONG | VT_UNSIGNED:
5610 case VT_LLONG:
5611 /* XXX: add const cases for long long */
5612 goto do_itof;
5613 case VT_INT | VT_UNSIGNED:
5614 switch(dbt) {
5615 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5616 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5617 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5619 break;
5620 default:
5621 switch(dbt) {
5622 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5623 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5624 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5626 break;
5628 } else {
5629 do_itof:
5630 #if !defined(TCC_TARGET_ARM)
5631 gen_cvt_itof1(dbt);
5632 #else
5633 gen_cvt_itof(dbt);
5634 #endif
5636 } else if (sf) {
5637 /* convert fp to int */
5638 /* we handle char/short/etc... with generic code */
5639 if (dbt != (VT_INT | VT_UNSIGNED) &&
5640 dbt != (VT_LLONG | VT_UNSIGNED) &&
5641 dbt != VT_LLONG)
5642 dbt = VT_INT;
5643 if (c) {
5644 switch(dbt) {
5645 case VT_LLONG | VT_UNSIGNED:
5646 case VT_LLONG:
5647 /* XXX: add const cases for long long */
5648 goto do_ftoi;
5649 case VT_INT | VT_UNSIGNED:
5650 switch(sbt) {
5651 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5652 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5653 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5655 break;
5656 default:
5657 /* int case */
5658 switch(sbt) {
5659 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5660 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5661 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5663 break;
5665 } else {
5666 do_ftoi:
5667 gen_cvt_ftoi1(dbt);
5669 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5670 /* additional cast for char/short/bool... */
5671 vtop->type.t = dbt;
5672 gen_cast(type);
5674 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5675 if ((sbt & VT_BTYPE) != VT_LLONG) {
5676 /* scalar to long long */
5677 if (c) {
5678 if (sbt == (VT_INT | VT_UNSIGNED))
5679 vtop->c.ll = vtop->c.ui;
5680 else
5681 vtop->c.ll = vtop->c.i;
5682 } else {
5683 /* machine independent conversion */
5684 gv(RC_INT);
5685 /* generate high word */
5686 if (sbt == (VT_INT | VT_UNSIGNED)) {
5687 vpushi(0);
5688 gv(RC_INT);
5689 } else {
5690 gv_dup();
5691 vpushi(31);
5692 gen_op(TOK_SAR);
5694 /* patch second register */
5695 vtop[-1].r2 = vtop->r;
5696 vpop();
5699 } else if (dbt == VT_BOOL) {
5700 /* scalar to bool */
5701 vpushi(0);
5702 gen_op(TOK_NE);
5703 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5704 (dbt & VT_BTYPE) == VT_SHORT) {
5705 force_charshort_cast(dbt);
5706 } else if ((dbt & VT_BTYPE) == VT_INT) {
5707 /* scalar to int */
5708 if (sbt == VT_LLONG) {
5709 /* from long long: just take low order word */
5710 lexpand();
5711 vpop();
5713 /* if lvalue and single word type, nothing to do because
5714 the lvalue already contains the real type size (see
5715 VT_LVAL_xxx constants) */
5718 vtop->type = *type;
5721 /* return type size. Put alignment at 'a' */
5722 static int type_size(CType *type, int *a)
5724 Sym *s;
5725 int bt;
5727 bt = type->t & VT_BTYPE;
5728 if (bt == VT_STRUCT) {
5729 /* struct/union */
5730 s = type->ref;
5731 *a = s->r;
5732 return s->c;
5733 } else if (bt == VT_PTR) {
5734 if (type->t & VT_ARRAY) {
5735 s = type->ref;
5736 return type_size(&s->type, a) * s->c;
5737 } else {
5738 *a = PTR_SIZE;
5739 return PTR_SIZE;
5741 } else if (bt == VT_LDOUBLE) {
5742 *a = LDOUBLE_ALIGN;
5743 return LDOUBLE_SIZE;
5744 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5745 #ifdef TCC_TARGET_I386
5746 *a = 4;
5747 #else
5748 *a = 8;
5749 #endif
5750 return 8;
5751 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5752 *a = 4;
5753 return 4;
5754 } else if (bt == VT_SHORT) {
5755 *a = 2;
5756 return 2;
5757 } else {
5758 /* char, void, function, _Bool */
5759 *a = 1;
5760 return 1;
5764 /* return the pointed type of t */
5765 static inline CType *pointed_type(CType *type)
5767 return &type->ref->type;
5770 /* modify type so that its it is a pointer to type. */
5771 static void mk_pointer(CType *type)
5773 Sym *s;
5774 s = sym_push(SYM_FIELD, type, 0, -1);
5775 type->t = VT_PTR | (type->t & ~VT_TYPE);
5776 type->ref = s;
5779 /* compare function types. OLD functions match any new functions */
5780 static int is_compatible_func(CType *type1, CType *type2)
5782 Sym *s1, *s2;
5784 s1 = type1->ref;
5785 s2 = type2->ref;
5786 if (!is_compatible_types(&s1->type, &s2->type))
5787 return 0;
5788 /* check func_call */
5789 if (s1->r != s2->r)
5790 return 0;
5791 /* XXX: not complete */
5792 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5793 return 1;
5794 if (s1->c != s2->c)
5795 return 0;
5796 while (s1 != NULL) {
5797 if (s2 == NULL)
5798 return 0;
5799 if (!is_compatible_types(&s1->type, &s2->type))
5800 return 0;
5801 s1 = s1->next;
5802 s2 = s2->next;
5804 if (s2)
5805 return 0;
5806 return 1;
5809 /* return true if type1 and type2 are exactly the same (including
5810 qualifiers).
5812 - enums are not checked as gcc __builtin_types_compatible_p ()
5814 static int is_compatible_types(CType *type1, CType *type2)
5816 int bt1, t1, t2;
5818 t1 = type1->t & VT_TYPE;
5819 t2 = type2->t & VT_TYPE;
5820 /* XXX: bitfields ? */
5821 if (t1 != t2)
5822 return 0;
5823 /* test more complicated cases */
5824 bt1 = t1 & VT_BTYPE;
5825 if (bt1 == VT_PTR) {
5826 type1 = pointed_type(type1);
5827 type2 = pointed_type(type2);
5828 return is_compatible_types(type1, type2);
5829 } else if (bt1 == VT_STRUCT) {
5830 return (type1->ref == type2->ref);
5831 } else if (bt1 == VT_FUNC) {
5832 return is_compatible_func(type1, type2);
5833 } else {
5834 return 1;
5838 /* print a type. If 'varstr' is not NULL, then the variable is also
5839 printed in the type */
5840 /* XXX: union */
5841 /* XXX: add array and function pointers */
5842 void type_to_str(char *buf, int buf_size,
5843 CType *type, const char *varstr)
5845 int bt, v, t;
5846 Sym *s, *sa;
5847 char buf1[256];
5848 const char *tstr;
5850 t = type->t & VT_TYPE;
5851 bt = t & VT_BTYPE;
5852 buf[0] = '\0';
5853 if (t & VT_CONSTANT)
5854 pstrcat(buf, buf_size, "const ");
5855 if (t & VT_VOLATILE)
5856 pstrcat(buf, buf_size, "volatile ");
5857 if (t & VT_UNSIGNED)
5858 pstrcat(buf, buf_size, "unsigned ");
5859 switch(bt) {
5860 case VT_VOID:
5861 tstr = "void";
5862 goto add_tstr;
5863 case VT_BOOL:
5864 tstr = "_Bool";
5865 goto add_tstr;
5866 case VT_BYTE:
5867 tstr = "char";
5868 goto add_tstr;
5869 case VT_SHORT:
5870 tstr = "short";
5871 goto add_tstr;
5872 case VT_INT:
5873 tstr = "int";
5874 goto add_tstr;
5875 case VT_LONG:
5876 tstr = "long";
5877 goto add_tstr;
5878 case VT_LLONG:
5879 tstr = "long long";
5880 goto add_tstr;
5881 case VT_FLOAT:
5882 tstr = "float";
5883 goto add_tstr;
5884 case VT_DOUBLE:
5885 tstr = "double";
5886 goto add_tstr;
5887 case VT_LDOUBLE:
5888 tstr = "long double";
5889 add_tstr:
5890 pstrcat(buf, buf_size, tstr);
5891 break;
5892 case VT_ENUM:
5893 case VT_STRUCT:
5894 if (bt == VT_STRUCT)
5895 tstr = "struct ";
5896 else
5897 tstr = "enum ";
5898 pstrcat(buf, buf_size, tstr);
5899 v = type->ref->v & ~SYM_STRUCT;
5900 if (v >= SYM_FIRST_ANOM)
5901 pstrcat(buf, buf_size, "<anonymous>");
5902 else
5903 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5904 break;
5905 case VT_FUNC:
5906 s = type->ref;
5907 type_to_str(buf, buf_size, &s->type, varstr);
5908 pstrcat(buf, buf_size, "(");
5909 sa = s->next;
5910 while (sa != NULL) {
5911 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5912 pstrcat(buf, buf_size, buf1);
5913 sa = sa->next;
5914 if (sa)
5915 pstrcat(buf, buf_size, ", ");
5917 pstrcat(buf, buf_size, ")");
5918 goto no_var;
5919 case VT_PTR:
5920 s = type->ref;
5921 pstrcpy(buf1, sizeof(buf1), "*");
5922 if (varstr)
5923 pstrcat(buf1, sizeof(buf1), varstr);
5924 type_to_str(buf, buf_size, &s->type, buf1);
5925 goto no_var;
5927 if (varstr) {
5928 pstrcat(buf, buf_size, " ");
5929 pstrcat(buf, buf_size, varstr);
5931 no_var: ;
5934 /* verify type compatibility to store vtop in 'dt' type, and generate
5935 casts if needed. */
5936 static void gen_assign_cast(CType *dt)
5938 CType *st, *type1, *type2, tmp_type1, tmp_type2;
5939 char buf1[256], buf2[256];
5940 int dbt, sbt;
5942 st = &vtop->type; /* source type */
5943 dbt = dt->t & VT_BTYPE;
5944 sbt = st->t & VT_BTYPE;
5945 if (dt->t & VT_CONSTANT)
5946 warning("assignment of read-only location");
5947 switch(dbt) {
5948 case VT_PTR:
5949 /* special cases for pointers */
5950 /* '0' can also be a pointer */
5951 if (is_null_pointer(vtop))
5952 goto type_ok;
5953 /* accept implicit pointer to integer cast with warning */
5954 if (is_integer_btype(sbt)) {
5955 warning("assignment makes pointer from integer without a cast");
5956 goto type_ok;
5958 type1 = pointed_type(dt);
5959 /* a function is implicitely a function pointer */
5960 if (sbt == VT_FUNC) {
5961 if ((type1->t & VT_BTYPE) != VT_VOID &&
5962 !is_compatible_types(pointed_type(dt), st))
5963 goto error;
5964 else
5965 goto type_ok;
5967 if (sbt != VT_PTR)
5968 goto error;
5969 type2 = pointed_type(st);
5970 if ((type1->t & VT_BTYPE) == VT_VOID ||
5971 (type2->t & VT_BTYPE) == VT_VOID) {
5972 /* void * can match anything */
5973 } else {
5974 /* exact type match, except for unsigned */
5975 tmp_type1 = *type1;
5976 tmp_type2 = *type2;
5977 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5978 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5979 if (!is_compatible_types(&tmp_type1, &tmp_type2))
5980 goto error;
5982 /* check const and volatile */
5983 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
5984 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
5985 warning("assignment discards qualifiers from pointer target type");
5986 break;
5987 case VT_BYTE:
5988 case VT_SHORT:
5989 case VT_INT:
5990 case VT_LLONG:
5991 if (sbt == VT_PTR || sbt == VT_FUNC) {
5992 warning("assignment makes integer from pointer without a cast");
5994 /* XXX: more tests */
5995 break;
5996 case VT_STRUCT:
5997 tmp_type1 = *dt;
5998 tmp_type2 = *st;
5999 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6000 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6001 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6002 error:
6003 type_to_str(buf1, sizeof(buf1), st, NULL);
6004 type_to_str(buf2, sizeof(buf2), dt, NULL);
6005 error("cannot cast '%s' to '%s'", buf1, buf2);
6007 break;
6009 type_ok:
6010 gen_cast(dt);
6013 /* store vtop in lvalue pushed on stack */
6014 void vstore(void)
6016 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6018 ft = vtop[-1].type.t;
6019 sbt = vtop->type.t & VT_BTYPE;
6020 dbt = ft & VT_BTYPE;
6021 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6022 (sbt == VT_INT && dbt == VT_SHORT)) {
6023 /* optimize char/short casts */
6024 delayed_cast = VT_MUSTCAST;
6025 vtop->type.t = ft & VT_TYPE;
6026 /* XXX: factorize */
6027 if (ft & VT_CONSTANT)
6028 warning("assignment of read-only location");
6029 } else {
6030 delayed_cast = 0;
6031 if (!(ft & VT_BITFIELD))
6032 gen_assign_cast(&vtop[-1].type);
6035 if (sbt == VT_STRUCT) {
6036 /* if structure, only generate pointer */
6037 /* structure assignment : generate memcpy */
6038 /* XXX: optimize if small size */
6039 if (!nocode_wanted) {
6040 size = type_size(&vtop->type, &align);
6042 vpush_global_sym(&func_old_type, TOK_memcpy);
6044 /* destination */
6045 vpushv(vtop - 2);
6046 vtop->type.t = VT_INT;
6047 gaddrof();
6048 /* source */
6049 vpushv(vtop - 2);
6050 vtop->type.t = VT_INT;
6051 gaddrof();
6052 /* type size */
6053 vpushi(size);
6054 gfunc_call(3);
6056 vswap();
6057 vpop();
6058 } else {
6059 vswap();
6060 vpop();
6062 /* leave source on stack */
6063 } else if (ft & VT_BITFIELD) {
6064 /* bitfield store handling */
6065 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6066 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6067 /* remove bit field info to avoid loops */
6068 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6070 /* duplicate destination */
6071 vdup();
6072 vtop[-1] = vtop[-2];
6074 /* mask and shift source */
6075 vpushi((1 << bit_size) - 1);
6076 gen_op('&');
6077 vpushi(bit_pos);
6078 gen_op(TOK_SHL);
6079 /* load destination, mask and or with source */
6080 vswap();
6081 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6082 gen_op('&');
6083 gen_op('|');
6084 /* store result */
6085 vstore();
6086 } else {
6087 #ifdef CONFIG_TCC_BCHECK
6088 /* bound check case */
6089 if (vtop[-1].r & VT_MUSTBOUND) {
6090 vswap();
6091 gbound();
6092 vswap();
6094 #endif
6095 if (!nocode_wanted) {
6096 rc = RC_INT;
6097 if (is_float(ft))
6098 rc = RC_FLOAT;
6099 r = gv(rc); /* generate value */
6100 /* if lvalue was saved on stack, must read it */
6101 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6102 SValue sv;
6103 t = get_reg(RC_INT);
6104 sv.type.t = VT_INT;
6105 sv.r = VT_LOCAL | VT_LVAL;
6106 sv.c.ul = vtop[-1].c.ul;
6107 load(t, &sv);
6108 vtop[-1].r = t | VT_LVAL;
6110 store(r, vtop - 1);
6111 /* two word case handling : store second register at word + 4 */
6112 if ((ft & VT_BTYPE) == VT_LLONG) {
6113 vswap();
6114 /* convert to int to increment easily */
6115 vtop->type.t = VT_INT;
6116 gaddrof();
6117 vpushi(4);
6118 gen_op('+');
6119 vtop->r |= VT_LVAL;
6120 vswap();
6121 /* XXX: it works because r2 is spilled last ! */
6122 store(vtop->r2, vtop - 1);
6125 vswap();
6126 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6127 vtop->r |= delayed_cast;
6131 /* post defines POST/PRE add. c is the token ++ or -- */
6132 void inc(int post, int c)
6134 test_lvalue();
6135 vdup(); /* save lvalue */
6136 if (post) {
6137 gv_dup(); /* duplicate value */
6138 vrotb(3);
6139 vrotb(3);
6141 /* add constant */
6142 vpushi(c - TOK_MID);
6143 gen_op('+');
6144 vstore(); /* store value */
6145 if (post)
6146 vpop(); /* if post op, return saved value */
6149 /* Parse GNUC __attribute__ extension. Currently, the following
6150 extensions are recognized:
6151 - aligned(n) : set data/function alignment.
6152 - section(x) : generate data/code in this section.
6153 - unused : currently ignored, but may be used someday.
6155 static void parse_attribute(AttributeDef *ad)
6157 int t, n;
6159 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6160 next();
6161 skip('(');
6162 skip('(');
6163 while (tok != ')') {
6164 if (tok < TOK_IDENT)
6165 expect("attribute name");
6166 t = tok;
6167 next();
6168 switch(t) {
6169 case TOK_SECTION1:
6170 case TOK_SECTION2:
6171 skip('(');
6172 if (tok != TOK_STR)
6173 expect("section name");
6174 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6175 next();
6176 skip(')');
6177 break;
6178 case TOK_ALIGNED1:
6179 case TOK_ALIGNED2:
6180 if (tok == '(') {
6181 next();
6182 n = expr_const();
6183 if (n <= 0 || (n & (n - 1)) != 0)
6184 error("alignment must be a positive power of two");
6185 skip(')');
6186 } else {
6187 n = MAX_ALIGN;
6189 ad->aligned = n;
6190 break;
6191 case TOK_UNUSED1:
6192 case TOK_UNUSED2:
6193 /* currently, no need to handle it because tcc does not
6194 track unused objects */
6195 break;
6196 case TOK_NORETURN1:
6197 case TOK_NORETURN2:
6198 /* currently, no need to handle it because tcc does not
6199 track unused objects */
6200 break;
6201 case TOK_CDECL1:
6202 case TOK_CDECL2:
6203 case TOK_CDECL3:
6204 ad->func_call = FUNC_CDECL;
6205 break;
6206 case TOK_STDCALL1:
6207 case TOK_STDCALL2:
6208 case TOK_STDCALL3:
6209 ad->func_call = FUNC_STDCALL;
6210 break;
6211 #ifdef TCC_TARGET_I386
6212 case TOK_REGPARM1:
6213 case TOK_REGPARM2:
6214 skip('(');
6215 n = expr_const();
6216 if (n > 3)
6217 n = 3;
6218 else if (n < 0)
6219 n = 0;
6220 if (n > 0)
6221 ad->func_call = FUNC_FASTCALL1 + n - 1;
6222 skip(')');
6223 break;
6224 #endif
6225 default:
6226 if (tcc_state->warn_unsupported)
6227 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6228 /* skip parameters */
6229 /* XXX: skip parenthesis too */
6230 if (tok == '(') {
6231 next();
6232 while (tok != ')' && tok != -1)
6233 next();
6234 next();
6236 break;
6238 if (tok != ',')
6239 break;
6240 next();
6242 skip(')');
6243 skip(')');
6247 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6248 static void struct_decl(CType *type, int u)
6250 int a, v, size, align, maxalign, c, offset;
6251 int bit_size, bit_pos, bsize, bt, lbit_pos;
6252 Sym *s, *ss, **ps;
6253 AttributeDef ad;
6254 CType type1, btype;
6256 a = tok; /* save decl type */
6257 next();
6258 if (tok != '{') {
6259 v = tok;
6260 next();
6261 /* struct already defined ? return it */
6262 if (v < TOK_IDENT)
6263 expect("struct/union/enum name");
6264 s = struct_find(v);
6265 if (s) {
6266 if (s->type.t != a)
6267 error("invalid type");
6268 goto do_decl;
6270 } else {
6271 v = anon_sym++;
6273 type1.t = a;
6274 /* we put an undefined size for struct/union */
6275 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6276 s->r = 0; /* default alignment is zero as gcc */
6277 /* put struct/union/enum name in type */
6278 do_decl:
6279 type->t = u;
6280 type->ref = s;
6282 if (tok == '{') {
6283 next();
6284 if (s->c != -1)
6285 error("struct/union/enum already defined");
6286 /* cannot be empty */
6287 c = 0;
6288 /* non empty enums are not allowed */
6289 if (a == TOK_ENUM) {
6290 for(;;) {
6291 v = tok;
6292 if (v < TOK_UIDENT)
6293 expect("identifier");
6294 next();
6295 if (tok == '=') {
6296 next();
6297 c = expr_const();
6299 /* enum symbols have static storage */
6300 ss = sym_push(v, &int_type, VT_CONST, c);
6301 ss->type.t |= VT_STATIC;
6302 if (tok != ',')
6303 break;
6304 next();
6305 c++;
6306 /* NOTE: we accept a trailing comma */
6307 if (tok == '}')
6308 break;
6310 skip('}');
6311 } else {
6312 maxalign = 1;
6313 ps = &s->next;
6314 bit_pos = 0;
6315 offset = 0;
6316 while (tok != '}') {
6317 parse_btype(&btype, &ad);
6318 while (1) {
6319 bit_size = -1;
6320 v = 0;
6321 type1 = btype;
6322 if (tok != ':') {
6323 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6324 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6325 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6326 error("invalid type for '%s'",
6327 get_tok_str(v, NULL));
6329 if (tok == ':') {
6330 next();
6331 bit_size = expr_const();
6332 /* XXX: handle v = 0 case for messages */
6333 if (bit_size < 0)
6334 error("negative width in bit-field '%s'",
6335 get_tok_str(v, NULL));
6336 if (v && bit_size == 0)
6337 error("zero width for bit-field '%s'",
6338 get_tok_str(v, NULL));
6340 size = type_size(&type1, &align);
6341 if (align < ad.aligned)
6342 align = ad.aligned;
6343 lbit_pos = 0;
6344 if (bit_size >= 0) {
6345 bt = type1.t & VT_BTYPE;
6346 if (bt != VT_INT &&
6347 bt != VT_BYTE &&
6348 bt != VT_SHORT &&
6349 bt != VT_ENUM)
6350 error("bitfields must have scalar type");
6351 bsize = size * 8;
6352 if (bit_size > bsize) {
6353 error("width of '%s' exceeds its type",
6354 get_tok_str(v, NULL));
6355 } else if (bit_size == bsize) {
6356 /* no need for bit fields */
6357 bit_pos = 0;
6358 } else if (bit_size == 0) {
6359 /* XXX: what to do if only padding in a
6360 structure ? */
6361 /* zero size: means to pad */
6362 if (bit_pos > 0)
6363 bit_pos = bsize;
6364 } else {
6365 /* we do not have enough room ? */
6366 if ((bit_pos + bit_size) > bsize)
6367 bit_pos = 0;
6368 lbit_pos = bit_pos;
6369 /* XXX: handle LSB first */
6370 type1.t |= VT_BITFIELD |
6371 (bit_pos << VT_STRUCT_SHIFT) |
6372 (bit_size << (VT_STRUCT_SHIFT + 6));
6373 bit_pos += bit_size;
6375 } else {
6376 bit_pos = 0;
6378 if (v) {
6379 /* add new memory data only if starting
6380 bit field */
6381 if (lbit_pos == 0) {
6382 if (a == TOK_STRUCT) {
6383 c = (c + align - 1) & -align;
6384 offset = c;
6385 c += size;
6386 } else {
6387 offset = 0;
6388 if (size > c)
6389 c = size;
6391 if (align > maxalign)
6392 maxalign = align;
6394 #if 0
6395 printf("add field %s offset=%d",
6396 get_tok_str(v, NULL), offset);
6397 if (type1.t & VT_BITFIELD) {
6398 printf(" pos=%d size=%d",
6399 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6400 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6402 printf("\n");
6403 #endif
6404 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6405 *ps = ss;
6406 ps = &ss->next;
6408 if (tok == ';' || tok == TOK_EOF)
6409 break;
6410 skip(',');
6412 skip(';');
6414 skip('}');
6415 /* store size and alignment */
6416 s->c = (c + maxalign - 1) & -maxalign;
6417 s->r = maxalign;
6422 /* return 0 if no type declaration. otherwise, return the basic type
6423 and skip it.
6425 static int parse_btype(CType *type, AttributeDef *ad)
6427 int t, u, type_found, typespec_found;
6428 Sym *s;
6429 CType type1;
6431 memset(ad, 0, sizeof(AttributeDef));
6432 type_found = 0;
6433 typespec_found = 0;
6434 t = 0;
6435 while(1) {
6436 switch(tok) {
6437 case TOK_EXTENSION:
6438 /* currently, we really ignore extension */
6439 next();
6440 continue;
6442 /* basic types */
6443 case TOK_CHAR:
6444 u = VT_BYTE;
6445 basic_type:
6446 next();
6447 basic_type1:
6448 if ((t & VT_BTYPE) != 0)
6449 error("too many basic types");
6450 t |= u;
6451 typespec_found = 1;
6452 break;
6453 case TOK_VOID:
6454 u = VT_VOID;
6455 goto basic_type;
6456 case TOK_SHORT:
6457 u = VT_SHORT;
6458 goto basic_type;
6459 case TOK_INT:
6460 next();
6461 typespec_found = 1;
6462 break;
6463 case TOK_LONG:
6464 next();
6465 if ((t & VT_BTYPE) == VT_DOUBLE) {
6466 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6467 } else if ((t & VT_BTYPE) == VT_LONG) {
6468 t = (t & ~VT_BTYPE) | VT_LLONG;
6469 } else {
6470 u = VT_LONG;
6471 goto basic_type1;
6473 break;
6474 case TOK_BOOL:
6475 u = VT_BOOL;
6476 goto basic_type;
6477 case TOK_FLOAT:
6478 u = VT_FLOAT;
6479 goto basic_type;
6480 case TOK_DOUBLE:
6481 next();
6482 if ((t & VT_BTYPE) == VT_LONG) {
6483 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6484 } else {
6485 u = VT_DOUBLE;
6486 goto basic_type1;
6488 break;
6489 case TOK_ENUM:
6490 struct_decl(&type1, VT_ENUM);
6491 basic_type2:
6492 u = type1.t;
6493 type->ref = type1.ref;
6494 goto basic_type1;
6495 case TOK_STRUCT:
6496 case TOK_UNION:
6497 struct_decl(&type1, VT_STRUCT);
6498 goto basic_type2;
6500 /* type modifiers */
6501 case TOK_CONST1:
6502 case TOK_CONST2:
6503 case TOK_CONST3:
6504 t |= VT_CONSTANT;
6505 next();
6506 break;
6507 case TOK_VOLATILE1:
6508 case TOK_VOLATILE2:
6509 case TOK_VOLATILE3:
6510 t |= VT_VOLATILE;
6511 next();
6512 break;
6513 case TOK_SIGNED1:
6514 case TOK_SIGNED2:
6515 case TOK_SIGNED3:
6516 typespec_found = 1;
6517 t |= VT_SIGNED;
6518 next();
6519 break;
6520 case TOK_REGISTER:
6521 case TOK_AUTO:
6522 case TOK_RESTRICT1:
6523 case TOK_RESTRICT2:
6524 case TOK_RESTRICT3:
6525 next();
6526 break;
6527 case TOK_UNSIGNED:
6528 t |= VT_UNSIGNED;
6529 next();
6530 typespec_found = 1;
6531 break;
6533 /* storage */
6534 case TOK_EXTERN:
6535 t |= VT_EXTERN;
6536 next();
6537 break;
6538 case TOK_STATIC:
6539 t |= VT_STATIC;
6540 next();
6541 break;
6542 case TOK_TYPEDEF:
6543 t |= VT_TYPEDEF;
6544 next();
6545 break;
6546 case TOK_INLINE1:
6547 case TOK_INLINE2:
6548 case TOK_INLINE3:
6549 t |= VT_INLINE;
6550 next();
6551 break;
6553 /* GNUC attribute */
6554 case TOK_ATTRIBUTE1:
6555 case TOK_ATTRIBUTE2:
6556 parse_attribute(ad);
6557 break;
6558 /* GNUC typeof */
6559 case TOK_TYPEOF1:
6560 case TOK_TYPEOF2:
6561 case TOK_TYPEOF3:
6562 next();
6563 parse_expr_type(&type1);
6564 goto basic_type2;
6565 default:
6566 if (typespec_found)
6567 goto the_end;
6568 s = sym_find(tok);
6569 if (!s || !(s->type.t & VT_TYPEDEF))
6570 goto the_end;
6571 t |= (s->type.t & ~VT_TYPEDEF);
6572 type->ref = s->type.ref;
6573 next();
6574 break;
6576 type_found = 1;
6578 the_end:
6579 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6580 error("signed and unsigned modifier");
6581 if (tcc_state->char_is_unsigned) {
6582 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6583 t |= VT_UNSIGNED;
6585 t &= ~VT_SIGNED;
6587 /* long is never used as type */
6588 if ((t & VT_BTYPE) == VT_LONG)
6589 t = (t & ~VT_BTYPE) | VT_INT;
6590 type->t = t;
6591 return type_found;
6594 /* convert a function parameter type (array to pointer and function to
6595 function pointer) */
6596 static inline void convert_parameter_type(CType *pt)
6598 /* array must be transformed to pointer according to ANSI C */
6599 pt->t &= ~VT_ARRAY;
6600 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6601 mk_pointer(pt);
6605 static void post_type(CType *type, AttributeDef *ad)
6607 int n, l, t1;
6608 Sym **plast, *s, *first;
6609 AttributeDef ad1;
6610 CType pt;
6612 if (tok == '(') {
6613 /* function declaration */
6614 next();
6615 l = 0;
6616 first = NULL;
6617 plast = &first;
6618 while (tok != ')') {
6619 /* read param name and compute offset */
6620 if (l != FUNC_OLD) {
6621 if (!parse_btype(&pt, &ad1)) {
6622 if (l) {
6623 error("invalid type");
6624 } else {
6625 l = FUNC_OLD;
6626 goto old_proto;
6629 l = FUNC_NEW;
6630 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6631 break;
6632 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6633 if ((pt.t & VT_BTYPE) == VT_VOID)
6634 error("parameter declared as void");
6635 } else {
6636 old_proto:
6637 n = tok;
6638 pt.t = VT_INT;
6639 next();
6641 convert_parameter_type(&pt);
6642 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6643 *plast = s;
6644 plast = &s->next;
6645 if (tok == ',') {
6646 next();
6647 if (l == FUNC_NEW && tok == TOK_DOTS) {
6648 l = FUNC_ELLIPSIS;
6649 next();
6650 break;
6654 /* if no parameters, then old type prototype */
6655 if (l == 0)
6656 l = FUNC_OLD;
6657 skip(')');
6658 t1 = type->t & VT_STORAGE;
6659 /* NOTE: const is ignored in returned type as it has a special
6660 meaning in gcc / C++ */
6661 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6662 post_type(type, ad);
6663 /* we push a anonymous symbol which will contain the function prototype */
6664 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6665 s->next = first;
6666 type->t = t1 | VT_FUNC;
6667 type->ref = s;
6668 } else if (tok == '[') {
6669 /* array definition */
6670 next();
6671 n = -1;
6672 if (tok != ']') {
6673 n = expr_const();
6674 if (n < 0)
6675 error("invalid array size");
6677 skip(']');
6678 /* parse next post type */
6679 t1 = type->t & VT_STORAGE;
6680 type->t &= ~VT_STORAGE;
6681 post_type(type, ad);
6683 /* we push a anonymous symbol which will contain the array
6684 element type */
6685 s = sym_push(SYM_FIELD, type, 0, n);
6686 type->t = t1 | VT_ARRAY | VT_PTR;
6687 type->ref = s;
6691 /* Parse a type declaration (except basic type), and return the type
6692 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6693 expected. 'type' should contain the basic type. 'ad' is the
6694 attribute definition of the basic type. It can be modified by
6695 type_decl().
6697 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6699 Sym *s;
6700 CType type1, *type2;
6701 int qualifiers;
6703 while (tok == '*') {
6704 qualifiers = 0;
6705 redo:
6706 next();
6707 switch(tok) {
6708 case TOK_CONST1:
6709 case TOK_CONST2:
6710 case TOK_CONST3:
6711 qualifiers |= VT_CONSTANT;
6712 goto redo;
6713 case TOK_VOLATILE1:
6714 case TOK_VOLATILE2:
6715 case TOK_VOLATILE3:
6716 qualifiers |= VT_VOLATILE;
6717 goto redo;
6718 case TOK_RESTRICT1:
6719 case TOK_RESTRICT2:
6720 case TOK_RESTRICT3:
6721 goto redo;
6723 mk_pointer(type);
6724 type->t |= qualifiers;
6727 /* XXX: clarify attribute handling */
6728 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6729 parse_attribute(ad);
6731 /* recursive type */
6732 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6733 type1.t = 0; /* XXX: same as int */
6734 if (tok == '(') {
6735 next();
6736 /* XXX: this is not correct to modify 'ad' at this point, but
6737 the syntax is not clear */
6738 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6739 parse_attribute(ad);
6740 type_decl(&type1, ad, v, td);
6741 skip(')');
6742 } else {
6743 /* type identifier */
6744 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6745 *v = tok;
6746 next();
6747 } else {
6748 if (!(td & TYPE_ABSTRACT))
6749 expect("identifier");
6750 *v = 0;
6753 post_type(type, ad);
6754 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6755 parse_attribute(ad);
6756 if (!type1.t)
6757 return;
6758 /* append type at the end of type1 */
6759 type2 = &type1;
6760 for(;;) {
6761 s = type2->ref;
6762 type2 = &s->type;
6763 if (!type2->t) {
6764 *type2 = *type;
6765 break;
6768 *type = type1;
6771 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6772 static int lvalue_type(int t)
6774 int bt, r;
6775 r = VT_LVAL;
6776 bt = t & VT_BTYPE;
6777 if (bt == VT_BYTE || bt == VT_BOOL)
6778 r |= VT_LVAL_BYTE;
6779 else if (bt == VT_SHORT)
6780 r |= VT_LVAL_SHORT;
6781 else
6782 return r;
6783 if (t & VT_UNSIGNED)
6784 r |= VT_LVAL_UNSIGNED;
6785 return r;
6788 /* indirection with full error checking and bound check */
6789 static void indir(void)
6791 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6792 expect("pointer");
6793 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6794 gv(RC_INT);
6795 vtop->type = *pointed_type(&vtop->type);
6796 /* an array is never an lvalue */
6797 if (!(vtop->type.t & VT_ARRAY)) {
6798 vtop->r |= lvalue_type(vtop->type.t);
6799 /* if bound checking, the referenced pointer must be checked */
6800 if (do_bounds_check)
6801 vtop->r |= VT_MUSTBOUND;
6805 /* pass a parameter to a function and do type checking and casting */
6806 static void gfunc_param_typed(Sym *func, Sym *arg)
6808 int func_type;
6809 CType type;
6811 func_type = func->c;
6812 if (func_type == FUNC_OLD ||
6813 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6814 /* default casting : only need to convert float to double */
6815 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6816 type.t = VT_DOUBLE;
6817 gen_cast(&type);
6819 } else if (arg == NULL) {
6820 error("too many arguments to function");
6821 } else {
6822 type = arg->type;
6823 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6824 gen_assign_cast(&type);
6828 /* parse an expression of the form '(type)' or '(expr)' and return its
6829 type */
6830 static void parse_expr_type(CType *type)
6832 int n;
6833 AttributeDef ad;
6835 skip('(');
6836 if (parse_btype(type, &ad)) {
6837 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6838 } else {
6839 expr_type(type);
6841 skip(')');
6844 static void parse_type(CType *type)
6846 AttributeDef ad;
6847 int n;
6849 if (!parse_btype(type, &ad)) {
6850 expect("type");
6852 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6855 static void vpush_tokc(int t)
6857 CType type;
6858 type.t = t;
6859 vsetc(&type, VT_CONST, &tokc);
6862 static void unary(void)
6864 int n, t, align, size, r;
6865 CType type;
6866 Sym *s;
6867 AttributeDef ad;
6869 /* XXX: GCC 2.95.3 does not generate a table although it should be
6870 better here */
6871 tok_next:
6872 switch(tok) {
6873 case TOK_EXTENSION:
6874 next();
6875 goto tok_next;
6876 case TOK_CINT:
6877 case TOK_CCHAR:
6878 case TOK_LCHAR:
6879 vpushi(tokc.i);
6880 next();
6881 break;
6882 case TOK_CUINT:
6883 vpush_tokc(VT_INT | VT_UNSIGNED);
6884 next();
6885 break;
6886 case TOK_CLLONG:
6887 vpush_tokc(VT_LLONG);
6888 next();
6889 break;
6890 case TOK_CULLONG:
6891 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6892 next();
6893 break;
6894 case TOK_CFLOAT:
6895 vpush_tokc(VT_FLOAT);
6896 next();
6897 break;
6898 case TOK_CDOUBLE:
6899 vpush_tokc(VT_DOUBLE);
6900 next();
6901 break;
6902 case TOK_CLDOUBLE:
6903 vpush_tokc(VT_LDOUBLE);
6904 next();
6905 break;
6906 case TOK___FUNCTION__:
6907 if (!gnu_ext)
6908 goto tok_identifier;
6909 /* fall thru */
6910 case TOK___FUNC__:
6912 void *ptr;
6913 int len;
6914 /* special function name identifier */
6915 len = strlen(funcname) + 1;
6916 /* generate char[len] type */
6917 type.t = VT_BYTE;
6918 mk_pointer(&type);
6919 type.t |= VT_ARRAY;
6920 type.ref->c = len;
6921 vpush_ref(&type, data_section, data_section->data_offset, len);
6922 ptr = section_ptr_add(data_section, len);
6923 memcpy(ptr, funcname, len);
6924 next();
6926 break;
6927 case TOK_LSTR:
6928 t = VT_INT;
6929 goto str_init;
6930 case TOK_STR:
6931 /* string parsing */
6932 t = VT_BYTE;
6933 str_init:
6934 if (tcc_state->warn_write_strings)
6935 t |= VT_CONSTANT;
6936 type.t = t;
6937 mk_pointer(&type);
6938 type.t |= VT_ARRAY;
6939 memset(&ad, 0, sizeof(AttributeDef));
6940 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6941 break;
6942 case '(':
6943 next();
6944 /* cast ? */
6945 if (parse_btype(&type, &ad)) {
6946 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6947 skip(')');
6948 /* check ISOC99 compound literal */
6949 if (tok == '{') {
6950 /* data is allocated locally by default */
6951 if (global_expr)
6952 r = VT_CONST;
6953 else
6954 r = VT_LOCAL;
6955 /* all except arrays are lvalues */
6956 if (!(type.t & VT_ARRAY))
6957 r |= lvalue_type(type.t);
6958 memset(&ad, 0, sizeof(AttributeDef));
6959 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6960 } else {
6961 unary();
6962 gen_cast(&type);
6964 } else if (tok == '{') {
6965 /* save all registers */
6966 save_regs(0);
6967 /* statement expression : we do not accept break/continue
6968 inside as GCC does */
6969 block(NULL, NULL, NULL, NULL, 0, 1);
6970 skip(')');
6971 } else {
6972 gexpr();
6973 skip(')');
6975 break;
6976 case '*':
6977 next();
6978 unary();
6979 indir();
6980 break;
6981 case '&':
6982 next();
6983 unary();
6984 /* functions names must be treated as function pointers,
6985 except for unary '&' and sizeof. Since we consider that
6986 functions are not lvalues, we only have to handle it
6987 there and in function calls. */
6988 /* arrays can also be used although they are not lvalues */
6989 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6990 !(vtop->type.t & VT_ARRAY))
6991 test_lvalue();
6992 mk_pointer(&vtop->type);
6993 gaddrof();
6994 break;
6995 case '!':
6996 next();
6997 unary();
6998 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6999 vtop->c.i = !vtop->c.i;
7000 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7001 vtop->c.i = vtop->c.i ^ 1;
7002 else
7003 vseti(VT_JMP, gtst(1, 0));
7004 break;
7005 case '~':
7006 next();
7007 unary();
7008 vpushi(-1);
7009 gen_op('^');
7010 break;
7011 case '+':
7012 next();
7013 /* in order to force cast, we add zero */
7014 unary();
7015 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7016 error("pointer not accepted for unary plus");
7017 vpushi(0);
7018 gen_op('+');
7019 break;
7020 case TOK_SIZEOF:
7021 case TOK_ALIGNOF1:
7022 case TOK_ALIGNOF2:
7023 t = tok;
7024 next();
7025 if (tok == '(') {
7026 parse_expr_type(&type);
7027 } else {
7028 unary_type(&type);
7030 size = type_size(&type, &align);
7031 if (t == TOK_SIZEOF) {
7032 if (size < 0)
7033 error("sizeof applied to an incomplete type");
7034 vpushi(size);
7035 } else {
7036 vpushi(align);
7038 break;
7040 case TOK_builtin_types_compatible_p:
7042 CType type1, type2;
7043 next();
7044 skip('(');
7045 parse_type(&type1);
7046 skip(',');
7047 parse_type(&type2);
7048 skip(')');
7049 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7050 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7051 vpushi(is_compatible_types(&type1, &type2));
7053 break;
7054 case TOK_builtin_constant_p:
7056 int saved_nocode_wanted, res;
7057 next();
7058 skip('(');
7059 saved_nocode_wanted = nocode_wanted;
7060 nocode_wanted = 1;
7061 gexpr();
7062 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7063 vpop();
7064 nocode_wanted = saved_nocode_wanted;
7065 skip(')');
7066 vpushi(res);
7068 break;
7069 case TOK_INC:
7070 case TOK_DEC:
7071 t = tok;
7072 next();
7073 unary();
7074 inc(0, t);
7075 break;
7076 case '-':
7077 next();
7078 vpushi(0);
7079 unary();
7080 gen_op('-');
7081 break;
7082 case TOK_LAND:
7083 if (!gnu_ext)
7084 goto tok_identifier;
7085 next();
7086 /* allow to take the address of a label */
7087 if (tok < TOK_UIDENT)
7088 expect("label identifier");
7089 s = label_find(tok);
7090 if (!s) {
7091 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7092 } else {
7093 if (s->r == LABEL_DECLARED)
7094 s->r = LABEL_FORWARD;
7096 if (!s->type.t) {
7097 s->type.t = VT_VOID;
7098 mk_pointer(&s->type);
7099 s->type.t |= VT_STATIC;
7101 vset(&s->type, VT_CONST | VT_SYM, 0);
7102 vtop->sym = s;
7103 next();
7104 break;
7105 default:
7106 tok_identifier:
7107 t = tok;
7108 next();
7109 if (t < TOK_UIDENT)
7110 expect("identifier");
7111 s = sym_find(t);
7112 if (!s) {
7113 if (tok != '(')
7114 error("'%s' undeclared", get_tok_str(t, NULL));
7115 /* for simple function calls, we tolerate undeclared
7116 external reference to int() function */
7117 if (tcc_state->warn_implicit_function_declaration)
7118 warning("implicit declaration of function '%s'",
7119 get_tok_str(t, NULL));
7120 s = external_global_sym(t, &func_old_type, 0);
7122 vset(&s->type, s->r, s->c);
7123 /* if forward reference, we must point to s */
7124 if (vtop->r & VT_SYM) {
7125 vtop->sym = s;
7126 vtop->c.ul = 0;
7128 break;
7131 /* post operations */
7132 while (1) {
7133 if (tok == TOK_INC || tok == TOK_DEC) {
7134 inc(1, tok);
7135 next();
7136 } else if (tok == '.' || tok == TOK_ARROW) {
7137 /* field */
7138 if (tok == TOK_ARROW)
7139 indir();
7140 test_lvalue();
7141 gaddrof();
7142 next();
7143 /* expect pointer on structure */
7144 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7145 expect("struct or union");
7146 s = vtop->type.ref;
7147 /* find field */
7148 tok |= SYM_FIELD;
7149 while ((s = s->next) != NULL) {
7150 if (s->v == tok)
7151 break;
7153 if (!s)
7154 error("field not found");
7155 /* add field offset to pointer */
7156 vtop->type = char_pointer_type; /* change type to 'char *' */
7157 vpushi(s->c);
7158 gen_op('+');
7159 /* change type to field type, and set to lvalue */
7160 vtop->type = s->type;
7161 /* an array is never an lvalue */
7162 if (!(vtop->type.t & VT_ARRAY)) {
7163 vtop->r |= lvalue_type(vtop->type.t);
7164 /* if bound checking, the referenced pointer must be checked */
7165 if (do_bounds_check)
7166 vtop->r |= VT_MUSTBOUND;
7168 next();
7169 } else if (tok == '[') {
7170 next();
7171 gexpr();
7172 gen_op('+');
7173 indir();
7174 skip(']');
7175 } else if (tok == '(') {
7176 SValue ret;
7177 Sym *sa;
7178 int nb_args;
7180 /* function call */
7181 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7182 /* pointer test (no array accepted) */
7183 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7184 vtop->type = *pointed_type(&vtop->type);
7185 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7186 goto error_func;
7187 } else {
7188 error_func:
7189 expect("function pointer");
7191 } else {
7192 vtop->r &= ~VT_LVAL; /* no lvalue */
7194 /* get return type */
7195 s = vtop->type.ref;
7196 next();
7197 sa = s->next; /* first parameter */
7198 nb_args = 0;
7199 /* compute first implicit argument if a structure is returned */
7200 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7201 /* get some space for the returned structure */
7202 size = type_size(&s->type, &align);
7203 loc = (loc - size) & -align;
7204 ret.type = s->type;
7205 ret.r = VT_LOCAL | VT_LVAL;
7206 /* pass it as 'int' to avoid structure arg passing
7207 problems */
7208 vseti(VT_LOCAL, loc);
7209 ret.c = vtop->c;
7210 nb_args++;
7211 } else {
7212 ret.type = s->type;
7213 ret.r2 = VT_CONST;
7214 /* return in register */
7215 if (is_float(ret.type.t)) {
7216 ret.r = REG_FRET;
7217 } else {
7218 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7219 ret.r2 = REG_LRET;
7220 ret.r = REG_IRET;
7222 ret.c.i = 0;
7224 if (tok != ')') {
7225 for(;;) {
7226 expr_eq();
7227 gfunc_param_typed(s, sa);
7228 nb_args++;
7229 if (sa)
7230 sa = sa->next;
7231 if (tok == ')')
7232 break;
7233 skip(',');
7236 if (sa)
7237 error("too few arguments to function");
7238 skip(')');
7239 if (!nocode_wanted) {
7240 gfunc_call(nb_args);
7241 } else {
7242 vtop -= (nb_args + 1);
7244 /* return value */
7245 vsetc(&ret.type, ret.r, &ret.c);
7246 vtop->r2 = ret.r2;
7247 } else {
7248 break;
7253 static void uneq(void)
7255 int t;
7257 unary();
7258 if (tok == '=' ||
7259 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7260 tok == TOK_A_XOR || tok == TOK_A_OR ||
7261 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7262 test_lvalue();
7263 t = tok;
7264 next();
7265 if (t == '=') {
7266 expr_eq();
7267 } else {
7268 vdup();
7269 expr_eq();
7270 gen_op(t & 0x7f);
7272 vstore();
7276 static void expr_prod(void)
7278 int t;
7280 uneq();
7281 while (tok == '*' || tok == '/' || tok == '%') {
7282 t = tok;
7283 next();
7284 uneq();
7285 gen_op(t);
7289 static void expr_sum(void)
7291 int t;
7293 expr_prod();
7294 while (tok == '+' || tok == '-') {
7295 t = tok;
7296 next();
7297 expr_prod();
7298 gen_op(t);
7302 static void expr_shift(void)
7304 int t;
7306 expr_sum();
7307 while (tok == TOK_SHL || tok == TOK_SAR) {
7308 t = tok;
7309 next();
7310 expr_sum();
7311 gen_op(t);
7315 static void expr_cmp(void)
7317 int t;
7319 expr_shift();
7320 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7321 tok == TOK_ULT || tok == TOK_UGE) {
7322 t = tok;
7323 next();
7324 expr_shift();
7325 gen_op(t);
7329 static void expr_cmpeq(void)
7331 int t;
7333 expr_cmp();
7334 while (tok == TOK_EQ || tok == TOK_NE) {
7335 t = tok;
7336 next();
7337 expr_cmp();
7338 gen_op(t);
7342 static void expr_and(void)
7344 expr_cmpeq();
7345 while (tok == '&') {
7346 next();
7347 expr_cmpeq();
7348 gen_op('&');
7352 static void expr_xor(void)
7354 expr_and();
7355 while (tok == '^') {
7356 next();
7357 expr_and();
7358 gen_op('^');
7362 static void expr_or(void)
7364 expr_xor();
7365 while (tok == '|') {
7366 next();
7367 expr_xor();
7368 gen_op('|');
7372 /* XXX: fix this mess */
7373 static void expr_land_const(void)
7375 expr_or();
7376 while (tok == TOK_LAND) {
7377 next();
7378 expr_or();
7379 gen_op(TOK_LAND);
7383 /* XXX: fix this mess */
7384 static void expr_lor_const(void)
7386 expr_land_const();
7387 while (tok == TOK_LOR) {
7388 next();
7389 expr_land_const();
7390 gen_op(TOK_LOR);
7394 /* only used if non constant */
7395 static void expr_land(void)
7397 int t;
7399 expr_or();
7400 if (tok == TOK_LAND) {
7401 t = 0;
7402 for(;;) {
7403 t = gtst(1, t);
7404 if (tok != TOK_LAND) {
7405 vseti(VT_JMPI, t);
7406 break;
7408 next();
7409 expr_or();
7414 static void expr_lor(void)
7416 int t;
7418 expr_land();
7419 if (tok == TOK_LOR) {
7420 t = 0;
7421 for(;;) {
7422 t = gtst(0, t);
7423 if (tok != TOK_LOR) {
7424 vseti(VT_JMP, t);
7425 break;
7427 next();
7428 expr_land();
7433 /* XXX: better constant handling */
7434 static void expr_eq(void)
7436 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7437 SValue sv;
7438 CType type, type1, type2;
7440 if (const_wanted) {
7441 int c1, c;
7442 expr_lor_const();
7443 if (tok == '?') {
7444 c = vtop->c.i;
7445 vpop();
7446 next();
7447 if (tok == ':' && gnu_ext) {
7448 c1 = c;
7449 } else {
7450 gexpr();
7451 c1 = vtop->c.i;
7452 vpop();
7454 skip(':');
7455 expr_eq();
7456 if (c)
7457 vtop->c.i = c1;
7459 } else {
7460 expr_lor();
7461 if (tok == '?') {
7462 next();
7463 if (vtop != vstack) {
7464 /* needed to avoid having different registers saved in
7465 each branch */
7466 if (is_float(vtop->type.t))
7467 rc = RC_FLOAT;
7468 else
7469 rc = RC_INT;
7470 gv(rc);
7471 save_regs(1);
7473 if (tok == ':' && gnu_ext) {
7474 gv_dup();
7475 tt = gtst(1, 0);
7476 } else {
7477 tt = gtst(1, 0);
7478 gexpr();
7480 type1 = vtop->type;
7481 sv = *vtop; /* save value to handle it later */
7482 vtop--; /* no vpop so that FP stack is not flushed */
7483 skip(':');
7484 u = gjmp(0);
7485 gsym(tt);
7486 expr_eq();
7487 type2 = vtop->type;
7489 t1 = type1.t;
7490 bt1 = t1 & VT_BTYPE;
7491 t2 = type2.t;
7492 bt2 = t2 & VT_BTYPE;
7493 /* cast operands to correct type according to ISOC rules */
7494 if (is_float(bt1) || is_float(bt2)) {
7495 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7496 type.t = VT_LDOUBLE;
7497 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7498 type.t = VT_DOUBLE;
7499 } else {
7500 type.t = VT_FLOAT;
7502 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7503 /* cast to biggest op */
7504 type.t = VT_LLONG;
7505 /* convert to unsigned if it does not fit in a long long */
7506 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7507 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7508 type.t |= VT_UNSIGNED;
7509 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7510 /* XXX: test pointer compatibility */
7511 type = type1;
7512 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7513 /* XXX: test structure compatibility */
7514 type = type1;
7515 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7516 /* NOTE: as an extension, we accept void on only one side */
7517 type.t = VT_VOID;
7518 } else {
7519 /* integer operations */
7520 type.t = VT_INT;
7521 /* convert to unsigned if it does not fit in an integer */
7522 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7523 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7524 type.t |= VT_UNSIGNED;
7527 /* now we convert second operand */
7528 gen_cast(&type);
7529 rc = RC_INT;
7530 if (is_float(type.t)) {
7531 rc = RC_FLOAT;
7532 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7533 /* for long longs, we use fixed registers to avoid having
7534 to handle a complicated move */
7535 rc = RC_IRET;
7538 r2 = gv(rc);
7539 /* this is horrible, but we must also convert first
7540 operand */
7541 tt = gjmp(0);
7542 gsym(u);
7543 /* put again first value and cast it */
7544 *vtop = sv;
7545 gen_cast(&type);
7546 r1 = gv(rc);
7547 move_reg(r2, r1);
7548 vtop->r = r2;
7549 gsym(tt);
7554 static void gexpr(void)
7556 while (1) {
7557 expr_eq();
7558 if (tok != ',')
7559 break;
7560 vpop();
7561 next();
7565 /* parse an expression and return its type without any side effect. */
7566 static void expr_type(CType *type)
7568 int saved_nocode_wanted;
7570 saved_nocode_wanted = nocode_wanted;
7571 nocode_wanted = 1;
7572 gexpr();
7573 *type = vtop->type;
7574 vpop();
7575 nocode_wanted = saved_nocode_wanted;
7578 /* parse a unary expression and return its type without any side
7579 effect. */
7580 static void unary_type(CType *type)
7582 int a;
7584 a = nocode_wanted;
7585 nocode_wanted = 1;
7586 unary();
7587 *type = vtop->type;
7588 vpop();
7589 nocode_wanted = a;
7592 /* parse a constant expression and return value in vtop. */
7593 static void expr_const1(void)
7595 int a;
7596 a = const_wanted;
7597 const_wanted = 1;
7598 expr_eq();
7599 const_wanted = a;
7602 /* parse an integer constant and return its value. */
7603 static int expr_const(void)
7605 int c;
7606 expr_const1();
7607 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7608 expect("constant expression");
7609 c = vtop->c.i;
7610 vpop();
7611 return c;
7614 /* return the label token if current token is a label, otherwise
7615 return zero */
7616 static int is_label(void)
7618 int last_tok;
7620 /* fast test first */
7621 if (tok < TOK_UIDENT)
7622 return 0;
7623 /* no need to save tokc because tok is an identifier */
7624 last_tok = tok;
7625 next();
7626 if (tok == ':') {
7627 next();
7628 return last_tok;
7629 } else {
7630 unget_tok(last_tok);
7631 return 0;
7635 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7636 int case_reg, int is_expr)
7638 int a, b, c, d;
7639 Sym *s;
7641 /* generate line number info */
7642 if (do_debug &&
7643 (last_line_num != file->line_num || last_ind != ind)) {
7644 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7645 last_ind = ind;
7646 last_line_num = file->line_num;
7649 if (is_expr) {
7650 /* default return value is (void) */
7651 vpushi(0);
7652 vtop->type.t = VT_VOID;
7655 if (tok == TOK_IF) {
7656 /* if test */
7657 next();
7658 skip('(');
7659 gexpr();
7660 skip(')');
7661 a = gtst(1, 0);
7662 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7663 c = tok;
7664 if (c == TOK_ELSE) {
7665 next();
7666 d = gjmp(0);
7667 gsym(a);
7668 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7669 gsym(d); /* patch else jmp */
7670 } else
7671 gsym(a);
7672 } else if (tok == TOK_WHILE) {
7673 next();
7674 d = ind;
7675 skip('(');
7676 gexpr();
7677 skip(')');
7678 a = gtst(1, 0);
7679 b = 0;
7680 block(&a, &b, case_sym, def_sym, case_reg, 0);
7681 gjmp_addr(d);
7682 gsym(a);
7683 gsym_addr(b, d);
7684 } else if (tok == '{') {
7685 Sym *llabel;
7687 next();
7688 /* record local declaration stack position */
7689 s = local_stack;
7690 llabel = local_label_stack;
7691 /* handle local labels declarations */
7692 if (tok == TOK_LABEL) {
7693 next();
7694 for(;;) {
7695 if (tok < TOK_UIDENT)
7696 expect("label identifier");
7697 label_push(&local_label_stack, tok, LABEL_DECLARED);
7698 next();
7699 if (tok == ',') {
7700 next();
7701 } else {
7702 skip(';');
7703 break;
7707 while (tok != '}') {
7708 decl(VT_LOCAL);
7709 if (tok != '}') {
7710 if (is_expr)
7711 vpop();
7712 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7715 /* pop locally defined labels */
7716 label_pop(&local_label_stack, llabel);
7717 /* pop locally defined symbols */
7718 sym_pop(&local_stack, s);
7719 next();
7720 } else if (tok == TOK_RETURN) {
7721 next();
7722 if (tok != ';') {
7723 gexpr();
7724 gen_assign_cast(&func_vt);
7725 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7726 CType type;
7727 /* if returning structure, must copy it to implicit
7728 first pointer arg location */
7729 type = func_vt;
7730 mk_pointer(&type);
7731 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7732 indir();
7733 vswap();
7734 /* copy structure value to pointer */
7735 vstore();
7736 } else if (is_float(func_vt.t)) {
7737 gv(RC_FRET);
7738 } else {
7739 gv(RC_IRET);
7741 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7743 skip(';');
7744 rsym = gjmp(rsym); /* jmp */
7745 } else if (tok == TOK_BREAK) {
7746 /* compute jump */
7747 if (!bsym)
7748 error("cannot break");
7749 *bsym = gjmp(*bsym);
7750 next();
7751 skip(';');
7752 } else if (tok == TOK_CONTINUE) {
7753 /* compute jump */
7754 if (!csym)
7755 error("cannot continue");
7756 *csym = gjmp(*csym);
7757 next();
7758 skip(';');
7759 } else if (tok == TOK_FOR) {
7760 int e;
7761 next();
7762 skip('(');
7763 if (tok != ';') {
7764 gexpr();
7765 vpop();
7767 skip(';');
7768 d = ind;
7769 c = ind;
7770 a = 0;
7771 b = 0;
7772 if (tok != ';') {
7773 gexpr();
7774 a = gtst(1, 0);
7776 skip(';');
7777 if (tok != ')') {
7778 e = gjmp(0);
7779 c = ind;
7780 gexpr();
7781 vpop();
7782 gjmp_addr(d);
7783 gsym(e);
7785 skip(')');
7786 block(&a, &b, case_sym, def_sym, case_reg, 0);
7787 gjmp_addr(c);
7788 gsym(a);
7789 gsym_addr(b, c);
7790 } else
7791 if (tok == TOK_DO) {
7792 next();
7793 a = 0;
7794 b = 0;
7795 d = ind;
7796 block(&a, &b, case_sym, def_sym, case_reg, 0);
7797 skip(TOK_WHILE);
7798 skip('(');
7799 gsym(b);
7800 gexpr();
7801 c = gtst(0, 0);
7802 gsym_addr(c, d);
7803 skip(')');
7804 gsym(a);
7805 skip(';');
7806 } else
7807 if (tok == TOK_SWITCH) {
7808 next();
7809 skip('(');
7810 gexpr();
7811 /* XXX: other types than integer */
7812 case_reg = gv(RC_INT);
7813 vpop();
7814 skip(')');
7815 a = 0;
7816 b = gjmp(0); /* jump to first case */
7817 c = 0;
7818 block(&a, csym, &b, &c, case_reg, 0);
7819 /* if no default, jmp after switch */
7820 if (c == 0)
7821 c = ind;
7822 /* default label */
7823 gsym_addr(b, c);
7824 /* break label */
7825 gsym(a);
7826 } else
7827 if (tok == TOK_CASE) {
7828 int v1, v2;
7829 if (!case_sym)
7830 expect("switch");
7831 next();
7832 v1 = expr_const();
7833 v2 = v1;
7834 if (gnu_ext && tok == TOK_DOTS) {
7835 next();
7836 v2 = expr_const();
7837 if (v2 < v1)
7838 warning("empty case range");
7840 /* since a case is like a label, we must skip it with a jmp */
7841 b = gjmp(0);
7842 gsym(*case_sym);
7843 vseti(case_reg, 0);
7844 vpushi(v1);
7845 if (v1 == v2) {
7846 gen_op(TOK_EQ);
7847 *case_sym = gtst(1, 0);
7848 } else {
7849 gen_op(TOK_GE);
7850 *case_sym = gtst(1, 0);
7851 vseti(case_reg, 0);
7852 vpushi(v2);
7853 gen_op(TOK_LE);
7854 *case_sym = gtst(1, *case_sym);
7856 gsym(b);
7857 skip(':');
7858 is_expr = 0;
7859 goto block_after_label;
7860 } else
7861 if (tok == TOK_DEFAULT) {
7862 next();
7863 skip(':');
7864 if (!def_sym)
7865 expect("switch");
7866 if (*def_sym)
7867 error("too many 'default'");
7868 *def_sym = ind;
7869 is_expr = 0;
7870 goto block_after_label;
7871 } else
7872 if (tok == TOK_GOTO) {
7873 next();
7874 if (tok == '*' && gnu_ext) {
7875 /* computed goto */
7876 next();
7877 gexpr();
7878 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7879 expect("pointer");
7880 ggoto();
7881 } else if (tok >= TOK_UIDENT) {
7882 s = label_find(tok);
7883 /* put forward definition if needed */
7884 if (!s) {
7885 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7886 } else {
7887 if (s->r == LABEL_DECLARED)
7888 s->r = LABEL_FORWARD;
7890 /* label already defined */
7891 if (s->r & LABEL_FORWARD)
7892 s->next = (void *)gjmp((long)s->next);
7893 else
7894 gjmp_addr((long)s->next);
7895 next();
7896 } else {
7897 expect("label identifier");
7899 skip(';');
7900 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7901 asm_instr();
7902 } else {
7903 b = is_label();
7904 if (b) {
7905 /* label case */
7906 s = label_find(b);
7907 if (s) {
7908 if (s->r == LABEL_DEFINED)
7909 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7910 gsym((long)s->next);
7911 s->r = LABEL_DEFINED;
7912 } else {
7913 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7915 s->next = (void *)ind;
7916 /* we accept this, but it is a mistake */
7917 block_after_label:
7918 if (tok == '}') {
7919 warning("deprecated use of label at end of compound statement");
7920 } else {
7921 if (is_expr)
7922 vpop();
7923 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7925 } else {
7926 /* expression case */
7927 if (tok != ';') {
7928 if (is_expr) {
7929 vpop();
7930 gexpr();
7931 } else {
7932 gexpr();
7933 vpop();
7936 skip(';');
7941 /* t is the array or struct type. c is the array or struct
7942 address. cur_index/cur_field is the pointer to the current
7943 value. 'size_only' is true if only size info is needed (only used
7944 in arrays) */
7945 static void decl_designator(CType *type, Section *sec, unsigned long c,
7946 int *cur_index, Sym **cur_field,
7947 int size_only)
7949 Sym *s, *f;
7950 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7951 CType type1;
7953 notfirst = 0;
7954 elem_size = 0;
7955 nb_elems = 1;
7956 if (gnu_ext && (l = is_label()) != 0)
7957 goto struct_field;
7958 while (tok == '[' || tok == '.') {
7959 if (tok == '[') {
7960 if (!(type->t & VT_ARRAY))
7961 expect("array type");
7962 s = type->ref;
7963 next();
7964 index = expr_const();
7965 if (index < 0 || (s->c >= 0 && index >= s->c))
7966 expect("invalid index");
7967 if (tok == TOK_DOTS && gnu_ext) {
7968 next();
7969 index_last = expr_const();
7970 if (index_last < 0 ||
7971 (s->c >= 0 && index_last >= s->c) ||
7972 index_last < index)
7973 expect("invalid index");
7974 } else {
7975 index_last = index;
7977 skip(']');
7978 if (!notfirst)
7979 *cur_index = index_last;
7980 type = pointed_type(type);
7981 elem_size = type_size(type, &align);
7982 c += index * elem_size;
7983 /* NOTE: we only support ranges for last designator */
7984 nb_elems = index_last - index + 1;
7985 if (nb_elems != 1) {
7986 notfirst = 1;
7987 break;
7989 } else {
7990 next();
7991 l = tok;
7992 next();
7993 struct_field:
7994 if ((type->t & VT_BTYPE) != VT_STRUCT)
7995 expect("struct/union type");
7996 s = type->ref;
7997 l |= SYM_FIELD;
7998 f = s->next;
7999 while (f) {
8000 if (f->v == l)
8001 break;
8002 f = f->next;
8004 if (!f)
8005 expect("field");
8006 if (!notfirst)
8007 *cur_field = f;
8008 /* XXX: fix this mess by using explicit storage field */
8009 type1 = f->type;
8010 type1.t |= (type->t & ~VT_TYPE);
8011 type = &type1;
8012 c += f->c;
8014 notfirst = 1;
8016 if (notfirst) {
8017 if (tok == '=') {
8018 next();
8019 } else {
8020 if (!gnu_ext)
8021 expect("=");
8023 } else {
8024 if (type->t & VT_ARRAY) {
8025 index = *cur_index;
8026 type = pointed_type(type);
8027 c += index * type_size(type, &align);
8028 } else {
8029 f = *cur_field;
8030 if (!f)
8031 error("too many field init");
8032 /* XXX: fix this mess by using explicit storage field */
8033 type1 = f->type;
8034 type1.t |= (type->t & ~VT_TYPE);
8035 type = &type1;
8036 c += f->c;
8039 decl_initializer(type, sec, c, 0, size_only);
8041 /* XXX: make it more general */
8042 if (!size_only && nb_elems > 1) {
8043 unsigned long c_end;
8044 uint8_t *src, *dst;
8045 int i;
8047 if (!sec)
8048 error("range init not supported yet for dynamic storage");
8049 c_end = c + nb_elems * elem_size;
8050 if (c_end > sec->data_allocated)
8051 section_realloc(sec, c_end);
8052 src = sec->data + c;
8053 dst = src;
8054 for(i = 1; i < nb_elems; i++) {
8055 dst += elem_size;
8056 memcpy(dst, src, elem_size);
8061 #define EXPR_VAL 0
8062 #define EXPR_CONST 1
8063 #define EXPR_ANY 2
8065 /* store a value or an expression directly in global data or in local array */
8066 static void init_putv(CType *type, Section *sec, unsigned long c,
8067 int v, int expr_type)
8069 int saved_global_expr, bt, bit_pos, bit_size;
8070 void *ptr;
8071 unsigned long long bit_mask;
8072 CType dtype;
8074 switch(expr_type) {
8075 case EXPR_VAL:
8076 vpushi(v);
8077 break;
8078 case EXPR_CONST:
8079 /* compound literals must be allocated globally in this case */
8080 saved_global_expr = global_expr;
8081 global_expr = 1;
8082 expr_const1();
8083 global_expr = saved_global_expr;
8084 /* NOTE: symbols are accepted */
8085 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8086 error("initializer element is not constant");
8087 break;
8088 case EXPR_ANY:
8089 expr_eq();
8090 break;
8093 dtype = *type;
8094 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8096 if (sec) {
8097 /* XXX: not portable */
8098 /* XXX: generate error if incorrect relocation */
8099 gen_assign_cast(&dtype);
8100 bt = type->t & VT_BTYPE;
8101 ptr = sec->data + c;
8102 /* XXX: make code faster ? */
8103 if (!(type->t & VT_BITFIELD)) {
8104 bit_pos = 0;
8105 bit_size = 32;
8106 bit_mask = -1LL;
8107 } else {
8108 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8109 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8110 bit_mask = (1LL << bit_size) - 1;
8112 if ((vtop->r & VT_SYM) &&
8113 (bt == VT_BYTE ||
8114 bt == VT_SHORT ||
8115 bt == VT_DOUBLE ||
8116 bt == VT_LDOUBLE ||
8117 bt == VT_LLONG ||
8118 (bt == VT_INT && bit_size != 32)))
8119 error("initializer element is not computable at load time");
8120 switch(bt) {
8121 case VT_BYTE:
8122 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8123 break;
8124 case VT_SHORT:
8125 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8126 break;
8127 case VT_DOUBLE:
8128 *(double *)ptr = vtop->c.d;
8129 break;
8130 case VT_LDOUBLE:
8131 *(long double *)ptr = vtop->c.ld;
8132 break;
8133 case VT_LLONG:
8134 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8135 break;
8136 default:
8137 if (vtop->r & VT_SYM) {
8138 greloc(sec, vtop->sym, c, R_DATA_32);
8140 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8141 break;
8143 vtop--;
8144 } else {
8145 vset(&dtype, VT_LOCAL, c);
8146 vswap();
8147 vstore();
8148 vpop();
8152 /* put zeros for variable based init */
8153 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8155 if (sec) {
8156 /* nothing to do because globals are already set to zero */
8157 } else {
8158 vpush_global_sym(&func_old_type, TOK_memset);
8159 vseti(VT_LOCAL, c);
8160 vpushi(0);
8161 vpushi(size);
8162 gfunc_call(3);
8166 /* 't' contains the type and storage info. 'c' is the offset of the
8167 object in section 'sec'. If 'sec' is NULL, it means stack based
8168 allocation. 'first' is true if array '{' must be read (multi
8169 dimension implicit array init handling). 'size_only' is true if
8170 size only evaluation is wanted (only for arrays). */
8171 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8172 int first, int size_only)
8174 int index, array_length, n, no_oblock, nb, parlevel, i;
8175 int size1, align1, expr_type;
8176 Sym *s, *f;
8177 CType *t1;
8179 if (type->t & VT_ARRAY) {
8180 s = type->ref;
8181 n = s->c;
8182 array_length = 0;
8183 t1 = pointed_type(type);
8184 size1 = type_size(t1, &align1);
8186 no_oblock = 1;
8187 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8188 tok == '{') {
8189 skip('{');
8190 no_oblock = 0;
8193 /* only parse strings here if correct type (otherwise: handle
8194 them as ((w)char *) expressions */
8195 if ((tok == TOK_LSTR &&
8196 (t1->t & VT_BTYPE) == VT_INT) ||
8197 (tok == TOK_STR &&
8198 (t1->t & VT_BTYPE) == VT_BYTE)) {
8199 while (tok == TOK_STR || tok == TOK_LSTR) {
8200 int cstr_len, ch;
8201 CString *cstr;
8203 cstr = tokc.cstr;
8204 /* compute maximum number of chars wanted */
8205 if (tok == TOK_STR)
8206 cstr_len = cstr->size;
8207 else
8208 cstr_len = cstr->size / sizeof(int);
8209 cstr_len--;
8210 nb = cstr_len;
8211 if (n >= 0 && nb > (n - array_length))
8212 nb = n - array_length;
8213 if (!size_only) {
8214 if (cstr_len > nb)
8215 warning("initializer-string for array is too long");
8216 /* in order to go faster for common case (char
8217 string in global variable, we handle it
8218 specifically */
8219 if (sec && tok == TOK_STR && size1 == 1) {
8220 memcpy(sec->data + c + array_length, cstr->data, nb);
8221 } else {
8222 for(i=0;i<nb;i++) {
8223 if (tok == TOK_STR)
8224 ch = ((unsigned char *)cstr->data)[i];
8225 else
8226 ch = ((int *)cstr->data)[i];
8227 init_putv(t1, sec, c + (array_length + i) * size1,
8228 ch, EXPR_VAL);
8232 array_length += nb;
8233 next();
8235 /* only add trailing zero if enough storage (no
8236 warning in this case since it is standard) */
8237 if (n < 0 || array_length < n) {
8238 if (!size_only) {
8239 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8241 array_length++;
8243 } else {
8244 index = 0;
8245 while (tok != '}') {
8246 decl_designator(type, sec, c, &index, NULL, size_only);
8247 if (n >= 0 && index >= n)
8248 error("index too large");
8249 /* must put zero in holes (note that doing it that way
8250 ensures that it even works with designators) */
8251 if (!size_only && array_length < index) {
8252 init_putz(t1, sec, c + array_length * size1,
8253 (index - array_length) * size1);
8255 index++;
8256 if (index > array_length)
8257 array_length = index;
8258 /* special test for multi dimensional arrays (may not
8259 be strictly correct if designators are used at the
8260 same time) */
8261 if (index >= n && no_oblock)
8262 break;
8263 if (tok == '}')
8264 break;
8265 skip(',');
8268 if (!no_oblock)
8269 skip('}');
8270 /* put zeros at the end */
8271 if (!size_only && n >= 0 && array_length < n) {
8272 init_putz(t1, sec, c + array_length * size1,
8273 (n - array_length) * size1);
8275 /* patch type size if needed */
8276 if (n < 0)
8277 s->c = array_length;
8278 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8279 (sec || !first || tok == '{')) {
8280 int par_count;
8282 /* NOTE: the previous test is a specific case for automatic
8283 struct/union init */
8284 /* XXX: union needs only one init */
8286 /* XXX: this test is incorrect for local initializers
8287 beginning with ( without {. It would be much more difficult
8288 to do it correctly (ideally, the expression parser should
8289 be used in all cases) */
8290 par_count = 0;
8291 if (tok == '(') {
8292 AttributeDef ad1;
8293 CType type1;
8294 next();
8295 while (tok == '(') {
8296 par_count++;
8297 next();
8299 if (!parse_btype(&type1, &ad1))
8300 expect("cast");
8301 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8302 #if 0
8303 if (!is_assignable_types(type, &type1))
8304 error("invalid type for cast");
8305 #endif
8306 skip(')');
8308 no_oblock = 1;
8309 if (first || tok == '{') {
8310 skip('{');
8311 no_oblock = 0;
8313 s = type->ref;
8314 f = s->next;
8315 array_length = 0;
8316 index = 0;
8317 n = s->c;
8318 while (tok != '}') {
8319 decl_designator(type, sec, c, NULL, &f, size_only);
8320 index = f->c;
8321 if (!size_only && array_length < index) {
8322 init_putz(type, sec, c + array_length,
8323 index - array_length);
8325 index = index + type_size(&f->type, &align1);
8326 if (index > array_length)
8327 array_length = index;
8328 f = f->next;
8329 if (no_oblock && f == NULL)
8330 break;
8331 if (tok == '}')
8332 break;
8333 skip(',');
8335 /* put zeros at the end */
8336 if (!size_only && array_length < n) {
8337 init_putz(type, sec, c + array_length,
8338 n - array_length);
8340 if (!no_oblock)
8341 skip('}');
8342 while (par_count) {
8343 skip(')');
8344 par_count--;
8346 } else if (tok == '{') {
8347 next();
8348 decl_initializer(type, sec, c, first, size_only);
8349 skip('}');
8350 } else if (size_only) {
8351 /* just skip expression */
8352 parlevel = 0;
8353 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8354 tok != -1) {
8355 if (tok == '(')
8356 parlevel++;
8357 else if (tok == ')')
8358 parlevel--;
8359 next();
8361 } else {
8362 /* currently, we always use constant expression for globals
8363 (may change for scripting case) */
8364 expr_type = EXPR_CONST;
8365 if (!sec)
8366 expr_type = EXPR_ANY;
8367 init_putv(type, sec, c, 0, expr_type);
8371 /* parse an initializer for type 't' if 'has_init' is non zero, and
8372 allocate space in local or global data space ('r' is either
8373 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8374 variable 'v' of scope 'scope' is declared before initializers are
8375 parsed. If 'v' is zero, then a reference to the new object is put
8376 in the value stack. If 'has_init' is 2, a special parsing is done
8377 to handle string constants. */
8378 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8379 int has_init, int v, int scope)
8381 int size, align, addr, data_offset;
8382 int level;
8383 ParseState saved_parse_state;
8384 TokenString init_str;
8385 Section *sec;
8387 size = type_size(type, &align);
8388 /* If unknown size, we must evaluate it before
8389 evaluating initializers because
8390 initializers can generate global data too
8391 (e.g. string pointers or ISOC99 compound
8392 literals). It also simplifies local
8393 initializers handling */
8394 tok_str_new(&init_str);
8395 if (size < 0) {
8396 if (!has_init)
8397 error("unknown type size");
8398 /* get all init string */
8399 if (has_init == 2) {
8400 /* only get strings */
8401 while (tok == TOK_STR || tok == TOK_LSTR) {
8402 tok_str_add_tok(&init_str);
8403 next();
8405 } else {
8406 level = 0;
8407 while (level > 0 || (tok != ',' && tok != ';')) {
8408 if (tok < 0)
8409 error("unexpected end of file in initializer");
8410 tok_str_add_tok(&init_str);
8411 if (tok == '{')
8412 level++;
8413 else if (tok == '}') {
8414 if (level == 0)
8415 break;
8416 level--;
8418 next();
8421 tok_str_add(&init_str, -1);
8422 tok_str_add(&init_str, 0);
8424 /* compute size */
8425 save_parse_state(&saved_parse_state);
8427 macro_ptr = init_str.str;
8428 next();
8429 decl_initializer(type, NULL, 0, 1, 1);
8430 /* prepare second initializer parsing */
8431 macro_ptr = init_str.str;
8432 next();
8434 /* if still unknown size, error */
8435 size = type_size(type, &align);
8436 if (size < 0)
8437 error("unknown type size");
8439 /* take into account specified alignment if bigger */
8440 if (ad->aligned > align)
8441 align = ad->aligned;
8442 if ((r & VT_VALMASK) == VT_LOCAL) {
8443 sec = NULL;
8444 if (do_bounds_check && (type->t & VT_ARRAY))
8445 loc--;
8446 loc = (loc - size) & -align;
8447 addr = loc;
8448 /* handles bounds */
8449 /* XXX: currently, since we do only one pass, we cannot track
8450 '&' operators, so we add only arrays */
8451 if (do_bounds_check && (type->t & VT_ARRAY)) {
8452 unsigned long *bounds_ptr;
8453 /* add padding between regions */
8454 loc--;
8455 /* then add local bound info */
8456 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8457 bounds_ptr[0] = addr;
8458 bounds_ptr[1] = size;
8460 if (v) {
8461 /* local variable */
8462 sym_push(v, type, r, addr);
8463 } else {
8464 /* push local reference */
8465 vset(type, r, addr);
8467 } else {
8468 Sym *sym;
8470 sym = NULL;
8471 if (v && scope == VT_CONST) {
8472 /* see if the symbol was already defined */
8473 sym = sym_find(v);
8474 if (sym) {
8475 if (!is_compatible_types(&sym->type, type))
8476 error("incompatible types for redefinition of '%s'",
8477 get_tok_str(v, NULL));
8478 if (sym->type.t & VT_EXTERN) {
8479 /* if the variable is extern, it was not allocated */
8480 sym->type.t &= ~VT_EXTERN;
8481 /* set array size if it was ommited in extern
8482 declaration */
8483 if ((sym->type.t & VT_ARRAY) &&
8484 sym->type.ref->c < 0 &&
8485 type->ref->c >= 0)
8486 sym->type.ref->c = type->ref->c;
8487 } else {
8488 /* we accept several definitions of the same
8489 global variable. this is tricky, because we
8490 must play with the SHN_COMMON type of the symbol */
8491 /* XXX: should check if the variable was already
8492 initialized. It is incorrect to initialized it
8493 twice */
8494 /* no init data, we won't add more to the symbol */
8495 if (!has_init)
8496 goto no_alloc;
8501 /* allocate symbol in corresponding section */
8502 sec = ad->section;
8503 if (!sec) {
8504 if (has_init)
8505 sec = data_section;
8506 else if (tcc_state->nocommon)
8507 sec = bss_section;
8509 if (sec) {
8510 data_offset = sec->data_offset;
8511 data_offset = (data_offset + align - 1) & -align;
8512 addr = data_offset;
8513 /* very important to increment global pointer at this time
8514 because initializers themselves can create new initializers */
8515 data_offset += size;
8516 /* add padding if bound check */
8517 if (do_bounds_check)
8518 data_offset++;
8519 sec->data_offset = data_offset;
8520 /* allocate section space to put the data */
8521 if (sec->sh_type != SHT_NOBITS &&
8522 data_offset > sec->data_allocated)
8523 section_realloc(sec, data_offset);
8524 /* align section if needed */
8525 if (align > sec->sh_addralign)
8526 sec->sh_addralign = align;
8527 } else {
8528 addr = 0; /* avoid warning */
8531 if (v) {
8532 if (scope == VT_CONST) {
8533 if (!sym)
8534 goto do_def;
8535 } else {
8536 do_def:
8537 sym = sym_push(v, type, r | VT_SYM, 0);
8539 /* update symbol definition */
8540 if (sec) {
8541 put_extern_sym(sym, sec, addr, size);
8542 } else {
8543 Elf32_Sym *esym;
8544 /* put a common area */
8545 put_extern_sym(sym, NULL, align, size);
8546 /* XXX: find a nicer way */
8547 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8548 esym->st_shndx = SHN_COMMON;
8550 } else {
8551 CValue cval;
8553 /* push global reference */
8554 sym = get_sym_ref(type, sec, addr, size);
8555 cval.ul = 0;
8556 vsetc(type, VT_CONST | VT_SYM, &cval);
8557 vtop->sym = sym;
8560 /* handles bounds now because the symbol must be defined
8561 before for the relocation */
8562 if (do_bounds_check) {
8563 unsigned long *bounds_ptr;
8565 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8566 /* then add global bound info */
8567 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8568 bounds_ptr[0] = 0; /* relocated */
8569 bounds_ptr[1] = size;
8572 if (has_init) {
8573 decl_initializer(type, sec, addr, 1, 0);
8574 /* restore parse state if needed */
8575 if (init_str.str) {
8576 tok_str_free(init_str.str);
8577 restore_parse_state(&saved_parse_state);
8580 no_alloc: ;
8583 void put_func_debug(Sym *sym)
8585 char buf[512];
8587 /* stabs info */
8588 /* XXX: we put here a dummy type */
8589 snprintf(buf, sizeof(buf), "%s:%c1",
8590 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8591 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8592 cur_text_section, sym->c);
8593 last_ind = 0;
8594 last_line_num = 0;
8597 /* not finished : try to put some local vars in registers */
8598 //#define CONFIG_REG_VARS
8600 #ifdef CONFIG_REG_VARS
8601 void add_var_ref(int t)
8603 printf("%s:%d: &%s\n",
8604 file->filename, file->line_num,
8605 get_tok_str(t, NULL));
8608 /* first pass on a function with heuristic to extract variable usage
8609 and pointer references to local variables for register allocation */
8610 void analyse_function(void)
8612 int level, t;
8614 for(;;) {
8615 if (tok == -1)
8616 break;
8617 /* any symbol coming after '&' is considered as being a
8618 variable whose reference is taken. It is highly unaccurate
8619 but it is difficult to do better without a complete parse */
8620 if (tok == '&') {
8621 next();
8622 /* if '& number', then no need to examine next tokens */
8623 if (tok == TOK_CINT ||
8624 tok == TOK_CUINT ||
8625 tok == TOK_CLLONG ||
8626 tok == TOK_CULLONG) {
8627 continue;
8628 } else if (tok >= TOK_UIDENT) {
8629 /* if '& ident [' or '& ident ->', then ident address
8630 is not needed */
8631 t = tok;
8632 next();
8633 if (tok != '[' && tok != TOK_ARROW)
8634 add_var_ref(t);
8635 } else {
8636 level = 0;
8637 while (tok != '}' && tok != ';' &&
8638 !((tok == ',' || tok == ')') && level == 0)) {
8639 if (tok >= TOK_UIDENT) {
8640 add_var_ref(tok);
8641 } else if (tok == '(') {
8642 level++;
8643 } else if (tok == ')') {
8644 level--;
8646 next();
8649 } else {
8650 next();
8654 #endif
8656 /* parse an old style function declaration list */
8657 /* XXX: check multiple parameter */
8658 static void func_decl_list(Sym *func_sym)
8660 AttributeDef ad;
8661 int v;
8662 Sym *s;
8663 CType btype, type;
8665 /* parse each declaration */
8666 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8667 if (!parse_btype(&btype, &ad))
8668 expect("declaration list");
8669 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8670 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8671 tok == ';') {
8672 /* we accept no variable after */
8673 } else {
8674 for(;;) {
8675 type = btype;
8676 type_decl(&type, &ad, &v, TYPE_DIRECT);
8677 /* find parameter in function parameter list */
8678 s = func_sym->next;
8679 while (s != NULL) {
8680 if ((s->v & ~SYM_FIELD) == v)
8681 goto found;
8682 s = s->next;
8684 error("declaration for parameter '%s' but no such parameter",
8685 get_tok_str(v, NULL));
8686 found:
8687 /* check that no storage specifier except 'register' was given */
8688 if (type.t & VT_STORAGE)
8689 error("storage class specified for '%s'", get_tok_str(v, NULL));
8690 convert_parameter_type(&type);
8691 /* we can add the type (NOTE: it could be local to the function) */
8692 s->type = type;
8693 /* accept other parameters */
8694 if (tok == ',')
8695 next();
8696 else
8697 break;
8700 skip(';');
8704 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8705 static void decl(int l)
8707 int v, has_init, r;
8708 CType type, btype;
8709 Sym *sym;
8710 AttributeDef ad;
8712 while (1) {
8713 if (!parse_btype(&btype, &ad)) {
8714 /* skip redundant ';' */
8715 /* XXX: find more elegant solution */
8716 if (tok == ';') {
8717 next();
8718 continue;
8720 if (l == VT_CONST &&
8721 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
8722 /* global asm block */
8723 asm_global_instr();
8724 continue;
8726 /* special test for old K&R protos without explicit int
8727 type. Only accepted when defining global data */
8728 if (l == VT_LOCAL || tok < TOK_DEFINE)
8729 break;
8730 btype.t = VT_INT;
8732 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8733 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8734 tok == ';') {
8735 /* we accept no variable after */
8736 next();
8737 continue;
8739 while (1) { /* iterate thru each declaration */
8740 type = btype;
8741 type_decl(&type, &ad, &v, TYPE_DIRECT);
8742 #if 0
8744 char buf[500];
8745 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8746 printf("type = '%s'\n", buf);
8748 #endif
8749 if ((type.t & VT_BTYPE) == VT_FUNC) {
8750 /* if old style function prototype, we accept a
8751 declaration list */
8752 sym = type.ref;
8753 if (sym->c == FUNC_OLD)
8754 func_decl_list(sym);
8757 if (tok == '{') {
8758 #ifdef CONFIG_REG_VARS
8759 TokenString func_str;
8760 ParseState saved_parse_state;
8761 int block_level;
8762 #endif
8763 if (l == VT_LOCAL)
8764 error("cannot use local functions");
8765 if (!(type.t & VT_FUNC))
8766 expect("function definition");
8768 /* reject abstract declarators in function definition */
8769 sym = type.ref;
8770 while ((sym = sym->next) != NULL)
8771 if (!(sym->v & ~SYM_FIELD))
8772 expect("identifier");
8774 /* XXX: cannot do better now: convert extern line to static inline */
8775 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8776 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8778 #ifdef CONFIG_REG_VARS
8779 /* parse all function code and record it */
8781 tok_str_new(&func_str);
8783 block_level = 0;
8784 for(;;) {
8785 int t;
8786 if (tok == -1)
8787 error("unexpected end of file");
8788 tok_str_add_tok(&func_str);
8789 t = tok;
8790 next();
8791 if (t == '{') {
8792 block_level++;
8793 } else if (t == '}') {
8794 block_level--;
8795 if (block_level == 0)
8796 break;
8799 tok_str_add(&func_str, -1);
8800 tok_str_add(&func_str, 0);
8802 save_parse_state(&saved_parse_state);
8804 macro_ptr = func_str.str;
8805 next();
8806 analyse_function();
8807 #endif
8809 /* compute text section */
8810 cur_text_section = ad.section;
8811 if (!cur_text_section)
8812 cur_text_section = text_section;
8813 ind = cur_text_section->data_offset;
8814 funcname = get_tok_str(v, NULL);
8815 sym = sym_find(v);
8816 if (sym) {
8817 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
8818 goto func_error1;
8819 /* specific case: if not func_call defined, we put
8820 the one of the prototype */
8821 /* XXX: should have default value */
8822 if (sym->type.ref->r != FUNC_CDECL &&
8823 type.ref->r == FUNC_CDECL)
8824 type.ref->r = sym->type.ref->r;
8825 if (!is_compatible_types(&sym->type, &type)) {
8826 func_error1:
8827 error("incompatible types for redefinition of '%s'",
8828 get_tok_str(v, NULL));
8830 /* if symbol is already defined, then put complete type */
8831 sym->type = type;
8832 } else {
8833 /* put function symbol */
8834 sym = global_identifier_push(v, type.t, 0);
8835 sym->type.ref = type.ref;
8837 /* NOTE: we patch the symbol size later */
8838 put_extern_sym(sym, cur_text_section, ind, 0);
8839 func_ind = ind;
8840 sym->r = VT_SYM | VT_CONST;
8841 /* put debug symbol */
8842 if (do_debug)
8843 put_func_debug(sym);
8844 /* push a dummy symbol to enable local sym storage */
8845 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8846 gfunc_prolog(&type);
8847 rsym = 0;
8848 #ifdef CONFIG_REG_VARS
8849 macro_ptr = func_str.str;
8850 next();
8851 #endif
8852 block(NULL, NULL, NULL, NULL, 0, 0);
8853 gsym(rsym);
8854 gfunc_epilog();
8855 cur_text_section->data_offset = ind;
8856 label_pop(&global_label_stack, NULL);
8857 sym_pop(&local_stack, NULL); /* reset local stack */
8858 /* end of function */
8859 /* patch symbol size */
8860 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8861 ind - func_ind;
8862 if (do_debug) {
8863 put_stabn(N_FUN, 0, 0, ind - func_ind);
8865 funcname = ""; /* for safety */
8866 func_vt.t = VT_VOID; /* for safety */
8867 ind = 0; /* for safety */
8869 #ifdef CONFIG_REG_VARS
8870 tok_str_free(func_str.str);
8871 restore_parse_state(&saved_parse_state);
8872 #endif
8873 break;
8874 } else {
8875 if (btype.t & VT_TYPEDEF) {
8876 /* save typedefed type */
8877 /* XXX: test storage specifiers ? */
8878 sym = sym_push(v, &type, 0, 0);
8879 sym->type.t |= VT_TYPEDEF;
8880 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8881 /* external function definition */
8882 /* specific case for func_call attribute */
8883 if (ad.func_call)
8884 type.ref->r = ad.func_call;
8885 external_sym(v, &type, 0);
8886 } else {
8887 /* not lvalue if array */
8888 r = 0;
8889 if (!(type.t & VT_ARRAY))
8890 r |= lvalue_type(type.t);
8891 has_init = (tok == '=');
8892 if ((btype.t & VT_EXTERN) ||
8893 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8894 !has_init && l == VT_CONST && type.ref->c < 0)) {
8895 /* external variable */
8896 /* NOTE: as GCC, uninitialized global static
8897 arrays of null size are considered as
8898 extern */
8899 external_sym(v, &type, r);
8900 } else {
8901 if (type.t & VT_STATIC)
8902 r |= VT_CONST;
8903 else
8904 r |= l;
8905 if (has_init)
8906 next();
8907 decl_initializer_alloc(&type, &ad, r,
8908 has_init, v, l);
8911 if (tok != ',') {
8912 skip(';');
8913 break;
8915 next();
8921 /* better than nothing, but needs extension to handle '-E' option
8922 correctly too */
8923 static void preprocess_init(TCCState *s1)
8925 s1->include_stack_ptr = s1->include_stack;
8926 /* XXX: move that before to avoid having to initialize
8927 file->ifdef_stack_ptr ? */
8928 s1->ifdef_stack_ptr = s1->ifdef_stack;
8929 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8931 /* XXX: not ANSI compliant: bound checking says error */
8932 vtop = vstack - 1;
8935 /* compile the C file opened in 'file'. Return non zero if errors. */
8936 static int tcc_compile(TCCState *s1)
8938 Sym *define_start;
8939 char buf[512];
8940 volatile int section_sym;
8942 #ifdef INC_DEBUG
8943 printf("%s: **** new file\n", file->filename);
8944 #endif
8945 preprocess_init(s1);
8947 funcname = "";
8948 anon_sym = SYM_FIRST_ANOM;
8950 /* file info: full path + filename */
8951 section_sym = 0; /* avoid warning */
8952 if (do_debug) {
8953 section_sym = put_elf_sym(symtab_section, 0, 0,
8954 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8955 text_section->sh_num, NULL);
8956 getcwd(buf, sizeof(buf));
8957 pstrcat(buf, sizeof(buf), "/");
8958 put_stabs_r(buf, N_SO, 0, 0,
8959 text_section->data_offset, text_section, section_sym);
8960 put_stabs_r(file->filename, N_SO, 0, 0,
8961 text_section->data_offset, text_section, section_sym);
8963 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8964 symbols can be safely used */
8965 put_elf_sym(symtab_section, 0, 0,
8966 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8967 SHN_ABS, file->filename);
8969 /* define some often used types */
8970 int_type.t = VT_INT;
8972 char_pointer_type.t = VT_BYTE;
8973 mk_pointer(&char_pointer_type);
8975 func_old_type.t = VT_FUNC;
8976 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8978 #if 0
8979 /* define 'void *alloca(unsigned int)' builtin function */
8981 Sym *s1;
8983 p = anon_sym++;
8984 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8985 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8986 s1->next = NULL;
8987 sym->next = s1;
8988 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8990 #endif
8992 define_start = define_stack;
8994 if (setjmp(s1->error_jmp_buf) == 0) {
8995 s1->nb_errors = 0;
8996 s1->error_set_jmp_enabled = 1;
8998 ch = file->buf_ptr[0];
8999 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9000 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9001 next();
9002 decl(VT_CONST);
9003 if (tok != TOK_EOF)
9004 expect("declaration");
9006 /* end of translation unit info */
9007 if (do_debug) {
9008 put_stabs_r(NULL, N_SO, 0, 0,
9009 text_section->data_offset, text_section, section_sym);
9012 s1->error_set_jmp_enabled = 0;
9014 /* reset define stack, but leave -Dsymbols (may be incorrect if
9015 they are undefined) */
9016 free_defines(define_start);
9018 sym_pop(&global_stack, NULL);
9020 return s1->nb_errors != 0 ? -1 : 0;
9023 #ifdef LIBTCC
9024 int tcc_compile_string(TCCState *s, const char *str)
9026 BufferedFile bf1, *bf = &bf1;
9027 int ret, len;
9028 char *buf;
9030 /* init file structure */
9031 bf->fd = -1;
9032 /* XXX: avoid copying */
9033 len = strlen(str);
9034 buf = tcc_malloc(len + 1);
9035 if (!buf)
9036 return -1;
9037 memcpy(buf, str, len);
9038 buf[len] = CH_EOB;
9039 bf->buf_ptr = buf;
9040 bf->buf_end = buf + len;
9041 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9042 bf->line_num = 1;
9043 file = bf;
9045 ret = tcc_compile(s);
9047 tcc_free(buf);
9049 /* currently, no need to close */
9050 return ret;
9052 #endif
9054 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9055 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9057 BufferedFile bf1, *bf = &bf1;
9059 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9060 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9061 /* default value */
9062 if (!value)
9063 value = "1";
9064 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9066 /* init file structure */
9067 bf->fd = -1;
9068 bf->buf_ptr = bf->buffer;
9069 bf->buf_end = bf->buffer + strlen(bf->buffer);
9070 *bf->buf_end = CH_EOB;
9071 bf->filename[0] = '\0';
9072 bf->line_num = 1;
9073 file = bf;
9075 s1->include_stack_ptr = s1->include_stack;
9077 /* parse with define parser */
9078 ch = file->buf_ptr[0];
9079 next_nomacro();
9080 parse_define();
9081 file = NULL;
9084 /* undefine a preprocessor symbol */
9085 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9087 TokenSym *ts;
9088 Sym *s;
9089 ts = tok_alloc(sym, strlen(sym));
9090 s = define_find(ts->tok);
9091 /* undefine symbol by putting an invalid name */
9092 if (s)
9093 define_undef(s);
9096 #ifdef CONFIG_TCC_ASM
9098 #ifdef TCC_TARGET_I386
9099 #include "i386-asm.c"
9100 #endif
9101 #include "tccasm.c"
9103 #else
9104 static void asm_instr(void)
9106 error("inline asm() not supported");
9108 static void asm_global_instr(void)
9110 error("inline asm() not supported");
9112 #endif
9114 #include "tccelf.c"
9116 #ifdef TCC_TARGET_COFF
9117 #include "tcccoff.c"
9118 #endif
9120 /* print the position in the source file of PC value 'pc' by reading
9121 the stabs debug information */
9122 static void rt_printline(unsigned long wanted_pc)
9124 Stab_Sym *sym, *sym_end;
9125 char func_name[128], last_func_name[128];
9126 unsigned long func_addr, last_pc, pc;
9127 const char *incl_files[INCLUDE_STACK_SIZE];
9128 int incl_index, len, last_line_num, i;
9129 const char *str, *p;
9131 fprintf(stderr, "0x%08lx:", wanted_pc);
9133 func_name[0] = '\0';
9134 func_addr = 0;
9135 incl_index = 0;
9136 last_func_name[0] = '\0';
9137 last_pc = 0xffffffff;
9138 last_line_num = 1;
9139 sym = (Stab_Sym *)stab_section->data + 1;
9140 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9141 while (sym < sym_end) {
9142 switch(sym->n_type) {
9143 /* function start or end */
9144 case N_FUN:
9145 if (sym->n_strx == 0) {
9146 /* we test if between last line and end of function */
9147 pc = sym->n_value + func_addr;
9148 if (wanted_pc >= last_pc && wanted_pc < pc)
9149 goto found;
9150 func_name[0] = '\0';
9151 func_addr = 0;
9152 } else {
9153 str = stabstr_section->data + sym->n_strx;
9154 p = strchr(str, ':');
9155 if (!p) {
9156 pstrcpy(func_name, sizeof(func_name), str);
9157 } else {
9158 len = p - str;
9159 if (len > sizeof(func_name) - 1)
9160 len = sizeof(func_name) - 1;
9161 memcpy(func_name, str, len);
9162 func_name[len] = '\0';
9164 func_addr = sym->n_value;
9166 break;
9167 /* line number info */
9168 case N_SLINE:
9169 pc = sym->n_value + func_addr;
9170 if (wanted_pc >= last_pc && wanted_pc < pc)
9171 goto found;
9172 last_pc = pc;
9173 last_line_num = sym->n_desc;
9174 /* XXX: slow! */
9175 strcpy(last_func_name, func_name);
9176 break;
9177 /* include files */
9178 case N_BINCL:
9179 str = stabstr_section->data + sym->n_strx;
9180 add_incl:
9181 if (incl_index < INCLUDE_STACK_SIZE) {
9182 incl_files[incl_index++] = str;
9184 break;
9185 case N_EINCL:
9186 if (incl_index > 1)
9187 incl_index--;
9188 break;
9189 case N_SO:
9190 if (sym->n_strx == 0) {
9191 incl_index = 0; /* end of translation unit */
9192 } else {
9193 str = stabstr_section->data + sym->n_strx;
9194 /* do not add path */
9195 len = strlen(str);
9196 if (len > 0 && str[len - 1] != '/')
9197 goto add_incl;
9199 break;
9201 sym++;
9204 /* second pass: we try symtab symbols (no line number info) */
9205 incl_index = 0;
9207 Elf32_Sym *sym, *sym_end;
9208 int type;
9210 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9211 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9212 sym < sym_end;
9213 sym++) {
9214 type = ELF32_ST_TYPE(sym->st_info);
9215 if (type == STT_FUNC) {
9216 if (wanted_pc >= sym->st_value &&
9217 wanted_pc < sym->st_value + sym->st_size) {
9218 pstrcpy(last_func_name, sizeof(last_func_name),
9219 strtab_section->data + sym->st_name);
9220 goto found;
9225 /* did not find any info: */
9226 fprintf(stderr, " ???\n");
9227 return;
9228 found:
9229 if (last_func_name[0] != '\0') {
9230 fprintf(stderr, " %s()", last_func_name);
9232 if (incl_index > 0) {
9233 fprintf(stderr, " (%s:%d",
9234 incl_files[incl_index - 1], last_line_num);
9235 for(i = incl_index - 2; i >= 0; i--)
9236 fprintf(stderr, ", included from %s", incl_files[i]);
9237 fprintf(stderr, ")");
9239 fprintf(stderr, "\n");
9242 #ifndef WIN32
9244 #ifdef __i386__
9246 /* fix for glibc 2.1 */
9247 #ifndef REG_EIP
9248 #define REG_EIP EIP
9249 #define REG_EBP EBP
9250 #endif
9252 /* return the PC at frame level 'level'. Return non zero if not found */
9253 static int rt_get_caller_pc(unsigned long *paddr,
9254 ucontext_t *uc, int level)
9256 unsigned long fp;
9257 int i;
9259 if (level == 0) {
9260 #if defined(__FreeBSD__)
9261 *paddr = uc->uc_mcontext.mc_eip;
9262 #elif defined(__dietlibc__)
9263 *paddr = uc->uc_mcontext.eip;
9264 #else
9265 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9266 #endif
9267 return 0;
9268 } else {
9269 #if defined(__FreeBSD__)
9270 fp = uc->uc_mcontext.mc_ebp;
9271 #elif defined(__dietlibc__)
9272 fp = uc->uc_mcontext.ebp;
9273 #else
9274 fp = uc->uc_mcontext.gregs[REG_EBP];
9275 #endif
9276 for(i=1;i<level;i++) {
9277 /* XXX: check address validity with program info */
9278 if (fp <= 0x1000 || fp >= 0xc0000000)
9279 return -1;
9280 fp = ((unsigned long *)fp)[0];
9282 *paddr = ((unsigned long *)fp)[1];
9283 return 0;
9286 #else
9288 #warning add arch specific rt_get_caller_pc()
9290 static int rt_get_caller_pc(unsigned long *paddr,
9291 ucontext_t *uc, int level)
9293 return -1;
9295 #endif
9297 /* emit a run time error at position 'pc' */
9298 void rt_error(ucontext_t *uc, const char *fmt, ...)
9300 va_list ap;
9301 unsigned long pc;
9302 int i;
9304 va_start(ap, fmt);
9305 fprintf(stderr, "Runtime error: ");
9306 vfprintf(stderr, fmt, ap);
9307 fprintf(stderr, "\n");
9308 for(i=0;i<num_callers;i++) {
9309 if (rt_get_caller_pc(&pc, uc, i) < 0)
9310 break;
9311 if (i == 0)
9312 fprintf(stderr, "at ");
9313 else
9314 fprintf(stderr, "by ");
9315 rt_printline(pc);
9317 exit(255);
9318 va_end(ap);
9321 /* signal handler for fatal errors */
9322 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9324 ucontext_t *uc = puc;
9326 switch(signum) {
9327 case SIGFPE:
9328 switch(siginf->si_code) {
9329 case FPE_INTDIV:
9330 case FPE_FLTDIV:
9331 rt_error(uc, "division by zero");
9332 break;
9333 default:
9334 rt_error(uc, "floating point exception");
9335 break;
9337 break;
9338 case SIGBUS:
9339 case SIGSEGV:
9340 if (rt_bound_error_msg && *rt_bound_error_msg)
9341 rt_error(uc, *rt_bound_error_msg);
9342 else
9343 rt_error(uc, "dereferencing invalid pointer");
9344 break;
9345 case SIGILL:
9346 rt_error(uc, "illegal instruction");
9347 break;
9348 case SIGABRT:
9349 rt_error(uc, "abort() called");
9350 break;
9351 default:
9352 rt_error(uc, "caught signal %d", signum);
9353 break;
9355 exit(255);
9357 #endif
9359 /* do all relocations (needed before using tcc_get_symbol()) */
9360 int tcc_relocate(TCCState *s1)
9362 Section *s;
9363 int i;
9365 s1->nb_errors = 0;
9367 tcc_add_runtime(s1);
9369 build_got_entries(s1);
9371 relocate_common_syms();
9373 /* compute relocation address : section are relocated in place. We
9374 also alloc the bss space */
9375 for(i = 1; i < s1->nb_sections; i++) {
9376 s = s1->sections[i];
9377 if (s->sh_flags & SHF_ALLOC) {
9378 if (s->sh_type == SHT_NOBITS)
9379 s->data = tcc_mallocz(s->data_offset);
9380 s->sh_addr = (unsigned long)s->data;
9384 relocate_syms(s1, 1);
9386 if (s1->nb_errors != 0)
9387 return -1;
9389 /* relocate each section */
9390 for(i = 1; i < s1->nb_sections; i++) {
9391 s = s1->sections[i];
9392 if (s->reloc)
9393 relocate_section(s1, s);
9395 return 0;
9398 /* launch the compiled program with the given arguments */
9399 int tcc_run(TCCState *s1, int argc, char **argv)
9401 int (*prog_main)(int, char **);
9403 if (tcc_relocate(s1) < 0)
9404 return -1;
9406 prog_main = tcc_get_symbol_err(s1, "main");
9408 if (do_debug) {
9409 #ifdef WIN32
9410 error("debug mode currently not available for Windows");
9411 #else
9412 struct sigaction sigact;
9413 /* install TCC signal handlers to print debug info on fatal
9414 runtime errors */
9415 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9416 sigact.sa_sigaction = sig_error;
9417 sigemptyset(&sigact.sa_mask);
9418 sigaction(SIGFPE, &sigact, NULL);
9419 sigaction(SIGILL, &sigact, NULL);
9420 sigaction(SIGSEGV, &sigact, NULL);
9421 sigaction(SIGBUS, &sigact, NULL);
9422 sigaction(SIGABRT, &sigact, NULL);
9423 #endif
9426 #ifdef CONFIG_TCC_BCHECK
9427 if (do_bounds_check) {
9428 void (*bound_init)(void);
9430 /* set error function */
9431 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9432 "__bound_error_msg");
9434 /* XXX: use .init section so that it also work in binary ? */
9435 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9436 bound_init();
9438 #endif
9439 return (*prog_main)(argc, argv);
9442 TCCState *tcc_new(void)
9444 const char *p, *r;
9445 TCCState *s;
9446 TokenSym *ts;
9447 int i, c;
9449 s = tcc_mallocz(sizeof(TCCState));
9450 if (!s)
9451 return NULL;
9452 tcc_state = s;
9453 s->output_type = TCC_OUTPUT_MEMORY;
9455 /* init isid table */
9456 for(i=0;i<256;i++)
9457 isidnum_table[i] = isid(i) || isnum(i);
9459 /* add all tokens */
9460 table_ident = NULL;
9461 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9463 tok_ident = TOK_IDENT;
9464 p = tcc_keywords;
9465 while (*p) {
9466 r = p;
9467 for(;;) {
9468 c = *r++;
9469 if (c == '\0')
9470 break;
9472 ts = tok_alloc(p, r - p - 1);
9473 p = r;
9476 /* we add dummy defines for some special macros to speed up tests
9477 and to have working defined() */
9478 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9479 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9480 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9481 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9483 /* standard defines */
9484 tcc_define_symbol(s, "__STDC__", NULL);
9485 #if defined(TCC_TARGET_I386)
9486 tcc_define_symbol(s, "__i386__", NULL);
9487 #endif
9488 #if defined(TCC_TARGET_ARM)
9489 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9490 tcc_define_symbol(s, "__arm_elf__", NULL);
9491 tcc_define_symbol(s, "__arm_elf", NULL);
9492 tcc_define_symbol(s, "arm_elf", NULL);
9493 tcc_define_symbol(s, "__arm__", NULL);
9494 tcc_define_symbol(s, "__arm", NULL);
9495 tcc_define_symbol(s, "arm", NULL);
9496 tcc_define_symbol(s, "__APCS_32__", NULL);
9497 #endif
9498 #if defined(linux)
9499 tcc_define_symbol(s, "__linux__", NULL);
9500 tcc_define_symbol(s, "linux", NULL);
9501 #endif
9502 /* tiny C specific defines */
9503 tcc_define_symbol(s, "__TINYC__", NULL);
9505 /* tiny C & gcc defines */
9506 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9507 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9508 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9510 /* default library paths */
9511 tcc_add_library_path(s, "/usr/local/lib");
9512 tcc_add_library_path(s, "/usr/lib");
9513 tcc_add_library_path(s, "/lib");
9515 /* no section zero */
9516 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9518 /* create standard sections */
9519 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9520 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9521 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9523 /* symbols are always generated for linking stage */
9524 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9525 ".strtab",
9526 ".hashtab", SHF_PRIVATE);
9527 strtab_section = symtab_section->link;
9529 /* private symbol table for dynamic symbols */
9530 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9531 ".dynstrtab",
9532 ".dynhashtab", SHF_PRIVATE);
9533 s->alacarte_link = 1;
9535 #ifdef CHAR_IS_UNSIGNED
9536 s->char_is_unsigned = 1;
9537 #endif
9538 return s;
9541 void tcc_delete(TCCState *s1)
9543 int i, n;
9545 /* free -D defines */
9546 free_defines(NULL);
9548 /* free tokens */
9549 n = tok_ident - TOK_IDENT;
9550 for(i = 0; i < n; i++)
9551 tcc_free(table_ident[i]);
9552 tcc_free(table_ident);
9554 /* free all sections */
9556 free_section(symtab_section->hash);
9558 free_section(s1->dynsymtab_section->hash);
9559 free_section(s1->dynsymtab_section->link);
9560 free_section(s1->dynsymtab_section);
9562 for(i = 1; i < s1->nb_sections; i++)
9563 free_section(s1->sections[i]);
9564 tcc_free(s1->sections);
9566 /* free loaded dlls array */
9567 for(i = 0; i < s1->nb_loaded_dlls; i++)
9568 tcc_free(s1->loaded_dlls[i]);
9569 tcc_free(s1->loaded_dlls);
9571 /* library paths */
9572 for(i = 0; i < s1->nb_library_paths; i++)
9573 tcc_free(s1->library_paths[i]);
9574 tcc_free(s1->library_paths);
9576 /* cached includes */
9577 for(i = 0; i < s1->nb_cached_includes; i++)
9578 tcc_free(s1->cached_includes[i]);
9579 tcc_free(s1->cached_includes);
9581 for(i = 0; i < s1->nb_include_paths; i++)
9582 tcc_free(s1->include_paths[i]);
9583 tcc_free(s1->include_paths);
9585 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9586 tcc_free(s1->sysinclude_paths[i]);
9587 tcc_free(s1->sysinclude_paths);
9589 tcc_free(s1);
9592 int tcc_add_include_path(TCCState *s1, const char *pathname)
9594 char *pathname1;
9596 pathname1 = tcc_strdup(pathname);
9597 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9598 return 0;
9601 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9603 char *pathname1;
9605 pathname1 = tcc_strdup(pathname);
9606 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9607 return 0;
9610 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9612 const char *ext, *filename1;
9613 Elf32_Ehdr ehdr;
9614 int fd, ret;
9615 BufferedFile *saved_file;
9617 /* find source file type with extension */
9618 filename1 = strrchr(filename, '/');
9619 if (filename1)
9620 filename1++;
9621 else
9622 filename1 = filename;
9623 ext = strrchr(filename1, '.');
9624 if (ext)
9625 ext++;
9627 /* open the file */
9628 saved_file = file;
9629 file = tcc_open(s1, filename);
9630 if (!file) {
9631 if (flags & AFF_PRINT_ERROR) {
9632 error_noabort("file '%s' not found", filename);
9634 ret = -1;
9635 goto fail1;
9638 if (!ext || !strcmp(ext, "c")) {
9639 /* C file assumed */
9640 ret = tcc_compile(s1);
9641 } else
9642 #ifdef CONFIG_TCC_ASM
9643 if (!strcmp(ext, "S")) {
9644 /* preprocessed assembler */
9645 ret = tcc_assemble(s1, 1);
9646 } else if (!strcmp(ext, "s")) {
9647 /* non preprocessed assembler */
9648 ret = tcc_assemble(s1, 0);
9649 } else
9650 #endif
9652 fd = file->fd;
9653 /* assume executable format: auto guess file type */
9654 ret = read(fd, &ehdr, sizeof(ehdr));
9655 lseek(fd, 0, SEEK_SET);
9656 if (ret <= 0) {
9657 error_noabort("could not read header");
9658 goto fail;
9659 } else if (ret != sizeof(ehdr)) {
9660 goto try_load_script;
9663 if (ehdr.e_ident[0] == ELFMAG0 &&
9664 ehdr.e_ident[1] == ELFMAG1 &&
9665 ehdr.e_ident[2] == ELFMAG2 &&
9666 ehdr.e_ident[3] == ELFMAG3) {
9667 file->line_num = 0; /* do not display line number if error */
9668 if (ehdr.e_type == ET_REL) {
9669 ret = tcc_load_object_file(s1, fd, 0);
9670 } else if (ehdr.e_type == ET_DYN) {
9671 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9672 void *h;
9673 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9674 if (h)
9675 ret = 0;
9676 else
9677 ret = -1;
9678 } else {
9679 ret = tcc_load_dll(s1, fd, filename,
9680 (flags & AFF_REFERENCED_DLL) != 0);
9682 } else {
9683 error_noabort("unrecognized ELF file");
9684 goto fail;
9686 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9687 file->line_num = 0; /* do not display line number if error */
9688 ret = tcc_load_archive(s1, fd);
9689 } else
9690 #ifdef TCC_TARGET_COFF
9691 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
9692 ret = tcc_load_coff(s1, fd);
9693 } else
9694 #endif
9696 /* as GNU ld, consider it is an ld script if not recognized */
9697 try_load_script:
9698 ret = tcc_load_ldscript(s1);
9699 if (ret < 0) {
9700 error_noabort("unrecognized file type");
9701 goto fail;
9705 the_end:
9706 tcc_close(file);
9707 fail1:
9708 file = saved_file;
9709 return ret;
9710 fail:
9711 ret = -1;
9712 goto the_end;
9715 int tcc_add_file(TCCState *s, const char *filename)
9717 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9720 int tcc_add_library_path(TCCState *s, const char *pathname)
9722 char *pathname1;
9724 pathname1 = tcc_strdup(pathname);
9725 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9726 return 0;
9729 /* find and load a dll. Return non zero if not found */
9730 /* XXX: add '-rpath' option support ? */
9731 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9733 char buf[1024];
9734 int i;
9736 for(i = 0; i < s->nb_library_paths; i++) {
9737 snprintf(buf, sizeof(buf), "%s/%s",
9738 s->library_paths[i], filename);
9739 if (tcc_add_file_internal(s, buf, flags) == 0)
9740 return 0;
9742 return -1;
9745 /* the library name is the same as the argument of the '-l' option */
9746 int tcc_add_library(TCCState *s, const char *libraryname)
9748 char buf[1024];
9749 int i;
9751 /* first we look for the dynamic library if not static linking */
9752 if (!s->static_link) {
9753 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9754 if (tcc_add_dll(s, buf, 0) == 0)
9755 return 0;
9758 /* then we look for the static library */
9759 for(i = 0; i < s->nb_library_paths; i++) {
9760 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9761 s->library_paths[i], libraryname);
9762 if (tcc_add_file_internal(s, buf, 0) == 0)
9763 return 0;
9765 return -1;
9768 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9770 add_elf_sym(symtab_section, val, 0,
9771 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9772 SHN_ABS, name);
9773 return 0;
9776 int tcc_set_output_type(TCCState *s, int output_type)
9778 char buf[1024];
9780 s->output_type = output_type;
9782 if (!s->nostdinc) {
9783 /* default include paths */
9784 /* XXX: reverse order needed if -isystem support */
9785 tcc_add_sysinclude_path(s, "/usr/local/include");
9786 tcc_add_sysinclude_path(s, "/usr/include");
9787 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9788 tcc_add_sysinclude_path(s, buf);
9791 /* if bound checking, then add corresponding sections */
9792 #ifdef CONFIG_TCC_BCHECK
9793 if (do_bounds_check) {
9794 /* define symbol */
9795 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9796 /* create bounds sections */
9797 bounds_section = new_section(s, ".bounds",
9798 SHT_PROGBITS, SHF_ALLOC);
9799 lbounds_section = new_section(s, ".lbounds",
9800 SHT_PROGBITS, SHF_ALLOC);
9802 #endif
9804 if (s->char_is_unsigned) {
9805 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
9808 /* add debug sections */
9809 if (do_debug) {
9810 /* stab symbols */
9811 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9812 stab_section->sh_entsize = sizeof(Stab_Sym);
9813 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9814 put_elf_str(stabstr_section, "");
9815 stab_section->link = stabstr_section;
9816 /* put first entry */
9817 put_stabs("", 0, 0, 0, 0);
9820 /* add libc crt1/crti objects */
9821 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9822 !s->nostdlib) {
9823 if (output_type != TCC_OUTPUT_DLL)
9824 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9825 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9827 return 0;
9830 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9831 #define FD_INVERT 0x0002 /* invert value before storing */
9833 typedef struct FlagDef {
9834 uint16_t offset;
9835 uint16_t flags;
9836 const char *name;
9837 } FlagDef;
9839 static const FlagDef warning_defs[] = {
9840 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9841 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9842 { offsetof(TCCState, warn_error), 0, "error" },
9843 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
9844 "implicit-function-declaration" },
9847 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
9848 const char *name, int value)
9850 int i;
9851 const FlagDef *p;
9852 const char *r;
9854 r = name;
9855 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
9856 r += 3;
9857 value = !value;
9859 for(i = 0, p = flags; i < nb_flags; i++, p++) {
9860 if (!strcmp(r, p->name))
9861 goto found;
9863 return -1;
9864 found:
9865 if (p->flags & FD_INVERT)
9866 value = !value;
9867 *(int *)((uint8_t *)s + p->offset) = value;
9868 return 0;
9872 /* set/reset a warning */
9873 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9875 int i;
9876 const FlagDef *p;
9878 if (!strcmp(warning_name, "all")) {
9879 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9880 if (p->flags & WD_ALL)
9881 *(int *)((uint8_t *)s + p->offset) = 1;
9883 return 0;
9884 } else {
9885 return set_flag(s, warning_defs, countof(warning_defs),
9886 warning_name, value);
9890 static const FlagDef flag_defs[] = {
9891 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
9892 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
9893 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
9896 /* set/reset a flag */
9897 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
9899 return set_flag(s, flag_defs, countof(flag_defs),
9900 flag_name, value);
9903 #if !defined(LIBTCC)
9905 /* extract the basename of a file */
9906 static const char *tcc_basename(const char *name)
9908 const char *p;
9909 p = strrchr(name, '/');
9910 #ifdef WIN32
9911 if (!p)
9912 p = strrchr(name, '\\');
9913 #endif
9914 if (!p)
9915 p = name;
9916 else
9917 p++;
9918 return p;
9921 static int64_t getclock_us(void)
9923 #ifdef WIN32
9924 struct _timeb tb;
9925 _ftime(&tb);
9926 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9927 #else
9928 struct timeval tv;
9929 gettimeofday(&tv, NULL);
9930 return tv.tv_sec * 1000000LL + tv.tv_usec;
9931 #endif
9934 void help(void)
9936 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2003 Fabrice Bellard\n"
9937 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9938 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9939 " [infile1 infile2...] [-run infile args...]\n"
9940 "\n"
9941 "General options:\n"
9942 " -v display current version\n"
9943 " -c compile only - generate an object file\n"
9944 " -o outfile set output filename\n"
9945 " -Bdir set tcc internal library path\n"
9946 " -bench output compilation statistics\n"
9947 " -run run compiled source\n"
9948 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
9949 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
9950 " -w disable all warnings\n"
9951 "Preprocessor options:\n"
9952 " -Idir add include path 'dir'\n"
9953 " -Dsym[=val] define 'sym' with value 'val'\n"
9954 " -Usym undefine 'sym'\n"
9955 "Linker options:\n"
9956 " -Ldir add library path 'dir'\n"
9957 " -llib link with dynamic or static library 'lib'\n"
9958 " -shared generate a shared library\n"
9959 " -static static linking\n"
9960 " -rdynamic export all global symbols to dynamic linker\n"
9961 " -r relocatable output\n"
9962 "Debugger options:\n"
9963 " -g generate runtime debug info\n"
9964 #ifdef CONFIG_TCC_BCHECK
9965 " -b compile with built-in memory and bounds checker (implies -g)\n"
9966 #endif
9967 " -bt N show N callers in stack traces\n"
9971 #define TCC_OPTION_HAS_ARG 0x0001
9972 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9974 typedef struct TCCOption {
9975 const char *name;
9976 uint16_t index;
9977 uint16_t flags;
9978 } TCCOption;
9980 enum {
9981 TCC_OPTION_HELP,
9982 TCC_OPTION_I,
9983 TCC_OPTION_D,
9984 TCC_OPTION_U,
9985 TCC_OPTION_L,
9986 TCC_OPTION_B,
9987 TCC_OPTION_l,
9988 TCC_OPTION_bench,
9989 TCC_OPTION_bt,
9990 TCC_OPTION_b,
9991 TCC_OPTION_g,
9992 TCC_OPTION_c,
9993 TCC_OPTION_static,
9994 TCC_OPTION_shared,
9995 TCC_OPTION_o,
9996 TCC_OPTION_r,
9997 TCC_OPTION_Wl,
9998 TCC_OPTION_W,
9999 TCC_OPTION_O,
10000 TCC_OPTION_m,
10001 TCC_OPTION_f,
10002 TCC_OPTION_nostdinc,
10003 TCC_OPTION_nostdlib,
10004 TCC_OPTION_print_search_dirs,
10005 TCC_OPTION_rdynamic,
10006 TCC_OPTION_run,
10007 TCC_OPTION_v,
10008 TCC_OPTION_w,
10011 static const TCCOption tcc_options[] = {
10012 { "h", TCC_OPTION_HELP, 0 },
10013 { "?", TCC_OPTION_HELP, 0 },
10014 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10015 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10016 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10017 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10018 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10019 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10020 { "bench", TCC_OPTION_bench, 0 },
10021 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10022 #ifdef CONFIG_TCC_BCHECK
10023 { "b", TCC_OPTION_b, 0 },
10024 #endif
10025 { "g", TCC_OPTION_g, 0 },
10026 { "c", TCC_OPTION_c, 0 },
10027 { "static", TCC_OPTION_static, 0 },
10028 { "shared", TCC_OPTION_shared, 0 },
10029 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10030 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10031 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10032 { "r", TCC_OPTION_r, 0 },
10033 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10034 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10035 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10036 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10037 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10038 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10039 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10040 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10041 { "v", TCC_OPTION_v, 0 },
10042 { "w", TCC_OPTION_w, 0 },
10043 { NULL },
10046 /* convert 'str' into an array of space separated strings */
10047 static int expand_args(char ***pargv, const char *str)
10049 const char *s1;
10050 char **argv, *arg;
10051 int argc, len;
10053 argc = 0;
10054 argv = NULL;
10055 for(;;) {
10056 while (is_space(*str))
10057 str++;
10058 if (*str == '\0')
10059 break;
10060 s1 = str;
10061 while (*str != '\0' && !is_space(*str))
10062 str++;
10063 len = str - s1;
10064 arg = tcc_malloc(len + 1);
10065 memcpy(arg, s1, len);
10066 arg[len] = '\0';
10067 dynarray_add((void ***)&argv, &argc, arg);
10069 *pargv = argv;
10070 return argc;
10073 static char **files;
10074 static int nb_files, nb_libraries;
10075 static int multiple_files;
10076 static int print_search_dirs;
10077 static int output_type;
10078 static int reloc_output;
10079 static const char *outfile;
10081 int parse_args(TCCState *s, int argc, char **argv)
10083 int optind;
10084 const TCCOption *popt;
10085 const char *optarg, *p1, *r1;
10086 char *r;
10088 optind = 0;
10089 while (1) {
10090 if (optind >= argc) {
10091 if (nb_files == 0 && !print_search_dirs)
10092 goto show_help;
10093 else
10094 break;
10096 r = argv[optind++];
10097 if (r[0] != '-') {
10098 /* add a new file */
10099 dynarray_add((void ***)&files, &nb_files, r);
10100 if (!multiple_files) {
10101 optind--;
10102 /* argv[0] will be this file */
10103 break;
10105 } else {
10106 /* find option in table (match only the first chars */
10107 popt = tcc_options;
10108 for(;;) {
10109 p1 = popt->name;
10110 if (p1 == NULL)
10111 error("invalid option -- '%s'", r);
10112 r1 = r + 1;
10113 for(;;) {
10114 if (*p1 == '\0')
10115 goto option_found;
10116 if (*r1 != *p1)
10117 break;
10118 p1++;
10119 r1++;
10121 popt++;
10123 option_found:
10124 if (popt->flags & TCC_OPTION_HAS_ARG) {
10125 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10126 optarg = r1;
10127 } else {
10128 if (optind >= argc)
10129 error("argument to '%s' is missing", r);
10130 optarg = argv[optind++];
10132 } else {
10133 if (*r1 != '\0')
10134 goto show_help;
10135 optarg = NULL;
10138 switch(popt->index) {
10139 case TCC_OPTION_HELP:
10140 show_help:
10141 help();
10142 exit(1);
10143 case TCC_OPTION_I:
10144 if (tcc_add_include_path(s, optarg) < 0)
10145 error("too many include paths");
10146 break;
10147 case TCC_OPTION_D:
10149 char *sym, *value;
10150 sym = (char *)optarg;
10151 value = strchr(sym, '=');
10152 if (value) {
10153 *value = '\0';
10154 value++;
10156 tcc_define_symbol(s, sym, value);
10158 break;
10159 case TCC_OPTION_U:
10160 tcc_undefine_symbol(s, optarg);
10161 break;
10162 case TCC_OPTION_L:
10163 tcc_add_library_path(s, optarg);
10164 break;
10165 case TCC_OPTION_B:
10166 /* set tcc utilities path (mainly for tcc development) */
10167 tcc_lib_path = optarg;
10168 break;
10169 case TCC_OPTION_l:
10170 dynarray_add((void ***)&files, &nb_files, r);
10171 nb_libraries++;
10172 break;
10173 case TCC_OPTION_bench:
10174 do_bench = 1;
10175 break;
10176 case TCC_OPTION_bt:
10177 num_callers = atoi(optarg);
10178 break;
10179 #ifdef CONFIG_TCC_BCHECK
10180 case TCC_OPTION_b:
10181 do_bounds_check = 1;
10182 do_debug = 1;
10183 break;
10184 #endif
10185 case TCC_OPTION_g:
10186 do_debug = 1;
10187 break;
10188 case TCC_OPTION_c:
10189 multiple_files = 1;
10190 output_type = TCC_OUTPUT_OBJ;
10191 break;
10192 case TCC_OPTION_static:
10193 s->static_link = 1;
10194 break;
10195 case TCC_OPTION_shared:
10196 output_type = TCC_OUTPUT_DLL;
10197 break;
10198 case TCC_OPTION_o:
10199 multiple_files = 1;
10200 outfile = optarg;
10201 break;
10202 case TCC_OPTION_r:
10203 /* generate a .o merging several output files */
10204 reloc_output = 1;
10205 output_type = TCC_OUTPUT_OBJ;
10206 break;
10207 case TCC_OPTION_nostdinc:
10208 s->nostdinc = 1;
10209 break;
10210 case TCC_OPTION_nostdlib:
10211 s->nostdlib = 1;
10212 break;
10213 case TCC_OPTION_print_search_dirs:
10214 print_search_dirs = 1;
10215 break;
10216 case TCC_OPTION_run:
10218 int argc1;
10219 char **argv1;
10220 argc1 = expand_args(&argv1, optarg);
10221 if (argc1 > 0) {
10222 parse_args(s, argc1, argv1);
10224 multiple_files = 0;
10225 output_type = TCC_OUTPUT_MEMORY;
10227 break;
10228 case TCC_OPTION_v:
10229 printf("tcc version %s\n", TCC_VERSION);
10230 exit(0);
10231 case TCC_OPTION_f:
10232 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10233 goto unsupported_option;
10234 break;
10235 case TCC_OPTION_W:
10236 if (tcc_set_warning(s, optarg, 1) < 0 &&
10237 s->warn_unsupported)
10238 goto unsupported_option;
10239 break;
10240 case TCC_OPTION_w:
10241 s->warn_none = 1;
10242 break;
10243 case TCC_OPTION_rdynamic:
10244 s->rdynamic = 1;
10245 break;
10246 case TCC_OPTION_Wl:
10248 const char *p;
10249 if (strstart(optarg, "-Ttext,", &p)) {
10250 s->text_addr = strtoul(p, NULL, 16);
10251 s->has_text_addr = 1;
10252 } else {
10253 error("unsupported ld option '%s'", optarg);
10256 break;
10257 default:
10258 if (s->warn_unsupported) {
10259 unsupported_option:
10260 warning("unsupported option '%s'", r);
10262 break;
10266 return optind;
10269 int main(int argc, char **argv)
10271 int i;
10272 TCCState *s;
10273 int nb_objfiles, ret, optind;
10274 char objfilename[1024];
10275 int64_t start_time = 0;
10277 s = tcc_new();
10278 output_type = TCC_OUTPUT_EXE;
10279 outfile = NULL;
10280 multiple_files = 1;
10281 files = NULL;
10282 nb_files = 0;
10283 nb_libraries = 0;
10284 reloc_output = 0;
10285 print_search_dirs = 0;
10287 optind = parse_args(s, argc - 1, argv + 1) + 1;
10289 if (print_search_dirs) {
10290 /* enough for Linux kernel */
10291 printf("install: %s/\n", tcc_lib_path);
10292 return 0;
10295 nb_objfiles = nb_files - nb_libraries;
10297 /* if outfile provided without other options, we output an
10298 executable */
10299 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10300 output_type = TCC_OUTPUT_EXE;
10302 /* check -c consistency : only single file handled. XXX: checks file type */
10303 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10304 /* accepts only a single input file */
10305 if (nb_objfiles != 1)
10306 error("cannot specify multiple files with -c");
10307 if (nb_libraries != 0)
10308 error("cannot specify libraries with -c");
10311 /* compute default outfile name */
10312 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
10313 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10314 char *ext;
10315 /* strip path */
10316 pstrcpy(objfilename, sizeof(objfilename) - 1,
10317 tcc_basename(files[0]));
10318 /* add .o extension */
10319 ext = strrchr(objfilename, '.');
10320 if (!ext)
10321 goto default_outfile;
10322 strcpy(ext + 1, "o");
10323 } else {
10324 default_outfile:
10325 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10327 outfile = objfilename;
10330 if (do_bench) {
10331 start_time = getclock_us();
10334 tcc_set_output_type(s, output_type);
10336 /* compile or add each files or library */
10337 for(i = 0;i < nb_files; i++) {
10338 const char *filename;
10340 filename = files[i];
10341 if (filename[0] == '-') {
10342 if (tcc_add_library(s, filename + 2) < 0)
10343 error("cannot find %s", filename);
10344 } else {
10345 if (tcc_add_file(s, filename) < 0) {
10346 ret = 1;
10347 goto the_end;
10352 /* free all files */
10353 tcc_free(files);
10355 if (do_bench) {
10356 double total_time;
10357 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10358 if (total_time < 0.001)
10359 total_time = 0.001;
10360 if (total_bytes < 1)
10361 total_bytes = 1;
10362 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10363 tok_ident - TOK_IDENT, total_lines, total_bytes,
10364 total_time, (int)(total_lines / total_time),
10365 total_bytes / total_time / 1000000.0);
10368 if (s->output_type != TCC_OUTPUT_MEMORY) {
10369 tcc_output_file(s, outfile);
10370 ret = 0;
10371 } else {
10372 ret = tcc_run(s, argc - optind, argv + optind);
10374 the_end:
10375 /* XXX: cannot do it with bound checking because of the malloc hooks */
10376 if (!do_bounds_check)
10377 tcc_delete(s);
10379 #ifdef MEM_DEBUG
10380 if (do_bench) {
10381 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10383 #endif
10384 return ret;
10387 #endif