initial TMS320C67xx support (TK)
[tinycc.git] / tcc.c
blob3b7c58a7186c5bf0dc836132c64d72ace2d501b5
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define _GNU_SOURCE
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <math.h>
29 #include <unistd.h>
30 #include <signal.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <setjmp.h>
34 #include <time.h>
35 #ifdef WIN32
36 #include <sys/timeb.h>
37 #endif
38 #ifndef WIN32
39 #include <sys/time.h>
40 #include <sys/ucontext.h>
41 #endif
42 #include "elf.h"
43 #include "stab.h"
44 #ifndef CONFIG_TCC_STATIC
45 #include <dlfcn.h>
46 #endif
48 #include "libtcc.h"
50 /* parser debug */
51 //#define PARSE_DEBUG
52 /* preprocessor debug */
53 //#define PP_DEBUG
54 /* include file debug */
55 //#define INC_DEBUG
57 //#define MEM_DEBUG
59 /* assembler debug */
60 //#define ASM_DEBUG
62 /* target selection */
63 //#define TCC_TARGET_I386 /* i386 code generator */
64 //#define TCC_TARGET_ARM /* ARMv4 code generator */
65 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
67 /* default target is I386 */
68 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
69 !defined(TCC_TARGET_C67)
70 #define TCC_TARGET_I386
71 #endif
73 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
74 !defined(TCC_TARGET_C67)
75 #define CONFIG_TCC_BCHECK /* enable bound checking code */
76 #endif
78 /* define it to include assembler support */
79 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
80 #define CONFIG_TCC_ASM
81 #endif
83 #if !defined(WIN32)
84 #define FALSE 0
85 #define false 0
86 #define TRUE 1
87 #define true 1
88 typedef int BOOL;
89 #endif
91 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
92 executables or dlls */
93 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
95 #define INCLUDE_STACK_SIZE 32
96 #define IFDEF_STACK_SIZE 64
97 #define VSTACK_SIZE 64
98 #define STRING_MAX_SIZE 1024
100 #define TOK_HASH_SIZE 2048 /* must be a power of two */
101 #define TOK_ALLOC_INCR 512 /* must be a power of two */
102 #define TOK_STR_ALLOC_INCR_BITS 6
103 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
104 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
106 /* token symbol management */
107 typedef struct TokenSym {
108 struct TokenSym *hash_next;
109 struct Sym *sym_define; /* direct pointer to define */
110 struct Sym *sym_label; /* direct pointer to label */
111 struct Sym *sym_struct; /* direct pointer to structure */
112 struct Sym *sym_identifier; /* direct pointer to identifier */
113 int tok; /* token number */
114 int len;
115 char str[1];
116 } TokenSym;
118 typedef struct CString {
119 int size; /* size in bytes */
120 void *data; /* either 'char *' or 'int *' */
121 int size_allocated;
122 void *data_allocated; /* if non NULL, data has been malloced */
123 } CString;
125 /* type definition */
126 typedef struct CType {
127 int t;
128 struct Sym *ref;
129 } CType;
131 /* constant value */
132 typedef union CValue {
133 long double ld;
134 double d;
135 float f;
136 int i;
137 unsigned int ui;
138 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
139 long long ll;
140 unsigned long long ull;
141 struct CString *cstr;
142 void *ptr;
143 int tab[1];
144 } CValue;
146 /* value on stack */
147 typedef struct SValue {
148 CType type; /* type */
149 unsigned short r; /* register + flags */
150 unsigned short r2; /* second register, used for 'long long'
151 type. If not used, set to VT_CONST */
152 CValue c; /* constant, if VT_CONST */
153 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
154 } SValue;
156 /* symbol management */
157 typedef struct Sym {
158 int v; /* symbol token */
159 int r; /* associated register */
160 int c; /* associated number */
161 CType type; /* associated type */
162 struct Sym *next; /* next related symbol */
163 struct Sym *prev; /* prev symbol in stack */
164 struct Sym *prev_tok; /* previous symbol for this token */
165 } Sym;
167 /* section definition */
168 /* XXX: use directly ELF structure for parameters ? */
169 /* special flag to indicate that the section should not be linked to
170 the other ones */
171 #define SHF_PRIVATE 0x80000000
173 typedef struct Section {
174 unsigned long data_offset; /* current data offset */
175 unsigned char *data; /* section data */
176 unsigned long data_allocated; /* used for realloc() handling */
177 int sh_name; /* elf section name (only used during output) */
178 int sh_num; /* elf section number */
179 int sh_type; /* elf section type */
180 int sh_flags; /* elf section flags */
181 int sh_info; /* elf section info */
182 int sh_addralign; /* elf section alignment */
183 int sh_entsize; /* elf entry size */
184 unsigned long sh_size; /* section size (only used during output) */
185 unsigned long sh_addr; /* address at which the section is relocated */
186 unsigned long sh_offset; /* address at which the section is relocated */
187 int nb_hashed_syms; /* used to resize the hash table */
188 struct Section *link; /* link to another section */
189 struct Section *reloc; /* corresponding section for relocation, if any */
190 struct Section *hash; /* hash table for symbols */
191 struct Section *next;
192 char name[1]; /* section name */
193 } Section;
195 typedef struct DLLReference {
196 int level;
197 char name[1];
198 } DLLReference;
200 /* GNUC attribute definition */
201 typedef struct AttributeDef {
202 int aligned;
203 Section *section;
204 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
205 } AttributeDef;
207 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
208 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
209 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
211 /* stored in 'Sym.c' field */
212 #define FUNC_NEW 1 /* ansi function prototype */
213 #define FUNC_OLD 2 /* old function prototype */
214 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
216 /* stored in 'Sym.r' field */
217 #define FUNC_CDECL 0 /* standard c call */
218 #define FUNC_STDCALL 1 /* pascal c call */
220 /* field 'Sym.t' for macros */
221 #define MACRO_OBJ 0 /* object like macro */
222 #define MACRO_FUNC 1 /* function like macro */
224 /* field 'Sym.r' for C labels */
225 #define LABEL_DEFINED 0 /* label is defined */
226 #define LABEL_FORWARD 1 /* label is forward defined */
227 #define LABEL_DECLARED 2 /* label is declared but never used */
229 /* type_decl() types */
230 #define TYPE_ABSTRACT 1 /* type without variable */
231 #define TYPE_DIRECT 2 /* type with variable */
233 #define IO_BUF_SIZE 8192
235 typedef struct BufferedFile {
236 uint8_t *buf_ptr;
237 uint8_t *buf_end;
238 int fd;
239 int line_num; /* current line number - here to simplify code */
240 int ifndef_macro; /* #ifndef macro / #endif search */
241 int ifndef_macro_saved; /* saved ifndef_macro */
242 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
243 char inc_type; /* type of include */
244 char inc_filename[512]; /* filename specified by the user */
245 char filename[1024]; /* current filename - here to simplify code */
246 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
247 } BufferedFile;
249 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
250 #define CH_EOF (-1) /* end of file */
252 /* parsing state (used to save parser state to reparse part of the
253 source several times) */
254 typedef struct ParseState {
255 int *macro_ptr;
256 int line_num;
257 int tok;
258 CValue tokc;
259 } ParseState;
261 /* used to record tokens */
262 typedef struct TokenString {
263 int *str;
264 int len;
265 int allocated_len;
266 int last_line_num;
267 } TokenString;
269 /* include file cache, used to find files faster and also to eliminate
270 inclusion if the include file is protected by #ifndef ... #endif */
271 typedef struct CachedInclude {
272 int ifndef_macro;
273 char type; /* '"' or '>' to give include type */
274 char filename[1]; /* path specified in #include */
275 } CachedInclude;
277 /* parser */
278 static struct BufferedFile *file;
279 static int ch, tok;
280 static CValue tokc;
281 static CString tokcstr; /* current parsed string, if any */
282 /* additional informations about token */
283 static int tok_flags;
284 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
285 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
286 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
288 static int *macro_ptr, *macro_ptr_allocated;
289 static int *unget_saved_macro_ptr;
290 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
291 static int unget_buffer_enabled;
292 static int parse_flags;
293 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
294 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
295 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
296 token. line feed is also
297 returned at eof */
299 static Section *text_section, *data_section, *bss_section; /* predefined sections */
300 static Section *cur_text_section; /* current section where function code is
301 generated */
302 /* bound check related sections */
303 static Section *bounds_section; /* contains global data bound description */
304 static Section *lbounds_section; /* contains local data bound description */
305 /* symbol sections */
306 static Section *symtab_section, *strtab_section;
308 /* debug sections */
309 static Section *stab_section, *stabstr_section;
311 /* loc : local variable index
312 ind : output code index
313 rsym: return symbol
314 anon_sym: anonymous symbol index
316 static int rsym, anon_sym, ind, loc;
317 /* expression generation modifiers */
318 static int const_wanted; /* true if constant wanted */
319 static int nocode_wanted; /* true if no code generation wanted for an expression */
320 static int global_expr; /* true if compound literals must be allocated
321 globally (used during initializers parsing */
322 static CType func_vt; /* current function return type (used by return
323 instruction) */
324 static int func_vc;
325 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
326 static int tok_ident;
327 static TokenSym **table_ident;
328 static TokenSym *hash_ident[TOK_HASH_SIZE];
329 static char token_buf[STRING_MAX_SIZE + 1];
330 static char *funcname;
331 static Sym *global_stack, *local_stack;
332 static Sym *define_stack;
333 static Sym *global_label_stack, *local_label_stack;
335 static SValue vstack[VSTACK_SIZE], *vtop;
336 /* some predefined types */
337 static CType char_pointer_type, func_old_type, int_type;
338 /* true if isid(c) || isnum(c) */
339 static unsigned char isidnum_table[256];
341 /* compile with debug symbol (and use them if error during execution) */
342 static int do_debug = 0;
344 /* compile with built-in memory and bounds checker */
345 static int do_bounds_check = 0;
347 /* display benchmark infos */
348 #if !defined(LIBTCC)
349 static int do_bench = 0;
350 #endif
351 static int total_lines;
352 static int total_bytes;
354 /* use GNU C extensions */
355 static int gnu_ext = 1;
357 /* use Tiny C extensions */
358 static int tcc_ext = 1;
360 /* max number of callers shown if error */
361 static int num_callers = 6;
362 static const char **rt_bound_error_msg;
364 /* XXX: get rid of this ASAP */
365 static struct TCCState *tcc_state;
367 /* give the path of the tcc libraries */
368 static const char *tcc_lib_path = CONFIG_TCC_LIBDIR "/tcc";
370 struct TCCState {
371 int output_type;
373 BufferedFile **include_stack_ptr;
374 int *ifdef_stack_ptr;
376 /* include file handling */
377 char **include_paths;
378 int nb_include_paths;
379 char **sysinclude_paths;
380 int nb_sysinclude_paths;
381 CachedInclude **cached_includes;
382 int nb_cached_includes;
384 char **library_paths;
385 int nb_library_paths;
387 /* array of all loaded dlls (including those referenced by loaded
388 dlls) */
389 DLLReference **loaded_dlls;
390 int nb_loaded_dlls;
392 /* sections */
393 Section **sections;
394 int nb_sections; /* number of sections, including first dummy section */
396 /* got handling */
397 Section *got;
398 Section *plt;
399 unsigned long *got_offsets;
400 int nb_got_offsets;
401 /* give the correspondance from symtab indexes to dynsym indexes */
402 int *symtab_to_dynsym;
404 /* temporary dynamic symbol sections (for dll loading) */
405 Section *dynsymtab_section;
406 /* exported dynamic symbol section */
407 Section *dynsym;
409 int nostdinc; /* if true, no standard headers are added */
410 int nostdlib; /* if true, no standard libraries are added */
412 /* if true, static linking is performed */
413 int static_link;
415 /* if true, all symbols are exported */
416 int rdynamic;
418 /* if true, only link in referenced objects from archive */
419 int alacarte_link;
421 /* C language options */
422 int char_is_unsigned;
424 /* warning switches */
425 int warn_write_strings;
426 int warn_unsupported;
427 int warn_error;
428 int warn_none;
429 int warn_implicit_function_declaration;
431 /* error handling */
432 void *error_opaque;
433 void (*error_func)(void *opaque, const char *msg);
434 int error_set_jmp_enabled;
435 jmp_buf error_jmp_buf;
436 int nb_errors;
438 /* tiny assembler state */
439 Sym *asm_labels;
441 /* see include_stack_ptr */
442 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
444 /* see ifdef_stack_ptr */
445 int ifdef_stack[IFDEF_STACK_SIZE];
448 /* The current value can be: */
449 #define VT_VALMASK 0x00ff
450 #define VT_CONST 0x00f0 /* constant in vc
451 (must be first non register value) */
452 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
453 #define VT_LOCAL 0x00f2 /* offset on stack */
454 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
455 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
456 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
457 #define VT_LVAL 0x0100 /* var is an lvalue */
458 #define VT_SYM 0x0200 /* a symbol value is added */
459 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
460 char/short stored in integer registers) */
461 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
462 dereferencing value */
463 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
464 bounding function call point is in vc */
465 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
466 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
467 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
468 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
470 /* types */
471 #define VT_INT 0 /* integer type */
472 #define VT_BYTE 1 /* signed byte type */
473 #define VT_SHORT 2 /* short type */
474 #define VT_VOID 3 /* void type */
475 #define VT_PTR 4 /* pointer */
476 #define VT_ENUM 5 /* enum definition */
477 #define VT_FUNC 6 /* function type */
478 #define VT_STRUCT 7 /* struct/union definition */
479 #define VT_FLOAT 8 /* IEEE float */
480 #define VT_DOUBLE 9 /* IEEE double */
481 #define VT_LDOUBLE 10 /* IEEE long double */
482 #define VT_BOOL 11 /* ISOC99 boolean type */
483 #define VT_LLONG 12 /* 64 bit integer */
484 #define VT_LONG 13 /* long integer (NEVER USED as type, only
485 during parsing) */
486 #define VT_BTYPE 0x000f /* mask for basic type */
487 #define VT_UNSIGNED 0x0010 /* unsigned type */
488 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
489 #define VT_BITFIELD 0x0040 /* bitfield modifier */
490 #define VT_CONSTANT 0x0800 /* const modifier */
491 #define VT_VOLATILE 0x1000 /* volatile modifier */
492 #define VT_SIGNED 0x2000 /* signed type */
494 /* storage */
495 #define VT_EXTERN 0x00000080 /* extern definition */
496 #define VT_STATIC 0x00000100 /* static variable */
497 #define VT_TYPEDEF 0x00000200 /* typedef definition */
498 #define VT_INLINE 0x00000400 /* inline definition */
500 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
502 /* type mask (except storage) */
503 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
504 #define VT_TYPE (~(VT_STORAGE))
506 /* token values */
508 /* warning: the following compare tokens depend on i386 asm code */
509 #define TOK_ULT 0x92
510 #define TOK_UGE 0x93
511 #define TOK_EQ 0x94
512 #define TOK_NE 0x95
513 #define TOK_ULE 0x96
514 #define TOK_UGT 0x97
515 #define TOK_LT 0x9c
516 #define TOK_GE 0x9d
517 #define TOK_LE 0x9e
518 #define TOK_GT 0x9f
520 #define TOK_LAND 0xa0
521 #define TOK_LOR 0xa1
523 #define TOK_DEC 0xa2
524 #define TOK_MID 0xa3 /* inc/dec, to void constant */
525 #define TOK_INC 0xa4
526 #define TOK_UDIV 0xb0 /* unsigned division */
527 #define TOK_UMOD 0xb1 /* unsigned modulo */
528 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
529 #define TOK_CINT 0xb3 /* number in tokc */
530 #define TOK_CCHAR 0xb4 /* char constant in tokc */
531 #define TOK_STR 0xb5 /* pointer to string in tokc */
532 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
533 #define TOK_LCHAR 0xb7
534 #define TOK_LSTR 0xb8
535 #define TOK_CFLOAT 0xb9 /* float constant */
536 #define TOK_LINENUM 0xba /* line number info */
537 #define TOK_CDOUBLE 0xc0 /* double constant */
538 #define TOK_CLDOUBLE 0xc1 /* long double constant */
539 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
540 #define TOK_ADDC1 0xc3 /* add with carry generation */
541 #define TOK_ADDC2 0xc4 /* add with carry use */
542 #define TOK_SUBC1 0xc5 /* add with carry generation */
543 #define TOK_SUBC2 0xc6 /* add with carry use */
544 #define TOK_CUINT 0xc8 /* unsigned int constant */
545 #define TOK_CLLONG 0xc9 /* long long constant */
546 #define TOK_CULLONG 0xca /* unsigned long long constant */
547 #define TOK_ARROW 0xcb
548 #define TOK_DOTS 0xcc /* three dots */
549 #define TOK_SHR 0xcd /* unsigned shift right */
550 #define TOK_PPNUM 0xce /* preprocessor number */
552 #define TOK_SHL 0x01 /* shift left */
553 #define TOK_SAR 0x02 /* signed shift right */
555 /* assignement operators : normal operator or 0x80 */
556 #define TOK_A_MOD 0xa5
557 #define TOK_A_AND 0xa6
558 #define TOK_A_MUL 0xaa
559 #define TOK_A_ADD 0xab
560 #define TOK_A_SUB 0xad
561 #define TOK_A_DIV 0xaf
562 #define TOK_A_XOR 0xde
563 #define TOK_A_OR 0xfc
564 #define TOK_A_SHL 0x81
565 #define TOK_A_SAR 0x82
567 #ifndef offsetof
568 #define offsetof(type, field) ((size_t) &((type *)0)->field)
569 #endif
571 #ifndef countof
572 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
573 #endif
575 /* WARNING: the content of this string encodes token numbers */
576 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";
578 #define TOK_EOF (-1) /* end of file */
579 #define TOK_LINEFEED 10 /* line feed */
581 /* all identificators and strings have token above that */
582 #define TOK_IDENT 256
584 /* only used for i386 asm opcodes definitions */
585 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
587 #define DEF_BWL(x) \
588 DEF(TOK_ASM_ ## x ## b, #x "b") \
589 DEF(TOK_ASM_ ## x ## w, #x "w") \
590 DEF(TOK_ASM_ ## x ## l, #x "l") \
591 DEF(TOK_ASM_ ## x, #x)
593 #define DEF_WL(x) \
594 DEF(TOK_ASM_ ## x ## w, #x "w") \
595 DEF(TOK_ASM_ ## x ## l, #x "l") \
596 DEF(TOK_ASM_ ## x, #x)
598 #define DEF_FP1(x) \
599 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
600 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
601 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
602 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
604 #define DEF_FP(x) \
605 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
606 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
607 DEF_FP1(x)
609 #define DEF_ASMTEST(x) \
610 DEF_ASM(x ## o) \
611 DEF_ASM(x ## no) \
612 DEF_ASM(x ## b) \
613 DEF_ASM(x ## c) \
614 DEF_ASM(x ## nae) \
615 DEF_ASM(x ## nb) \
616 DEF_ASM(x ## nc) \
617 DEF_ASM(x ## ae) \
618 DEF_ASM(x ## e) \
619 DEF_ASM(x ## z) \
620 DEF_ASM(x ## ne) \
621 DEF_ASM(x ## nz) \
622 DEF_ASM(x ## be) \
623 DEF_ASM(x ## na) \
624 DEF_ASM(x ## nbe) \
625 DEF_ASM(x ## a) \
626 DEF_ASM(x ## s) \
627 DEF_ASM(x ## ns) \
628 DEF_ASM(x ## p) \
629 DEF_ASM(x ## pe) \
630 DEF_ASM(x ## np) \
631 DEF_ASM(x ## po) \
632 DEF_ASM(x ## l) \
633 DEF_ASM(x ## nge) \
634 DEF_ASM(x ## nl) \
635 DEF_ASM(x ## ge) \
636 DEF_ASM(x ## le) \
637 DEF_ASM(x ## ng) \
638 DEF_ASM(x ## nle) \
639 DEF_ASM(x ## g)
641 #define TOK_ASM_int TOK_INT
643 enum {
644 TOK_LAST = TOK_IDENT - 1,
645 #define DEF(id, str) id,
646 #include "tcctok.h"
647 #undef DEF
650 static const char tcc_keywords[] =
651 #define DEF(id, str) str "\0"
652 #include "tcctok.h"
653 #undef DEF
656 #define TOK_UIDENT TOK_DEFINE
658 #ifdef WIN32
659 #define snprintf _snprintf
660 #define vsnprintf _vsnprintf
661 #endif
663 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
664 /* currently incorrect */
665 long double strtold(const char *nptr, char **endptr)
667 return (long double)strtod(nptr, endptr);
669 float strtof(const char *nptr, char **endptr)
671 return (float)strtod(nptr, endptr);
673 #else
674 /* XXX: need to define this to use them in non ISOC99 context */
675 extern float strtof (const char *__nptr, char **__endptr);
676 extern long double strtold (const char *__nptr, char **__endptr);
677 #endif
679 static char *pstrcpy(char *buf, int buf_size, const char *s);
680 static char *pstrcat(char *buf, int buf_size, const char *s);
682 static void next(void);
683 static void next_nomacro(void);
684 static void parse_expr_type(CType *type);
685 static void expr_type(CType *type);
686 static void unary_type(CType *type);
687 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
688 int case_reg, int is_expr);
689 static int expr_const(void);
690 static void expr_eq(void);
691 static void gexpr(void);
692 static void decl(int l);
693 static void decl_initializer(CType *type, Section *sec, unsigned long c,
694 int first, int size_only);
695 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
696 int has_init, int v, int scope);
697 int gv(int rc);
698 void gv2(int rc1, int rc2);
699 void move_reg(int r, int s);
700 void save_regs(int n);
701 void save_reg(int r);
702 void vpop(void);
703 void vswap(void);
704 void vdup(void);
705 int get_reg(int rc);
706 int get_reg_ex(int rc,int rc2);
708 static void macro_subst(TokenString *tok_str, Sym **nested_list,
709 const int *macro_str, int can_read_stream);
710 int save_reg_forced(int r);
711 void gen_op(int op);
712 void force_charshort_cast(int t);
713 static void gen_cast(CType *type);
714 void vstore(void);
715 static Sym *sym_find(int v);
716 static Sym *sym_push(int v, CType *type, int r, int c);
718 /* type handling */
719 static int type_size(CType *type, int *a);
720 static inline CType *pointed_type(CType *type);
721 static int pointed_size(CType *type);
722 static int lvalue_type(int t);
723 static int parse_btype(CType *type, AttributeDef *ad);
724 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
725 static int is_compatible_types(CType *type1, CType *type2);
727 int ieee_finite(double d);
728 void error(const char *fmt, ...);
729 void vpushi(int v);
730 void vrott(int n);
731 static void vpush_global_sym(CType *type, int v);
732 void vset(CType *type, int r, int v);
733 void type_to_str(char *buf, int buf_size,
734 CType *type, const char *varstr);
735 char *get_tok_str(int v, CValue *cv);
736 static Sym *get_sym_ref(CType *type, Section *sec,
737 unsigned long offset, unsigned long size);
738 static Sym *external_global_sym(int v, CType *type, int r);
740 /* section generation */
741 static void section_realloc(Section *sec, unsigned long new_size);
742 static void *section_ptr_add(Section *sec, unsigned long size);
743 static void put_extern_sym(Sym *sym, Section *section,
744 unsigned long value, unsigned long size);
745 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
746 static int put_elf_str(Section *s, const char *sym);
747 static int put_elf_sym(Section *s,
748 unsigned long value, unsigned long size,
749 int info, int other, int shndx, const char *name);
750 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
751 int info, int sh_num, const char *name);
752 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
753 int type, int symbol);
754 static void put_stabs(const char *str, int type, int other, int desc,
755 unsigned long value);
756 static void put_stabs_r(const char *str, int type, int other, int desc,
757 unsigned long value, Section *sec, int sym_index);
758 static void put_stabn(int type, int other, int desc, int value);
759 static void put_stabd(int type, int other, int desc);
760 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
762 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
763 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
764 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
766 /* tccasm.c */
768 #ifdef CONFIG_TCC_ASM
770 typedef struct ExprValue {
771 uint32_t v;
772 Sym *sym;
773 } ExprValue;
775 #define MAX_ASM_OPERANDS 30
777 typedef struct ASMOperand {
778 int id; /* GCC 3 optionnal identifier (0 if number only supported */
779 char *constraint;
780 char asm_str[16]; /* computed asm string for operand */
781 SValue *vt; /* C value of the expression */
782 int ref_index; /* if >= 0, gives reference to a output constraint */
783 int priority; /* priority, used to assign registers */
784 int reg; /* if >= 0, register number used for this operand */
785 int is_llong; /* true if double register value */
786 } ASMOperand;
788 static void asm_expr(TCCState *s1, ExprValue *pe);
789 static int asm_int_expr(TCCState *s1);
790 static int find_constraint(ASMOperand *operands, int nb_operands,
791 const char *name, const char **pp);
793 static int tcc_assemble(TCCState *s1, int do_preprocess);
795 #endif
797 static void asm_instr(void);
799 /* true if float/double/long double type */
800 static inline int is_float(int t)
802 int bt;
803 bt = t & VT_BTYPE;
804 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
807 #ifdef TCC_TARGET_I386
808 #include "i386-gen.c"
809 #endif
811 #ifdef TCC_TARGET_ARM
812 #include "arm-gen.c"
813 #endif
815 #ifdef TCC_TARGET_C67
816 #include "c67-gen.c"
817 #endif
819 #ifdef CONFIG_TCC_STATIC
821 #define RTLD_LAZY 0x001
822 #define RTLD_NOW 0x002
823 #define RTLD_GLOBAL 0x100
824 #define RTLD_DEFAULT NULL
826 /* dummy function for profiling */
827 void *dlopen(const char *filename, int flag)
829 return NULL;
832 const char *dlerror(void)
834 return "error";
837 typedef struct TCCSyms {
838 char *str;
839 void *ptr;
840 } TCCSyms;
842 #define TCCSYM(a) { #a, &a, },
844 /* add the symbol you want here if no dynamic linking is done */
845 static TCCSyms tcc_syms[] = {
846 TCCSYM(printf)
847 TCCSYM(fprintf)
848 TCCSYM(fopen)
849 TCCSYM(fclose)
850 { NULL, NULL },
853 void *dlsym(void *handle, const char *symbol)
855 TCCSyms *p;
856 p = tcc_syms;
857 while (p->str != NULL) {
858 if (!strcmp(p->str, symbol))
859 return p->ptr;
860 p++;
862 return NULL;
865 #endif
867 /********************************************************/
869 /* we use our own 'finite' function to avoid potential problems with
870 non standard math libs */
871 /* XXX: endianness dependent */
872 int ieee_finite(double d)
874 int *p = (int *)&d;
875 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
878 /* copy a string and truncate it. */
879 static char *pstrcpy(char *buf, int buf_size, const char *s)
881 char *q, *q_end;
882 int c;
884 if (buf_size > 0) {
885 q = buf;
886 q_end = buf + buf_size - 1;
887 while (q < q_end) {
888 c = *s++;
889 if (c == '\0')
890 break;
891 *q++ = c;
893 *q = '\0';
895 return buf;
898 /* strcat and truncate. */
899 static char *pstrcat(char *buf, int buf_size, const char *s)
901 int len;
902 len = strlen(buf);
903 if (len < buf_size)
904 pstrcpy(buf + len, buf_size - len, s);
905 return buf;
908 /* memory management */
909 #ifdef MEM_DEBUG
910 int mem_cur_size;
911 int mem_max_size;
912 #endif
914 static inline void tcc_free(void *ptr)
916 #ifdef MEM_DEBUG
917 mem_cur_size -= malloc_usable_size(ptr);
918 #endif
919 free(ptr);
922 static void *tcc_malloc(unsigned long size)
924 void *ptr;
925 ptr = malloc(size);
926 if (!ptr && size)
927 error("memory full");
928 #ifdef MEM_DEBUG
929 mem_cur_size += malloc_usable_size(ptr);
930 if (mem_cur_size > mem_max_size)
931 mem_max_size = mem_cur_size;
932 #endif
933 return ptr;
936 static void *tcc_mallocz(unsigned long size)
938 void *ptr;
939 ptr = tcc_malloc(size);
940 memset(ptr, 0, size);
941 return ptr;
944 static inline void *tcc_realloc(void *ptr, unsigned long size)
946 void *ptr1;
947 #ifdef MEM_DEBUG
948 mem_cur_size -= malloc_usable_size(ptr);
949 #endif
950 ptr1 = realloc(ptr, size);
951 #ifdef MEM_DEBUG
952 /* NOTE: count not correct if alloc error, but not critical */
953 mem_cur_size += malloc_usable_size(ptr1);
954 if (mem_cur_size > mem_max_size)
955 mem_max_size = mem_cur_size;
956 #endif
957 return ptr1;
960 static char *tcc_strdup(const char *str)
962 char *ptr;
963 ptr = tcc_malloc(strlen(str) + 1);
964 strcpy(ptr, str);
965 return ptr;
968 #define free(p) use_tcc_free(p)
969 #define malloc(s) use_tcc_malloc(s)
970 #define realloc(p, s) use_tcc_realloc(p, s)
972 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
974 int nb, nb_alloc;
975 void **pp;
977 nb = *nb_ptr;
978 pp = *ptab;
979 /* every power of two we double array size */
980 if ((nb & (nb - 1)) == 0) {
981 if (!nb)
982 nb_alloc = 1;
983 else
984 nb_alloc = nb * 2;
985 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
986 if (!pp)
987 error("memory full");
988 *ptab = pp;
990 pp[nb++] = data;
991 *nb_ptr = nb;
994 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
996 Section *sec;
998 sec = tcc_mallocz(sizeof(Section) + strlen(name));
999 strcpy(sec->name, name);
1000 sec->sh_type = sh_type;
1001 sec->sh_flags = sh_flags;
1002 switch(sh_type) {
1003 case SHT_HASH:
1004 case SHT_REL:
1005 case SHT_DYNSYM:
1006 case SHT_SYMTAB:
1007 case SHT_DYNAMIC:
1008 sec->sh_addralign = 4;
1009 break;
1010 case SHT_STRTAB:
1011 sec->sh_addralign = 1;
1012 break;
1013 default:
1014 sec->sh_addralign = 32; /* default conservative alignment */
1015 break;
1018 /* only add section if not private */
1019 if (!(sh_flags & SHF_PRIVATE)) {
1020 sec->sh_num = s1->nb_sections;
1021 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1023 return sec;
1026 static void free_section(Section *s)
1028 tcc_free(s->data);
1029 tcc_free(s);
1032 /* realloc section and set its content to zero */
1033 static void section_realloc(Section *sec, unsigned long new_size)
1035 unsigned long size;
1036 unsigned char *data;
1038 size = sec->data_allocated;
1039 if (size == 0)
1040 size = 1;
1041 while (size < new_size)
1042 size = size * 2;
1043 data = tcc_realloc(sec->data, size);
1044 if (!data)
1045 error("memory full");
1046 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1047 sec->data = data;
1048 sec->data_allocated = size;
1051 /* reserve at least 'size' bytes in section 'sec' from
1052 sec->data_offset. */
1053 static void *section_ptr_add(Section *sec, unsigned long size)
1055 unsigned long offset, offset1;
1057 offset = sec->data_offset;
1058 offset1 = offset + size;
1059 if (offset1 > sec->data_allocated)
1060 section_realloc(sec, offset1);
1061 sec->data_offset = offset1;
1062 return sec->data + offset;
1065 /* return a reference to a section, and create it if it does not
1066 exists */
1067 Section *find_section(TCCState *s1, const char *name)
1069 Section *sec;
1070 int i;
1071 for(i = 1; i < s1->nb_sections; i++) {
1072 sec = s1->sections[i];
1073 if (!strcmp(name, sec->name))
1074 return sec;
1076 /* sections are created as PROGBITS */
1077 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1080 /* update sym->c so that it points to an external symbol in section
1081 'section' with value 'value' */
1082 static void put_extern_sym(Sym *sym, Section *section,
1083 unsigned long value, unsigned long size)
1085 int sym_type, sym_bind, sh_num, info;
1086 Elf32_Sym *esym;
1087 const char *name;
1089 if (section)
1090 sh_num = section->sh_num;
1091 else
1092 sh_num = SHN_UNDEF;
1093 if (!sym->c) {
1094 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1095 sym_type = STT_FUNC;
1096 else
1097 sym_type = STT_OBJECT;
1098 if (sym->type.t & VT_STATIC)
1099 sym_bind = STB_LOCAL;
1100 else
1101 sym_bind = STB_GLOBAL;
1103 name = get_tok_str(sym->v, NULL);
1104 #ifdef CONFIG_TCC_BCHECK
1105 if (do_bounds_check) {
1106 char buf[32];
1108 /* XXX: avoid doing that for statics ? */
1109 /* if bound checking is activated, we change some function
1110 names by adding the "__bound" prefix */
1111 switch(sym->v) {
1112 #if 0
1113 /* XXX: we rely only on malloc hooks */
1114 case TOK_malloc:
1115 case TOK_free:
1116 case TOK_realloc:
1117 case TOK_memalign:
1118 case TOK_calloc:
1119 #endif
1120 case TOK_memcpy:
1121 case TOK_memmove:
1122 case TOK_memset:
1123 case TOK_strlen:
1124 case TOK_strcpy:
1125 strcpy(buf, "__bound_");
1126 strcat(buf, name);
1127 name = buf;
1128 break;
1131 #endif
1132 info = ELF32_ST_INFO(sym_bind, sym_type);
1133 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1134 } else {
1135 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1136 esym->st_value = value;
1137 esym->st_size = size;
1138 esym->st_shndx = sh_num;
1142 /* add a new relocation entry to symbol 'sym' in section 's' */
1143 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1145 if (!sym->c)
1146 put_extern_sym(sym, NULL, 0, 0);
1147 /* now we can add ELF relocation info */
1148 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1151 static inline int isid(int c)
1153 return (c >= 'a' && c <= 'z') ||
1154 (c >= 'A' && c <= 'Z') ||
1155 c == '_';
1158 static inline int isnum(int c)
1160 return c >= '0' && c <= '9';
1163 static inline int isoct(int c)
1165 return c >= '0' && c <= '7';
1168 static inline int toup(int c)
1170 if (c >= 'a' && c <= 'z')
1171 return c - 'a' + 'A';
1172 else
1173 return c;
1176 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1178 int len;
1179 len = strlen(buf);
1180 vsnprintf(buf + len, buf_size - len, fmt, ap);
1183 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1185 va_list ap;
1186 va_start(ap, fmt);
1187 strcat_vprintf(buf, buf_size, fmt, ap);
1188 va_end(ap);
1191 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1193 char buf[2048];
1194 BufferedFile **f;
1196 buf[0] = '\0';
1197 if (file) {
1198 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1199 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1200 (*f)->filename, (*f)->line_num);
1201 if (file->line_num > 0) {
1202 strcat_printf(buf, sizeof(buf),
1203 "%s:%d: ", file->filename, file->line_num);
1204 } else {
1205 strcat_printf(buf, sizeof(buf),
1206 "%s: ", file->filename);
1208 } else {
1209 strcat_printf(buf, sizeof(buf),
1210 "tcc: ");
1212 if (is_warning)
1213 strcat_printf(buf, sizeof(buf), "warning: ");
1214 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1216 if (!s1->error_func) {
1217 /* default case: stderr */
1218 fprintf(stderr, "%s\n", buf);
1219 } else {
1220 s1->error_func(s1->error_opaque, buf);
1222 if (!is_warning || s1->warn_error)
1223 s1->nb_errors++;
1226 #ifdef LIBTCC
1227 void tcc_set_error_func(TCCState *s, void *error_opaque,
1228 void (*error_func)(void *opaque, const char *msg))
1230 s->error_opaque = error_opaque;
1231 s->error_func = error_func;
1233 #endif
1235 /* error without aborting current compilation */
1236 void error_noabort(const char *fmt, ...)
1238 TCCState *s1 = tcc_state;
1239 va_list ap;
1241 va_start(ap, fmt);
1242 error1(s1, 0, fmt, ap);
1243 va_end(ap);
1246 void error(const char *fmt, ...)
1248 TCCState *s1 = tcc_state;
1249 va_list ap;
1251 va_start(ap, fmt);
1252 error1(s1, 0, fmt, ap);
1253 va_end(ap);
1254 /* better than nothing: in some cases, we accept to handle errors */
1255 if (s1->error_set_jmp_enabled) {
1256 longjmp(s1->error_jmp_buf, 1);
1257 } else {
1258 /* XXX: eliminate this someday */
1259 exit(1);
1263 void expect(const char *msg)
1265 error("%s expected", msg);
1268 void warning(const char *fmt, ...)
1270 TCCState *s1 = tcc_state;
1271 va_list ap;
1273 if (s1->warn_none)
1274 return;
1276 va_start(ap, fmt);
1277 error1(s1, 1, fmt, ap);
1278 va_end(ap);
1281 void skip(int c)
1283 if (tok != c)
1284 error("'%c' expected", c);
1285 next();
1288 static void test_lvalue(void)
1290 if (!(vtop->r & VT_LVAL))
1291 expect("lvalue");
1294 /* allocate a new token */
1295 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1297 TokenSym *ts, **ptable;
1298 int i;
1300 if (tok_ident >= SYM_FIRST_ANOM)
1301 error("memory full");
1303 /* expand token table if needed */
1304 i = tok_ident - TOK_IDENT;
1305 if ((i % TOK_ALLOC_INCR) == 0) {
1306 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1307 if (!ptable)
1308 error("memory full");
1309 table_ident = ptable;
1312 ts = tcc_malloc(sizeof(TokenSym) + len);
1313 table_ident[i] = ts;
1314 ts->tok = tok_ident++;
1315 ts->sym_define = NULL;
1316 ts->sym_label = NULL;
1317 ts->sym_struct = NULL;
1318 ts->sym_identifier = NULL;
1319 ts->len = len;
1320 ts->hash_next = NULL;
1321 memcpy(ts->str, str, len);
1322 ts->str[len] = '\0';
1323 *pts = ts;
1324 return ts;
1327 #define TOK_HASH_INIT 1
1328 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1330 /* find a token and add it if not found */
1331 static TokenSym *tok_alloc(const char *str, int len)
1333 TokenSym *ts, **pts;
1334 int i;
1335 unsigned int h;
1337 h = TOK_HASH_INIT;
1338 for(i=0;i<len;i++)
1339 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1340 h &= (TOK_HASH_SIZE - 1);
1342 pts = &hash_ident[h];
1343 for(;;) {
1344 ts = *pts;
1345 if (!ts)
1346 break;
1347 if (ts->len == len && !memcmp(ts->str, str, len))
1348 return ts;
1349 pts = &(ts->hash_next);
1351 return tok_alloc_new(pts, str, len);
1354 /* CString handling */
1356 static void cstr_realloc(CString *cstr, int new_size)
1358 int size;
1359 void *data;
1361 size = cstr->size_allocated;
1362 if (size == 0)
1363 size = 8; /* no need to allocate a too small first string */
1364 while (size < new_size)
1365 size = size * 2;
1366 data = tcc_realloc(cstr->data_allocated, size);
1367 if (!data)
1368 error("memory full");
1369 cstr->data_allocated = data;
1370 cstr->size_allocated = size;
1371 cstr->data = data;
1374 /* add a byte */
1375 static void cstr_ccat(CString *cstr, int ch)
1377 int size;
1378 size = cstr->size + 1;
1379 if (size > cstr->size_allocated)
1380 cstr_realloc(cstr, size);
1381 ((unsigned char *)cstr->data)[size - 1] = ch;
1382 cstr->size = size;
1385 static void cstr_cat(CString *cstr, const char *str)
1387 int c;
1388 for(;;) {
1389 c = *str;
1390 if (c == '\0')
1391 break;
1392 cstr_ccat(cstr, c);
1393 str++;
1397 /* add a wide char */
1398 static void cstr_wccat(CString *cstr, int ch)
1400 int size;
1401 size = cstr->size + sizeof(int);
1402 if (size > cstr->size_allocated)
1403 cstr_realloc(cstr, size);
1404 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1405 cstr->size = size;
1408 static void cstr_new(CString *cstr)
1410 memset(cstr, 0, sizeof(CString));
1413 /* free string and reset it to NULL */
1414 static void cstr_free(CString *cstr)
1416 tcc_free(cstr->data_allocated);
1417 cstr_new(cstr);
1420 #define cstr_reset(cstr) cstr_free(cstr)
1422 static CString *cstr_dup(CString *cstr1)
1424 CString *cstr;
1425 int size;
1427 cstr = tcc_malloc(sizeof(CString));
1428 size = cstr1->size;
1429 cstr->size = size;
1430 cstr->size_allocated = size;
1431 cstr->data_allocated = tcc_malloc(size);
1432 cstr->data = cstr->data_allocated;
1433 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1434 return cstr;
1437 /* XXX: unicode ? */
1438 static void add_char(CString *cstr, int c)
1440 if (c == '\'' || c == '\"' || c == '\\') {
1441 /* XXX: could be more precise if char or string */
1442 cstr_ccat(cstr, '\\');
1444 if (c >= 32 && c <= 126) {
1445 cstr_ccat(cstr, c);
1446 } else {
1447 cstr_ccat(cstr, '\\');
1448 if (c == '\n') {
1449 cstr_ccat(cstr, 'n');
1450 } else {
1451 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1452 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1453 cstr_ccat(cstr, '0' + (c & 7));
1458 /* XXX: buffer overflow */
1459 /* XXX: float tokens */
1460 char *get_tok_str(int v, CValue *cv)
1462 static char buf[STRING_MAX_SIZE + 1];
1463 static CString cstr_buf;
1464 CString *cstr;
1465 unsigned char *q;
1466 char *p;
1467 int i, len;
1469 /* NOTE: to go faster, we give a fixed buffer for small strings */
1470 cstr_reset(&cstr_buf);
1471 cstr_buf.data = buf;
1472 cstr_buf.size_allocated = sizeof(buf);
1473 p = buf;
1475 switch(v) {
1476 case TOK_CINT:
1477 case TOK_CUINT:
1478 /* XXX: not quite exact, but only useful for testing */
1479 sprintf(p, "%u", cv->ui);
1480 break;
1481 case TOK_CLLONG:
1482 case TOK_CULLONG:
1483 /* XXX: not quite exact, but only useful for testing */
1484 sprintf(p, "%Lu", cv->ull);
1485 break;
1486 case TOK_CCHAR:
1487 case TOK_LCHAR:
1488 cstr_ccat(&cstr_buf, '\'');
1489 add_char(&cstr_buf, cv->i);
1490 cstr_ccat(&cstr_buf, '\'');
1491 cstr_ccat(&cstr_buf, '\0');
1492 break;
1493 case TOK_PPNUM:
1494 cstr = cv->cstr;
1495 len = cstr->size - 1;
1496 for(i=0;i<len;i++)
1497 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1498 cstr_ccat(&cstr_buf, '\0');
1499 break;
1500 case TOK_STR:
1501 case TOK_LSTR:
1502 cstr = cv->cstr;
1503 cstr_ccat(&cstr_buf, '\"');
1504 if (v == TOK_STR) {
1505 len = cstr->size - 1;
1506 for(i=0;i<len;i++)
1507 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1508 } else {
1509 len = (cstr->size / sizeof(int)) - 1;
1510 for(i=0;i<len;i++)
1511 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1513 cstr_ccat(&cstr_buf, '\"');
1514 cstr_ccat(&cstr_buf, '\0');
1515 break;
1516 case TOK_LT:
1517 v = '<';
1518 goto addv;
1519 case TOK_GT:
1520 v = '>';
1521 goto addv;
1522 case TOK_A_SHL:
1523 return strcpy(p, "<<=");
1524 case TOK_A_SAR:
1525 return strcpy(p, ">>=");
1526 default:
1527 if (v < TOK_IDENT) {
1528 /* search in two bytes table */
1529 q = tok_two_chars;
1530 while (*q) {
1531 if (q[2] == v) {
1532 *p++ = q[0];
1533 *p++ = q[1];
1534 *p = '\0';
1535 return buf;
1537 q += 3;
1539 addv:
1540 *p++ = v;
1541 *p = '\0';
1542 } else if (v < tok_ident) {
1543 return table_ident[v - TOK_IDENT]->str;
1544 } else if (v >= SYM_FIRST_ANOM) {
1545 /* special name for anonymous symbol */
1546 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1547 } else {
1548 /* should never happen */
1549 return NULL;
1551 break;
1553 return cstr_buf.data;
1556 /* push, without hashing */
1557 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1559 Sym *s;
1560 s = tcc_malloc(sizeof(Sym));
1561 s->v = v;
1562 s->type.t = t;
1563 s->c = c;
1564 s->next = NULL;
1565 /* add in stack */
1566 s->prev = *ps;
1567 *ps = s;
1568 return s;
1571 /* find a symbol and return its associated structure. 's' is the top
1572 of the symbol stack */
1573 static Sym *sym_find2(Sym *s, int v)
1575 while (s) {
1576 if (s->v == v)
1577 return s;
1578 s = s->prev;
1580 return NULL;
1583 /* structure lookup */
1584 static inline Sym *struct_find(int v)
1586 v -= TOK_IDENT;
1587 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1588 return NULL;
1589 return table_ident[v]->sym_struct;
1592 /* find an identifier */
1593 static inline Sym *sym_find(int v)
1595 v -= TOK_IDENT;
1596 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1597 return NULL;
1598 return table_ident[v]->sym_identifier;
1601 /* push a given symbol on the symbol stack */
1602 static Sym *sym_push(int v, CType *type, int r, int c)
1604 Sym *s, **ps;
1605 TokenSym *ts;
1607 if (local_stack)
1608 ps = &local_stack;
1609 else
1610 ps = &global_stack;
1611 s = sym_push2(ps, v, type->t, c);
1612 s->type.ref = type->ref;
1613 s->r = r;
1614 /* don't record fields or anonymous symbols */
1615 /* XXX: simplify */
1616 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1617 /* record symbol in token array */
1618 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1619 if (v & SYM_STRUCT)
1620 ps = &ts->sym_struct;
1621 else
1622 ps = &ts->sym_identifier;
1623 s->prev_tok = *ps;
1624 *ps = s;
1626 return s;
1629 /* push a global identifier */
1630 static Sym *global_identifier_push(int v, int t, int c)
1632 Sym *s, **ps;
1633 s = sym_push2(&global_stack, v, t, c);
1634 /* don't record anonymous symbol */
1635 if (v < SYM_FIRST_ANOM) {
1636 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1637 /* modify the top most local identifier, so that
1638 sym_identifier will point to 's' when popped */
1639 while (*ps != NULL)
1640 ps = &(*ps)->prev_tok;
1641 s->prev_tok = NULL;
1642 *ps = s;
1644 return s;
1647 /* pop symbols until top reaches 'b' */
1648 static void sym_pop(Sym **ptop, Sym *b)
1650 Sym *s, *ss, **ps;
1651 TokenSym *ts;
1652 int v;
1654 s = *ptop;
1655 while(s != b) {
1656 ss = s->prev;
1657 v = s->v;
1658 /* remove symbol in token array */
1659 /* XXX: simplify */
1660 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1661 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1662 if (v & SYM_STRUCT)
1663 ps = &ts->sym_struct;
1664 else
1665 ps = &ts->sym_identifier;
1666 *ps = s->prev_tok;
1668 tcc_free(s);
1669 s = ss;
1671 *ptop = b;
1674 /* I/O layer */
1676 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1678 int fd;
1679 BufferedFile *bf;
1681 fd = open(filename, O_RDONLY);
1682 if (fd < 0)
1683 return NULL;
1684 bf = tcc_malloc(sizeof(BufferedFile));
1685 if (!bf) {
1686 close(fd);
1687 return NULL;
1689 bf->fd = fd;
1690 bf->buf_ptr = bf->buffer;
1691 bf->buf_end = bf->buffer;
1692 bf->buffer[0] = CH_EOB; /* put eob symbol */
1693 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1694 bf->line_num = 1;
1695 bf->ifndef_macro = 0;
1696 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1697 // printf("opening '%s'\n", filename);
1698 return bf;
1701 void tcc_close(BufferedFile *bf)
1703 total_lines += bf->line_num;
1704 close(bf->fd);
1705 tcc_free(bf);
1708 /* fill input buffer and peek next char */
1709 static int tcc_peekc_slow(BufferedFile *bf)
1711 int len;
1712 /* only tries to read if really end of buffer */
1713 if (bf->buf_ptr >= bf->buf_end) {
1714 if (bf->fd != -1) {
1715 #if defined(PARSE_DEBUG)
1716 len = 8;
1717 #else
1718 len = IO_BUF_SIZE;
1719 #endif
1720 len = read(bf->fd, bf->buffer, len);
1721 if (len < 0)
1722 len = 0;
1723 } else {
1724 len = 0;
1726 total_bytes += len;
1727 bf->buf_ptr = bf->buffer;
1728 bf->buf_end = bf->buffer + len;
1729 *bf->buf_end = CH_EOB;
1731 if (bf->buf_ptr < bf->buf_end) {
1732 return bf->buf_ptr[0];
1733 } else {
1734 bf->buf_ptr = bf->buf_end;
1735 return CH_EOF;
1739 /* return the current character, handling end of block if necessary
1740 (but not stray) */
1741 static int handle_eob(void)
1743 return tcc_peekc_slow(file);
1746 /* read next char from current input file and handle end of input buffer */
1747 static inline void inp(void)
1749 ch = *(++(file->buf_ptr));
1750 /* end of buffer/file handling */
1751 if (ch == CH_EOB)
1752 ch = handle_eob();
1755 /* handle '\[\r]\n' */
1756 static void handle_stray(void)
1758 while (ch == '\\') {
1759 inp();
1760 if (ch == '\n') {
1761 file->line_num++;
1762 inp();
1763 } else if (ch == '\r') {
1764 inp();
1765 if (ch != '\n')
1766 goto fail;
1767 file->line_num++;
1768 inp();
1769 } else {
1770 fail:
1771 error("stray '\\' in program");
1776 /* skip the stray and handle the \\n case. Output an error if
1777 incorrect char after the stray */
1778 static int handle_stray1(uint8_t *p)
1780 int c;
1782 if (p >= file->buf_end) {
1783 file->buf_ptr = p;
1784 c = handle_eob();
1785 p = file->buf_ptr;
1786 if (c == '\\')
1787 goto parse_stray;
1788 } else {
1789 parse_stray:
1790 file->buf_ptr = p;
1791 ch = *p;
1792 handle_stray();
1793 p = file->buf_ptr;
1794 c = *p;
1796 return c;
1799 /* handle just the EOB case, but not stray */
1800 #define PEEKC_EOB(c, p)\
1802 p++;\
1803 c = *p;\
1804 if (c == '\\') {\
1805 file->buf_ptr = p;\
1806 c = handle_eob();\
1807 p = file->buf_ptr;\
1811 /* handle the complicated stray case */
1812 #define PEEKC(c, p)\
1814 p++;\
1815 c = *p;\
1816 if (c == '\\') {\
1817 c = handle_stray1(p);\
1818 p = file->buf_ptr;\
1822 /* input with '\[\r]\n' handling. Note that this function cannot
1823 handle other characters after '\', so you cannot call it inside
1824 strings or comments */
1825 static void minp(void)
1827 inp();
1828 if (ch == '\\')
1829 handle_stray();
1833 /* single line C++ comments */
1834 static uint8_t *parse_line_comment(uint8_t *p)
1836 int c;
1838 p++;
1839 for(;;) {
1840 c = *p;
1841 redo:
1842 if (c == '\n' || c == CH_EOF) {
1843 break;
1844 } else if (c == '\\') {
1845 file->buf_ptr = p;
1846 c = handle_eob();
1847 p = file->buf_ptr;
1848 if (c == '\\') {
1849 PEEKC_EOB(c, p);
1850 if (c == '\n') {
1851 file->line_num++;
1852 PEEKC_EOB(c, p);
1853 } else if (c == '\r') {
1854 PEEKC_EOB(c, p);
1855 if (c == '\n') {
1856 file->line_num++;
1857 PEEKC_EOB(c, p);
1860 } else {
1861 goto redo;
1863 } else {
1864 p++;
1867 return p;
1870 /* C comments */
1871 static uint8_t *parse_comment(uint8_t *p)
1873 int c;
1875 p++;
1876 for(;;) {
1877 /* fast skip loop */
1878 for(;;) {
1879 c = *p;
1880 if (c == '\n' || c == '*' || c == '\\')
1881 break;
1882 p++;
1883 c = *p;
1884 if (c == '\n' || c == '*' || c == '\\')
1885 break;
1886 p++;
1888 /* now we can handle all the cases */
1889 if (c == '\n') {
1890 file->line_num++;
1891 p++;
1892 } else if (c == '*') {
1893 p++;
1894 for(;;) {
1895 c = *p;
1896 if (c == '*') {
1897 p++;
1898 } else if (c == '/') {
1899 goto end_of_comment;
1900 } else if (c == '\\') {
1901 file->buf_ptr = p;
1902 c = handle_eob();
1903 p = file->buf_ptr;
1904 if (c == '\\') {
1905 /* skip '\[\r]\n', otherwise just skip the stray */
1906 while (c == '\\') {
1907 PEEKC_EOB(c, p);
1908 if (c == '\n') {
1909 file->line_num++;
1910 PEEKC_EOB(c, p);
1911 } else if (c == '\r') {
1912 PEEKC_EOB(c, p);
1913 if (c == '\n') {
1914 file->line_num++;
1915 PEEKC_EOB(c, p);
1917 } else {
1918 goto after_star;
1922 } else {
1923 break;
1926 after_star: ;
1927 } else {
1928 /* stray, eob or eof */
1929 file->buf_ptr = p;
1930 c = handle_eob();
1931 p = file->buf_ptr;
1932 if (c == CH_EOF) {
1933 error("unexpected end of file in comment");
1934 } else if (c == '\\') {
1935 p++;
1939 end_of_comment:
1940 p++;
1941 return p;
1944 #define cinp minp
1946 /* space exlcuding newline */
1947 static inline int is_space(int ch)
1949 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1952 static inline void skip_spaces(void)
1954 while (is_space(ch))
1955 cinp();
1958 /* parse a string without interpreting escapes */
1959 static uint8_t *parse_pp_string(uint8_t *p,
1960 int sep, CString *str)
1962 int c;
1963 p++;
1964 for(;;) {
1965 c = *p;
1966 if (c == sep) {
1967 break;
1968 } else if (c == '\\') {
1969 file->buf_ptr = p;
1970 c = handle_eob();
1971 p = file->buf_ptr;
1972 if (c == CH_EOF) {
1973 unterminated_string:
1974 /* XXX: indicate line number of start of string */
1975 error("missing terminating %c character", sep);
1976 } else if (c == '\\') {
1977 /* escape : just skip \[\r]\n */
1978 PEEKC_EOB(c, p);
1979 if (c == '\n') {
1980 file->line_num++;
1981 p++;
1982 } else if (c == '\r') {
1983 PEEKC_EOB(c, p);
1984 if (c != '\n')
1985 expect("'\n' after '\r'");
1986 file->line_num++;
1987 p++;
1988 } else if (c == CH_EOF) {
1989 goto unterminated_string;
1990 } else {
1991 if (str) {
1992 cstr_ccat(str, '\\');
1993 cstr_ccat(str, c);
1995 p++;
1998 } else if (c == '\n') {
1999 file->line_num++;
2000 goto add_char;
2001 } else if (c == '\r') {
2002 PEEKC_EOB(c, p);
2003 if (c != '\n') {
2004 cstr_ccat(str, '\r');
2005 } else {
2006 file->line_num++;
2007 goto add_char;
2009 } else {
2010 add_char:
2011 if (str)
2012 cstr_ccat(str, c);
2013 p++;
2016 p++;
2017 return p;
2020 /* skip block of text until #else, #elif or #endif. skip also pairs of
2021 #if/#endif */
2022 void preprocess_skip(void)
2024 int a, start_of_line, c;
2025 uint8_t *p;
2027 p = file->buf_ptr;
2028 start_of_line = 1;
2029 a = 0;
2030 for(;;) {
2031 redo_no_start:
2032 c = *p;
2033 switch(c) {
2034 case ' ':
2035 case '\t':
2036 case '\f':
2037 case '\v':
2038 case '\r':
2039 p++;
2040 goto redo_no_start;
2041 case '\n':
2042 start_of_line = 1;
2043 file->line_num++;
2044 p++;
2045 goto redo_no_start;
2046 case '\\':
2047 file->buf_ptr = p;
2048 c = handle_eob();
2049 if (c == CH_EOF) {
2050 expect("#endif");
2051 } else if (c == '\\') {
2052 /* XXX: incorrect: should not give an error */
2053 ch = file->buf_ptr[0];
2054 handle_stray();
2056 p = file->buf_ptr;
2057 goto redo_no_start;
2058 /* skip strings */
2059 case '\"':
2060 case '\'':
2061 p = parse_pp_string(p, c, NULL);
2062 break;
2063 /* skip comments */
2064 case '/':
2065 file->buf_ptr = p;
2066 ch = *p;
2067 minp();
2068 p = file->buf_ptr;
2069 if (ch == '*') {
2070 p = parse_comment(p);
2071 } else if (ch == '/') {
2072 p = parse_line_comment(p);
2074 break;
2076 case '#':
2077 p++;
2078 if (start_of_line) {
2079 file->buf_ptr = p;
2080 next_nomacro();
2081 p = file->buf_ptr;
2082 if (a == 0 &&
2083 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2084 goto the_end;
2085 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2086 a++;
2087 else if (tok == TOK_ENDIF)
2088 a--;
2090 break;
2091 default:
2092 p++;
2093 break;
2095 start_of_line = 0;
2097 the_end: ;
2098 file->buf_ptr = p;
2101 /* ParseState handling */
2103 /* XXX: currently, no include file info is stored. Thus, we cannot display
2104 accurate messages if the function or data definition spans multiple
2105 files */
2107 /* save current parse state in 's' */
2108 void save_parse_state(ParseState *s)
2110 s->line_num = file->line_num;
2111 s->macro_ptr = macro_ptr;
2112 s->tok = tok;
2113 s->tokc = tokc;
2116 /* restore parse state from 's' */
2117 void restore_parse_state(ParseState *s)
2119 file->line_num = s->line_num;
2120 macro_ptr = s->macro_ptr;
2121 tok = s->tok;
2122 tokc = s->tokc;
2125 /* return the number of additional 'ints' necessary to store the
2126 token */
2127 static inline int tok_ext_size(int t)
2129 switch(t) {
2130 /* 4 bytes */
2131 case TOK_CINT:
2132 case TOK_CUINT:
2133 case TOK_CCHAR:
2134 case TOK_LCHAR:
2135 case TOK_STR:
2136 case TOK_LSTR:
2137 case TOK_CFLOAT:
2138 case TOK_LINENUM:
2139 case TOK_PPNUM:
2140 return 1;
2141 case TOK_CDOUBLE:
2142 case TOK_CLLONG:
2143 case TOK_CULLONG:
2144 return 2;
2145 case TOK_CLDOUBLE:
2146 return LDOUBLE_SIZE / 4;
2147 default:
2148 return 0;
2152 /* token string handling */
2154 static inline void tok_str_new(TokenString *s)
2156 s->str = NULL;
2157 s->len = 0;
2158 s->allocated_len = 0;
2159 s->last_line_num = -1;
2162 static void tok_str_free(int *str)
2164 const int *p;
2165 CString *cstr;
2166 int t;
2168 p = str;
2169 for(;;) {
2170 t = *p;
2171 /* NOTE: we test zero separately so that GCC can generate a
2172 table for the following switch */
2173 if (t == 0)
2174 break;
2175 switch(t) {
2176 case TOK_CINT:
2177 case TOK_CUINT:
2178 case TOK_CCHAR:
2179 case TOK_LCHAR:
2180 case TOK_CFLOAT:
2181 case TOK_LINENUM:
2182 p += 2;
2183 break;
2184 case TOK_PPNUM:
2185 case TOK_STR:
2186 case TOK_LSTR:
2187 /* XXX: use a macro to be portable on 64 bit ? */
2188 cstr = (CString *)p[1];
2189 cstr_free(cstr);
2190 tcc_free(cstr);
2191 p += 2;
2192 break;
2193 case TOK_CDOUBLE:
2194 case TOK_CLLONG:
2195 case TOK_CULLONG:
2196 p += 3;
2197 break;
2198 case TOK_CLDOUBLE:
2199 p += 1 + (LDOUBLE_SIZE / 4);
2200 break;
2201 default:
2202 p++;
2203 break;
2206 tcc_free(str);
2209 static int *tok_str_realloc(TokenString *s)
2211 int *str, len;
2213 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2214 str = tcc_realloc(s->str, len * sizeof(int));
2215 if (!str)
2216 error("memory full");
2217 s->allocated_len = len;
2218 s->str = str;
2219 return str;
2222 static void tok_str_add(TokenString *s, int t)
2224 int len, *str;
2226 len = s->len;
2227 str = s->str;
2228 if (len >= s->allocated_len)
2229 str = tok_str_realloc(s);
2230 str[len++] = t;
2231 s->len = len;
2234 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2236 int len, *str;
2238 len = s->len;
2239 str = s->str;
2241 /* allocate space for worst case */
2242 if (len + TOK_MAX_SIZE > s->allocated_len)
2243 str = tok_str_realloc(s);
2244 str[len++] = t;
2245 switch(t) {
2246 case TOK_CINT:
2247 case TOK_CUINT:
2248 case TOK_CCHAR:
2249 case TOK_LCHAR:
2250 case TOK_CFLOAT:
2251 case TOK_LINENUM:
2252 str[len++] = cv->tab[0];
2253 break;
2254 case TOK_PPNUM:
2255 case TOK_STR:
2256 case TOK_LSTR:
2257 str[len++] = (int)cstr_dup(cv->cstr);
2258 break;
2259 case TOK_CDOUBLE:
2260 case TOK_CLLONG:
2261 case TOK_CULLONG:
2262 #if LDOUBLE_SIZE == 8
2263 case TOK_CLDOUBLE:
2264 #endif
2265 str[len++] = cv->tab[0];
2266 str[len++] = cv->tab[1];
2267 break;
2268 #if LDOUBLE_SIZE == 12
2269 case TOK_CLDOUBLE:
2270 str[len++] = cv->tab[0];
2271 str[len++] = cv->tab[1];
2272 str[len++] = cv->tab[2];
2273 #elif LDOUBLE_SIZE != 8
2274 #error add long double size support
2275 #endif
2276 break;
2277 default:
2278 break;
2280 s->len = len;
2283 /* add the current parse token in token string 's' */
2284 static void tok_str_add_tok(TokenString *s)
2286 CValue cval;
2288 /* save line number info */
2289 if (file->line_num != s->last_line_num) {
2290 s->last_line_num = file->line_num;
2291 cval.i = s->last_line_num;
2292 tok_str_add2(s, TOK_LINENUM, &cval);
2294 tok_str_add2(s, tok, &tokc);
2297 #if LDOUBLE_SIZE == 12
2298 #define LDOUBLE_GET(p, cv) \
2299 cv.tab[0] = p[0]; \
2300 cv.tab[1] = p[1]; \
2301 cv.tab[2] = p[2];
2302 #elif LDOUBLE_SIZE == 8
2303 #define LDOUBLE_GET(p, cv) \
2304 cv.tab[0] = p[0]; \
2305 cv.tab[1] = p[1];
2306 #else
2307 #error add long double size support
2308 #endif
2311 /* get a token from an integer array and increment pointer
2312 accordingly. we code it as a macro to avoid pointer aliasing. */
2313 #define TOK_GET(t, p, cv) \
2315 t = *p++; \
2316 switch(t) { \
2317 case TOK_CINT: \
2318 case TOK_CUINT: \
2319 case TOK_CCHAR: \
2320 case TOK_LCHAR: \
2321 case TOK_CFLOAT: \
2322 case TOK_LINENUM: \
2323 case TOK_STR: \
2324 case TOK_LSTR: \
2325 case TOK_PPNUM: \
2326 cv.tab[0] = *p++; \
2327 break; \
2328 case TOK_CDOUBLE: \
2329 case TOK_CLLONG: \
2330 case TOK_CULLONG: \
2331 cv.tab[0] = p[0]; \
2332 cv.tab[1] = p[1]; \
2333 p += 2; \
2334 break; \
2335 case TOK_CLDOUBLE: \
2336 LDOUBLE_GET(p, cv); \
2337 p += LDOUBLE_SIZE / 4; \
2338 break; \
2339 default: \
2340 break; \
2344 /* defines handling */
2345 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2347 Sym *s;
2349 s = sym_push2(&define_stack, v, macro_type, (int)str);
2350 s->next = first_arg;
2351 table_ident[v - TOK_IDENT]->sym_define = s;
2354 /* undefined a define symbol. Its name is just set to zero */
2355 static void define_undef(Sym *s)
2357 int v;
2358 v = s->v;
2359 if (v >= TOK_IDENT && v < tok_ident)
2360 table_ident[v - TOK_IDENT]->sym_define = NULL;
2361 s->v = 0;
2364 static inline Sym *define_find(int v)
2366 v -= TOK_IDENT;
2367 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2368 return NULL;
2369 return table_ident[v]->sym_define;
2372 /* free define stack until top reaches 'b' */
2373 static void free_defines(Sym *b)
2375 Sym *top, *top1;
2376 int v;
2378 top = define_stack;
2379 while (top != b) {
2380 top1 = top->prev;
2381 /* do not free args or predefined defines */
2382 if (top->c)
2383 tok_str_free((int *)top->c);
2384 v = top->v;
2385 if (v >= TOK_IDENT && v < tok_ident)
2386 table_ident[v - TOK_IDENT]->sym_define = NULL;
2387 tcc_free(top);
2388 top = top1;
2390 define_stack = b;
2393 /* label lookup */
2394 static Sym *label_find(int v)
2396 v -= TOK_IDENT;
2397 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2398 return NULL;
2399 return table_ident[v]->sym_label;
2402 static Sym *label_push(Sym **ptop, int v, int flags)
2404 Sym *s, **ps;
2405 s = sym_push2(ptop, v, 0, 0);
2406 s->r = flags;
2407 ps = &table_ident[v - TOK_IDENT]->sym_label;
2408 if (ptop == &global_label_stack) {
2409 /* modify the top most local identifier, so that
2410 sym_identifier will point to 's' when popped */
2411 while (*ps != NULL)
2412 ps = &(*ps)->prev_tok;
2414 s->prev_tok = *ps;
2415 *ps = s;
2416 return s;
2419 /* pop labels until element last is reached. Look if any labels are
2420 undefined. Define symbols if '&&label' was used. */
2421 static void label_pop(Sym **ptop, Sym *slast)
2423 Sym *s, *s1;
2424 for(s = *ptop; s != slast; s = s1) {
2425 s1 = s->prev;
2426 if (s->r == LABEL_DECLARED) {
2427 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2428 } else if (s->r == LABEL_FORWARD) {
2429 error("label '%s' used but not defined",
2430 get_tok_str(s->v, NULL));
2431 } else {
2432 if (s->c) {
2433 /* define corresponding symbol. A size of
2434 1 is put. */
2435 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2438 /* remove label */
2439 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2440 tcc_free(s);
2442 *ptop = slast;
2445 /* eval an expression for #if/#elif */
2446 static int expr_preprocess(void)
2448 int c, t;
2449 TokenString str;
2451 tok_str_new(&str);
2452 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2453 next(); /* do macro subst */
2454 if (tok == TOK_DEFINED) {
2455 next_nomacro();
2456 t = tok;
2457 if (t == '(')
2458 next_nomacro();
2459 c = define_find(tok) != 0;
2460 if (t == '(')
2461 next_nomacro();
2462 tok = TOK_CINT;
2463 tokc.i = c;
2464 } else if (tok >= TOK_IDENT) {
2465 /* if undefined macro */
2466 tok = TOK_CINT;
2467 tokc.i = 0;
2469 tok_str_add_tok(&str);
2471 tok_str_add(&str, -1); /* simulate end of file */
2472 tok_str_add(&str, 0);
2473 /* now evaluate C constant expression */
2474 macro_ptr = str.str;
2475 next();
2476 c = expr_const();
2477 macro_ptr = NULL;
2478 tok_str_free(str.str);
2479 return c != 0;
2482 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2483 static void tok_print(int *str)
2485 int t;
2486 CValue cval;
2488 while (1) {
2489 TOK_GET(t, str, cval);
2490 if (!t)
2491 break;
2492 printf(" %s", get_tok_str(t, &cval));
2494 printf("\n");
2496 #endif
2498 /* parse after #define */
2499 static void parse_define(void)
2501 Sym *s, *first, **ps;
2502 int v, t, varg, is_vaargs, c;
2503 TokenString str;
2505 v = tok;
2506 if (v < TOK_IDENT)
2507 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2508 /* XXX: should check if same macro (ANSI) */
2509 first = NULL;
2510 t = MACRO_OBJ;
2511 /* '(' must be just after macro definition for MACRO_FUNC */
2512 c = file->buf_ptr[0];
2513 if (c == '\\')
2514 c = handle_stray1(file->buf_ptr);
2515 if (c == '(') {
2516 next_nomacro();
2517 next_nomacro();
2518 ps = &first;
2519 while (tok != ')') {
2520 varg = tok;
2521 next_nomacro();
2522 is_vaargs = 0;
2523 if (varg == TOK_DOTS) {
2524 varg = TOK___VA_ARGS__;
2525 is_vaargs = 1;
2526 } else if (tok == TOK_DOTS && gnu_ext) {
2527 is_vaargs = 1;
2528 next_nomacro();
2530 if (varg < TOK_IDENT)
2531 error("badly punctuated parameter list");
2532 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2533 *ps = s;
2534 ps = &s->next;
2535 if (tok != ',')
2536 break;
2537 next_nomacro();
2539 t = MACRO_FUNC;
2541 tok_str_new(&str);
2542 next_nomacro();
2543 /* EOF testing necessary for '-D' handling */
2544 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2545 tok_str_add2(&str, tok, &tokc);
2546 next_nomacro();
2548 tok_str_add(&str, 0);
2549 #ifdef PP_DEBUG
2550 printf("define %s %d: ", get_tok_str(v, NULL), t);
2551 tok_print(str.str);
2552 #endif
2553 define_push(v, t, str.str, first);
2556 /* XXX: use a token or a hash table to accelerate matching ? */
2557 static CachedInclude *search_cached_include(TCCState *s1,
2558 int type, const char *filename)
2560 CachedInclude *e;
2561 int i;
2563 for(i = 0;i < s1->nb_cached_includes; i++) {
2564 e = s1->cached_includes[i];
2565 if (e->type == type && !strcmp(e->filename, filename))
2566 return e;
2568 return NULL;
2571 static inline void add_cached_include(TCCState *s1, int type,
2572 const char *filename, int ifndef_macro)
2574 CachedInclude *e;
2576 if (search_cached_include(s1, type, filename))
2577 return;
2578 #ifdef INC_DEBUG
2579 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2580 #endif
2581 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2582 if (!e)
2583 return;
2584 e->type = type;
2585 strcpy(e->filename, filename);
2586 e->ifndef_macro = ifndef_macro;
2587 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2590 /* is_bof is true if first non space token at beginning of file */
2591 static void preprocess(int is_bof)
2593 TCCState *s1 = tcc_state;
2594 int size, i, c, n, saved_parse_flags;
2595 char buf[1024], *q, *p;
2596 char buf1[1024];
2597 BufferedFile *f;
2598 Sym *s;
2599 CachedInclude *e;
2601 saved_parse_flags = parse_flags;
2602 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2603 PARSE_FLAG_LINEFEED;
2604 next_nomacro();
2605 redo:
2606 switch(tok) {
2607 case TOK_DEFINE:
2608 next_nomacro();
2609 parse_define();
2610 break;
2611 case TOK_UNDEF:
2612 next_nomacro();
2613 s = define_find(tok);
2614 /* undefine symbol by putting an invalid name */
2615 if (s)
2616 define_undef(s);
2617 break;
2618 case TOK_INCLUDE:
2619 ch = file->buf_ptr[0];
2620 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2621 skip_spaces();
2622 if (ch == '<') {
2623 c = '>';
2624 goto read_name;
2625 } else if (ch == '\"') {
2626 c = ch;
2627 read_name:
2628 /* XXX: better stray handling */
2629 minp();
2630 q = buf;
2631 while (ch != c && ch != '\n' && ch != CH_EOF) {
2632 if ((q - buf) < sizeof(buf) - 1)
2633 *q++ = ch;
2634 minp();
2636 *q = '\0';
2637 minp();
2638 #if 0
2639 /* eat all spaces and comments after include */
2640 /* XXX: slightly incorrect */
2641 while (ch1 != '\n' && ch1 != CH_EOF)
2642 inp();
2643 #endif
2644 } else {
2645 /* computed #include : either we have only strings or
2646 we have anything enclosed in '<>' */
2647 next();
2648 buf[0] = '\0';
2649 if (tok == TOK_STR) {
2650 while (tok != TOK_LINEFEED) {
2651 if (tok != TOK_STR) {
2652 include_syntax:
2653 error("'#include' expects \"FILENAME\" or <FILENAME>");
2655 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2656 next();
2658 c = '\"';
2659 } else {
2660 int len;
2661 while (tok != TOK_LINEFEED) {
2662 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2663 next();
2665 len = strlen(buf);
2666 /* check syntax and remove '<>' */
2667 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2668 goto include_syntax;
2669 memmove(buf, buf + 1, len - 2);
2670 buf[len - 2] = '\0';
2671 c = '>';
2675 e = search_cached_include(s1, c, buf);
2676 if (e && define_find(e->ifndef_macro)) {
2677 /* no need to parse the include because the 'ifndef macro'
2678 is defined */
2679 #ifdef INC_DEBUG
2680 printf("%s: skipping %s\n", file->filename, buf);
2681 #endif
2682 } else {
2683 if (c == '\"') {
2684 /* first search in current dir if "header.h" */
2685 size = 0;
2686 p = strrchr(file->filename, '/');
2687 if (p)
2688 size = p + 1 - file->filename;
2689 if (size > sizeof(buf1) - 1)
2690 size = sizeof(buf1) - 1;
2691 memcpy(buf1, file->filename, size);
2692 buf1[size] = '\0';
2693 pstrcat(buf1, sizeof(buf1), buf);
2694 f = tcc_open(s1, buf1);
2695 if (f)
2696 goto found;
2698 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2699 error("#include recursion too deep");
2700 /* now search in all the include paths */
2701 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2702 for(i = 0; i < n; i++) {
2703 const char *path;
2704 if (i < s1->nb_include_paths)
2705 path = s1->include_paths[i];
2706 else
2707 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2708 pstrcpy(buf1, sizeof(buf1), path);
2709 pstrcat(buf1, sizeof(buf1), "/");
2710 pstrcat(buf1, sizeof(buf1), buf);
2711 f = tcc_open(s1, buf1);
2712 if (f)
2713 goto found;
2715 error("include file '%s' not found", buf);
2716 f = NULL;
2717 found:
2718 #ifdef INC_DEBUG
2719 printf("%s: including %s\n", file->filename, buf1);
2720 #endif
2721 f->inc_type = c;
2722 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2723 /* push current file in stack */
2724 /* XXX: fix current line init */
2725 *s1->include_stack_ptr++ = file;
2726 file = f;
2727 /* add include file debug info */
2728 if (do_debug) {
2729 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2731 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2732 ch = file->buf_ptr[0];
2733 goto the_end;
2735 break;
2736 case TOK_IFNDEF:
2737 c = 1;
2738 goto do_ifdef;
2739 case TOK_IF:
2740 c = expr_preprocess();
2741 goto do_if;
2742 case TOK_IFDEF:
2743 c = 0;
2744 do_ifdef:
2745 next_nomacro();
2746 if (tok < TOK_IDENT)
2747 error("invalid argument for '#if%sdef'", c ? "n" : "");
2748 if (is_bof) {
2749 if (c) {
2750 #ifdef INC_DEBUG
2751 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2752 #endif
2753 file->ifndef_macro = tok;
2756 c = (define_find(tok) != 0) ^ c;
2757 do_if:
2758 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2759 error("memory full");
2760 *s1->ifdef_stack_ptr++ = c;
2761 goto test_skip;
2762 case TOK_ELSE:
2763 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2764 error("#else without matching #if");
2765 if (s1->ifdef_stack_ptr[-1] & 2)
2766 error("#else after #else");
2767 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2768 goto test_skip;
2769 case TOK_ELIF:
2770 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2771 error("#elif without matching #if");
2772 c = s1->ifdef_stack_ptr[-1];
2773 if (c > 1)
2774 error("#elif after #else");
2775 /* last #if/#elif expression was true: we skip */
2776 if (c == 1)
2777 goto skip;
2778 c = expr_preprocess();
2779 s1->ifdef_stack_ptr[-1] = c;
2780 test_skip:
2781 if (!(c & 1)) {
2782 skip:
2783 preprocess_skip();
2784 is_bof = 0;
2785 goto redo;
2787 break;
2788 case TOK_ENDIF:
2789 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2790 error("#endif without matching #if");
2791 s1->ifdef_stack_ptr--;
2792 /* '#ifndef macro' was at the start of file. Now we check if
2793 an '#endif' is exactly at the end of file */
2794 if (file->ifndef_macro &&
2795 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2796 file->ifndef_macro_saved = file->ifndef_macro;
2797 /* need to set to zero to avoid false matches if another
2798 #ifndef at middle of file */
2799 file->ifndef_macro = 0;
2800 while (tok != TOK_LINEFEED)
2801 next_nomacro();
2802 tok_flags |= TOK_FLAG_ENDIF;
2803 goto the_end;
2805 break;
2806 case TOK_LINE:
2807 next();
2808 if (tok != TOK_CINT)
2809 error("#line");
2810 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2811 next();
2812 if (tok != TOK_LINEFEED) {
2813 if (tok != TOK_STR)
2814 error("#line");
2815 pstrcpy(file->filename, sizeof(file->filename),
2816 (char *)tokc.cstr->data);
2818 break;
2819 case TOK_ERROR:
2820 case TOK_WARNING:
2821 c = tok;
2822 ch = file->buf_ptr[0];
2823 skip_spaces();
2824 q = buf;
2825 while (ch != '\n' && ch != CH_EOF) {
2826 if ((q - buf) < sizeof(buf) - 1)
2827 *q++ = ch;
2828 minp();
2830 *q = '\0';
2831 if (c == TOK_ERROR)
2832 error("#error %s", buf);
2833 else
2834 warning("#warning %s", buf);
2835 break;
2836 case TOK_PRAGMA:
2837 /* ignored */
2838 break;
2839 default:
2840 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2841 /* '!' is ignored to allow C scripts. numbers are ignored
2842 to emulate cpp behaviour */
2843 } else {
2844 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2846 break;
2848 /* ignore other preprocess commands or #! for C scripts */
2849 while (tok != TOK_LINEFEED)
2850 next_nomacro();
2851 the_end:
2852 parse_flags = saved_parse_flags;
2855 /* evaluate escape codes in a string. */
2856 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2858 int c, n;
2859 const uint8_t *p;
2861 p = buf;
2862 for(;;) {
2863 c = *p;
2864 if (c == '\0')
2865 break;
2866 if (c == '\\') {
2867 p++;
2868 /* escape */
2869 c = *p;
2870 switch(c) {
2871 case '0': case '1': case '2': case '3':
2872 case '4': case '5': case '6': case '7':
2873 /* at most three octal digits */
2874 n = c - '0';
2875 p++;
2876 c = *p;
2877 if (isoct(c)) {
2878 n = n * 8 + c - '0';
2879 p++;
2880 c = *p;
2881 if (isoct(c)) {
2882 n = n * 8 + c - '0';
2883 p++;
2886 c = n;
2887 goto add_char_nonext;
2888 case 'x':
2889 p++;
2890 n = 0;
2891 for(;;) {
2892 c = *p;
2893 if (c >= 'a' && c <= 'f')
2894 c = c - 'a' + 10;
2895 else if (c >= 'A' && c <= 'F')
2896 c = c - 'A' + 10;
2897 else if (isnum(c))
2898 c = c - '0';
2899 else
2900 break;
2901 n = n * 16 + c;
2902 p++;
2904 c = n;
2905 goto add_char_nonext;
2906 case 'a':
2907 c = '\a';
2908 break;
2909 case 'b':
2910 c = '\b';
2911 break;
2912 case 'f':
2913 c = '\f';
2914 break;
2915 case 'n':
2916 c = '\n';
2917 break;
2918 case 'r':
2919 c = '\r';
2920 break;
2921 case 't':
2922 c = '\t';
2923 break;
2924 case 'v':
2925 c = '\v';
2926 break;
2927 case 'e':
2928 if (!gnu_ext)
2929 goto invalid_escape;
2930 c = 27;
2931 break;
2932 case '\'':
2933 case '\"':
2934 case '\\':
2935 case '?':
2936 break;
2937 default:
2938 invalid_escape:
2939 if (c >= '!' && c <= '~')
2940 warning("unknown escape sequence: \'\\%c\'", c);
2941 else
2942 warning("unknown escape sequence: \'\\x%x\'", c);
2943 break;
2946 p++;
2947 add_char_nonext:
2948 if (!is_long)
2949 cstr_ccat(outstr, c);
2950 else
2951 cstr_wccat(outstr, c);
2953 /* add a trailing '\0' */
2954 if (!is_long)
2955 cstr_ccat(outstr, '\0');
2956 else
2957 cstr_wccat(outstr, '\0');
2960 /* we use 64 bit numbers */
2961 #define BN_SIZE 2
2963 /* bn = (bn << shift) | or_val */
2964 void bn_lshift(unsigned int *bn, int shift, int or_val)
2966 int i;
2967 unsigned int v;
2968 for(i=0;i<BN_SIZE;i++) {
2969 v = bn[i];
2970 bn[i] = (v << shift) | or_val;
2971 or_val = v >> (32 - shift);
2975 void bn_zero(unsigned int *bn)
2977 int i;
2978 for(i=0;i<BN_SIZE;i++) {
2979 bn[i] = 0;
2983 /* parse number in null terminated string 'p' and return it in the
2984 current token */
2985 void parse_number(const char *p)
2987 int b, t, shift, frac_bits, s, exp_val, ch;
2988 char *q;
2989 unsigned int bn[BN_SIZE];
2990 double d;
2992 /* number */
2993 q = token_buf;
2994 ch = *p++;
2995 t = ch;
2996 ch = *p++;
2997 *q++ = t;
2998 b = 10;
2999 if (t == '.') {
3000 goto float_frac_parse;
3001 } else if (t == '0') {
3002 if (ch == 'x' || ch == 'X') {
3003 q--;
3004 ch = *p++;
3005 b = 16;
3006 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3007 q--;
3008 ch = *p++;
3009 b = 2;
3012 /* parse all digits. cannot check octal numbers at this stage
3013 because of floating point constants */
3014 while (1) {
3015 if (ch >= 'a' && ch <= 'f')
3016 t = ch - 'a' + 10;
3017 else if (ch >= 'A' && ch <= 'F')
3018 t = ch - 'A' + 10;
3019 else if (isnum(ch))
3020 t = ch - '0';
3021 else
3022 break;
3023 if (t >= b)
3024 break;
3025 if (q >= token_buf + STRING_MAX_SIZE) {
3026 num_too_long:
3027 error("number too long");
3029 *q++ = ch;
3030 ch = *p++;
3032 if (ch == '.' ||
3033 ((ch == 'e' || ch == 'E') && b == 10) ||
3034 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3035 if (b != 10) {
3036 /* NOTE: strtox should support that for hexa numbers, but
3037 non ISOC99 libcs do not support it, so we prefer to do
3038 it by hand */
3039 /* hexadecimal or binary floats */
3040 /* XXX: handle overflows */
3041 *q = '\0';
3042 if (b == 16)
3043 shift = 4;
3044 else
3045 shift = 2;
3046 bn_zero(bn);
3047 q = token_buf;
3048 while (1) {
3049 t = *q++;
3050 if (t == '\0') {
3051 break;
3052 } else if (t >= 'a') {
3053 t = t - 'a' + 10;
3054 } else if (t >= 'A') {
3055 t = t - 'A' + 10;
3056 } else {
3057 t = t - '0';
3059 bn_lshift(bn, shift, t);
3061 frac_bits = 0;
3062 if (ch == '.') {
3063 ch = *p++;
3064 while (1) {
3065 t = ch;
3066 if (t >= 'a' && t <= 'f') {
3067 t = t - 'a' + 10;
3068 } else if (t >= 'A' && t <= 'F') {
3069 t = t - 'A' + 10;
3070 } else if (t >= '0' && t <= '9') {
3071 t = t - '0';
3072 } else {
3073 break;
3075 if (t >= b)
3076 error("invalid digit");
3077 bn_lshift(bn, shift, t);
3078 frac_bits += shift;
3079 ch = *p++;
3082 if (ch != 'p' && ch != 'P')
3083 expect("exponent");
3084 ch = *p++;
3085 s = 1;
3086 exp_val = 0;
3087 if (ch == '+') {
3088 ch = *p++;
3089 } else if (ch == '-') {
3090 s = -1;
3091 ch = *p++;
3093 if (ch < '0' || ch > '9')
3094 expect("exponent digits");
3095 while (ch >= '0' && ch <= '9') {
3096 exp_val = exp_val * 10 + ch - '0';
3097 ch = *p++;
3099 exp_val = exp_val * s;
3101 /* now we can generate the number */
3102 /* XXX: should patch directly float number */
3103 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3104 d = ldexp(d, exp_val - frac_bits);
3105 t = toup(ch);
3106 if (t == 'F') {
3107 ch = *p++;
3108 tok = TOK_CFLOAT;
3109 /* float : should handle overflow */
3110 tokc.f = (float)d;
3111 } else if (t == 'L') {
3112 ch = *p++;
3113 tok = TOK_CLDOUBLE;
3114 /* XXX: not large enough */
3115 tokc.ld = (long double)d;
3116 } else {
3117 tok = TOK_CDOUBLE;
3118 tokc.d = d;
3120 } else {
3121 /* decimal floats */
3122 if (ch == '.') {
3123 if (q >= token_buf + STRING_MAX_SIZE)
3124 goto num_too_long;
3125 *q++ = ch;
3126 ch = *p++;
3127 float_frac_parse:
3128 while (ch >= '0' && ch <= '9') {
3129 if (q >= token_buf + STRING_MAX_SIZE)
3130 goto num_too_long;
3131 *q++ = ch;
3132 ch = *p++;
3135 if (ch == 'e' || ch == 'E') {
3136 if (q >= token_buf + STRING_MAX_SIZE)
3137 goto num_too_long;
3138 *q++ = ch;
3139 ch = *p++;
3140 if (ch == '-' || ch == '+') {
3141 if (q >= token_buf + STRING_MAX_SIZE)
3142 goto num_too_long;
3143 *q++ = ch;
3144 ch = *p++;
3146 if (ch < '0' || ch > '9')
3147 expect("exponent digits");
3148 while (ch >= '0' && ch <= '9') {
3149 if (q >= token_buf + STRING_MAX_SIZE)
3150 goto num_too_long;
3151 *q++ = ch;
3152 ch = *p++;
3155 *q = '\0';
3156 t = toup(ch);
3157 errno = 0;
3158 if (t == 'F') {
3159 ch = *p++;
3160 tok = TOK_CFLOAT;
3161 tokc.f = strtof(token_buf, NULL);
3162 } else if (t == 'L') {
3163 ch = *p++;
3164 tok = TOK_CLDOUBLE;
3165 tokc.ld = strtold(token_buf, NULL);
3166 } else {
3167 tok = TOK_CDOUBLE;
3168 tokc.d = strtod(token_buf, NULL);
3171 } else {
3172 unsigned long long n, n1;
3173 int lcount, ucount;
3175 /* integer number */
3176 *q = '\0';
3177 q = token_buf;
3178 if (b == 10 && *q == '0') {
3179 b = 8;
3180 q++;
3182 n = 0;
3183 while(1) {
3184 t = *q++;
3185 /* no need for checks except for base 10 / 8 errors */
3186 if (t == '\0') {
3187 break;
3188 } else if (t >= 'a') {
3189 t = t - 'a' + 10;
3190 } else if (t >= 'A') {
3191 t = t - 'A' + 10;
3192 } else {
3193 t = t - '0';
3194 if (t >= b)
3195 error("invalid digit");
3197 n1 = n;
3198 n = n * b + t;
3199 /* detect overflow */
3200 /* XXX: this test is not reliable */
3201 if (n < n1)
3202 error("integer constant overflow");
3205 /* XXX: not exactly ANSI compliant */
3206 if ((n & 0xffffffff00000000LL) != 0) {
3207 if ((n >> 63) != 0)
3208 tok = TOK_CULLONG;
3209 else
3210 tok = TOK_CLLONG;
3211 } else if (n > 0x7fffffff) {
3212 tok = TOK_CUINT;
3213 } else {
3214 tok = TOK_CINT;
3216 lcount = 0;
3217 ucount = 0;
3218 for(;;) {
3219 t = toup(ch);
3220 if (t == 'L') {
3221 if (lcount >= 2)
3222 error("three 'l's in integer constant");
3223 lcount++;
3224 if (lcount == 2) {
3225 if (tok == TOK_CINT)
3226 tok = TOK_CLLONG;
3227 else if (tok == TOK_CUINT)
3228 tok = TOK_CULLONG;
3230 ch = *p++;
3231 } else if (t == 'U') {
3232 if (ucount >= 1)
3233 error("two 'u's in integer constant");
3234 ucount++;
3235 if (tok == TOK_CINT)
3236 tok = TOK_CUINT;
3237 else if (tok == TOK_CLLONG)
3238 tok = TOK_CULLONG;
3239 ch = *p++;
3240 } else {
3241 break;
3244 if (tok == TOK_CINT || tok == TOK_CUINT)
3245 tokc.ui = n;
3246 else
3247 tokc.ull = n;
3252 #define PARSE2(c1, tok1, c2, tok2) \
3253 case c1: \
3254 PEEKC(c, p); \
3255 if (c == c2) { \
3256 p++; \
3257 tok = tok2; \
3258 } else { \
3259 tok = tok1; \
3261 break;
3263 /* return next token without macro substitution */
3264 static inline void next_nomacro1(void)
3266 int t, c, is_long;
3267 TokenSym *ts;
3268 uint8_t *p, *p1;
3269 unsigned int h;
3271 p = file->buf_ptr;
3272 redo_no_start:
3273 c = *p;
3274 switch(c) {
3275 case ' ':
3276 case '\t':
3277 case '\f':
3278 case '\v':
3279 case '\r':
3280 p++;
3281 goto redo_no_start;
3283 case '\\':
3284 /* first look if it is in fact an end of buffer */
3285 if (p >= file->buf_end) {
3286 file->buf_ptr = p;
3287 handle_eob();
3288 p = file->buf_ptr;
3289 if (p >= file->buf_end)
3290 goto parse_eof;
3291 else
3292 goto redo_no_start;
3293 } else {
3294 file->buf_ptr = p;
3295 ch = *p;
3296 handle_stray();
3297 p = file->buf_ptr;
3298 goto redo_no_start;
3300 parse_eof:
3302 TCCState *s1 = tcc_state;
3303 if (parse_flags & PARSE_FLAG_LINEFEED) {
3304 tok = TOK_LINEFEED;
3305 } else if (s1->include_stack_ptr == s1->include_stack ||
3306 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3307 /* no include left : end of file. */
3308 tok = TOK_EOF;
3309 } else {
3310 /* pop include file */
3312 /* test if previous '#endif' was after a #ifdef at
3313 start of file */
3314 if (tok_flags & TOK_FLAG_ENDIF) {
3315 #ifdef INC_DEBUG
3316 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3317 #endif
3318 add_cached_include(s1, file->inc_type, file->inc_filename,
3319 file->ifndef_macro_saved);
3322 /* add end of include file debug info */
3323 if (do_debug) {
3324 put_stabd(N_EINCL, 0, 0);
3326 /* pop include stack */
3327 tcc_close(file);
3328 s1->include_stack_ptr--;
3329 file = *s1->include_stack_ptr;
3330 p = file->buf_ptr;
3331 goto redo_no_start;
3334 break;
3336 case '\n':
3337 if (parse_flags & PARSE_FLAG_LINEFEED) {
3338 tok = TOK_LINEFEED;
3339 } else {
3340 file->line_num++;
3341 tok_flags |= TOK_FLAG_BOL;
3342 p++;
3343 goto redo_no_start;
3345 break;
3347 case '#':
3348 /* XXX: simplify */
3349 PEEKC(c, p);
3350 if ((tok_flags & TOK_FLAG_BOL) &&
3351 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3352 file->buf_ptr = p;
3353 preprocess(tok_flags & TOK_FLAG_BOF);
3354 p = file->buf_ptr;
3355 goto redo_no_start;
3356 } else {
3357 if (c == '#') {
3358 p++;
3359 tok = TOK_TWOSHARPS;
3360 } else {
3361 tok = '#';
3364 break;
3366 case 'a': case 'b': case 'c': case 'd':
3367 case 'e': case 'f': case 'g': case 'h':
3368 case 'i': case 'j': case 'k': case 'l':
3369 case 'm': case 'n': case 'o': case 'p':
3370 case 'q': case 'r': case 's': case 't':
3371 case 'u': case 'v': case 'w': case 'x':
3372 case 'y': case 'z':
3373 case 'A': case 'B': case 'C': case 'D':
3374 case 'E': case 'F': case 'G': case 'H':
3375 case 'I': case 'J': case 'K':
3376 case 'M': case 'N': case 'O': case 'P':
3377 case 'Q': case 'R': case 'S': case 'T':
3378 case 'U': case 'V': case 'W': case 'X':
3379 case 'Y': case 'Z':
3380 case '_':
3381 parse_ident_fast:
3382 p1 = p;
3383 h = TOK_HASH_INIT;
3384 h = TOK_HASH_FUNC(h, c);
3385 p++;
3386 for(;;) {
3387 c = *p;
3388 if (!isidnum_table[c])
3389 break;
3390 h = TOK_HASH_FUNC(h, c);
3391 p++;
3393 if (c != '\\') {
3394 TokenSym **pts;
3395 int len;
3397 /* fast case : no stray found, so we have the full token
3398 and we have already hashed it */
3399 len = p - p1;
3400 h &= (TOK_HASH_SIZE - 1);
3401 pts = &hash_ident[h];
3402 for(;;) {
3403 ts = *pts;
3404 if (!ts)
3405 break;
3406 if (ts->len == len && !memcmp(ts->str, p1, len))
3407 goto token_found;
3408 pts = &(ts->hash_next);
3410 ts = tok_alloc_new(pts, p1, len);
3411 token_found: ;
3412 } else {
3413 /* slower case */
3414 cstr_reset(&tokcstr);
3416 while (p1 < p) {
3417 cstr_ccat(&tokcstr, *p1);
3418 p1++;
3420 p--;
3421 PEEKC(c, p);
3422 parse_ident_slow:
3423 while (isidnum_table[c]) {
3424 cstr_ccat(&tokcstr, c);
3425 PEEKC(c, p);
3427 ts = tok_alloc(tokcstr.data, tokcstr.size);
3429 tok = ts->tok;
3430 break;
3431 case 'L':
3432 t = p[1];
3433 if (t != '\\' && t != '\'' && t != '\"') {
3434 /* fast case */
3435 goto parse_ident_fast;
3436 } else {
3437 PEEKC(c, p);
3438 if (c == '\'' || c == '\"') {
3439 is_long = 1;
3440 goto str_const;
3441 } else {
3442 cstr_reset(&tokcstr);
3443 cstr_ccat(&tokcstr, 'L');
3444 goto parse_ident_slow;
3447 break;
3448 case '0': case '1': case '2': case '3':
3449 case '4': case '5': case '6': case '7':
3450 case '8': case '9':
3452 cstr_reset(&tokcstr);
3453 /* after the first digit, accept digits, alpha, '.' or sign if
3454 prefixed by 'eEpP' */
3455 parse_num:
3456 for(;;) {
3457 t = c;
3458 cstr_ccat(&tokcstr, c);
3459 PEEKC(c, p);
3460 if (!(isnum(c) || isid(c) || c == '.' ||
3461 ((c == '+' || c == '-') &&
3462 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3463 break;
3465 /* We add a trailing '\0' to ease parsing */
3466 cstr_ccat(&tokcstr, '\0');
3467 tokc.cstr = &tokcstr;
3468 tok = TOK_PPNUM;
3469 break;
3470 case '.':
3471 /* special dot handling because it can also start a number */
3472 PEEKC(c, p);
3473 if (isnum(c)) {
3474 cstr_reset(&tokcstr);
3475 cstr_ccat(&tokcstr, '.');
3476 goto parse_num;
3477 } else if (c == '.') {
3478 PEEKC(c, p);
3479 if (c != '.')
3480 expect("'.'");
3481 PEEKC(c, p);
3482 tok = TOK_DOTS;
3483 } else {
3484 tok = '.';
3486 break;
3487 case '\'':
3488 case '\"':
3489 is_long = 0;
3490 str_const:
3492 CString str;
3493 int sep;
3495 sep = c;
3497 /* parse the string */
3498 cstr_new(&str);
3499 p = parse_pp_string(p, sep, &str);
3500 cstr_ccat(&str, '\0');
3502 /* eval the escape (should be done as TOK_PPNUM) */
3503 cstr_reset(&tokcstr);
3504 parse_escape_string(&tokcstr, str.data, is_long);
3505 cstr_free(&str);
3507 if (sep == '\'') {
3508 int char_size;
3509 /* XXX: make it portable */
3510 if (!is_long)
3511 char_size = 1;
3512 else
3513 char_size = sizeof(int);
3514 if (tokcstr.size <= char_size)
3515 error("empty character constant");
3516 if (tokcstr.size > 2 * char_size)
3517 warning("multi-character character constant");
3518 if (!is_long) {
3519 tokc.i = *(int8_t *)tokcstr.data;
3520 tok = TOK_CCHAR;
3521 } else {
3522 tokc.i = *(int *)tokcstr.data;
3523 tok = TOK_LCHAR;
3525 } else {
3526 tokc.cstr = &tokcstr;
3527 if (!is_long)
3528 tok = TOK_STR;
3529 else
3530 tok = TOK_LSTR;
3533 break;
3535 case '<':
3536 PEEKC(c, p);
3537 if (c == '=') {
3538 p++;
3539 tok = TOK_LE;
3540 } else if (c == '<') {
3541 PEEKC(c, p);
3542 if (c == '=') {
3543 p++;
3544 tok = TOK_A_SHL;
3545 } else {
3546 tok = TOK_SHL;
3548 } else {
3549 tok = TOK_LT;
3551 break;
3553 case '>':
3554 PEEKC(c, p);
3555 if (c == '=') {
3556 p++;
3557 tok = TOK_GE;
3558 } else if (c == '>') {
3559 PEEKC(c, p);
3560 if (c == '=') {
3561 p++;
3562 tok = TOK_A_SAR;
3563 } else {
3564 tok = TOK_SAR;
3566 } else {
3567 tok = TOK_GT;
3569 break;
3571 case '&':
3572 PEEKC(c, p);
3573 if (c == '&') {
3574 p++;
3575 tok = TOK_LAND;
3576 } else if (c == '=') {
3577 p++;
3578 tok = TOK_A_AND;
3579 } else {
3580 tok = '&';
3582 break;
3584 case '|':
3585 PEEKC(c, p);
3586 if (c == '|') {
3587 p++;
3588 tok = TOK_LOR;
3589 } else if (c == '=') {
3590 p++;
3591 tok = TOK_A_OR;
3592 } else {
3593 tok = '|';
3595 break;
3597 case '+':
3598 PEEKC(c, p);
3599 if (c == '+') {
3600 p++;
3601 tok = TOK_INC;
3602 } else if (c == '=') {
3603 p++;
3604 tok = TOK_A_ADD;
3605 } else {
3606 tok = '+';
3608 break;
3610 case '-':
3611 PEEKC(c, p);
3612 if (c == '-') {
3613 p++;
3614 tok = TOK_DEC;
3615 } else if (c == '=') {
3616 p++;
3617 tok = TOK_A_SUB;
3618 } else if (c == '>') {
3619 p++;
3620 tok = TOK_ARROW;
3621 } else {
3622 tok = '-';
3624 break;
3626 PARSE2('!', '!', '=', TOK_NE)
3627 PARSE2('=', '=', '=', TOK_EQ)
3628 PARSE2('*', '*', '=', TOK_A_MUL)
3629 PARSE2('%', '%', '=', TOK_A_MOD)
3630 PARSE2('^', '^', '=', TOK_A_XOR)
3632 /* comments or operator */
3633 case '/':
3634 PEEKC(c, p);
3635 if (c == '*') {
3636 p = parse_comment(p);
3637 goto redo_no_start;
3638 } else if (c == '/') {
3639 p = parse_line_comment(p);
3640 goto redo_no_start;
3641 } else if (c == '=') {
3642 p++;
3643 tok = TOK_A_DIV;
3644 } else {
3645 tok = '/';
3647 break;
3649 /* simple tokens */
3650 case '(':
3651 case ')':
3652 case '[':
3653 case ']':
3654 case '{':
3655 case '}':
3656 case ',':
3657 case ';':
3658 case ':':
3659 case '?':
3660 case '~':
3661 case '$': /* only used in assembler */
3662 tok = c;
3663 p++;
3664 break;
3665 default:
3666 error("unrecognized character \\x%02x", c);
3667 break;
3669 file->buf_ptr = p;
3670 tok_flags = 0;
3671 #if defined(PARSE_DEBUG)
3672 printf("token = %s\n", get_tok_str(tok, &tokc));
3673 #endif
3676 /* return next token without macro substitution. Can read input from
3677 macro_ptr buffer */
3678 static void next_nomacro(void)
3680 if (macro_ptr) {
3681 redo:
3682 tok = *macro_ptr;
3683 if (tok) {
3684 TOK_GET(tok, macro_ptr, tokc);
3685 if (tok == TOK_LINENUM) {
3686 file->line_num = tokc.i;
3687 goto redo;
3690 } else {
3691 next_nomacro1();
3695 /* substitute args in macro_str and return allocated string */
3696 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3698 int *st, last_tok, t, notfirst;
3699 Sym *s;
3700 CValue cval;
3701 TokenString str;
3702 CString cstr;
3704 tok_str_new(&str);
3705 last_tok = 0;
3706 while(1) {
3707 TOK_GET(t, macro_str, cval);
3708 if (!t)
3709 break;
3710 if (t == '#') {
3711 /* stringize */
3712 TOK_GET(t, macro_str, cval);
3713 if (!t)
3714 break;
3715 s = sym_find2(args, t);
3716 if (s) {
3717 cstr_new(&cstr);
3718 st = (int *)s->c;
3719 notfirst = 0;
3720 while (*st) {
3721 if (notfirst)
3722 cstr_ccat(&cstr, ' ');
3723 TOK_GET(t, st, cval);
3724 cstr_cat(&cstr, get_tok_str(t, &cval));
3725 notfirst = 1;
3727 cstr_ccat(&cstr, '\0');
3728 #ifdef PP_DEBUG
3729 printf("stringize: %s\n", (char *)cstr.data);
3730 #endif
3731 /* add string */
3732 cval.cstr = &cstr;
3733 tok_str_add2(&str, TOK_STR, &cval);
3734 cstr_free(&cstr);
3735 } else {
3736 tok_str_add2(&str, t, &cval);
3738 } else if (t >= TOK_IDENT) {
3739 s = sym_find2(args, t);
3740 if (s) {
3741 st = (int *)s->c;
3742 /* if '##' is present before or after, no arg substitution */
3743 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3744 /* special case for var arg macros : ## eats the
3745 ',' if empty VA_ARGS variable. */
3746 /* XXX: test of the ',' is not 100%
3747 reliable. should fix it to avoid security
3748 problems */
3749 if (gnu_ext && s->type.t &&
3750 last_tok == TOK_TWOSHARPS &&
3751 str.len >= 2 && str.str[str.len - 2] == ',') {
3752 if (*st == 0) {
3753 /* suppress ',' '##' */
3754 str.len -= 2;
3755 } else {
3756 /* suppress '##' and add variable */
3757 str.len--;
3758 goto add_var;
3760 } else {
3761 int t1;
3762 add_var:
3763 for(;;) {
3764 TOK_GET(t1, st, cval);
3765 if (!t1)
3766 break;
3767 tok_str_add2(&str, t1, &cval);
3770 } else {
3771 /* NOTE: the stream cannot be read when macro
3772 substituing an argument */
3773 macro_subst(&str, nested_list, st, 0);
3775 } else {
3776 tok_str_add(&str, t);
3778 } else {
3779 tok_str_add2(&str, t, &cval);
3781 last_tok = t;
3783 tok_str_add(&str, 0);
3784 return str.str;
3787 static char const ab_month_name[12][4] =
3789 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3790 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3793 /* do macro substitution of current token with macro 's' and add
3794 result to (tok_str,tok_len). 'nested_list' is the list of all
3795 macros we got inside to avoid recursing. Return non zero if no
3796 substitution needs to be done */
3797 static int macro_subst_tok(TokenString *tok_str,
3798 Sym **nested_list, Sym *s, int can_read_stream)
3800 Sym *args, *sa, *sa1;
3801 int mstr_allocated, parlevel, *mstr, t;
3802 TokenString str;
3803 char *cstrval;
3804 CValue cval;
3805 CString cstr;
3807 /* if symbol is a macro, prepare substitution */
3809 /* special macros */
3810 if (tok == TOK___LINE__) {
3811 cval.i = file->line_num;
3812 tok_str_add2(tok_str, TOK_CINT, &cval);
3813 } else if (tok == TOK___FILE__) {
3814 cstrval = file->filename;
3815 goto add_cstr;
3816 tok_str_add2(tok_str, TOK_STR, &cval);
3817 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3818 time_t ti;
3819 struct tm *tm;
3820 char buf[64];
3822 time(&ti);
3823 tm = localtime(&ti);
3824 if (tok == TOK___DATE__) {
3825 snprintf(buf, sizeof(buf), "%s %2d %d",
3826 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3827 } else {
3828 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3829 tm->tm_hour, tm->tm_min, tm->tm_sec);
3831 cstrval = buf;
3832 add_cstr:
3833 cstr_new(&cstr);
3834 cstr_cat(&cstr, cstrval);
3835 cstr_ccat(&cstr, '\0');
3836 cval.cstr = &cstr;
3837 tok_str_add2(tok_str, TOK_STR, &cval);
3838 cstr_free(&cstr);
3839 } else {
3840 mstr = (int *)s->c;
3841 mstr_allocated = 0;
3842 if (s->type.t == MACRO_FUNC) {
3843 /* NOTE: we do not use next_nomacro to avoid eating the
3844 next token. XXX: find better solution */
3845 if (macro_ptr) {
3846 t = *macro_ptr;
3847 if (t == 0 && can_read_stream) {
3848 /* end of macro stream: we must look at the token
3849 after in the file */
3850 macro_ptr = NULL;
3851 goto parse_stream;
3853 } else {
3854 parse_stream:
3855 /* XXX: incorrect with comments */
3856 ch = file->buf_ptr[0];
3857 while (is_space(ch) || ch == '\n')
3858 cinp();
3859 t = ch;
3861 if (t != '(') /* no macro subst */
3862 return -1;
3864 /* argument macro */
3865 next_nomacro();
3866 next_nomacro();
3867 args = NULL;
3868 sa = s->next;
3869 /* NOTE: empty args are allowed, except if no args */
3870 for(;;) {
3871 /* handle '()' case */
3872 if (!args && !sa && tok == ')')
3873 break;
3874 if (!sa)
3875 error("macro '%s' used with too many args",
3876 get_tok_str(s->v, 0));
3877 tok_str_new(&str);
3878 parlevel = 0;
3879 /* NOTE: non zero sa->t indicates VA_ARGS */
3880 while ((parlevel > 0 ||
3881 (tok != ')' &&
3882 (tok != ',' || sa->type.t))) &&
3883 tok != -1) {
3884 if (tok == '(')
3885 parlevel++;
3886 else if (tok == ')')
3887 parlevel--;
3888 tok_str_add2(&str, tok, &tokc);
3889 next_nomacro();
3891 tok_str_add(&str, 0);
3892 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3893 sa = sa->next;
3894 if (tok == ')') {
3895 /* special case for gcc var args: add an empty
3896 var arg argument if it is omitted */
3897 if (sa && sa->type.t && gnu_ext)
3898 continue;
3899 else
3900 break;
3902 if (tok != ',')
3903 expect(",");
3904 next_nomacro();
3906 if (sa) {
3907 error("macro '%s' used with too few args",
3908 get_tok_str(s->v, 0));
3911 /* now subst each arg */
3912 mstr = macro_arg_subst(nested_list, mstr, args);
3913 /* free memory */
3914 sa = args;
3915 while (sa) {
3916 sa1 = sa->prev;
3917 tok_str_free((int *)sa->c);
3918 tcc_free(sa);
3919 sa = sa1;
3921 mstr_allocated = 1;
3923 sym_push2(nested_list, s->v, 0, 0);
3924 macro_subst(tok_str, nested_list, mstr, 1);
3925 /* pop nested defined symbol */
3926 sa1 = *nested_list;
3927 *nested_list = sa1->prev;
3928 tcc_free(sa1);
3929 if (mstr_allocated)
3930 tok_str_free(mstr);
3932 return 0;
3935 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3936 return the resulting string (which must be freed). */
3937 static inline int *macro_twosharps(const int *macro_str)
3939 TokenSym *ts;
3940 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3941 int t;
3942 const char *p1, *p2;
3943 CValue cval;
3944 TokenString macro_str1;
3945 CString cstr;
3947 start_macro_ptr = macro_str;
3948 /* we search the first '##' */
3949 for(;;) {
3950 macro_ptr1 = macro_str;
3951 TOK_GET(t, macro_str, cval);
3952 /* nothing more to do if end of string */
3953 if (t == 0)
3954 return NULL;
3955 if (*macro_str == TOK_TWOSHARPS)
3956 break;
3959 /* we saw '##', so we need more processing to handle it */
3960 cstr_new(&cstr);
3961 tok_str_new(&macro_str1);
3962 tok = t;
3963 tokc = cval;
3965 /* add all tokens seen so far */
3966 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
3967 TOK_GET(t, ptr, cval);
3968 tok_str_add2(&macro_str1, t, &cval);
3970 saved_macro_ptr = macro_ptr;
3971 /* XXX: get rid of the use of macro_ptr here */
3972 macro_ptr = (int *)macro_str;
3973 for(;;) {
3974 while (*macro_ptr == TOK_TWOSHARPS) {
3975 macro_ptr++;
3976 macro_ptr1 = macro_ptr;
3977 t = *macro_ptr;
3978 if (t) {
3979 TOK_GET(t, macro_ptr, cval);
3980 /* We concatenate the two tokens if we have an
3981 identifier or a preprocessing number */
3982 cstr_reset(&cstr);
3983 p1 = get_tok_str(tok, &tokc);
3984 cstr_cat(&cstr, p1);
3985 p2 = get_tok_str(t, &cval);
3986 cstr_cat(&cstr, p2);
3987 cstr_ccat(&cstr, '\0');
3989 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3990 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3991 if (tok == TOK_PPNUM) {
3992 /* if number, then create a number token */
3993 /* NOTE: no need to allocate because
3994 tok_str_add2() does it */
3995 tokc.cstr = &cstr;
3996 } else {
3997 /* if identifier, we must do a test to
3998 validate we have a correct identifier */
3999 if (t == TOK_PPNUM) {
4000 const char *p;
4001 int c;
4003 p = p2;
4004 for(;;) {
4005 c = *p;
4006 if (c == '\0')
4007 break;
4008 p++;
4009 if (!isnum(c) && !isid(c))
4010 goto error_pasting;
4013 ts = tok_alloc(cstr.data, strlen(cstr.data));
4014 tok = ts->tok; /* modify current token */
4016 } else {
4017 const char *str = cstr.data;
4018 const unsigned char *q;
4020 /* we look for a valid token */
4021 /* XXX: do more extensive checks */
4022 if (!strcmp(str, ">>=")) {
4023 tok = TOK_A_SAR;
4024 } else if (!strcmp(str, "<<=")) {
4025 tok = TOK_A_SHL;
4026 } else if (strlen(str) == 2) {
4027 /* search in two bytes table */
4028 q = tok_two_chars;
4029 for(;;) {
4030 if (!*q)
4031 goto error_pasting;
4032 if (q[0] == str[0] && q[1] == str[1])
4033 break;
4034 q += 3;
4036 tok = q[2];
4037 } else {
4038 error_pasting:
4039 /* NOTE: because get_tok_str use a static buffer,
4040 we must save it */
4041 cstr_reset(&cstr);
4042 p1 = get_tok_str(tok, &tokc);
4043 cstr_cat(&cstr, p1);
4044 cstr_ccat(&cstr, '\0');
4045 p2 = get_tok_str(t, &cval);
4046 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4047 /* cannot merge tokens: just add them separately */
4048 tok_str_add2(&macro_str1, tok, &tokc);
4049 /* XXX: free associated memory ? */
4050 tok = t;
4051 tokc = cval;
4056 tok_str_add2(&macro_str1, tok, &tokc);
4057 next_nomacro();
4058 if (tok == 0)
4059 break;
4061 macro_ptr = (int *)saved_macro_ptr;
4062 cstr_free(&cstr);
4063 tok_str_add(&macro_str1, 0);
4064 return macro_str1.str;
4068 /* do macro substitution of macro_str and add result to
4069 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4070 inside to avoid recursing. */
4071 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4072 const int *macro_str, int can_read_stream)
4074 Sym *s;
4075 int *saved_macro_ptr, *macro_str1;
4076 const int *ptr;
4077 int t, ret;
4078 CValue cval;
4080 /* first scan for '##' operator handling */
4081 ptr = macro_str;
4082 macro_str1 = macro_twosharps(ptr);
4083 if (macro_str1)
4084 ptr = macro_str1;
4085 while (1) {
4086 /* NOTE: ptr == NULL can only happen if tokens are read from
4087 file stream due to a macro function call */
4088 if (ptr == NULL)
4089 break;
4090 TOK_GET(t, ptr, cval);
4091 if (t == 0)
4092 break;
4093 s = define_find(t);
4094 if (s != NULL) {
4095 /* if nested substitution, do nothing */
4096 if (sym_find2(*nested_list, t))
4097 goto no_subst;
4098 saved_macro_ptr = macro_ptr;
4099 macro_ptr = (int *)ptr;
4100 tok = t;
4101 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4102 ptr = (int *)macro_ptr;
4103 macro_ptr = saved_macro_ptr;
4104 if (ret != 0)
4105 goto no_subst;
4106 } else {
4107 no_subst:
4108 tok_str_add2(tok_str, t, &cval);
4111 if (macro_str1)
4112 tok_str_free(macro_str1);
4115 /* return next token with macro substitution */
4116 static void next(void)
4118 Sym *nested_list, *s;
4119 TokenString str;
4121 redo:
4122 next_nomacro();
4123 if (!macro_ptr) {
4124 /* if not reading from macro substituted string, then try
4125 to substitute macros */
4126 if (tok >= TOK_IDENT &&
4127 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4128 s = define_find(tok);
4129 if (s) {
4130 /* we have a macro: we try to substitute */
4131 tok_str_new(&str);
4132 nested_list = NULL;
4133 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4134 /* substitution done, NOTE: maybe empty */
4135 tok_str_add(&str, 0);
4136 macro_ptr = str.str;
4137 macro_ptr_allocated = str.str;
4138 goto redo;
4142 } else {
4143 if (tok == 0) {
4144 /* end of macro or end of unget buffer */
4145 if (unget_buffer_enabled) {
4146 macro_ptr = unget_saved_macro_ptr;
4147 unget_buffer_enabled = 0;
4148 } else {
4149 /* end of macro string: free it */
4150 tok_str_free(macro_ptr_allocated);
4151 macro_ptr = NULL;
4153 goto redo;
4157 /* convert preprocessor tokens into C tokens */
4158 if (tok == TOK_PPNUM &&
4159 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4160 parse_number((char *)tokc.cstr->data);
4164 /* push back current token and set current token to 'last_tok'. Only
4165 identifier case handled for labels. */
4166 static inline void unget_tok(int last_tok)
4168 int i, n;
4169 int *q;
4170 unget_saved_macro_ptr = macro_ptr;
4171 unget_buffer_enabled = 1;
4172 q = unget_saved_buffer;
4173 macro_ptr = q;
4174 *q++ = tok;
4175 n = tok_ext_size(tok) - 1;
4176 for(i=0;i<n;i++)
4177 *q++ = tokc.tab[i];
4178 *q = 0; /* end of token string */
4179 tok = last_tok;
4183 void swap(int *p, int *q)
4185 int t;
4186 t = *p;
4187 *p = *q;
4188 *q = t;
4191 void vsetc(CType *type, int r, CValue *vc)
4193 int v;
4195 if (vtop >= vstack + VSTACK_SIZE)
4196 error("memory full");
4197 /* cannot let cpu flags if other instruction are generated. Also
4198 avoid leaving VT_JMP anywhere except on the top of the stack
4199 because it would complicate the code generator. */
4200 if (vtop >= vstack) {
4201 v = vtop->r & VT_VALMASK;
4202 if (v == VT_CMP || (v & ~1) == VT_JMP)
4203 gv(RC_INT);
4205 vtop++;
4206 vtop->type = *type;
4207 vtop->r = r;
4208 vtop->r2 = VT_CONST;
4209 vtop->c = *vc;
4212 /* push integer constant */
4213 void vpushi(int v)
4215 CValue cval;
4216 cval.i = v;
4217 vsetc(&int_type, VT_CONST, &cval);
4220 /* Return a static symbol pointing to a section */
4221 static Sym *get_sym_ref(CType *type, Section *sec,
4222 unsigned long offset, unsigned long size)
4224 int v;
4225 Sym *sym;
4227 v = anon_sym++;
4228 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4229 sym->type.ref = type->ref;
4230 sym->r = VT_CONST | VT_SYM;
4231 put_extern_sym(sym, sec, offset, size);
4232 return sym;
4235 /* push a reference to a section offset by adding a dummy symbol */
4236 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4238 CValue cval;
4240 cval.ul = 0;
4241 vsetc(type, VT_CONST | VT_SYM, &cval);
4242 vtop->sym = get_sym_ref(type, sec, offset, size);
4245 /* define a new external reference to a symbol 'v' of type 'u' */
4246 static Sym *external_global_sym(int v, CType *type, int r)
4248 Sym *s;
4250 s = sym_find(v);
4251 if (!s) {
4252 /* push forward reference */
4253 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4254 s->type.ref = type->ref;
4255 s->r = r | VT_CONST | VT_SYM;
4257 return s;
4260 /* define a new external reference to a symbol 'v' of type 'u' */
4261 static Sym *external_sym(int v, CType *type, int r)
4263 Sym *s;
4265 s = sym_find(v);
4266 if (!s) {
4267 /* push forward reference */
4268 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4269 s->type.t |= VT_EXTERN;
4270 } else {
4271 if (!is_compatible_types(&s->type, type))
4272 error("incompatible types for redefinition of '%s'",
4273 get_tok_str(v, NULL));
4275 return s;
4278 /* push a reference to global symbol v */
4279 static void vpush_global_sym(CType *type, int v)
4281 Sym *sym;
4282 CValue cval;
4284 sym = external_global_sym(v, type, 0);
4285 cval.ul = 0;
4286 vsetc(type, VT_CONST | VT_SYM, &cval);
4287 vtop->sym = sym;
4290 void vset(CType *type, int r, int v)
4292 CValue cval;
4294 cval.i = v;
4295 vsetc(type, r, &cval);
4298 void vseti(int r, int v)
4300 CType type;
4301 type.t = VT_INT;
4302 vset(&type, r, v);
4305 void vswap(void)
4307 SValue tmp;
4309 tmp = vtop[0];
4310 vtop[0] = vtop[-1];
4311 vtop[-1] = tmp;
4314 void vpushv(SValue *v)
4316 if (vtop >= vstack + VSTACK_SIZE)
4317 error("memory full");
4318 vtop++;
4319 *vtop = *v;
4322 void vdup(void)
4324 vpushv(vtop);
4327 /* save r to the memory stack, and mark it as being free */
4328 void save_reg(int r)
4330 int l, saved, size, align;
4331 SValue *p, sv;
4332 CType *type;
4334 /* modify all stack values */
4335 saved = 0;
4336 l = 0;
4337 for(p=vstack;p<=vtop;p++) {
4338 if ((p->r & VT_VALMASK) == r ||
4339 (p->r2 & VT_VALMASK) == r) {
4340 /* must save value on stack if not already done */
4341 if (!saved) {
4342 /* NOTE: must reload 'r' because r might be equal to r2 */
4343 r = p->r & VT_VALMASK;
4344 /* store register in the stack */
4345 type = &p->type;
4346 if ((p->r & VT_LVAL) ||
4347 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4348 type = &int_type;
4349 size = type_size(type, &align);
4350 loc = (loc - size) & -align;
4351 sv.type.t = type->t;
4352 sv.r = VT_LOCAL | VT_LVAL;
4353 sv.c.ul = loc;
4354 store(r, &sv);
4355 #ifdef TCC_TARGET_I386
4356 /* x86 specific: need to pop fp register ST0 if saved */
4357 if (r == TREG_ST0) {
4358 o(0xd9dd); /* fstp %st(1) */
4360 #endif
4361 /* special long long case */
4362 if ((type->t & VT_BTYPE) == VT_LLONG) {
4363 sv.c.ul += 4;
4364 store(p->r2, &sv);
4366 l = loc;
4367 saved = 1;
4369 /* mark that stack entry as being saved on the stack */
4370 if (p->r & VT_LVAL) {
4371 /* also clear the bounded flag because the
4372 relocation address of the function was stored in
4373 p->c.ul */
4374 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4375 } else {
4376 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4378 p->r2 = VT_CONST;
4379 p->c.ul = l;
4384 /* find a register of class 'rc2' with at most one reference on stack.
4385 * If none, call get_reg(rc) */
4386 int get_reg_ex(int rc, int rc2)
4388 int r;
4389 SValue *p;
4391 for(r=0;r<NB_REGS;r++) {
4392 if (reg_classes[r] & rc2) {
4393 int n;
4394 n=0;
4395 for(p = vstack; p <= vtop; p++) {
4396 if ((p->r & VT_VALMASK) == r ||
4397 (p->r2 & VT_VALMASK) == r)
4398 n++;
4400 if (n <= 1)
4401 return r;
4404 return get_reg(rc);
4407 /* find a free register of class 'rc'. If none, save one register */
4408 int get_reg(int rc)
4410 int r;
4411 SValue *p;
4413 /* find a free register */
4414 for(r=0;r<NB_REGS;r++) {
4415 if (reg_classes[r] & rc) {
4416 for(p=vstack;p<=vtop;p++) {
4417 if ((p->r & VT_VALMASK) == r ||
4418 (p->r2 & VT_VALMASK) == r)
4419 goto notfound;
4421 return r;
4423 notfound: ;
4426 /* no register left : free the first one on the stack (VERY
4427 IMPORTANT to start from the bottom to ensure that we don't
4428 spill registers used in gen_opi()) */
4429 for(p=vstack;p<=vtop;p++) {
4430 r = p->r & VT_VALMASK;
4431 if (r < VT_CONST && (reg_classes[r] & rc))
4432 goto save_found;
4433 /* also look at second register (if long long) */
4434 r = p->r2 & VT_VALMASK;
4435 if (r < VT_CONST && (reg_classes[r] & rc)) {
4436 save_found:
4437 save_reg(r);
4438 return r;
4441 /* Should never comes here */
4442 return -1;
4445 /* save registers up to (vtop - n) stack entry */
4446 void save_regs(int n)
4448 int r;
4449 SValue *p, *p1;
4450 p1 = vtop - n;
4451 for(p = vstack;p <= p1; p++) {
4452 r = p->r & VT_VALMASK;
4453 if (r < VT_CONST) {
4454 save_reg(r);
4459 /* move register 's' to 'r', and flush previous value of r to memory
4460 if needed */
4461 void move_reg(int r, int s)
4463 SValue sv;
4465 if (r != s) {
4466 save_reg(r);
4467 sv.type.t = VT_INT;
4468 sv.r = s;
4469 sv.c.ul = 0;
4470 load(r, &sv);
4474 /* get address of vtop (vtop MUST BE an lvalue) */
4475 void gaddrof(void)
4477 vtop->r &= ~VT_LVAL;
4478 /* tricky: if saved lvalue, then we can go back to lvalue */
4479 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4480 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4483 #ifdef CONFIG_TCC_BCHECK
4484 /* generate lvalue bound code */
4485 void gbound(void)
4487 int lval_type;
4488 CType type1;
4490 vtop->r &= ~VT_MUSTBOUND;
4491 /* if lvalue, then use checking code before dereferencing */
4492 if (vtop->r & VT_LVAL) {
4493 /* if not VT_BOUNDED value, then make one */
4494 if (!(vtop->r & VT_BOUNDED)) {
4495 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4496 /* must save type because we must set it to int to get pointer */
4497 type1 = vtop->type;
4498 vtop->type.t = VT_INT;
4499 gaddrof();
4500 vpushi(0);
4501 gen_bounded_ptr_add();
4502 vtop->r |= lval_type;
4503 vtop->type = type1;
4505 /* then check for dereferencing */
4506 gen_bounded_ptr_deref();
4509 #endif
4511 /* store vtop a register belonging to class 'rc'. lvalues are
4512 converted to values. Cannot be used if cannot be converted to
4513 register value (such as structures). */
4514 int gv(int rc)
4516 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4517 unsigned long long ll;
4519 /* NOTE: get_reg can modify vstack[] */
4520 if (vtop->type.t & VT_BITFIELD) {
4521 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4522 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4523 /* remove bit field info to avoid loops */
4524 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4525 /* generate shifts */
4526 vpushi(32 - (bit_pos + bit_size));
4527 gen_op(TOK_SHL);
4528 vpushi(32 - bit_size);
4529 /* NOTE: transformed to SHR if unsigned */
4530 gen_op(TOK_SAR);
4531 r = gv(rc);
4532 } else {
4533 if (is_float(vtop->type.t) &&
4534 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4535 Sym *sym;
4536 int *ptr;
4537 unsigned long offset;
4539 /* XXX: unify with initializers handling ? */
4540 /* CPUs usually cannot use float constants, so we store them
4541 generically in data segment */
4542 size = type_size(&vtop->type, &align);
4543 offset = (data_section->data_offset + align - 1) & -align;
4544 data_section->data_offset = offset;
4545 /* XXX: not portable yet */
4546 ptr = section_ptr_add(data_section, size);
4547 size = size >> 2;
4548 for(i=0;i<size;i++)
4549 ptr[i] = vtop->c.tab[i];
4550 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4551 vtop->r |= VT_LVAL | VT_SYM;
4552 vtop->sym = sym;
4553 vtop->c.ul = 0;
4555 #ifdef CONFIG_TCC_BCHECK
4556 if (vtop->r & VT_MUSTBOUND)
4557 gbound();
4558 #endif
4560 r = vtop->r & VT_VALMASK;
4561 /* need to reload if:
4562 - constant
4563 - lvalue (need to dereference pointer)
4564 - already a register, but not in the right class */
4565 if (r >= VT_CONST ||
4566 (vtop->r & VT_LVAL) ||
4567 !(reg_classes[r] & rc) ||
4568 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4569 !(reg_classes[vtop->r2] & rc))) {
4570 r = get_reg(rc);
4571 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4572 /* two register type load : expand to two words
4573 temporarily */
4574 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4575 /* load constant */
4576 ll = vtop->c.ull;
4577 vtop->c.ui = ll; /* first word */
4578 load(r, vtop);
4579 vtop->r = r; /* save register value */
4580 vpushi(ll >> 32); /* second word */
4581 } else if (r >= VT_CONST ||
4582 (vtop->r & VT_LVAL)) {
4583 /* load from memory */
4584 load(r, vtop);
4585 vdup();
4586 vtop[-1].r = r; /* save register value */
4587 /* increment pointer to get second word */
4588 vtop->type.t = VT_INT;
4589 gaddrof();
4590 vpushi(4);
4591 gen_op('+');
4592 vtop->r |= VT_LVAL;
4593 } else {
4594 /* move registers */
4595 load(r, vtop);
4596 vdup();
4597 vtop[-1].r = r; /* save register value */
4598 vtop->r = vtop[-1].r2;
4600 /* allocate second register */
4601 rc2 = RC_INT;
4602 if (rc == RC_IRET)
4603 rc2 = RC_LRET;
4604 r2 = get_reg(rc2);
4605 load(r2, vtop);
4606 vpop();
4607 /* write second register */
4608 vtop->r2 = r2;
4609 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4610 int t1, t;
4611 /* lvalue of scalar type : need to use lvalue type
4612 because of possible cast */
4613 t = vtop->type.t;
4614 t1 = t;
4615 /* compute memory access type */
4616 if (vtop->r & VT_LVAL_BYTE)
4617 t = VT_BYTE;
4618 else if (vtop->r & VT_LVAL_SHORT)
4619 t = VT_SHORT;
4620 if (vtop->r & VT_LVAL_UNSIGNED)
4621 t |= VT_UNSIGNED;
4622 vtop->type.t = t;
4623 load(r, vtop);
4624 /* restore wanted type */
4625 vtop->type.t = t1;
4626 } else {
4627 /* one register type load */
4628 load(r, vtop);
4631 vtop->r = r;
4632 #ifdef TCC_TARGET_C67
4633 /* uses register pairs for doubles */
4634 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4635 vtop->r2 = r+1;
4636 #endif
4638 return r;
4641 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4642 void gv2(int rc1, int rc2)
4644 int v;
4646 /* generate more generic register first. But VT_JMP or VT_CMP
4647 values must be generated first in all cases to avoid possible
4648 reload errors */
4649 v = vtop[0].r & VT_VALMASK;
4650 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4651 vswap();
4652 gv(rc1);
4653 vswap();
4654 gv(rc2);
4655 /* test if reload is needed for first register */
4656 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4657 vswap();
4658 gv(rc1);
4659 vswap();
4661 } else {
4662 gv(rc2);
4663 vswap();
4664 gv(rc1);
4665 vswap();
4666 /* test if reload is needed for first register */
4667 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4668 gv(rc2);
4673 /* expand long long on stack in two int registers */
4674 void lexpand(void)
4676 int u;
4678 u = vtop->type.t & VT_UNSIGNED;
4679 gv(RC_INT);
4680 vdup();
4681 vtop[0].r = vtop[-1].r2;
4682 vtop[0].r2 = VT_CONST;
4683 vtop[-1].r2 = VT_CONST;
4684 vtop[0].type.t = VT_INT | u;
4685 vtop[-1].type.t = VT_INT | u;
4688 /* build a long long from two ints */
4689 void lbuild(int t)
4691 gv2(RC_INT, RC_INT);
4692 vtop[-1].r2 = vtop[0].r;
4693 vtop[-1].type.t = t;
4694 vpop();
4697 /* rotate n first stack elements to the bottom
4698 I1 ... In -> I2 ... In I1 [top is right]
4700 void vrotb(int n)
4702 int i;
4703 SValue tmp;
4705 tmp = vtop[-n + 1];
4706 for(i=-n+1;i!=0;i++)
4707 vtop[i] = vtop[i+1];
4708 vtop[0] = tmp;
4711 /* rotate n first stack elements to the top
4712 I1 ... In -> In I1 ... I(n-1) [top is right]
4714 void vrott(int n)
4716 int i;
4717 SValue tmp;
4719 tmp = vtop[0];
4720 for(i = 0;i < n - 1; i++)
4721 vtop[-i] = vtop[-i - 1];
4722 vtop[-n + 1] = tmp;
4725 /* pop stack value */
4726 void vpop(void)
4728 int v;
4729 v = vtop->r & VT_VALMASK;
4730 #ifdef TCC_TARGET_I386
4731 /* for x86, we need to pop the FP stack */
4732 if (v == TREG_ST0 && !nocode_wanted) {
4733 o(0xd9dd); /* fstp %st(1) */
4734 } else
4735 #endif
4736 if (v == VT_JMP || v == VT_JMPI) {
4737 /* need to put correct jump if && or || without test */
4738 gsym(vtop->c.ul);
4740 vtop--;
4743 /* convert stack entry to register and duplicate its value in another
4744 register */
4745 void gv_dup(void)
4747 int rc, t, r, r1;
4748 SValue sv;
4750 t = vtop->type.t;
4751 if ((t & VT_BTYPE) == VT_LLONG) {
4752 lexpand();
4753 gv_dup();
4754 vswap();
4755 vrotb(3);
4756 gv_dup();
4757 vrotb(4);
4758 /* stack: H L L1 H1 */
4759 lbuild(t);
4760 vrotb(3);
4761 vrotb(3);
4762 vswap();
4763 lbuild(t);
4764 vswap();
4765 } else {
4766 /* duplicate value */
4767 rc = RC_INT;
4768 sv.type.t = VT_INT;
4769 if (is_float(t)) {
4770 rc = RC_FLOAT;
4771 sv.type.t = t;
4773 r = gv(rc);
4774 r1 = get_reg(rc);
4775 sv.r = r;
4776 sv.c.ul = 0;
4777 load(r1, &sv); /* move r to r1 */
4778 vdup();
4779 /* duplicates value */
4780 vtop->r = r1;
4784 /* generate CPU independent (unsigned) long long operations */
4785 void gen_opl(int op)
4787 int t, a, b, op1, c, i;
4788 int func;
4789 SValue tmp;
4791 switch(op) {
4792 case '/':
4793 case TOK_PDIV:
4794 func = TOK___divdi3;
4795 goto gen_func;
4796 case TOK_UDIV:
4797 func = TOK___udivdi3;
4798 goto gen_func;
4799 case '%':
4800 func = TOK___moddi3;
4801 goto gen_func;
4802 case TOK_UMOD:
4803 func = TOK___umoddi3;
4804 gen_func:
4805 /* call generic long long function */
4806 vpush_global_sym(&func_old_type, func);
4807 vrott(3);
4808 gfunc_call(2);
4809 vpushi(0);
4810 vtop->r = REG_IRET;
4811 vtop->r2 = REG_LRET;
4812 break;
4813 case '^':
4814 case '&':
4815 case '|':
4816 case '*':
4817 case '+':
4818 case '-':
4819 t = vtop->type.t;
4820 vswap();
4821 lexpand();
4822 vrotb(3);
4823 lexpand();
4824 /* stack: L1 H1 L2 H2 */
4825 tmp = vtop[0];
4826 vtop[0] = vtop[-3];
4827 vtop[-3] = tmp;
4828 tmp = vtop[-2];
4829 vtop[-2] = vtop[-3];
4830 vtop[-3] = tmp;
4831 vswap();
4832 /* stack: H1 H2 L1 L2 */
4833 if (op == '*') {
4834 vpushv(vtop - 1);
4835 vpushv(vtop - 1);
4836 gen_op(TOK_UMULL);
4837 lexpand();
4838 /* stack: H1 H2 L1 L2 ML MH */
4839 for(i=0;i<4;i++)
4840 vrotb(6);
4841 /* stack: ML MH H1 H2 L1 L2 */
4842 tmp = vtop[0];
4843 vtop[0] = vtop[-2];
4844 vtop[-2] = tmp;
4845 /* stack: ML MH H1 L2 H2 L1 */
4846 gen_op('*');
4847 vrotb(3);
4848 vrotb(3);
4849 gen_op('*');
4850 /* stack: ML MH M1 M2 */
4851 gen_op('+');
4852 gen_op('+');
4853 } else if (op == '+' || op == '-') {
4854 /* XXX: add non carry method too (for MIPS or alpha) */
4855 if (op == '+')
4856 op1 = TOK_ADDC1;
4857 else
4858 op1 = TOK_SUBC1;
4859 gen_op(op1);
4860 /* stack: H1 H2 (L1 op L2) */
4861 vrotb(3);
4862 vrotb(3);
4863 gen_op(op1 + 1); /* TOK_xxxC2 */
4864 } else {
4865 gen_op(op);
4866 /* stack: H1 H2 (L1 op L2) */
4867 vrotb(3);
4868 vrotb(3);
4869 /* stack: (L1 op L2) H1 H2 */
4870 gen_op(op);
4871 /* stack: (L1 op L2) (H1 op H2) */
4873 /* stack: L H */
4874 lbuild(t);
4875 break;
4876 case TOK_SAR:
4877 case TOK_SHR:
4878 case TOK_SHL:
4879 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4880 t = vtop[-1].type.t;
4881 vswap();
4882 lexpand();
4883 vrotb(3);
4884 /* stack: L H shift */
4885 c = (int)vtop->c.i;
4886 /* constant: simpler */
4887 /* NOTE: all comments are for SHL. the other cases are
4888 done by swaping words */
4889 vpop();
4890 if (op != TOK_SHL)
4891 vswap();
4892 if (c >= 32) {
4893 /* stack: L H */
4894 vpop();
4895 if (c > 32) {
4896 vpushi(c - 32);
4897 gen_op(op);
4899 if (op != TOK_SAR) {
4900 vpushi(0);
4901 } else {
4902 gv_dup();
4903 vpushi(31);
4904 gen_op(TOK_SAR);
4906 vswap();
4907 } else {
4908 vswap();
4909 gv_dup();
4910 /* stack: H L L */
4911 vpushi(c);
4912 gen_op(op);
4913 vswap();
4914 vpushi(32 - c);
4915 if (op == TOK_SHL)
4916 gen_op(TOK_SHR);
4917 else
4918 gen_op(TOK_SHL);
4919 vrotb(3);
4920 /* stack: L L H */
4921 vpushi(c);
4922 if (op == TOK_SHL)
4923 gen_op(TOK_SHL);
4924 else
4925 gen_op(TOK_SHR);
4926 gen_op('|');
4928 if (op != TOK_SHL)
4929 vswap();
4930 lbuild(t);
4931 } else {
4932 /* XXX: should provide a faster fallback on x86 ? */
4933 switch(op) {
4934 case TOK_SAR:
4935 func = TOK___sardi3;
4936 goto gen_func;
4937 case TOK_SHR:
4938 func = TOK___shrdi3;
4939 goto gen_func;
4940 case TOK_SHL:
4941 func = TOK___shldi3;
4942 goto gen_func;
4945 break;
4946 default:
4947 /* compare operations */
4948 t = vtop->type.t;
4949 vswap();
4950 lexpand();
4951 vrotb(3);
4952 lexpand();
4953 /* stack: L1 H1 L2 H2 */
4954 tmp = vtop[-1];
4955 vtop[-1] = vtop[-2];
4956 vtop[-2] = tmp;
4957 /* stack: L1 L2 H1 H2 */
4958 /* compare high */
4959 op1 = op;
4960 /* when values are equal, we need to compare low words. since
4961 the jump is inverted, we invert the test too. */
4962 if (op1 == TOK_LT)
4963 op1 = TOK_LE;
4964 else if (op1 == TOK_GT)
4965 op1 = TOK_GE;
4966 else if (op1 == TOK_ULT)
4967 op1 = TOK_ULE;
4968 else if (op1 == TOK_UGT)
4969 op1 = TOK_UGE;
4970 a = 0;
4971 b = 0;
4972 gen_op(op1);
4973 if (op1 != TOK_NE) {
4974 a = gtst(1, 0);
4976 if (op != TOK_EQ) {
4977 /* generate non equal test */
4978 /* XXX: NOT PORTABLE yet */
4979 if (a == 0) {
4980 b = gtst(0, 0);
4981 } else {
4982 #if defined(TCC_TARGET_I386)
4983 b = psym(0x850f, 0);
4984 #elif defined(TCC_TARGET_ARM)
4985 b = ind;
4986 o(0x1A000000 | encbranch(ind, 0, 1));
4987 #elif defined(TCC_TARGET_C67)
4988 error("not implemented");
4989 #else
4990 #error not supported
4991 #endif
4994 /* compare low. Always unsigned */
4995 op1 = op;
4996 if (op1 == TOK_LT)
4997 op1 = TOK_ULT;
4998 else if (op1 == TOK_LE)
4999 op1 = TOK_ULE;
5000 else if (op1 == TOK_GT)
5001 op1 = TOK_UGT;
5002 else if (op1 == TOK_GE)
5003 op1 = TOK_UGE;
5004 gen_op(op1);
5005 a = gtst(1, a);
5006 gsym(b);
5007 vseti(VT_JMPI, a);
5008 break;
5012 /* handle integer constant optimizations and various machine
5013 independent opt */
5014 void gen_opic(int op)
5016 int fc, c1, c2, n;
5017 SValue *v1, *v2;
5019 v1 = vtop - 1;
5020 v2 = vtop;
5021 /* currently, we cannot do computations with forward symbols */
5022 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5023 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5024 if (c1 && c2) {
5025 fc = v2->c.i;
5026 switch(op) {
5027 case '+': v1->c.i += fc; break;
5028 case '-': v1->c.i -= fc; break;
5029 case '&': v1->c.i &= fc; break;
5030 case '^': v1->c.i ^= fc; break;
5031 case '|': v1->c.i |= fc; break;
5032 case '*': v1->c.i *= fc; break;
5034 case TOK_PDIV:
5035 case '/':
5036 case '%':
5037 case TOK_UDIV:
5038 case TOK_UMOD:
5039 /* if division by zero, generate explicit division */
5040 if (fc == 0) {
5041 if (const_wanted)
5042 error("division by zero in constant");
5043 goto general_case;
5045 switch(op) {
5046 default: v1->c.i /= fc; break;
5047 case '%': v1->c.i %= fc; break;
5048 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5049 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5051 break;
5052 case TOK_SHL: v1->c.i <<= fc; break;
5053 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5054 case TOK_SAR: v1->c.i >>= fc; break;
5055 /* tests */
5056 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5057 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5058 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5059 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5060 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5061 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5062 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5063 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5064 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5065 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5066 /* logical */
5067 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5068 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5069 default:
5070 goto general_case;
5072 vtop--;
5073 } else {
5074 /* if commutative ops, put c2 as constant */
5075 if (c1 && (op == '+' || op == '&' || op == '^' ||
5076 op == '|' || op == '*')) {
5077 vswap();
5078 swap(&c1, &c2);
5080 fc = vtop->c.i;
5081 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5082 op == TOK_PDIV) &&
5083 fc == 1) ||
5084 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5085 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5086 fc == 0) ||
5087 (op == '&' &&
5088 fc == -1))) {
5089 /* nothing to do */
5090 vtop--;
5091 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5092 /* try to use shifts instead of muls or divs */
5093 if (fc > 0 && (fc & (fc - 1)) == 0) {
5094 n = -1;
5095 while (fc) {
5096 fc >>= 1;
5097 n++;
5099 vtop->c.i = n;
5100 if (op == '*')
5101 op = TOK_SHL;
5102 else if (op == TOK_PDIV)
5103 op = TOK_SAR;
5104 else
5105 op = TOK_SHR;
5107 goto general_case;
5108 } else if (c2 && (op == '+' || op == '-') &&
5109 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5110 (VT_CONST | VT_SYM)) {
5111 /* symbol + constant case */
5112 if (op == '-')
5113 fc = -fc;
5114 vtop--;
5115 vtop->c.i += fc;
5116 } else {
5117 general_case:
5118 if (!nocode_wanted) {
5119 /* call low level op generator */
5120 gen_opi(op);
5121 } else {
5122 vtop--;
5128 /* generate a floating point operation with constant propagation */
5129 void gen_opif(int op)
5131 int c1, c2;
5132 SValue *v1, *v2;
5133 long double f1, f2;
5135 v1 = vtop - 1;
5136 v2 = vtop;
5137 /* currently, we cannot do computations with forward symbols */
5138 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5139 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5140 if (c1 && c2) {
5141 if (v1->type.t == VT_FLOAT) {
5142 f1 = v1->c.f;
5143 f2 = v2->c.f;
5144 } else if (v1->type.t == VT_DOUBLE) {
5145 f1 = v1->c.d;
5146 f2 = v2->c.d;
5147 } else {
5148 f1 = v1->c.ld;
5149 f2 = v2->c.ld;
5152 /* NOTE: we only do constant propagation if finite number (not
5153 NaN or infinity) (ANSI spec) */
5154 if (!ieee_finite(f1) || !ieee_finite(f2))
5155 goto general_case;
5157 switch(op) {
5158 case '+': f1 += f2; break;
5159 case '-': f1 -= f2; break;
5160 case '*': f1 *= f2; break;
5161 case '/':
5162 if (f2 == 0.0) {
5163 if (const_wanted)
5164 error("division by zero in constant");
5165 goto general_case;
5167 f1 /= f2;
5168 break;
5169 /* XXX: also handles tests ? */
5170 default:
5171 goto general_case;
5173 /* XXX: overflow test ? */
5174 if (v1->type.t == VT_FLOAT) {
5175 v1->c.f = f1;
5176 } else if (v1->type.t == VT_DOUBLE) {
5177 v1->c.d = f1;
5178 } else {
5179 v1->c.ld = f1;
5181 vtop--;
5182 } else {
5183 general_case:
5184 if (!nocode_wanted) {
5185 gen_opf(op);
5186 } else {
5187 vtop--;
5192 static int pointed_size(CType *type)
5194 int align;
5195 return type_size(pointed_type(type), &align);
5198 static inline int is_null_pointer(SValue *p)
5200 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5201 return 0;
5202 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5203 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5206 static inline int is_integer_btype(int bt)
5208 return (bt == VT_BYTE || bt == VT_SHORT ||
5209 bt == VT_INT || bt == VT_LLONG);
5212 /* check types for comparison or substraction of pointers */
5213 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5215 CType *type1, *type2, tmp_type1, tmp_type2;
5216 int bt1, bt2;
5218 /* null pointers are accepted for all comparisons as gcc */
5219 if (is_null_pointer(p1) || is_null_pointer(p2))
5220 return;
5221 type1 = &p1->type;
5222 type2 = &p2->type;
5223 bt1 = type1->t & VT_BTYPE;
5224 bt2 = type2->t & VT_BTYPE;
5225 /* accept comparison between pointer and integer with a warning */
5226 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5227 warning("comparison between pointer and integer");
5228 return;
5231 /* both must be pointers or implicit function pointers */
5232 if (bt1 == VT_PTR) {
5233 type1 = pointed_type(type1);
5234 } else if (bt1 != VT_FUNC)
5235 goto invalid_operands;
5237 if (bt2 == VT_PTR) {
5238 type2 = pointed_type(type2);
5239 } else if (bt2 != VT_FUNC) {
5240 invalid_operands:
5241 error("invalid operands to binary %s", get_tok_str(op, NULL));
5243 if ((type1->t & VT_BTYPE) == VT_VOID ||
5244 (type2->t & VT_BTYPE) == VT_VOID)
5245 return;
5246 tmp_type1 = *type1;
5247 tmp_type2 = *type2;
5248 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5249 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5250 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5251 /* gcc-like error if '-' is used */
5252 if (op == '-')
5253 goto invalid_operands;
5254 else
5255 warning("comparison of distinct pointer types lacks a cast");
5259 /* generic gen_op: handles types problems */
5260 void gen_op(int op)
5262 int u, t1, t2, bt1, bt2, t;
5263 CType type1;
5265 t1 = vtop[-1].type.t;
5266 t2 = vtop[0].type.t;
5267 bt1 = t1 & VT_BTYPE;
5268 bt2 = t2 & VT_BTYPE;
5270 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5271 /* at least one operand is a pointer */
5272 /* relationnal op: must be both pointers */
5273 if (op >= TOK_ULT && op <= TOK_GT) {
5274 check_comparison_pointer_types(vtop - 1, vtop, op);
5275 /* pointers are handled are unsigned */
5276 t = VT_INT | VT_UNSIGNED;
5277 goto std_op;
5279 /* if both pointers, then it must be the '-' op */
5280 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5281 if (op != '-')
5282 error("cannot use pointers here");
5283 check_comparison_pointer_types(vtop - 1, vtop, op);
5284 /* XXX: check that types are compatible */
5285 u = pointed_size(&vtop[-1].type);
5286 gen_opic(op);
5287 /* set to integer type */
5288 vtop->type.t = VT_INT;
5289 vpushi(u);
5290 gen_op(TOK_PDIV);
5291 } else {
5292 /* exactly one pointer : must be '+' or '-'. */
5293 if (op != '-' && op != '+')
5294 error("cannot use pointers here");
5295 /* Put pointer as first operand */
5296 if (bt2 == VT_PTR) {
5297 vswap();
5298 swap(&t1, &t2);
5300 type1 = vtop[-1].type;
5301 /* XXX: cast to int ? (long long case) */
5302 vpushi(pointed_size(&vtop[-1].type));
5303 gen_op('*');
5304 #ifdef CONFIG_TCC_BCHECK
5305 /* if evaluating constant expression, no code should be
5306 generated, so no bound check */
5307 if (do_bounds_check && !const_wanted) {
5308 /* if bounded pointers, we generate a special code to
5309 test bounds */
5310 if (op == '-') {
5311 vpushi(0);
5312 vswap();
5313 gen_op('-');
5315 gen_bounded_ptr_add();
5316 } else
5317 #endif
5319 gen_opic(op);
5321 /* put again type if gen_opic() swaped operands */
5322 vtop->type = type1;
5324 } else if (is_float(bt1) || is_float(bt2)) {
5325 /* compute bigger type and do implicit casts */
5326 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5327 t = VT_LDOUBLE;
5328 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5329 t = VT_DOUBLE;
5330 } else {
5331 t = VT_FLOAT;
5333 /* floats can only be used for a few operations */
5334 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5335 (op < TOK_ULT || op > TOK_GT))
5336 error("invalid operands for binary operation");
5337 goto std_op;
5338 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5339 /* cast to biggest op */
5340 t = VT_LLONG;
5341 /* convert to unsigned if it does not fit in a long long */
5342 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5343 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5344 t |= VT_UNSIGNED;
5345 goto std_op;
5346 } else {
5347 /* integer operations */
5348 t = VT_INT;
5349 /* convert to unsigned if it does not fit in an integer */
5350 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5351 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5352 t |= VT_UNSIGNED;
5353 std_op:
5354 /* XXX: currently, some unsigned operations are explicit, so
5355 we modify them here */
5356 if (t & VT_UNSIGNED) {
5357 if (op == TOK_SAR)
5358 op = TOK_SHR;
5359 else if (op == '/')
5360 op = TOK_UDIV;
5361 else if (op == '%')
5362 op = TOK_UMOD;
5363 else if (op == TOK_LT)
5364 op = TOK_ULT;
5365 else if (op == TOK_GT)
5366 op = TOK_UGT;
5367 else if (op == TOK_LE)
5368 op = TOK_ULE;
5369 else if (op == TOK_GE)
5370 op = TOK_UGE;
5372 vswap();
5373 type1.t = t;
5374 gen_cast(&type1);
5375 vswap();
5376 /* special case for shifts and long long: we keep the shift as
5377 an integer */
5378 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5379 type1.t = VT_INT;
5380 gen_cast(&type1);
5381 if (is_float(t))
5382 gen_opif(op);
5383 else if ((t & VT_BTYPE) == VT_LLONG)
5384 gen_opl(op);
5385 else
5386 gen_opic(op);
5387 if (op >= TOK_ULT && op <= TOK_GT) {
5388 /* relationnal op: the result is an int */
5389 vtop->type.t = VT_INT;
5390 } else {
5391 vtop->type.t = t;
5396 /* generic itof for unsigned long long case */
5397 void gen_cvt_itof1(int t)
5399 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5400 (VT_LLONG | VT_UNSIGNED)) {
5402 if (t == VT_FLOAT)
5403 vpush_global_sym(&func_old_type, TOK___ulltof);
5404 else if (t == VT_DOUBLE)
5405 vpush_global_sym(&func_old_type, TOK___ulltod);
5406 else
5407 vpush_global_sym(&func_old_type, TOK___ulltold);
5408 vrott(2);
5409 gfunc_call(1);
5410 vpushi(0);
5411 vtop->r = REG_FRET;
5412 } else {
5413 gen_cvt_itof(t);
5417 /* generic ftoi for unsigned long long case */
5418 void gen_cvt_ftoi1(int t)
5420 int st;
5422 if (t == (VT_LLONG | VT_UNSIGNED)) {
5423 /* not handled natively */
5424 st = vtop->type.t & VT_BTYPE;
5425 if (st == VT_FLOAT)
5426 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5427 else if (st == VT_DOUBLE)
5428 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5429 else
5430 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5431 vrott(2);
5432 gfunc_call(1);
5433 vpushi(0);
5434 vtop->r = REG_IRET;
5435 vtop->r2 = REG_LRET;
5436 } else {
5437 gen_cvt_ftoi(t);
5441 /* force char or short cast */
5442 void force_charshort_cast(int t)
5444 int bits, dbt;
5445 dbt = t & VT_BTYPE;
5446 /* XXX: add optimization if lvalue : just change type and offset */
5447 if (dbt == VT_BYTE)
5448 bits = 8;
5449 else
5450 bits = 16;
5451 if (t & VT_UNSIGNED) {
5452 vpushi((1 << bits) - 1);
5453 gen_op('&');
5454 } else {
5455 bits = 32 - bits;
5456 vpushi(bits);
5457 gen_op(TOK_SHL);
5458 vpushi(bits);
5459 gen_op(TOK_SAR);
5463 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5464 static void gen_cast(CType *type)
5466 int sbt, dbt, sf, df, c;
5468 /* special delayed cast for char/short */
5469 /* XXX: in some cases (multiple cascaded casts), it may still
5470 be incorrect */
5471 if (vtop->r & VT_MUSTCAST) {
5472 vtop->r &= ~VT_MUSTCAST;
5473 force_charshort_cast(vtop->type.t);
5476 /* bitfields first get cast to ints */
5477 if (vtop->type.t & VT_BITFIELD) {
5478 gv(RC_INT);
5481 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5482 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5484 if (sbt != dbt && !nocode_wanted) {
5485 sf = is_float(sbt);
5486 df = is_float(dbt);
5487 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5488 if (sf && df) {
5489 /* convert from fp to fp */
5490 if (c) {
5491 /* constant case: we can do it now */
5492 /* XXX: in ISOC, cannot do it if error in convert */
5493 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5494 vtop->c.f = (float)vtop->c.d;
5495 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5496 vtop->c.f = (float)vtop->c.ld;
5497 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5498 vtop->c.d = (double)vtop->c.f;
5499 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5500 vtop->c.d = (double)vtop->c.ld;
5501 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5502 vtop->c.ld = (long double)vtop->c.f;
5503 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5504 vtop->c.ld = (long double)vtop->c.d;
5505 } else {
5506 /* non constant case: generate code */
5507 gen_cvt_ftof(dbt);
5509 } else if (df) {
5510 /* convert int to fp */
5511 if (c) {
5512 switch(sbt) {
5513 case VT_LLONG | VT_UNSIGNED:
5514 case VT_LLONG:
5515 /* XXX: add const cases for long long */
5516 goto do_itof;
5517 case VT_INT | VT_UNSIGNED:
5518 switch(dbt) {
5519 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5520 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5521 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5523 break;
5524 default:
5525 switch(dbt) {
5526 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5527 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5528 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5530 break;
5532 } else {
5533 do_itof:
5534 #if !defined(TCC_TARGET_ARM)
5535 gen_cvt_itof1(dbt);
5536 #else
5537 gen_cvt_itof(dbt);
5538 #endif
5540 } else if (sf) {
5541 /* convert fp to int */
5542 /* we handle char/short/etc... with generic code */
5543 if (dbt != (VT_INT | VT_UNSIGNED) &&
5544 dbt != (VT_LLONG | VT_UNSIGNED) &&
5545 dbt != VT_LLONG)
5546 dbt = VT_INT;
5547 if (c) {
5548 switch(dbt) {
5549 case VT_LLONG | VT_UNSIGNED:
5550 case VT_LLONG:
5551 /* XXX: add const cases for long long */
5552 goto do_ftoi;
5553 case VT_INT | VT_UNSIGNED:
5554 switch(sbt) {
5555 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5556 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5557 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5559 break;
5560 default:
5561 /* int case */
5562 switch(sbt) {
5563 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5564 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5565 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5567 break;
5569 } else {
5570 do_ftoi:
5571 gen_cvt_ftoi1(dbt);
5573 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5574 /* additional cast for char/short/bool... */
5575 vtop->type.t = dbt;
5576 gen_cast(type);
5578 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5579 if ((sbt & VT_BTYPE) != VT_LLONG) {
5580 /* scalar to long long */
5581 if (c) {
5582 if (sbt == (VT_INT | VT_UNSIGNED))
5583 vtop->c.ll = vtop->c.ui;
5584 else
5585 vtop->c.ll = vtop->c.i;
5586 } else {
5587 /* machine independent conversion */
5588 gv(RC_INT);
5589 /* generate high word */
5590 if (sbt == (VT_INT | VT_UNSIGNED)) {
5591 vpushi(0);
5592 gv(RC_INT);
5593 } else {
5594 gv_dup();
5595 vpushi(31);
5596 gen_op(TOK_SAR);
5598 /* patch second register */
5599 vtop[-1].r2 = vtop->r;
5600 vpop();
5603 } else if (dbt == VT_BOOL) {
5604 /* scalar to bool */
5605 vpushi(0);
5606 gen_op(TOK_NE);
5607 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5608 (dbt & VT_BTYPE) == VT_SHORT) {
5609 force_charshort_cast(dbt);
5610 } else if ((dbt & VT_BTYPE) == VT_INT) {
5611 /* scalar to int */
5612 if (sbt == VT_LLONG) {
5613 /* from long long: just take low order word */
5614 lexpand();
5615 vpop();
5617 /* if lvalue and single word type, nothing to do because
5618 the lvalue already contains the real type size (see
5619 VT_LVAL_xxx constants) */
5622 vtop->type = *type;
5625 /* return type size. Put alignment at 'a' */
5626 static int type_size(CType *type, int *a)
5628 Sym *s;
5629 int bt;
5631 bt = type->t & VT_BTYPE;
5632 if (bt == VT_STRUCT) {
5633 /* struct/union */
5634 s = type->ref;
5635 *a = s->r;
5636 return s->c;
5637 } else if (bt == VT_PTR) {
5638 if (type->t & VT_ARRAY) {
5639 s = type->ref;
5640 return type_size(&s->type, a) * s->c;
5641 } else {
5642 *a = PTR_SIZE;
5643 return PTR_SIZE;
5645 } else if (bt == VT_LDOUBLE) {
5646 *a = LDOUBLE_ALIGN;
5647 return LDOUBLE_SIZE;
5648 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5649 #ifdef TCC_TARGET_I386
5650 *a = 4;
5651 #else
5652 *a = 8;
5653 #endif
5654 return 8;
5655 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5656 *a = 4;
5657 return 4;
5658 } else if (bt == VT_SHORT) {
5659 *a = 2;
5660 return 2;
5661 } else {
5662 /* char, void, function, _Bool */
5663 *a = 1;
5664 return 1;
5668 /* return the pointed type of t */
5669 static inline CType *pointed_type(CType *type)
5671 return &type->ref->type;
5674 /* modify type so that its it is a pointer to type. */
5675 static void mk_pointer(CType *type)
5677 Sym *s;
5678 s = sym_push(SYM_FIELD, type, 0, -1);
5679 type->t = VT_PTR | (type->t & ~VT_TYPE);
5680 type->ref = s;
5683 /* compare function types. OLD functions match any new functions */
5684 static int is_compatible_func(CType *type1, CType *type2)
5686 Sym *s1, *s2;
5688 s1 = type1->ref;
5689 s2 = type2->ref;
5690 if (!is_compatible_types(&s1->type, &s2->type))
5691 return 0;
5692 /* XXX: not complete */
5693 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5694 return 1;
5695 if (s1->c != s2->c)
5696 return 0;
5697 while (s1 != NULL) {
5698 if (s2 == NULL)
5699 return 0;
5700 if (!is_compatible_types(&s1->type, &s2->type))
5701 return 0;
5702 s1 = s1->next;
5703 s2 = s2->next;
5705 if (s2)
5706 return 0;
5707 return 1;
5710 /* return true if type1 and type2 are exactly the same (including
5711 qualifiers).
5713 - enums are not checked as gcc __builtin_types_compatible_p ()
5715 static int is_compatible_types(CType *type1, CType *type2)
5717 int bt1, t1, t2;
5719 t1 = type1->t & VT_TYPE;
5720 t2 = type2->t & VT_TYPE;
5721 /* XXX: bitfields ? */
5722 if (t1 != t2)
5723 return 0;
5724 /* test more complicated cases */
5725 bt1 = t1 & VT_BTYPE;
5726 if (bt1 == VT_PTR) {
5727 type1 = pointed_type(type1);
5728 type2 = pointed_type(type2);
5729 return is_compatible_types(type1, type2);
5730 } else if (bt1 == VT_STRUCT) {
5731 return (type1->ref == type2->ref);
5732 } else if (bt1 == VT_FUNC) {
5733 return is_compatible_func(type1, type2);
5734 } else {
5735 return 1;
5739 /* print a type. If 'varstr' is not NULL, then the variable is also
5740 printed in the type */
5741 /* XXX: union */
5742 /* XXX: add array and function pointers */
5743 void type_to_str(char *buf, int buf_size,
5744 CType *type, const char *varstr)
5746 int bt, v, t;
5747 Sym *s, *sa;
5748 char buf1[256];
5749 const char *tstr;
5751 t = type->t & VT_TYPE;
5752 bt = t & VT_BTYPE;
5753 buf[0] = '\0';
5754 if (t & VT_CONSTANT)
5755 pstrcat(buf, buf_size, "const ");
5756 if (t & VT_VOLATILE)
5757 pstrcat(buf, buf_size, "volatile ");
5758 if (t & VT_UNSIGNED)
5759 pstrcat(buf, buf_size, "unsigned ");
5760 switch(bt) {
5761 case VT_VOID:
5762 tstr = "void";
5763 goto add_tstr;
5764 case VT_BOOL:
5765 tstr = "_Bool";
5766 goto add_tstr;
5767 case VT_BYTE:
5768 tstr = "char";
5769 goto add_tstr;
5770 case VT_SHORT:
5771 tstr = "short";
5772 goto add_tstr;
5773 case VT_INT:
5774 tstr = "int";
5775 goto add_tstr;
5776 case VT_LONG:
5777 tstr = "long";
5778 goto add_tstr;
5779 case VT_LLONG:
5780 tstr = "long long";
5781 goto add_tstr;
5782 case VT_FLOAT:
5783 tstr = "float";
5784 goto add_tstr;
5785 case VT_DOUBLE:
5786 tstr = "double";
5787 goto add_tstr;
5788 case VT_LDOUBLE:
5789 tstr = "long double";
5790 add_tstr:
5791 pstrcat(buf, buf_size, tstr);
5792 break;
5793 case VT_ENUM:
5794 case VT_STRUCT:
5795 if (bt == VT_STRUCT)
5796 tstr = "struct ";
5797 else
5798 tstr = "enum ";
5799 pstrcat(buf, buf_size, tstr);
5800 v = type->ref->v & ~SYM_STRUCT;
5801 if (v >= SYM_FIRST_ANOM)
5802 pstrcat(buf, buf_size, "<anonymous>");
5803 else
5804 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5805 break;
5806 case VT_FUNC:
5807 s = type->ref;
5808 type_to_str(buf, buf_size, &s->type, varstr);
5809 pstrcat(buf, buf_size, "(");
5810 sa = s->next;
5811 while (sa != NULL) {
5812 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5813 pstrcat(buf, buf_size, buf1);
5814 sa = sa->next;
5815 if (sa)
5816 pstrcat(buf, buf_size, ", ");
5818 pstrcat(buf, buf_size, ")");
5819 goto no_var;
5820 case VT_PTR:
5821 s = type->ref;
5822 pstrcpy(buf1, sizeof(buf1), "*");
5823 if (varstr)
5824 pstrcat(buf1, sizeof(buf1), varstr);
5825 type_to_str(buf, buf_size, &s->type, buf1);
5826 goto no_var;
5828 if (varstr) {
5829 pstrcat(buf, buf_size, " ");
5830 pstrcat(buf, buf_size, varstr);
5832 no_var: ;
5835 /* verify type compatibility to store vtop in 'dt' type, and generate
5836 casts if needed. */
5837 static void gen_assign_cast(CType *dt)
5839 CType *st, *type1, *type2, tmp_type1, tmp_type2;
5840 char buf1[256], buf2[256];
5841 int dbt, sbt;
5843 st = &vtop->type; /* source type */
5844 dbt = dt->t & VT_BTYPE;
5845 sbt = st->t & VT_BTYPE;
5846 if (dt->t & VT_CONSTANT)
5847 warning("assignment of read-only location");
5848 switch(dbt) {
5849 case VT_PTR:
5850 /* special cases for pointers */
5851 /* '0' can also be a pointer */
5852 if (is_null_pointer(vtop))
5853 goto type_ok;
5854 /* accept implicit pointer to integer cast with warning */
5855 if (is_integer_btype(sbt)) {
5856 warning("assignment makes pointer from integer without a cast");
5857 goto type_ok;
5859 type1 = pointed_type(dt);
5860 /* a function is implicitely a function pointer */
5861 if (sbt == VT_FUNC) {
5862 if ((type1->t & VT_BTYPE) != VT_VOID &&
5863 !is_compatible_types(pointed_type(dt), st))
5864 goto error;
5865 else
5866 goto type_ok;
5868 if (sbt != VT_PTR)
5869 goto error;
5870 type2 = pointed_type(st);
5871 if ((type1->t & VT_BTYPE) == VT_VOID ||
5872 (type2->t & VT_BTYPE) == VT_VOID) {
5873 /* void * can match anything */
5874 } else {
5875 /* exact type match, except for unsigned */
5876 tmp_type1 = *type1;
5877 tmp_type2 = *type2;
5878 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5879 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5880 if (!is_compatible_types(&tmp_type1, &tmp_type2))
5881 goto error;
5883 /* check const and volatile */
5884 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
5885 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
5886 warning("assignment discards qualifiers from pointer target type");
5887 break;
5888 case VT_BYTE:
5889 case VT_SHORT:
5890 case VT_INT:
5891 case VT_LLONG:
5892 if (sbt == VT_PTR || sbt == VT_FUNC) {
5893 warning("assignment makes integer from pointer without a cast");
5895 /* XXX: more tests */
5896 break;
5897 case VT_STRUCT:
5898 tmp_type1 = *dt;
5899 tmp_type2 = *st;
5900 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
5901 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
5902 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5903 error:
5904 type_to_str(buf1, sizeof(buf1), st, NULL);
5905 type_to_str(buf2, sizeof(buf2), dt, NULL);
5906 error("cannot cast '%s' to '%s'", buf1, buf2);
5908 break;
5910 type_ok:
5911 gen_cast(dt);
5914 /* store vtop in lvalue pushed on stack */
5915 void vstore(void)
5917 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5919 ft = vtop[-1].type.t;
5920 sbt = vtop->type.t & VT_BTYPE;
5921 dbt = ft & VT_BTYPE;
5922 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5923 (sbt == VT_INT && dbt == VT_SHORT)) {
5924 /* optimize char/short casts */
5925 delayed_cast = VT_MUSTCAST;
5926 vtop->type.t = ft & VT_TYPE;
5927 /* XXX: factorize */
5928 if (ft & VT_CONSTANT)
5929 warning("assignment of read-only location");
5930 } else {
5931 delayed_cast = 0;
5932 gen_assign_cast(&vtop[-1].type);
5935 if (sbt == VT_STRUCT) {
5936 /* if structure, only generate pointer */
5937 /* structure assignment : generate memcpy */
5938 /* XXX: optimize if small size */
5939 if (!nocode_wanted) {
5940 size = type_size(&vtop->type, &align);
5942 vpush_global_sym(&func_old_type, TOK_memcpy);
5944 /* destination */
5945 vpushv(vtop - 2);
5946 vtop->type.t = VT_INT;
5947 gaddrof();
5948 /* source */
5949 vpushv(vtop - 2);
5950 vtop->type.t = VT_INT;
5951 gaddrof();
5952 /* type size */
5953 vpushi(size);
5954 gfunc_call(3);
5956 vswap();
5957 vpop();
5958 } else {
5959 vswap();
5960 vpop();
5962 /* leave source on stack */
5963 } else if (ft & VT_BITFIELD) {
5964 /* bitfield store handling */
5965 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5966 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5967 /* remove bit field info to avoid loops */
5968 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5970 /* duplicate destination */
5971 vdup();
5972 vtop[-1] = vtop[-2];
5974 /* mask and shift source */
5975 vpushi((1 << bit_size) - 1);
5976 gen_op('&');
5977 vpushi(bit_pos);
5978 gen_op(TOK_SHL);
5979 /* load destination, mask and or with source */
5980 vswap();
5981 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5982 gen_op('&');
5983 gen_op('|');
5984 /* store result */
5985 vstore();
5986 } else {
5987 #ifdef CONFIG_TCC_BCHECK
5988 /* bound check case */
5989 if (vtop[-1].r & VT_MUSTBOUND) {
5990 vswap();
5991 gbound();
5992 vswap();
5994 #endif
5995 if (!nocode_wanted) {
5996 rc = RC_INT;
5997 if (is_float(ft))
5998 rc = RC_FLOAT;
5999 r = gv(rc); /* generate value */
6000 /* if lvalue was saved on stack, must read it */
6001 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6002 SValue sv;
6003 t = get_reg(RC_INT);
6004 sv.type.t = VT_INT;
6005 sv.r = VT_LOCAL | VT_LVAL;
6006 sv.c.ul = vtop[-1].c.ul;
6007 load(t, &sv);
6008 vtop[-1].r = t | VT_LVAL;
6010 store(r, vtop - 1);
6011 /* two word case handling : store second register at word + 4 */
6012 if ((ft & VT_BTYPE) == VT_LLONG) {
6013 vswap();
6014 /* convert to int to increment easily */
6015 vtop->type.t = VT_INT;
6016 gaddrof();
6017 vpushi(4);
6018 gen_op('+');
6019 vtop->r |= VT_LVAL;
6020 vswap();
6021 /* XXX: it works because r2 is spilled last ! */
6022 store(vtop->r2, vtop - 1);
6025 vswap();
6026 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6027 vtop->r |= delayed_cast;
6031 /* post defines POST/PRE add. c is the token ++ or -- */
6032 void inc(int post, int c)
6034 test_lvalue();
6035 vdup(); /* save lvalue */
6036 if (post) {
6037 gv_dup(); /* duplicate value */
6038 vrotb(3);
6039 vrotb(3);
6041 /* add constant */
6042 vpushi(c - TOK_MID);
6043 gen_op('+');
6044 vstore(); /* store value */
6045 if (post)
6046 vpop(); /* if post op, return saved value */
6049 /* Parse GNUC __attribute__ extension. Currently, the following
6050 extensions are recognized:
6051 - aligned(n) : set data/function alignment.
6052 - section(x) : generate data/code in this section.
6053 - unused : currently ignored, but may be used someday.
6055 static void parse_attribute(AttributeDef *ad)
6057 int t, n;
6059 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6060 next();
6061 skip('(');
6062 skip('(');
6063 while (tok != ')') {
6064 if (tok < TOK_IDENT)
6065 expect("attribute name");
6066 t = tok;
6067 next();
6068 switch(t) {
6069 case TOK_SECTION1:
6070 case TOK_SECTION2:
6071 skip('(');
6072 if (tok != TOK_STR)
6073 expect("section name");
6074 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6075 next();
6076 skip(')');
6077 break;
6078 case TOK_ALIGNED1:
6079 case TOK_ALIGNED2:
6080 if (tok == '(') {
6081 next();
6082 n = expr_const();
6083 if (n <= 0 || (n & (n - 1)) != 0)
6084 error("alignment must be a positive power of two");
6085 skip(')');
6086 } else {
6087 n = MAX_ALIGN;
6089 ad->aligned = n;
6090 break;
6091 case TOK_UNUSED1:
6092 case TOK_UNUSED2:
6093 /* currently, no need to handle it because tcc does not
6094 track unused objects */
6095 break;
6096 case TOK_NORETURN1:
6097 case TOK_NORETURN2:
6098 /* currently, no need to handle it because tcc does not
6099 track unused objects */
6100 break;
6101 case TOK_CDECL1:
6102 case TOK_CDECL2:
6103 case TOK_CDECL3:
6104 ad->func_call = FUNC_CDECL;
6105 break;
6106 case TOK_STDCALL1:
6107 case TOK_STDCALL2:
6108 case TOK_STDCALL3:
6109 ad->func_call = FUNC_STDCALL;
6110 break;
6111 default:
6112 if (tcc_state->warn_unsupported)
6113 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6114 /* skip parameters */
6115 /* XXX: skip parenthesis too */
6116 if (tok == '(') {
6117 next();
6118 while (tok != ')' && tok != -1)
6119 next();
6120 next();
6122 break;
6124 if (tok != ',')
6125 break;
6126 next();
6128 skip(')');
6129 skip(')');
6133 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6134 static void struct_decl(CType *type, int u)
6136 int a, v, size, align, maxalign, c, offset;
6137 int bit_size, bit_pos, bsize, bt, lbit_pos;
6138 Sym *s, *ss, **ps;
6139 AttributeDef ad;
6140 CType type1, btype;
6142 a = tok; /* save decl type */
6143 next();
6144 if (tok != '{') {
6145 v = tok;
6146 next();
6147 /* struct already defined ? return it */
6148 if (v < TOK_IDENT)
6149 expect("struct/union/enum name");
6150 s = struct_find(v);
6151 if (s) {
6152 if (s->type.t != a)
6153 error("invalid type");
6154 goto do_decl;
6156 } else {
6157 v = anon_sym++;
6159 type1.t = a;
6160 /* we put an undefined size for struct/union */
6161 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6162 s->r = 0; /* default alignment is zero as gcc */
6163 /* put struct/union/enum name in type */
6164 do_decl:
6165 type->t = u;
6166 type->ref = s;
6168 if (tok == '{') {
6169 next();
6170 if (s->c != -1)
6171 error("struct/union/enum already defined");
6172 /* cannot be empty */
6173 c = 0;
6174 /* non empty enums are not allowed */
6175 if (a == TOK_ENUM) {
6176 for(;;) {
6177 v = tok;
6178 if (v < TOK_UIDENT)
6179 expect("identifier");
6180 next();
6181 if (tok == '=') {
6182 next();
6183 c = expr_const();
6185 /* enum symbols have static storage */
6186 ss = sym_push(v, &int_type, VT_CONST, c);
6187 ss->type.t |= VT_STATIC;
6188 if (tok != ',')
6189 break;
6190 next();
6191 c++;
6192 /* NOTE: we accept a trailing comma */
6193 if (tok == '}')
6194 break;
6196 skip('}');
6197 } else {
6198 maxalign = 1;
6199 ps = &s->next;
6200 bit_pos = 0;
6201 offset = 0;
6202 while (tok != '}') {
6203 parse_btype(&btype, &ad);
6204 while (1) {
6205 bit_size = -1;
6206 v = 0;
6207 type1 = btype;
6208 if (tok != ':') {
6209 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6210 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6211 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6212 error("invalid type for '%s'",
6213 get_tok_str(v, NULL));
6215 if (tok == ':') {
6216 next();
6217 bit_size = expr_const();
6218 /* XXX: handle v = 0 case for messages */
6219 if (bit_size < 0)
6220 error("negative width in bit-field '%s'",
6221 get_tok_str(v, NULL));
6222 if (v && bit_size == 0)
6223 error("zero width for bit-field '%s'",
6224 get_tok_str(v, NULL));
6226 size = type_size(&type1, &align);
6227 lbit_pos = 0;
6228 if (bit_size >= 0) {
6229 bt = type1.t & VT_BTYPE;
6230 if (bt != VT_INT &&
6231 bt != VT_BYTE &&
6232 bt != VT_SHORT &&
6233 bt != VT_ENUM)
6234 error("bitfields must have scalar type");
6235 bsize = size * 8;
6236 if (bit_size > bsize) {
6237 error("width of '%s' exceeds its type",
6238 get_tok_str(v, NULL));
6239 } else if (bit_size == bsize) {
6240 /* no need for bit fields */
6241 bit_pos = 0;
6242 } else if (bit_size == 0) {
6243 /* XXX: what to do if only padding in a
6244 structure ? */
6245 /* zero size: means to pad */
6246 if (bit_pos > 0)
6247 bit_pos = bsize;
6248 } else {
6249 /* we do not have enough room ? */
6250 if ((bit_pos + bit_size) > bsize)
6251 bit_pos = 0;
6252 lbit_pos = bit_pos;
6253 /* XXX: handle LSB first */
6254 type1.t |= VT_BITFIELD |
6255 (bit_pos << VT_STRUCT_SHIFT) |
6256 (bit_size << (VT_STRUCT_SHIFT + 6));
6257 bit_pos += bit_size;
6259 } else {
6260 bit_pos = 0;
6262 if (v) {
6263 /* add new memory data only if starting
6264 bit field */
6265 if (lbit_pos == 0) {
6266 if (a == TOK_STRUCT) {
6267 c = (c + align - 1) & -align;
6268 offset = c;
6269 c += size;
6270 } else {
6271 offset = 0;
6272 if (size > c)
6273 c = size;
6275 if (align > maxalign)
6276 maxalign = align;
6278 #if 0
6279 printf("add field %s offset=%d",
6280 get_tok_str(v, NULL), offset);
6281 if (type1.t & VT_BITFIELD) {
6282 printf(" pos=%d size=%d",
6283 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6284 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6286 printf("\n");
6287 #endif
6288 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6289 *ps = ss;
6290 ps = &ss->next;
6292 if (tok == ';' || tok == TOK_EOF)
6293 break;
6294 skip(',');
6296 skip(';');
6298 skip('}');
6299 /* store size and alignment */
6300 s->c = (c + maxalign - 1) & -maxalign;
6301 s->r = maxalign;
6306 /* return 0 if no type declaration. otherwise, return the basic type
6307 and skip it.
6309 static int parse_btype(CType *type, AttributeDef *ad)
6311 int t, u, type_found, typespec_found;
6312 Sym *s;
6313 CType type1;
6315 memset(ad, 0, sizeof(AttributeDef));
6316 type_found = 0;
6317 typespec_found = 0;
6318 t = 0;
6319 while(1) {
6320 switch(tok) {
6321 case TOK_EXTENSION:
6322 /* currently, we really ignore extension */
6323 next();
6324 continue;
6326 /* basic types */
6327 case TOK_CHAR:
6328 u = VT_BYTE;
6329 basic_type:
6330 next();
6331 basic_type1:
6332 if ((t & VT_BTYPE) != 0)
6333 error("too many basic types");
6334 t |= u;
6335 typespec_found = 1;
6336 break;
6337 case TOK_VOID:
6338 u = VT_VOID;
6339 goto basic_type;
6340 case TOK_SHORT:
6341 u = VT_SHORT;
6342 goto basic_type;
6343 case TOK_INT:
6344 next();
6345 typespec_found = 1;
6346 break;
6347 case TOK_LONG:
6348 next();
6349 if ((t & VT_BTYPE) == VT_DOUBLE) {
6350 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6351 } else if ((t & VT_BTYPE) == VT_LONG) {
6352 t = (t & ~VT_BTYPE) | VT_LLONG;
6353 } else {
6354 u = VT_LONG;
6355 goto basic_type1;
6357 break;
6358 case TOK_BOOL:
6359 u = VT_BOOL;
6360 goto basic_type;
6361 case TOK_FLOAT:
6362 u = VT_FLOAT;
6363 goto basic_type;
6364 case TOK_DOUBLE:
6365 next();
6366 if ((t & VT_BTYPE) == VT_LONG) {
6367 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6368 } else {
6369 u = VT_DOUBLE;
6370 goto basic_type1;
6372 break;
6373 case TOK_ENUM:
6374 struct_decl(&type1, VT_ENUM);
6375 basic_type2:
6376 u = type1.t;
6377 type->ref = type1.ref;
6378 goto basic_type1;
6379 case TOK_STRUCT:
6380 case TOK_UNION:
6381 struct_decl(&type1, VT_STRUCT);
6382 goto basic_type2;
6384 /* type modifiers */
6385 case TOK_CONST1:
6386 case TOK_CONST2:
6387 case TOK_CONST3:
6388 t |= VT_CONSTANT;
6389 next();
6390 break;
6391 case TOK_VOLATILE1:
6392 case TOK_VOLATILE2:
6393 case TOK_VOLATILE3:
6394 t |= VT_VOLATILE;
6395 next();
6396 break;
6397 case TOK_SIGNED1:
6398 case TOK_SIGNED2:
6399 case TOK_SIGNED3:
6400 typespec_found = 1;
6401 t |= VT_SIGNED;
6402 next();
6403 break;
6404 case TOK_REGISTER:
6405 case TOK_AUTO:
6406 case TOK_RESTRICT1:
6407 case TOK_RESTRICT2:
6408 case TOK_RESTRICT3:
6409 next();
6410 break;
6411 case TOK_UNSIGNED:
6412 t |= VT_UNSIGNED;
6413 next();
6414 typespec_found = 1;
6415 break;
6417 /* storage */
6418 case TOK_EXTERN:
6419 t |= VT_EXTERN;
6420 next();
6421 break;
6422 case TOK_STATIC:
6423 t |= VT_STATIC;
6424 next();
6425 break;
6426 case TOK_TYPEDEF:
6427 t |= VT_TYPEDEF;
6428 next();
6429 break;
6430 case TOK_INLINE1:
6431 case TOK_INLINE2:
6432 case TOK_INLINE3:
6433 t |= VT_INLINE;
6434 next();
6435 break;
6437 /* GNUC attribute */
6438 case TOK_ATTRIBUTE1:
6439 case TOK_ATTRIBUTE2:
6440 parse_attribute(ad);
6441 break;
6442 /* GNUC typeof */
6443 case TOK_TYPEOF1:
6444 case TOK_TYPEOF2:
6445 case TOK_TYPEOF3:
6446 next();
6447 parse_expr_type(&type1);
6448 goto basic_type2;
6449 default:
6450 if (typespec_found)
6451 goto the_end;
6452 s = sym_find(tok);
6453 if (!s || !(s->type.t & VT_TYPEDEF))
6454 goto the_end;
6455 t |= (s->type.t & ~VT_TYPEDEF);
6456 type->ref = s->type.ref;
6457 next();
6458 break;
6460 type_found = 1;
6462 the_end:
6463 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6464 error("signed and unsigned modifier");
6465 if (tcc_state->char_is_unsigned) {
6466 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6467 t |= VT_UNSIGNED;
6469 t &= ~VT_SIGNED;
6471 /* long is never used as type */
6472 if ((t & VT_BTYPE) == VT_LONG)
6473 t = (t & ~VT_BTYPE) | VT_INT;
6474 type->t = t;
6475 return type_found;
6478 /* convert a function parameter type (array to pointer and function to
6479 function pointer) */
6480 static inline void convert_parameter_type(CType *pt)
6482 /* array must be transformed to pointer according to ANSI C */
6483 pt->t &= ~VT_ARRAY;
6484 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6485 mk_pointer(pt);
6489 static void post_type(CType *type, AttributeDef *ad)
6491 int n, l, t1;
6492 Sym **plast, *s, *first;
6493 AttributeDef ad1;
6494 CType pt;
6496 if (tok == '(') {
6497 /* function declaration */
6498 next();
6499 l = 0;
6500 first = NULL;
6501 plast = &first;
6502 while (tok != ')') {
6503 /* read param name and compute offset */
6504 if (l != FUNC_OLD) {
6505 if (!parse_btype(&pt, &ad1)) {
6506 if (l) {
6507 error("invalid type");
6508 } else {
6509 l = FUNC_OLD;
6510 goto old_proto;
6513 l = FUNC_NEW;
6514 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6515 break;
6516 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6517 if ((pt.t & VT_BTYPE) == VT_VOID)
6518 error("parameter declared as void");
6519 } else {
6520 old_proto:
6521 n = tok;
6522 pt.t = VT_INT;
6523 next();
6525 convert_parameter_type(&pt);
6526 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6527 *plast = s;
6528 plast = &s->next;
6529 if (tok == ',') {
6530 next();
6531 if (l == FUNC_NEW && tok == TOK_DOTS) {
6532 l = FUNC_ELLIPSIS;
6533 next();
6534 break;
6538 /* if no parameters, then old type prototype */
6539 if (l == 0)
6540 l = FUNC_OLD;
6541 skip(')');
6542 t1 = type->t & VT_STORAGE;
6543 /* NOTE: const is ignored in returned type as it has a special
6544 meaning in gcc / C++ */
6545 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6546 post_type(type, ad);
6547 /* we push a anonymous symbol which will contain the function prototype */
6548 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6549 s->next = first;
6550 type->t = t1 | VT_FUNC;
6551 type->ref = s;
6552 } else if (tok == '[') {
6553 /* array definition */
6554 next();
6555 n = -1;
6556 if (tok != ']') {
6557 n = expr_const();
6558 if (n < 0)
6559 error("invalid array size");
6561 skip(']');
6562 /* parse next post type */
6563 t1 = type->t & VT_STORAGE;
6564 type->t &= ~VT_STORAGE;
6565 post_type(type, ad);
6567 /* we push a anonymous symbol which will contain the array
6568 element type */
6569 s = sym_push(SYM_FIELD, type, 0, n);
6570 type->t = t1 | VT_ARRAY | VT_PTR;
6571 type->ref = s;
6575 /* Parse a type declaration (except basic type), and return the type
6576 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6577 expected. 'type' should contain the basic type. 'ad' is the
6578 attribute definition of the basic type. It can be modified by
6579 type_decl().
6581 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6583 Sym *s;
6584 CType type1, *type2;
6585 int qualifiers;
6587 while (tok == '*') {
6588 qualifiers = 0;
6589 redo:
6590 next();
6591 switch(tok) {
6592 case TOK_CONST1:
6593 case TOK_CONST2:
6594 case TOK_CONST3:
6595 qualifiers |= VT_CONSTANT;
6596 goto redo;
6597 case TOK_VOLATILE1:
6598 case TOK_VOLATILE2:
6599 case TOK_VOLATILE3:
6600 qualifiers |= VT_VOLATILE;
6601 goto redo;
6602 case TOK_RESTRICT1:
6603 case TOK_RESTRICT2:
6604 case TOK_RESTRICT3:
6605 goto redo;
6607 mk_pointer(type);
6608 type->t |= qualifiers;
6611 /* XXX: clarify attribute handling */
6612 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6613 parse_attribute(ad);
6615 /* recursive type */
6616 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6617 type1.t = 0; /* XXX: same as int */
6618 if (tok == '(') {
6619 next();
6620 /* XXX: this is not correct to modify 'ad' at this point, but
6621 the syntax is not clear */
6622 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6623 parse_attribute(ad);
6624 type_decl(&type1, ad, v, td);
6625 skip(')');
6626 } else {
6627 /* type identifier */
6628 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6629 *v = tok;
6630 next();
6631 } else {
6632 if (!(td & TYPE_ABSTRACT))
6633 expect("identifier");
6634 *v = 0;
6637 post_type(type, ad);
6638 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6639 parse_attribute(ad);
6640 if (!type1.t)
6641 return;
6642 /* append type at the end of type1 */
6643 type2 = &type1;
6644 for(;;) {
6645 s = type2->ref;
6646 type2 = &s->type;
6647 if (!type2->t) {
6648 *type2 = *type;
6649 break;
6652 *type = type1;
6655 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6656 static int lvalue_type(int t)
6658 int bt, r;
6659 r = VT_LVAL;
6660 bt = t & VT_BTYPE;
6661 if (bt == VT_BYTE || bt == VT_BOOL)
6662 r |= VT_LVAL_BYTE;
6663 else if (bt == VT_SHORT)
6664 r |= VT_LVAL_SHORT;
6665 else
6666 return r;
6667 if (t & VT_UNSIGNED)
6668 r |= VT_LVAL_UNSIGNED;
6669 return r;
6672 /* indirection with full error checking and bound check */
6673 static void indir(void)
6675 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6676 expect("pointer");
6677 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6678 gv(RC_INT);
6679 vtop->type = *pointed_type(&vtop->type);
6680 /* an array is never an lvalue */
6681 if (!(vtop->type.t & VT_ARRAY)) {
6682 vtop->r |= lvalue_type(vtop->type.t);
6683 /* if bound checking, the referenced pointer must be checked */
6684 if (do_bounds_check)
6685 vtop->r |= VT_MUSTBOUND;
6689 /* pass a parameter to a function and do type checking and casting */
6690 static void gfunc_param_typed(Sym *func, Sym *arg)
6692 int func_type;
6693 CType type;
6695 func_type = func->c;
6696 if (func_type == FUNC_OLD ||
6697 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6698 /* default casting : only need to convert float to double */
6699 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6700 type.t = VT_DOUBLE;
6701 gen_cast(&type);
6703 } else if (arg == NULL) {
6704 error("too many arguments to function");
6705 } else {
6706 type = arg->type;
6707 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6708 gen_assign_cast(&type);
6712 /* parse an expression of the form '(type)' or '(expr)' and return its
6713 type */
6714 static void parse_expr_type(CType *type)
6716 int n;
6717 AttributeDef ad;
6719 skip('(');
6720 if (parse_btype(type, &ad)) {
6721 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6722 } else {
6723 expr_type(type);
6725 skip(')');
6728 static void parse_type(CType *type)
6730 AttributeDef ad;
6731 int n;
6733 if (!parse_btype(type, &ad)) {
6734 expect("type");
6736 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6739 static void vpush_tokc(int t)
6741 CType type;
6742 type.t = t;
6743 vsetc(&type, VT_CONST, &tokc);
6746 static void unary(void)
6748 int n, t, align, size, r;
6749 CType type;
6750 Sym *s;
6751 AttributeDef ad;
6753 /* XXX: GCC 2.95.3 does not generate a table although it should be
6754 better here */
6755 tok_next:
6756 switch(tok) {
6757 case TOK_EXTENSION:
6758 next();
6759 goto tok_next;
6760 case TOK_CINT:
6761 case TOK_CCHAR:
6762 case TOK_LCHAR:
6763 vpushi(tokc.i);
6764 next();
6765 break;
6766 case TOK_CUINT:
6767 vpush_tokc(VT_INT | VT_UNSIGNED);
6768 next();
6769 break;
6770 case TOK_CLLONG:
6771 vpush_tokc(VT_LLONG);
6772 next();
6773 break;
6774 case TOK_CULLONG:
6775 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6776 next();
6777 break;
6778 case TOK_CFLOAT:
6779 vpush_tokc(VT_FLOAT);
6780 next();
6781 break;
6782 case TOK_CDOUBLE:
6783 vpush_tokc(VT_DOUBLE);
6784 next();
6785 break;
6786 case TOK_CLDOUBLE:
6787 vpush_tokc(VT_LDOUBLE);
6788 next();
6789 break;
6790 case TOK___FUNCTION__:
6791 if (!gnu_ext)
6792 goto tok_identifier;
6793 /* fall thru */
6794 case TOK___FUNC__:
6796 void *ptr;
6797 int len;
6798 /* special function name identifier */
6799 len = strlen(funcname) + 1;
6800 /* generate char[len] type */
6801 type.t = VT_BYTE;
6802 mk_pointer(&type);
6803 type.t |= VT_ARRAY;
6804 type.ref->c = len;
6805 vpush_ref(&type, data_section, data_section->data_offset, len);
6806 ptr = section_ptr_add(data_section, len);
6807 memcpy(ptr, funcname, len);
6808 next();
6810 break;
6811 case TOK_LSTR:
6812 t = VT_INT;
6813 goto str_init;
6814 case TOK_STR:
6815 /* string parsing */
6816 t = VT_BYTE;
6817 str_init:
6818 if (tcc_state->warn_write_strings)
6819 t |= VT_CONSTANT;
6820 type.t = t;
6821 mk_pointer(&type);
6822 type.t |= VT_ARRAY;
6823 memset(&ad, 0, sizeof(AttributeDef));
6824 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6825 break;
6826 case '(':
6827 next();
6828 /* cast ? */
6829 if (parse_btype(&type, &ad)) {
6830 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6831 skip(')');
6832 /* check ISOC99 compound literal */
6833 if (tok == '{') {
6834 /* data is allocated locally by default */
6835 if (global_expr)
6836 r = VT_CONST;
6837 else
6838 r = VT_LOCAL;
6839 /* all except arrays are lvalues */
6840 if (!(type.t & VT_ARRAY))
6841 r |= lvalue_type(type.t);
6842 memset(&ad, 0, sizeof(AttributeDef));
6843 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6844 } else {
6845 unary();
6846 gen_cast(&type);
6848 } else if (tok == '{') {
6849 /* save all registers */
6850 save_regs(0);
6851 /* statement expression : we do not accept break/continue
6852 inside as GCC does */
6853 block(NULL, NULL, NULL, NULL, 0, 1);
6854 skip(')');
6855 } else {
6856 gexpr();
6857 skip(')');
6859 break;
6860 case '*':
6861 next();
6862 unary();
6863 indir();
6864 break;
6865 case '&':
6866 next();
6867 unary();
6868 /* functions names must be treated as function pointers,
6869 except for unary '&' and sizeof. Since we consider that
6870 functions are not lvalues, we only have to handle it
6871 there and in function calls. */
6872 /* arrays can also be used although they are not lvalues */
6873 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6874 !(vtop->type.t & VT_ARRAY))
6875 test_lvalue();
6876 mk_pointer(&vtop->type);
6877 gaddrof();
6878 break;
6879 case '!':
6880 next();
6881 unary();
6882 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6883 vtop->c.i = !vtop->c.i;
6884 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6885 vtop->c.i = vtop->c.i ^ 1;
6886 else
6887 vseti(VT_JMP, gtst(1, 0));
6888 break;
6889 case '~':
6890 next();
6891 unary();
6892 vpushi(-1);
6893 gen_op('^');
6894 break;
6895 case '+':
6896 next();
6897 /* in order to force cast, we add zero */
6898 unary();
6899 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6900 error("pointer not accepted for unary plus");
6901 vpushi(0);
6902 gen_op('+');
6903 break;
6904 case TOK_SIZEOF:
6905 case TOK_ALIGNOF1:
6906 case TOK_ALIGNOF2:
6907 t = tok;
6908 next();
6909 if (tok == '(') {
6910 parse_expr_type(&type);
6911 } else {
6912 unary_type(&type);
6914 size = type_size(&type, &align);
6915 if (t == TOK_SIZEOF) {
6916 if (size < 0)
6917 error("sizeof applied to an incomplete type");
6918 vpushi(size);
6919 } else {
6920 vpushi(align);
6922 break;
6924 case TOK_builtin_types_compatible_p:
6926 CType type1, type2;
6927 next();
6928 skip('(');
6929 parse_type(&type1);
6930 skip(',');
6931 parse_type(&type2);
6932 skip(')');
6933 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6934 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6935 vpushi(is_compatible_types(&type1, &type2));
6937 break;
6938 case TOK_builtin_constant_p:
6940 int saved_nocode_wanted, res;
6941 next();
6942 skip('(');
6943 saved_nocode_wanted = nocode_wanted;
6944 nocode_wanted = 1;
6945 gexpr();
6946 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6947 vpop();
6948 nocode_wanted = saved_nocode_wanted;
6949 skip(')');
6950 vpushi(res);
6952 break;
6953 case TOK_INC:
6954 case TOK_DEC:
6955 t = tok;
6956 next();
6957 unary();
6958 inc(0, t);
6959 break;
6960 case '-':
6961 next();
6962 vpushi(0);
6963 unary();
6964 gen_op('-');
6965 break;
6966 case TOK_LAND:
6967 if (!gnu_ext)
6968 goto tok_identifier;
6969 next();
6970 /* allow to take the address of a label */
6971 if (tok < TOK_UIDENT)
6972 expect("label identifier");
6973 s = label_find(tok);
6974 if (!s) {
6975 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6976 } else {
6977 if (s->r == LABEL_DECLARED)
6978 s->r = LABEL_FORWARD;
6980 if (!s->type.t) {
6981 s->type.t = VT_VOID;
6982 mk_pointer(&s->type);
6983 s->type.t |= VT_STATIC;
6985 vset(&s->type, VT_CONST | VT_SYM, 0);
6986 vtop->sym = s;
6987 next();
6988 break;
6989 default:
6990 tok_identifier:
6991 t = tok;
6992 next();
6993 if (t < TOK_UIDENT)
6994 expect("identifier");
6995 s = sym_find(t);
6996 if (!s) {
6997 if (tok != '(')
6998 error("'%s' undeclared", get_tok_str(t, NULL));
6999 /* for simple function calls, we tolerate undeclared
7000 external reference to int() function */
7001 if (tcc_state->warn_implicit_function_declaration)
7002 warning("implicit declaration of function '%s'",
7003 get_tok_str(t, NULL));
7004 s = external_global_sym(t, &func_old_type, 0);
7006 vset(&s->type, s->r, s->c);
7007 /* if forward reference, we must point to s */
7008 if (vtop->r & VT_SYM) {
7009 vtop->sym = s;
7010 vtop->c.ul = 0;
7012 break;
7015 /* post operations */
7016 while (1) {
7017 if (tok == TOK_INC || tok == TOK_DEC) {
7018 inc(1, tok);
7019 next();
7020 } else if (tok == '.' || tok == TOK_ARROW) {
7021 /* field */
7022 if (tok == TOK_ARROW)
7023 indir();
7024 test_lvalue();
7025 gaddrof();
7026 next();
7027 /* expect pointer on structure */
7028 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7029 expect("struct or union");
7030 s = vtop->type.ref;
7031 /* find field */
7032 tok |= SYM_FIELD;
7033 while ((s = s->next) != NULL) {
7034 if (s->v == tok)
7035 break;
7037 if (!s)
7038 error("field not found");
7039 /* add field offset to pointer */
7040 vtop->type = char_pointer_type; /* change type to 'char *' */
7041 vpushi(s->c);
7042 gen_op('+');
7043 /* change type to field type, and set to lvalue */
7044 vtop->type = s->type;
7045 /* an array is never an lvalue */
7046 if (!(vtop->type.t & VT_ARRAY)) {
7047 vtop->r |= lvalue_type(vtop->type.t);
7048 /* if bound checking, the referenced pointer must be checked */
7049 if (do_bounds_check)
7050 vtop->r |= VT_MUSTBOUND;
7052 next();
7053 } else if (tok == '[') {
7054 next();
7055 gexpr();
7056 gen_op('+');
7057 indir();
7058 skip(']');
7059 } else if (tok == '(') {
7060 SValue ret;
7061 Sym *sa;
7062 int nb_args;
7064 /* function call */
7065 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7066 /* pointer test (no array accepted) */
7067 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7068 vtop->type = *pointed_type(&vtop->type);
7069 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7070 goto error_func;
7071 } else {
7072 error_func:
7073 expect("function pointer");
7075 } else {
7076 vtop->r &= ~VT_LVAL; /* no lvalue */
7078 /* get return type */
7079 s = vtop->type.ref;
7080 next();
7081 sa = s->next; /* first parameter */
7082 nb_args = 0;
7083 /* compute first implicit argument if a structure is returned */
7084 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7085 /* get some space for the returned structure */
7086 size = type_size(&s->type, &align);
7087 loc = (loc - size) & -align;
7088 ret.type = s->type;
7089 ret.r = VT_LOCAL | VT_LVAL;
7090 /* pass it as 'int' to avoid structure arg passing
7091 problems */
7092 vseti(VT_LOCAL, loc);
7093 ret.c = vtop->c;
7094 nb_args++;
7095 } else {
7096 ret.type = s->type;
7097 ret.r2 = VT_CONST;
7098 /* return in register */
7099 if (is_float(ret.type.t)) {
7100 ret.r = REG_FRET;
7101 } else {
7102 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7103 ret.r2 = REG_LRET;
7104 ret.r = REG_IRET;
7106 ret.c.i = 0;
7108 if (tok != ')') {
7109 for(;;) {
7110 expr_eq();
7111 gfunc_param_typed(s, sa);
7112 nb_args++;
7113 if (sa)
7114 sa = sa->next;
7115 if (tok == ')')
7116 break;
7117 skip(',');
7120 if (sa)
7121 error("too few arguments to function");
7122 skip(')');
7123 if (!nocode_wanted) {
7124 gfunc_call(nb_args);
7125 } else {
7126 vtop -= (nb_args + 1);
7128 /* return value */
7129 vsetc(&ret.type, ret.r, &ret.c);
7130 vtop->r2 = ret.r2;
7131 } else {
7132 break;
7137 static void uneq(void)
7139 int t;
7141 unary();
7142 if (tok == '=' ||
7143 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7144 tok == TOK_A_XOR || tok == TOK_A_OR ||
7145 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7146 test_lvalue();
7147 t = tok;
7148 next();
7149 if (t == '=') {
7150 expr_eq();
7151 } else {
7152 vdup();
7153 expr_eq();
7154 gen_op(t & 0x7f);
7156 vstore();
7160 static void expr_prod(void)
7162 int t;
7164 uneq();
7165 while (tok == '*' || tok == '/' || tok == '%') {
7166 t = tok;
7167 next();
7168 uneq();
7169 gen_op(t);
7173 static void expr_sum(void)
7175 int t;
7177 expr_prod();
7178 while (tok == '+' || tok == '-') {
7179 t = tok;
7180 next();
7181 expr_prod();
7182 gen_op(t);
7186 static void expr_shift(void)
7188 int t;
7190 expr_sum();
7191 while (tok == TOK_SHL || tok == TOK_SAR) {
7192 t = tok;
7193 next();
7194 expr_sum();
7195 gen_op(t);
7199 static void expr_cmp(void)
7201 int t;
7203 expr_shift();
7204 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7205 tok == TOK_ULT || tok == TOK_UGE) {
7206 t = tok;
7207 next();
7208 expr_shift();
7209 gen_op(t);
7213 static void expr_cmpeq(void)
7215 int t;
7217 expr_cmp();
7218 while (tok == TOK_EQ || tok == TOK_NE) {
7219 t = tok;
7220 next();
7221 expr_cmp();
7222 gen_op(t);
7226 static void expr_and(void)
7228 expr_cmpeq();
7229 while (tok == '&') {
7230 next();
7231 expr_cmpeq();
7232 gen_op('&');
7236 static void expr_xor(void)
7238 expr_and();
7239 while (tok == '^') {
7240 next();
7241 expr_and();
7242 gen_op('^');
7246 static void expr_or(void)
7248 expr_xor();
7249 while (tok == '|') {
7250 next();
7251 expr_xor();
7252 gen_op('|');
7256 /* XXX: fix this mess */
7257 static void expr_land_const(void)
7259 expr_or();
7260 while (tok == TOK_LAND) {
7261 next();
7262 expr_or();
7263 gen_op(TOK_LAND);
7267 /* XXX: fix this mess */
7268 static void expr_lor_const(void)
7270 expr_land_const();
7271 while (tok == TOK_LOR) {
7272 next();
7273 expr_land_const();
7274 gen_op(TOK_LOR);
7278 /* only used if non constant */
7279 static void expr_land(void)
7281 int t;
7283 expr_or();
7284 if (tok == TOK_LAND) {
7285 t = 0;
7286 for(;;) {
7287 t = gtst(1, t);
7288 if (tok != TOK_LAND) {
7289 vseti(VT_JMPI, t);
7290 break;
7292 next();
7293 expr_or();
7298 static void expr_lor(void)
7300 int t;
7302 expr_land();
7303 if (tok == TOK_LOR) {
7304 t = 0;
7305 for(;;) {
7306 t = gtst(0, t);
7307 if (tok != TOK_LOR) {
7308 vseti(VT_JMP, t);
7309 break;
7311 next();
7312 expr_land();
7317 /* XXX: better constant handling */
7318 static void expr_eq(void)
7320 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7321 SValue sv;
7322 CType type, type1, type2;
7324 if (const_wanted) {
7325 int c1, c;
7326 expr_lor_const();
7327 if (tok == '?') {
7328 c = vtop->c.i;
7329 vpop();
7330 next();
7331 if (tok == ':' && gnu_ext) {
7332 c1 = c;
7333 } else {
7334 gexpr();
7335 c1 = vtop->c.i;
7336 vpop();
7338 skip(':');
7339 expr_eq();
7340 if (c)
7341 vtop->c.i = c1;
7343 } else {
7344 expr_lor();
7345 if (tok == '?') {
7346 next();
7347 if (vtop != vstack) {
7348 /* needed to avoid having different registers saved in
7349 each branch */
7350 if (is_float(vtop->type.t))
7351 rc = RC_FLOAT;
7352 else
7353 rc = RC_INT;
7354 gv(rc);
7355 save_regs(1);
7357 if (tok == ':' && gnu_ext) {
7358 gv_dup();
7359 tt = gtst(1, 0);
7360 } else {
7361 tt = gtst(1, 0);
7362 gexpr();
7364 type1 = vtop->type;
7365 sv = *vtop; /* save value to handle it later */
7366 vtop--; /* no vpop so that FP stack is not flushed */
7367 skip(':');
7368 u = gjmp(0);
7369 gsym(tt);
7370 expr_eq();
7371 type2 = vtop->type;
7373 t1 = type1.t;
7374 bt1 = t1 & VT_BTYPE;
7375 t2 = type2.t;
7376 bt2 = t2 & VT_BTYPE;
7377 /* cast operands to correct type according to ISOC rules */
7378 if (is_float(bt1) || is_float(bt2)) {
7379 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7380 type.t = VT_LDOUBLE;
7381 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7382 type.t = VT_DOUBLE;
7383 } else {
7384 type.t = VT_FLOAT;
7386 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7387 /* cast to biggest op */
7388 type.t = VT_LLONG;
7389 /* convert to unsigned if it does not fit in a long long */
7390 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7391 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7392 type.t |= VT_UNSIGNED;
7393 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7394 /* XXX: test pointer compatibility */
7395 type = type1;
7396 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7397 /* XXX: test structure compatibility */
7398 type = type1;
7399 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7400 /* NOTE: as an extension, we accept void on only one side */
7401 type.t = VT_VOID;
7402 } else {
7403 /* integer operations */
7404 type.t = VT_INT;
7405 /* convert to unsigned if it does not fit in an integer */
7406 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7407 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7408 type.t |= VT_UNSIGNED;
7411 /* now we convert second operand */
7412 gen_cast(&type);
7413 rc = RC_INT;
7414 if (is_float(type.t)) {
7415 rc = RC_FLOAT;
7416 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7417 /* for long longs, we use fixed registers to avoid having
7418 to handle a complicated move */
7419 rc = RC_IRET;
7422 r2 = gv(rc);
7423 /* this is horrible, but we must also convert first
7424 operand */
7425 tt = gjmp(0);
7426 gsym(u);
7427 /* put again first value and cast it */
7428 *vtop = sv;
7429 gen_cast(&type);
7430 r1 = gv(rc);
7431 move_reg(r2, r1);
7432 vtop->r = r2;
7433 gsym(tt);
7438 static void gexpr(void)
7440 while (1) {
7441 expr_eq();
7442 if (tok != ',')
7443 break;
7444 vpop();
7445 next();
7449 /* parse an expression and return its type without any side effect. */
7450 static void expr_type(CType *type)
7452 int saved_nocode_wanted;
7454 saved_nocode_wanted = nocode_wanted;
7455 nocode_wanted = 1;
7456 gexpr();
7457 *type = vtop->type;
7458 vpop();
7459 nocode_wanted = saved_nocode_wanted;
7462 /* parse a unary expression and return its type without any side
7463 effect. */
7464 static void unary_type(CType *type)
7466 int a;
7468 a = nocode_wanted;
7469 nocode_wanted = 1;
7470 unary();
7471 *type = vtop->type;
7472 vpop();
7473 nocode_wanted = a;
7476 /* parse a constant expression and return value in vtop. */
7477 static void expr_const1(void)
7479 int a;
7480 a = const_wanted;
7481 const_wanted = 1;
7482 expr_eq();
7483 const_wanted = a;
7486 /* parse an integer constant and return its value. */
7487 static int expr_const(void)
7489 int c;
7490 expr_const1();
7491 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7492 expect("constant expression");
7493 c = vtop->c.i;
7494 vpop();
7495 return c;
7498 /* return the label token if current token is a label, otherwise
7499 return zero */
7500 static int is_label(void)
7502 int last_tok;
7504 /* fast test first */
7505 if (tok < TOK_UIDENT)
7506 return 0;
7507 /* no need to save tokc because tok is an identifier */
7508 last_tok = tok;
7509 next();
7510 if (tok == ':') {
7511 next();
7512 return last_tok;
7513 } else {
7514 unget_tok(last_tok);
7515 return 0;
7519 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7520 int case_reg, int is_expr)
7522 int a, b, c, d;
7523 Sym *s;
7525 /* generate line number info */
7526 if (do_debug &&
7527 (last_line_num != file->line_num || last_ind != ind)) {
7528 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7529 last_ind = ind;
7530 last_line_num = file->line_num;
7533 if (is_expr) {
7534 /* default return value is (void) */
7535 vpushi(0);
7536 vtop->type.t = VT_VOID;
7539 if (tok == TOK_IF) {
7540 /* if test */
7541 next();
7542 skip('(');
7543 gexpr();
7544 skip(')');
7545 a = gtst(1, 0);
7546 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7547 c = tok;
7548 if (c == TOK_ELSE) {
7549 next();
7550 d = gjmp(0);
7551 gsym(a);
7552 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7553 gsym(d); /* patch else jmp */
7554 } else
7555 gsym(a);
7556 } else if (tok == TOK_WHILE) {
7557 next();
7558 d = ind;
7559 skip('(');
7560 gexpr();
7561 skip(')');
7562 a = gtst(1, 0);
7563 b = 0;
7564 block(&a, &b, case_sym, def_sym, case_reg, 0);
7565 gjmp_addr(d);
7566 gsym(a);
7567 gsym_addr(b, d);
7568 } else if (tok == '{') {
7569 Sym *llabel;
7571 next();
7572 /* record local declaration stack position */
7573 s = local_stack;
7574 llabel = local_label_stack;
7575 /* handle local labels declarations */
7576 if (tok == TOK_LABEL) {
7577 next();
7578 for(;;) {
7579 if (tok < TOK_UIDENT)
7580 expect("label identifier");
7581 label_push(&local_label_stack, tok, LABEL_DECLARED);
7582 next();
7583 if (tok == ',') {
7584 next();
7585 } else {
7586 skip(';');
7587 break;
7591 while (tok != '}') {
7592 decl(VT_LOCAL);
7593 if (tok != '}') {
7594 if (is_expr)
7595 vpop();
7596 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7599 /* pop locally defined labels */
7600 label_pop(&local_label_stack, llabel);
7601 /* pop locally defined symbols */
7602 sym_pop(&local_stack, s);
7603 next();
7604 } else if (tok == TOK_RETURN) {
7605 next();
7606 if (tok != ';') {
7607 gexpr();
7608 gen_assign_cast(&func_vt);
7609 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7610 CType type;
7611 /* if returning structure, must copy it to implicit
7612 first pointer arg location */
7613 type = func_vt;
7614 mk_pointer(&type);
7615 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7616 indir();
7617 vswap();
7618 /* copy structure value to pointer */
7619 vstore();
7620 } else if (is_float(func_vt.t)) {
7621 gv(RC_FRET);
7622 } else {
7623 gv(RC_IRET);
7625 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7627 skip(';');
7628 rsym = gjmp(rsym); /* jmp */
7629 } else if (tok == TOK_BREAK) {
7630 /* compute jump */
7631 if (!bsym)
7632 error("cannot break");
7633 *bsym = gjmp(*bsym);
7634 next();
7635 skip(';');
7636 } else if (tok == TOK_CONTINUE) {
7637 /* compute jump */
7638 if (!csym)
7639 error("cannot continue");
7640 *csym = gjmp(*csym);
7641 next();
7642 skip(';');
7643 } else if (tok == TOK_FOR) {
7644 int e;
7645 next();
7646 skip('(');
7647 if (tok != ';') {
7648 gexpr();
7649 vpop();
7651 skip(';');
7652 d = ind;
7653 c = ind;
7654 a = 0;
7655 b = 0;
7656 if (tok != ';') {
7657 gexpr();
7658 a = gtst(1, 0);
7660 skip(';');
7661 if (tok != ')') {
7662 e = gjmp(0);
7663 c = ind;
7664 gexpr();
7665 vpop();
7666 gjmp_addr(d);
7667 gsym(e);
7669 skip(')');
7670 block(&a, &b, case_sym, def_sym, case_reg, 0);
7671 gjmp_addr(c);
7672 gsym(a);
7673 gsym_addr(b, c);
7674 } else
7675 if (tok == TOK_DO) {
7676 next();
7677 a = 0;
7678 b = 0;
7679 d = ind;
7680 block(&a, &b, case_sym, def_sym, case_reg, 0);
7681 skip(TOK_WHILE);
7682 skip('(');
7683 gsym(b);
7684 gexpr();
7685 c = gtst(0, 0);
7686 gsym_addr(c, d);
7687 skip(')');
7688 gsym(a);
7689 skip(';');
7690 } else
7691 if (tok == TOK_SWITCH) {
7692 next();
7693 skip('(');
7694 gexpr();
7695 /* XXX: other types than integer */
7696 case_reg = gv(RC_INT);
7697 vpop();
7698 skip(')');
7699 a = 0;
7700 b = gjmp(0); /* jump to first case */
7701 c = 0;
7702 block(&a, csym, &b, &c, case_reg, 0);
7703 /* if no default, jmp after switch */
7704 if (c == 0)
7705 c = ind;
7706 /* default label */
7707 gsym_addr(b, c);
7708 /* break label */
7709 gsym(a);
7710 } else
7711 if (tok == TOK_CASE) {
7712 int v1, v2;
7713 if (!case_sym)
7714 expect("switch");
7715 next();
7716 v1 = expr_const();
7717 v2 = v1;
7718 if (gnu_ext && tok == TOK_DOTS) {
7719 next();
7720 v2 = expr_const();
7721 if (v2 < v1)
7722 warning("empty case range");
7724 /* since a case is like a label, we must skip it with a jmp */
7725 b = gjmp(0);
7726 gsym(*case_sym);
7727 vseti(case_reg, 0);
7728 vpushi(v1);
7729 if (v1 == v2) {
7730 gen_op(TOK_EQ);
7731 *case_sym = gtst(1, 0);
7732 } else {
7733 gen_op(TOK_GE);
7734 *case_sym = gtst(1, 0);
7735 vseti(case_reg, 0);
7736 vpushi(v2);
7737 gen_op(TOK_LE);
7738 *case_sym = gtst(1, *case_sym);
7740 gsym(b);
7741 skip(':');
7742 is_expr = 0;
7743 goto block_after_label;
7744 } else
7745 if (tok == TOK_DEFAULT) {
7746 next();
7747 skip(':');
7748 if (!def_sym)
7749 expect("switch");
7750 if (*def_sym)
7751 error("too many 'default'");
7752 *def_sym = ind;
7753 is_expr = 0;
7754 goto block_after_label;
7755 } else
7756 if (tok == TOK_GOTO) {
7757 next();
7758 if (tok == '*' && gnu_ext) {
7759 /* computed goto */
7760 next();
7761 gexpr();
7762 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7763 expect("pointer");
7764 ggoto();
7765 } else if (tok >= TOK_UIDENT) {
7766 s = label_find(tok);
7767 /* put forward definition if needed */
7768 if (!s) {
7769 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7770 } else {
7771 if (s->r == LABEL_DECLARED)
7772 s->r = LABEL_FORWARD;
7774 /* label already defined */
7775 if (s->r & LABEL_FORWARD)
7776 s->next = (void *)gjmp((long)s->next);
7777 else
7778 gjmp_addr((long)s->next);
7779 next();
7780 } else {
7781 expect("label identifier");
7783 skip(';');
7784 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7785 asm_instr();
7786 } else {
7787 b = is_label();
7788 if (b) {
7789 /* label case */
7790 s = label_find(b);
7791 if (s) {
7792 if (s->r == LABEL_DEFINED)
7793 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7794 gsym((long)s->next);
7795 s->r = LABEL_DEFINED;
7796 } else {
7797 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7799 s->next = (void *)ind;
7800 /* we accept this, but it is a mistake */
7801 block_after_label:
7802 if (tok == '}') {
7803 warning("deprecated use of label at end of compound statement");
7804 } else {
7805 if (is_expr)
7806 vpop();
7807 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7809 } else {
7810 /* expression case */
7811 if (tok != ';') {
7812 if (is_expr) {
7813 vpop();
7814 gexpr();
7815 } else {
7816 gexpr();
7817 vpop();
7820 skip(';');
7825 /* t is the array or struct type. c is the array or struct
7826 address. cur_index/cur_field is the pointer to the current
7827 value. 'size_only' is true if only size info is needed (only used
7828 in arrays) */
7829 static void decl_designator(CType *type, Section *sec, unsigned long c,
7830 int *cur_index, Sym **cur_field,
7831 int size_only)
7833 Sym *s, *f;
7834 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7835 CType type1;
7837 notfirst = 0;
7838 elem_size = 0;
7839 nb_elems = 1;
7840 if (gnu_ext && (l = is_label()) != 0)
7841 goto struct_field;
7842 while (tok == '[' || tok == '.') {
7843 if (tok == '[') {
7844 if (!(type->t & VT_ARRAY))
7845 expect("array type");
7846 s = type->ref;
7847 next();
7848 index = expr_const();
7849 if (index < 0 || (s->c >= 0 && index >= s->c))
7850 expect("invalid index");
7851 if (tok == TOK_DOTS && gnu_ext) {
7852 next();
7853 index_last = expr_const();
7854 if (index_last < 0 ||
7855 (s->c >= 0 && index_last >= s->c) ||
7856 index_last < index)
7857 expect("invalid index");
7858 } else {
7859 index_last = index;
7861 skip(']');
7862 if (!notfirst)
7863 *cur_index = index_last;
7864 type = pointed_type(type);
7865 elem_size = type_size(type, &align);
7866 c += index * elem_size;
7867 /* NOTE: we only support ranges for last designator */
7868 nb_elems = index_last - index + 1;
7869 if (nb_elems != 1) {
7870 notfirst = 1;
7871 break;
7873 } else {
7874 next();
7875 l = tok;
7876 next();
7877 struct_field:
7878 if ((type->t & VT_BTYPE) != VT_STRUCT)
7879 expect("struct/union type");
7880 s = type->ref;
7881 l |= SYM_FIELD;
7882 f = s->next;
7883 while (f) {
7884 if (f->v == l)
7885 break;
7886 f = f->next;
7888 if (!f)
7889 expect("field");
7890 if (!notfirst)
7891 *cur_field = f;
7892 /* XXX: fix this mess by using explicit storage field */
7893 type1 = f->type;
7894 type1.t |= (type->t & ~VT_TYPE);
7895 type = &type1;
7896 c += f->c;
7898 notfirst = 1;
7900 if (notfirst) {
7901 if (tok == '=') {
7902 next();
7903 } else {
7904 if (!gnu_ext)
7905 expect("=");
7907 } else {
7908 if (type->t & VT_ARRAY) {
7909 index = *cur_index;
7910 type = pointed_type(type);
7911 c += index * type_size(type, &align);
7912 } else {
7913 f = *cur_field;
7914 if (!f)
7915 error("too many field init");
7916 /* XXX: fix this mess by using explicit storage field */
7917 type1 = f->type;
7918 type1.t |= (type->t & ~VT_TYPE);
7919 type = &type1;
7920 c += f->c;
7923 decl_initializer(type, sec, c, 0, size_only);
7925 /* XXX: make it more general */
7926 if (!size_only && nb_elems > 1) {
7927 unsigned long c_end;
7928 uint8_t *src, *dst;
7929 int i;
7931 if (!sec)
7932 error("range init not supported yet for dynamic storage");
7933 c_end = c + nb_elems * elem_size;
7934 if (c_end > sec->data_allocated)
7935 section_realloc(sec, c_end);
7936 src = sec->data + c;
7937 dst = src;
7938 for(i = 1; i < nb_elems; i++) {
7939 dst += elem_size;
7940 memcpy(dst, src, elem_size);
7945 #define EXPR_VAL 0
7946 #define EXPR_CONST 1
7947 #define EXPR_ANY 2
7949 /* store a value or an expression directly in global data or in local array */
7950 static void init_putv(CType *type, Section *sec, unsigned long c,
7951 int v, int expr_type)
7953 int saved_global_expr, bt, bit_pos, bit_size;
7954 void *ptr;
7955 unsigned long long bit_mask;
7956 CType dtype;
7958 switch(expr_type) {
7959 case EXPR_VAL:
7960 vpushi(v);
7961 break;
7962 case EXPR_CONST:
7963 /* compound literals must be allocated globally in this case */
7964 saved_global_expr = global_expr;
7965 global_expr = 1;
7966 expr_const1();
7967 global_expr = saved_global_expr;
7968 /* NOTE: symbols are accepted */
7969 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
7970 error("initializer element is not constant");
7971 break;
7972 case EXPR_ANY:
7973 expr_eq();
7974 break;
7977 dtype = *type;
7978 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7980 if (sec) {
7981 /* XXX: not portable */
7982 /* XXX: generate error if incorrect relocation */
7983 gen_assign_cast(&dtype);
7984 bt = type->t & VT_BTYPE;
7985 ptr = sec->data + c;
7986 /* XXX: make code faster ? */
7987 if (!(type->t & VT_BITFIELD)) {
7988 bit_pos = 0;
7989 bit_size = 32;
7990 bit_mask = -1LL;
7991 } else {
7992 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
7993 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
7994 bit_mask = (1LL << bit_size) - 1;
7996 if ((vtop->r & VT_SYM) &&
7997 (bt == VT_BYTE ||
7998 bt == VT_SHORT ||
7999 bt == VT_DOUBLE ||
8000 bt == VT_LDOUBLE ||
8001 bt == VT_LLONG ||
8002 (bt == VT_INT && bit_size != 32)))
8003 error("initializer element is not computable at load time");
8004 switch(bt) {
8005 case VT_BYTE:
8006 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8007 break;
8008 case VT_SHORT:
8009 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8010 break;
8011 case VT_DOUBLE:
8012 *(double *)ptr = vtop->c.d;
8013 break;
8014 case VT_LDOUBLE:
8015 *(long double *)ptr = vtop->c.ld;
8016 break;
8017 case VT_LLONG:
8018 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8019 break;
8020 default:
8021 if (vtop->r & VT_SYM) {
8022 greloc(sec, vtop->sym, c, R_DATA_32);
8024 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8025 break;
8027 vtop--;
8028 } else {
8029 vset(&dtype, VT_LOCAL, c);
8030 vswap();
8031 vstore();
8032 vpop();
8036 /* put zeros for variable based init */
8037 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8039 if (sec) {
8040 /* nothing to do because globals are already set to zero */
8041 } else {
8042 vpush_global_sym(&func_old_type, TOK_memset);
8043 vseti(VT_LOCAL, c);
8044 vpushi(0);
8045 vpushi(size);
8046 gfunc_call(3);
8050 /* 't' contains the type and storage info. 'c' is the offset of the
8051 object in section 'sec'. If 'sec' is NULL, it means stack based
8052 allocation. 'first' is true if array '{' must be read (multi
8053 dimension implicit array init handling). 'size_only' is true if
8054 size only evaluation is wanted (only for arrays). */
8055 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8056 int first, int size_only)
8058 int index, array_length, n, no_oblock, nb, parlevel, i;
8059 int size1, align1, expr_type;
8060 Sym *s, *f;
8061 CType *t1;
8063 if (type->t & VT_ARRAY) {
8064 s = type->ref;
8065 n = s->c;
8066 array_length = 0;
8067 t1 = pointed_type(type);
8068 size1 = type_size(t1, &align1);
8070 no_oblock = 1;
8071 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8072 tok == '{') {
8073 skip('{');
8074 no_oblock = 0;
8077 /* only parse strings here if correct type (otherwise: handle
8078 them as ((w)char *) expressions */
8079 if ((tok == TOK_LSTR &&
8080 (t1->t & VT_BTYPE) == VT_INT) ||
8081 (tok == TOK_STR &&
8082 (t1->t & VT_BTYPE) == VT_BYTE)) {
8083 while (tok == TOK_STR || tok == TOK_LSTR) {
8084 int cstr_len, ch;
8085 CString *cstr;
8087 cstr = tokc.cstr;
8088 /* compute maximum number of chars wanted */
8089 if (tok == TOK_STR)
8090 cstr_len = cstr->size;
8091 else
8092 cstr_len = cstr->size / sizeof(int);
8093 cstr_len--;
8094 nb = cstr_len;
8095 if (n >= 0 && nb > (n - array_length))
8096 nb = n - array_length;
8097 if (!size_only) {
8098 if (cstr_len > nb)
8099 warning("initializer-string for array is too long");
8100 /* in order to go faster for common case (char
8101 string in global variable, we handle it
8102 specifically */
8103 if (sec && tok == TOK_STR && size1 == 1) {
8104 memcpy(sec->data + c + array_length, cstr->data, nb);
8105 } else {
8106 for(i=0;i<nb;i++) {
8107 if (tok == TOK_STR)
8108 ch = ((unsigned char *)cstr->data)[i];
8109 else
8110 ch = ((int *)cstr->data)[i];
8111 init_putv(t1, sec, c + (array_length + i) * size1,
8112 ch, EXPR_VAL);
8116 array_length += nb;
8117 next();
8119 /* only add trailing zero if enough storage (no
8120 warning in this case since it is standard) */
8121 if (n < 0 || array_length < n) {
8122 if (!size_only) {
8123 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8125 array_length++;
8127 } else {
8128 index = 0;
8129 while (tok != '}') {
8130 decl_designator(type, sec, c, &index, NULL, size_only);
8131 if (n >= 0 && index >= n)
8132 error("index too large");
8133 /* must put zero in holes (note that doing it that way
8134 ensures that it even works with designators) */
8135 if (!size_only && array_length < index) {
8136 init_putz(t1, sec, c + array_length * size1,
8137 (index - array_length) * size1);
8139 index++;
8140 if (index > array_length)
8141 array_length = index;
8142 /* special test for multi dimensional arrays (may not
8143 be strictly correct if designators are used at the
8144 same time) */
8145 if (index >= n && no_oblock)
8146 break;
8147 if (tok == '}')
8148 break;
8149 skip(',');
8152 if (!no_oblock)
8153 skip('}');
8154 /* put zeros at the end */
8155 if (!size_only && n >= 0 && array_length < n) {
8156 init_putz(t1, sec, c + array_length * size1,
8157 (n - array_length) * size1);
8159 /* patch type size if needed */
8160 if (n < 0)
8161 s->c = array_length;
8162 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8163 (sec || !first || tok == '{')) {
8164 int par_count;
8166 /* NOTE: the previous test is a specific case for automatic
8167 struct/union init */
8168 /* XXX: union needs only one init */
8170 /* XXX: this test is incorrect for local initializers
8171 beginning with ( without {. It would be much more difficult
8172 to do it correctly (ideally, the expression parser should
8173 be used in all cases) */
8174 par_count = 0;
8175 if (tok == '(') {
8176 AttributeDef ad1;
8177 CType type1;
8178 next();
8179 while (tok == '(') {
8180 par_count++;
8181 next();
8183 if (!parse_btype(&type1, &ad1))
8184 expect("cast");
8185 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8186 #if 0
8187 if (!is_assignable_types(type, &type1))
8188 error("invalid type for cast");
8189 #endif
8190 skip(')');
8192 no_oblock = 1;
8193 if (first || tok == '{') {
8194 skip('{');
8195 no_oblock = 0;
8197 s = type->ref;
8198 f = s->next;
8199 array_length = 0;
8200 index = 0;
8201 n = s->c;
8202 while (tok != '}') {
8203 decl_designator(type, sec, c, NULL, &f, size_only);
8204 index = f->c;
8205 if (!size_only && array_length < index) {
8206 init_putz(type, sec, c + array_length,
8207 index - array_length);
8209 index = index + type_size(&f->type, &align1);
8210 if (index > array_length)
8211 array_length = index;
8212 f = f->next;
8213 if (no_oblock && f == NULL)
8214 break;
8215 if (tok == '}')
8216 break;
8217 skip(',');
8219 /* put zeros at the end */
8220 if (!size_only && array_length < n) {
8221 init_putz(type, sec, c + array_length,
8222 n - array_length);
8224 if (!no_oblock)
8225 skip('}');
8226 while (par_count) {
8227 skip(')');
8228 par_count--;
8230 } else if (tok == '{') {
8231 next();
8232 decl_initializer(type, sec, c, first, size_only);
8233 skip('}');
8234 } else if (size_only) {
8235 /* just skip expression */
8236 parlevel = 0;
8237 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8238 tok != -1) {
8239 if (tok == '(')
8240 parlevel++;
8241 else if (tok == ')')
8242 parlevel--;
8243 next();
8245 } else {
8246 /* currently, we always use constant expression for globals
8247 (may change for scripting case) */
8248 expr_type = EXPR_CONST;
8249 if (!sec)
8250 expr_type = EXPR_ANY;
8251 init_putv(type, sec, c, 0, expr_type);
8255 /* parse an initializer for type 't' if 'has_init' is non zero, and
8256 allocate space in local or global data space ('r' is either
8257 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8258 variable 'v' of scope 'scope' is declared before initializers are
8259 parsed. If 'v' is zero, then a reference to the new object is put
8260 in the value stack. If 'has_init' is 2, a special parsing is done
8261 to handle string constants. */
8262 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8263 int has_init, int v, int scope)
8265 int size, align, addr, data_offset;
8266 int level;
8267 ParseState saved_parse_state;
8268 TokenString init_str;
8269 Section *sec;
8271 size = type_size(type, &align);
8272 /* If unknown size, we must evaluate it before
8273 evaluating initializers because
8274 initializers can generate global data too
8275 (e.g. string pointers or ISOC99 compound
8276 literals). It also simplifies local
8277 initializers handling */
8278 tok_str_new(&init_str);
8279 if (size < 0) {
8280 if (!has_init)
8281 error("unknown type size");
8282 /* get all init string */
8283 if (has_init == 2) {
8284 /* only get strings */
8285 while (tok == TOK_STR || tok == TOK_LSTR) {
8286 tok_str_add_tok(&init_str);
8287 next();
8289 } else {
8290 level = 0;
8291 while (level > 0 || (tok != ',' && tok != ';')) {
8292 if (tok < 0)
8293 error("unexpected end of file in initializer");
8294 tok_str_add_tok(&init_str);
8295 if (tok == '{')
8296 level++;
8297 else if (tok == '}') {
8298 if (level == 0)
8299 break;
8300 level--;
8302 next();
8305 tok_str_add(&init_str, -1);
8306 tok_str_add(&init_str, 0);
8308 /* compute size */
8309 save_parse_state(&saved_parse_state);
8311 macro_ptr = init_str.str;
8312 next();
8313 decl_initializer(type, NULL, 0, 1, 1);
8314 /* prepare second initializer parsing */
8315 macro_ptr = init_str.str;
8316 next();
8318 /* if still unknown size, error */
8319 size = type_size(type, &align);
8320 if (size < 0)
8321 error("unknown type size");
8323 /* take into account specified alignment if bigger */
8324 if (ad->aligned > align)
8325 align = ad->aligned;
8326 if ((r & VT_VALMASK) == VT_LOCAL) {
8327 sec = NULL;
8328 if (do_bounds_check && (type->t & VT_ARRAY))
8329 loc--;
8330 loc = (loc - size) & -align;
8331 addr = loc;
8332 /* handles bounds */
8333 /* XXX: currently, since we do only one pass, we cannot track
8334 '&' operators, so we add only arrays */
8335 if (do_bounds_check && (type->t & VT_ARRAY)) {
8336 unsigned long *bounds_ptr;
8337 /* add padding between regions */
8338 loc--;
8339 /* then add local bound info */
8340 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8341 bounds_ptr[0] = addr;
8342 bounds_ptr[1] = size;
8344 if (v) {
8345 /* local variable */
8346 sym_push(v, type, r, addr);
8347 } else {
8348 /* push local reference */
8349 vset(type, r, addr);
8351 } else {
8352 Sym *sym;
8354 sym = NULL;
8355 if (v && scope == VT_CONST) {
8356 /* see if the symbol was already defined */
8357 sym = sym_find(v);
8358 if (sym) {
8359 if (!is_compatible_types(&sym->type, type))
8360 error("incompatible types for redefinition of '%s'",
8361 get_tok_str(v, NULL));
8362 if (sym->type.t & VT_EXTERN) {
8363 /* if the variable is extern, it was not allocated */
8364 sym->type.t &= ~VT_EXTERN;
8365 } else {
8366 /* we accept several definitions of the same
8367 global variable. this is tricky, because we
8368 must play with the SHN_COMMON type of the symbol */
8369 /* XXX: should check if the variable was already
8370 initialized. It is incorrect to initialized it
8371 twice */
8372 /* no init data, we won't add more to the symbol */
8373 if (!has_init)
8374 goto no_alloc;
8379 /* allocate symbol in corresponding section */
8380 sec = ad->section;
8381 if (!sec) {
8382 if (has_init)
8383 sec = data_section;
8385 if (sec) {
8386 data_offset = sec->data_offset;
8387 data_offset = (data_offset + align - 1) & -align;
8388 addr = data_offset;
8389 /* very important to increment global pointer at this time
8390 because initializers themselves can create new initializers */
8391 data_offset += size;
8392 /* add padding if bound check */
8393 if (do_bounds_check)
8394 data_offset++;
8395 sec->data_offset = data_offset;
8396 /* allocate section space to put the data */
8397 if (sec->sh_type != SHT_NOBITS &&
8398 data_offset > sec->data_allocated)
8399 section_realloc(sec, data_offset);
8400 } else {
8401 addr = 0; /* avoid warning */
8404 if (v) {
8405 if (scope == VT_CONST) {
8406 if (!sym)
8407 goto do_def;
8408 } else {
8409 do_def:
8410 sym = sym_push(v, type, r | VT_SYM, 0);
8412 /* update symbol definition */
8413 if (sec) {
8414 put_extern_sym(sym, sec, addr, size);
8415 } else {
8416 Elf32_Sym *esym;
8417 /* put a common area */
8418 put_extern_sym(sym, NULL, align, size);
8419 /* XXX: find a nicer way */
8420 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8421 esym->st_shndx = SHN_COMMON;
8423 } else {
8424 CValue cval;
8426 /* push global reference */
8427 sym = get_sym_ref(type, sec, addr, size);
8428 cval.ul = 0;
8429 vsetc(type, VT_CONST | VT_SYM, &cval);
8430 vtop->sym = sym;
8433 /* handles bounds now because the symbol must be defined
8434 before for the relocation */
8435 if (do_bounds_check) {
8436 unsigned long *bounds_ptr;
8438 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8439 /* then add global bound info */
8440 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8441 bounds_ptr[0] = 0; /* relocated */
8442 bounds_ptr[1] = size;
8445 if (has_init) {
8446 decl_initializer(type, sec, addr, 1, 0);
8447 /* restore parse state if needed */
8448 if (init_str.str) {
8449 tok_str_free(init_str.str);
8450 restore_parse_state(&saved_parse_state);
8453 no_alloc: ;
8456 void put_func_debug(Sym *sym)
8458 char buf[512];
8460 /* stabs info */
8461 /* XXX: we put here a dummy type */
8462 snprintf(buf, sizeof(buf), "%s:%c1",
8463 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8464 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8465 cur_text_section, sym->c);
8466 last_ind = 0;
8467 last_line_num = 0;
8470 /* not finished : try to put some local vars in registers */
8471 //#define CONFIG_REG_VARS
8473 #ifdef CONFIG_REG_VARS
8474 void add_var_ref(int t)
8476 printf("%s:%d: &%s\n",
8477 file->filename, file->line_num,
8478 get_tok_str(t, NULL));
8481 /* first pass on a function with heuristic to extract variable usage
8482 and pointer references to local variables for register allocation */
8483 void analyse_function(void)
8485 int level, t;
8487 for(;;) {
8488 if (tok == -1)
8489 break;
8490 /* any symbol coming after '&' is considered as being a
8491 variable whose reference is taken. It is highly unaccurate
8492 but it is difficult to do better without a complete parse */
8493 if (tok == '&') {
8494 next();
8495 /* if '& number', then no need to examine next tokens */
8496 if (tok == TOK_CINT ||
8497 tok == TOK_CUINT ||
8498 tok == TOK_CLLONG ||
8499 tok == TOK_CULLONG) {
8500 continue;
8501 } else if (tok >= TOK_UIDENT) {
8502 /* if '& ident [' or '& ident ->', then ident address
8503 is not needed */
8504 t = tok;
8505 next();
8506 if (tok != '[' && tok != TOK_ARROW)
8507 add_var_ref(t);
8508 } else {
8509 level = 0;
8510 while (tok != '}' && tok != ';' &&
8511 !((tok == ',' || tok == ')') && level == 0)) {
8512 if (tok >= TOK_UIDENT) {
8513 add_var_ref(tok);
8514 } else if (tok == '(') {
8515 level++;
8516 } else if (tok == ')') {
8517 level--;
8519 next();
8522 } else {
8523 next();
8527 #endif
8529 /* parse an old style function declaration list */
8530 /* XXX: check multiple parameter */
8531 static void func_decl_list(Sym *func_sym)
8533 AttributeDef ad;
8534 int v;
8535 Sym *s;
8536 CType btype, type;
8538 /* parse each declaration */
8539 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8540 if (!parse_btype(&btype, &ad))
8541 expect("declaration list");
8542 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8543 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8544 tok == ';') {
8545 /* we accept no variable after */
8546 } else {
8547 for(;;) {
8548 type = btype;
8549 type_decl(&type, &ad, &v, TYPE_DIRECT);
8550 /* find parameter in function parameter list */
8551 s = func_sym->next;
8552 while (s != NULL) {
8553 if ((s->v & ~SYM_FIELD) == v)
8554 goto found;
8555 s = s->next;
8557 error("declaration for parameter '%s' but no such parameter",
8558 get_tok_str(v, NULL));
8559 found:
8560 /* check that no storage specifier except 'register' was given */
8561 if (type.t & VT_STORAGE)
8562 error("storage class specified for '%s'", get_tok_str(v, NULL));
8563 convert_parameter_type(&type);
8564 /* we can add the type (NOTE: it could be local to the function) */
8565 s->type = type;
8566 /* accept other parameters */
8567 if (tok == ',')
8568 next();
8569 else
8570 break;
8573 skip(';');
8577 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8578 static void decl(int l)
8580 int v, has_init, r;
8581 CType type, btype;
8582 Sym *sym;
8583 AttributeDef ad;
8585 while (1) {
8586 if (!parse_btype(&btype, &ad)) {
8587 /* skip redundant ';' */
8588 /* XXX: find more elegant solution */
8589 if (tok == ';') {
8590 next();
8591 continue;
8593 /* special test for old K&R protos without explicit int
8594 type. Only accepted when defining global data */
8595 if (l == VT_LOCAL || tok < TOK_DEFINE)
8596 break;
8597 btype.t = VT_INT;
8599 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8600 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8601 tok == ';') {
8602 /* we accept no variable after */
8603 next();
8604 continue;
8606 while (1) { /* iterate thru each declaration */
8607 type = btype;
8608 type_decl(&type, &ad, &v, TYPE_DIRECT);
8609 #if 0
8611 char buf[500];
8612 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8613 printf("type = '%s'\n", buf);
8615 #endif
8616 if ((type.t & VT_BTYPE) == VT_FUNC) {
8617 /* if old style function prototype, we accept a
8618 declaration list */
8619 sym = type.ref;
8620 if (sym->c == FUNC_OLD)
8621 func_decl_list(sym);
8624 if (tok == '{') {
8625 #ifdef CONFIG_REG_VARS
8626 TokenString func_str;
8627 ParseState saved_parse_state;
8628 int block_level;
8629 #endif
8631 if (l == VT_LOCAL)
8632 error("cannot use local functions");
8633 if (!(type.t & VT_FUNC))
8634 expect("function definition");
8636 /* reject abstract declarators in function definition */
8637 sym = type.ref;
8638 while ((sym = sym->next) != NULL)
8639 if (!(sym->v & ~SYM_FIELD))
8640 expect("identifier");
8642 /* XXX: cannot do better now: convert extern line to static inline */
8643 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8644 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8646 #ifdef CONFIG_REG_VARS
8647 /* parse all function code and record it */
8649 tok_str_new(&func_str);
8651 block_level = 0;
8652 for(;;) {
8653 int t;
8654 if (tok == -1)
8655 error("unexpected end of file");
8656 tok_str_add_tok(&func_str);
8657 t = tok;
8658 next();
8659 if (t == '{') {
8660 block_level++;
8661 } else if (t == '}') {
8662 block_level--;
8663 if (block_level == 0)
8664 break;
8667 tok_str_add(&func_str, -1);
8668 tok_str_add(&func_str, 0);
8670 save_parse_state(&saved_parse_state);
8672 macro_ptr = func_str.str;
8673 next();
8674 analyse_function();
8675 #endif
8677 /* compute text section */
8678 cur_text_section = ad.section;
8679 if (!cur_text_section)
8680 cur_text_section = text_section;
8681 ind = cur_text_section->data_offset;
8682 funcname = get_tok_str(v, NULL);
8683 sym = sym_find(v);
8684 if (sym) {
8685 /* if symbol is already defined, then put complete type */
8686 sym->type = type;
8687 } else {
8688 /* put function symbol */
8689 sym = global_identifier_push(v, type.t, 0);
8690 sym->type.ref = type.ref;
8692 /* NOTE: we patch the symbol size later */
8693 put_extern_sym(sym, cur_text_section, ind, 0);
8694 func_ind = ind;
8695 sym->r = VT_SYM | VT_CONST;
8696 /* put debug symbol */
8697 if (do_debug)
8698 put_func_debug(sym);
8699 /* push a dummy symbol to enable local sym storage */
8700 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8701 gfunc_prolog(&type);
8702 rsym = 0;
8703 #ifdef CONFIG_REG_VARS
8704 macro_ptr = func_str.str;
8705 next();
8706 #endif
8707 block(NULL, NULL, NULL, NULL, 0, 0);
8708 gsym(rsym);
8709 gfunc_epilog();
8710 cur_text_section->data_offset = ind;
8711 label_pop(&global_label_stack, NULL);
8712 sym_pop(&local_stack, NULL); /* reset local stack */
8713 /* end of function */
8714 /* patch symbol size */
8715 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8716 ind - func_ind;
8717 if (do_debug) {
8718 put_stabn(N_FUN, 0, 0, ind - func_ind);
8720 funcname = ""; /* for safety */
8721 func_vt.t = VT_VOID; /* for safety */
8722 ind = 0; /* for safety */
8724 #ifdef CONFIG_REG_VARS
8725 tok_str_free(func_str.str);
8726 restore_parse_state(&saved_parse_state);
8727 #endif
8728 break;
8729 } else {
8730 if (btype.t & VT_TYPEDEF) {
8731 /* save typedefed type */
8732 /* XXX: test storage specifiers ? */
8733 sym = sym_push(v, &type, 0, 0);
8734 sym->type.t |= VT_TYPEDEF;
8735 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8736 /* external function definition */
8737 external_sym(v, &type, 0);
8738 } else {
8739 /* not lvalue if array */
8740 r = 0;
8741 if (!(type.t & VT_ARRAY))
8742 r |= lvalue_type(type.t);
8743 has_init = (tok == '=');
8744 if ((btype.t & VT_EXTERN) ||
8745 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8746 !has_init && l == VT_CONST && type.ref->c < 0)) {
8747 /* external variable */
8748 /* NOTE: as GCC, uninitialized global static
8749 arrays of null size are considered as
8750 extern */
8751 external_sym(v, &type, r);
8752 } else {
8753 if (type.t & VT_STATIC)
8754 r |= VT_CONST;
8755 else
8756 r |= l;
8757 if (has_init)
8758 next();
8759 decl_initializer_alloc(&type, &ad, r,
8760 has_init, v, l);
8763 if (tok != ',') {
8764 skip(';');
8765 break;
8767 next();
8773 /* better than nothing, but needs extension to handle '-E' option
8774 correctly too */
8775 static void preprocess_init(TCCState *s1)
8777 s1->include_stack_ptr = s1->include_stack;
8778 /* XXX: move that before to avoid having to initialize
8779 file->ifdef_stack_ptr ? */
8780 s1->ifdef_stack_ptr = s1->ifdef_stack;
8781 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8783 /* XXX: not ANSI compliant: bound checking says error */
8784 vtop = vstack - 1;
8787 /* compile the C file opened in 'file'. Return non zero if errors. */
8788 static int tcc_compile(TCCState *s1)
8790 Sym *define_start;
8791 char buf[512];
8792 volatile int section_sym;
8794 #ifdef INC_DEBUG
8795 printf("%s: **** new file\n", file->filename);
8796 #endif
8797 preprocess_init(s1);
8799 funcname = "";
8800 anon_sym = SYM_FIRST_ANOM;
8802 /* file info: full path + filename */
8803 section_sym = 0; /* avoid warning */
8804 if (do_debug) {
8805 section_sym = put_elf_sym(symtab_section, 0, 0,
8806 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8807 text_section->sh_num, NULL);
8808 getcwd(buf, sizeof(buf));
8809 pstrcat(buf, sizeof(buf), "/");
8810 put_stabs_r(buf, N_SO, 0, 0,
8811 text_section->data_offset, text_section, section_sym);
8812 put_stabs_r(file->filename, N_SO, 0, 0,
8813 text_section->data_offset, text_section, section_sym);
8815 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8816 symbols can be safely used */
8817 put_elf_sym(symtab_section, 0, 0,
8818 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8819 SHN_ABS, file->filename);
8821 /* define some often used types */
8822 int_type.t = VT_INT;
8824 char_pointer_type.t = VT_BYTE;
8825 mk_pointer(&char_pointer_type);
8827 func_old_type.t = VT_FUNC;
8828 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8830 #if 0
8831 /* define 'void *alloca(unsigned int)' builtin function */
8833 Sym *s1;
8835 p = anon_sym++;
8836 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8837 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8838 s1->next = NULL;
8839 sym->next = s1;
8840 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8842 #endif
8844 define_start = define_stack;
8846 if (setjmp(s1->error_jmp_buf) == 0) {
8847 s1->nb_errors = 0;
8848 s1->error_set_jmp_enabled = 1;
8850 ch = file->buf_ptr[0];
8851 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8852 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8853 next();
8854 decl(VT_CONST);
8855 if (tok != TOK_EOF)
8856 expect("declaration");
8858 /* end of translation unit info */
8859 if (do_debug) {
8860 put_stabs_r(NULL, N_SO, 0, 0,
8861 text_section->data_offset, text_section, section_sym);
8864 s1->error_set_jmp_enabled = 0;
8866 /* reset define stack, but leave -Dsymbols (may be incorrect if
8867 they are undefined) */
8868 free_defines(define_start);
8870 sym_pop(&global_stack, NULL);
8872 return s1->nb_errors != 0 ? -1 : 0;
8875 #ifdef LIBTCC
8876 int tcc_compile_string(TCCState *s, const char *str)
8878 BufferedFile bf1, *bf = &bf1;
8879 int ret, len;
8880 char *buf;
8882 /* init file structure */
8883 bf->fd = -1;
8884 /* XXX: avoid copying */
8885 len = strlen(str);
8886 buf = tcc_malloc(len + 1);
8887 if (!buf)
8888 return -1;
8889 memcpy(buf, str, len);
8890 buf[len] = CH_EOB;
8891 bf->buf_ptr = buf;
8892 bf->buf_end = buf + len;
8893 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8894 bf->line_num = 1;
8895 file = bf;
8897 ret = tcc_compile(s);
8899 tcc_free(buf);
8901 /* currently, no need to close */
8902 return ret;
8904 #endif
8906 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8907 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8909 BufferedFile bf1, *bf = &bf1;
8911 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8912 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8913 /* default value */
8914 if (!value)
8915 value = "1";
8916 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8918 /* init file structure */
8919 bf->fd = -1;
8920 bf->buf_ptr = bf->buffer;
8921 bf->buf_end = bf->buffer + strlen(bf->buffer);
8922 *bf->buf_end = CH_EOB;
8923 bf->filename[0] = '\0';
8924 bf->line_num = 1;
8925 file = bf;
8927 s1->include_stack_ptr = s1->include_stack;
8929 /* parse with define parser */
8930 ch = file->buf_ptr[0];
8931 next_nomacro();
8932 parse_define();
8933 file = NULL;
8936 /* undefine a preprocessor symbol */
8937 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8939 TokenSym *ts;
8940 Sym *s;
8941 ts = tok_alloc(sym, strlen(sym));
8942 s = define_find(ts->tok);
8943 /* undefine symbol by putting an invalid name */
8944 if (s)
8945 define_undef(s);
8948 #ifdef CONFIG_TCC_ASM
8950 #ifdef TCC_TARGET_I386
8951 #include "i386-asm.c"
8952 #endif
8953 #include "tccasm.c"
8955 #else
8956 static void asm_instr(void)
8958 error("inline asm() not supported");
8960 #endif
8962 #include "tccelf.c"
8964 /* print the position in the source file of PC value 'pc' by reading
8965 the stabs debug information */
8966 static void rt_printline(unsigned long wanted_pc)
8968 Stab_Sym *sym, *sym_end;
8969 char func_name[128], last_func_name[128];
8970 unsigned long func_addr, last_pc, pc;
8971 const char *incl_files[INCLUDE_STACK_SIZE];
8972 int incl_index, len, last_line_num, i;
8973 const char *str, *p;
8975 fprintf(stderr, "0x%08lx:", wanted_pc);
8977 func_name[0] = '\0';
8978 func_addr = 0;
8979 incl_index = 0;
8980 last_func_name[0] = '\0';
8981 last_pc = 0xffffffff;
8982 last_line_num = 1;
8983 sym = (Stab_Sym *)stab_section->data + 1;
8984 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
8985 while (sym < sym_end) {
8986 switch(sym->n_type) {
8987 /* function start or end */
8988 case N_FUN:
8989 if (sym->n_strx == 0) {
8990 /* we test if between last line and end of function */
8991 pc = sym->n_value + func_addr;
8992 if (wanted_pc >= last_pc && wanted_pc < pc)
8993 goto found;
8994 func_name[0] = '\0';
8995 func_addr = 0;
8996 } else {
8997 str = stabstr_section->data + sym->n_strx;
8998 p = strchr(str, ':');
8999 if (!p) {
9000 pstrcpy(func_name, sizeof(func_name), str);
9001 } else {
9002 len = p - str;
9003 if (len > sizeof(func_name) - 1)
9004 len = sizeof(func_name) - 1;
9005 memcpy(func_name, str, len);
9006 func_name[len] = '\0';
9008 func_addr = sym->n_value;
9010 break;
9011 /* line number info */
9012 case N_SLINE:
9013 pc = sym->n_value + func_addr;
9014 if (wanted_pc >= last_pc && wanted_pc < pc)
9015 goto found;
9016 last_pc = pc;
9017 last_line_num = sym->n_desc;
9018 /* XXX: slow! */
9019 strcpy(last_func_name, func_name);
9020 break;
9021 /* include files */
9022 case N_BINCL:
9023 str = stabstr_section->data + sym->n_strx;
9024 add_incl:
9025 if (incl_index < INCLUDE_STACK_SIZE) {
9026 incl_files[incl_index++] = str;
9028 break;
9029 case N_EINCL:
9030 if (incl_index > 1)
9031 incl_index--;
9032 break;
9033 case N_SO:
9034 if (sym->n_strx == 0) {
9035 incl_index = 0; /* end of translation unit */
9036 } else {
9037 str = stabstr_section->data + sym->n_strx;
9038 /* do not add path */
9039 len = strlen(str);
9040 if (len > 0 && str[len - 1] != '/')
9041 goto add_incl;
9043 break;
9045 sym++;
9048 /* second pass: we try symtab symbols (no line number info) */
9049 incl_index = 0;
9051 Elf32_Sym *sym, *sym_end;
9052 int type;
9054 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9055 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9056 sym < sym_end;
9057 sym++) {
9058 type = ELF32_ST_TYPE(sym->st_info);
9059 if (type == STT_FUNC) {
9060 if (wanted_pc >= sym->st_value &&
9061 wanted_pc < sym->st_value + sym->st_size) {
9062 pstrcpy(last_func_name, sizeof(last_func_name),
9063 strtab_section->data + sym->st_name);
9064 goto found;
9069 /* did not find any info: */
9070 fprintf(stderr, " ???\n");
9071 return;
9072 found:
9073 if (last_func_name[0] != '\0') {
9074 fprintf(stderr, " %s()", last_func_name);
9076 if (incl_index > 0) {
9077 fprintf(stderr, " (%s:%d",
9078 incl_files[incl_index - 1], last_line_num);
9079 for(i = incl_index - 2; i >= 0; i--)
9080 fprintf(stderr, ", included from %s", incl_files[i]);
9081 fprintf(stderr, ")");
9083 fprintf(stderr, "\n");
9086 #ifndef WIN32
9088 #ifdef __i386__
9090 /* fix for glibc 2.1 */
9091 #ifndef REG_EIP
9092 #define REG_EIP EIP
9093 #define REG_EBP EBP
9094 #endif
9096 /* return the PC at frame level 'level'. Return non zero if not found */
9097 static int rt_get_caller_pc(unsigned long *paddr,
9098 ucontext_t *uc, int level)
9100 unsigned long fp;
9101 int i;
9103 if (level == 0) {
9104 #if defined(__FreeBSD__)
9105 *paddr = uc->uc_mcontext.mc_eip;
9106 #elif defined(__dietlibc__)
9107 *paddr = uc->uc_mcontext.eip;
9108 #else
9109 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9110 #endif
9111 return 0;
9112 } else {
9113 #if defined(__FreeBSD__)
9114 fp = uc->uc_mcontext.mc_ebp;
9115 #elif defined(__dietlibc__)
9116 fp = uc->uc_mcontext.ebp;
9117 #else
9118 fp = uc->uc_mcontext.gregs[REG_EBP];
9119 #endif
9120 for(i=1;i<level;i++) {
9121 /* XXX: check address validity with program info */
9122 if (fp <= 0x1000 || fp >= 0xc0000000)
9123 return -1;
9124 fp = ((unsigned long *)fp)[0];
9126 *paddr = ((unsigned long *)fp)[1];
9127 return 0;
9130 #else
9132 #warning add arch specific rt_get_caller_pc()
9134 static int rt_get_caller_pc(unsigned long *paddr,
9135 ucontext_t *uc, int level)
9137 return -1;
9139 #endif
9141 /* emit a run time error at position 'pc' */
9142 void rt_error(ucontext_t *uc, const char *fmt, ...)
9144 va_list ap;
9145 unsigned long pc;
9146 int i;
9148 va_start(ap, fmt);
9149 fprintf(stderr, "Runtime error: ");
9150 vfprintf(stderr, fmt, ap);
9151 fprintf(stderr, "\n");
9152 for(i=0;i<num_callers;i++) {
9153 if (rt_get_caller_pc(&pc, uc, i) < 0)
9154 break;
9155 if (i == 0)
9156 fprintf(stderr, "at ");
9157 else
9158 fprintf(stderr, "by ");
9159 rt_printline(pc);
9161 exit(255);
9162 va_end(ap);
9165 /* signal handler for fatal errors */
9166 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9168 ucontext_t *uc = puc;
9170 switch(signum) {
9171 case SIGFPE:
9172 switch(siginf->si_code) {
9173 case FPE_INTDIV:
9174 case FPE_FLTDIV:
9175 rt_error(uc, "division by zero");
9176 break;
9177 default:
9178 rt_error(uc, "floating point exception");
9179 break;
9181 break;
9182 case SIGBUS:
9183 case SIGSEGV:
9184 if (rt_bound_error_msg && *rt_bound_error_msg)
9185 rt_error(uc, *rt_bound_error_msg);
9186 else
9187 rt_error(uc, "dereferencing invalid pointer");
9188 break;
9189 case SIGILL:
9190 rt_error(uc, "illegal instruction");
9191 break;
9192 case SIGABRT:
9193 rt_error(uc, "abort() called");
9194 break;
9195 default:
9196 rt_error(uc, "caught signal %d", signum);
9197 break;
9199 exit(255);
9201 #endif
9203 /* do all relocations (needed before using tcc_get_symbol()) */
9204 int tcc_relocate(TCCState *s1)
9206 Section *s;
9207 int i;
9209 s1->nb_errors = 0;
9211 tcc_add_runtime(s1);
9213 build_got_entries(s1);
9215 relocate_common_syms();
9217 /* compute relocation address : section are relocated in place. We
9218 also alloc the bss space */
9219 for(i = 1; i < s1->nb_sections; i++) {
9220 s = s1->sections[i];
9221 if (s->sh_flags & SHF_ALLOC) {
9222 if (s->sh_type == SHT_NOBITS)
9223 s->data = tcc_mallocz(s->data_offset);
9224 s->sh_addr = (unsigned long)s->data;
9228 relocate_syms(s1, 1);
9230 if (s1->nb_errors != 0)
9231 return -1;
9233 /* relocate each section */
9234 for(i = 1; i < s1->nb_sections; i++) {
9235 s = s1->sections[i];
9236 if (s->reloc)
9237 relocate_section(s1, s);
9239 return 0;
9242 /* launch the compiled program with the given arguments */
9243 int tcc_run(TCCState *s1, int argc, char **argv)
9245 int (*prog_main)(int, char **);
9247 if (tcc_relocate(s1) < 0)
9248 return -1;
9250 prog_main = tcc_get_symbol_err(s1, "main");
9252 if (do_debug) {
9253 #ifdef WIN32
9254 error("debug mode currently not available for Windows");
9255 #else
9256 struct sigaction sigact;
9257 /* install TCC signal handlers to print debug info on fatal
9258 runtime errors */
9259 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9260 sigact.sa_sigaction = sig_error;
9261 sigemptyset(&sigact.sa_mask);
9262 sigaction(SIGFPE, &sigact, NULL);
9263 sigaction(SIGILL, &sigact, NULL);
9264 sigaction(SIGSEGV, &sigact, NULL);
9265 sigaction(SIGBUS, &sigact, NULL);
9266 sigaction(SIGABRT, &sigact, NULL);
9267 #endif
9270 #ifdef CONFIG_TCC_BCHECK
9271 if (do_bounds_check) {
9272 void (*bound_init)(void);
9274 /* set error function */
9275 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9276 "__bound_error_msg");
9278 /* XXX: use .init section so that it also work in binary ? */
9279 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9280 bound_init();
9282 #endif
9283 return (*prog_main)(argc, argv);
9286 TCCState *tcc_new(void)
9288 const char *p, *r;
9289 TCCState *s;
9290 TokenSym *ts;
9291 int i, c;
9293 s = tcc_mallocz(sizeof(TCCState));
9294 if (!s)
9295 return NULL;
9296 tcc_state = s;
9297 s->output_type = TCC_OUTPUT_MEMORY;
9299 /* init isid table */
9300 for(i=0;i<256;i++)
9301 isidnum_table[i] = isid(i) || isnum(i);
9303 /* add all tokens */
9304 table_ident = NULL;
9305 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9307 tok_ident = TOK_IDENT;
9308 p = tcc_keywords;
9309 while (*p) {
9310 r = p;
9311 for(;;) {
9312 c = *r++;
9313 if (c == '\0')
9314 break;
9316 ts = tok_alloc(p, r - p - 1);
9317 p = r;
9320 /* we add dummy defines for some special macros to speed up tests
9321 and to have working defined() */
9322 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9323 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9324 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9325 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9327 /* standard defines */
9328 tcc_define_symbol(s, "__STDC__", NULL);
9329 #if defined(TCC_TARGET_I386)
9330 tcc_define_symbol(s, "__i386__", NULL);
9331 #endif
9332 #if defined(TCC_TARGET_ARM)
9333 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9334 tcc_define_symbol(s, "__arm_elf__", NULL);
9335 tcc_define_symbol(s, "__arm_elf", NULL);
9336 tcc_define_symbol(s, "arm_elf", NULL);
9337 tcc_define_symbol(s, "__arm__", NULL);
9338 tcc_define_symbol(s, "__arm", NULL);
9339 tcc_define_symbol(s, "arm", NULL);
9340 tcc_define_symbol(s, "__APCS_32__", NULL);
9341 #endif
9342 #if defined(linux)
9343 tcc_define_symbol(s, "__linux__", NULL);
9344 tcc_define_symbol(s, "linux", NULL);
9345 #endif
9346 /* tiny C specific defines */
9347 tcc_define_symbol(s, "__TINYC__", NULL);
9349 /* tiny C & gcc defines */
9350 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9351 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9352 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9354 /* default library paths */
9355 tcc_add_library_path(s, "/usr/local/lib");
9356 tcc_add_library_path(s, "/usr/lib");
9357 tcc_add_library_path(s, "/lib");
9359 /* no section zero */
9360 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9362 /* create standard sections */
9363 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9364 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9365 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9367 /* symbols are always generated for linking stage */
9368 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9369 ".strtab",
9370 ".hashtab", SHF_PRIVATE);
9371 strtab_section = symtab_section->link;
9373 /* private symbol table for dynamic symbols */
9374 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9375 ".dynstrtab",
9376 ".dynhashtab", SHF_PRIVATE);
9377 s->alacarte_link = 1;
9379 #ifdef CHAR_IS_UNSIGNED
9380 s->char_is_unsigned = 1;
9381 #endif
9382 return s;
9385 void tcc_delete(TCCState *s1)
9387 int i, n;
9389 /* free -D defines */
9390 free_defines(NULL);
9392 /* free tokens */
9393 n = tok_ident - TOK_IDENT;
9394 for(i = 0; i < n; i++)
9395 tcc_free(table_ident[i]);
9396 tcc_free(table_ident);
9398 /* free all sections */
9400 free_section(symtab_section->hash);
9402 free_section(s1->dynsymtab_section->hash);
9403 free_section(s1->dynsymtab_section->link);
9404 free_section(s1->dynsymtab_section);
9406 for(i = 1; i < s1->nb_sections; i++)
9407 free_section(s1->sections[i]);
9408 tcc_free(s1->sections);
9410 /* free loaded dlls array */
9411 for(i = 0; i < s1->nb_loaded_dlls; i++)
9412 tcc_free(s1->loaded_dlls[i]);
9413 tcc_free(s1->loaded_dlls);
9415 /* library paths */
9416 for(i = 0; i < s1->nb_library_paths; i++)
9417 tcc_free(s1->library_paths[i]);
9418 tcc_free(s1->library_paths);
9420 /* cached includes */
9421 for(i = 0; i < s1->nb_cached_includes; i++)
9422 tcc_free(s1->cached_includes[i]);
9423 tcc_free(s1->cached_includes);
9425 for(i = 0; i < s1->nb_include_paths; i++)
9426 tcc_free(s1->include_paths[i]);
9427 tcc_free(s1->include_paths);
9429 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9430 tcc_free(s1->sysinclude_paths[i]);
9431 tcc_free(s1->sysinclude_paths);
9433 tcc_free(s1);
9436 int tcc_add_include_path(TCCState *s1, const char *pathname)
9438 char *pathname1;
9440 pathname1 = tcc_strdup(pathname);
9441 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9442 return 0;
9445 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9447 char *pathname1;
9449 pathname1 = tcc_strdup(pathname);
9450 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9451 return 0;
9454 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9456 const char *ext, *filename1;
9457 Elf32_Ehdr ehdr;
9458 int fd, ret;
9459 BufferedFile *saved_file;
9461 /* find source file type with extension */
9462 filename1 = strrchr(filename, '/');
9463 if (filename1)
9464 filename1++;
9465 else
9466 filename1 = filename;
9467 ext = strrchr(filename1, '.');
9468 if (ext)
9469 ext++;
9471 /* open the file */
9472 saved_file = file;
9473 file = tcc_open(s1, filename);
9474 if (!file) {
9475 if (flags & AFF_PRINT_ERROR) {
9476 error_noabort("file '%s' not found", filename);
9478 ret = -1;
9479 goto fail1;
9482 if (!ext || !strcmp(ext, "c")) {
9483 /* C file assumed */
9484 ret = tcc_compile(s1);
9485 } else
9486 #ifdef CONFIG_TCC_ASM
9487 if (!strcmp(ext, "S")) {
9488 /* preprocessed assembler */
9489 ret = tcc_assemble(s1, 1);
9490 } else if (!strcmp(ext, "s")) {
9491 /* non preprocessed assembler */
9492 ret = tcc_assemble(s1, 0);
9493 } else
9494 #endif
9496 fd = file->fd;
9497 /* assume executable format: auto guess file type */
9498 ret = read(fd, &ehdr, sizeof(ehdr));
9499 lseek(fd, 0, SEEK_SET);
9500 if (ret <= 0) {
9501 error_noabort("could not read header");
9502 goto fail;
9503 } else if (ret != sizeof(ehdr)) {
9504 goto try_load_script;
9507 if (ehdr.e_ident[0] == ELFMAG0 &&
9508 ehdr.e_ident[1] == ELFMAG1 &&
9509 ehdr.e_ident[2] == ELFMAG2 &&
9510 ehdr.e_ident[3] == ELFMAG3) {
9511 file->line_num = 0; /* do not display line number if error */
9512 if (ehdr.e_type == ET_REL) {
9513 ret = tcc_load_object_file(s1, fd, 0);
9514 } else if (ehdr.e_type == ET_DYN) {
9515 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9516 void *h;
9517 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9518 if (h)
9519 ret = 0;
9520 else
9521 ret = -1;
9522 } else {
9523 ret = tcc_load_dll(s1, fd, filename,
9524 (flags & AFF_REFERENCED_DLL) != 0);
9526 } else {
9527 error_noabort("unrecognized ELF file");
9528 goto fail;
9530 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9531 file->line_num = 0; /* do not display line number if error */
9532 ret = tcc_load_archive(s1, fd);
9533 } else {
9534 /* as GNU ld, consider it is an ld script if not recognized */
9535 try_load_script:
9536 ret = tcc_load_ldscript(s1);
9537 if (ret < 0) {
9538 error_noabort("unrecognized file type");
9539 goto fail;
9543 the_end:
9544 tcc_close(file);
9545 fail1:
9546 file = saved_file;
9547 return ret;
9548 fail:
9549 ret = -1;
9550 goto the_end;
9553 int tcc_add_file(TCCState *s, const char *filename)
9555 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9558 int tcc_add_library_path(TCCState *s, const char *pathname)
9560 char *pathname1;
9562 pathname1 = tcc_strdup(pathname);
9563 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9564 return 0;
9567 /* find and load a dll. Return non zero if not found */
9568 /* XXX: add '-rpath' option support ? */
9569 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9571 char buf[1024];
9572 int i;
9574 for(i = 0; i < s->nb_library_paths; i++) {
9575 snprintf(buf, sizeof(buf), "%s/%s",
9576 s->library_paths[i], filename);
9577 if (tcc_add_file_internal(s, buf, flags) == 0)
9578 return 0;
9580 return -1;
9583 /* the library name is the same as the argument of the '-l' option */
9584 int tcc_add_library(TCCState *s, const char *libraryname)
9586 char buf[1024];
9587 int i;
9589 /* first we look for the dynamic library if not static linking */
9590 if (!s->static_link) {
9591 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9592 if (tcc_add_dll(s, buf, 0) == 0)
9593 return 0;
9596 /* then we look for the static library */
9597 for(i = 0; i < s->nb_library_paths; i++) {
9598 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9599 s->library_paths[i], libraryname);
9600 if (tcc_add_file_internal(s, buf, 0) == 0)
9601 return 0;
9603 return -1;
9606 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9608 add_elf_sym(symtab_section, val, 0,
9609 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9610 SHN_ABS, name);
9611 return 0;
9614 int tcc_set_output_type(TCCState *s, int output_type)
9616 char buf[1024];
9618 s->output_type = output_type;
9620 if (!s->nostdinc) {
9621 /* default include paths */
9622 /* XXX: reverse order needed if -isystem support */
9623 tcc_add_sysinclude_path(s, "/usr/local/include");
9624 tcc_add_sysinclude_path(s, "/usr/include");
9625 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9626 tcc_add_sysinclude_path(s, buf);
9629 /* if bound checking, then add corresponding sections */
9630 #ifdef CONFIG_TCC_BCHECK
9631 if (do_bounds_check) {
9632 /* define symbol */
9633 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9634 /* create bounds sections */
9635 bounds_section = new_section(s, ".bounds",
9636 SHT_PROGBITS, SHF_ALLOC);
9637 lbounds_section = new_section(s, ".lbounds",
9638 SHT_PROGBITS, SHF_ALLOC);
9640 #endif
9642 if (s->char_is_unsigned) {
9643 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
9646 /* add debug sections */
9647 if (do_debug) {
9648 /* stab symbols */
9649 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9650 stab_section->sh_entsize = sizeof(Stab_Sym);
9651 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9652 put_elf_str(stabstr_section, "");
9653 stab_section->link = stabstr_section;
9654 /* put first entry */
9655 put_stabs("", 0, 0, 0, 0);
9658 /* add libc crt1/crti objects */
9659 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9660 !s->nostdlib) {
9661 if (output_type != TCC_OUTPUT_DLL)
9662 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9663 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9665 return 0;
9668 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9669 #define FD_INVERT 0x0002 /* invert value before storing */
9671 typedef struct FlagDef {
9672 uint16_t offset;
9673 uint16_t flags;
9674 const char *name;
9675 } FlagDef;
9677 static const FlagDef warning_defs[] = {
9678 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9679 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9680 { offsetof(TCCState, warn_error), 0, "error" },
9681 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
9682 "implicit-function-declaration" },
9685 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
9686 const char *name, int value)
9688 int i;
9689 const FlagDef *p;
9690 const char *r;
9692 r = name;
9693 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
9694 r += 3;
9695 value = !value;
9697 for(i = 0, p = flags; i < nb_flags; i++, p++) {
9698 if (!strcmp(r, p->name))
9699 goto found;
9701 return -1;
9702 found:
9703 if (p->flags & FD_INVERT)
9704 value = !value;
9705 *(int *)((uint8_t *)s + p->offset) = value;
9706 return 0;
9710 /* set/reset a warning */
9711 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9713 int i;
9714 const FlagDef *p;
9716 if (!strcmp(warning_name, "all")) {
9717 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9718 if (p->flags & WD_ALL)
9719 *(int *)((uint8_t *)s + p->offset) = 1;
9721 return 0;
9722 } else {
9723 return set_flag(s, warning_defs, countof(warning_defs),
9724 warning_name, value);
9728 static const FlagDef flag_defs[] = {
9729 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
9730 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
9733 /* set/reset a flag */
9734 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
9736 return set_flag(s, flag_defs, countof(flag_defs),
9737 flag_name, value);
9740 #if !defined(LIBTCC)
9742 /* extract the basename of a file */
9743 static const char *tcc_basename(const char *name)
9745 const char *p;
9746 p = strrchr(name, '/');
9747 #ifdef WIN32
9748 if (!p)
9749 p = strrchr(name, '\\');
9750 #endif
9751 if (!p)
9752 p = name;
9753 else
9754 p++;
9755 return p;
9758 static int64_t getclock_us(void)
9760 #ifdef WIN32
9761 struct _timeb tb;
9762 _ftime(&tb);
9763 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9764 #else
9765 struct timeval tv;
9766 gettimeofday(&tv, NULL);
9767 return tv.tv_sec * 1000000LL + tv.tv_usec;
9768 #endif
9771 void help(void)
9773 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2003 Fabrice Bellard\n"
9774 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9775 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9776 " [infile1 infile2...] [-run infile args...]\n"
9777 "\n"
9778 "General options:\n"
9779 " -v display current version\n"
9780 " -c compile only - generate an object file\n"
9781 " -o outfile set output filename\n"
9782 " -Bdir set tcc internal library path\n"
9783 " -bench output compilation statistics\n"
9784 " -run run compiled source\n"
9785 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
9786 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
9787 " -w disable all warnings\n"
9788 "Preprocessor options:\n"
9789 " -Idir add include path 'dir'\n"
9790 " -Dsym[=val] define 'sym' with value 'val'\n"
9791 " -Usym undefine 'sym'\n"
9792 "Linker options:\n"
9793 " -Ldir add library path 'dir'\n"
9794 " -llib link with dynamic or static library 'lib'\n"
9795 " -shared generate a shared library\n"
9796 " -static static linking\n"
9797 " -rdynamic export all global symbols to dynamic linker\n"
9798 " -r relocatable output\n"
9799 "Debugger options:\n"
9800 " -g generate runtime debug info\n"
9801 #ifdef CONFIG_TCC_BCHECK
9802 " -b compile with built-in memory and bounds checker (implies -g)\n"
9803 #endif
9804 " -bt N show N callers in stack traces\n"
9808 #define TCC_OPTION_HAS_ARG 0x0001
9809 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9811 typedef struct TCCOption {
9812 const char *name;
9813 uint16_t index;
9814 uint16_t flags;
9815 } TCCOption;
9817 enum {
9818 TCC_OPTION_HELP,
9819 TCC_OPTION_I,
9820 TCC_OPTION_D,
9821 TCC_OPTION_U,
9822 TCC_OPTION_L,
9823 TCC_OPTION_B,
9824 TCC_OPTION_l,
9825 TCC_OPTION_bench,
9826 TCC_OPTION_bt,
9827 TCC_OPTION_b,
9828 TCC_OPTION_g,
9829 TCC_OPTION_c,
9830 TCC_OPTION_static,
9831 TCC_OPTION_shared,
9832 TCC_OPTION_o,
9833 TCC_OPTION_r,
9834 TCC_OPTION_W,
9835 TCC_OPTION_O,
9836 TCC_OPTION_m,
9837 TCC_OPTION_f,
9838 TCC_OPTION_nostdinc,
9839 TCC_OPTION_nostdlib,
9840 TCC_OPTION_print_search_dirs,
9841 TCC_OPTION_rdynamic,
9842 TCC_OPTION_run,
9843 TCC_OPTION_v,
9844 TCC_OPTION_w,
9847 static const TCCOption tcc_options[] = {
9848 { "h", TCC_OPTION_HELP, 0 },
9849 { "?", TCC_OPTION_HELP, 0 },
9850 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9851 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9852 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9853 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9854 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9855 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9856 { "bench", TCC_OPTION_bench, 0 },
9857 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9858 #ifdef CONFIG_TCC_BCHECK
9859 { "b", TCC_OPTION_b, 0 },
9860 #endif
9861 { "g", TCC_OPTION_g, 0 },
9862 { "c", TCC_OPTION_c, 0 },
9863 { "static", TCC_OPTION_static, 0 },
9864 { "shared", TCC_OPTION_shared, 0 },
9865 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9866 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9867 { "rdynamic", TCC_OPTION_rdynamic, 0 },
9868 { "r", TCC_OPTION_r, 0 },
9869 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9870 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9871 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9872 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9873 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9874 { "nostdlib", TCC_OPTION_nostdlib, 0 },
9875 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9876 { "v", TCC_OPTION_v, 0 },
9877 { "w", TCC_OPTION_w, 0 },
9878 { NULL },
9881 /* convert 'str' into an array of space separated strings */
9882 static int expand_args(char ***pargv, const char *str)
9884 const char *s1;
9885 char **argv, *arg;
9886 int argc, len;
9888 argc = 0;
9889 argv = NULL;
9890 for(;;) {
9891 while (is_space(*str))
9892 str++;
9893 if (*str == '\0')
9894 break;
9895 s1 = str;
9896 while (*str != '\0' && !is_space(*str))
9897 str++;
9898 len = str - s1;
9899 arg = tcc_malloc(len + 1);
9900 memcpy(arg, s1, len);
9901 arg[len] = '\0';
9902 dynarray_add((void ***)&argv, &argc, arg);
9904 *pargv = argv;
9905 return argc;
9908 static char **files;
9909 static int nb_files, nb_libraries;
9910 static int multiple_files;
9911 static int print_search_dirs;
9912 static int output_type;
9913 static int reloc_output;
9914 static const char *outfile;
9916 int parse_args(TCCState *s, int argc, char **argv)
9918 int optind;
9919 const TCCOption *popt;
9920 const char *optarg, *p1, *r1;
9921 char *r;
9923 optind = 0;
9924 while (1) {
9925 if (optind >= argc) {
9926 if (nb_files == 0 && !print_search_dirs)
9927 goto show_help;
9928 else
9929 break;
9931 r = argv[optind++];
9932 if (r[0] != '-') {
9933 /* add a new file */
9934 dynarray_add((void ***)&files, &nb_files, r);
9935 if (!multiple_files) {
9936 optind--;
9937 /* argv[0] will be this file */
9938 break;
9940 } else {
9941 /* find option in table (match only the first chars */
9942 popt = tcc_options;
9943 for(;;) {
9944 p1 = popt->name;
9945 if (p1 == NULL)
9946 error("invalid option -- '%s'", r);
9947 r1 = r + 1;
9948 for(;;) {
9949 if (*p1 == '\0')
9950 goto option_found;
9951 if (*r1 != *p1)
9952 break;
9953 p1++;
9954 r1++;
9956 popt++;
9958 option_found:
9959 if (popt->flags & TCC_OPTION_HAS_ARG) {
9960 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
9961 optarg = r1;
9962 } else {
9963 if (optind >= argc)
9964 error("argument to '%s' is missing", r);
9965 optarg = argv[optind++];
9967 } else {
9968 if (*r1 != '\0')
9969 goto show_help;
9970 optarg = NULL;
9973 switch(popt->index) {
9974 case TCC_OPTION_HELP:
9975 show_help:
9976 help();
9977 exit(1);
9978 case TCC_OPTION_I:
9979 if (tcc_add_include_path(s, optarg) < 0)
9980 error("too many include paths");
9981 break;
9982 case TCC_OPTION_D:
9984 char *sym, *value;
9985 sym = (char *)optarg;
9986 value = strchr(sym, '=');
9987 if (value) {
9988 *value = '\0';
9989 value++;
9991 tcc_define_symbol(s, sym, value);
9993 break;
9994 case TCC_OPTION_U:
9995 tcc_undefine_symbol(s, optarg);
9996 break;
9997 case TCC_OPTION_L:
9998 tcc_add_library_path(s, optarg);
9999 break;
10000 case TCC_OPTION_B:
10001 /* set tcc utilities path (mainly for tcc development) */
10002 tcc_lib_path = optarg;
10003 break;
10004 case TCC_OPTION_l:
10005 dynarray_add((void ***)&files, &nb_files, r);
10006 nb_libraries++;
10007 break;
10008 case TCC_OPTION_bench:
10009 do_bench = 1;
10010 break;
10011 case TCC_OPTION_bt:
10012 num_callers = atoi(optarg);
10013 break;
10014 #ifdef CONFIG_TCC_BCHECK
10015 case TCC_OPTION_b:
10016 do_bounds_check = 1;
10017 do_debug = 1;
10018 break;
10019 #endif
10020 case TCC_OPTION_g:
10021 do_debug = 1;
10022 break;
10023 case TCC_OPTION_c:
10024 multiple_files = 1;
10025 output_type = TCC_OUTPUT_OBJ;
10026 break;
10027 case TCC_OPTION_static:
10028 s->static_link = 1;
10029 break;
10030 case TCC_OPTION_shared:
10031 output_type = TCC_OUTPUT_DLL;
10032 break;
10033 case TCC_OPTION_o:
10034 multiple_files = 1;
10035 outfile = optarg;
10036 break;
10037 case TCC_OPTION_r:
10038 /* generate a .o merging several output files */
10039 reloc_output = 1;
10040 output_type = TCC_OUTPUT_OBJ;
10041 break;
10042 case TCC_OPTION_nostdinc:
10043 s->nostdinc = 1;
10044 break;
10045 case TCC_OPTION_nostdlib:
10046 s->nostdlib = 1;
10047 break;
10048 case TCC_OPTION_print_search_dirs:
10049 print_search_dirs = 1;
10050 break;
10051 case TCC_OPTION_run:
10053 int argc1;
10054 char **argv1;
10055 argc1 = expand_args(&argv1, optarg);
10056 if (argc1 > 0) {
10057 parse_args(s, argc1, argv1);
10059 multiple_files = 0;
10060 output_type = TCC_OUTPUT_MEMORY;
10062 break;
10063 case TCC_OPTION_v:
10064 printf("tcc version %s\n", TCC_VERSION);
10065 exit(0);
10066 case TCC_OPTION_f:
10067 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10068 goto unsupported_option;
10069 break;
10070 case TCC_OPTION_W:
10071 if (tcc_set_warning(s, optarg, 1) < 0 &&
10072 s->warn_unsupported)
10073 goto unsupported_option;
10074 break;
10075 case TCC_OPTION_w:
10076 s->warn_none = 1;
10077 break;
10078 case TCC_OPTION_rdynamic:
10079 s->rdynamic = 1;
10080 break;
10081 default:
10082 if (s->warn_unsupported) {
10083 unsupported_option:
10084 warning("unsupported option '%s'", r);
10086 break;
10090 return optind;
10093 int main(int argc, char **argv)
10095 int i;
10096 TCCState *s;
10097 int nb_objfiles, ret, optind;
10098 char objfilename[1024];
10099 int64_t start_time = 0;
10101 s = tcc_new();
10102 output_type = TCC_OUTPUT_EXE;
10103 outfile = NULL;
10104 multiple_files = 1;
10105 files = NULL;
10106 nb_files = 0;
10107 nb_libraries = 0;
10108 reloc_output = 0;
10109 print_search_dirs = 0;
10111 optind = parse_args(s, argc - 1, argv + 1) + 1;
10113 if (print_search_dirs) {
10114 /* enough for Linux kernel */
10115 printf("install: %s/\n", tcc_lib_path);
10116 return 0;
10119 nb_objfiles = nb_files - nb_libraries;
10121 /* if outfile provided without other options, we output an
10122 executable */
10123 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10124 output_type = TCC_OUTPUT_EXE;
10126 /* check -c consistency : only single file handled. XXX: checks file type */
10127 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10128 /* accepts only a single input file */
10129 if (nb_objfiles != 1)
10130 error("cannot specify multiple files with -c");
10131 if (nb_libraries != 0)
10132 error("cannot specify libraries with -c");
10135 /* compute default outfile name */
10136 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
10137 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10138 char *ext;
10139 /* strip path */
10140 pstrcpy(objfilename, sizeof(objfilename) - 1,
10141 tcc_basename(files[0]));
10142 /* add .o extension */
10143 ext = strrchr(objfilename, '.');
10144 if (!ext)
10145 goto default_outfile;
10146 strcpy(ext + 1, "o");
10147 } else {
10148 default_outfile:
10149 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10151 outfile = objfilename;
10154 if (do_bench) {
10155 start_time = getclock_us();
10158 tcc_set_output_type(s, output_type);
10160 /* compile or add each files or library */
10161 for(i = 0;i < nb_files; i++) {
10162 const char *filename;
10164 filename = files[i];
10165 if (filename[0] == '-') {
10166 if (tcc_add_library(s, filename + 2) < 0)
10167 error("cannot find %s", filename);
10168 } else {
10169 if (tcc_add_file(s, filename) < 0) {
10170 ret = 1;
10171 goto the_end;
10176 /* free all files */
10177 tcc_free(files);
10179 if (do_bench) {
10180 double total_time;
10181 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10182 if (total_time < 0.001)
10183 total_time = 0.001;
10184 if (total_bytes < 1)
10185 total_bytes = 1;
10186 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10187 tok_ident - TOK_IDENT, total_lines, total_bytes,
10188 total_time, (int)(total_lines / total_time),
10189 total_bytes / total_time / 1000000.0);
10192 if (s->output_type != TCC_OUTPUT_MEMORY) {
10193 tcc_output_file(s, outfile);
10194 ret = 0;
10195 } else {
10196 ret = tcc_run(s, argc - optind, argv + optind);
10198 the_end:
10199 /* XXX: cannot do it with bound checking because of the malloc hooks */
10200 if (!do_bounds_check)
10201 tcc_delete(s);
10203 #ifdef MEM_DEBUG
10204 if (do_bench) {
10205 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10207 #endif
10208 return ret;
10211 #endif