fixed 'no base' modrm generation - better asm constraints handling
[tinycc.git] / tcc.c
blob563dc73dc6c19b0fdc64d305f4a9159f09b03de8
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define _GNU_SOURCE
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <math.h>
29 #include <unistd.h>
30 #include <signal.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <setjmp.h>
34 #include <time.h>
35 #ifdef WIN32
36 #include <sys/timeb.h>
37 #define CONFIG_TCC_STATIC
38 #endif
39 #ifndef WIN32
40 #include <sys/time.h>
41 #include <sys/ucontext.h>
42 #endif
43 #include "elf.h"
44 #include "stab.h"
45 #ifndef CONFIG_TCC_STATIC
46 #include <dlfcn.h>
47 #endif
49 #include "libtcc.h"
51 /* parser debug */
52 //#define PARSE_DEBUG
53 /* preprocessor debug */
54 //#define PP_DEBUG
55 /* include file debug */
56 //#define INC_DEBUG
58 //#define MEM_DEBUG
60 /* assembler debug */
61 //#define ASM_DEBUG
63 /* target selection */
64 //#define TCC_TARGET_I386 /* i386 code generator */
65 //#define TCC_TARGET_ARM /* ARMv4 code generator */
66 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
68 /* default target is I386 */
69 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
70 !defined(TCC_TARGET_C67)
71 #define TCC_TARGET_I386
72 #endif
74 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
75 !defined(TCC_TARGET_C67)
76 #define CONFIG_TCC_BCHECK /* enable bound checking code */
77 #endif
79 /* define it to include assembler support */
80 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
81 #define CONFIG_TCC_ASM
82 #endif
84 /* object format selection */
85 #if defined(TCC_TARGET_C67)
86 #define TCC_TARGET_COFF
87 #endif
89 #define FALSE 0
90 #define false 0
91 #define TRUE 1
92 #define true 1
93 typedef int BOOL;
95 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
96 executables or dlls */
97 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
99 #define INCLUDE_STACK_SIZE 32
100 #define IFDEF_STACK_SIZE 64
101 #define VSTACK_SIZE 64
102 #define STRING_MAX_SIZE 1024
104 #define TOK_HASH_SIZE 2048 /* must be a power of two */
105 #define TOK_ALLOC_INCR 512 /* must be a power of two */
106 #define TOK_STR_ALLOC_INCR_BITS 6
107 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
108 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
110 /* token symbol management */
111 typedef struct TokenSym {
112 struct TokenSym *hash_next;
113 struct Sym *sym_define; /* direct pointer to define */
114 struct Sym *sym_label; /* direct pointer to label */
115 struct Sym *sym_struct; /* direct pointer to structure */
116 struct Sym *sym_identifier; /* direct pointer to identifier */
117 int tok; /* token number */
118 int len;
119 char str[1];
120 } TokenSym;
122 typedef struct CString {
123 int size; /* size in bytes */
124 void *data; /* either 'char *' or 'int *' */
125 int size_allocated;
126 void *data_allocated; /* if non NULL, data has been malloced */
127 } CString;
129 /* type definition */
130 typedef struct CType {
131 int t;
132 struct Sym *ref;
133 } CType;
135 /* constant value */
136 typedef union CValue {
137 long double ld;
138 double d;
139 float f;
140 int i;
141 unsigned int ui;
142 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
143 long long ll;
144 unsigned long long ull;
145 struct CString *cstr;
146 void *ptr;
147 int tab[1];
148 } CValue;
150 /* value on stack */
151 typedef struct SValue {
152 CType type; /* type */
153 unsigned short r; /* register + flags */
154 unsigned short r2; /* second register, used for 'long long'
155 type. If not used, set to VT_CONST */
156 CValue c; /* constant, if VT_CONST */
157 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
158 } SValue;
160 /* symbol management */
161 typedef struct Sym {
162 int v; /* symbol token */
163 int r; /* associated register */
164 int c; /* associated number */
165 CType type; /* associated type */
166 struct Sym *next; /* next related symbol */
167 struct Sym *prev; /* prev symbol in stack */
168 struct Sym *prev_tok; /* previous symbol for this token */
169 } Sym;
171 /* section definition */
172 /* XXX: use directly ELF structure for parameters ? */
173 /* special flag to indicate that the section should not be linked to
174 the other ones */
175 #define SHF_PRIVATE 0x80000000
177 typedef struct Section {
178 unsigned long data_offset; /* current data offset */
179 unsigned char *data; /* section data */
180 unsigned long data_allocated; /* used for realloc() handling */
181 int sh_name; /* elf section name (only used during output) */
182 int sh_num; /* elf section number */
183 int sh_type; /* elf section type */
184 int sh_flags; /* elf section flags */
185 int sh_info; /* elf section info */
186 int sh_addralign; /* elf section alignment */
187 int sh_entsize; /* elf entry size */
188 unsigned long sh_size; /* section size (only used during output) */
189 unsigned long sh_addr; /* address at which the section is relocated */
190 unsigned long sh_offset; /* address at which the section is relocated */
191 int nb_hashed_syms; /* used to resize the hash table */
192 struct Section *link; /* link to another section */
193 struct Section *reloc; /* corresponding section for relocation, if any */
194 struct Section *hash; /* hash table for symbols */
195 struct Section *next;
196 char name[1]; /* section name */
197 } Section;
199 typedef struct DLLReference {
200 int level;
201 char name[1];
202 } DLLReference;
204 /* GNUC attribute definition */
205 typedef struct AttributeDef {
206 int aligned;
207 Section *section;
208 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
209 } AttributeDef;
211 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
212 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
213 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
215 /* stored in 'Sym.c' field */
216 #define FUNC_NEW 1 /* ansi function prototype */
217 #define FUNC_OLD 2 /* old function prototype */
218 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
220 /* stored in 'Sym.r' field */
221 #define FUNC_CDECL 0 /* standard c call */
222 #define FUNC_STDCALL 1 /* pascal c call */
224 /* field 'Sym.t' for macros */
225 #define MACRO_OBJ 0 /* object like macro */
226 #define MACRO_FUNC 1 /* function like macro */
228 /* field 'Sym.r' for C labels */
229 #define LABEL_DEFINED 0 /* label is defined */
230 #define LABEL_FORWARD 1 /* label is forward defined */
231 #define LABEL_DECLARED 2 /* label is declared but never used */
233 /* type_decl() types */
234 #define TYPE_ABSTRACT 1 /* type without variable */
235 #define TYPE_DIRECT 2 /* type with variable */
237 #define IO_BUF_SIZE 8192
239 typedef struct BufferedFile {
240 uint8_t *buf_ptr;
241 uint8_t *buf_end;
242 int fd;
243 int line_num; /* current line number - here to simplify code */
244 int ifndef_macro; /* #ifndef macro / #endif search */
245 int ifndef_macro_saved; /* saved ifndef_macro */
246 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
247 char inc_type; /* type of include */
248 char inc_filename[512]; /* filename specified by the user */
249 char filename[1024]; /* current filename - here to simplify code */
250 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
251 } BufferedFile;
253 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
254 #define CH_EOF (-1) /* end of file */
256 /* parsing state (used to save parser state to reparse part of the
257 source several times) */
258 typedef struct ParseState {
259 int *macro_ptr;
260 int line_num;
261 int tok;
262 CValue tokc;
263 } ParseState;
265 /* used to record tokens */
266 typedef struct TokenString {
267 int *str;
268 int len;
269 int allocated_len;
270 int last_line_num;
271 } TokenString;
273 /* include file cache, used to find files faster and also to eliminate
274 inclusion if the include file is protected by #ifndef ... #endif */
275 typedef struct CachedInclude {
276 int ifndef_macro;
277 char type; /* '"' or '>' to give include type */
278 char filename[1]; /* path specified in #include */
279 } CachedInclude;
281 /* parser */
282 static struct BufferedFile *file;
283 static int ch, tok;
284 static CValue tokc;
285 static CString tokcstr; /* current parsed string, if any */
286 /* additional informations about token */
287 static int tok_flags;
288 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
289 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
290 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
292 static int *macro_ptr, *macro_ptr_allocated;
293 static int *unget_saved_macro_ptr;
294 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
295 static int unget_buffer_enabled;
296 static int parse_flags;
297 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
298 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
299 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
300 token. line feed is also
301 returned at eof */
303 static Section *text_section, *data_section, *bss_section; /* predefined sections */
304 static Section *cur_text_section; /* current section where function code is
305 generated */
306 /* bound check related sections */
307 static Section *bounds_section; /* contains global data bound description */
308 static Section *lbounds_section; /* contains local data bound description */
309 /* symbol sections */
310 static Section *symtab_section, *strtab_section;
312 /* debug sections */
313 static Section *stab_section, *stabstr_section;
315 /* loc : local variable index
316 ind : output code index
317 rsym: return symbol
318 anon_sym: anonymous symbol index
320 static int rsym, anon_sym, ind, loc;
321 /* expression generation modifiers */
322 static int const_wanted; /* true if constant wanted */
323 static int nocode_wanted; /* true if no code generation wanted for an expression */
324 static int global_expr; /* true if compound literals must be allocated
325 globally (used during initializers parsing */
326 static CType func_vt; /* current function return type (used by return
327 instruction) */
328 static int func_vc;
329 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
330 static int tok_ident;
331 static TokenSym **table_ident;
332 static TokenSym *hash_ident[TOK_HASH_SIZE];
333 static char token_buf[STRING_MAX_SIZE + 1];
334 static char *funcname;
335 static Sym *global_stack, *local_stack;
336 static Sym *define_stack;
337 static Sym *global_label_stack, *local_label_stack;
339 static SValue vstack[VSTACK_SIZE], *vtop;
340 /* some predefined types */
341 static CType char_pointer_type, func_old_type, int_type;
342 /* true if isid(c) || isnum(c) */
343 static unsigned char isidnum_table[256];
345 /* compile with debug symbol (and use them if error during execution) */
346 static int do_debug = 0;
348 /* compile with built-in memory and bounds checker */
349 static int do_bounds_check = 0;
351 /* display benchmark infos */
352 #if !defined(LIBTCC)
353 static int do_bench = 0;
354 #endif
355 static int total_lines;
356 static int total_bytes;
358 /* use GNU C extensions */
359 static int gnu_ext = 1;
361 /* use Tiny C extensions */
362 static int tcc_ext = 1;
364 /* max number of callers shown if error */
365 static int num_callers = 6;
366 static const char **rt_bound_error_msg;
368 /* XXX: get rid of this ASAP */
369 static struct TCCState *tcc_state;
371 /* give the path of the tcc libraries */
372 static const char *tcc_lib_path = CONFIG_TCC_LIBDIR "/tcc";
374 struct TCCState {
375 int output_type;
377 BufferedFile **include_stack_ptr;
378 int *ifdef_stack_ptr;
380 /* include file handling */
381 char **include_paths;
382 int nb_include_paths;
383 char **sysinclude_paths;
384 int nb_sysinclude_paths;
385 CachedInclude **cached_includes;
386 int nb_cached_includes;
388 char **library_paths;
389 int nb_library_paths;
391 /* array of all loaded dlls (including those referenced by loaded
392 dlls) */
393 DLLReference **loaded_dlls;
394 int nb_loaded_dlls;
396 /* sections */
397 Section **sections;
398 int nb_sections; /* number of sections, including first dummy section */
400 /* got handling */
401 Section *got;
402 Section *plt;
403 unsigned long *got_offsets;
404 int nb_got_offsets;
405 /* give the correspondance from symtab indexes to dynsym indexes */
406 int *symtab_to_dynsym;
408 /* temporary dynamic symbol sections (for dll loading) */
409 Section *dynsymtab_section;
410 /* exported dynamic symbol section */
411 Section *dynsym;
413 int nostdinc; /* if true, no standard headers are added */
414 int nostdlib; /* if true, no standard libraries are added */
416 /* if true, static linking is performed */
417 int static_link;
419 /* if true, all symbols are exported */
420 int rdynamic;
422 /* if true, only link in referenced objects from archive */
423 int alacarte_link;
425 /* C language options */
426 int char_is_unsigned;
428 /* warning switches */
429 int warn_write_strings;
430 int warn_unsupported;
431 int warn_error;
432 int warn_none;
433 int warn_implicit_function_declaration;
435 /* error handling */
436 void *error_opaque;
437 void (*error_func)(void *opaque, const char *msg);
438 int error_set_jmp_enabled;
439 jmp_buf error_jmp_buf;
440 int nb_errors;
442 /* tiny assembler state */
443 Sym *asm_labels;
445 /* see include_stack_ptr */
446 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
448 /* see ifdef_stack_ptr */
449 int ifdef_stack[IFDEF_STACK_SIZE];
452 /* The current value can be: */
453 #define VT_VALMASK 0x00ff
454 #define VT_CONST 0x00f0 /* constant in vc
455 (must be first non register value) */
456 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
457 #define VT_LOCAL 0x00f2 /* offset on stack */
458 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
459 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
460 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
461 #define VT_LVAL 0x0100 /* var is an lvalue */
462 #define VT_SYM 0x0200 /* a symbol value is added */
463 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
464 char/short stored in integer registers) */
465 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
466 dereferencing value */
467 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
468 bounding function call point is in vc */
469 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
470 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
471 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
472 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
474 /* types */
475 #define VT_INT 0 /* integer type */
476 #define VT_BYTE 1 /* signed byte type */
477 #define VT_SHORT 2 /* short type */
478 #define VT_VOID 3 /* void type */
479 #define VT_PTR 4 /* pointer */
480 #define VT_ENUM 5 /* enum definition */
481 #define VT_FUNC 6 /* function type */
482 #define VT_STRUCT 7 /* struct/union definition */
483 #define VT_FLOAT 8 /* IEEE float */
484 #define VT_DOUBLE 9 /* IEEE double */
485 #define VT_LDOUBLE 10 /* IEEE long double */
486 #define VT_BOOL 11 /* ISOC99 boolean type */
487 #define VT_LLONG 12 /* 64 bit integer */
488 #define VT_LONG 13 /* long integer (NEVER USED as type, only
489 during parsing) */
490 #define VT_BTYPE 0x000f /* mask for basic type */
491 #define VT_UNSIGNED 0x0010 /* unsigned type */
492 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
493 #define VT_BITFIELD 0x0040 /* bitfield modifier */
494 #define VT_CONSTANT 0x0800 /* const modifier */
495 #define VT_VOLATILE 0x1000 /* volatile modifier */
496 #define VT_SIGNED 0x2000 /* signed type */
498 /* storage */
499 #define VT_EXTERN 0x00000080 /* extern definition */
500 #define VT_STATIC 0x00000100 /* static variable */
501 #define VT_TYPEDEF 0x00000200 /* typedef definition */
502 #define VT_INLINE 0x00000400 /* inline definition */
504 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
506 /* type mask (except storage) */
507 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
508 #define VT_TYPE (~(VT_STORAGE))
510 /* token values */
512 /* warning: the following compare tokens depend on i386 asm code */
513 #define TOK_ULT 0x92
514 #define TOK_UGE 0x93
515 #define TOK_EQ 0x94
516 #define TOK_NE 0x95
517 #define TOK_ULE 0x96
518 #define TOK_UGT 0x97
519 #define TOK_LT 0x9c
520 #define TOK_GE 0x9d
521 #define TOK_LE 0x9e
522 #define TOK_GT 0x9f
524 #define TOK_LAND 0xa0
525 #define TOK_LOR 0xa1
527 #define TOK_DEC 0xa2
528 #define TOK_MID 0xa3 /* inc/dec, to void constant */
529 #define TOK_INC 0xa4
530 #define TOK_UDIV 0xb0 /* unsigned division */
531 #define TOK_UMOD 0xb1 /* unsigned modulo */
532 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
533 #define TOK_CINT 0xb3 /* number in tokc */
534 #define TOK_CCHAR 0xb4 /* char constant in tokc */
535 #define TOK_STR 0xb5 /* pointer to string in tokc */
536 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
537 #define TOK_LCHAR 0xb7
538 #define TOK_LSTR 0xb8
539 #define TOK_CFLOAT 0xb9 /* float constant */
540 #define TOK_LINENUM 0xba /* line number info */
541 #define TOK_CDOUBLE 0xc0 /* double constant */
542 #define TOK_CLDOUBLE 0xc1 /* long double constant */
543 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
544 #define TOK_ADDC1 0xc3 /* add with carry generation */
545 #define TOK_ADDC2 0xc4 /* add with carry use */
546 #define TOK_SUBC1 0xc5 /* add with carry generation */
547 #define TOK_SUBC2 0xc6 /* add with carry use */
548 #define TOK_CUINT 0xc8 /* unsigned int constant */
549 #define TOK_CLLONG 0xc9 /* long long constant */
550 #define TOK_CULLONG 0xca /* unsigned long long constant */
551 #define TOK_ARROW 0xcb
552 #define TOK_DOTS 0xcc /* three dots */
553 #define TOK_SHR 0xcd /* unsigned shift right */
554 #define TOK_PPNUM 0xce /* preprocessor number */
556 #define TOK_SHL 0x01 /* shift left */
557 #define TOK_SAR 0x02 /* signed shift right */
559 /* assignement operators : normal operator or 0x80 */
560 #define TOK_A_MOD 0xa5
561 #define TOK_A_AND 0xa6
562 #define TOK_A_MUL 0xaa
563 #define TOK_A_ADD 0xab
564 #define TOK_A_SUB 0xad
565 #define TOK_A_DIV 0xaf
566 #define TOK_A_XOR 0xde
567 #define TOK_A_OR 0xfc
568 #define TOK_A_SHL 0x81
569 #define TOK_A_SAR 0x82
571 #ifndef offsetof
572 #define offsetof(type, field) ((size_t) &((type *)0)->field)
573 #endif
575 #ifndef countof
576 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
577 #endif
579 /* WARNING: the content of this string encodes token numbers */
580 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";
582 #define TOK_EOF (-1) /* end of file */
583 #define TOK_LINEFEED 10 /* line feed */
585 /* all identificators and strings have token above that */
586 #define TOK_IDENT 256
588 /* only used for i386 asm opcodes definitions */
589 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
591 #define DEF_BWL(x) \
592 DEF(TOK_ASM_ ## x ## b, #x "b") \
593 DEF(TOK_ASM_ ## x ## w, #x "w") \
594 DEF(TOK_ASM_ ## x ## l, #x "l") \
595 DEF(TOK_ASM_ ## x, #x)
597 #define DEF_WL(x) \
598 DEF(TOK_ASM_ ## x ## w, #x "w") \
599 DEF(TOK_ASM_ ## x ## l, #x "l") \
600 DEF(TOK_ASM_ ## x, #x)
602 #define DEF_FP1(x) \
603 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
604 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
605 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
606 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
608 #define DEF_FP(x) \
609 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
610 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
611 DEF_FP1(x)
613 #define DEF_ASMTEST(x) \
614 DEF_ASM(x ## o) \
615 DEF_ASM(x ## no) \
616 DEF_ASM(x ## b) \
617 DEF_ASM(x ## c) \
618 DEF_ASM(x ## nae) \
619 DEF_ASM(x ## nb) \
620 DEF_ASM(x ## nc) \
621 DEF_ASM(x ## ae) \
622 DEF_ASM(x ## e) \
623 DEF_ASM(x ## z) \
624 DEF_ASM(x ## ne) \
625 DEF_ASM(x ## nz) \
626 DEF_ASM(x ## be) \
627 DEF_ASM(x ## na) \
628 DEF_ASM(x ## nbe) \
629 DEF_ASM(x ## a) \
630 DEF_ASM(x ## s) \
631 DEF_ASM(x ## ns) \
632 DEF_ASM(x ## p) \
633 DEF_ASM(x ## pe) \
634 DEF_ASM(x ## np) \
635 DEF_ASM(x ## po) \
636 DEF_ASM(x ## l) \
637 DEF_ASM(x ## nge) \
638 DEF_ASM(x ## nl) \
639 DEF_ASM(x ## ge) \
640 DEF_ASM(x ## le) \
641 DEF_ASM(x ## ng) \
642 DEF_ASM(x ## nle) \
643 DEF_ASM(x ## g)
645 #define TOK_ASM_int TOK_INT
647 enum tcc_token {
648 TOK_LAST = TOK_IDENT - 1,
649 #define DEF(id, str) id,
650 #include "tcctok.h"
651 #undef DEF
654 static const char tcc_keywords[] =
655 #define DEF(id, str) str "\0"
656 #include "tcctok.h"
657 #undef DEF
660 #define TOK_UIDENT TOK_DEFINE
662 #ifdef WIN32
663 #define snprintf _snprintf
664 #define vsnprintf _vsnprintf
665 #endif
667 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
668 /* currently incorrect */
669 long double strtold(const char *nptr, char **endptr)
671 return (long double)strtod(nptr, endptr);
673 float strtof(const char *nptr, char **endptr)
675 return (float)strtod(nptr, endptr);
677 #else
678 /* XXX: need to define this to use them in non ISOC99 context */
679 extern float strtof (const char *__nptr, char **__endptr);
680 extern long double strtold (const char *__nptr, char **__endptr);
681 #endif
683 static char *pstrcpy(char *buf, int buf_size, const char *s);
684 static char *pstrcat(char *buf, int buf_size, const char *s);
686 static void next(void);
687 static void next_nomacro(void);
688 static void parse_expr_type(CType *type);
689 static void expr_type(CType *type);
690 static void unary_type(CType *type);
691 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
692 int case_reg, int is_expr);
693 static int expr_const(void);
694 static void expr_eq(void);
695 static void gexpr(void);
696 static void decl(int l);
697 static void decl_initializer(CType *type, Section *sec, unsigned long c,
698 int first, int size_only);
699 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
700 int has_init, int v, int scope);
701 int gv(int rc);
702 void gv2(int rc1, int rc2);
703 void move_reg(int r, int s);
704 void save_regs(int n);
705 void save_reg(int r);
706 void vpop(void);
707 void vswap(void);
708 void vdup(void);
709 int get_reg(int rc);
710 int get_reg_ex(int rc,int rc2);
712 static void macro_subst(TokenString *tok_str, Sym **nested_list,
713 const int *macro_str, int can_read_stream);
714 int save_reg_forced(int r);
715 void gen_op(int op);
716 void force_charshort_cast(int t);
717 static void gen_cast(CType *type);
718 void vstore(void);
719 static Sym *sym_find(int v);
720 static Sym *sym_push(int v, CType *type, int r, int c);
722 /* type handling */
723 static int type_size(CType *type, int *a);
724 static inline CType *pointed_type(CType *type);
725 static int pointed_size(CType *type);
726 static int lvalue_type(int t);
727 static int parse_btype(CType *type, AttributeDef *ad);
728 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
729 static int is_compatible_types(CType *type1, CType *type2);
731 int ieee_finite(double d);
732 void error(const char *fmt, ...);
733 void vpushi(int v);
734 void vrott(int n);
735 void vnrott(int n);
736 void lexpand_nr(void);
737 static void vpush_global_sym(CType *type, int v);
738 void vset(CType *type, int r, int v);
739 void type_to_str(char *buf, int buf_size,
740 CType *type, const char *varstr);
741 char *get_tok_str(int v, CValue *cv);
742 static Sym *get_sym_ref(CType *type, Section *sec,
743 unsigned long offset, unsigned long size);
744 static Sym *external_global_sym(int v, CType *type, int r);
746 /* section generation */
747 static void section_realloc(Section *sec, unsigned long new_size);
748 static void *section_ptr_add(Section *sec, unsigned long size);
749 static void put_extern_sym(Sym *sym, Section *section,
750 unsigned long value, unsigned long size);
751 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
752 static int put_elf_str(Section *s, const char *sym);
753 static int put_elf_sym(Section *s,
754 unsigned long value, unsigned long size,
755 int info, int other, int shndx, const char *name);
756 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
757 int info, int sh_num, const char *name);
758 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
759 int type, int symbol);
760 static void put_stabs(const char *str, int type, int other, int desc,
761 unsigned long value);
762 static void put_stabs_r(const char *str, int type, int other, int desc,
763 unsigned long value, Section *sec, int sym_index);
764 static void put_stabn(int type, int other, int desc, int value);
765 static void put_stabd(int type, int other, int desc);
766 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
768 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
769 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
770 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
772 /* tcccoff.c */
773 int tcc_output_coff(TCCState *s1, const char *OutFile);
775 /* tccasm.c */
777 #ifdef CONFIG_TCC_ASM
779 typedef struct ExprValue {
780 uint32_t v;
781 Sym *sym;
782 } ExprValue;
784 #define MAX_ASM_OPERANDS 30
786 typedef struct ASMOperand {
787 int id; /* GCC 3 optionnal identifier (0 if number only supported */
788 char *constraint;
789 char asm_str[16]; /* computed asm string for operand */
790 SValue *vt; /* C value of the expression */
791 int ref_index; /* if >= 0, gives reference to a output constraint */
792 int priority; /* priority, used to assign registers */
793 int reg; /* if >= 0, register number used for this operand */
794 int is_llong; /* true if double register value */
795 } ASMOperand;
797 static void asm_expr(TCCState *s1, ExprValue *pe);
798 static int asm_int_expr(TCCState *s1);
799 static int find_constraint(ASMOperand *operands, int nb_operands,
800 const char *name, const char **pp);
802 static int tcc_assemble(TCCState *s1, int do_preprocess);
804 #endif
806 static void asm_instr(void);
808 /* true if float/double/long double type */
809 static inline int is_float(int t)
811 int bt;
812 bt = t & VT_BTYPE;
813 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
816 #ifdef TCC_TARGET_I386
817 #include "i386-gen.c"
818 #endif
820 #ifdef TCC_TARGET_ARM
821 #include "arm-gen.c"
822 #endif
824 #ifdef TCC_TARGET_C67
825 #include "c67-gen.c"
826 #endif
828 #ifdef CONFIG_TCC_STATIC
830 #define RTLD_LAZY 0x001
831 #define RTLD_NOW 0x002
832 #define RTLD_GLOBAL 0x100
833 #define RTLD_DEFAULT NULL
835 /* dummy function for profiling */
836 void *dlopen(const char *filename, int flag)
838 return NULL;
841 const char *dlerror(void)
843 return "error";
846 typedef struct TCCSyms {
847 char *str;
848 void *ptr;
849 } TCCSyms;
851 #define TCCSYM(a) { #a, &a, },
853 /* add the symbol you want here if no dynamic linking is done */
854 static TCCSyms tcc_syms[] = {
855 TCCSYM(printf)
856 TCCSYM(fprintf)
857 TCCSYM(fopen)
858 TCCSYM(fclose)
859 { NULL, NULL },
862 void *dlsym(void *handle, const char *symbol)
864 TCCSyms *p;
865 p = tcc_syms;
866 while (p->str != NULL) {
867 if (!strcmp(p->str, symbol))
868 return p->ptr;
869 p++;
871 return NULL;
874 #endif
876 /********************************************************/
878 /* we use our own 'finite' function to avoid potential problems with
879 non standard math libs */
880 /* XXX: endianness dependent */
881 int ieee_finite(double d)
883 int *p = (int *)&d;
884 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
887 /* copy a string and truncate it. */
888 static char *pstrcpy(char *buf, int buf_size, const char *s)
890 char *q, *q_end;
891 int c;
893 if (buf_size > 0) {
894 q = buf;
895 q_end = buf + buf_size - 1;
896 while (q < q_end) {
897 c = *s++;
898 if (c == '\0')
899 break;
900 *q++ = c;
902 *q = '\0';
904 return buf;
907 /* strcat and truncate. */
908 static char *pstrcat(char *buf, int buf_size, const char *s)
910 int len;
911 len = strlen(buf);
912 if (len < buf_size)
913 pstrcpy(buf + len, buf_size - len, s);
914 return buf;
917 /* memory management */
918 #ifdef MEM_DEBUG
919 int mem_cur_size;
920 int mem_max_size;
921 #endif
923 static inline void tcc_free(void *ptr)
925 #ifdef MEM_DEBUG
926 mem_cur_size -= malloc_usable_size(ptr);
927 #endif
928 free(ptr);
931 static void *tcc_malloc(unsigned long size)
933 void *ptr;
934 ptr = malloc(size);
935 if (!ptr && size)
936 error("memory full");
937 #ifdef MEM_DEBUG
938 mem_cur_size += malloc_usable_size(ptr);
939 if (mem_cur_size > mem_max_size)
940 mem_max_size = mem_cur_size;
941 #endif
942 return ptr;
945 static void *tcc_mallocz(unsigned long size)
947 void *ptr;
948 ptr = tcc_malloc(size);
949 memset(ptr, 0, size);
950 return ptr;
953 static inline void *tcc_realloc(void *ptr, unsigned long size)
955 void *ptr1;
956 #ifdef MEM_DEBUG
957 mem_cur_size -= malloc_usable_size(ptr);
958 #endif
959 ptr1 = realloc(ptr, size);
960 #ifdef MEM_DEBUG
961 /* NOTE: count not correct if alloc error, but not critical */
962 mem_cur_size += malloc_usable_size(ptr1);
963 if (mem_cur_size > mem_max_size)
964 mem_max_size = mem_cur_size;
965 #endif
966 return ptr1;
969 static char *tcc_strdup(const char *str)
971 char *ptr;
972 ptr = tcc_malloc(strlen(str) + 1);
973 strcpy(ptr, str);
974 return ptr;
977 #define free(p) use_tcc_free(p)
978 #define malloc(s) use_tcc_malloc(s)
979 #define realloc(p, s) use_tcc_realloc(p, s)
981 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
983 int nb, nb_alloc;
984 void **pp;
986 nb = *nb_ptr;
987 pp = *ptab;
988 /* every power of two we double array size */
989 if ((nb & (nb - 1)) == 0) {
990 if (!nb)
991 nb_alloc = 1;
992 else
993 nb_alloc = nb * 2;
994 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
995 if (!pp)
996 error("memory full");
997 *ptab = pp;
999 pp[nb++] = data;
1000 *nb_ptr = nb;
1003 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1005 Section *sec;
1007 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1008 strcpy(sec->name, name);
1009 sec->sh_type = sh_type;
1010 sec->sh_flags = sh_flags;
1011 switch(sh_type) {
1012 case SHT_HASH:
1013 case SHT_REL:
1014 case SHT_DYNSYM:
1015 case SHT_SYMTAB:
1016 case SHT_DYNAMIC:
1017 sec->sh_addralign = 4;
1018 break;
1019 case SHT_STRTAB:
1020 sec->sh_addralign = 1;
1021 break;
1022 default:
1023 sec->sh_addralign = 32; /* default conservative alignment */
1024 break;
1027 /* only add section if not private */
1028 if (!(sh_flags & SHF_PRIVATE)) {
1029 sec->sh_num = s1->nb_sections;
1030 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1032 return sec;
1035 static void free_section(Section *s)
1037 tcc_free(s->data);
1038 tcc_free(s);
1041 /* realloc section and set its content to zero */
1042 static void section_realloc(Section *sec, unsigned long new_size)
1044 unsigned long size;
1045 unsigned char *data;
1047 size = sec->data_allocated;
1048 if (size == 0)
1049 size = 1;
1050 while (size < new_size)
1051 size = size * 2;
1052 data = tcc_realloc(sec->data, size);
1053 if (!data)
1054 error("memory full");
1055 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1056 sec->data = data;
1057 sec->data_allocated = size;
1060 /* reserve at least 'size' bytes in section 'sec' from
1061 sec->data_offset. */
1062 static void *section_ptr_add(Section *sec, unsigned long size)
1064 unsigned long offset, offset1;
1066 offset = sec->data_offset;
1067 offset1 = offset + size;
1068 if (offset1 > sec->data_allocated)
1069 section_realloc(sec, offset1);
1070 sec->data_offset = offset1;
1071 return sec->data + offset;
1074 /* return a reference to a section, and create it if it does not
1075 exists */
1076 Section *find_section(TCCState *s1, const char *name)
1078 Section *sec;
1079 int i;
1080 for(i = 1; i < s1->nb_sections; i++) {
1081 sec = s1->sections[i];
1082 if (!strcmp(name, sec->name))
1083 return sec;
1085 /* sections are created as PROGBITS */
1086 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1089 /* update sym->c so that it points to an external symbol in section
1090 'section' with value 'value' */
1091 static void put_extern_sym(Sym *sym, Section *section,
1092 unsigned long value, unsigned long size)
1094 int sym_type, sym_bind, sh_num, info;
1095 Elf32_Sym *esym;
1096 const char *name;
1098 if (section)
1099 sh_num = section->sh_num;
1100 else
1101 sh_num = SHN_UNDEF;
1102 if (!sym->c) {
1103 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1104 sym_type = STT_FUNC;
1105 else
1106 sym_type = STT_OBJECT;
1107 if (sym->type.t & VT_STATIC)
1108 sym_bind = STB_LOCAL;
1109 else
1110 sym_bind = STB_GLOBAL;
1112 name = get_tok_str(sym->v, NULL);
1113 #ifdef CONFIG_TCC_BCHECK
1114 if (do_bounds_check) {
1115 char buf[32];
1117 /* XXX: avoid doing that for statics ? */
1118 /* if bound checking is activated, we change some function
1119 names by adding the "__bound" prefix */
1120 switch(sym->v) {
1121 #if 0
1122 /* XXX: we rely only on malloc hooks */
1123 case TOK_malloc:
1124 case TOK_free:
1125 case TOK_realloc:
1126 case TOK_memalign:
1127 case TOK_calloc:
1128 #endif
1129 case TOK_memcpy:
1130 case TOK_memmove:
1131 case TOK_memset:
1132 case TOK_strlen:
1133 case TOK_strcpy:
1134 strcpy(buf, "__bound_");
1135 strcat(buf, name);
1136 name = buf;
1137 break;
1140 #endif
1141 info = ELF32_ST_INFO(sym_bind, sym_type);
1142 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1143 } else {
1144 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1145 esym->st_value = value;
1146 esym->st_size = size;
1147 esym->st_shndx = sh_num;
1151 /* add a new relocation entry to symbol 'sym' in section 's' */
1152 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1154 if (!sym->c)
1155 put_extern_sym(sym, NULL, 0, 0);
1156 /* now we can add ELF relocation info */
1157 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1160 static inline int isid(int c)
1162 return (c >= 'a' && c <= 'z') ||
1163 (c >= 'A' && c <= 'Z') ||
1164 c == '_';
1167 static inline int isnum(int c)
1169 return c >= '0' && c <= '9';
1172 static inline int isoct(int c)
1174 return c >= '0' && c <= '7';
1177 static inline int toup(int c)
1179 if (c >= 'a' && c <= 'z')
1180 return c - 'a' + 'A';
1181 else
1182 return c;
1185 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1187 int len;
1188 len = strlen(buf);
1189 vsnprintf(buf + len, buf_size - len, fmt, ap);
1192 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1194 va_list ap;
1195 va_start(ap, fmt);
1196 strcat_vprintf(buf, buf_size, fmt, ap);
1197 va_end(ap);
1200 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1202 char buf[2048];
1203 BufferedFile **f;
1205 buf[0] = '\0';
1206 if (file) {
1207 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1208 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1209 (*f)->filename, (*f)->line_num);
1210 if (file->line_num > 0) {
1211 strcat_printf(buf, sizeof(buf),
1212 "%s:%d: ", file->filename, file->line_num);
1213 } else {
1214 strcat_printf(buf, sizeof(buf),
1215 "%s: ", file->filename);
1217 } else {
1218 strcat_printf(buf, sizeof(buf),
1219 "tcc: ");
1221 if (is_warning)
1222 strcat_printf(buf, sizeof(buf), "warning: ");
1223 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1225 if (!s1->error_func) {
1226 /* default case: stderr */
1227 fprintf(stderr, "%s\n", buf);
1228 } else {
1229 s1->error_func(s1->error_opaque, buf);
1231 if (!is_warning || s1->warn_error)
1232 s1->nb_errors++;
1235 #ifdef LIBTCC
1236 void tcc_set_error_func(TCCState *s, void *error_opaque,
1237 void (*error_func)(void *opaque, const char *msg))
1239 s->error_opaque = error_opaque;
1240 s->error_func = error_func;
1242 #endif
1244 /* error without aborting current compilation */
1245 void error_noabort(const char *fmt, ...)
1247 TCCState *s1 = tcc_state;
1248 va_list ap;
1250 va_start(ap, fmt);
1251 error1(s1, 0, fmt, ap);
1252 va_end(ap);
1255 void error(const char *fmt, ...)
1257 TCCState *s1 = tcc_state;
1258 va_list ap;
1260 va_start(ap, fmt);
1261 error1(s1, 0, fmt, ap);
1262 va_end(ap);
1263 /* better than nothing: in some cases, we accept to handle errors */
1264 if (s1->error_set_jmp_enabled) {
1265 longjmp(s1->error_jmp_buf, 1);
1266 } else {
1267 /* XXX: eliminate this someday */
1268 exit(1);
1272 void expect(const char *msg)
1274 error("%s expected", msg);
1277 void warning(const char *fmt, ...)
1279 TCCState *s1 = tcc_state;
1280 va_list ap;
1282 if (s1->warn_none)
1283 return;
1285 va_start(ap, fmt);
1286 error1(s1, 1, fmt, ap);
1287 va_end(ap);
1290 void skip(int c)
1292 if (tok != c)
1293 error("'%c' expected", c);
1294 next();
1297 static void test_lvalue(void)
1299 if (!(vtop->r & VT_LVAL))
1300 expect("lvalue");
1303 /* allocate a new token */
1304 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1306 TokenSym *ts, **ptable;
1307 int i;
1309 if (tok_ident >= SYM_FIRST_ANOM)
1310 error("memory full");
1312 /* expand token table if needed */
1313 i = tok_ident - TOK_IDENT;
1314 if ((i % TOK_ALLOC_INCR) == 0) {
1315 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1316 if (!ptable)
1317 error("memory full");
1318 table_ident = ptable;
1321 ts = tcc_malloc(sizeof(TokenSym) + len);
1322 table_ident[i] = ts;
1323 ts->tok = tok_ident++;
1324 ts->sym_define = NULL;
1325 ts->sym_label = NULL;
1326 ts->sym_struct = NULL;
1327 ts->sym_identifier = NULL;
1328 ts->len = len;
1329 ts->hash_next = NULL;
1330 memcpy(ts->str, str, len);
1331 ts->str[len] = '\0';
1332 *pts = ts;
1333 return ts;
1336 #define TOK_HASH_INIT 1
1337 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1339 /* find a token and add it if not found */
1340 static TokenSym *tok_alloc(const char *str, int len)
1342 TokenSym *ts, **pts;
1343 int i;
1344 unsigned int h;
1346 h = TOK_HASH_INIT;
1347 for(i=0;i<len;i++)
1348 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1349 h &= (TOK_HASH_SIZE - 1);
1351 pts = &hash_ident[h];
1352 for(;;) {
1353 ts = *pts;
1354 if (!ts)
1355 break;
1356 if (ts->len == len && !memcmp(ts->str, str, len))
1357 return ts;
1358 pts = &(ts->hash_next);
1360 return tok_alloc_new(pts, str, len);
1363 /* CString handling */
1365 static void cstr_realloc(CString *cstr, int new_size)
1367 int size;
1368 void *data;
1370 size = cstr->size_allocated;
1371 if (size == 0)
1372 size = 8; /* no need to allocate a too small first string */
1373 while (size < new_size)
1374 size = size * 2;
1375 data = tcc_realloc(cstr->data_allocated, size);
1376 if (!data)
1377 error("memory full");
1378 cstr->data_allocated = data;
1379 cstr->size_allocated = size;
1380 cstr->data = data;
1383 /* add a byte */
1384 static void cstr_ccat(CString *cstr, int ch)
1386 int size;
1387 size = cstr->size + 1;
1388 if (size > cstr->size_allocated)
1389 cstr_realloc(cstr, size);
1390 ((unsigned char *)cstr->data)[size - 1] = ch;
1391 cstr->size = size;
1394 static void cstr_cat(CString *cstr, const char *str)
1396 int c;
1397 for(;;) {
1398 c = *str;
1399 if (c == '\0')
1400 break;
1401 cstr_ccat(cstr, c);
1402 str++;
1406 /* add a wide char */
1407 static void cstr_wccat(CString *cstr, int ch)
1409 int size;
1410 size = cstr->size + sizeof(int);
1411 if (size > cstr->size_allocated)
1412 cstr_realloc(cstr, size);
1413 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1414 cstr->size = size;
1417 static void cstr_new(CString *cstr)
1419 memset(cstr, 0, sizeof(CString));
1422 /* free string and reset it to NULL */
1423 static void cstr_free(CString *cstr)
1425 tcc_free(cstr->data_allocated);
1426 cstr_new(cstr);
1429 #define cstr_reset(cstr) cstr_free(cstr)
1431 static CString *cstr_dup(CString *cstr1)
1433 CString *cstr;
1434 int size;
1436 cstr = tcc_malloc(sizeof(CString));
1437 size = cstr1->size;
1438 cstr->size = size;
1439 cstr->size_allocated = size;
1440 cstr->data_allocated = tcc_malloc(size);
1441 cstr->data = cstr->data_allocated;
1442 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1443 return cstr;
1446 /* XXX: unicode ? */
1447 static void add_char(CString *cstr, int c)
1449 if (c == '\'' || c == '\"' || c == '\\') {
1450 /* XXX: could be more precise if char or string */
1451 cstr_ccat(cstr, '\\');
1453 if (c >= 32 && c <= 126) {
1454 cstr_ccat(cstr, c);
1455 } else {
1456 cstr_ccat(cstr, '\\');
1457 if (c == '\n') {
1458 cstr_ccat(cstr, 'n');
1459 } else {
1460 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1461 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1462 cstr_ccat(cstr, '0' + (c & 7));
1467 /* XXX: buffer overflow */
1468 /* XXX: float tokens */
1469 char *get_tok_str(int v, CValue *cv)
1471 static char buf[STRING_MAX_SIZE + 1];
1472 static CString cstr_buf;
1473 CString *cstr;
1474 unsigned char *q;
1475 char *p;
1476 int i, len;
1478 /* NOTE: to go faster, we give a fixed buffer for small strings */
1479 cstr_reset(&cstr_buf);
1480 cstr_buf.data = buf;
1481 cstr_buf.size_allocated = sizeof(buf);
1482 p = buf;
1484 switch(v) {
1485 case TOK_CINT:
1486 case TOK_CUINT:
1487 /* XXX: not quite exact, but only useful for testing */
1488 sprintf(p, "%u", cv->ui);
1489 break;
1490 case TOK_CLLONG:
1491 case TOK_CULLONG:
1492 /* XXX: not quite exact, but only useful for testing */
1493 sprintf(p, "%Lu", cv->ull);
1494 break;
1495 case TOK_CCHAR:
1496 case TOK_LCHAR:
1497 cstr_ccat(&cstr_buf, '\'');
1498 add_char(&cstr_buf, cv->i);
1499 cstr_ccat(&cstr_buf, '\'');
1500 cstr_ccat(&cstr_buf, '\0');
1501 break;
1502 case TOK_PPNUM:
1503 cstr = cv->cstr;
1504 len = cstr->size - 1;
1505 for(i=0;i<len;i++)
1506 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1507 cstr_ccat(&cstr_buf, '\0');
1508 break;
1509 case TOK_STR:
1510 case TOK_LSTR:
1511 cstr = cv->cstr;
1512 cstr_ccat(&cstr_buf, '\"');
1513 if (v == TOK_STR) {
1514 len = cstr->size - 1;
1515 for(i=0;i<len;i++)
1516 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1517 } else {
1518 len = (cstr->size / sizeof(int)) - 1;
1519 for(i=0;i<len;i++)
1520 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1522 cstr_ccat(&cstr_buf, '\"');
1523 cstr_ccat(&cstr_buf, '\0');
1524 break;
1525 case TOK_LT:
1526 v = '<';
1527 goto addv;
1528 case TOK_GT:
1529 v = '>';
1530 goto addv;
1531 case TOK_A_SHL:
1532 return strcpy(p, "<<=");
1533 case TOK_A_SAR:
1534 return strcpy(p, ">>=");
1535 default:
1536 if (v < TOK_IDENT) {
1537 /* search in two bytes table */
1538 q = tok_two_chars;
1539 while (*q) {
1540 if (q[2] == v) {
1541 *p++ = q[0];
1542 *p++ = q[1];
1543 *p = '\0';
1544 return buf;
1546 q += 3;
1548 addv:
1549 *p++ = v;
1550 *p = '\0';
1551 } else if (v < tok_ident) {
1552 return table_ident[v - TOK_IDENT]->str;
1553 } else if (v >= SYM_FIRST_ANOM) {
1554 /* special name for anonymous symbol */
1555 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1556 } else {
1557 /* should never happen */
1558 return NULL;
1560 break;
1562 return cstr_buf.data;
1565 /* push, without hashing */
1566 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1568 Sym *s;
1569 s = tcc_malloc(sizeof(Sym));
1570 s->v = v;
1571 s->type.t = t;
1572 s->c = c;
1573 s->next = NULL;
1574 /* add in stack */
1575 s->prev = *ps;
1576 *ps = s;
1577 return s;
1580 /* find a symbol and return its associated structure. 's' is the top
1581 of the symbol stack */
1582 static Sym *sym_find2(Sym *s, int v)
1584 while (s) {
1585 if (s->v == v)
1586 return s;
1587 s = s->prev;
1589 return NULL;
1592 /* structure lookup */
1593 static inline Sym *struct_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_struct;
1601 /* find an identifier */
1602 static inline Sym *sym_find(int v)
1604 v -= TOK_IDENT;
1605 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1606 return NULL;
1607 return table_ident[v]->sym_identifier;
1610 /* push a given symbol on the symbol stack */
1611 static Sym *sym_push(int v, CType *type, int r, int c)
1613 Sym *s, **ps;
1614 TokenSym *ts;
1616 if (local_stack)
1617 ps = &local_stack;
1618 else
1619 ps = &global_stack;
1620 s = sym_push2(ps, v, type->t, c);
1621 s->type.ref = type->ref;
1622 s->r = r;
1623 /* don't record fields or anonymous symbols */
1624 /* XXX: simplify */
1625 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1626 /* record symbol in token array */
1627 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1628 if (v & SYM_STRUCT)
1629 ps = &ts->sym_struct;
1630 else
1631 ps = &ts->sym_identifier;
1632 s->prev_tok = *ps;
1633 *ps = s;
1635 return s;
1638 /* push a global identifier */
1639 static Sym *global_identifier_push(int v, int t, int c)
1641 Sym *s, **ps;
1642 s = sym_push2(&global_stack, v, t, c);
1643 /* don't record anonymous symbol */
1644 if (v < SYM_FIRST_ANOM) {
1645 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1646 /* modify the top most local identifier, so that
1647 sym_identifier will point to 's' when popped */
1648 while (*ps != NULL)
1649 ps = &(*ps)->prev_tok;
1650 s->prev_tok = NULL;
1651 *ps = s;
1653 return s;
1656 /* pop symbols until top reaches 'b' */
1657 static void sym_pop(Sym **ptop, Sym *b)
1659 Sym *s, *ss, **ps;
1660 TokenSym *ts;
1661 int v;
1663 s = *ptop;
1664 while(s != b) {
1665 ss = s->prev;
1666 v = s->v;
1667 /* remove symbol in token array */
1668 /* XXX: simplify */
1669 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1670 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1671 if (v & SYM_STRUCT)
1672 ps = &ts->sym_struct;
1673 else
1674 ps = &ts->sym_identifier;
1675 *ps = s->prev_tok;
1677 tcc_free(s);
1678 s = ss;
1680 *ptop = b;
1683 /* I/O layer */
1685 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1687 int fd;
1688 BufferedFile *bf;
1690 fd = open(filename, O_RDONLY);
1691 if (fd < 0)
1692 return NULL;
1693 bf = tcc_malloc(sizeof(BufferedFile));
1694 if (!bf) {
1695 close(fd);
1696 return NULL;
1698 bf->fd = fd;
1699 bf->buf_ptr = bf->buffer;
1700 bf->buf_end = bf->buffer;
1701 bf->buffer[0] = CH_EOB; /* put eob symbol */
1702 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1703 bf->line_num = 1;
1704 bf->ifndef_macro = 0;
1705 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1706 // printf("opening '%s'\n", filename);
1707 return bf;
1710 void tcc_close(BufferedFile *bf)
1712 total_lines += bf->line_num;
1713 close(bf->fd);
1714 tcc_free(bf);
1717 /* fill input buffer and peek next char */
1718 static int tcc_peekc_slow(BufferedFile *bf)
1720 int len;
1721 /* only tries to read if really end of buffer */
1722 if (bf->buf_ptr >= bf->buf_end) {
1723 if (bf->fd != -1) {
1724 #if defined(PARSE_DEBUG)
1725 len = 8;
1726 #else
1727 len = IO_BUF_SIZE;
1728 #endif
1729 len = read(bf->fd, bf->buffer, len);
1730 if (len < 0)
1731 len = 0;
1732 } else {
1733 len = 0;
1735 total_bytes += len;
1736 bf->buf_ptr = bf->buffer;
1737 bf->buf_end = bf->buffer + len;
1738 *bf->buf_end = CH_EOB;
1740 if (bf->buf_ptr < bf->buf_end) {
1741 return bf->buf_ptr[0];
1742 } else {
1743 bf->buf_ptr = bf->buf_end;
1744 return CH_EOF;
1748 /* return the current character, handling end of block if necessary
1749 (but not stray) */
1750 static int handle_eob(void)
1752 return tcc_peekc_slow(file);
1755 /* read next char from current input file and handle end of input buffer */
1756 static inline void inp(void)
1758 ch = *(++(file->buf_ptr));
1759 /* end of buffer/file handling */
1760 if (ch == CH_EOB)
1761 ch = handle_eob();
1764 /* handle '\[\r]\n' */
1765 static void handle_stray(void)
1767 while (ch == '\\') {
1768 inp();
1769 if (ch == '\n') {
1770 file->line_num++;
1771 inp();
1772 } else if (ch == '\r') {
1773 inp();
1774 if (ch != '\n')
1775 goto fail;
1776 file->line_num++;
1777 inp();
1778 } else {
1779 fail:
1780 error("stray '\\' in program");
1785 /* skip the stray and handle the \\n case. Output an error if
1786 incorrect char after the stray */
1787 static int handle_stray1(uint8_t *p)
1789 int c;
1791 if (p >= file->buf_end) {
1792 file->buf_ptr = p;
1793 c = handle_eob();
1794 p = file->buf_ptr;
1795 if (c == '\\')
1796 goto parse_stray;
1797 } else {
1798 parse_stray:
1799 file->buf_ptr = p;
1800 ch = *p;
1801 handle_stray();
1802 p = file->buf_ptr;
1803 c = *p;
1805 return c;
1808 /* handle just the EOB case, but not stray */
1809 #define PEEKC_EOB(c, p)\
1811 p++;\
1812 c = *p;\
1813 if (c == '\\') {\
1814 file->buf_ptr = p;\
1815 c = handle_eob();\
1816 p = file->buf_ptr;\
1820 /* handle the complicated stray case */
1821 #define PEEKC(c, p)\
1823 p++;\
1824 c = *p;\
1825 if (c == '\\') {\
1826 c = handle_stray1(p);\
1827 p = file->buf_ptr;\
1831 /* input with '\[\r]\n' handling. Note that this function cannot
1832 handle other characters after '\', so you cannot call it inside
1833 strings or comments */
1834 static void minp(void)
1836 inp();
1837 if (ch == '\\')
1838 handle_stray();
1842 /* single line C++ comments */
1843 static uint8_t *parse_line_comment(uint8_t *p)
1845 int c;
1847 p++;
1848 for(;;) {
1849 c = *p;
1850 redo:
1851 if (c == '\n' || c == CH_EOF) {
1852 break;
1853 } else if (c == '\\') {
1854 file->buf_ptr = p;
1855 c = handle_eob();
1856 p = file->buf_ptr;
1857 if (c == '\\') {
1858 PEEKC_EOB(c, p);
1859 if (c == '\n') {
1860 file->line_num++;
1861 PEEKC_EOB(c, p);
1862 } else if (c == '\r') {
1863 PEEKC_EOB(c, p);
1864 if (c == '\n') {
1865 file->line_num++;
1866 PEEKC_EOB(c, p);
1869 } else {
1870 goto redo;
1872 } else {
1873 p++;
1876 return p;
1879 /* C comments */
1880 static uint8_t *parse_comment(uint8_t *p)
1882 int c;
1884 p++;
1885 for(;;) {
1886 /* fast skip loop */
1887 for(;;) {
1888 c = *p;
1889 if (c == '\n' || c == '*' || c == '\\')
1890 break;
1891 p++;
1892 c = *p;
1893 if (c == '\n' || c == '*' || c == '\\')
1894 break;
1895 p++;
1897 /* now we can handle all the cases */
1898 if (c == '\n') {
1899 file->line_num++;
1900 p++;
1901 } else if (c == '*') {
1902 p++;
1903 for(;;) {
1904 c = *p;
1905 if (c == '*') {
1906 p++;
1907 } else if (c == '/') {
1908 goto end_of_comment;
1909 } else if (c == '\\') {
1910 file->buf_ptr = p;
1911 c = handle_eob();
1912 p = file->buf_ptr;
1913 if (c == '\\') {
1914 /* skip '\[\r]\n', otherwise just skip the stray */
1915 while (c == '\\') {
1916 PEEKC_EOB(c, p);
1917 if (c == '\n') {
1918 file->line_num++;
1919 PEEKC_EOB(c, p);
1920 } else if (c == '\r') {
1921 PEEKC_EOB(c, p);
1922 if (c == '\n') {
1923 file->line_num++;
1924 PEEKC_EOB(c, p);
1926 } else {
1927 goto after_star;
1931 } else {
1932 break;
1935 after_star: ;
1936 } else {
1937 /* stray, eob or eof */
1938 file->buf_ptr = p;
1939 c = handle_eob();
1940 p = file->buf_ptr;
1941 if (c == CH_EOF) {
1942 error("unexpected end of file in comment");
1943 } else if (c == '\\') {
1944 p++;
1948 end_of_comment:
1949 p++;
1950 return p;
1953 #define cinp minp
1955 /* space exlcuding newline */
1956 static inline int is_space(int ch)
1958 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1961 static inline void skip_spaces(void)
1963 while (is_space(ch))
1964 cinp();
1967 /* parse a string without interpreting escapes */
1968 static uint8_t *parse_pp_string(uint8_t *p,
1969 int sep, CString *str)
1971 int c;
1972 p++;
1973 for(;;) {
1974 c = *p;
1975 if (c == sep) {
1976 break;
1977 } else if (c == '\\') {
1978 file->buf_ptr = p;
1979 c = handle_eob();
1980 p = file->buf_ptr;
1981 if (c == CH_EOF) {
1982 unterminated_string:
1983 /* XXX: indicate line number of start of string */
1984 error("missing terminating %c character", sep);
1985 } else if (c == '\\') {
1986 /* escape : just skip \[\r]\n */
1987 PEEKC_EOB(c, p);
1988 if (c == '\n') {
1989 file->line_num++;
1990 p++;
1991 } else if (c == '\r') {
1992 PEEKC_EOB(c, p);
1993 if (c != '\n')
1994 expect("'\n' after '\r'");
1995 file->line_num++;
1996 p++;
1997 } else if (c == CH_EOF) {
1998 goto unterminated_string;
1999 } else {
2000 if (str) {
2001 cstr_ccat(str, '\\');
2002 cstr_ccat(str, c);
2004 p++;
2007 } else if (c == '\n') {
2008 file->line_num++;
2009 goto add_char;
2010 } else if (c == '\r') {
2011 PEEKC_EOB(c, p);
2012 if (c != '\n') {
2013 cstr_ccat(str, '\r');
2014 } else {
2015 file->line_num++;
2016 goto add_char;
2018 } else {
2019 add_char:
2020 if (str)
2021 cstr_ccat(str, c);
2022 p++;
2025 p++;
2026 return p;
2029 /* skip block of text until #else, #elif or #endif. skip also pairs of
2030 #if/#endif */
2031 void preprocess_skip(void)
2033 int a, start_of_line, c;
2034 uint8_t *p;
2036 p = file->buf_ptr;
2037 start_of_line = 1;
2038 a = 0;
2039 for(;;) {
2040 redo_no_start:
2041 c = *p;
2042 switch(c) {
2043 case ' ':
2044 case '\t':
2045 case '\f':
2046 case '\v':
2047 case '\r':
2048 p++;
2049 goto redo_no_start;
2050 case '\n':
2051 start_of_line = 1;
2052 file->line_num++;
2053 p++;
2054 goto redo_no_start;
2055 case '\\':
2056 file->buf_ptr = p;
2057 c = handle_eob();
2058 if (c == CH_EOF) {
2059 expect("#endif");
2060 } else if (c == '\\') {
2061 /* XXX: incorrect: should not give an error */
2062 ch = file->buf_ptr[0];
2063 handle_stray();
2065 p = file->buf_ptr;
2066 goto redo_no_start;
2067 /* skip strings */
2068 case '\"':
2069 case '\'':
2070 p = parse_pp_string(p, c, NULL);
2071 break;
2072 /* skip comments */
2073 case '/':
2074 file->buf_ptr = p;
2075 ch = *p;
2076 minp();
2077 p = file->buf_ptr;
2078 if (ch == '*') {
2079 p = parse_comment(p);
2080 } else if (ch == '/') {
2081 p = parse_line_comment(p);
2083 break;
2085 case '#':
2086 p++;
2087 if (start_of_line) {
2088 file->buf_ptr = p;
2089 next_nomacro();
2090 p = file->buf_ptr;
2091 if (a == 0 &&
2092 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2093 goto the_end;
2094 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2095 a++;
2096 else if (tok == TOK_ENDIF)
2097 a--;
2099 break;
2100 default:
2101 p++;
2102 break;
2104 start_of_line = 0;
2106 the_end: ;
2107 file->buf_ptr = p;
2110 /* ParseState handling */
2112 /* XXX: currently, no include file info is stored. Thus, we cannot display
2113 accurate messages if the function or data definition spans multiple
2114 files */
2116 /* save current parse state in 's' */
2117 void save_parse_state(ParseState *s)
2119 s->line_num = file->line_num;
2120 s->macro_ptr = macro_ptr;
2121 s->tok = tok;
2122 s->tokc = tokc;
2125 /* restore parse state from 's' */
2126 void restore_parse_state(ParseState *s)
2128 file->line_num = s->line_num;
2129 macro_ptr = s->macro_ptr;
2130 tok = s->tok;
2131 tokc = s->tokc;
2134 /* return the number of additional 'ints' necessary to store the
2135 token */
2136 static inline int tok_ext_size(int t)
2138 switch(t) {
2139 /* 4 bytes */
2140 case TOK_CINT:
2141 case TOK_CUINT:
2142 case TOK_CCHAR:
2143 case TOK_LCHAR:
2144 case TOK_STR:
2145 case TOK_LSTR:
2146 case TOK_CFLOAT:
2147 case TOK_LINENUM:
2148 case TOK_PPNUM:
2149 return 1;
2150 case TOK_CDOUBLE:
2151 case TOK_CLLONG:
2152 case TOK_CULLONG:
2153 return 2;
2154 case TOK_CLDOUBLE:
2155 return LDOUBLE_SIZE / 4;
2156 default:
2157 return 0;
2161 /* token string handling */
2163 static inline void tok_str_new(TokenString *s)
2165 s->str = NULL;
2166 s->len = 0;
2167 s->allocated_len = 0;
2168 s->last_line_num = -1;
2171 static void tok_str_free(int *str)
2173 const int *p;
2174 CString *cstr;
2175 int t;
2177 p = str;
2178 for(;;) {
2179 t = *p;
2180 /* NOTE: we test zero separately so that GCC can generate a
2181 table for the following switch */
2182 if (t == 0)
2183 break;
2184 switch(t) {
2185 case TOK_CINT:
2186 case TOK_CUINT:
2187 case TOK_CCHAR:
2188 case TOK_LCHAR:
2189 case TOK_CFLOAT:
2190 case TOK_LINENUM:
2191 p += 2;
2192 break;
2193 case TOK_PPNUM:
2194 case TOK_STR:
2195 case TOK_LSTR:
2196 /* XXX: use a macro to be portable on 64 bit ? */
2197 cstr = (CString *)p[1];
2198 cstr_free(cstr);
2199 tcc_free(cstr);
2200 p += 2;
2201 break;
2202 case TOK_CDOUBLE:
2203 case TOK_CLLONG:
2204 case TOK_CULLONG:
2205 p += 3;
2206 break;
2207 case TOK_CLDOUBLE:
2208 p += 1 + (LDOUBLE_SIZE / 4);
2209 break;
2210 default:
2211 p++;
2212 break;
2215 tcc_free(str);
2218 static int *tok_str_realloc(TokenString *s)
2220 int *str, len;
2222 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2223 str = tcc_realloc(s->str, len * sizeof(int));
2224 if (!str)
2225 error("memory full");
2226 s->allocated_len = len;
2227 s->str = str;
2228 return str;
2231 static void tok_str_add(TokenString *s, int t)
2233 int len, *str;
2235 len = s->len;
2236 str = s->str;
2237 if (len >= s->allocated_len)
2238 str = tok_str_realloc(s);
2239 str[len++] = t;
2240 s->len = len;
2243 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2245 int len, *str;
2247 len = s->len;
2248 str = s->str;
2250 /* allocate space for worst case */
2251 if (len + TOK_MAX_SIZE > s->allocated_len)
2252 str = tok_str_realloc(s);
2253 str[len++] = t;
2254 switch(t) {
2255 case TOK_CINT:
2256 case TOK_CUINT:
2257 case TOK_CCHAR:
2258 case TOK_LCHAR:
2259 case TOK_CFLOAT:
2260 case TOK_LINENUM:
2261 str[len++] = cv->tab[0];
2262 break;
2263 case TOK_PPNUM:
2264 case TOK_STR:
2265 case TOK_LSTR:
2266 str[len++] = (int)cstr_dup(cv->cstr);
2267 break;
2268 case TOK_CDOUBLE:
2269 case TOK_CLLONG:
2270 case TOK_CULLONG:
2271 #if LDOUBLE_SIZE == 8
2272 case TOK_CLDOUBLE:
2273 #endif
2274 str[len++] = cv->tab[0];
2275 str[len++] = cv->tab[1];
2276 break;
2277 #if LDOUBLE_SIZE == 12
2278 case TOK_CLDOUBLE:
2279 str[len++] = cv->tab[0];
2280 str[len++] = cv->tab[1];
2281 str[len++] = cv->tab[2];
2282 #elif LDOUBLE_SIZE != 8
2283 #error add long double size support
2284 #endif
2285 break;
2286 default:
2287 break;
2289 s->len = len;
2292 /* add the current parse token in token string 's' */
2293 static void tok_str_add_tok(TokenString *s)
2295 CValue cval;
2297 /* save line number info */
2298 if (file->line_num != s->last_line_num) {
2299 s->last_line_num = file->line_num;
2300 cval.i = s->last_line_num;
2301 tok_str_add2(s, TOK_LINENUM, &cval);
2303 tok_str_add2(s, tok, &tokc);
2306 #if LDOUBLE_SIZE == 12
2307 #define LDOUBLE_GET(p, cv) \
2308 cv.tab[0] = p[0]; \
2309 cv.tab[1] = p[1]; \
2310 cv.tab[2] = p[2];
2311 #elif LDOUBLE_SIZE == 8
2312 #define LDOUBLE_GET(p, cv) \
2313 cv.tab[0] = p[0]; \
2314 cv.tab[1] = p[1];
2315 #else
2316 #error add long double size support
2317 #endif
2320 /* get a token from an integer array and increment pointer
2321 accordingly. we code it as a macro to avoid pointer aliasing. */
2322 #define TOK_GET(t, p, cv) \
2324 t = *p++; \
2325 switch(t) { \
2326 case TOK_CINT: \
2327 case TOK_CUINT: \
2328 case TOK_CCHAR: \
2329 case TOK_LCHAR: \
2330 case TOK_CFLOAT: \
2331 case TOK_LINENUM: \
2332 case TOK_STR: \
2333 case TOK_LSTR: \
2334 case TOK_PPNUM: \
2335 cv.tab[0] = *p++; \
2336 break; \
2337 case TOK_CDOUBLE: \
2338 case TOK_CLLONG: \
2339 case TOK_CULLONG: \
2340 cv.tab[0] = p[0]; \
2341 cv.tab[1] = p[1]; \
2342 p += 2; \
2343 break; \
2344 case TOK_CLDOUBLE: \
2345 LDOUBLE_GET(p, cv); \
2346 p += LDOUBLE_SIZE / 4; \
2347 break; \
2348 default: \
2349 break; \
2353 /* defines handling */
2354 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2356 Sym *s;
2358 s = sym_push2(&define_stack, v, macro_type, (int)str);
2359 s->next = first_arg;
2360 table_ident[v - TOK_IDENT]->sym_define = s;
2363 /* undefined a define symbol. Its name is just set to zero */
2364 static void define_undef(Sym *s)
2366 int v;
2367 v = s->v;
2368 if (v >= TOK_IDENT && v < tok_ident)
2369 table_ident[v - TOK_IDENT]->sym_define = NULL;
2370 s->v = 0;
2373 static inline Sym *define_find(int v)
2375 v -= TOK_IDENT;
2376 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2377 return NULL;
2378 return table_ident[v]->sym_define;
2381 /* free define stack until top reaches 'b' */
2382 static void free_defines(Sym *b)
2384 Sym *top, *top1;
2385 int v;
2387 top = define_stack;
2388 while (top != b) {
2389 top1 = top->prev;
2390 /* do not free args or predefined defines */
2391 if (top->c)
2392 tok_str_free((int *)top->c);
2393 v = top->v;
2394 if (v >= TOK_IDENT && v < tok_ident)
2395 table_ident[v - TOK_IDENT]->sym_define = NULL;
2396 tcc_free(top);
2397 top = top1;
2399 define_stack = b;
2402 /* label lookup */
2403 static Sym *label_find(int v)
2405 v -= TOK_IDENT;
2406 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2407 return NULL;
2408 return table_ident[v]->sym_label;
2411 static Sym *label_push(Sym **ptop, int v, int flags)
2413 Sym *s, **ps;
2414 s = sym_push2(ptop, v, 0, 0);
2415 s->r = flags;
2416 ps = &table_ident[v - TOK_IDENT]->sym_label;
2417 if (ptop == &global_label_stack) {
2418 /* modify the top most local identifier, so that
2419 sym_identifier will point to 's' when popped */
2420 while (*ps != NULL)
2421 ps = &(*ps)->prev_tok;
2423 s->prev_tok = *ps;
2424 *ps = s;
2425 return s;
2428 /* pop labels until element last is reached. Look if any labels are
2429 undefined. Define symbols if '&&label' was used. */
2430 static void label_pop(Sym **ptop, Sym *slast)
2432 Sym *s, *s1;
2433 for(s = *ptop; s != slast; s = s1) {
2434 s1 = s->prev;
2435 if (s->r == LABEL_DECLARED) {
2436 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2437 } else if (s->r == LABEL_FORWARD) {
2438 error("label '%s' used but not defined",
2439 get_tok_str(s->v, NULL));
2440 } else {
2441 if (s->c) {
2442 /* define corresponding symbol. A size of
2443 1 is put. */
2444 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2447 /* remove label */
2448 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2449 tcc_free(s);
2451 *ptop = slast;
2454 /* eval an expression for #if/#elif */
2455 static int expr_preprocess(void)
2457 int c, t;
2458 TokenString str;
2460 tok_str_new(&str);
2461 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2462 next(); /* do macro subst */
2463 if (tok == TOK_DEFINED) {
2464 next_nomacro();
2465 t = tok;
2466 if (t == '(')
2467 next_nomacro();
2468 c = define_find(tok) != 0;
2469 if (t == '(')
2470 next_nomacro();
2471 tok = TOK_CINT;
2472 tokc.i = c;
2473 } else if (tok >= TOK_IDENT) {
2474 /* if undefined macro */
2475 tok = TOK_CINT;
2476 tokc.i = 0;
2478 tok_str_add_tok(&str);
2480 tok_str_add(&str, -1); /* simulate end of file */
2481 tok_str_add(&str, 0);
2482 /* now evaluate C constant expression */
2483 macro_ptr = str.str;
2484 next();
2485 c = expr_const();
2486 macro_ptr = NULL;
2487 tok_str_free(str.str);
2488 return c != 0;
2491 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2492 static void tok_print(int *str)
2494 int t;
2495 CValue cval;
2497 while (1) {
2498 TOK_GET(t, str, cval);
2499 if (!t)
2500 break;
2501 printf(" %s", get_tok_str(t, &cval));
2503 printf("\n");
2505 #endif
2507 /* parse after #define */
2508 static void parse_define(void)
2510 Sym *s, *first, **ps;
2511 int v, t, varg, is_vaargs, c;
2512 TokenString str;
2514 v = tok;
2515 if (v < TOK_IDENT)
2516 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2517 /* XXX: should check if same macro (ANSI) */
2518 first = NULL;
2519 t = MACRO_OBJ;
2520 /* '(' must be just after macro definition for MACRO_FUNC */
2521 c = file->buf_ptr[0];
2522 if (c == '\\')
2523 c = handle_stray1(file->buf_ptr);
2524 if (c == '(') {
2525 next_nomacro();
2526 next_nomacro();
2527 ps = &first;
2528 while (tok != ')') {
2529 varg = tok;
2530 next_nomacro();
2531 is_vaargs = 0;
2532 if (varg == TOK_DOTS) {
2533 varg = TOK___VA_ARGS__;
2534 is_vaargs = 1;
2535 } else if (tok == TOK_DOTS && gnu_ext) {
2536 is_vaargs = 1;
2537 next_nomacro();
2539 if (varg < TOK_IDENT)
2540 error("badly punctuated parameter list");
2541 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2542 *ps = s;
2543 ps = &s->next;
2544 if (tok != ',')
2545 break;
2546 next_nomacro();
2548 t = MACRO_FUNC;
2550 tok_str_new(&str);
2551 next_nomacro();
2552 /* EOF testing necessary for '-D' handling */
2553 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2554 tok_str_add2(&str, tok, &tokc);
2555 next_nomacro();
2557 tok_str_add(&str, 0);
2558 #ifdef PP_DEBUG
2559 printf("define %s %d: ", get_tok_str(v, NULL), t);
2560 tok_print(str.str);
2561 #endif
2562 define_push(v, t, str.str, first);
2565 /* XXX: use a token or a hash table to accelerate matching ? */
2566 static CachedInclude *search_cached_include(TCCState *s1,
2567 int type, const char *filename)
2569 CachedInclude *e;
2570 int i;
2572 for(i = 0;i < s1->nb_cached_includes; i++) {
2573 e = s1->cached_includes[i];
2574 if (e->type == type && !strcmp(e->filename, filename))
2575 return e;
2577 return NULL;
2580 static inline void add_cached_include(TCCState *s1, int type,
2581 const char *filename, int ifndef_macro)
2583 CachedInclude *e;
2585 if (search_cached_include(s1, type, filename))
2586 return;
2587 #ifdef INC_DEBUG
2588 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2589 #endif
2590 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2591 if (!e)
2592 return;
2593 e->type = type;
2594 strcpy(e->filename, filename);
2595 e->ifndef_macro = ifndef_macro;
2596 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2599 /* is_bof is true if first non space token at beginning of file */
2600 static void preprocess(int is_bof)
2602 TCCState *s1 = tcc_state;
2603 int size, i, c, n, saved_parse_flags;
2604 char buf[1024], *q, *p;
2605 char buf1[1024];
2606 BufferedFile *f;
2607 Sym *s;
2608 CachedInclude *e;
2610 saved_parse_flags = parse_flags;
2611 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2612 PARSE_FLAG_LINEFEED;
2613 next_nomacro();
2614 redo:
2615 switch(tok) {
2616 case TOK_DEFINE:
2617 next_nomacro();
2618 parse_define();
2619 break;
2620 case TOK_UNDEF:
2621 next_nomacro();
2622 s = define_find(tok);
2623 /* undefine symbol by putting an invalid name */
2624 if (s)
2625 define_undef(s);
2626 break;
2627 case TOK_INCLUDE:
2628 ch = file->buf_ptr[0];
2629 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2630 skip_spaces();
2631 if (ch == '<') {
2632 c = '>';
2633 goto read_name;
2634 } else if (ch == '\"') {
2635 c = ch;
2636 read_name:
2637 /* XXX: better stray handling */
2638 minp();
2639 q = buf;
2640 while (ch != c && ch != '\n' && ch != CH_EOF) {
2641 if ((q - buf) < sizeof(buf) - 1)
2642 *q++ = ch;
2643 minp();
2645 *q = '\0';
2646 minp();
2647 #if 0
2648 /* eat all spaces and comments after include */
2649 /* XXX: slightly incorrect */
2650 while (ch1 != '\n' && ch1 != CH_EOF)
2651 inp();
2652 #endif
2653 } else {
2654 /* computed #include : either we have only strings or
2655 we have anything enclosed in '<>' */
2656 next();
2657 buf[0] = '\0';
2658 if (tok == TOK_STR) {
2659 while (tok != TOK_LINEFEED) {
2660 if (tok != TOK_STR) {
2661 include_syntax:
2662 error("'#include' expects \"FILENAME\" or <FILENAME>");
2664 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2665 next();
2667 c = '\"';
2668 } else {
2669 int len;
2670 while (tok != TOK_LINEFEED) {
2671 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2672 next();
2674 len = strlen(buf);
2675 /* check syntax and remove '<>' */
2676 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2677 goto include_syntax;
2678 memmove(buf, buf + 1, len - 2);
2679 buf[len - 2] = '\0';
2680 c = '>';
2684 e = search_cached_include(s1, c, buf);
2685 if (e && define_find(e->ifndef_macro)) {
2686 /* no need to parse the include because the 'ifndef macro'
2687 is defined */
2688 #ifdef INC_DEBUG
2689 printf("%s: skipping %s\n", file->filename, buf);
2690 #endif
2691 } else {
2692 if (c == '\"') {
2693 /* first search in current dir if "header.h" */
2694 size = 0;
2695 p = strrchr(file->filename, '/');
2696 if (p)
2697 size = p + 1 - file->filename;
2698 if (size > sizeof(buf1) - 1)
2699 size = sizeof(buf1) - 1;
2700 memcpy(buf1, file->filename, size);
2701 buf1[size] = '\0';
2702 pstrcat(buf1, sizeof(buf1), buf);
2703 f = tcc_open(s1, buf1);
2704 if (f)
2705 goto found;
2707 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2708 error("#include recursion too deep");
2709 /* now search in all the include paths */
2710 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2711 for(i = 0; i < n; i++) {
2712 const char *path;
2713 if (i < s1->nb_include_paths)
2714 path = s1->include_paths[i];
2715 else
2716 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2717 pstrcpy(buf1, sizeof(buf1), path);
2718 pstrcat(buf1, sizeof(buf1), "/");
2719 pstrcat(buf1, sizeof(buf1), buf);
2720 f = tcc_open(s1, buf1);
2721 if (f)
2722 goto found;
2724 error("include file '%s' not found", buf);
2725 f = NULL;
2726 found:
2727 #ifdef INC_DEBUG
2728 printf("%s: including %s\n", file->filename, buf1);
2729 #endif
2730 f->inc_type = c;
2731 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2732 /* push current file in stack */
2733 /* XXX: fix current line init */
2734 *s1->include_stack_ptr++ = file;
2735 file = f;
2736 /* add include file debug info */
2737 if (do_debug) {
2738 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2740 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2741 ch = file->buf_ptr[0];
2742 goto the_end;
2744 break;
2745 case TOK_IFNDEF:
2746 c = 1;
2747 goto do_ifdef;
2748 case TOK_IF:
2749 c = expr_preprocess();
2750 goto do_if;
2751 case TOK_IFDEF:
2752 c = 0;
2753 do_ifdef:
2754 next_nomacro();
2755 if (tok < TOK_IDENT)
2756 error("invalid argument for '#if%sdef'", c ? "n" : "");
2757 if (is_bof) {
2758 if (c) {
2759 #ifdef INC_DEBUG
2760 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2761 #endif
2762 file->ifndef_macro = tok;
2765 c = (define_find(tok) != 0) ^ c;
2766 do_if:
2767 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2768 error("memory full");
2769 *s1->ifdef_stack_ptr++ = c;
2770 goto test_skip;
2771 case TOK_ELSE:
2772 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2773 error("#else without matching #if");
2774 if (s1->ifdef_stack_ptr[-1] & 2)
2775 error("#else after #else");
2776 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2777 goto test_skip;
2778 case TOK_ELIF:
2779 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2780 error("#elif without matching #if");
2781 c = s1->ifdef_stack_ptr[-1];
2782 if (c > 1)
2783 error("#elif after #else");
2784 /* last #if/#elif expression was true: we skip */
2785 if (c == 1)
2786 goto skip;
2787 c = expr_preprocess();
2788 s1->ifdef_stack_ptr[-1] = c;
2789 test_skip:
2790 if (!(c & 1)) {
2791 skip:
2792 preprocess_skip();
2793 is_bof = 0;
2794 goto redo;
2796 break;
2797 case TOK_ENDIF:
2798 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2799 error("#endif without matching #if");
2800 s1->ifdef_stack_ptr--;
2801 /* '#ifndef macro' was at the start of file. Now we check if
2802 an '#endif' is exactly at the end of file */
2803 if (file->ifndef_macro &&
2804 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2805 file->ifndef_macro_saved = file->ifndef_macro;
2806 /* need to set to zero to avoid false matches if another
2807 #ifndef at middle of file */
2808 file->ifndef_macro = 0;
2809 while (tok != TOK_LINEFEED)
2810 next_nomacro();
2811 tok_flags |= TOK_FLAG_ENDIF;
2812 goto the_end;
2814 break;
2815 case TOK_LINE:
2816 next();
2817 if (tok != TOK_CINT)
2818 error("#line");
2819 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2820 next();
2821 if (tok != TOK_LINEFEED) {
2822 if (tok != TOK_STR)
2823 error("#line");
2824 pstrcpy(file->filename, sizeof(file->filename),
2825 (char *)tokc.cstr->data);
2827 break;
2828 case TOK_ERROR:
2829 case TOK_WARNING:
2830 c = tok;
2831 ch = file->buf_ptr[0];
2832 skip_spaces();
2833 q = buf;
2834 while (ch != '\n' && ch != CH_EOF) {
2835 if ((q - buf) < sizeof(buf) - 1)
2836 *q++ = ch;
2837 minp();
2839 *q = '\0';
2840 if (c == TOK_ERROR)
2841 error("#error %s", buf);
2842 else
2843 warning("#warning %s", buf);
2844 break;
2845 case TOK_PRAGMA:
2846 /* ignored */
2847 break;
2848 default:
2849 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2850 /* '!' is ignored to allow C scripts. numbers are ignored
2851 to emulate cpp behaviour */
2852 } else {
2853 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2855 break;
2857 /* ignore other preprocess commands or #! for C scripts */
2858 while (tok != TOK_LINEFEED)
2859 next_nomacro();
2860 the_end:
2861 parse_flags = saved_parse_flags;
2864 /* evaluate escape codes in a string. */
2865 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2867 int c, n;
2868 const uint8_t *p;
2870 p = buf;
2871 for(;;) {
2872 c = *p;
2873 if (c == '\0')
2874 break;
2875 if (c == '\\') {
2876 p++;
2877 /* escape */
2878 c = *p;
2879 switch(c) {
2880 case '0': case '1': case '2': case '3':
2881 case '4': case '5': case '6': case '7':
2882 /* at most three octal digits */
2883 n = c - '0';
2884 p++;
2885 c = *p;
2886 if (isoct(c)) {
2887 n = n * 8 + c - '0';
2888 p++;
2889 c = *p;
2890 if (isoct(c)) {
2891 n = n * 8 + c - '0';
2892 p++;
2895 c = n;
2896 goto add_char_nonext;
2897 case 'x':
2898 p++;
2899 n = 0;
2900 for(;;) {
2901 c = *p;
2902 if (c >= 'a' && c <= 'f')
2903 c = c - 'a' + 10;
2904 else if (c >= 'A' && c <= 'F')
2905 c = c - 'A' + 10;
2906 else if (isnum(c))
2907 c = c - '0';
2908 else
2909 break;
2910 n = n * 16 + c;
2911 p++;
2913 c = n;
2914 goto add_char_nonext;
2915 case 'a':
2916 c = '\a';
2917 break;
2918 case 'b':
2919 c = '\b';
2920 break;
2921 case 'f':
2922 c = '\f';
2923 break;
2924 case 'n':
2925 c = '\n';
2926 break;
2927 case 'r':
2928 c = '\r';
2929 break;
2930 case 't':
2931 c = '\t';
2932 break;
2933 case 'v':
2934 c = '\v';
2935 break;
2936 case 'e':
2937 if (!gnu_ext)
2938 goto invalid_escape;
2939 c = 27;
2940 break;
2941 case '\'':
2942 case '\"':
2943 case '\\':
2944 case '?':
2945 break;
2946 default:
2947 invalid_escape:
2948 if (c >= '!' && c <= '~')
2949 warning("unknown escape sequence: \'\\%c\'", c);
2950 else
2951 warning("unknown escape sequence: \'\\x%x\'", c);
2952 break;
2955 p++;
2956 add_char_nonext:
2957 if (!is_long)
2958 cstr_ccat(outstr, c);
2959 else
2960 cstr_wccat(outstr, c);
2962 /* add a trailing '\0' */
2963 if (!is_long)
2964 cstr_ccat(outstr, '\0');
2965 else
2966 cstr_wccat(outstr, '\0');
2969 /* we use 64 bit numbers */
2970 #define BN_SIZE 2
2972 /* bn = (bn << shift) | or_val */
2973 void bn_lshift(unsigned int *bn, int shift, int or_val)
2975 int i;
2976 unsigned int v;
2977 for(i=0;i<BN_SIZE;i++) {
2978 v = bn[i];
2979 bn[i] = (v << shift) | or_val;
2980 or_val = v >> (32 - shift);
2984 void bn_zero(unsigned int *bn)
2986 int i;
2987 for(i=0;i<BN_SIZE;i++) {
2988 bn[i] = 0;
2992 /* parse number in null terminated string 'p' and return it in the
2993 current token */
2994 void parse_number(const char *p)
2996 int b, t, shift, frac_bits, s, exp_val, ch;
2997 char *q;
2998 unsigned int bn[BN_SIZE];
2999 double d;
3001 /* number */
3002 q = token_buf;
3003 ch = *p++;
3004 t = ch;
3005 ch = *p++;
3006 *q++ = t;
3007 b = 10;
3008 if (t == '.') {
3009 goto float_frac_parse;
3010 } else if (t == '0') {
3011 if (ch == 'x' || ch == 'X') {
3012 q--;
3013 ch = *p++;
3014 b = 16;
3015 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3016 q--;
3017 ch = *p++;
3018 b = 2;
3021 /* parse all digits. cannot check octal numbers at this stage
3022 because of floating point constants */
3023 while (1) {
3024 if (ch >= 'a' && ch <= 'f')
3025 t = ch - 'a' + 10;
3026 else if (ch >= 'A' && ch <= 'F')
3027 t = ch - 'A' + 10;
3028 else if (isnum(ch))
3029 t = ch - '0';
3030 else
3031 break;
3032 if (t >= b)
3033 break;
3034 if (q >= token_buf + STRING_MAX_SIZE) {
3035 num_too_long:
3036 error("number too long");
3038 *q++ = ch;
3039 ch = *p++;
3041 if (ch == '.' ||
3042 ((ch == 'e' || ch == 'E') && b == 10) ||
3043 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3044 if (b != 10) {
3045 /* NOTE: strtox should support that for hexa numbers, but
3046 non ISOC99 libcs do not support it, so we prefer to do
3047 it by hand */
3048 /* hexadecimal or binary floats */
3049 /* XXX: handle overflows */
3050 *q = '\0';
3051 if (b == 16)
3052 shift = 4;
3053 else
3054 shift = 2;
3055 bn_zero(bn);
3056 q = token_buf;
3057 while (1) {
3058 t = *q++;
3059 if (t == '\0') {
3060 break;
3061 } else if (t >= 'a') {
3062 t = t - 'a' + 10;
3063 } else if (t >= 'A') {
3064 t = t - 'A' + 10;
3065 } else {
3066 t = t - '0';
3068 bn_lshift(bn, shift, t);
3070 frac_bits = 0;
3071 if (ch == '.') {
3072 ch = *p++;
3073 while (1) {
3074 t = ch;
3075 if (t >= 'a' && t <= 'f') {
3076 t = t - 'a' + 10;
3077 } else if (t >= 'A' && t <= 'F') {
3078 t = t - 'A' + 10;
3079 } else if (t >= '0' && t <= '9') {
3080 t = t - '0';
3081 } else {
3082 break;
3084 if (t >= b)
3085 error("invalid digit");
3086 bn_lshift(bn, shift, t);
3087 frac_bits += shift;
3088 ch = *p++;
3091 if (ch != 'p' && ch != 'P')
3092 expect("exponent");
3093 ch = *p++;
3094 s = 1;
3095 exp_val = 0;
3096 if (ch == '+') {
3097 ch = *p++;
3098 } else if (ch == '-') {
3099 s = -1;
3100 ch = *p++;
3102 if (ch < '0' || ch > '9')
3103 expect("exponent digits");
3104 while (ch >= '0' && ch <= '9') {
3105 exp_val = exp_val * 10 + ch - '0';
3106 ch = *p++;
3108 exp_val = exp_val * s;
3110 /* now we can generate the number */
3111 /* XXX: should patch directly float number */
3112 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3113 d = ldexp(d, exp_val - frac_bits);
3114 t = toup(ch);
3115 if (t == 'F') {
3116 ch = *p++;
3117 tok = TOK_CFLOAT;
3118 /* float : should handle overflow */
3119 tokc.f = (float)d;
3120 } else if (t == 'L') {
3121 ch = *p++;
3122 tok = TOK_CLDOUBLE;
3123 /* XXX: not large enough */
3124 tokc.ld = (long double)d;
3125 } else {
3126 tok = TOK_CDOUBLE;
3127 tokc.d = d;
3129 } else {
3130 /* decimal floats */
3131 if (ch == '.') {
3132 if (q >= token_buf + STRING_MAX_SIZE)
3133 goto num_too_long;
3134 *q++ = ch;
3135 ch = *p++;
3136 float_frac_parse:
3137 while (ch >= '0' && ch <= '9') {
3138 if (q >= token_buf + STRING_MAX_SIZE)
3139 goto num_too_long;
3140 *q++ = ch;
3141 ch = *p++;
3144 if (ch == 'e' || ch == 'E') {
3145 if (q >= token_buf + STRING_MAX_SIZE)
3146 goto num_too_long;
3147 *q++ = ch;
3148 ch = *p++;
3149 if (ch == '-' || ch == '+') {
3150 if (q >= token_buf + STRING_MAX_SIZE)
3151 goto num_too_long;
3152 *q++ = ch;
3153 ch = *p++;
3155 if (ch < '0' || ch > '9')
3156 expect("exponent digits");
3157 while (ch >= '0' && ch <= '9') {
3158 if (q >= token_buf + STRING_MAX_SIZE)
3159 goto num_too_long;
3160 *q++ = ch;
3161 ch = *p++;
3164 *q = '\0';
3165 t = toup(ch);
3166 errno = 0;
3167 if (t == 'F') {
3168 ch = *p++;
3169 tok = TOK_CFLOAT;
3170 tokc.f = strtof(token_buf, NULL);
3171 } else if (t == 'L') {
3172 ch = *p++;
3173 tok = TOK_CLDOUBLE;
3174 tokc.ld = strtold(token_buf, NULL);
3175 } else {
3176 tok = TOK_CDOUBLE;
3177 tokc.d = strtod(token_buf, NULL);
3180 } else {
3181 unsigned long long n, n1;
3182 int lcount, ucount;
3184 /* integer number */
3185 *q = '\0';
3186 q = token_buf;
3187 if (b == 10 && *q == '0') {
3188 b = 8;
3189 q++;
3191 n = 0;
3192 while(1) {
3193 t = *q++;
3194 /* no need for checks except for base 10 / 8 errors */
3195 if (t == '\0') {
3196 break;
3197 } else if (t >= 'a') {
3198 t = t - 'a' + 10;
3199 } else if (t >= 'A') {
3200 t = t - 'A' + 10;
3201 } else {
3202 t = t - '0';
3203 if (t >= b)
3204 error("invalid digit");
3206 n1 = n;
3207 n = n * b + t;
3208 /* detect overflow */
3209 /* XXX: this test is not reliable */
3210 if (n < n1)
3211 error("integer constant overflow");
3214 /* XXX: not exactly ANSI compliant */
3215 if ((n & 0xffffffff00000000LL) != 0) {
3216 if ((n >> 63) != 0)
3217 tok = TOK_CULLONG;
3218 else
3219 tok = TOK_CLLONG;
3220 } else if (n > 0x7fffffff) {
3221 tok = TOK_CUINT;
3222 } else {
3223 tok = TOK_CINT;
3225 lcount = 0;
3226 ucount = 0;
3227 for(;;) {
3228 t = toup(ch);
3229 if (t == 'L') {
3230 if (lcount >= 2)
3231 error("three 'l's in integer constant");
3232 lcount++;
3233 if (lcount == 2) {
3234 if (tok == TOK_CINT)
3235 tok = TOK_CLLONG;
3236 else if (tok == TOK_CUINT)
3237 tok = TOK_CULLONG;
3239 ch = *p++;
3240 } else if (t == 'U') {
3241 if (ucount >= 1)
3242 error("two 'u's in integer constant");
3243 ucount++;
3244 if (tok == TOK_CINT)
3245 tok = TOK_CUINT;
3246 else if (tok == TOK_CLLONG)
3247 tok = TOK_CULLONG;
3248 ch = *p++;
3249 } else {
3250 break;
3253 if (tok == TOK_CINT || tok == TOK_CUINT)
3254 tokc.ui = n;
3255 else
3256 tokc.ull = n;
3261 #define PARSE2(c1, tok1, c2, tok2) \
3262 case c1: \
3263 PEEKC(c, p); \
3264 if (c == c2) { \
3265 p++; \
3266 tok = tok2; \
3267 } else { \
3268 tok = tok1; \
3270 break;
3272 /* return next token without macro substitution */
3273 static inline void next_nomacro1(void)
3275 int t, c, is_long;
3276 TokenSym *ts;
3277 uint8_t *p, *p1;
3278 unsigned int h;
3280 p = file->buf_ptr;
3281 redo_no_start:
3282 c = *p;
3283 switch(c) {
3284 case ' ':
3285 case '\t':
3286 case '\f':
3287 case '\v':
3288 case '\r':
3289 p++;
3290 goto redo_no_start;
3292 case '\\':
3293 /* first look if it is in fact an end of buffer */
3294 if (p >= file->buf_end) {
3295 file->buf_ptr = p;
3296 handle_eob();
3297 p = file->buf_ptr;
3298 if (p >= file->buf_end)
3299 goto parse_eof;
3300 else
3301 goto redo_no_start;
3302 } else {
3303 file->buf_ptr = p;
3304 ch = *p;
3305 handle_stray();
3306 p = file->buf_ptr;
3307 goto redo_no_start;
3309 parse_eof:
3311 TCCState *s1 = tcc_state;
3312 if (parse_flags & PARSE_FLAG_LINEFEED) {
3313 tok = TOK_LINEFEED;
3314 } else if (s1->include_stack_ptr == s1->include_stack ||
3315 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3316 /* no include left : end of file. */
3317 tok = TOK_EOF;
3318 } else {
3319 /* pop include file */
3321 /* test if previous '#endif' was after a #ifdef at
3322 start of file */
3323 if (tok_flags & TOK_FLAG_ENDIF) {
3324 #ifdef INC_DEBUG
3325 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3326 #endif
3327 add_cached_include(s1, file->inc_type, file->inc_filename,
3328 file->ifndef_macro_saved);
3331 /* add end of include file debug info */
3332 if (do_debug) {
3333 put_stabd(N_EINCL, 0, 0);
3335 /* pop include stack */
3336 tcc_close(file);
3337 s1->include_stack_ptr--;
3338 file = *s1->include_stack_ptr;
3339 p = file->buf_ptr;
3340 goto redo_no_start;
3343 break;
3345 case '\n':
3346 if (parse_flags & PARSE_FLAG_LINEFEED) {
3347 tok = TOK_LINEFEED;
3348 } else {
3349 file->line_num++;
3350 tok_flags |= TOK_FLAG_BOL;
3351 p++;
3352 goto redo_no_start;
3354 break;
3356 case '#':
3357 /* XXX: simplify */
3358 PEEKC(c, p);
3359 if ((tok_flags & TOK_FLAG_BOL) &&
3360 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3361 file->buf_ptr = p;
3362 preprocess(tok_flags & TOK_FLAG_BOF);
3363 p = file->buf_ptr;
3364 goto redo_no_start;
3365 } else {
3366 if (c == '#') {
3367 p++;
3368 tok = TOK_TWOSHARPS;
3369 } else {
3370 tok = '#';
3373 break;
3375 case 'a': case 'b': case 'c': case 'd':
3376 case 'e': case 'f': case 'g': case 'h':
3377 case 'i': case 'j': case 'k': case 'l':
3378 case 'm': case 'n': case 'o': case 'p':
3379 case 'q': case 'r': case 's': case 't':
3380 case 'u': case 'v': case 'w': case 'x':
3381 case 'y': case 'z':
3382 case 'A': case 'B': case 'C': case 'D':
3383 case 'E': case 'F': case 'G': case 'H':
3384 case 'I': case 'J': case 'K':
3385 case 'M': case 'N': case 'O': case 'P':
3386 case 'Q': case 'R': case 'S': case 'T':
3387 case 'U': case 'V': case 'W': case 'X':
3388 case 'Y': case 'Z':
3389 case '_':
3390 parse_ident_fast:
3391 p1 = p;
3392 h = TOK_HASH_INIT;
3393 h = TOK_HASH_FUNC(h, c);
3394 p++;
3395 for(;;) {
3396 c = *p;
3397 if (!isidnum_table[c])
3398 break;
3399 h = TOK_HASH_FUNC(h, c);
3400 p++;
3402 if (c != '\\') {
3403 TokenSym **pts;
3404 int len;
3406 /* fast case : no stray found, so we have the full token
3407 and we have already hashed it */
3408 len = p - p1;
3409 h &= (TOK_HASH_SIZE - 1);
3410 pts = &hash_ident[h];
3411 for(;;) {
3412 ts = *pts;
3413 if (!ts)
3414 break;
3415 if (ts->len == len && !memcmp(ts->str, p1, len))
3416 goto token_found;
3417 pts = &(ts->hash_next);
3419 ts = tok_alloc_new(pts, p1, len);
3420 token_found: ;
3421 } else {
3422 /* slower case */
3423 cstr_reset(&tokcstr);
3425 while (p1 < p) {
3426 cstr_ccat(&tokcstr, *p1);
3427 p1++;
3429 p--;
3430 PEEKC(c, p);
3431 parse_ident_slow:
3432 while (isidnum_table[c]) {
3433 cstr_ccat(&tokcstr, c);
3434 PEEKC(c, p);
3436 ts = tok_alloc(tokcstr.data, tokcstr.size);
3438 tok = ts->tok;
3439 break;
3440 case 'L':
3441 t = p[1];
3442 if (t != '\\' && t != '\'' && t != '\"') {
3443 /* fast case */
3444 goto parse_ident_fast;
3445 } else {
3446 PEEKC(c, p);
3447 if (c == '\'' || c == '\"') {
3448 is_long = 1;
3449 goto str_const;
3450 } else {
3451 cstr_reset(&tokcstr);
3452 cstr_ccat(&tokcstr, 'L');
3453 goto parse_ident_slow;
3456 break;
3457 case '0': case '1': case '2': case '3':
3458 case '4': case '5': case '6': case '7':
3459 case '8': case '9':
3461 cstr_reset(&tokcstr);
3462 /* after the first digit, accept digits, alpha, '.' or sign if
3463 prefixed by 'eEpP' */
3464 parse_num:
3465 for(;;) {
3466 t = c;
3467 cstr_ccat(&tokcstr, c);
3468 PEEKC(c, p);
3469 if (!(isnum(c) || isid(c) || c == '.' ||
3470 ((c == '+' || c == '-') &&
3471 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3472 break;
3474 /* We add a trailing '\0' to ease parsing */
3475 cstr_ccat(&tokcstr, '\0');
3476 tokc.cstr = &tokcstr;
3477 tok = TOK_PPNUM;
3478 break;
3479 case '.':
3480 /* special dot handling because it can also start a number */
3481 PEEKC(c, p);
3482 if (isnum(c)) {
3483 cstr_reset(&tokcstr);
3484 cstr_ccat(&tokcstr, '.');
3485 goto parse_num;
3486 } else if (c == '.') {
3487 PEEKC(c, p);
3488 if (c != '.')
3489 expect("'.'");
3490 PEEKC(c, p);
3491 tok = TOK_DOTS;
3492 } else {
3493 tok = '.';
3495 break;
3496 case '\'':
3497 case '\"':
3498 is_long = 0;
3499 str_const:
3501 CString str;
3502 int sep;
3504 sep = c;
3506 /* parse the string */
3507 cstr_new(&str);
3508 p = parse_pp_string(p, sep, &str);
3509 cstr_ccat(&str, '\0');
3511 /* eval the escape (should be done as TOK_PPNUM) */
3512 cstr_reset(&tokcstr);
3513 parse_escape_string(&tokcstr, str.data, is_long);
3514 cstr_free(&str);
3516 if (sep == '\'') {
3517 int char_size;
3518 /* XXX: make it portable */
3519 if (!is_long)
3520 char_size = 1;
3521 else
3522 char_size = sizeof(int);
3523 if (tokcstr.size <= char_size)
3524 error("empty character constant");
3525 if (tokcstr.size > 2 * char_size)
3526 warning("multi-character character constant");
3527 if (!is_long) {
3528 tokc.i = *(int8_t *)tokcstr.data;
3529 tok = TOK_CCHAR;
3530 } else {
3531 tokc.i = *(int *)tokcstr.data;
3532 tok = TOK_LCHAR;
3534 } else {
3535 tokc.cstr = &tokcstr;
3536 if (!is_long)
3537 tok = TOK_STR;
3538 else
3539 tok = TOK_LSTR;
3542 break;
3544 case '<':
3545 PEEKC(c, p);
3546 if (c == '=') {
3547 p++;
3548 tok = TOK_LE;
3549 } else if (c == '<') {
3550 PEEKC(c, p);
3551 if (c == '=') {
3552 p++;
3553 tok = TOK_A_SHL;
3554 } else {
3555 tok = TOK_SHL;
3557 } else {
3558 tok = TOK_LT;
3560 break;
3562 case '>':
3563 PEEKC(c, p);
3564 if (c == '=') {
3565 p++;
3566 tok = TOK_GE;
3567 } else if (c == '>') {
3568 PEEKC(c, p);
3569 if (c == '=') {
3570 p++;
3571 tok = TOK_A_SAR;
3572 } else {
3573 tok = TOK_SAR;
3575 } else {
3576 tok = TOK_GT;
3578 break;
3580 case '&':
3581 PEEKC(c, p);
3582 if (c == '&') {
3583 p++;
3584 tok = TOK_LAND;
3585 } else if (c == '=') {
3586 p++;
3587 tok = TOK_A_AND;
3588 } else {
3589 tok = '&';
3591 break;
3593 case '|':
3594 PEEKC(c, p);
3595 if (c == '|') {
3596 p++;
3597 tok = TOK_LOR;
3598 } else if (c == '=') {
3599 p++;
3600 tok = TOK_A_OR;
3601 } else {
3602 tok = '|';
3604 break;
3606 case '+':
3607 PEEKC(c, p);
3608 if (c == '+') {
3609 p++;
3610 tok = TOK_INC;
3611 } else if (c == '=') {
3612 p++;
3613 tok = TOK_A_ADD;
3614 } else {
3615 tok = '+';
3617 break;
3619 case '-':
3620 PEEKC(c, p);
3621 if (c == '-') {
3622 p++;
3623 tok = TOK_DEC;
3624 } else if (c == '=') {
3625 p++;
3626 tok = TOK_A_SUB;
3627 } else if (c == '>') {
3628 p++;
3629 tok = TOK_ARROW;
3630 } else {
3631 tok = '-';
3633 break;
3635 PARSE2('!', '!', '=', TOK_NE)
3636 PARSE2('=', '=', '=', TOK_EQ)
3637 PARSE2('*', '*', '=', TOK_A_MUL)
3638 PARSE2('%', '%', '=', TOK_A_MOD)
3639 PARSE2('^', '^', '=', TOK_A_XOR)
3641 /* comments or operator */
3642 case '/':
3643 PEEKC(c, p);
3644 if (c == '*') {
3645 p = parse_comment(p);
3646 goto redo_no_start;
3647 } else if (c == '/') {
3648 p = parse_line_comment(p);
3649 goto redo_no_start;
3650 } else if (c == '=') {
3651 p++;
3652 tok = TOK_A_DIV;
3653 } else {
3654 tok = '/';
3656 break;
3658 /* simple tokens */
3659 case '(':
3660 case ')':
3661 case '[':
3662 case ']':
3663 case '{':
3664 case '}':
3665 case ',':
3666 case ';':
3667 case ':':
3668 case '?':
3669 case '~':
3670 case '$': /* only used in assembler */
3671 tok = c;
3672 p++;
3673 break;
3674 default:
3675 error("unrecognized character \\x%02x", c);
3676 break;
3678 file->buf_ptr = p;
3679 tok_flags = 0;
3680 #if defined(PARSE_DEBUG)
3681 printf("token = %s\n", get_tok_str(tok, &tokc));
3682 #endif
3685 /* return next token without macro substitution. Can read input from
3686 macro_ptr buffer */
3687 static void next_nomacro(void)
3689 if (macro_ptr) {
3690 redo:
3691 tok = *macro_ptr;
3692 if (tok) {
3693 TOK_GET(tok, macro_ptr, tokc);
3694 if (tok == TOK_LINENUM) {
3695 file->line_num = tokc.i;
3696 goto redo;
3699 } else {
3700 next_nomacro1();
3704 /* substitute args in macro_str and return allocated string */
3705 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3707 int *st, last_tok, t, notfirst;
3708 Sym *s;
3709 CValue cval;
3710 TokenString str;
3711 CString cstr;
3713 tok_str_new(&str);
3714 last_tok = 0;
3715 while(1) {
3716 TOK_GET(t, macro_str, cval);
3717 if (!t)
3718 break;
3719 if (t == '#') {
3720 /* stringize */
3721 TOK_GET(t, macro_str, cval);
3722 if (!t)
3723 break;
3724 s = sym_find2(args, t);
3725 if (s) {
3726 cstr_new(&cstr);
3727 st = (int *)s->c;
3728 notfirst = 0;
3729 while (*st) {
3730 if (notfirst)
3731 cstr_ccat(&cstr, ' ');
3732 TOK_GET(t, st, cval);
3733 cstr_cat(&cstr, get_tok_str(t, &cval));
3734 notfirst = 1;
3736 cstr_ccat(&cstr, '\0');
3737 #ifdef PP_DEBUG
3738 printf("stringize: %s\n", (char *)cstr.data);
3739 #endif
3740 /* add string */
3741 cval.cstr = &cstr;
3742 tok_str_add2(&str, TOK_STR, &cval);
3743 cstr_free(&cstr);
3744 } else {
3745 tok_str_add2(&str, t, &cval);
3747 } else if (t >= TOK_IDENT) {
3748 s = sym_find2(args, t);
3749 if (s) {
3750 st = (int *)s->c;
3751 /* if '##' is present before or after, no arg substitution */
3752 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3753 /* special case for var arg macros : ## eats the
3754 ',' if empty VA_ARGS variable. */
3755 /* XXX: test of the ',' is not 100%
3756 reliable. should fix it to avoid security
3757 problems */
3758 if (gnu_ext && s->type.t &&
3759 last_tok == TOK_TWOSHARPS &&
3760 str.len >= 2 && str.str[str.len - 2] == ',') {
3761 if (*st == 0) {
3762 /* suppress ',' '##' */
3763 str.len -= 2;
3764 } else {
3765 /* suppress '##' and add variable */
3766 str.len--;
3767 goto add_var;
3769 } else {
3770 int t1;
3771 add_var:
3772 for(;;) {
3773 TOK_GET(t1, st, cval);
3774 if (!t1)
3775 break;
3776 tok_str_add2(&str, t1, &cval);
3779 } else {
3780 /* NOTE: the stream cannot be read when macro
3781 substituing an argument */
3782 macro_subst(&str, nested_list, st, 0);
3784 } else {
3785 tok_str_add(&str, t);
3787 } else {
3788 tok_str_add2(&str, t, &cval);
3790 last_tok = t;
3792 tok_str_add(&str, 0);
3793 return str.str;
3796 static char const ab_month_name[12][4] =
3798 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3799 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3802 /* do macro substitution of current token with macro 's' and add
3803 result to (tok_str,tok_len). 'nested_list' is the list of all
3804 macros we got inside to avoid recursing. Return non zero if no
3805 substitution needs to be done */
3806 static int macro_subst_tok(TokenString *tok_str,
3807 Sym **nested_list, Sym *s, int can_read_stream)
3809 Sym *args, *sa, *sa1;
3810 int mstr_allocated, parlevel, *mstr, t, t1;
3811 TokenString str;
3812 char *cstrval;
3813 CValue cval;
3814 CString cstr;
3815 char buf[32];
3817 /* if symbol is a macro, prepare substitution */
3819 /* special macros */
3820 if (tok == TOK___LINE__) {
3821 snprintf(buf, sizeof(buf), "%d", file->line_num);
3822 cstrval = buf;
3823 t1 = TOK_PPNUM;
3824 goto add_cstr1;
3825 } else if (tok == TOK___FILE__) {
3826 cstrval = file->filename;
3827 goto add_cstr;
3828 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3829 time_t ti;
3830 struct tm *tm;
3832 time(&ti);
3833 tm = localtime(&ti);
3834 if (tok == TOK___DATE__) {
3835 snprintf(buf, sizeof(buf), "%s %2d %d",
3836 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3837 } else {
3838 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3839 tm->tm_hour, tm->tm_min, tm->tm_sec);
3841 cstrval = buf;
3842 add_cstr:
3843 t1 = TOK_STR;
3844 add_cstr1:
3845 cstr_new(&cstr);
3846 cstr_cat(&cstr, cstrval);
3847 cstr_ccat(&cstr, '\0');
3848 cval.cstr = &cstr;
3849 tok_str_add2(tok_str, t1, &cval);
3850 cstr_free(&cstr);
3851 } else {
3852 mstr = (int *)s->c;
3853 mstr_allocated = 0;
3854 if (s->type.t == MACRO_FUNC) {
3855 /* NOTE: we do not use next_nomacro to avoid eating the
3856 next token. XXX: find better solution */
3857 if (macro_ptr) {
3858 t = *macro_ptr;
3859 if (t == 0 && can_read_stream) {
3860 /* end of macro stream: we must look at the token
3861 after in the file */
3862 macro_ptr = NULL;
3863 goto parse_stream;
3865 } else {
3866 parse_stream:
3867 /* XXX: incorrect with comments */
3868 ch = file->buf_ptr[0];
3869 while (is_space(ch) || ch == '\n')
3870 cinp();
3871 t = ch;
3873 if (t != '(') /* no macro subst */
3874 return -1;
3876 /* argument macro */
3877 next_nomacro();
3878 next_nomacro();
3879 args = NULL;
3880 sa = s->next;
3881 /* NOTE: empty args are allowed, except if no args */
3882 for(;;) {
3883 /* handle '()' case */
3884 if (!args && !sa && tok == ')')
3885 break;
3886 if (!sa)
3887 error("macro '%s' used with too many args",
3888 get_tok_str(s->v, 0));
3889 tok_str_new(&str);
3890 parlevel = 0;
3891 /* NOTE: non zero sa->t indicates VA_ARGS */
3892 while ((parlevel > 0 ||
3893 (tok != ')' &&
3894 (tok != ',' || sa->type.t))) &&
3895 tok != -1) {
3896 if (tok == '(')
3897 parlevel++;
3898 else if (tok == ')')
3899 parlevel--;
3900 tok_str_add2(&str, tok, &tokc);
3901 next_nomacro();
3903 tok_str_add(&str, 0);
3904 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3905 sa = sa->next;
3906 if (tok == ')') {
3907 /* special case for gcc var args: add an empty
3908 var arg argument if it is omitted */
3909 if (sa && sa->type.t && gnu_ext)
3910 continue;
3911 else
3912 break;
3914 if (tok != ',')
3915 expect(",");
3916 next_nomacro();
3918 if (sa) {
3919 error("macro '%s' used with too few args",
3920 get_tok_str(s->v, 0));
3923 /* now subst each arg */
3924 mstr = macro_arg_subst(nested_list, mstr, args);
3925 /* free memory */
3926 sa = args;
3927 while (sa) {
3928 sa1 = sa->prev;
3929 tok_str_free((int *)sa->c);
3930 tcc_free(sa);
3931 sa = sa1;
3933 mstr_allocated = 1;
3935 sym_push2(nested_list, s->v, 0, 0);
3936 macro_subst(tok_str, nested_list, mstr, 1);
3937 /* pop nested defined symbol */
3938 sa1 = *nested_list;
3939 *nested_list = sa1->prev;
3940 tcc_free(sa1);
3941 if (mstr_allocated)
3942 tok_str_free(mstr);
3944 return 0;
3947 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3948 return the resulting string (which must be freed). */
3949 static inline int *macro_twosharps(const int *macro_str)
3951 TokenSym *ts;
3952 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3953 int t;
3954 const char *p1, *p2;
3955 CValue cval;
3956 TokenString macro_str1;
3957 CString cstr;
3959 start_macro_ptr = macro_str;
3960 /* we search the first '##' */
3961 for(;;) {
3962 macro_ptr1 = macro_str;
3963 TOK_GET(t, macro_str, cval);
3964 /* nothing more to do if end of string */
3965 if (t == 0)
3966 return NULL;
3967 if (*macro_str == TOK_TWOSHARPS)
3968 break;
3971 /* we saw '##', so we need more processing to handle it */
3972 cstr_new(&cstr);
3973 tok_str_new(&macro_str1);
3974 tok = t;
3975 tokc = cval;
3977 /* add all tokens seen so far */
3978 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
3979 TOK_GET(t, ptr, cval);
3980 tok_str_add2(&macro_str1, t, &cval);
3982 saved_macro_ptr = macro_ptr;
3983 /* XXX: get rid of the use of macro_ptr here */
3984 macro_ptr = (int *)macro_str;
3985 for(;;) {
3986 while (*macro_ptr == TOK_TWOSHARPS) {
3987 macro_ptr++;
3988 macro_ptr1 = macro_ptr;
3989 t = *macro_ptr;
3990 if (t) {
3991 TOK_GET(t, macro_ptr, cval);
3992 /* We concatenate the two tokens if we have an
3993 identifier or a preprocessing number */
3994 cstr_reset(&cstr);
3995 p1 = get_tok_str(tok, &tokc);
3996 cstr_cat(&cstr, p1);
3997 p2 = get_tok_str(t, &cval);
3998 cstr_cat(&cstr, p2);
3999 cstr_ccat(&cstr, '\0');
4001 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4002 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4003 if (tok == TOK_PPNUM) {
4004 /* if number, then create a number token */
4005 /* NOTE: no need to allocate because
4006 tok_str_add2() does it */
4007 tokc.cstr = &cstr;
4008 } else {
4009 /* if identifier, we must do a test to
4010 validate we have a correct identifier */
4011 if (t == TOK_PPNUM) {
4012 const char *p;
4013 int c;
4015 p = p2;
4016 for(;;) {
4017 c = *p;
4018 if (c == '\0')
4019 break;
4020 p++;
4021 if (!isnum(c) && !isid(c))
4022 goto error_pasting;
4025 ts = tok_alloc(cstr.data, strlen(cstr.data));
4026 tok = ts->tok; /* modify current token */
4028 } else {
4029 const char *str = cstr.data;
4030 const unsigned char *q;
4032 /* we look for a valid token */
4033 /* XXX: do more extensive checks */
4034 if (!strcmp(str, ">>=")) {
4035 tok = TOK_A_SAR;
4036 } else if (!strcmp(str, "<<=")) {
4037 tok = TOK_A_SHL;
4038 } else if (strlen(str) == 2) {
4039 /* search in two bytes table */
4040 q = tok_two_chars;
4041 for(;;) {
4042 if (!*q)
4043 goto error_pasting;
4044 if (q[0] == str[0] && q[1] == str[1])
4045 break;
4046 q += 3;
4048 tok = q[2];
4049 } else {
4050 error_pasting:
4051 /* NOTE: because get_tok_str use a static buffer,
4052 we must save it */
4053 cstr_reset(&cstr);
4054 p1 = get_tok_str(tok, &tokc);
4055 cstr_cat(&cstr, p1);
4056 cstr_ccat(&cstr, '\0');
4057 p2 = get_tok_str(t, &cval);
4058 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4059 /* cannot merge tokens: just add them separately */
4060 tok_str_add2(&macro_str1, tok, &tokc);
4061 /* XXX: free associated memory ? */
4062 tok = t;
4063 tokc = cval;
4068 tok_str_add2(&macro_str1, tok, &tokc);
4069 next_nomacro();
4070 if (tok == 0)
4071 break;
4073 macro_ptr = (int *)saved_macro_ptr;
4074 cstr_free(&cstr);
4075 tok_str_add(&macro_str1, 0);
4076 return macro_str1.str;
4080 /* do macro substitution of macro_str and add result to
4081 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4082 inside to avoid recursing. */
4083 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4084 const int *macro_str, int can_read_stream)
4086 Sym *s;
4087 int *saved_macro_ptr, *macro_str1;
4088 const int *ptr;
4089 int t, ret;
4090 CValue cval;
4092 /* first scan for '##' operator handling */
4093 ptr = macro_str;
4094 macro_str1 = macro_twosharps(ptr);
4095 if (macro_str1)
4096 ptr = macro_str1;
4097 while (1) {
4098 /* NOTE: ptr == NULL can only happen if tokens are read from
4099 file stream due to a macro function call */
4100 if (ptr == NULL)
4101 break;
4102 TOK_GET(t, ptr, cval);
4103 if (t == 0)
4104 break;
4105 s = define_find(t);
4106 if (s != NULL) {
4107 /* if nested substitution, do nothing */
4108 if (sym_find2(*nested_list, t))
4109 goto no_subst;
4110 saved_macro_ptr = macro_ptr;
4111 macro_ptr = (int *)ptr;
4112 tok = t;
4113 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4114 ptr = (int *)macro_ptr;
4115 macro_ptr = saved_macro_ptr;
4116 if (ret != 0)
4117 goto no_subst;
4118 } else {
4119 no_subst:
4120 tok_str_add2(tok_str, t, &cval);
4123 if (macro_str1)
4124 tok_str_free(macro_str1);
4127 /* return next token with macro substitution */
4128 static void next(void)
4130 Sym *nested_list, *s;
4131 TokenString str;
4133 redo:
4134 next_nomacro();
4135 if (!macro_ptr) {
4136 /* if not reading from macro substituted string, then try
4137 to substitute macros */
4138 if (tok >= TOK_IDENT &&
4139 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4140 s = define_find(tok);
4141 if (s) {
4142 /* we have a macro: we try to substitute */
4143 tok_str_new(&str);
4144 nested_list = NULL;
4145 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4146 /* substitution done, NOTE: maybe empty */
4147 tok_str_add(&str, 0);
4148 macro_ptr = str.str;
4149 macro_ptr_allocated = str.str;
4150 goto redo;
4154 } else {
4155 if (tok == 0) {
4156 /* end of macro or end of unget buffer */
4157 if (unget_buffer_enabled) {
4158 macro_ptr = unget_saved_macro_ptr;
4159 unget_buffer_enabled = 0;
4160 } else {
4161 /* end of macro string: free it */
4162 tok_str_free(macro_ptr_allocated);
4163 macro_ptr = NULL;
4165 goto redo;
4169 /* convert preprocessor tokens into C tokens */
4170 if (tok == TOK_PPNUM &&
4171 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4172 parse_number((char *)tokc.cstr->data);
4176 /* push back current token and set current token to 'last_tok'. Only
4177 identifier case handled for labels. */
4178 static inline void unget_tok(int last_tok)
4180 int i, n;
4181 int *q;
4182 unget_saved_macro_ptr = macro_ptr;
4183 unget_buffer_enabled = 1;
4184 q = unget_saved_buffer;
4185 macro_ptr = q;
4186 *q++ = tok;
4187 n = tok_ext_size(tok) - 1;
4188 for(i=0;i<n;i++)
4189 *q++ = tokc.tab[i];
4190 *q = 0; /* end of token string */
4191 tok = last_tok;
4195 void swap(int *p, int *q)
4197 int t;
4198 t = *p;
4199 *p = *q;
4200 *q = t;
4203 void vsetc(CType *type, int r, CValue *vc)
4205 int v;
4207 if (vtop >= vstack + VSTACK_SIZE)
4208 error("memory full");
4209 /* cannot let cpu flags if other instruction are generated. Also
4210 avoid leaving VT_JMP anywhere except on the top of the stack
4211 because it would complicate the code generator. */
4212 if (vtop >= vstack) {
4213 v = vtop->r & VT_VALMASK;
4214 if (v == VT_CMP || (v & ~1) == VT_JMP)
4215 gv(RC_INT);
4217 vtop++;
4218 vtop->type = *type;
4219 vtop->r = r;
4220 vtop->r2 = VT_CONST;
4221 vtop->c = *vc;
4224 /* push integer constant */
4225 void vpushi(int v)
4227 CValue cval;
4228 cval.i = v;
4229 vsetc(&int_type, VT_CONST, &cval);
4232 /* Return a static symbol pointing to a section */
4233 static Sym *get_sym_ref(CType *type, Section *sec,
4234 unsigned long offset, unsigned long size)
4236 int v;
4237 Sym *sym;
4239 v = anon_sym++;
4240 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4241 sym->type.ref = type->ref;
4242 sym->r = VT_CONST | VT_SYM;
4243 put_extern_sym(sym, sec, offset, size);
4244 return sym;
4247 /* push a reference to a section offset by adding a dummy symbol */
4248 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4250 CValue cval;
4252 cval.ul = 0;
4253 vsetc(type, VT_CONST | VT_SYM, &cval);
4254 vtop->sym = get_sym_ref(type, sec, offset, size);
4257 /* define a new external reference to a symbol 'v' of type 'u' */
4258 static Sym *external_global_sym(int v, CType *type, int r)
4260 Sym *s;
4262 s = sym_find(v);
4263 if (!s) {
4264 /* push forward reference */
4265 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4266 s->type.ref = type->ref;
4267 s->r = r | VT_CONST | VT_SYM;
4269 return s;
4272 /* define a new external reference to a symbol 'v' of type 'u' */
4273 static Sym *external_sym(int v, CType *type, int r)
4275 Sym *s;
4277 s = sym_find(v);
4278 if (!s) {
4279 /* push forward reference */
4280 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4281 s->type.t |= VT_EXTERN;
4282 } else {
4283 if (!is_compatible_types(&s->type, type))
4284 error("incompatible types for redefinition of '%s'",
4285 get_tok_str(v, NULL));
4287 return s;
4290 /* push a reference to global symbol v */
4291 static void vpush_global_sym(CType *type, int v)
4293 Sym *sym;
4294 CValue cval;
4296 sym = external_global_sym(v, type, 0);
4297 cval.ul = 0;
4298 vsetc(type, VT_CONST | VT_SYM, &cval);
4299 vtop->sym = sym;
4302 void vset(CType *type, int r, int v)
4304 CValue cval;
4306 cval.i = v;
4307 vsetc(type, r, &cval);
4310 void vseti(int r, int v)
4312 CType type;
4313 type.t = VT_INT;
4314 vset(&type, r, v);
4317 void vswap(void)
4319 SValue tmp;
4321 tmp = vtop[0];
4322 vtop[0] = vtop[-1];
4323 vtop[-1] = tmp;
4326 void vpushv(SValue *v)
4328 if (vtop >= vstack + VSTACK_SIZE)
4329 error("memory full");
4330 vtop++;
4331 *vtop = *v;
4334 void vdup(void)
4336 vpushv(vtop);
4339 /* save r to the memory stack, and mark it as being free */
4340 void save_reg(int r)
4342 int l, saved, size, align;
4343 SValue *p, sv;
4344 CType *type;
4346 /* modify all stack values */
4347 saved = 0;
4348 l = 0;
4349 for(p=vstack;p<=vtop;p++) {
4350 if ((p->r & VT_VALMASK) == r ||
4351 (p->r2 & VT_VALMASK) == r) {
4352 /* must save value on stack if not already done */
4353 if (!saved) {
4354 /* NOTE: must reload 'r' because r might be equal to r2 */
4355 r = p->r & VT_VALMASK;
4356 /* store register in the stack */
4357 type = &p->type;
4358 if ((p->r & VT_LVAL) ||
4359 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4360 type = &int_type;
4361 size = type_size(type, &align);
4362 loc = (loc - size) & -align;
4363 sv.type.t = type->t;
4364 sv.r = VT_LOCAL | VT_LVAL;
4365 sv.c.ul = loc;
4366 store(r, &sv);
4367 #ifdef TCC_TARGET_I386
4368 /* x86 specific: need to pop fp register ST0 if saved */
4369 if (r == TREG_ST0) {
4370 o(0xd9dd); /* fstp %st(1) */
4372 #endif
4373 /* special long long case */
4374 if ((type->t & VT_BTYPE) == VT_LLONG) {
4375 sv.c.ul += 4;
4376 store(p->r2, &sv);
4378 l = loc;
4379 saved = 1;
4381 /* mark that stack entry as being saved on the stack */
4382 if (p->r & VT_LVAL) {
4383 /* also clear the bounded flag because the
4384 relocation address of the function was stored in
4385 p->c.ul */
4386 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4387 } else {
4388 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4390 p->r2 = VT_CONST;
4391 p->c.ul = l;
4396 /* find a register of class 'rc2' with at most one reference on stack.
4397 * If none, call get_reg(rc) */
4398 int get_reg_ex(int rc, int rc2)
4400 int r;
4401 SValue *p;
4403 for(r=0;r<NB_REGS;r++) {
4404 if (reg_classes[r] & rc2) {
4405 int n;
4406 n=0;
4407 for(p = vstack; p <= vtop; p++) {
4408 if ((p->r & VT_VALMASK) == r ||
4409 (p->r2 & VT_VALMASK) == r)
4410 n++;
4412 if (n <= 1)
4413 return r;
4416 return get_reg(rc);
4419 /* find a free register of class 'rc'. If none, save one register */
4420 int get_reg(int rc)
4422 int r;
4423 SValue *p;
4425 /* find a free register */
4426 for(r=0;r<NB_REGS;r++) {
4427 if (reg_classes[r] & rc) {
4428 for(p=vstack;p<=vtop;p++) {
4429 if ((p->r & VT_VALMASK) == r ||
4430 (p->r2 & VT_VALMASK) == r)
4431 goto notfound;
4433 return r;
4435 notfound: ;
4438 /* no register left : free the first one on the stack (VERY
4439 IMPORTANT to start from the bottom to ensure that we don't
4440 spill registers used in gen_opi()) */
4441 for(p=vstack;p<=vtop;p++) {
4442 r = p->r & VT_VALMASK;
4443 if (r < VT_CONST && (reg_classes[r] & rc))
4444 goto save_found;
4445 /* also look at second register (if long long) */
4446 r = p->r2 & VT_VALMASK;
4447 if (r < VT_CONST && (reg_classes[r] & rc)) {
4448 save_found:
4449 save_reg(r);
4450 return r;
4453 /* Should never comes here */
4454 return -1;
4457 /* save registers up to (vtop - n) stack entry */
4458 void save_regs(int n)
4460 int r;
4461 SValue *p, *p1;
4462 p1 = vtop - n;
4463 for(p = vstack;p <= p1; p++) {
4464 r = p->r & VT_VALMASK;
4465 if (r < VT_CONST) {
4466 save_reg(r);
4471 /* move register 's' to 'r', and flush previous value of r to memory
4472 if needed */
4473 void move_reg(int r, int s)
4475 SValue sv;
4477 if (r != s) {
4478 save_reg(r);
4479 sv.type.t = VT_INT;
4480 sv.r = s;
4481 sv.c.ul = 0;
4482 load(r, &sv);
4486 /* get address of vtop (vtop MUST BE an lvalue) */
4487 void gaddrof(void)
4489 vtop->r &= ~VT_LVAL;
4490 /* tricky: if saved lvalue, then we can go back to lvalue */
4491 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4492 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4495 #ifdef CONFIG_TCC_BCHECK
4496 /* generate lvalue bound code */
4497 void gbound(void)
4499 int lval_type;
4500 CType type1;
4502 vtop->r &= ~VT_MUSTBOUND;
4503 /* if lvalue, then use checking code before dereferencing */
4504 if (vtop->r & VT_LVAL) {
4505 /* if not VT_BOUNDED value, then make one */
4506 if (!(vtop->r & VT_BOUNDED)) {
4507 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4508 /* must save type because we must set it to int to get pointer */
4509 type1 = vtop->type;
4510 vtop->type.t = VT_INT;
4511 gaddrof();
4512 vpushi(0);
4513 gen_bounded_ptr_add();
4514 vtop->r |= lval_type;
4515 vtop->type = type1;
4517 /* then check for dereferencing */
4518 gen_bounded_ptr_deref();
4521 #endif
4523 /* store vtop a register belonging to class 'rc'. lvalues are
4524 converted to values. Cannot be used if cannot be converted to
4525 register value (such as structures). */
4526 int gv(int rc)
4528 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4529 unsigned long long ll;
4531 /* NOTE: get_reg can modify vstack[] */
4532 if (vtop->type.t & VT_BITFIELD) {
4533 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4534 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4535 /* remove bit field info to avoid loops */
4536 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4537 /* generate shifts */
4538 vpushi(32 - (bit_pos + bit_size));
4539 gen_op(TOK_SHL);
4540 vpushi(32 - bit_size);
4541 /* NOTE: transformed to SHR if unsigned */
4542 gen_op(TOK_SAR);
4543 r = gv(rc);
4544 } else {
4545 if (is_float(vtop->type.t) &&
4546 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4547 Sym *sym;
4548 int *ptr;
4549 unsigned long offset;
4551 /* XXX: unify with initializers handling ? */
4552 /* CPUs usually cannot use float constants, so we store them
4553 generically in data segment */
4554 size = type_size(&vtop->type, &align);
4555 offset = (data_section->data_offset + align - 1) & -align;
4556 data_section->data_offset = offset;
4557 /* XXX: not portable yet */
4558 ptr = section_ptr_add(data_section, size);
4559 size = size >> 2;
4560 for(i=0;i<size;i++)
4561 ptr[i] = vtop->c.tab[i];
4562 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4563 vtop->r |= VT_LVAL | VT_SYM;
4564 vtop->sym = sym;
4565 vtop->c.ul = 0;
4567 #ifdef CONFIG_TCC_BCHECK
4568 if (vtop->r & VT_MUSTBOUND)
4569 gbound();
4570 #endif
4572 r = vtop->r & VT_VALMASK;
4573 /* need to reload if:
4574 - constant
4575 - lvalue (need to dereference pointer)
4576 - already a register, but not in the right class */
4577 if (r >= VT_CONST ||
4578 (vtop->r & VT_LVAL) ||
4579 !(reg_classes[r] & rc) ||
4580 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4581 !(reg_classes[vtop->r2] & rc))) {
4582 r = get_reg(rc);
4583 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4584 /* two register type load : expand to two words
4585 temporarily */
4586 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4587 /* load constant */
4588 ll = vtop->c.ull;
4589 vtop->c.ui = ll; /* first word */
4590 load(r, vtop);
4591 vtop->r = r; /* save register value */
4592 vpushi(ll >> 32); /* second word */
4593 } else if (r >= VT_CONST ||
4594 (vtop->r & VT_LVAL)) {
4595 /* load from memory */
4596 load(r, vtop);
4597 vdup();
4598 vtop[-1].r = r; /* save register value */
4599 /* increment pointer to get second word */
4600 vtop->type.t = VT_INT;
4601 gaddrof();
4602 vpushi(4);
4603 gen_op('+');
4604 vtop->r |= VT_LVAL;
4605 } else {
4606 /* move registers */
4607 load(r, vtop);
4608 vdup();
4609 vtop[-1].r = r; /* save register value */
4610 vtop->r = vtop[-1].r2;
4612 /* allocate second register */
4613 rc2 = RC_INT;
4614 if (rc == RC_IRET)
4615 rc2 = RC_LRET;
4616 r2 = get_reg(rc2);
4617 load(r2, vtop);
4618 vpop();
4619 /* write second register */
4620 vtop->r2 = r2;
4621 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4622 int t1, t;
4623 /* lvalue of scalar type : need to use lvalue type
4624 because of possible cast */
4625 t = vtop->type.t;
4626 t1 = t;
4627 /* compute memory access type */
4628 if (vtop->r & VT_LVAL_BYTE)
4629 t = VT_BYTE;
4630 else if (vtop->r & VT_LVAL_SHORT)
4631 t = VT_SHORT;
4632 if (vtop->r & VT_LVAL_UNSIGNED)
4633 t |= VT_UNSIGNED;
4634 vtop->type.t = t;
4635 load(r, vtop);
4636 /* restore wanted type */
4637 vtop->type.t = t1;
4638 } else {
4639 /* one register type load */
4640 load(r, vtop);
4643 vtop->r = r;
4644 #ifdef TCC_TARGET_C67
4645 /* uses register pairs for doubles */
4646 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4647 vtop->r2 = r+1;
4648 #endif
4650 return r;
4653 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4654 void gv2(int rc1, int rc2)
4656 int v;
4658 /* generate more generic register first. But VT_JMP or VT_CMP
4659 values must be generated first in all cases to avoid possible
4660 reload errors */
4661 v = vtop[0].r & VT_VALMASK;
4662 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4663 vswap();
4664 gv(rc1);
4665 vswap();
4666 gv(rc2);
4667 /* test if reload is needed for first register */
4668 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4669 vswap();
4670 gv(rc1);
4671 vswap();
4673 } else {
4674 gv(rc2);
4675 vswap();
4676 gv(rc1);
4677 vswap();
4678 /* test if reload is needed for first register */
4679 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4680 gv(rc2);
4685 /* expand long long on stack in two int registers */
4686 void lexpand(void)
4688 int u;
4690 u = vtop->type.t & VT_UNSIGNED;
4691 gv(RC_INT);
4692 vdup();
4693 vtop[0].r = vtop[-1].r2;
4694 vtop[0].r2 = VT_CONST;
4695 vtop[-1].r2 = VT_CONST;
4696 vtop[0].type.t = VT_INT | u;
4697 vtop[-1].type.t = VT_INT | u;
4700 #ifdef TCC_TARGET_ARM
4701 /* expand long long on stack */
4702 void lexpand_nr(void)
4704 int u,v;
4706 u = vtop->type.t & VT_UNSIGNED;
4707 vdup();
4708 vtop->r2 = VT_CONST;
4709 vtop->type.t = VT_INT | u;
4710 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4711 if (v == VT_CONST) {
4712 vtop[-1].c.ui = vtop->c.ull;
4713 vtop->c.ui = vtop->c.ull >> 32;
4714 vtop->r = VT_CONST;
4715 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4716 vtop->c.ui += 4;
4717 vtop->r = vtop[-1].r;
4718 } else if (v > VT_CONST) {
4719 vtop--;
4720 lexpand();
4721 } else
4722 vtop->r = vtop[-1].r2;
4723 vtop[-1].r2 = VT_CONST;
4724 vtop[-1].type.t = VT_INT | u;
4726 #endif
4728 /* build a long long from two ints */
4729 void lbuild(int t)
4731 gv2(RC_INT, RC_INT);
4732 vtop[-1].r2 = vtop[0].r;
4733 vtop[-1].type.t = t;
4734 vpop();
4737 /* rotate n first stack elements to the bottom
4738 I1 ... In -> I2 ... In I1 [top is right]
4740 void vrotb(int n)
4742 int i;
4743 SValue tmp;
4745 tmp = vtop[-n + 1];
4746 for(i=-n+1;i!=0;i++)
4747 vtop[i] = vtop[i+1];
4748 vtop[0] = tmp;
4751 /* rotate n first stack elements to the top
4752 I1 ... In -> In I1 ... I(n-1) [top is right]
4754 void vrott(int n)
4756 int i;
4757 SValue tmp;
4759 tmp = vtop[0];
4760 for(i = 0;i < n - 1; i++)
4761 vtop[-i] = vtop[-i - 1];
4762 vtop[-n + 1] = tmp;
4765 #ifdef TCC_TARGET_ARM
4766 /* like vrott but in other direction
4767 In ... I1 -> I(n-1) ... I1 In [top is right]
4769 void vnrott(int n)
4771 int i;
4772 SValue tmp;
4774 tmp = vtop[-n + 1];
4775 for(i = n - 1; i > 0; i--)
4776 vtop[-i] = vtop[-i + 1];
4777 vtop[0] = tmp;
4779 #endif
4781 /* pop stack value */
4782 void vpop(void)
4784 int v;
4785 v = vtop->r & VT_VALMASK;
4786 #ifdef TCC_TARGET_I386
4787 /* for x86, we need to pop the FP stack */
4788 if (v == TREG_ST0 && !nocode_wanted) {
4789 o(0xd9dd); /* fstp %st(1) */
4790 } else
4791 #endif
4792 if (v == VT_JMP || v == VT_JMPI) {
4793 /* need to put correct jump if && or || without test */
4794 gsym(vtop->c.ul);
4796 vtop--;
4799 /* convert stack entry to register and duplicate its value in another
4800 register */
4801 void gv_dup(void)
4803 int rc, t, r, r1;
4804 SValue sv;
4806 t = vtop->type.t;
4807 if ((t & VT_BTYPE) == VT_LLONG) {
4808 lexpand();
4809 gv_dup();
4810 vswap();
4811 vrotb(3);
4812 gv_dup();
4813 vrotb(4);
4814 /* stack: H L L1 H1 */
4815 lbuild(t);
4816 vrotb(3);
4817 vrotb(3);
4818 vswap();
4819 lbuild(t);
4820 vswap();
4821 } else {
4822 /* duplicate value */
4823 rc = RC_INT;
4824 sv.type.t = VT_INT;
4825 if (is_float(t)) {
4826 rc = RC_FLOAT;
4827 sv.type.t = t;
4829 r = gv(rc);
4830 r1 = get_reg(rc);
4831 sv.r = r;
4832 sv.c.ul = 0;
4833 load(r1, &sv); /* move r to r1 */
4834 vdup();
4835 /* duplicates value */
4836 vtop->r = r1;
4840 /* generate CPU independent (unsigned) long long operations */
4841 void gen_opl(int op)
4843 int t, a, b, op1, c, i;
4844 int func;
4845 SValue tmp;
4847 switch(op) {
4848 case '/':
4849 case TOK_PDIV:
4850 func = TOK___divdi3;
4851 goto gen_func;
4852 case TOK_UDIV:
4853 func = TOK___udivdi3;
4854 goto gen_func;
4855 case '%':
4856 func = TOK___moddi3;
4857 goto gen_func;
4858 case TOK_UMOD:
4859 func = TOK___umoddi3;
4860 gen_func:
4861 /* call generic long long function */
4862 vpush_global_sym(&func_old_type, func);
4863 vrott(3);
4864 gfunc_call(2);
4865 vpushi(0);
4866 vtop->r = REG_IRET;
4867 vtop->r2 = REG_LRET;
4868 break;
4869 case '^':
4870 case '&':
4871 case '|':
4872 case '*':
4873 case '+':
4874 case '-':
4875 t = vtop->type.t;
4876 vswap();
4877 lexpand();
4878 vrotb(3);
4879 lexpand();
4880 /* stack: L1 H1 L2 H2 */
4881 tmp = vtop[0];
4882 vtop[0] = vtop[-3];
4883 vtop[-3] = tmp;
4884 tmp = vtop[-2];
4885 vtop[-2] = vtop[-3];
4886 vtop[-3] = tmp;
4887 vswap();
4888 /* stack: H1 H2 L1 L2 */
4889 if (op == '*') {
4890 vpushv(vtop - 1);
4891 vpushv(vtop - 1);
4892 gen_op(TOK_UMULL);
4893 lexpand();
4894 /* stack: H1 H2 L1 L2 ML MH */
4895 for(i=0;i<4;i++)
4896 vrotb(6);
4897 /* stack: ML MH H1 H2 L1 L2 */
4898 tmp = vtop[0];
4899 vtop[0] = vtop[-2];
4900 vtop[-2] = tmp;
4901 /* stack: ML MH H1 L2 H2 L1 */
4902 gen_op('*');
4903 vrotb(3);
4904 vrotb(3);
4905 gen_op('*');
4906 /* stack: ML MH M1 M2 */
4907 gen_op('+');
4908 gen_op('+');
4909 } else if (op == '+' || op == '-') {
4910 /* XXX: add non carry method too (for MIPS or alpha) */
4911 if (op == '+')
4912 op1 = TOK_ADDC1;
4913 else
4914 op1 = TOK_SUBC1;
4915 gen_op(op1);
4916 /* stack: H1 H2 (L1 op L2) */
4917 vrotb(3);
4918 vrotb(3);
4919 gen_op(op1 + 1); /* TOK_xxxC2 */
4920 } else {
4921 gen_op(op);
4922 /* stack: H1 H2 (L1 op L2) */
4923 vrotb(3);
4924 vrotb(3);
4925 /* stack: (L1 op L2) H1 H2 */
4926 gen_op(op);
4927 /* stack: (L1 op L2) (H1 op H2) */
4929 /* stack: L H */
4930 lbuild(t);
4931 break;
4932 case TOK_SAR:
4933 case TOK_SHR:
4934 case TOK_SHL:
4935 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4936 t = vtop[-1].type.t;
4937 vswap();
4938 lexpand();
4939 vrotb(3);
4940 /* stack: L H shift */
4941 c = (int)vtop->c.i;
4942 /* constant: simpler */
4943 /* NOTE: all comments are for SHL. the other cases are
4944 done by swaping words */
4945 vpop();
4946 if (op != TOK_SHL)
4947 vswap();
4948 if (c >= 32) {
4949 /* stack: L H */
4950 vpop();
4951 if (c > 32) {
4952 vpushi(c - 32);
4953 gen_op(op);
4955 if (op != TOK_SAR) {
4956 vpushi(0);
4957 } else {
4958 gv_dup();
4959 vpushi(31);
4960 gen_op(TOK_SAR);
4962 vswap();
4963 } else {
4964 vswap();
4965 gv_dup();
4966 /* stack: H L L */
4967 vpushi(c);
4968 gen_op(op);
4969 vswap();
4970 vpushi(32 - c);
4971 if (op == TOK_SHL)
4972 gen_op(TOK_SHR);
4973 else
4974 gen_op(TOK_SHL);
4975 vrotb(3);
4976 /* stack: L L H */
4977 vpushi(c);
4978 if (op == TOK_SHL)
4979 gen_op(TOK_SHL);
4980 else
4981 gen_op(TOK_SHR);
4982 gen_op('|');
4984 if (op != TOK_SHL)
4985 vswap();
4986 lbuild(t);
4987 } else {
4988 /* XXX: should provide a faster fallback on x86 ? */
4989 switch(op) {
4990 case TOK_SAR:
4991 func = TOK___sardi3;
4992 goto gen_func;
4993 case TOK_SHR:
4994 func = TOK___shrdi3;
4995 goto gen_func;
4996 case TOK_SHL:
4997 func = TOK___shldi3;
4998 goto gen_func;
5001 break;
5002 default:
5003 /* compare operations */
5004 t = vtop->type.t;
5005 vswap();
5006 lexpand();
5007 vrotb(3);
5008 lexpand();
5009 /* stack: L1 H1 L2 H2 */
5010 tmp = vtop[-1];
5011 vtop[-1] = vtop[-2];
5012 vtop[-2] = tmp;
5013 /* stack: L1 L2 H1 H2 */
5014 /* compare high */
5015 op1 = op;
5016 /* when values are equal, we need to compare low words. since
5017 the jump is inverted, we invert the test too. */
5018 if (op1 == TOK_LT)
5019 op1 = TOK_LE;
5020 else if (op1 == TOK_GT)
5021 op1 = TOK_GE;
5022 else if (op1 == TOK_ULT)
5023 op1 = TOK_ULE;
5024 else if (op1 == TOK_UGT)
5025 op1 = TOK_UGE;
5026 a = 0;
5027 b = 0;
5028 gen_op(op1);
5029 if (op1 != TOK_NE) {
5030 a = gtst(1, 0);
5032 if (op != TOK_EQ) {
5033 /* generate non equal test */
5034 /* XXX: NOT PORTABLE yet */
5035 if (a == 0) {
5036 b = gtst(0, 0);
5037 } else {
5038 #if defined(TCC_TARGET_I386)
5039 b = psym(0x850f, 0);
5040 #elif defined(TCC_TARGET_ARM)
5041 b = ind;
5042 o(0x1A000000 | encbranch(ind, 0, 1));
5043 #elif defined(TCC_TARGET_C67)
5044 error("not implemented");
5045 #else
5046 #error not supported
5047 #endif
5050 /* compare low. Always unsigned */
5051 op1 = op;
5052 if (op1 == TOK_LT)
5053 op1 = TOK_ULT;
5054 else if (op1 == TOK_LE)
5055 op1 = TOK_ULE;
5056 else if (op1 == TOK_GT)
5057 op1 = TOK_UGT;
5058 else if (op1 == TOK_GE)
5059 op1 = TOK_UGE;
5060 gen_op(op1);
5061 a = gtst(1, a);
5062 gsym(b);
5063 vseti(VT_JMPI, a);
5064 break;
5068 /* handle integer constant optimizations and various machine
5069 independent opt */
5070 void gen_opic(int op)
5072 int fc, c1, c2, n;
5073 SValue *v1, *v2;
5075 v1 = vtop - 1;
5076 v2 = vtop;
5077 /* currently, we cannot do computations with forward symbols */
5078 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5079 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5080 if (c1 && c2) {
5081 fc = v2->c.i;
5082 switch(op) {
5083 case '+': v1->c.i += fc; break;
5084 case '-': v1->c.i -= fc; break;
5085 case '&': v1->c.i &= fc; break;
5086 case '^': v1->c.i ^= fc; break;
5087 case '|': v1->c.i |= fc; break;
5088 case '*': v1->c.i *= fc; break;
5090 case TOK_PDIV:
5091 case '/':
5092 case '%':
5093 case TOK_UDIV:
5094 case TOK_UMOD:
5095 /* if division by zero, generate explicit division */
5096 if (fc == 0) {
5097 if (const_wanted)
5098 error("division by zero in constant");
5099 goto general_case;
5101 switch(op) {
5102 default: v1->c.i /= fc; break;
5103 case '%': v1->c.i %= fc; break;
5104 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5105 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5107 break;
5108 case TOK_SHL: v1->c.i <<= fc; break;
5109 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5110 case TOK_SAR: v1->c.i >>= fc; break;
5111 /* tests */
5112 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5113 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5114 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5115 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5116 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5117 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5118 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5119 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5120 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5121 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5122 /* logical */
5123 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5124 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5125 default:
5126 goto general_case;
5128 vtop--;
5129 } else {
5130 /* if commutative ops, put c2 as constant */
5131 if (c1 && (op == '+' || op == '&' || op == '^' ||
5132 op == '|' || op == '*')) {
5133 vswap();
5134 swap(&c1, &c2);
5136 fc = vtop->c.i;
5137 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5138 op == TOK_PDIV) &&
5139 fc == 1) ||
5140 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5141 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5142 fc == 0) ||
5143 (op == '&' &&
5144 fc == -1))) {
5145 /* nothing to do */
5146 vtop--;
5147 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5148 /* try to use shifts instead of muls or divs */
5149 if (fc > 0 && (fc & (fc - 1)) == 0) {
5150 n = -1;
5151 while (fc) {
5152 fc >>= 1;
5153 n++;
5155 vtop->c.i = n;
5156 if (op == '*')
5157 op = TOK_SHL;
5158 else if (op == TOK_PDIV)
5159 op = TOK_SAR;
5160 else
5161 op = TOK_SHR;
5163 goto general_case;
5164 } else if (c2 && (op == '+' || op == '-') &&
5165 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5166 (VT_CONST | VT_SYM)) {
5167 /* symbol + constant case */
5168 if (op == '-')
5169 fc = -fc;
5170 vtop--;
5171 vtop->c.i += fc;
5172 } else {
5173 general_case:
5174 if (!nocode_wanted) {
5175 /* call low level op generator */
5176 gen_opi(op);
5177 } else {
5178 vtop--;
5184 /* generate a floating point operation with constant propagation */
5185 void gen_opif(int op)
5187 int c1, c2;
5188 SValue *v1, *v2;
5189 long double f1, f2;
5191 v1 = vtop - 1;
5192 v2 = vtop;
5193 /* currently, we cannot do computations with forward symbols */
5194 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5195 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5196 if (c1 && c2) {
5197 if (v1->type.t == VT_FLOAT) {
5198 f1 = v1->c.f;
5199 f2 = v2->c.f;
5200 } else if (v1->type.t == VT_DOUBLE) {
5201 f1 = v1->c.d;
5202 f2 = v2->c.d;
5203 } else {
5204 f1 = v1->c.ld;
5205 f2 = v2->c.ld;
5208 /* NOTE: we only do constant propagation if finite number (not
5209 NaN or infinity) (ANSI spec) */
5210 if (!ieee_finite(f1) || !ieee_finite(f2))
5211 goto general_case;
5213 switch(op) {
5214 case '+': f1 += f2; break;
5215 case '-': f1 -= f2; break;
5216 case '*': f1 *= f2; break;
5217 case '/':
5218 if (f2 == 0.0) {
5219 if (const_wanted)
5220 error("division by zero in constant");
5221 goto general_case;
5223 f1 /= f2;
5224 break;
5225 /* XXX: also handles tests ? */
5226 default:
5227 goto general_case;
5229 /* XXX: overflow test ? */
5230 if (v1->type.t == VT_FLOAT) {
5231 v1->c.f = f1;
5232 } else if (v1->type.t == VT_DOUBLE) {
5233 v1->c.d = f1;
5234 } else {
5235 v1->c.ld = f1;
5237 vtop--;
5238 } else {
5239 general_case:
5240 if (!nocode_wanted) {
5241 gen_opf(op);
5242 } else {
5243 vtop--;
5248 static int pointed_size(CType *type)
5250 int align;
5251 return type_size(pointed_type(type), &align);
5254 static inline int is_null_pointer(SValue *p)
5256 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5257 return 0;
5258 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5259 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5262 static inline int is_integer_btype(int bt)
5264 return (bt == VT_BYTE || bt == VT_SHORT ||
5265 bt == VT_INT || bt == VT_LLONG);
5268 /* check types for comparison or substraction of pointers */
5269 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5271 CType *type1, *type2, tmp_type1, tmp_type2;
5272 int bt1, bt2;
5274 /* null pointers are accepted for all comparisons as gcc */
5275 if (is_null_pointer(p1) || is_null_pointer(p2))
5276 return;
5277 type1 = &p1->type;
5278 type2 = &p2->type;
5279 bt1 = type1->t & VT_BTYPE;
5280 bt2 = type2->t & VT_BTYPE;
5281 /* accept comparison between pointer and integer with a warning */
5282 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5283 warning("comparison between pointer and integer");
5284 return;
5287 /* both must be pointers or implicit function pointers */
5288 if (bt1 == VT_PTR) {
5289 type1 = pointed_type(type1);
5290 } else if (bt1 != VT_FUNC)
5291 goto invalid_operands;
5293 if (bt2 == VT_PTR) {
5294 type2 = pointed_type(type2);
5295 } else if (bt2 != VT_FUNC) {
5296 invalid_operands:
5297 error("invalid operands to binary %s", get_tok_str(op, NULL));
5299 if ((type1->t & VT_BTYPE) == VT_VOID ||
5300 (type2->t & VT_BTYPE) == VT_VOID)
5301 return;
5302 tmp_type1 = *type1;
5303 tmp_type2 = *type2;
5304 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5305 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5306 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5307 /* gcc-like error if '-' is used */
5308 if (op == '-')
5309 goto invalid_operands;
5310 else
5311 warning("comparison of distinct pointer types lacks a cast");
5315 /* generic gen_op: handles types problems */
5316 void gen_op(int op)
5318 int u, t1, t2, bt1, bt2, t;
5319 CType type1;
5321 t1 = vtop[-1].type.t;
5322 t2 = vtop[0].type.t;
5323 bt1 = t1 & VT_BTYPE;
5324 bt2 = t2 & VT_BTYPE;
5326 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5327 /* at least one operand is a pointer */
5328 /* relationnal op: must be both pointers */
5329 if (op >= TOK_ULT && op <= TOK_GT) {
5330 check_comparison_pointer_types(vtop - 1, vtop, op);
5331 /* pointers are handled are unsigned */
5332 t = VT_INT | VT_UNSIGNED;
5333 goto std_op;
5335 /* if both pointers, then it must be the '-' op */
5336 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5337 if (op != '-')
5338 error("cannot use pointers here");
5339 check_comparison_pointer_types(vtop - 1, vtop, op);
5340 /* XXX: check that types are compatible */
5341 u = pointed_size(&vtop[-1].type);
5342 gen_opic(op);
5343 /* set to integer type */
5344 vtop->type.t = VT_INT;
5345 vpushi(u);
5346 gen_op(TOK_PDIV);
5347 } else {
5348 /* exactly one pointer : must be '+' or '-'. */
5349 if (op != '-' && op != '+')
5350 error("cannot use pointers here");
5351 /* Put pointer as first operand */
5352 if (bt2 == VT_PTR) {
5353 vswap();
5354 swap(&t1, &t2);
5356 type1 = vtop[-1].type;
5357 /* XXX: cast to int ? (long long case) */
5358 vpushi(pointed_size(&vtop[-1].type));
5359 gen_op('*');
5360 #ifdef CONFIG_TCC_BCHECK
5361 /* if evaluating constant expression, no code should be
5362 generated, so no bound check */
5363 if (do_bounds_check && !const_wanted) {
5364 /* if bounded pointers, we generate a special code to
5365 test bounds */
5366 if (op == '-') {
5367 vpushi(0);
5368 vswap();
5369 gen_op('-');
5371 gen_bounded_ptr_add();
5372 } else
5373 #endif
5375 gen_opic(op);
5377 /* put again type if gen_opic() swaped operands */
5378 vtop->type = type1;
5380 } else if (is_float(bt1) || is_float(bt2)) {
5381 /* compute bigger type and do implicit casts */
5382 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5383 t = VT_LDOUBLE;
5384 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5385 t = VT_DOUBLE;
5386 } else {
5387 t = VT_FLOAT;
5389 /* floats can only be used for a few operations */
5390 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5391 (op < TOK_ULT || op > TOK_GT))
5392 error("invalid operands for binary operation");
5393 goto std_op;
5394 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5395 /* cast to biggest op */
5396 t = VT_LLONG;
5397 /* convert to unsigned if it does not fit in a long long */
5398 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5399 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5400 t |= VT_UNSIGNED;
5401 goto std_op;
5402 } else {
5403 /* integer operations */
5404 t = VT_INT;
5405 /* convert to unsigned if it does not fit in an integer */
5406 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5407 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5408 t |= VT_UNSIGNED;
5409 std_op:
5410 /* XXX: currently, some unsigned operations are explicit, so
5411 we modify them here */
5412 if (t & VT_UNSIGNED) {
5413 if (op == TOK_SAR)
5414 op = TOK_SHR;
5415 else if (op == '/')
5416 op = TOK_UDIV;
5417 else if (op == '%')
5418 op = TOK_UMOD;
5419 else if (op == TOK_LT)
5420 op = TOK_ULT;
5421 else if (op == TOK_GT)
5422 op = TOK_UGT;
5423 else if (op == TOK_LE)
5424 op = TOK_ULE;
5425 else if (op == TOK_GE)
5426 op = TOK_UGE;
5428 vswap();
5429 type1.t = t;
5430 gen_cast(&type1);
5431 vswap();
5432 /* special case for shifts and long long: we keep the shift as
5433 an integer */
5434 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5435 type1.t = VT_INT;
5436 gen_cast(&type1);
5437 if (is_float(t))
5438 gen_opif(op);
5439 else if ((t & VT_BTYPE) == VT_LLONG)
5440 gen_opl(op);
5441 else
5442 gen_opic(op);
5443 if (op >= TOK_ULT && op <= TOK_GT) {
5444 /* relationnal op: the result is an int */
5445 vtop->type.t = VT_INT;
5446 } else {
5447 vtop->type.t = t;
5452 /* generic itof for unsigned long long case */
5453 void gen_cvt_itof1(int t)
5455 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5456 (VT_LLONG | VT_UNSIGNED)) {
5458 if (t == VT_FLOAT)
5459 vpush_global_sym(&func_old_type, TOK___ulltof);
5460 else if (t == VT_DOUBLE)
5461 vpush_global_sym(&func_old_type, TOK___ulltod);
5462 else
5463 vpush_global_sym(&func_old_type, TOK___ulltold);
5464 vrott(2);
5465 gfunc_call(1);
5466 vpushi(0);
5467 vtop->r = REG_FRET;
5468 } else {
5469 gen_cvt_itof(t);
5473 /* generic ftoi for unsigned long long case */
5474 void gen_cvt_ftoi1(int t)
5476 int st;
5478 if (t == (VT_LLONG | VT_UNSIGNED)) {
5479 /* not handled natively */
5480 st = vtop->type.t & VT_BTYPE;
5481 if (st == VT_FLOAT)
5482 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5483 else if (st == VT_DOUBLE)
5484 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5485 else
5486 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5487 vrott(2);
5488 gfunc_call(1);
5489 vpushi(0);
5490 vtop->r = REG_IRET;
5491 vtop->r2 = REG_LRET;
5492 } else {
5493 gen_cvt_ftoi(t);
5497 /* force char or short cast */
5498 void force_charshort_cast(int t)
5500 int bits, dbt;
5501 dbt = t & VT_BTYPE;
5502 /* XXX: add optimization if lvalue : just change type and offset */
5503 if (dbt == VT_BYTE)
5504 bits = 8;
5505 else
5506 bits = 16;
5507 if (t & VT_UNSIGNED) {
5508 vpushi((1 << bits) - 1);
5509 gen_op('&');
5510 } else {
5511 bits = 32 - bits;
5512 vpushi(bits);
5513 gen_op(TOK_SHL);
5514 vpushi(bits);
5515 gen_op(TOK_SAR);
5519 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5520 static void gen_cast(CType *type)
5522 int sbt, dbt, sf, df, c;
5524 /* special delayed cast for char/short */
5525 /* XXX: in some cases (multiple cascaded casts), it may still
5526 be incorrect */
5527 if (vtop->r & VT_MUSTCAST) {
5528 vtop->r &= ~VT_MUSTCAST;
5529 force_charshort_cast(vtop->type.t);
5532 /* bitfields first get cast to ints */
5533 if (vtop->type.t & VT_BITFIELD) {
5534 gv(RC_INT);
5537 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5538 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5540 if (sbt != dbt && !nocode_wanted) {
5541 sf = is_float(sbt);
5542 df = is_float(dbt);
5543 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5544 if (sf && df) {
5545 /* convert from fp to fp */
5546 if (c) {
5547 /* constant case: we can do it now */
5548 /* XXX: in ISOC, cannot do it if error in convert */
5549 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5550 vtop->c.f = (float)vtop->c.d;
5551 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5552 vtop->c.f = (float)vtop->c.ld;
5553 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5554 vtop->c.d = (double)vtop->c.f;
5555 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5556 vtop->c.d = (double)vtop->c.ld;
5557 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5558 vtop->c.ld = (long double)vtop->c.f;
5559 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5560 vtop->c.ld = (long double)vtop->c.d;
5561 } else {
5562 /* non constant case: generate code */
5563 gen_cvt_ftof(dbt);
5565 } else if (df) {
5566 /* convert int to fp */
5567 if (c) {
5568 switch(sbt) {
5569 case VT_LLONG | VT_UNSIGNED:
5570 case VT_LLONG:
5571 /* XXX: add const cases for long long */
5572 goto do_itof;
5573 case VT_INT | VT_UNSIGNED:
5574 switch(dbt) {
5575 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5576 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5577 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5579 break;
5580 default:
5581 switch(dbt) {
5582 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5583 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5584 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5586 break;
5588 } else {
5589 do_itof:
5590 #if !defined(TCC_TARGET_ARM)
5591 gen_cvt_itof1(dbt);
5592 #else
5593 gen_cvt_itof(dbt);
5594 #endif
5596 } else if (sf) {
5597 /* convert fp to int */
5598 /* we handle char/short/etc... with generic code */
5599 if (dbt != (VT_INT | VT_UNSIGNED) &&
5600 dbt != (VT_LLONG | VT_UNSIGNED) &&
5601 dbt != VT_LLONG)
5602 dbt = VT_INT;
5603 if (c) {
5604 switch(dbt) {
5605 case VT_LLONG | VT_UNSIGNED:
5606 case VT_LLONG:
5607 /* XXX: add const cases for long long */
5608 goto do_ftoi;
5609 case VT_INT | VT_UNSIGNED:
5610 switch(sbt) {
5611 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5612 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5613 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5615 break;
5616 default:
5617 /* int case */
5618 switch(sbt) {
5619 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5620 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5621 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5623 break;
5625 } else {
5626 do_ftoi:
5627 gen_cvt_ftoi1(dbt);
5629 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5630 /* additional cast for char/short/bool... */
5631 vtop->type.t = dbt;
5632 gen_cast(type);
5634 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5635 if ((sbt & VT_BTYPE) != VT_LLONG) {
5636 /* scalar to long long */
5637 if (c) {
5638 if (sbt == (VT_INT | VT_UNSIGNED))
5639 vtop->c.ll = vtop->c.ui;
5640 else
5641 vtop->c.ll = vtop->c.i;
5642 } else {
5643 /* machine independent conversion */
5644 gv(RC_INT);
5645 /* generate high word */
5646 if (sbt == (VT_INT | VT_UNSIGNED)) {
5647 vpushi(0);
5648 gv(RC_INT);
5649 } else {
5650 gv_dup();
5651 vpushi(31);
5652 gen_op(TOK_SAR);
5654 /* patch second register */
5655 vtop[-1].r2 = vtop->r;
5656 vpop();
5659 } else if (dbt == VT_BOOL) {
5660 /* scalar to bool */
5661 vpushi(0);
5662 gen_op(TOK_NE);
5663 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5664 (dbt & VT_BTYPE) == VT_SHORT) {
5665 force_charshort_cast(dbt);
5666 } else if ((dbt & VT_BTYPE) == VT_INT) {
5667 /* scalar to int */
5668 if (sbt == VT_LLONG) {
5669 /* from long long: just take low order word */
5670 lexpand();
5671 vpop();
5673 /* if lvalue and single word type, nothing to do because
5674 the lvalue already contains the real type size (see
5675 VT_LVAL_xxx constants) */
5678 vtop->type = *type;
5681 /* return type size. Put alignment at 'a' */
5682 static int type_size(CType *type, int *a)
5684 Sym *s;
5685 int bt;
5687 bt = type->t & VT_BTYPE;
5688 if (bt == VT_STRUCT) {
5689 /* struct/union */
5690 s = type->ref;
5691 *a = s->r;
5692 return s->c;
5693 } else if (bt == VT_PTR) {
5694 if (type->t & VT_ARRAY) {
5695 s = type->ref;
5696 return type_size(&s->type, a) * s->c;
5697 } else {
5698 *a = PTR_SIZE;
5699 return PTR_SIZE;
5701 } else if (bt == VT_LDOUBLE) {
5702 *a = LDOUBLE_ALIGN;
5703 return LDOUBLE_SIZE;
5704 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5705 #ifdef TCC_TARGET_I386
5706 *a = 4;
5707 #else
5708 *a = 8;
5709 #endif
5710 return 8;
5711 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5712 *a = 4;
5713 return 4;
5714 } else if (bt == VT_SHORT) {
5715 *a = 2;
5716 return 2;
5717 } else {
5718 /* char, void, function, _Bool */
5719 *a = 1;
5720 return 1;
5724 /* return the pointed type of t */
5725 static inline CType *pointed_type(CType *type)
5727 return &type->ref->type;
5730 /* modify type so that its it is a pointer to type. */
5731 static void mk_pointer(CType *type)
5733 Sym *s;
5734 s = sym_push(SYM_FIELD, type, 0, -1);
5735 type->t = VT_PTR | (type->t & ~VT_TYPE);
5736 type->ref = s;
5739 /* compare function types. OLD functions match any new functions */
5740 static int is_compatible_func(CType *type1, CType *type2)
5742 Sym *s1, *s2;
5744 s1 = type1->ref;
5745 s2 = type2->ref;
5746 if (!is_compatible_types(&s1->type, &s2->type))
5747 return 0;
5748 /* XXX: not complete */
5749 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5750 return 1;
5751 if (s1->c != s2->c)
5752 return 0;
5753 while (s1 != NULL) {
5754 if (s2 == NULL)
5755 return 0;
5756 if (!is_compatible_types(&s1->type, &s2->type))
5757 return 0;
5758 s1 = s1->next;
5759 s2 = s2->next;
5761 if (s2)
5762 return 0;
5763 return 1;
5766 /* return true if type1 and type2 are exactly the same (including
5767 qualifiers).
5769 - enums are not checked as gcc __builtin_types_compatible_p ()
5771 static int is_compatible_types(CType *type1, CType *type2)
5773 int bt1, t1, t2;
5775 t1 = type1->t & VT_TYPE;
5776 t2 = type2->t & VT_TYPE;
5777 /* XXX: bitfields ? */
5778 if (t1 != t2)
5779 return 0;
5780 /* test more complicated cases */
5781 bt1 = t1 & VT_BTYPE;
5782 if (bt1 == VT_PTR) {
5783 type1 = pointed_type(type1);
5784 type2 = pointed_type(type2);
5785 return is_compatible_types(type1, type2);
5786 } else if (bt1 == VT_STRUCT) {
5787 return (type1->ref == type2->ref);
5788 } else if (bt1 == VT_FUNC) {
5789 return is_compatible_func(type1, type2);
5790 } else {
5791 return 1;
5795 /* print a type. If 'varstr' is not NULL, then the variable is also
5796 printed in the type */
5797 /* XXX: union */
5798 /* XXX: add array and function pointers */
5799 void type_to_str(char *buf, int buf_size,
5800 CType *type, const char *varstr)
5802 int bt, v, t;
5803 Sym *s, *sa;
5804 char buf1[256];
5805 const char *tstr;
5807 t = type->t & VT_TYPE;
5808 bt = t & VT_BTYPE;
5809 buf[0] = '\0';
5810 if (t & VT_CONSTANT)
5811 pstrcat(buf, buf_size, "const ");
5812 if (t & VT_VOLATILE)
5813 pstrcat(buf, buf_size, "volatile ");
5814 if (t & VT_UNSIGNED)
5815 pstrcat(buf, buf_size, "unsigned ");
5816 switch(bt) {
5817 case VT_VOID:
5818 tstr = "void";
5819 goto add_tstr;
5820 case VT_BOOL:
5821 tstr = "_Bool";
5822 goto add_tstr;
5823 case VT_BYTE:
5824 tstr = "char";
5825 goto add_tstr;
5826 case VT_SHORT:
5827 tstr = "short";
5828 goto add_tstr;
5829 case VT_INT:
5830 tstr = "int";
5831 goto add_tstr;
5832 case VT_LONG:
5833 tstr = "long";
5834 goto add_tstr;
5835 case VT_LLONG:
5836 tstr = "long long";
5837 goto add_tstr;
5838 case VT_FLOAT:
5839 tstr = "float";
5840 goto add_tstr;
5841 case VT_DOUBLE:
5842 tstr = "double";
5843 goto add_tstr;
5844 case VT_LDOUBLE:
5845 tstr = "long double";
5846 add_tstr:
5847 pstrcat(buf, buf_size, tstr);
5848 break;
5849 case VT_ENUM:
5850 case VT_STRUCT:
5851 if (bt == VT_STRUCT)
5852 tstr = "struct ";
5853 else
5854 tstr = "enum ";
5855 pstrcat(buf, buf_size, tstr);
5856 v = type->ref->v & ~SYM_STRUCT;
5857 if (v >= SYM_FIRST_ANOM)
5858 pstrcat(buf, buf_size, "<anonymous>");
5859 else
5860 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5861 break;
5862 case VT_FUNC:
5863 s = type->ref;
5864 type_to_str(buf, buf_size, &s->type, varstr);
5865 pstrcat(buf, buf_size, "(");
5866 sa = s->next;
5867 while (sa != NULL) {
5868 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5869 pstrcat(buf, buf_size, buf1);
5870 sa = sa->next;
5871 if (sa)
5872 pstrcat(buf, buf_size, ", ");
5874 pstrcat(buf, buf_size, ")");
5875 goto no_var;
5876 case VT_PTR:
5877 s = type->ref;
5878 pstrcpy(buf1, sizeof(buf1), "*");
5879 if (varstr)
5880 pstrcat(buf1, sizeof(buf1), varstr);
5881 type_to_str(buf, buf_size, &s->type, buf1);
5882 goto no_var;
5884 if (varstr) {
5885 pstrcat(buf, buf_size, " ");
5886 pstrcat(buf, buf_size, varstr);
5888 no_var: ;
5891 /* verify type compatibility to store vtop in 'dt' type, and generate
5892 casts if needed. */
5893 static void gen_assign_cast(CType *dt)
5895 CType *st, *type1, *type2, tmp_type1, tmp_type2;
5896 char buf1[256], buf2[256];
5897 int dbt, sbt;
5899 st = &vtop->type; /* source type */
5900 dbt = dt->t & VT_BTYPE;
5901 sbt = st->t & VT_BTYPE;
5902 if (dt->t & VT_CONSTANT)
5903 warning("assignment of read-only location");
5904 switch(dbt) {
5905 case VT_PTR:
5906 /* special cases for pointers */
5907 /* '0' can also be a pointer */
5908 if (is_null_pointer(vtop))
5909 goto type_ok;
5910 /* accept implicit pointer to integer cast with warning */
5911 if (is_integer_btype(sbt)) {
5912 warning("assignment makes pointer from integer without a cast");
5913 goto type_ok;
5915 type1 = pointed_type(dt);
5916 /* a function is implicitely a function pointer */
5917 if (sbt == VT_FUNC) {
5918 if ((type1->t & VT_BTYPE) != VT_VOID &&
5919 !is_compatible_types(pointed_type(dt), st))
5920 goto error;
5921 else
5922 goto type_ok;
5924 if (sbt != VT_PTR)
5925 goto error;
5926 type2 = pointed_type(st);
5927 if ((type1->t & VT_BTYPE) == VT_VOID ||
5928 (type2->t & VT_BTYPE) == VT_VOID) {
5929 /* void * can match anything */
5930 } else {
5931 /* exact type match, except for unsigned */
5932 tmp_type1 = *type1;
5933 tmp_type2 = *type2;
5934 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5935 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5936 if (!is_compatible_types(&tmp_type1, &tmp_type2))
5937 goto error;
5939 /* check const and volatile */
5940 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
5941 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
5942 warning("assignment discards qualifiers from pointer target type");
5943 break;
5944 case VT_BYTE:
5945 case VT_SHORT:
5946 case VT_INT:
5947 case VT_LLONG:
5948 if (sbt == VT_PTR || sbt == VT_FUNC) {
5949 warning("assignment makes integer from pointer without a cast");
5951 /* XXX: more tests */
5952 break;
5953 case VT_STRUCT:
5954 tmp_type1 = *dt;
5955 tmp_type2 = *st;
5956 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
5957 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
5958 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5959 error:
5960 type_to_str(buf1, sizeof(buf1), st, NULL);
5961 type_to_str(buf2, sizeof(buf2), dt, NULL);
5962 error("cannot cast '%s' to '%s'", buf1, buf2);
5964 break;
5966 type_ok:
5967 gen_cast(dt);
5970 /* store vtop in lvalue pushed on stack */
5971 void vstore(void)
5973 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5975 ft = vtop[-1].type.t;
5976 sbt = vtop->type.t & VT_BTYPE;
5977 dbt = ft & VT_BTYPE;
5978 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5979 (sbt == VT_INT && dbt == VT_SHORT)) {
5980 /* optimize char/short casts */
5981 delayed_cast = VT_MUSTCAST;
5982 vtop->type.t = ft & VT_TYPE;
5983 /* XXX: factorize */
5984 if (ft & VT_CONSTANT)
5985 warning("assignment of read-only location");
5986 } else {
5987 delayed_cast = 0;
5988 gen_assign_cast(&vtop[-1].type);
5991 if (sbt == VT_STRUCT) {
5992 /* if structure, only generate pointer */
5993 /* structure assignment : generate memcpy */
5994 /* XXX: optimize if small size */
5995 if (!nocode_wanted) {
5996 size = type_size(&vtop->type, &align);
5998 vpush_global_sym(&func_old_type, TOK_memcpy);
6000 /* destination */
6001 vpushv(vtop - 2);
6002 vtop->type.t = VT_INT;
6003 gaddrof();
6004 /* source */
6005 vpushv(vtop - 2);
6006 vtop->type.t = VT_INT;
6007 gaddrof();
6008 /* type size */
6009 vpushi(size);
6010 gfunc_call(3);
6012 vswap();
6013 vpop();
6014 } else {
6015 vswap();
6016 vpop();
6018 /* leave source on stack */
6019 } else if (ft & VT_BITFIELD) {
6020 /* bitfield store handling */
6021 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6022 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6023 /* remove bit field info to avoid loops */
6024 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6026 /* duplicate destination */
6027 vdup();
6028 vtop[-1] = vtop[-2];
6030 /* mask and shift source */
6031 vpushi((1 << bit_size) - 1);
6032 gen_op('&');
6033 vpushi(bit_pos);
6034 gen_op(TOK_SHL);
6035 /* load destination, mask and or with source */
6036 vswap();
6037 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6038 gen_op('&');
6039 gen_op('|');
6040 /* store result */
6041 vstore();
6042 } else {
6043 #ifdef CONFIG_TCC_BCHECK
6044 /* bound check case */
6045 if (vtop[-1].r & VT_MUSTBOUND) {
6046 vswap();
6047 gbound();
6048 vswap();
6050 #endif
6051 if (!nocode_wanted) {
6052 rc = RC_INT;
6053 if (is_float(ft))
6054 rc = RC_FLOAT;
6055 r = gv(rc); /* generate value */
6056 /* if lvalue was saved on stack, must read it */
6057 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6058 SValue sv;
6059 t = get_reg(RC_INT);
6060 sv.type.t = VT_INT;
6061 sv.r = VT_LOCAL | VT_LVAL;
6062 sv.c.ul = vtop[-1].c.ul;
6063 load(t, &sv);
6064 vtop[-1].r = t | VT_LVAL;
6066 store(r, vtop - 1);
6067 /* two word case handling : store second register at word + 4 */
6068 if ((ft & VT_BTYPE) == VT_LLONG) {
6069 vswap();
6070 /* convert to int to increment easily */
6071 vtop->type.t = VT_INT;
6072 gaddrof();
6073 vpushi(4);
6074 gen_op('+');
6075 vtop->r |= VT_LVAL;
6076 vswap();
6077 /* XXX: it works because r2 is spilled last ! */
6078 store(vtop->r2, vtop - 1);
6081 vswap();
6082 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6083 vtop->r |= delayed_cast;
6087 /* post defines POST/PRE add. c is the token ++ or -- */
6088 void inc(int post, int c)
6090 test_lvalue();
6091 vdup(); /* save lvalue */
6092 if (post) {
6093 gv_dup(); /* duplicate value */
6094 vrotb(3);
6095 vrotb(3);
6097 /* add constant */
6098 vpushi(c - TOK_MID);
6099 gen_op('+');
6100 vstore(); /* store value */
6101 if (post)
6102 vpop(); /* if post op, return saved value */
6105 /* Parse GNUC __attribute__ extension. Currently, the following
6106 extensions are recognized:
6107 - aligned(n) : set data/function alignment.
6108 - section(x) : generate data/code in this section.
6109 - unused : currently ignored, but may be used someday.
6111 static void parse_attribute(AttributeDef *ad)
6113 int t, n;
6115 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6116 next();
6117 skip('(');
6118 skip('(');
6119 while (tok != ')') {
6120 if (tok < TOK_IDENT)
6121 expect("attribute name");
6122 t = tok;
6123 next();
6124 switch(t) {
6125 case TOK_SECTION1:
6126 case TOK_SECTION2:
6127 skip('(');
6128 if (tok != TOK_STR)
6129 expect("section name");
6130 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6131 next();
6132 skip(')');
6133 break;
6134 case TOK_ALIGNED1:
6135 case TOK_ALIGNED2:
6136 if (tok == '(') {
6137 next();
6138 n = expr_const();
6139 if (n <= 0 || (n & (n - 1)) != 0)
6140 error("alignment must be a positive power of two");
6141 skip(')');
6142 } else {
6143 n = MAX_ALIGN;
6145 ad->aligned = n;
6146 break;
6147 case TOK_UNUSED1:
6148 case TOK_UNUSED2:
6149 /* currently, no need to handle it because tcc does not
6150 track unused objects */
6151 break;
6152 case TOK_NORETURN1:
6153 case TOK_NORETURN2:
6154 /* currently, no need to handle it because tcc does not
6155 track unused objects */
6156 break;
6157 case TOK_CDECL1:
6158 case TOK_CDECL2:
6159 case TOK_CDECL3:
6160 ad->func_call = FUNC_CDECL;
6161 break;
6162 case TOK_STDCALL1:
6163 case TOK_STDCALL2:
6164 case TOK_STDCALL3:
6165 ad->func_call = FUNC_STDCALL;
6166 break;
6167 default:
6168 if (tcc_state->warn_unsupported)
6169 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6170 /* skip parameters */
6171 /* XXX: skip parenthesis too */
6172 if (tok == '(') {
6173 next();
6174 while (tok != ')' && tok != -1)
6175 next();
6176 next();
6178 break;
6180 if (tok != ',')
6181 break;
6182 next();
6184 skip(')');
6185 skip(')');
6189 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6190 static void struct_decl(CType *type, int u)
6192 int a, v, size, align, maxalign, c, offset;
6193 int bit_size, bit_pos, bsize, bt, lbit_pos;
6194 Sym *s, *ss, **ps;
6195 AttributeDef ad;
6196 CType type1, btype;
6198 a = tok; /* save decl type */
6199 next();
6200 if (tok != '{') {
6201 v = tok;
6202 next();
6203 /* struct already defined ? return it */
6204 if (v < TOK_IDENT)
6205 expect("struct/union/enum name");
6206 s = struct_find(v);
6207 if (s) {
6208 if (s->type.t != a)
6209 error("invalid type");
6210 goto do_decl;
6212 } else {
6213 v = anon_sym++;
6215 type1.t = a;
6216 /* we put an undefined size for struct/union */
6217 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6218 s->r = 0; /* default alignment is zero as gcc */
6219 /* put struct/union/enum name in type */
6220 do_decl:
6221 type->t = u;
6222 type->ref = s;
6224 if (tok == '{') {
6225 next();
6226 if (s->c != -1)
6227 error("struct/union/enum already defined");
6228 /* cannot be empty */
6229 c = 0;
6230 /* non empty enums are not allowed */
6231 if (a == TOK_ENUM) {
6232 for(;;) {
6233 v = tok;
6234 if (v < TOK_UIDENT)
6235 expect("identifier");
6236 next();
6237 if (tok == '=') {
6238 next();
6239 c = expr_const();
6241 /* enum symbols have static storage */
6242 ss = sym_push(v, &int_type, VT_CONST, c);
6243 ss->type.t |= VT_STATIC;
6244 if (tok != ',')
6245 break;
6246 next();
6247 c++;
6248 /* NOTE: we accept a trailing comma */
6249 if (tok == '}')
6250 break;
6252 skip('}');
6253 } else {
6254 maxalign = 1;
6255 ps = &s->next;
6256 bit_pos = 0;
6257 offset = 0;
6258 while (tok != '}') {
6259 parse_btype(&btype, &ad);
6260 while (1) {
6261 bit_size = -1;
6262 v = 0;
6263 type1 = btype;
6264 if (tok != ':') {
6265 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6266 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6267 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6268 error("invalid type for '%s'",
6269 get_tok_str(v, NULL));
6271 if (tok == ':') {
6272 next();
6273 bit_size = expr_const();
6274 /* XXX: handle v = 0 case for messages */
6275 if (bit_size < 0)
6276 error("negative width in bit-field '%s'",
6277 get_tok_str(v, NULL));
6278 if (v && bit_size == 0)
6279 error("zero width for bit-field '%s'",
6280 get_tok_str(v, NULL));
6282 size = type_size(&type1, &align);
6283 lbit_pos = 0;
6284 if (bit_size >= 0) {
6285 bt = type1.t & VT_BTYPE;
6286 if (bt != VT_INT &&
6287 bt != VT_BYTE &&
6288 bt != VT_SHORT &&
6289 bt != VT_ENUM)
6290 error("bitfields must have scalar type");
6291 bsize = size * 8;
6292 if (bit_size > bsize) {
6293 error("width of '%s' exceeds its type",
6294 get_tok_str(v, NULL));
6295 } else if (bit_size == bsize) {
6296 /* no need for bit fields */
6297 bit_pos = 0;
6298 } else if (bit_size == 0) {
6299 /* XXX: what to do if only padding in a
6300 structure ? */
6301 /* zero size: means to pad */
6302 if (bit_pos > 0)
6303 bit_pos = bsize;
6304 } else {
6305 /* we do not have enough room ? */
6306 if ((bit_pos + bit_size) > bsize)
6307 bit_pos = 0;
6308 lbit_pos = bit_pos;
6309 /* XXX: handle LSB first */
6310 type1.t |= VT_BITFIELD |
6311 (bit_pos << VT_STRUCT_SHIFT) |
6312 (bit_size << (VT_STRUCT_SHIFT + 6));
6313 bit_pos += bit_size;
6315 } else {
6316 bit_pos = 0;
6318 if (v) {
6319 /* add new memory data only if starting
6320 bit field */
6321 if (lbit_pos == 0) {
6322 if (a == TOK_STRUCT) {
6323 c = (c + align - 1) & -align;
6324 offset = c;
6325 c += size;
6326 } else {
6327 offset = 0;
6328 if (size > c)
6329 c = size;
6331 if (align > maxalign)
6332 maxalign = align;
6334 #if 0
6335 printf("add field %s offset=%d",
6336 get_tok_str(v, NULL), offset);
6337 if (type1.t & VT_BITFIELD) {
6338 printf(" pos=%d size=%d",
6339 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6340 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6342 printf("\n");
6343 #endif
6344 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6345 *ps = ss;
6346 ps = &ss->next;
6348 if (tok == ';' || tok == TOK_EOF)
6349 break;
6350 skip(',');
6352 skip(';');
6354 skip('}');
6355 /* store size and alignment */
6356 s->c = (c + maxalign - 1) & -maxalign;
6357 s->r = maxalign;
6362 /* return 0 if no type declaration. otherwise, return the basic type
6363 and skip it.
6365 static int parse_btype(CType *type, AttributeDef *ad)
6367 int t, u, type_found, typespec_found;
6368 Sym *s;
6369 CType type1;
6371 memset(ad, 0, sizeof(AttributeDef));
6372 type_found = 0;
6373 typespec_found = 0;
6374 t = 0;
6375 while(1) {
6376 switch(tok) {
6377 case TOK_EXTENSION:
6378 /* currently, we really ignore extension */
6379 next();
6380 continue;
6382 /* basic types */
6383 case TOK_CHAR:
6384 u = VT_BYTE;
6385 basic_type:
6386 next();
6387 basic_type1:
6388 if ((t & VT_BTYPE) != 0)
6389 error("too many basic types");
6390 t |= u;
6391 typespec_found = 1;
6392 break;
6393 case TOK_VOID:
6394 u = VT_VOID;
6395 goto basic_type;
6396 case TOK_SHORT:
6397 u = VT_SHORT;
6398 goto basic_type;
6399 case TOK_INT:
6400 next();
6401 typespec_found = 1;
6402 break;
6403 case TOK_LONG:
6404 next();
6405 if ((t & VT_BTYPE) == VT_DOUBLE) {
6406 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6407 } else if ((t & VT_BTYPE) == VT_LONG) {
6408 t = (t & ~VT_BTYPE) | VT_LLONG;
6409 } else {
6410 u = VT_LONG;
6411 goto basic_type1;
6413 break;
6414 case TOK_BOOL:
6415 u = VT_BOOL;
6416 goto basic_type;
6417 case TOK_FLOAT:
6418 u = VT_FLOAT;
6419 goto basic_type;
6420 case TOK_DOUBLE:
6421 next();
6422 if ((t & VT_BTYPE) == VT_LONG) {
6423 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6424 } else {
6425 u = VT_DOUBLE;
6426 goto basic_type1;
6428 break;
6429 case TOK_ENUM:
6430 struct_decl(&type1, VT_ENUM);
6431 basic_type2:
6432 u = type1.t;
6433 type->ref = type1.ref;
6434 goto basic_type1;
6435 case TOK_STRUCT:
6436 case TOK_UNION:
6437 struct_decl(&type1, VT_STRUCT);
6438 goto basic_type2;
6440 /* type modifiers */
6441 case TOK_CONST1:
6442 case TOK_CONST2:
6443 case TOK_CONST3:
6444 t |= VT_CONSTANT;
6445 next();
6446 break;
6447 case TOK_VOLATILE1:
6448 case TOK_VOLATILE2:
6449 case TOK_VOLATILE3:
6450 t |= VT_VOLATILE;
6451 next();
6452 break;
6453 case TOK_SIGNED1:
6454 case TOK_SIGNED2:
6455 case TOK_SIGNED3:
6456 typespec_found = 1;
6457 t |= VT_SIGNED;
6458 next();
6459 break;
6460 case TOK_REGISTER:
6461 case TOK_AUTO:
6462 case TOK_RESTRICT1:
6463 case TOK_RESTRICT2:
6464 case TOK_RESTRICT3:
6465 next();
6466 break;
6467 case TOK_UNSIGNED:
6468 t |= VT_UNSIGNED;
6469 next();
6470 typespec_found = 1;
6471 break;
6473 /* storage */
6474 case TOK_EXTERN:
6475 t |= VT_EXTERN;
6476 next();
6477 break;
6478 case TOK_STATIC:
6479 t |= VT_STATIC;
6480 next();
6481 break;
6482 case TOK_TYPEDEF:
6483 t |= VT_TYPEDEF;
6484 next();
6485 break;
6486 case TOK_INLINE1:
6487 case TOK_INLINE2:
6488 case TOK_INLINE3:
6489 t |= VT_INLINE;
6490 next();
6491 break;
6493 /* GNUC attribute */
6494 case TOK_ATTRIBUTE1:
6495 case TOK_ATTRIBUTE2:
6496 parse_attribute(ad);
6497 break;
6498 /* GNUC typeof */
6499 case TOK_TYPEOF1:
6500 case TOK_TYPEOF2:
6501 case TOK_TYPEOF3:
6502 next();
6503 parse_expr_type(&type1);
6504 goto basic_type2;
6505 default:
6506 if (typespec_found)
6507 goto the_end;
6508 s = sym_find(tok);
6509 if (!s || !(s->type.t & VT_TYPEDEF))
6510 goto the_end;
6511 t |= (s->type.t & ~VT_TYPEDEF);
6512 type->ref = s->type.ref;
6513 next();
6514 break;
6516 type_found = 1;
6518 the_end:
6519 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6520 error("signed and unsigned modifier");
6521 if (tcc_state->char_is_unsigned) {
6522 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6523 t |= VT_UNSIGNED;
6525 t &= ~VT_SIGNED;
6527 /* long is never used as type */
6528 if ((t & VT_BTYPE) == VT_LONG)
6529 t = (t & ~VT_BTYPE) | VT_INT;
6530 type->t = t;
6531 return type_found;
6534 /* convert a function parameter type (array to pointer and function to
6535 function pointer) */
6536 static inline void convert_parameter_type(CType *pt)
6538 /* array must be transformed to pointer according to ANSI C */
6539 pt->t &= ~VT_ARRAY;
6540 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6541 mk_pointer(pt);
6545 static void post_type(CType *type, AttributeDef *ad)
6547 int n, l, t1;
6548 Sym **plast, *s, *first;
6549 AttributeDef ad1;
6550 CType pt;
6552 if (tok == '(') {
6553 /* function declaration */
6554 next();
6555 l = 0;
6556 first = NULL;
6557 plast = &first;
6558 while (tok != ')') {
6559 /* read param name and compute offset */
6560 if (l != FUNC_OLD) {
6561 if (!parse_btype(&pt, &ad1)) {
6562 if (l) {
6563 error("invalid type");
6564 } else {
6565 l = FUNC_OLD;
6566 goto old_proto;
6569 l = FUNC_NEW;
6570 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6571 break;
6572 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6573 if ((pt.t & VT_BTYPE) == VT_VOID)
6574 error("parameter declared as void");
6575 } else {
6576 old_proto:
6577 n = tok;
6578 pt.t = VT_INT;
6579 next();
6581 convert_parameter_type(&pt);
6582 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6583 *plast = s;
6584 plast = &s->next;
6585 if (tok == ',') {
6586 next();
6587 if (l == FUNC_NEW && tok == TOK_DOTS) {
6588 l = FUNC_ELLIPSIS;
6589 next();
6590 break;
6594 /* if no parameters, then old type prototype */
6595 if (l == 0)
6596 l = FUNC_OLD;
6597 skip(')');
6598 t1 = type->t & VT_STORAGE;
6599 /* NOTE: const is ignored in returned type as it has a special
6600 meaning in gcc / C++ */
6601 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6602 post_type(type, ad);
6603 /* we push a anonymous symbol which will contain the function prototype */
6604 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6605 s->next = first;
6606 type->t = t1 | VT_FUNC;
6607 type->ref = s;
6608 } else if (tok == '[') {
6609 /* array definition */
6610 next();
6611 n = -1;
6612 if (tok != ']') {
6613 n = expr_const();
6614 if (n < 0)
6615 error("invalid array size");
6617 skip(']');
6618 /* parse next post type */
6619 t1 = type->t & VT_STORAGE;
6620 type->t &= ~VT_STORAGE;
6621 post_type(type, ad);
6623 /* we push a anonymous symbol which will contain the array
6624 element type */
6625 s = sym_push(SYM_FIELD, type, 0, n);
6626 type->t = t1 | VT_ARRAY | VT_PTR;
6627 type->ref = s;
6631 /* Parse a type declaration (except basic type), and return the type
6632 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6633 expected. 'type' should contain the basic type. 'ad' is the
6634 attribute definition of the basic type. It can be modified by
6635 type_decl().
6637 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6639 Sym *s;
6640 CType type1, *type2;
6641 int qualifiers;
6643 while (tok == '*') {
6644 qualifiers = 0;
6645 redo:
6646 next();
6647 switch(tok) {
6648 case TOK_CONST1:
6649 case TOK_CONST2:
6650 case TOK_CONST3:
6651 qualifiers |= VT_CONSTANT;
6652 goto redo;
6653 case TOK_VOLATILE1:
6654 case TOK_VOLATILE2:
6655 case TOK_VOLATILE3:
6656 qualifiers |= VT_VOLATILE;
6657 goto redo;
6658 case TOK_RESTRICT1:
6659 case TOK_RESTRICT2:
6660 case TOK_RESTRICT3:
6661 goto redo;
6663 mk_pointer(type);
6664 type->t |= qualifiers;
6667 /* XXX: clarify attribute handling */
6668 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6669 parse_attribute(ad);
6671 /* recursive type */
6672 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6673 type1.t = 0; /* XXX: same as int */
6674 if (tok == '(') {
6675 next();
6676 /* XXX: this is not correct to modify 'ad' at this point, but
6677 the syntax is not clear */
6678 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6679 parse_attribute(ad);
6680 type_decl(&type1, ad, v, td);
6681 skip(')');
6682 } else {
6683 /* type identifier */
6684 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6685 *v = tok;
6686 next();
6687 } else {
6688 if (!(td & TYPE_ABSTRACT))
6689 expect("identifier");
6690 *v = 0;
6693 post_type(type, ad);
6694 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6695 parse_attribute(ad);
6696 if (!type1.t)
6697 return;
6698 /* append type at the end of type1 */
6699 type2 = &type1;
6700 for(;;) {
6701 s = type2->ref;
6702 type2 = &s->type;
6703 if (!type2->t) {
6704 *type2 = *type;
6705 break;
6708 *type = type1;
6711 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6712 static int lvalue_type(int t)
6714 int bt, r;
6715 r = VT_LVAL;
6716 bt = t & VT_BTYPE;
6717 if (bt == VT_BYTE || bt == VT_BOOL)
6718 r |= VT_LVAL_BYTE;
6719 else if (bt == VT_SHORT)
6720 r |= VT_LVAL_SHORT;
6721 else
6722 return r;
6723 if (t & VT_UNSIGNED)
6724 r |= VT_LVAL_UNSIGNED;
6725 return r;
6728 /* indirection with full error checking and bound check */
6729 static void indir(void)
6731 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6732 expect("pointer");
6733 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6734 gv(RC_INT);
6735 vtop->type = *pointed_type(&vtop->type);
6736 /* an array is never an lvalue */
6737 if (!(vtop->type.t & VT_ARRAY)) {
6738 vtop->r |= lvalue_type(vtop->type.t);
6739 /* if bound checking, the referenced pointer must be checked */
6740 if (do_bounds_check)
6741 vtop->r |= VT_MUSTBOUND;
6745 /* pass a parameter to a function and do type checking and casting */
6746 static void gfunc_param_typed(Sym *func, Sym *arg)
6748 int func_type;
6749 CType type;
6751 func_type = func->c;
6752 if (func_type == FUNC_OLD ||
6753 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6754 /* default casting : only need to convert float to double */
6755 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6756 type.t = VT_DOUBLE;
6757 gen_cast(&type);
6759 } else if (arg == NULL) {
6760 error("too many arguments to function");
6761 } else {
6762 type = arg->type;
6763 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6764 gen_assign_cast(&type);
6768 /* parse an expression of the form '(type)' or '(expr)' and return its
6769 type */
6770 static void parse_expr_type(CType *type)
6772 int n;
6773 AttributeDef ad;
6775 skip('(');
6776 if (parse_btype(type, &ad)) {
6777 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6778 } else {
6779 expr_type(type);
6781 skip(')');
6784 static void parse_type(CType *type)
6786 AttributeDef ad;
6787 int n;
6789 if (!parse_btype(type, &ad)) {
6790 expect("type");
6792 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6795 static void vpush_tokc(int t)
6797 CType type;
6798 type.t = t;
6799 vsetc(&type, VT_CONST, &tokc);
6802 static void unary(void)
6804 int n, t, align, size, r;
6805 CType type;
6806 Sym *s;
6807 AttributeDef ad;
6809 /* XXX: GCC 2.95.3 does not generate a table although it should be
6810 better here */
6811 tok_next:
6812 switch(tok) {
6813 case TOK_EXTENSION:
6814 next();
6815 goto tok_next;
6816 case TOK_CINT:
6817 case TOK_CCHAR:
6818 case TOK_LCHAR:
6819 vpushi(tokc.i);
6820 next();
6821 break;
6822 case TOK_CUINT:
6823 vpush_tokc(VT_INT | VT_UNSIGNED);
6824 next();
6825 break;
6826 case TOK_CLLONG:
6827 vpush_tokc(VT_LLONG);
6828 next();
6829 break;
6830 case TOK_CULLONG:
6831 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6832 next();
6833 break;
6834 case TOK_CFLOAT:
6835 vpush_tokc(VT_FLOAT);
6836 next();
6837 break;
6838 case TOK_CDOUBLE:
6839 vpush_tokc(VT_DOUBLE);
6840 next();
6841 break;
6842 case TOK_CLDOUBLE:
6843 vpush_tokc(VT_LDOUBLE);
6844 next();
6845 break;
6846 case TOK___FUNCTION__:
6847 if (!gnu_ext)
6848 goto tok_identifier;
6849 /* fall thru */
6850 case TOK___FUNC__:
6852 void *ptr;
6853 int len;
6854 /* special function name identifier */
6855 len = strlen(funcname) + 1;
6856 /* generate char[len] type */
6857 type.t = VT_BYTE;
6858 mk_pointer(&type);
6859 type.t |= VT_ARRAY;
6860 type.ref->c = len;
6861 vpush_ref(&type, data_section, data_section->data_offset, len);
6862 ptr = section_ptr_add(data_section, len);
6863 memcpy(ptr, funcname, len);
6864 next();
6866 break;
6867 case TOK_LSTR:
6868 t = VT_INT;
6869 goto str_init;
6870 case TOK_STR:
6871 /* string parsing */
6872 t = VT_BYTE;
6873 str_init:
6874 if (tcc_state->warn_write_strings)
6875 t |= VT_CONSTANT;
6876 type.t = t;
6877 mk_pointer(&type);
6878 type.t |= VT_ARRAY;
6879 memset(&ad, 0, sizeof(AttributeDef));
6880 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6881 break;
6882 case '(':
6883 next();
6884 /* cast ? */
6885 if (parse_btype(&type, &ad)) {
6886 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6887 skip(')');
6888 /* check ISOC99 compound literal */
6889 if (tok == '{') {
6890 /* data is allocated locally by default */
6891 if (global_expr)
6892 r = VT_CONST;
6893 else
6894 r = VT_LOCAL;
6895 /* all except arrays are lvalues */
6896 if (!(type.t & VT_ARRAY))
6897 r |= lvalue_type(type.t);
6898 memset(&ad, 0, sizeof(AttributeDef));
6899 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6900 } else {
6901 unary();
6902 gen_cast(&type);
6904 } else if (tok == '{') {
6905 /* save all registers */
6906 save_regs(0);
6907 /* statement expression : we do not accept break/continue
6908 inside as GCC does */
6909 block(NULL, NULL, NULL, NULL, 0, 1);
6910 skip(')');
6911 } else {
6912 gexpr();
6913 skip(')');
6915 break;
6916 case '*':
6917 next();
6918 unary();
6919 indir();
6920 break;
6921 case '&':
6922 next();
6923 unary();
6924 /* functions names must be treated as function pointers,
6925 except for unary '&' and sizeof. Since we consider that
6926 functions are not lvalues, we only have to handle it
6927 there and in function calls. */
6928 /* arrays can also be used although they are not lvalues */
6929 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6930 !(vtop->type.t & VT_ARRAY))
6931 test_lvalue();
6932 mk_pointer(&vtop->type);
6933 gaddrof();
6934 break;
6935 case '!':
6936 next();
6937 unary();
6938 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6939 vtop->c.i = !vtop->c.i;
6940 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6941 vtop->c.i = vtop->c.i ^ 1;
6942 else
6943 vseti(VT_JMP, gtst(1, 0));
6944 break;
6945 case '~':
6946 next();
6947 unary();
6948 vpushi(-1);
6949 gen_op('^');
6950 break;
6951 case '+':
6952 next();
6953 /* in order to force cast, we add zero */
6954 unary();
6955 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6956 error("pointer not accepted for unary plus");
6957 vpushi(0);
6958 gen_op('+');
6959 break;
6960 case TOK_SIZEOF:
6961 case TOK_ALIGNOF1:
6962 case TOK_ALIGNOF2:
6963 t = tok;
6964 next();
6965 if (tok == '(') {
6966 parse_expr_type(&type);
6967 } else {
6968 unary_type(&type);
6970 size = type_size(&type, &align);
6971 if (t == TOK_SIZEOF) {
6972 if (size < 0)
6973 error("sizeof applied to an incomplete type");
6974 vpushi(size);
6975 } else {
6976 vpushi(align);
6978 break;
6980 case TOK_builtin_types_compatible_p:
6982 CType type1, type2;
6983 next();
6984 skip('(');
6985 parse_type(&type1);
6986 skip(',');
6987 parse_type(&type2);
6988 skip(')');
6989 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6990 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6991 vpushi(is_compatible_types(&type1, &type2));
6993 break;
6994 case TOK_builtin_constant_p:
6996 int saved_nocode_wanted, res;
6997 next();
6998 skip('(');
6999 saved_nocode_wanted = nocode_wanted;
7000 nocode_wanted = 1;
7001 gexpr();
7002 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7003 vpop();
7004 nocode_wanted = saved_nocode_wanted;
7005 skip(')');
7006 vpushi(res);
7008 break;
7009 case TOK_INC:
7010 case TOK_DEC:
7011 t = tok;
7012 next();
7013 unary();
7014 inc(0, t);
7015 break;
7016 case '-':
7017 next();
7018 vpushi(0);
7019 unary();
7020 gen_op('-');
7021 break;
7022 case TOK_LAND:
7023 if (!gnu_ext)
7024 goto tok_identifier;
7025 next();
7026 /* allow to take the address of a label */
7027 if (tok < TOK_UIDENT)
7028 expect("label identifier");
7029 s = label_find(tok);
7030 if (!s) {
7031 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7032 } else {
7033 if (s->r == LABEL_DECLARED)
7034 s->r = LABEL_FORWARD;
7036 if (!s->type.t) {
7037 s->type.t = VT_VOID;
7038 mk_pointer(&s->type);
7039 s->type.t |= VT_STATIC;
7041 vset(&s->type, VT_CONST | VT_SYM, 0);
7042 vtop->sym = s;
7043 next();
7044 break;
7045 default:
7046 tok_identifier:
7047 t = tok;
7048 next();
7049 if (t < TOK_UIDENT)
7050 expect("identifier");
7051 s = sym_find(t);
7052 if (!s) {
7053 if (tok != '(')
7054 error("'%s' undeclared", get_tok_str(t, NULL));
7055 /* for simple function calls, we tolerate undeclared
7056 external reference to int() function */
7057 if (tcc_state->warn_implicit_function_declaration)
7058 warning("implicit declaration of function '%s'",
7059 get_tok_str(t, NULL));
7060 s = external_global_sym(t, &func_old_type, 0);
7062 vset(&s->type, s->r, s->c);
7063 /* if forward reference, we must point to s */
7064 if (vtop->r & VT_SYM) {
7065 vtop->sym = s;
7066 vtop->c.ul = 0;
7068 break;
7071 /* post operations */
7072 while (1) {
7073 if (tok == TOK_INC || tok == TOK_DEC) {
7074 inc(1, tok);
7075 next();
7076 } else if (tok == '.' || tok == TOK_ARROW) {
7077 /* field */
7078 if (tok == TOK_ARROW)
7079 indir();
7080 test_lvalue();
7081 gaddrof();
7082 next();
7083 /* expect pointer on structure */
7084 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7085 expect("struct or union");
7086 s = vtop->type.ref;
7087 /* find field */
7088 tok |= SYM_FIELD;
7089 while ((s = s->next) != NULL) {
7090 if (s->v == tok)
7091 break;
7093 if (!s)
7094 error("field not found");
7095 /* add field offset to pointer */
7096 vtop->type = char_pointer_type; /* change type to 'char *' */
7097 vpushi(s->c);
7098 gen_op('+');
7099 /* change type to field type, and set to lvalue */
7100 vtop->type = s->type;
7101 /* an array is never an lvalue */
7102 if (!(vtop->type.t & VT_ARRAY)) {
7103 vtop->r |= lvalue_type(vtop->type.t);
7104 /* if bound checking, the referenced pointer must be checked */
7105 if (do_bounds_check)
7106 vtop->r |= VT_MUSTBOUND;
7108 next();
7109 } else if (tok == '[') {
7110 next();
7111 gexpr();
7112 gen_op('+');
7113 indir();
7114 skip(']');
7115 } else if (tok == '(') {
7116 SValue ret;
7117 Sym *sa;
7118 int nb_args;
7120 /* function call */
7121 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7122 /* pointer test (no array accepted) */
7123 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7124 vtop->type = *pointed_type(&vtop->type);
7125 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7126 goto error_func;
7127 } else {
7128 error_func:
7129 expect("function pointer");
7131 } else {
7132 vtop->r &= ~VT_LVAL; /* no lvalue */
7134 /* get return type */
7135 s = vtop->type.ref;
7136 next();
7137 sa = s->next; /* first parameter */
7138 nb_args = 0;
7139 /* compute first implicit argument if a structure is returned */
7140 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7141 /* get some space for the returned structure */
7142 size = type_size(&s->type, &align);
7143 loc = (loc - size) & -align;
7144 ret.type = s->type;
7145 ret.r = VT_LOCAL | VT_LVAL;
7146 /* pass it as 'int' to avoid structure arg passing
7147 problems */
7148 vseti(VT_LOCAL, loc);
7149 ret.c = vtop->c;
7150 nb_args++;
7151 } else {
7152 ret.type = s->type;
7153 ret.r2 = VT_CONST;
7154 /* return in register */
7155 if (is_float(ret.type.t)) {
7156 ret.r = REG_FRET;
7157 } else {
7158 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7159 ret.r2 = REG_LRET;
7160 ret.r = REG_IRET;
7162 ret.c.i = 0;
7164 if (tok != ')') {
7165 for(;;) {
7166 expr_eq();
7167 gfunc_param_typed(s, sa);
7168 nb_args++;
7169 if (sa)
7170 sa = sa->next;
7171 if (tok == ')')
7172 break;
7173 skip(',');
7176 if (sa)
7177 error("too few arguments to function");
7178 skip(')');
7179 if (!nocode_wanted) {
7180 gfunc_call(nb_args);
7181 } else {
7182 vtop -= (nb_args + 1);
7184 /* return value */
7185 vsetc(&ret.type, ret.r, &ret.c);
7186 vtop->r2 = ret.r2;
7187 } else {
7188 break;
7193 static void uneq(void)
7195 int t;
7197 unary();
7198 if (tok == '=' ||
7199 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7200 tok == TOK_A_XOR || tok == TOK_A_OR ||
7201 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7202 test_lvalue();
7203 t = tok;
7204 next();
7205 if (t == '=') {
7206 expr_eq();
7207 } else {
7208 vdup();
7209 expr_eq();
7210 gen_op(t & 0x7f);
7212 vstore();
7216 static void expr_prod(void)
7218 int t;
7220 uneq();
7221 while (tok == '*' || tok == '/' || tok == '%') {
7222 t = tok;
7223 next();
7224 uneq();
7225 gen_op(t);
7229 static void expr_sum(void)
7231 int t;
7233 expr_prod();
7234 while (tok == '+' || tok == '-') {
7235 t = tok;
7236 next();
7237 expr_prod();
7238 gen_op(t);
7242 static void expr_shift(void)
7244 int t;
7246 expr_sum();
7247 while (tok == TOK_SHL || tok == TOK_SAR) {
7248 t = tok;
7249 next();
7250 expr_sum();
7251 gen_op(t);
7255 static void expr_cmp(void)
7257 int t;
7259 expr_shift();
7260 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7261 tok == TOK_ULT || tok == TOK_UGE) {
7262 t = tok;
7263 next();
7264 expr_shift();
7265 gen_op(t);
7269 static void expr_cmpeq(void)
7271 int t;
7273 expr_cmp();
7274 while (tok == TOK_EQ || tok == TOK_NE) {
7275 t = tok;
7276 next();
7277 expr_cmp();
7278 gen_op(t);
7282 static void expr_and(void)
7284 expr_cmpeq();
7285 while (tok == '&') {
7286 next();
7287 expr_cmpeq();
7288 gen_op('&');
7292 static void expr_xor(void)
7294 expr_and();
7295 while (tok == '^') {
7296 next();
7297 expr_and();
7298 gen_op('^');
7302 static void expr_or(void)
7304 expr_xor();
7305 while (tok == '|') {
7306 next();
7307 expr_xor();
7308 gen_op('|');
7312 /* XXX: fix this mess */
7313 static void expr_land_const(void)
7315 expr_or();
7316 while (tok == TOK_LAND) {
7317 next();
7318 expr_or();
7319 gen_op(TOK_LAND);
7323 /* XXX: fix this mess */
7324 static void expr_lor_const(void)
7326 expr_land_const();
7327 while (tok == TOK_LOR) {
7328 next();
7329 expr_land_const();
7330 gen_op(TOK_LOR);
7334 /* only used if non constant */
7335 static void expr_land(void)
7337 int t;
7339 expr_or();
7340 if (tok == TOK_LAND) {
7341 t = 0;
7342 for(;;) {
7343 t = gtst(1, t);
7344 if (tok != TOK_LAND) {
7345 vseti(VT_JMPI, t);
7346 break;
7348 next();
7349 expr_or();
7354 static void expr_lor(void)
7356 int t;
7358 expr_land();
7359 if (tok == TOK_LOR) {
7360 t = 0;
7361 for(;;) {
7362 t = gtst(0, t);
7363 if (tok != TOK_LOR) {
7364 vseti(VT_JMP, t);
7365 break;
7367 next();
7368 expr_land();
7373 /* XXX: better constant handling */
7374 static void expr_eq(void)
7376 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7377 SValue sv;
7378 CType type, type1, type2;
7380 if (const_wanted) {
7381 int c1, c;
7382 expr_lor_const();
7383 if (tok == '?') {
7384 c = vtop->c.i;
7385 vpop();
7386 next();
7387 if (tok == ':' && gnu_ext) {
7388 c1 = c;
7389 } else {
7390 gexpr();
7391 c1 = vtop->c.i;
7392 vpop();
7394 skip(':');
7395 expr_eq();
7396 if (c)
7397 vtop->c.i = c1;
7399 } else {
7400 expr_lor();
7401 if (tok == '?') {
7402 next();
7403 if (vtop != vstack) {
7404 /* needed to avoid having different registers saved in
7405 each branch */
7406 if (is_float(vtop->type.t))
7407 rc = RC_FLOAT;
7408 else
7409 rc = RC_INT;
7410 gv(rc);
7411 save_regs(1);
7413 if (tok == ':' && gnu_ext) {
7414 gv_dup();
7415 tt = gtst(1, 0);
7416 } else {
7417 tt = gtst(1, 0);
7418 gexpr();
7420 type1 = vtop->type;
7421 sv = *vtop; /* save value to handle it later */
7422 vtop--; /* no vpop so that FP stack is not flushed */
7423 skip(':');
7424 u = gjmp(0);
7425 gsym(tt);
7426 expr_eq();
7427 type2 = vtop->type;
7429 t1 = type1.t;
7430 bt1 = t1 & VT_BTYPE;
7431 t2 = type2.t;
7432 bt2 = t2 & VT_BTYPE;
7433 /* cast operands to correct type according to ISOC rules */
7434 if (is_float(bt1) || is_float(bt2)) {
7435 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7436 type.t = VT_LDOUBLE;
7437 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7438 type.t = VT_DOUBLE;
7439 } else {
7440 type.t = VT_FLOAT;
7442 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7443 /* cast to biggest op */
7444 type.t = VT_LLONG;
7445 /* convert to unsigned if it does not fit in a long long */
7446 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7447 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7448 type.t |= VT_UNSIGNED;
7449 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7450 /* XXX: test pointer compatibility */
7451 type = type1;
7452 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7453 /* XXX: test structure compatibility */
7454 type = type1;
7455 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7456 /* NOTE: as an extension, we accept void on only one side */
7457 type.t = VT_VOID;
7458 } else {
7459 /* integer operations */
7460 type.t = VT_INT;
7461 /* convert to unsigned if it does not fit in an integer */
7462 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7463 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7464 type.t |= VT_UNSIGNED;
7467 /* now we convert second operand */
7468 gen_cast(&type);
7469 rc = RC_INT;
7470 if (is_float(type.t)) {
7471 rc = RC_FLOAT;
7472 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7473 /* for long longs, we use fixed registers to avoid having
7474 to handle a complicated move */
7475 rc = RC_IRET;
7478 r2 = gv(rc);
7479 /* this is horrible, but we must also convert first
7480 operand */
7481 tt = gjmp(0);
7482 gsym(u);
7483 /* put again first value and cast it */
7484 *vtop = sv;
7485 gen_cast(&type);
7486 r1 = gv(rc);
7487 move_reg(r2, r1);
7488 vtop->r = r2;
7489 gsym(tt);
7494 static void gexpr(void)
7496 while (1) {
7497 expr_eq();
7498 if (tok != ',')
7499 break;
7500 vpop();
7501 next();
7505 /* parse an expression and return its type without any side effect. */
7506 static void expr_type(CType *type)
7508 int saved_nocode_wanted;
7510 saved_nocode_wanted = nocode_wanted;
7511 nocode_wanted = 1;
7512 gexpr();
7513 *type = vtop->type;
7514 vpop();
7515 nocode_wanted = saved_nocode_wanted;
7518 /* parse a unary expression and return its type without any side
7519 effect. */
7520 static void unary_type(CType *type)
7522 int a;
7524 a = nocode_wanted;
7525 nocode_wanted = 1;
7526 unary();
7527 *type = vtop->type;
7528 vpop();
7529 nocode_wanted = a;
7532 /* parse a constant expression and return value in vtop. */
7533 static void expr_const1(void)
7535 int a;
7536 a = const_wanted;
7537 const_wanted = 1;
7538 expr_eq();
7539 const_wanted = a;
7542 /* parse an integer constant and return its value. */
7543 static int expr_const(void)
7545 int c;
7546 expr_const1();
7547 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7548 expect("constant expression");
7549 c = vtop->c.i;
7550 vpop();
7551 return c;
7554 /* return the label token if current token is a label, otherwise
7555 return zero */
7556 static int is_label(void)
7558 int last_tok;
7560 /* fast test first */
7561 if (tok < TOK_UIDENT)
7562 return 0;
7563 /* no need to save tokc because tok is an identifier */
7564 last_tok = tok;
7565 next();
7566 if (tok == ':') {
7567 next();
7568 return last_tok;
7569 } else {
7570 unget_tok(last_tok);
7571 return 0;
7575 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7576 int case_reg, int is_expr)
7578 int a, b, c, d;
7579 Sym *s;
7581 /* generate line number info */
7582 if (do_debug &&
7583 (last_line_num != file->line_num || last_ind != ind)) {
7584 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7585 last_ind = ind;
7586 last_line_num = file->line_num;
7589 if (is_expr) {
7590 /* default return value is (void) */
7591 vpushi(0);
7592 vtop->type.t = VT_VOID;
7595 if (tok == TOK_IF) {
7596 /* if test */
7597 next();
7598 skip('(');
7599 gexpr();
7600 skip(')');
7601 a = gtst(1, 0);
7602 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7603 c = tok;
7604 if (c == TOK_ELSE) {
7605 next();
7606 d = gjmp(0);
7607 gsym(a);
7608 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7609 gsym(d); /* patch else jmp */
7610 } else
7611 gsym(a);
7612 } else if (tok == TOK_WHILE) {
7613 next();
7614 d = ind;
7615 skip('(');
7616 gexpr();
7617 skip(')');
7618 a = gtst(1, 0);
7619 b = 0;
7620 block(&a, &b, case_sym, def_sym, case_reg, 0);
7621 gjmp_addr(d);
7622 gsym(a);
7623 gsym_addr(b, d);
7624 } else if (tok == '{') {
7625 Sym *llabel;
7627 next();
7628 /* record local declaration stack position */
7629 s = local_stack;
7630 llabel = local_label_stack;
7631 /* handle local labels declarations */
7632 if (tok == TOK_LABEL) {
7633 next();
7634 for(;;) {
7635 if (tok < TOK_UIDENT)
7636 expect("label identifier");
7637 label_push(&local_label_stack, tok, LABEL_DECLARED);
7638 next();
7639 if (tok == ',') {
7640 next();
7641 } else {
7642 skip(';');
7643 break;
7647 while (tok != '}') {
7648 decl(VT_LOCAL);
7649 if (tok != '}') {
7650 if (is_expr)
7651 vpop();
7652 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7655 /* pop locally defined labels */
7656 label_pop(&local_label_stack, llabel);
7657 /* pop locally defined symbols */
7658 sym_pop(&local_stack, s);
7659 next();
7660 } else if (tok == TOK_RETURN) {
7661 next();
7662 if (tok != ';') {
7663 gexpr();
7664 gen_assign_cast(&func_vt);
7665 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7666 CType type;
7667 /* if returning structure, must copy it to implicit
7668 first pointer arg location */
7669 type = func_vt;
7670 mk_pointer(&type);
7671 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7672 indir();
7673 vswap();
7674 /* copy structure value to pointer */
7675 vstore();
7676 } else if (is_float(func_vt.t)) {
7677 gv(RC_FRET);
7678 } else {
7679 gv(RC_IRET);
7681 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7683 skip(';');
7684 rsym = gjmp(rsym); /* jmp */
7685 } else if (tok == TOK_BREAK) {
7686 /* compute jump */
7687 if (!bsym)
7688 error("cannot break");
7689 *bsym = gjmp(*bsym);
7690 next();
7691 skip(';');
7692 } else if (tok == TOK_CONTINUE) {
7693 /* compute jump */
7694 if (!csym)
7695 error("cannot continue");
7696 *csym = gjmp(*csym);
7697 next();
7698 skip(';');
7699 } else if (tok == TOK_FOR) {
7700 int e;
7701 next();
7702 skip('(');
7703 if (tok != ';') {
7704 gexpr();
7705 vpop();
7707 skip(';');
7708 d = ind;
7709 c = ind;
7710 a = 0;
7711 b = 0;
7712 if (tok != ';') {
7713 gexpr();
7714 a = gtst(1, 0);
7716 skip(';');
7717 if (tok != ')') {
7718 e = gjmp(0);
7719 c = ind;
7720 gexpr();
7721 vpop();
7722 gjmp_addr(d);
7723 gsym(e);
7725 skip(')');
7726 block(&a, &b, case_sym, def_sym, case_reg, 0);
7727 gjmp_addr(c);
7728 gsym(a);
7729 gsym_addr(b, c);
7730 } else
7731 if (tok == TOK_DO) {
7732 next();
7733 a = 0;
7734 b = 0;
7735 d = ind;
7736 block(&a, &b, case_sym, def_sym, case_reg, 0);
7737 skip(TOK_WHILE);
7738 skip('(');
7739 gsym(b);
7740 gexpr();
7741 c = gtst(0, 0);
7742 gsym_addr(c, d);
7743 skip(')');
7744 gsym(a);
7745 skip(';');
7746 } else
7747 if (tok == TOK_SWITCH) {
7748 next();
7749 skip('(');
7750 gexpr();
7751 /* XXX: other types than integer */
7752 case_reg = gv(RC_INT);
7753 vpop();
7754 skip(')');
7755 a = 0;
7756 b = gjmp(0); /* jump to first case */
7757 c = 0;
7758 block(&a, csym, &b, &c, case_reg, 0);
7759 /* if no default, jmp after switch */
7760 if (c == 0)
7761 c = ind;
7762 /* default label */
7763 gsym_addr(b, c);
7764 /* break label */
7765 gsym(a);
7766 } else
7767 if (tok == TOK_CASE) {
7768 int v1, v2;
7769 if (!case_sym)
7770 expect("switch");
7771 next();
7772 v1 = expr_const();
7773 v2 = v1;
7774 if (gnu_ext && tok == TOK_DOTS) {
7775 next();
7776 v2 = expr_const();
7777 if (v2 < v1)
7778 warning("empty case range");
7780 /* since a case is like a label, we must skip it with a jmp */
7781 b = gjmp(0);
7782 gsym(*case_sym);
7783 vseti(case_reg, 0);
7784 vpushi(v1);
7785 if (v1 == v2) {
7786 gen_op(TOK_EQ);
7787 *case_sym = gtst(1, 0);
7788 } else {
7789 gen_op(TOK_GE);
7790 *case_sym = gtst(1, 0);
7791 vseti(case_reg, 0);
7792 vpushi(v2);
7793 gen_op(TOK_LE);
7794 *case_sym = gtst(1, *case_sym);
7796 gsym(b);
7797 skip(':');
7798 is_expr = 0;
7799 goto block_after_label;
7800 } else
7801 if (tok == TOK_DEFAULT) {
7802 next();
7803 skip(':');
7804 if (!def_sym)
7805 expect("switch");
7806 if (*def_sym)
7807 error("too many 'default'");
7808 *def_sym = ind;
7809 is_expr = 0;
7810 goto block_after_label;
7811 } else
7812 if (tok == TOK_GOTO) {
7813 next();
7814 if (tok == '*' && gnu_ext) {
7815 /* computed goto */
7816 next();
7817 gexpr();
7818 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7819 expect("pointer");
7820 ggoto();
7821 } else if (tok >= TOK_UIDENT) {
7822 s = label_find(tok);
7823 /* put forward definition if needed */
7824 if (!s) {
7825 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7826 } else {
7827 if (s->r == LABEL_DECLARED)
7828 s->r = LABEL_FORWARD;
7830 /* label already defined */
7831 if (s->r & LABEL_FORWARD)
7832 s->next = (void *)gjmp((long)s->next);
7833 else
7834 gjmp_addr((long)s->next);
7835 next();
7836 } else {
7837 expect("label identifier");
7839 skip(';');
7840 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7841 asm_instr();
7842 } else {
7843 b = is_label();
7844 if (b) {
7845 /* label case */
7846 s = label_find(b);
7847 if (s) {
7848 if (s->r == LABEL_DEFINED)
7849 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7850 gsym((long)s->next);
7851 s->r = LABEL_DEFINED;
7852 } else {
7853 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7855 s->next = (void *)ind;
7856 /* we accept this, but it is a mistake */
7857 block_after_label:
7858 if (tok == '}') {
7859 warning("deprecated use of label at end of compound statement");
7860 } else {
7861 if (is_expr)
7862 vpop();
7863 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7865 } else {
7866 /* expression case */
7867 if (tok != ';') {
7868 if (is_expr) {
7869 vpop();
7870 gexpr();
7871 } else {
7872 gexpr();
7873 vpop();
7876 skip(';');
7881 /* t is the array or struct type. c is the array or struct
7882 address. cur_index/cur_field is the pointer to the current
7883 value. 'size_only' is true if only size info is needed (only used
7884 in arrays) */
7885 static void decl_designator(CType *type, Section *sec, unsigned long c,
7886 int *cur_index, Sym **cur_field,
7887 int size_only)
7889 Sym *s, *f;
7890 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7891 CType type1;
7893 notfirst = 0;
7894 elem_size = 0;
7895 nb_elems = 1;
7896 if (gnu_ext && (l = is_label()) != 0)
7897 goto struct_field;
7898 while (tok == '[' || tok == '.') {
7899 if (tok == '[') {
7900 if (!(type->t & VT_ARRAY))
7901 expect("array type");
7902 s = type->ref;
7903 next();
7904 index = expr_const();
7905 if (index < 0 || (s->c >= 0 && index >= s->c))
7906 expect("invalid index");
7907 if (tok == TOK_DOTS && gnu_ext) {
7908 next();
7909 index_last = expr_const();
7910 if (index_last < 0 ||
7911 (s->c >= 0 && index_last >= s->c) ||
7912 index_last < index)
7913 expect("invalid index");
7914 } else {
7915 index_last = index;
7917 skip(']');
7918 if (!notfirst)
7919 *cur_index = index_last;
7920 type = pointed_type(type);
7921 elem_size = type_size(type, &align);
7922 c += index * elem_size;
7923 /* NOTE: we only support ranges for last designator */
7924 nb_elems = index_last - index + 1;
7925 if (nb_elems != 1) {
7926 notfirst = 1;
7927 break;
7929 } else {
7930 next();
7931 l = tok;
7932 next();
7933 struct_field:
7934 if ((type->t & VT_BTYPE) != VT_STRUCT)
7935 expect("struct/union type");
7936 s = type->ref;
7937 l |= SYM_FIELD;
7938 f = s->next;
7939 while (f) {
7940 if (f->v == l)
7941 break;
7942 f = f->next;
7944 if (!f)
7945 expect("field");
7946 if (!notfirst)
7947 *cur_field = f;
7948 /* XXX: fix this mess by using explicit storage field */
7949 type1 = f->type;
7950 type1.t |= (type->t & ~VT_TYPE);
7951 type = &type1;
7952 c += f->c;
7954 notfirst = 1;
7956 if (notfirst) {
7957 if (tok == '=') {
7958 next();
7959 } else {
7960 if (!gnu_ext)
7961 expect("=");
7963 } else {
7964 if (type->t & VT_ARRAY) {
7965 index = *cur_index;
7966 type = pointed_type(type);
7967 c += index * type_size(type, &align);
7968 } else {
7969 f = *cur_field;
7970 if (!f)
7971 error("too many field init");
7972 /* XXX: fix this mess by using explicit storage field */
7973 type1 = f->type;
7974 type1.t |= (type->t & ~VT_TYPE);
7975 type = &type1;
7976 c += f->c;
7979 decl_initializer(type, sec, c, 0, size_only);
7981 /* XXX: make it more general */
7982 if (!size_only && nb_elems > 1) {
7983 unsigned long c_end;
7984 uint8_t *src, *dst;
7985 int i;
7987 if (!sec)
7988 error("range init not supported yet for dynamic storage");
7989 c_end = c + nb_elems * elem_size;
7990 if (c_end > sec->data_allocated)
7991 section_realloc(sec, c_end);
7992 src = sec->data + c;
7993 dst = src;
7994 for(i = 1; i < nb_elems; i++) {
7995 dst += elem_size;
7996 memcpy(dst, src, elem_size);
8001 #define EXPR_VAL 0
8002 #define EXPR_CONST 1
8003 #define EXPR_ANY 2
8005 /* store a value or an expression directly in global data or in local array */
8006 static void init_putv(CType *type, Section *sec, unsigned long c,
8007 int v, int expr_type)
8009 int saved_global_expr, bt, bit_pos, bit_size;
8010 void *ptr;
8011 unsigned long long bit_mask;
8012 CType dtype;
8014 switch(expr_type) {
8015 case EXPR_VAL:
8016 vpushi(v);
8017 break;
8018 case EXPR_CONST:
8019 /* compound literals must be allocated globally in this case */
8020 saved_global_expr = global_expr;
8021 global_expr = 1;
8022 expr_const1();
8023 global_expr = saved_global_expr;
8024 /* NOTE: symbols are accepted */
8025 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8026 error("initializer element is not constant");
8027 break;
8028 case EXPR_ANY:
8029 expr_eq();
8030 break;
8033 dtype = *type;
8034 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8036 if (sec) {
8037 /* XXX: not portable */
8038 /* XXX: generate error if incorrect relocation */
8039 gen_assign_cast(&dtype);
8040 bt = type->t & VT_BTYPE;
8041 ptr = sec->data + c;
8042 /* XXX: make code faster ? */
8043 if (!(type->t & VT_BITFIELD)) {
8044 bit_pos = 0;
8045 bit_size = 32;
8046 bit_mask = -1LL;
8047 } else {
8048 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8049 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8050 bit_mask = (1LL << bit_size) - 1;
8052 if ((vtop->r & VT_SYM) &&
8053 (bt == VT_BYTE ||
8054 bt == VT_SHORT ||
8055 bt == VT_DOUBLE ||
8056 bt == VT_LDOUBLE ||
8057 bt == VT_LLONG ||
8058 (bt == VT_INT && bit_size != 32)))
8059 error("initializer element is not computable at load time");
8060 switch(bt) {
8061 case VT_BYTE:
8062 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8063 break;
8064 case VT_SHORT:
8065 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8066 break;
8067 case VT_DOUBLE:
8068 *(double *)ptr = vtop->c.d;
8069 break;
8070 case VT_LDOUBLE:
8071 *(long double *)ptr = vtop->c.ld;
8072 break;
8073 case VT_LLONG:
8074 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8075 break;
8076 default:
8077 if (vtop->r & VT_SYM) {
8078 greloc(sec, vtop->sym, c, R_DATA_32);
8080 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8081 break;
8083 vtop--;
8084 } else {
8085 vset(&dtype, VT_LOCAL, c);
8086 vswap();
8087 vstore();
8088 vpop();
8092 /* put zeros for variable based init */
8093 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8095 if (sec) {
8096 /* nothing to do because globals are already set to zero */
8097 } else {
8098 vpush_global_sym(&func_old_type, TOK_memset);
8099 vseti(VT_LOCAL, c);
8100 vpushi(0);
8101 vpushi(size);
8102 gfunc_call(3);
8106 /* 't' contains the type and storage info. 'c' is the offset of the
8107 object in section 'sec'. If 'sec' is NULL, it means stack based
8108 allocation. 'first' is true if array '{' must be read (multi
8109 dimension implicit array init handling). 'size_only' is true if
8110 size only evaluation is wanted (only for arrays). */
8111 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8112 int first, int size_only)
8114 int index, array_length, n, no_oblock, nb, parlevel, i;
8115 int size1, align1, expr_type;
8116 Sym *s, *f;
8117 CType *t1;
8119 if (type->t & VT_ARRAY) {
8120 s = type->ref;
8121 n = s->c;
8122 array_length = 0;
8123 t1 = pointed_type(type);
8124 size1 = type_size(t1, &align1);
8126 no_oblock = 1;
8127 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8128 tok == '{') {
8129 skip('{');
8130 no_oblock = 0;
8133 /* only parse strings here if correct type (otherwise: handle
8134 them as ((w)char *) expressions */
8135 if ((tok == TOK_LSTR &&
8136 (t1->t & VT_BTYPE) == VT_INT) ||
8137 (tok == TOK_STR &&
8138 (t1->t & VT_BTYPE) == VT_BYTE)) {
8139 while (tok == TOK_STR || tok == TOK_LSTR) {
8140 int cstr_len, ch;
8141 CString *cstr;
8143 cstr = tokc.cstr;
8144 /* compute maximum number of chars wanted */
8145 if (tok == TOK_STR)
8146 cstr_len = cstr->size;
8147 else
8148 cstr_len = cstr->size / sizeof(int);
8149 cstr_len--;
8150 nb = cstr_len;
8151 if (n >= 0 && nb > (n - array_length))
8152 nb = n - array_length;
8153 if (!size_only) {
8154 if (cstr_len > nb)
8155 warning("initializer-string for array is too long");
8156 /* in order to go faster for common case (char
8157 string in global variable, we handle it
8158 specifically */
8159 if (sec && tok == TOK_STR && size1 == 1) {
8160 memcpy(sec->data + c + array_length, cstr->data, nb);
8161 } else {
8162 for(i=0;i<nb;i++) {
8163 if (tok == TOK_STR)
8164 ch = ((unsigned char *)cstr->data)[i];
8165 else
8166 ch = ((int *)cstr->data)[i];
8167 init_putv(t1, sec, c + (array_length + i) * size1,
8168 ch, EXPR_VAL);
8172 array_length += nb;
8173 next();
8175 /* only add trailing zero if enough storage (no
8176 warning in this case since it is standard) */
8177 if (n < 0 || array_length < n) {
8178 if (!size_only) {
8179 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8181 array_length++;
8183 } else {
8184 index = 0;
8185 while (tok != '}') {
8186 decl_designator(type, sec, c, &index, NULL, size_only);
8187 if (n >= 0 && index >= n)
8188 error("index too large");
8189 /* must put zero in holes (note that doing it that way
8190 ensures that it even works with designators) */
8191 if (!size_only && array_length < index) {
8192 init_putz(t1, sec, c + array_length * size1,
8193 (index - array_length) * size1);
8195 index++;
8196 if (index > array_length)
8197 array_length = index;
8198 /* special test for multi dimensional arrays (may not
8199 be strictly correct if designators are used at the
8200 same time) */
8201 if (index >= n && no_oblock)
8202 break;
8203 if (tok == '}')
8204 break;
8205 skip(',');
8208 if (!no_oblock)
8209 skip('}');
8210 /* put zeros at the end */
8211 if (!size_only && n >= 0 && array_length < n) {
8212 init_putz(t1, sec, c + array_length * size1,
8213 (n - array_length) * size1);
8215 /* patch type size if needed */
8216 if (n < 0)
8217 s->c = array_length;
8218 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8219 (sec || !first || tok == '{')) {
8220 int par_count;
8222 /* NOTE: the previous test is a specific case for automatic
8223 struct/union init */
8224 /* XXX: union needs only one init */
8226 /* XXX: this test is incorrect for local initializers
8227 beginning with ( without {. It would be much more difficult
8228 to do it correctly (ideally, the expression parser should
8229 be used in all cases) */
8230 par_count = 0;
8231 if (tok == '(') {
8232 AttributeDef ad1;
8233 CType type1;
8234 next();
8235 while (tok == '(') {
8236 par_count++;
8237 next();
8239 if (!parse_btype(&type1, &ad1))
8240 expect("cast");
8241 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8242 #if 0
8243 if (!is_assignable_types(type, &type1))
8244 error("invalid type for cast");
8245 #endif
8246 skip(')');
8248 no_oblock = 1;
8249 if (first || tok == '{') {
8250 skip('{');
8251 no_oblock = 0;
8253 s = type->ref;
8254 f = s->next;
8255 array_length = 0;
8256 index = 0;
8257 n = s->c;
8258 while (tok != '}') {
8259 decl_designator(type, sec, c, NULL, &f, size_only);
8260 index = f->c;
8261 if (!size_only && array_length < index) {
8262 init_putz(type, sec, c + array_length,
8263 index - array_length);
8265 index = index + type_size(&f->type, &align1);
8266 if (index > array_length)
8267 array_length = index;
8268 f = f->next;
8269 if (no_oblock && f == NULL)
8270 break;
8271 if (tok == '}')
8272 break;
8273 skip(',');
8275 /* put zeros at the end */
8276 if (!size_only && array_length < n) {
8277 init_putz(type, sec, c + array_length,
8278 n - array_length);
8280 if (!no_oblock)
8281 skip('}');
8282 while (par_count) {
8283 skip(')');
8284 par_count--;
8286 } else if (tok == '{') {
8287 next();
8288 decl_initializer(type, sec, c, first, size_only);
8289 skip('}');
8290 } else if (size_only) {
8291 /* just skip expression */
8292 parlevel = 0;
8293 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8294 tok != -1) {
8295 if (tok == '(')
8296 parlevel++;
8297 else if (tok == ')')
8298 parlevel--;
8299 next();
8301 } else {
8302 /* currently, we always use constant expression for globals
8303 (may change for scripting case) */
8304 expr_type = EXPR_CONST;
8305 if (!sec)
8306 expr_type = EXPR_ANY;
8307 init_putv(type, sec, c, 0, expr_type);
8311 /* parse an initializer for type 't' if 'has_init' is non zero, and
8312 allocate space in local or global data space ('r' is either
8313 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8314 variable 'v' of scope 'scope' is declared before initializers are
8315 parsed. If 'v' is zero, then a reference to the new object is put
8316 in the value stack. If 'has_init' is 2, a special parsing is done
8317 to handle string constants. */
8318 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8319 int has_init, int v, int scope)
8321 int size, align, addr, data_offset;
8322 int level;
8323 ParseState saved_parse_state;
8324 TokenString init_str;
8325 Section *sec;
8327 size = type_size(type, &align);
8328 /* If unknown size, we must evaluate it before
8329 evaluating initializers because
8330 initializers can generate global data too
8331 (e.g. string pointers or ISOC99 compound
8332 literals). It also simplifies local
8333 initializers handling */
8334 tok_str_new(&init_str);
8335 if (size < 0) {
8336 if (!has_init)
8337 error("unknown type size");
8338 /* get all init string */
8339 if (has_init == 2) {
8340 /* only get strings */
8341 while (tok == TOK_STR || tok == TOK_LSTR) {
8342 tok_str_add_tok(&init_str);
8343 next();
8345 } else {
8346 level = 0;
8347 while (level > 0 || (tok != ',' && tok != ';')) {
8348 if (tok < 0)
8349 error("unexpected end of file in initializer");
8350 tok_str_add_tok(&init_str);
8351 if (tok == '{')
8352 level++;
8353 else if (tok == '}') {
8354 if (level == 0)
8355 break;
8356 level--;
8358 next();
8361 tok_str_add(&init_str, -1);
8362 tok_str_add(&init_str, 0);
8364 /* compute size */
8365 save_parse_state(&saved_parse_state);
8367 macro_ptr = init_str.str;
8368 next();
8369 decl_initializer(type, NULL, 0, 1, 1);
8370 /* prepare second initializer parsing */
8371 macro_ptr = init_str.str;
8372 next();
8374 /* if still unknown size, error */
8375 size = type_size(type, &align);
8376 if (size < 0)
8377 error("unknown type size");
8379 /* take into account specified alignment if bigger */
8380 if (ad->aligned > align)
8381 align = ad->aligned;
8382 if ((r & VT_VALMASK) == VT_LOCAL) {
8383 sec = NULL;
8384 if (do_bounds_check && (type->t & VT_ARRAY))
8385 loc--;
8386 loc = (loc - size) & -align;
8387 addr = loc;
8388 /* handles bounds */
8389 /* XXX: currently, since we do only one pass, we cannot track
8390 '&' operators, so we add only arrays */
8391 if (do_bounds_check && (type->t & VT_ARRAY)) {
8392 unsigned long *bounds_ptr;
8393 /* add padding between regions */
8394 loc--;
8395 /* then add local bound info */
8396 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8397 bounds_ptr[0] = addr;
8398 bounds_ptr[1] = size;
8400 if (v) {
8401 /* local variable */
8402 sym_push(v, type, r, addr);
8403 } else {
8404 /* push local reference */
8405 vset(type, r, addr);
8407 } else {
8408 Sym *sym;
8410 sym = NULL;
8411 if (v && scope == VT_CONST) {
8412 /* see if the symbol was already defined */
8413 sym = sym_find(v);
8414 if (sym) {
8415 if (!is_compatible_types(&sym->type, type))
8416 error("incompatible types for redefinition of '%s'",
8417 get_tok_str(v, NULL));
8418 if (sym->type.t & VT_EXTERN) {
8419 /* if the variable is extern, it was not allocated */
8420 sym->type.t &= ~VT_EXTERN;
8421 } else {
8422 /* we accept several definitions of the same
8423 global variable. this is tricky, because we
8424 must play with the SHN_COMMON type of the symbol */
8425 /* XXX: should check if the variable was already
8426 initialized. It is incorrect to initialized it
8427 twice */
8428 /* no init data, we won't add more to the symbol */
8429 if (!has_init)
8430 goto no_alloc;
8435 /* allocate symbol in corresponding section */
8436 sec = ad->section;
8437 if (!sec) {
8438 if (has_init)
8439 sec = data_section;
8441 if (sec) {
8442 data_offset = sec->data_offset;
8443 data_offset = (data_offset + align - 1) & -align;
8444 addr = data_offset;
8445 /* very important to increment global pointer at this time
8446 because initializers themselves can create new initializers */
8447 data_offset += size;
8448 /* add padding if bound check */
8449 if (do_bounds_check)
8450 data_offset++;
8451 sec->data_offset = data_offset;
8452 /* allocate section space to put the data */
8453 if (sec->sh_type != SHT_NOBITS &&
8454 data_offset > sec->data_allocated)
8455 section_realloc(sec, data_offset);
8456 } else {
8457 addr = 0; /* avoid warning */
8460 if (v) {
8461 if (scope == VT_CONST) {
8462 if (!sym)
8463 goto do_def;
8464 } else {
8465 do_def:
8466 sym = sym_push(v, type, r | VT_SYM, 0);
8468 /* update symbol definition */
8469 if (sec) {
8470 put_extern_sym(sym, sec, addr, size);
8471 } else {
8472 Elf32_Sym *esym;
8473 /* put a common area */
8474 put_extern_sym(sym, NULL, align, size);
8475 /* XXX: find a nicer way */
8476 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8477 esym->st_shndx = SHN_COMMON;
8479 } else {
8480 CValue cval;
8482 /* push global reference */
8483 sym = get_sym_ref(type, sec, addr, size);
8484 cval.ul = 0;
8485 vsetc(type, VT_CONST | VT_SYM, &cval);
8486 vtop->sym = sym;
8489 /* handles bounds now because the symbol must be defined
8490 before for the relocation */
8491 if (do_bounds_check) {
8492 unsigned long *bounds_ptr;
8494 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8495 /* then add global bound info */
8496 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8497 bounds_ptr[0] = 0; /* relocated */
8498 bounds_ptr[1] = size;
8501 if (has_init) {
8502 decl_initializer(type, sec, addr, 1, 0);
8503 /* restore parse state if needed */
8504 if (init_str.str) {
8505 tok_str_free(init_str.str);
8506 restore_parse_state(&saved_parse_state);
8509 no_alloc: ;
8512 void put_func_debug(Sym *sym)
8514 char buf[512];
8516 /* stabs info */
8517 /* XXX: we put here a dummy type */
8518 snprintf(buf, sizeof(buf), "%s:%c1",
8519 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8520 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8521 cur_text_section, sym->c);
8522 last_ind = 0;
8523 last_line_num = 0;
8526 /* not finished : try to put some local vars in registers */
8527 //#define CONFIG_REG_VARS
8529 #ifdef CONFIG_REG_VARS
8530 void add_var_ref(int t)
8532 printf("%s:%d: &%s\n",
8533 file->filename, file->line_num,
8534 get_tok_str(t, NULL));
8537 /* first pass on a function with heuristic to extract variable usage
8538 and pointer references to local variables for register allocation */
8539 void analyse_function(void)
8541 int level, t;
8543 for(;;) {
8544 if (tok == -1)
8545 break;
8546 /* any symbol coming after '&' is considered as being a
8547 variable whose reference is taken. It is highly unaccurate
8548 but it is difficult to do better without a complete parse */
8549 if (tok == '&') {
8550 next();
8551 /* if '& number', then no need to examine next tokens */
8552 if (tok == TOK_CINT ||
8553 tok == TOK_CUINT ||
8554 tok == TOK_CLLONG ||
8555 tok == TOK_CULLONG) {
8556 continue;
8557 } else if (tok >= TOK_UIDENT) {
8558 /* if '& ident [' or '& ident ->', then ident address
8559 is not needed */
8560 t = tok;
8561 next();
8562 if (tok != '[' && tok != TOK_ARROW)
8563 add_var_ref(t);
8564 } else {
8565 level = 0;
8566 while (tok != '}' && tok != ';' &&
8567 !((tok == ',' || tok == ')') && level == 0)) {
8568 if (tok >= TOK_UIDENT) {
8569 add_var_ref(tok);
8570 } else if (tok == '(') {
8571 level++;
8572 } else if (tok == ')') {
8573 level--;
8575 next();
8578 } else {
8579 next();
8583 #endif
8585 /* parse an old style function declaration list */
8586 /* XXX: check multiple parameter */
8587 static void func_decl_list(Sym *func_sym)
8589 AttributeDef ad;
8590 int v;
8591 Sym *s;
8592 CType btype, type;
8594 /* parse each declaration */
8595 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8596 if (!parse_btype(&btype, &ad))
8597 expect("declaration list");
8598 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8599 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8600 tok == ';') {
8601 /* we accept no variable after */
8602 } else {
8603 for(;;) {
8604 type = btype;
8605 type_decl(&type, &ad, &v, TYPE_DIRECT);
8606 /* find parameter in function parameter list */
8607 s = func_sym->next;
8608 while (s != NULL) {
8609 if ((s->v & ~SYM_FIELD) == v)
8610 goto found;
8611 s = s->next;
8613 error("declaration for parameter '%s' but no such parameter",
8614 get_tok_str(v, NULL));
8615 found:
8616 /* check that no storage specifier except 'register' was given */
8617 if (type.t & VT_STORAGE)
8618 error("storage class specified for '%s'", get_tok_str(v, NULL));
8619 convert_parameter_type(&type);
8620 /* we can add the type (NOTE: it could be local to the function) */
8621 s->type = type;
8622 /* accept other parameters */
8623 if (tok == ',')
8624 next();
8625 else
8626 break;
8629 skip(';');
8633 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8634 static void decl(int l)
8636 int v, has_init, r;
8637 CType type, btype;
8638 Sym *sym;
8639 AttributeDef ad;
8641 while (1) {
8642 if (!parse_btype(&btype, &ad)) {
8643 /* skip redundant ';' */
8644 /* XXX: find more elegant solution */
8645 if (tok == ';') {
8646 next();
8647 continue;
8649 /* special test for old K&R protos without explicit int
8650 type. Only accepted when defining global data */
8651 if (l == VT_LOCAL || tok < TOK_DEFINE)
8652 break;
8653 btype.t = VT_INT;
8655 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8656 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8657 tok == ';') {
8658 /* we accept no variable after */
8659 next();
8660 continue;
8662 while (1) { /* iterate thru each declaration */
8663 type = btype;
8664 type_decl(&type, &ad, &v, TYPE_DIRECT);
8665 #if 0
8667 char buf[500];
8668 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8669 printf("type = '%s'\n", buf);
8671 #endif
8672 if ((type.t & VT_BTYPE) == VT_FUNC) {
8673 /* if old style function prototype, we accept a
8674 declaration list */
8675 sym = type.ref;
8676 if (sym->c == FUNC_OLD)
8677 func_decl_list(sym);
8680 if (tok == '{') {
8681 #ifdef CONFIG_REG_VARS
8682 TokenString func_str;
8683 ParseState saved_parse_state;
8684 int block_level;
8685 #endif
8687 if (l == VT_LOCAL)
8688 error("cannot use local functions");
8689 if (!(type.t & VT_FUNC))
8690 expect("function definition");
8692 /* reject abstract declarators in function definition */
8693 sym = type.ref;
8694 while ((sym = sym->next) != NULL)
8695 if (!(sym->v & ~SYM_FIELD))
8696 expect("identifier");
8698 /* XXX: cannot do better now: convert extern line to static inline */
8699 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8700 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8702 #ifdef CONFIG_REG_VARS
8703 /* parse all function code and record it */
8705 tok_str_new(&func_str);
8707 block_level = 0;
8708 for(;;) {
8709 int t;
8710 if (tok == -1)
8711 error("unexpected end of file");
8712 tok_str_add_tok(&func_str);
8713 t = tok;
8714 next();
8715 if (t == '{') {
8716 block_level++;
8717 } else if (t == '}') {
8718 block_level--;
8719 if (block_level == 0)
8720 break;
8723 tok_str_add(&func_str, -1);
8724 tok_str_add(&func_str, 0);
8726 save_parse_state(&saved_parse_state);
8728 macro_ptr = func_str.str;
8729 next();
8730 analyse_function();
8731 #endif
8733 /* compute text section */
8734 cur_text_section = ad.section;
8735 if (!cur_text_section)
8736 cur_text_section = text_section;
8737 ind = cur_text_section->data_offset;
8738 funcname = get_tok_str(v, NULL);
8739 sym = sym_find(v);
8740 if (sym) {
8741 /* if symbol is already defined, then put complete type */
8742 sym->type = type;
8743 } else {
8744 /* put function symbol */
8745 sym = global_identifier_push(v, type.t, 0);
8746 sym->type.ref = type.ref;
8748 /* NOTE: we patch the symbol size later */
8749 put_extern_sym(sym, cur_text_section, ind, 0);
8750 func_ind = ind;
8751 sym->r = VT_SYM | VT_CONST;
8752 /* put debug symbol */
8753 if (do_debug)
8754 put_func_debug(sym);
8755 /* push a dummy symbol to enable local sym storage */
8756 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8757 gfunc_prolog(&type);
8758 rsym = 0;
8759 #ifdef CONFIG_REG_VARS
8760 macro_ptr = func_str.str;
8761 next();
8762 #endif
8763 block(NULL, NULL, NULL, NULL, 0, 0);
8764 gsym(rsym);
8765 gfunc_epilog();
8766 cur_text_section->data_offset = ind;
8767 label_pop(&global_label_stack, NULL);
8768 sym_pop(&local_stack, NULL); /* reset local stack */
8769 /* end of function */
8770 /* patch symbol size */
8771 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8772 ind - func_ind;
8773 if (do_debug) {
8774 put_stabn(N_FUN, 0, 0, ind - func_ind);
8776 funcname = ""; /* for safety */
8777 func_vt.t = VT_VOID; /* for safety */
8778 ind = 0; /* for safety */
8780 #ifdef CONFIG_REG_VARS
8781 tok_str_free(func_str.str);
8782 restore_parse_state(&saved_parse_state);
8783 #endif
8784 break;
8785 } else {
8786 if (btype.t & VT_TYPEDEF) {
8787 /* save typedefed type */
8788 /* XXX: test storage specifiers ? */
8789 sym = sym_push(v, &type, 0, 0);
8790 sym->type.t |= VT_TYPEDEF;
8791 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8792 /* external function definition */
8793 external_sym(v, &type, 0);
8794 } else {
8795 /* not lvalue if array */
8796 r = 0;
8797 if (!(type.t & VT_ARRAY))
8798 r |= lvalue_type(type.t);
8799 has_init = (tok == '=');
8800 if ((btype.t & VT_EXTERN) ||
8801 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8802 !has_init && l == VT_CONST && type.ref->c < 0)) {
8803 /* external variable */
8804 /* NOTE: as GCC, uninitialized global static
8805 arrays of null size are considered as
8806 extern */
8807 external_sym(v, &type, r);
8808 } else {
8809 if (type.t & VT_STATIC)
8810 r |= VT_CONST;
8811 else
8812 r |= l;
8813 if (has_init)
8814 next();
8815 decl_initializer_alloc(&type, &ad, r,
8816 has_init, v, l);
8819 if (tok != ',') {
8820 skip(';');
8821 break;
8823 next();
8829 /* better than nothing, but needs extension to handle '-E' option
8830 correctly too */
8831 static void preprocess_init(TCCState *s1)
8833 s1->include_stack_ptr = s1->include_stack;
8834 /* XXX: move that before to avoid having to initialize
8835 file->ifdef_stack_ptr ? */
8836 s1->ifdef_stack_ptr = s1->ifdef_stack;
8837 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8839 /* XXX: not ANSI compliant: bound checking says error */
8840 vtop = vstack - 1;
8843 /* compile the C file opened in 'file'. Return non zero if errors. */
8844 static int tcc_compile(TCCState *s1)
8846 Sym *define_start;
8847 char buf[512];
8848 volatile int section_sym;
8850 #ifdef INC_DEBUG
8851 printf("%s: **** new file\n", file->filename);
8852 #endif
8853 preprocess_init(s1);
8855 funcname = "";
8856 anon_sym = SYM_FIRST_ANOM;
8858 /* file info: full path + filename */
8859 section_sym = 0; /* avoid warning */
8860 if (do_debug) {
8861 section_sym = put_elf_sym(symtab_section, 0, 0,
8862 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8863 text_section->sh_num, NULL);
8864 getcwd(buf, sizeof(buf));
8865 pstrcat(buf, sizeof(buf), "/");
8866 put_stabs_r(buf, N_SO, 0, 0,
8867 text_section->data_offset, text_section, section_sym);
8868 put_stabs_r(file->filename, N_SO, 0, 0,
8869 text_section->data_offset, text_section, section_sym);
8871 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8872 symbols can be safely used */
8873 put_elf_sym(symtab_section, 0, 0,
8874 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8875 SHN_ABS, file->filename);
8877 /* define some often used types */
8878 int_type.t = VT_INT;
8880 char_pointer_type.t = VT_BYTE;
8881 mk_pointer(&char_pointer_type);
8883 func_old_type.t = VT_FUNC;
8884 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8886 #if 0
8887 /* define 'void *alloca(unsigned int)' builtin function */
8889 Sym *s1;
8891 p = anon_sym++;
8892 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8893 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8894 s1->next = NULL;
8895 sym->next = s1;
8896 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8898 #endif
8900 define_start = define_stack;
8902 if (setjmp(s1->error_jmp_buf) == 0) {
8903 s1->nb_errors = 0;
8904 s1->error_set_jmp_enabled = 1;
8906 ch = file->buf_ptr[0];
8907 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8908 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8909 next();
8910 decl(VT_CONST);
8911 if (tok != TOK_EOF)
8912 expect("declaration");
8914 /* end of translation unit info */
8915 if (do_debug) {
8916 put_stabs_r(NULL, N_SO, 0, 0,
8917 text_section->data_offset, text_section, section_sym);
8920 s1->error_set_jmp_enabled = 0;
8922 /* reset define stack, but leave -Dsymbols (may be incorrect if
8923 they are undefined) */
8924 free_defines(define_start);
8926 sym_pop(&global_stack, NULL);
8928 return s1->nb_errors != 0 ? -1 : 0;
8931 #ifdef LIBTCC
8932 int tcc_compile_string(TCCState *s, const char *str)
8934 BufferedFile bf1, *bf = &bf1;
8935 int ret, len;
8936 char *buf;
8938 /* init file structure */
8939 bf->fd = -1;
8940 /* XXX: avoid copying */
8941 len = strlen(str);
8942 buf = tcc_malloc(len + 1);
8943 if (!buf)
8944 return -1;
8945 memcpy(buf, str, len);
8946 buf[len] = CH_EOB;
8947 bf->buf_ptr = buf;
8948 bf->buf_end = buf + len;
8949 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8950 bf->line_num = 1;
8951 file = bf;
8953 ret = tcc_compile(s);
8955 tcc_free(buf);
8957 /* currently, no need to close */
8958 return ret;
8960 #endif
8962 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8963 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8965 BufferedFile bf1, *bf = &bf1;
8967 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8968 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8969 /* default value */
8970 if (!value)
8971 value = "1";
8972 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8974 /* init file structure */
8975 bf->fd = -1;
8976 bf->buf_ptr = bf->buffer;
8977 bf->buf_end = bf->buffer + strlen(bf->buffer);
8978 *bf->buf_end = CH_EOB;
8979 bf->filename[0] = '\0';
8980 bf->line_num = 1;
8981 file = bf;
8983 s1->include_stack_ptr = s1->include_stack;
8985 /* parse with define parser */
8986 ch = file->buf_ptr[0];
8987 next_nomacro();
8988 parse_define();
8989 file = NULL;
8992 /* undefine a preprocessor symbol */
8993 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8995 TokenSym *ts;
8996 Sym *s;
8997 ts = tok_alloc(sym, strlen(sym));
8998 s = define_find(ts->tok);
8999 /* undefine symbol by putting an invalid name */
9000 if (s)
9001 define_undef(s);
9004 #ifdef CONFIG_TCC_ASM
9006 #ifdef TCC_TARGET_I386
9007 #include "i386-asm.c"
9008 #endif
9009 #include "tccasm.c"
9011 #else
9012 static void asm_instr(void)
9014 error("inline asm() not supported");
9016 #endif
9018 #include "tccelf.c"
9020 #ifdef TCC_TARGET_COFF
9021 #include "tcccoff.c"
9022 #endif
9024 /* print the position in the source file of PC value 'pc' by reading
9025 the stabs debug information */
9026 static void rt_printline(unsigned long wanted_pc)
9028 Stab_Sym *sym, *sym_end;
9029 char func_name[128], last_func_name[128];
9030 unsigned long func_addr, last_pc, pc;
9031 const char *incl_files[INCLUDE_STACK_SIZE];
9032 int incl_index, len, last_line_num, i;
9033 const char *str, *p;
9035 fprintf(stderr, "0x%08lx:", wanted_pc);
9037 func_name[0] = '\0';
9038 func_addr = 0;
9039 incl_index = 0;
9040 last_func_name[0] = '\0';
9041 last_pc = 0xffffffff;
9042 last_line_num = 1;
9043 sym = (Stab_Sym *)stab_section->data + 1;
9044 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9045 while (sym < sym_end) {
9046 switch(sym->n_type) {
9047 /* function start or end */
9048 case N_FUN:
9049 if (sym->n_strx == 0) {
9050 /* we test if between last line and end of function */
9051 pc = sym->n_value + func_addr;
9052 if (wanted_pc >= last_pc && wanted_pc < pc)
9053 goto found;
9054 func_name[0] = '\0';
9055 func_addr = 0;
9056 } else {
9057 str = stabstr_section->data + sym->n_strx;
9058 p = strchr(str, ':');
9059 if (!p) {
9060 pstrcpy(func_name, sizeof(func_name), str);
9061 } else {
9062 len = p - str;
9063 if (len > sizeof(func_name) - 1)
9064 len = sizeof(func_name) - 1;
9065 memcpy(func_name, str, len);
9066 func_name[len] = '\0';
9068 func_addr = sym->n_value;
9070 break;
9071 /* line number info */
9072 case N_SLINE:
9073 pc = sym->n_value + func_addr;
9074 if (wanted_pc >= last_pc && wanted_pc < pc)
9075 goto found;
9076 last_pc = pc;
9077 last_line_num = sym->n_desc;
9078 /* XXX: slow! */
9079 strcpy(last_func_name, func_name);
9080 break;
9081 /* include files */
9082 case N_BINCL:
9083 str = stabstr_section->data + sym->n_strx;
9084 add_incl:
9085 if (incl_index < INCLUDE_STACK_SIZE) {
9086 incl_files[incl_index++] = str;
9088 break;
9089 case N_EINCL:
9090 if (incl_index > 1)
9091 incl_index--;
9092 break;
9093 case N_SO:
9094 if (sym->n_strx == 0) {
9095 incl_index = 0; /* end of translation unit */
9096 } else {
9097 str = stabstr_section->data + sym->n_strx;
9098 /* do not add path */
9099 len = strlen(str);
9100 if (len > 0 && str[len - 1] != '/')
9101 goto add_incl;
9103 break;
9105 sym++;
9108 /* second pass: we try symtab symbols (no line number info) */
9109 incl_index = 0;
9111 Elf32_Sym *sym, *sym_end;
9112 int type;
9114 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9115 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9116 sym < sym_end;
9117 sym++) {
9118 type = ELF32_ST_TYPE(sym->st_info);
9119 if (type == STT_FUNC) {
9120 if (wanted_pc >= sym->st_value &&
9121 wanted_pc < sym->st_value + sym->st_size) {
9122 pstrcpy(last_func_name, sizeof(last_func_name),
9123 strtab_section->data + sym->st_name);
9124 goto found;
9129 /* did not find any info: */
9130 fprintf(stderr, " ???\n");
9131 return;
9132 found:
9133 if (last_func_name[0] != '\0') {
9134 fprintf(stderr, " %s()", last_func_name);
9136 if (incl_index > 0) {
9137 fprintf(stderr, " (%s:%d",
9138 incl_files[incl_index - 1], last_line_num);
9139 for(i = incl_index - 2; i >= 0; i--)
9140 fprintf(stderr, ", included from %s", incl_files[i]);
9141 fprintf(stderr, ")");
9143 fprintf(stderr, "\n");
9146 #ifndef WIN32
9148 #ifdef __i386__
9150 /* fix for glibc 2.1 */
9151 #ifndef REG_EIP
9152 #define REG_EIP EIP
9153 #define REG_EBP EBP
9154 #endif
9156 /* return the PC at frame level 'level'. Return non zero if not found */
9157 static int rt_get_caller_pc(unsigned long *paddr,
9158 ucontext_t *uc, int level)
9160 unsigned long fp;
9161 int i;
9163 if (level == 0) {
9164 #if defined(__FreeBSD__)
9165 *paddr = uc->uc_mcontext.mc_eip;
9166 #elif defined(__dietlibc__)
9167 *paddr = uc->uc_mcontext.eip;
9168 #else
9169 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9170 #endif
9171 return 0;
9172 } else {
9173 #if defined(__FreeBSD__)
9174 fp = uc->uc_mcontext.mc_ebp;
9175 #elif defined(__dietlibc__)
9176 fp = uc->uc_mcontext.ebp;
9177 #else
9178 fp = uc->uc_mcontext.gregs[REG_EBP];
9179 #endif
9180 for(i=1;i<level;i++) {
9181 /* XXX: check address validity with program info */
9182 if (fp <= 0x1000 || fp >= 0xc0000000)
9183 return -1;
9184 fp = ((unsigned long *)fp)[0];
9186 *paddr = ((unsigned long *)fp)[1];
9187 return 0;
9190 #else
9192 #warning add arch specific rt_get_caller_pc()
9194 static int rt_get_caller_pc(unsigned long *paddr,
9195 ucontext_t *uc, int level)
9197 return -1;
9199 #endif
9201 /* emit a run time error at position 'pc' */
9202 void rt_error(ucontext_t *uc, const char *fmt, ...)
9204 va_list ap;
9205 unsigned long pc;
9206 int i;
9208 va_start(ap, fmt);
9209 fprintf(stderr, "Runtime error: ");
9210 vfprintf(stderr, fmt, ap);
9211 fprintf(stderr, "\n");
9212 for(i=0;i<num_callers;i++) {
9213 if (rt_get_caller_pc(&pc, uc, i) < 0)
9214 break;
9215 if (i == 0)
9216 fprintf(stderr, "at ");
9217 else
9218 fprintf(stderr, "by ");
9219 rt_printline(pc);
9221 exit(255);
9222 va_end(ap);
9225 /* signal handler for fatal errors */
9226 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9228 ucontext_t *uc = puc;
9230 switch(signum) {
9231 case SIGFPE:
9232 switch(siginf->si_code) {
9233 case FPE_INTDIV:
9234 case FPE_FLTDIV:
9235 rt_error(uc, "division by zero");
9236 break;
9237 default:
9238 rt_error(uc, "floating point exception");
9239 break;
9241 break;
9242 case SIGBUS:
9243 case SIGSEGV:
9244 if (rt_bound_error_msg && *rt_bound_error_msg)
9245 rt_error(uc, *rt_bound_error_msg);
9246 else
9247 rt_error(uc, "dereferencing invalid pointer");
9248 break;
9249 case SIGILL:
9250 rt_error(uc, "illegal instruction");
9251 break;
9252 case SIGABRT:
9253 rt_error(uc, "abort() called");
9254 break;
9255 default:
9256 rt_error(uc, "caught signal %d", signum);
9257 break;
9259 exit(255);
9261 #endif
9263 /* do all relocations (needed before using tcc_get_symbol()) */
9264 int tcc_relocate(TCCState *s1)
9266 Section *s;
9267 int i;
9269 s1->nb_errors = 0;
9271 tcc_add_runtime(s1);
9273 build_got_entries(s1);
9275 relocate_common_syms();
9277 /* compute relocation address : section are relocated in place. We
9278 also alloc the bss space */
9279 for(i = 1; i < s1->nb_sections; i++) {
9280 s = s1->sections[i];
9281 if (s->sh_flags & SHF_ALLOC) {
9282 if (s->sh_type == SHT_NOBITS)
9283 s->data = tcc_mallocz(s->data_offset);
9284 s->sh_addr = (unsigned long)s->data;
9288 relocate_syms(s1, 1);
9290 if (s1->nb_errors != 0)
9291 return -1;
9293 /* relocate each section */
9294 for(i = 1; i < s1->nb_sections; i++) {
9295 s = s1->sections[i];
9296 if (s->reloc)
9297 relocate_section(s1, s);
9299 return 0;
9302 /* launch the compiled program with the given arguments */
9303 int tcc_run(TCCState *s1, int argc, char **argv)
9305 int (*prog_main)(int, char **);
9307 if (tcc_relocate(s1) < 0)
9308 return -1;
9310 prog_main = tcc_get_symbol_err(s1, "main");
9312 if (do_debug) {
9313 #ifdef WIN32
9314 error("debug mode currently not available for Windows");
9315 #else
9316 struct sigaction sigact;
9317 /* install TCC signal handlers to print debug info on fatal
9318 runtime errors */
9319 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9320 sigact.sa_sigaction = sig_error;
9321 sigemptyset(&sigact.sa_mask);
9322 sigaction(SIGFPE, &sigact, NULL);
9323 sigaction(SIGILL, &sigact, NULL);
9324 sigaction(SIGSEGV, &sigact, NULL);
9325 sigaction(SIGBUS, &sigact, NULL);
9326 sigaction(SIGABRT, &sigact, NULL);
9327 #endif
9330 #ifdef CONFIG_TCC_BCHECK
9331 if (do_bounds_check) {
9332 void (*bound_init)(void);
9334 /* set error function */
9335 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9336 "__bound_error_msg");
9338 /* XXX: use .init section so that it also work in binary ? */
9339 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9340 bound_init();
9342 #endif
9343 return (*prog_main)(argc, argv);
9346 TCCState *tcc_new(void)
9348 const char *p, *r;
9349 TCCState *s;
9350 TokenSym *ts;
9351 int i, c;
9353 s = tcc_mallocz(sizeof(TCCState));
9354 if (!s)
9355 return NULL;
9356 tcc_state = s;
9357 s->output_type = TCC_OUTPUT_MEMORY;
9359 /* init isid table */
9360 for(i=0;i<256;i++)
9361 isidnum_table[i] = isid(i) || isnum(i);
9363 /* add all tokens */
9364 table_ident = NULL;
9365 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9367 tok_ident = TOK_IDENT;
9368 p = tcc_keywords;
9369 while (*p) {
9370 r = p;
9371 for(;;) {
9372 c = *r++;
9373 if (c == '\0')
9374 break;
9376 ts = tok_alloc(p, r - p - 1);
9377 p = r;
9380 /* we add dummy defines for some special macros to speed up tests
9381 and to have working defined() */
9382 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9383 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9384 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9385 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9387 /* standard defines */
9388 tcc_define_symbol(s, "__STDC__", NULL);
9389 #if defined(TCC_TARGET_I386)
9390 tcc_define_symbol(s, "__i386__", NULL);
9391 #endif
9392 #if defined(TCC_TARGET_ARM)
9393 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9394 tcc_define_symbol(s, "__arm_elf__", NULL);
9395 tcc_define_symbol(s, "__arm_elf", NULL);
9396 tcc_define_symbol(s, "arm_elf", NULL);
9397 tcc_define_symbol(s, "__arm__", NULL);
9398 tcc_define_symbol(s, "__arm", NULL);
9399 tcc_define_symbol(s, "arm", NULL);
9400 tcc_define_symbol(s, "__APCS_32__", NULL);
9401 #endif
9402 #if defined(linux)
9403 tcc_define_symbol(s, "__linux__", NULL);
9404 tcc_define_symbol(s, "linux", NULL);
9405 #endif
9406 /* tiny C specific defines */
9407 tcc_define_symbol(s, "__TINYC__", NULL);
9409 /* tiny C & gcc defines */
9410 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9411 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9412 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9414 /* default library paths */
9415 tcc_add_library_path(s, "/usr/local/lib");
9416 tcc_add_library_path(s, "/usr/lib");
9417 tcc_add_library_path(s, "/lib");
9419 /* no section zero */
9420 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9422 /* create standard sections */
9423 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9424 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9425 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9427 /* symbols are always generated for linking stage */
9428 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9429 ".strtab",
9430 ".hashtab", SHF_PRIVATE);
9431 strtab_section = symtab_section->link;
9433 /* private symbol table for dynamic symbols */
9434 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9435 ".dynstrtab",
9436 ".dynhashtab", SHF_PRIVATE);
9437 s->alacarte_link = 1;
9439 #ifdef CHAR_IS_UNSIGNED
9440 s->char_is_unsigned = 1;
9441 #endif
9442 return s;
9445 void tcc_delete(TCCState *s1)
9447 int i, n;
9449 /* free -D defines */
9450 free_defines(NULL);
9452 /* free tokens */
9453 n = tok_ident - TOK_IDENT;
9454 for(i = 0; i < n; i++)
9455 tcc_free(table_ident[i]);
9456 tcc_free(table_ident);
9458 /* free all sections */
9460 free_section(symtab_section->hash);
9462 free_section(s1->dynsymtab_section->hash);
9463 free_section(s1->dynsymtab_section->link);
9464 free_section(s1->dynsymtab_section);
9466 for(i = 1; i < s1->nb_sections; i++)
9467 free_section(s1->sections[i]);
9468 tcc_free(s1->sections);
9470 /* free loaded dlls array */
9471 for(i = 0; i < s1->nb_loaded_dlls; i++)
9472 tcc_free(s1->loaded_dlls[i]);
9473 tcc_free(s1->loaded_dlls);
9475 /* library paths */
9476 for(i = 0; i < s1->nb_library_paths; i++)
9477 tcc_free(s1->library_paths[i]);
9478 tcc_free(s1->library_paths);
9480 /* cached includes */
9481 for(i = 0; i < s1->nb_cached_includes; i++)
9482 tcc_free(s1->cached_includes[i]);
9483 tcc_free(s1->cached_includes);
9485 for(i = 0; i < s1->nb_include_paths; i++)
9486 tcc_free(s1->include_paths[i]);
9487 tcc_free(s1->include_paths);
9489 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9490 tcc_free(s1->sysinclude_paths[i]);
9491 tcc_free(s1->sysinclude_paths);
9493 tcc_free(s1);
9496 int tcc_add_include_path(TCCState *s1, const char *pathname)
9498 char *pathname1;
9500 pathname1 = tcc_strdup(pathname);
9501 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9502 return 0;
9505 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9507 char *pathname1;
9509 pathname1 = tcc_strdup(pathname);
9510 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9511 return 0;
9514 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9516 const char *ext, *filename1;
9517 Elf32_Ehdr ehdr;
9518 int fd, ret;
9519 BufferedFile *saved_file;
9521 /* find source file type with extension */
9522 filename1 = strrchr(filename, '/');
9523 if (filename1)
9524 filename1++;
9525 else
9526 filename1 = filename;
9527 ext = strrchr(filename1, '.');
9528 if (ext)
9529 ext++;
9531 /* open the file */
9532 saved_file = file;
9533 file = tcc_open(s1, filename);
9534 if (!file) {
9535 if (flags & AFF_PRINT_ERROR) {
9536 error_noabort("file '%s' not found", filename);
9538 ret = -1;
9539 goto fail1;
9542 if (!ext || !strcmp(ext, "c")) {
9543 /* C file assumed */
9544 ret = tcc_compile(s1);
9545 } else
9546 #ifdef CONFIG_TCC_ASM
9547 if (!strcmp(ext, "S")) {
9548 /* preprocessed assembler */
9549 ret = tcc_assemble(s1, 1);
9550 } else if (!strcmp(ext, "s")) {
9551 /* non preprocessed assembler */
9552 ret = tcc_assemble(s1, 0);
9553 } else
9554 #endif
9556 fd = file->fd;
9557 /* assume executable format: auto guess file type */
9558 ret = read(fd, &ehdr, sizeof(ehdr));
9559 lseek(fd, 0, SEEK_SET);
9560 if (ret <= 0) {
9561 error_noabort("could not read header");
9562 goto fail;
9563 } else if (ret != sizeof(ehdr)) {
9564 goto try_load_script;
9567 if (ehdr.e_ident[0] == ELFMAG0 &&
9568 ehdr.e_ident[1] == ELFMAG1 &&
9569 ehdr.e_ident[2] == ELFMAG2 &&
9570 ehdr.e_ident[3] == ELFMAG3) {
9571 file->line_num = 0; /* do not display line number if error */
9572 if (ehdr.e_type == ET_REL) {
9573 ret = tcc_load_object_file(s1, fd, 0);
9574 } else if (ehdr.e_type == ET_DYN) {
9575 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9576 void *h;
9577 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9578 if (h)
9579 ret = 0;
9580 else
9581 ret = -1;
9582 } else {
9583 ret = tcc_load_dll(s1, fd, filename,
9584 (flags & AFF_REFERENCED_DLL) != 0);
9586 } else {
9587 error_noabort("unrecognized ELF file");
9588 goto fail;
9590 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9591 file->line_num = 0; /* do not display line number if error */
9592 ret = tcc_load_archive(s1, fd);
9593 } else
9594 #ifdef TCC_TARGET_COFF
9595 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
9596 ret = tcc_load_coff(s1, fd);
9597 } else
9598 #endif
9600 /* as GNU ld, consider it is an ld script if not recognized */
9601 try_load_script:
9602 ret = tcc_load_ldscript(s1);
9603 if (ret < 0) {
9604 error_noabort("unrecognized file type");
9605 goto fail;
9609 the_end:
9610 tcc_close(file);
9611 fail1:
9612 file = saved_file;
9613 return ret;
9614 fail:
9615 ret = -1;
9616 goto the_end;
9619 int tcc_add_file(TCCState *s, const char *filename)
9621 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9624 int tcc_add_library_path(TCCState *s, const char *pathname)
9626 char *pathname1;
9628 pathname1 = tcc_strdup(pathname);
9629 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9630 return 0;
9633 /* find and load a dll. Return non zero if not found */
9634 /* XXX: add '-rpath' option support ? */
9635 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9637 char buf[1024];
9638 int i;
9640 for(i = 0; i < s->nb_library_paths; i++) {
9641 snprintf(buf, sizeof(buf), "%s/%s",
9642 s->library_paths[i], filename);
9643 if (tcc_add_file_internal(s, buf, flags) == 0)
9644 return 0;
9646 return -1;
9649 /* the library name is the same as the argument of the '-l' option */
9650 int tcc_add_library(TCCState *s, const char *libraryname)
9652 char buf[1024];
9653 int i;
9655 /* first we look for the dynamic library if not static linking */
9656 if (!s->static_link) {
9657 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9658 if (tcc_add_dll(s, buf, 0) == 0)
9659 return 0;
9662 /* then we look for the static library */
9663 for(i = 0; i < s->nb_library_paths; i++) {
9664 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9665 s->library_paths[i], libraryname);
9666 if (tcc_add_file_internal(s, buf, 0) == 0)
9667 return 0;
9669 return -1;
9672 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9674 add_elf_sym(symtab_section, val, 0,
9675 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9676 SHN_ABS, name);
9677 return 0;
9680 int tcc_set_output_type(TCCState *s, int output_type)
9682 char buf[1024];
9684 s->output_type = output_type;
9686 if (!s->nostdinc) {
9687 /* default include paths */
9688 /* XXX: reverse order needed if -isystem support */
9689 tcc_add_sysinclude_path(s, "/usr/local/include");
9690 tcc_add_sysinclude_path(s, "/usr/include");
9691 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9692 tcc_add_sysinclude_path(s, buf);
9695 /* if bound checking, then add corresponding sections */
9696 #ifdef CONFIG_TCC_BCHECK
9697 if (do_bounds_check) {
9698 /* define symbol */
9699 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9700 /* create bounds sections */
9701 bounds_section = new_section(s, ".bounds",
9702 SHT_PROGBITS, SHF_ALLOC);
9703 lbounds_section = new_section(s, ".lbounds",
9704 SHT_PROGBITS, SHF_ALLOC);
9706 #endif
9708 if (s->char_is_unsigned) {
9709 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
9712 /* add debug sections */
9713 if (do_debug) {
9714 /* stab symbols */
9715 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9716 stab_section->sh_entsize = sizeof(Stab_Sym);
9717 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9718 put_elf_str(stabstr_section, "");
9719 stab_section->link = stabstr_section;
9720 /* put first entry */
9721 put_stabs("", 0, 0, 0, 0);
9724 /* add libc crt1/crti objects */
9725 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9726 !s->nostdlib) {
9727 if (output_type != TCC_OUTPUT_DLL)
9728 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9729 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9731 return 0;
9734 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9735 #define FD_INVERT 0x0002 /* invert value before storing */
9737 typedef struct FlagDef {
9738 uint16_t offset;
9739 uint16_t flags;
9740 const char *name;
9741 } FlagDef;
9743 static const FlagDef warning_defs[] = {
9744 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9745 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9746 { offsetof(TCCState, warn_error), 0, "error" },
9747 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
9748 "implicit-function-declaration" },
9751 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
9752 const char *name, int value)
9754 int i;
9755 const FlagDef *p;
9756 const char *r;
9758 r = name;
9759 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
9760 r += 3;
9761 value = !value;
9763 for(i = 0, p = flags; i < nb_flags; i++, p++) {
9764 if (!strcmp(r, p->name))
9765 goto found;
9767 return -1;
9768 found:
9769 if (p->flags & FD_INVERT)
9770 value = !value;
9771 *(int *)((uint8_t *)s + p->offset) = value;
9772 return 0;
9776 /* set/reset a warning */
9777 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9779 int i;
9780 const FlagDef *p;
9782 if (!strcmp(warning_name, "all")) {
9783 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9784 if (p->flags & WD_ALL)
9785 *(int *)((uint8_t *)s + p->offset) = 1;
9787 return 0;
9788 } else {
9789 return set_flag(s, warning_defs, countof(warning_defs),
9790 warning_name, value);
9794 static const FlagDef flag_defs[] = {
9795 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
9796 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
9799 /* set/reset a flag */
9800 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
9802 return set_flag(s, flag_defs, countof(flag_defs),
9803 flag_name, value);
9806 #if !defined(LIBTCC)
9808 /* extract the basename of a file */
9809 static const char *tcc_basename(const char *name)
9811 const char *p;
9812 p = strrchr(name, '/');
9813 #ifdef WIN32
9814 if (!p)
9815 p = strrchr(name, '\\');
9816 #endif
9817 if (!p)
9818 p = name;
9819 else
9820 p++;
9821 return p;
9824 static int64_t getclock_us(void)
9826 #ifdef WIN32
9827 struct _timeb tb;
9828 _ftime(&tb);
9829 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9830 #else
9831 struct timeval tv;
9832 gettimeofday(&tv, NULL);
9833 return tv.tv_sec * 1000000LL + tv.tv_usec;
9834 #endif
9837 void help(void)
9839 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2003 Fabrice Bellard\n"
9840 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9841 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9842 " [infile1 infile2...] [-run infile args...]\n"
9843 "\n"
9844 "General options:\n"
9845 " -v display current version\n"
9846 " -c compile only - generate an object file\n"
9847 " -o outfile set output filename\n"
9848 " -Bdir set tcc internal library path\n"
9849 " -bench output compilation statistics\n"
9850 " -run run compiled source\n"
9851 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
9852 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
9853 " -w disable all warnings\n"
9854 "Preprocessor options:\n"
9855 " -Idir add include path 'dir'\n"
9856 " -Dsym[=val] define 'sym' with value 'val'\n"
9857 " -Usym undefine 'sym'\n"
9858 "Linker options:\n"
9859 " -Ldir add library path 'dir'\n"
9860 " -llib link with dynamic or static library 'lib'\n"
9861 " -shared generate a shared library\n"
9862 " -static static linking\n"
9863 " -rdynamic export all global symbols to dynamic linker\n"
9864 " -r relocatable output\n"
9865 "Debugger options:\n"
9866 " -g generate runtime debug info\n"
9867 #ifdef CONFIG_TCC_BCHECK
9868 " -b compile with built-in memory and bounds checker (implies -g)\n"
9869 #endif
9870 " -bt N show N callers in stack traces\n"
9874 #define TCC_OPTION_HAS_ARG 0x0001
9875 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9877 typedef struct TCCOption {
9878 const char *name;
9879 uint16_t index;
9880 uint16_t flags;
9881 } TCCOption;
9883 enum {
9884 TCC_OPTION_HELP,
9885 TCC_OPTION_I,
9886 TCC_OPTION_D,
9887 TCC_OPTION_U,
9888 TCC_OPTION_L,
9889 TCC_OPTION_B,
9890 TCC_OPTION_l,
9891 TCC_OPTION_bench,
9892 TCC_OPTION_bt,
9893 TCC_OPTION_b,
9894 TCC_OPTION_g,
9895 TCC_OPTION_c,
9896 TCC_OPTION_static,
9897 TCC_OPTION_shared,
9898 TCC_OPTION_o,
9899 TCC_OPTION_r,
9900 TCC_OPTION_W,
9901 TCC_OPTION_O,
9902 TCC_OPTION_m,
9903 TCC_OPTION_f,
9904 TCC_OPTION_nostdinc,
9905 TCC_OPTION_nostdlib,
9906 TCC_OPTION_print_search_dirs,
9907 TCC_OPTION_rdynamic,
9908 TCC_OPTION_run,
9909 TCC_OPTION_v,
9910 TCC_OPTION_w,
9913 static const TCCOption tcc_options[] = {
9914 { "h", TCC_OPTION_HELP, 0 },
9915 { "?", TCC_OPTION_HELP, 0 },
9916 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9917 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9918 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9919 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9920 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9921 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9922 { "bench", TCC_OPTION_bench, 0 },
9923 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9924 #ifdef CONFIG_TCC_BCHECK
9925 { "b", TCC_OPTION_b, 0 },
9926 #endif
9927 { "g", TCC_OPTION_g, 0 },
9928 { "c", TCC_OPTION_c, 0 },
9929 { "static", TCC_OPTION_static, 0 },
9930 { "shared", TCC_OPTION_shared, 0 },
9931 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9932 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9933 { "rdynamic", TCC_OPTION_rdynamic, 0 },
9934 { "r", TCC_OPTION_r, 0 },
9935 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9936 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9937 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9938 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9939 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9940 { "nostdlib", TCC_OPTION_nostdlib, 0 },
9941 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9942 { "v", TCC_OPTION_v, 0 },
9943 { "w", TCC_OPTION_w, 0 },
9944 { NULL },
9947 /* convert 'str' into an array of space separated strings */
9948 static int expand_args(char ***pargv, const char *str)
9950 const char *s1;
9951 char **argv, *arg;
9952 int argc, len;
9954 argc = 0;
9955 argv = NULL;
9956 for(;;) {
9957 while (is_space(*str))
9958 str++;
9959 if (*str == '\0')
9960 break;
9961 s1 = str;
9962 while (*str != '\0' && !is_space(*str))
9963 str++;
9964 len = str - s1;
9965 arg = tcc_malloc(len + 1);
9966 memcpy(arg, s1, len);
9967 arg[len] = '\0';
9968 dynarray_add((void ***)&argv, &argc, arg);
9970 *pargv = argv;
9971 return argc;
9974 static char **files;
9975 static int nb_files, nb_libraries;
9976 static int multiple_files;
9977 static int print_search_dirs;
9978 static int output_type;
9979 static int reloc_output;
9980 static const char *outfile;
9982 int parse_args(TCCState *s, int argc, char **argv)
9984 int optind;
9985 const TCCOption *popt;
9986 const char *optarg, *p1, *r1;
9987 char *r;
9989 optind = 0;
9990 while (1) {
9991 if (optind >= argc) {
9992 if (nb_files == 0 && !print_search_dirs)
9993 goto show_help;
9994 else
9995 break;
9997 r = argv[optind++];
9998 if (r[0] != '-') {
9999 /* add a new file */
10000 dynarray_add((void ***)&files, &nb_files, r);
10001 if (!multiple_files) {
10002 optind--;
10003 /* argv[0] will be this file */
10004 break;
10006 } else {
10007 /* find option in table (match only the first chars */
10008 popt = tcc_options;
10009 for(;;) {
10010 p1 = popt->name;
10011 if (p1 == NULL)
10012 error("invalid option -- '%s'", r);
10013 r1 = r + 1;
10014 for(;;) {
10015 if (*p1 == '\0')
10016 goto option_found;
10017 if (*r1 != *p1)
10018 break;
10019 p1++;
10020 r1++;
10022 popt++;
10024 option_found:
10025 if (popt->flags & TCC_OPTION_HAS_ARG) {
10026 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10027 optarg = r1;
10028 } else {
10029 if (optind >= argc)
10030 error("argument to '%s' is missing", r);
10031 optarg = argv[optind++];
10033 } else {
10034 if (*r1 != '\0')
10035 goto show_help;
10036 optarg = NULL;
10039 switch(popt->index) {
10040 case TCC_OPTION_HELP:
10041 show_help:
10042 help();
10043 exit(1);
10044 case TCC_OPTION_I:
10045 if (tcc_add_include_path(s, optarg) < 0)
10046 error("too many include paths");
10047 break;
10048 case TCC_OPTION_D:
10050 char *sym, *value;
10051 sym = (char *)optarg;
10052 value = strchr(sym, '=');
10053 if (value) {
10054 *value = '\0';
10055 value++;
10057 tcc_define_symbol(s, sym, value);
10059 break;
10060 case TCC_OPTION_U:
10061 tcc_undefine_symbol(s, optarg);
10062 break;
10063 case TCC_OPTION_L:
10064 tcc_add_library_path(s, optarg);
10065 break;
10066 case TCC_OPTION_B:
10067 /* set tcc utilities path (mainly for tcc development) */
10068 tcc_lib_path = optarg;
10069 break;
10070 case TCC_OPTION_l:
10071 dynarray_add((void ***)&files, &nb_files, r);
10072 nb_libraries++;
10073 break;
10074 case TCC_OPTION_bench:
10075 do_bench = 1;
10076 break;
10077 case TCC_OPTION_bt:
10078 num_callers = atoi(optarg);
10079 break;
10080 #ifdef CONFIG_TCC_BCHECK
10081 case TCC_OPTION_b:
10082 do_bounds_check = 1;
10083 do_debug = 1;
10084 break;
10085 #endif
10086 case TCC_OPTION_g:
10087 do_debug = 1;
10088 break;
10089 case TCC_OPTION_c:
10090 multiple_files = 1;
10091 output_type = TCC_OUTPUT_OBJ;
10092 break;
10093 case TCC_OPTION_static:
10094 s->static_link = 1;
10095 break;
10096 case TCC_OPTION_shared:
10097 output_type = TCC_OUTPUT_DLL;
10098 break;
10099 case TCC_OPTION_o:
10100 multiple_files = 1;
10101 outfile = optarg;
10102 break;
10103 case TCC_OPTION_r:
10104 /* generate a .o merging several output files */
10105 reloc_output = 1;
10106 output_type = TCC_OUTPUT_OBJ;
10107 break;
10108 case TCC_OPTION_nostdinc:
10109 s->nostdinc = 1;
10110 break;
10111 case TCC_OPTION_nostdlib:
10112 s->nostdlib = 1;
10113 break;
10114 case TCC_OPTION_print_search_dirs:
10115 print_search_dirs = 1;
10116 break;
10117 case TCC_OPTION_run:
10119 int argc1;
10120 char **argv1;
10121 argc1 = expand_args(&argv1, optarg);
10122 if (argc1 > 0) {
10123 parse_args(s, argc1, argv1);
10125 multiple_files = 0;
10126 output_type = TCC_OUTPUT_MEMORY;
10128 break;
10129 case TCC_OPTION_v:
10130 printf("tcc version %s\n", TCC_VERSION);
10131 exit(0);
10132 case TCC_OPTION_f:
10133 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10134 goto unsupported_option;
10135 break;
10136 case TCC_OPTION_W:
10137 if (tcc_set_warning(s, optarg, 1) < 0 &&
10138 s->warn_unsupported)
10139 goto unsupported_option;
10140 break;
10141 case TCC_OPTION_w:
10142 s->warn_none = 1;
10143 break;
10144 case TCC_OPTION_rdynamic:
10145 s->rdynamic = 1;
10146 break;
10147 default:
10148 if (s->warn_unsupported) {
10149 unsupported_option:
10150 warning("unsupported option '%s'", r);
10152 break;
10156 return optind;
10159 int main(int argc, char **argv)
10161 int i;
10162 TCCState *s;
10163 int nb_objfiles, ret, optind;
10164 char objfilename[1024];
10165 int64_t start_time = 0;
10167 s = tcc_new();
10168 output_type = TCC_OUTPUT_EXE;
10169 outfile = NULL;
10170 multiple_files = 1;
10171 files = NULL;
10172 nb_files = 0;
10173 nb_libraries = 0;
10174 reloc_output = 0;
10175 print_search_dirs = 0;
10177 optind = parse_args(s, argc - 1, argv + 1) + 1;
10179 if (print_search_dirs) {
10180 /* enough for Linux kernel */
10181 printf("install: %s/\n", tcc_lib_path);
10182 return 0;
10185 nb_objfiles = nb_files - nb_libraries;
10187 /* if outfile provided without other options, we output an
10188 executable */
10189 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10190 output_type = TCC_OUTPUT_EXE;
10192 /* check -c consistency : only single file handled. XXX: checks file type */
10193 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10194 /* accepts only a single input file */
10195 if (nb_objfiles != 1)
10196 error("cannot specify multiple files with -c");
10197 if (nb_libraries != 0)
10198 error("cannot specify libraries with -c");
10201 /* compute default outfile name */
10202 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
10203 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10204 char *ext;
10205 /* strip path */
10206 pstrcpy(objfilename, sizeof(objfilename) - 1,
10207 tcc_basename(files[0]));
10208 /* add .o extension */
10209 ext = strrchr(objfilename, '.');
10210 if (!ext)
10211 goto default_outfile;
10212 strcpy(ext + 1, "o");
10213 } else {
10214 default_outfile:
10215 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10217 outfile = objfilename;
10220 if (do_bench) {
10221 start_time = getclock_us();
10224 tcc_set_output_type(s, output_type);
10226 /* compile or add each files or library */
10227 for(i = 0;i < nb_files; i++) {
10228 const char *filename;
10230 filename = files[i];
10231 if (filename[0] == '-') {
10232 if (tcc_add_library(s, filename + 2) < 0)
10233 error("cannot find %s", filename);
10234 } else {
10235 if (tcc_add_file(s, filename) < 0) {
10236 ret = 1;
10237 goto the_end;
10242 /* free all files */
10243 tcc_free(files);
10245 if (do_bench) {
10246 double total_time;
10247 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10248 if (total_time < 0.001)
10249 total_time = 0.001;
10250 if (total_bytes < 1)
10251 total_bytes = 1;
10252 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10253 tok_ident - TOK_IDENT, total_lines, total_bytes,
10254 total_time, (int)(total_lines / total_time),
10255 total_bytes / total_time / 1000000.0);
10258 if (s->output_type != TCC_OUTPUT_MEMORY) {
10259 tcc_output_file(s, outfile);
10260 ret = 0;
10261 } else {
10262 ret = tcc_run(s, argc - optind, argv + optind);
10264 the_end:
10265 /* XXX: cannot do it with bound checking because of the malloc hooks */
10266 if (!do_bounds_check)
10267 tcc_delete(s);
10269 #ifdef MEM_DEBUG
10270 if (do_bench) {
10271 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10273 #endif
10274 return ret;
10277 #endif