.gnu.linkonce section support (useful to link with recent glibc)
[tinycc.git] / tcc.c
blobb5860c35cf25ea0391ac618be151dfa5befaa0d7
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define _GNU_SOURCE
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <math.h>
29 #include <unistd.h>
30 #include <signal.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <setjmp.h>
34 #include <time.h>
35 #ifdef WIN32
36 #include <sys/timeb.h>
37 #endif
38 #ifndef WIN32
39 #include <sys/time.h>
40 #include <sys/ucontext.h>
41 #endif
42 #include "elf.h"
43 #include "stab.h"
44 #ifndef CONFIG_TCC_STATIC
45 #include <dlfcn.h>
46 #endif
48 #include "libtcc.h"
50 /* parser debug */
51 //#define PARSE_DEBUG
52 /* preprocessor debug */
53 //#define PP_DEBUG
54 /* include file debug */
55 //#define INC_DEBUG
57 //#define MEM_DEBUG
59 /* assembler debug */
60 //#define ASM_DEBUG
62 /* target selection */
63 //#define TCC_TARGET_I386 /* i386 code generator */
65 /* default target is I386 */
66 #if !defined(TCC_TARGET_I386)
67 #define TCC_TARGET_I386
68 #endif
70 #if !defined(WIN32) && !defined(TCC_UCLIBC)
71 #define CONFIG_TCC_BCHECK /* enable bound checking code */
72 #endif
74 /* define it to include assembler support */
75 #define CONFIG_TCC_ASM
77 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
78 executables or dlls */
79 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
81 #define INCLUDE_STACK_SIZE 32
82 #define IFDEF_STACK_SIZE 64
83 #define VSTACK_SIZE 64
84 #define STRING_MAX_SIZE 1024
86 #define TOK_HASH_SIZE 2048 /* must be a power of two */
87 #define TOK_ALLOC_INCR 512 /* must be a power of two */
88 #define TOK_STR_ALLOC_INCR_BITS 6
89 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
90 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
92 /* token symbol management */
93 typedef struct TokenSym {
94 struct TokenSym *hash_next;
95 struct Sym *sym_define; /* direct pointer to define */
96 struct Sym *sym_label; /* direct pointer to label */
97 struct Sym *sym_struct; /* direct pointer to structure */
98 struct Sym *sym_identifier; /* direct pointer to identifier */
99 int tok; /* token number */
100 int len;
101 char str[1];
102 } TokenSym;
104 typedef struct CString {
105 int size; /* size in bytes */
106 void *data; /* either 'char *' or 'int *' */
107 int size_allocated;
108 void *data_allocated; /* if non NULL, data has been malloced */
109 } CString;
111 /* type definition */
112 typedef struct CType {
113 int t;
114 struct Sym *ref;
115 } CType;
117 /* constant value */
118 typedef union CValue {
119 long double ld;
120 double d;
121 float f;
122 int i;
123 unsigned int ui;
124 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
125 long long ll;
126 unsigned long long ull;
127 struct CString *cstr;
128 void *ptr;
129 int tab[1];
130 } CValue;
132 /* value on stack */
133 typedef struct SValue {
134 CType type; /* type */
135 unsigned short r; /* register + flags */
136 unsigned short r2; /* second register, used for 'long long'
137 type. If not used, set to VT_CONST */
138 CValue c; /* constant, if VT_CONST */
139 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
140 } SValue;
142 /* symbol management */
143 typedef struct Sym {
144 int v; /* symbol token */
145 int r; /* associated register */
146 int c; /* associated number */
147 CType type; /* associated type */
148 struct Sym *next; /* next related symbol */
149 struct Sym *prev; /* prev symbol in stack */
150 struct Sym *prev_tok; /* previous symbol for this token */
151 } Sym;
153 /* section definition */
154 /* XXX: use directly ELF structure for parameters ? */
155 /* special flag to indicate that the section should not be linked to
156 the other ones */
157 #define SHF_PRIVATE 0x80000000
159 typedef struct Section {
160 unsigned long data_offset; /* current data offset */
161 unsigned char *data; /* section data */
162 unsigned long data_allocated; /* used for realloc() handling */
163 int sh_name; /* elf section name (only used during output) */
164 int sh_num; /* elf section number */
165 int sh_type; /* elf section type */
166 int sh_flags; /* elf section flags */
167 int sh_info; /* elf section info */
168 int sh_addralign; /* elf section alignment */
169 int sh_entsize; /* elf entry size */
170 unsigned long sh_size; /* section size (only used during output) */
171 unsigned long sh_addr; /* address at which the section is relocated */
172 unsigned long sh_offset; /* address at which the section is relocated */
173 int nb_hashed_syms; /* used to resize the hash table */
174 struct Section *link; /* link to another section */
175 struct Section *reloc; /* corresponding section for relocation, if any */
176 struct Section *hash; /* hash table for symbols */
177 struct Section *next;
178 char name[1]; /* section name */
179 } Section;
181 typedef struct DLLReference {
182 int level;
183 char name[1];
184 } DLLReference;
186 /* GNUC attribute definition */
187 typedef struct AttributeDef {
188 int aligned;
189 Section *section;
190 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
191 } AttributeDef;
193 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
194 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
195 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
197 /* stored in 'Sym.c' field */
198 #define FUNC_NEW 1 /* ansi function prototype */
199 #define FUNC_OLD 2 /* old function prototype */
200 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
202 /* stored in 'Sym.r' field */
203 #define FUNC_CDECL 0 /* standard c call */
204 #define FUNC_STDCALL 1 /* pascal c call */
206 /* field 'Sym.t' for macros */
207 #define MACRO_OBJ 0 /* object like macro */
208 #define MACRO_FUNC 1 /* function like macro */
210 /* field 'Sym.r' for C labels */
211 #define LABEL_DEFINED 0 /* label is defined */
212 #define LABEL_FORWARD 1 /* label is forward defined */
213 #define LABEL_DECLARED 2 /* label is declared but never used */
215 /* type_decl() types */
216 #define TYPE_ABSTRACT 1 /* type without variable */
217 #define TYPE_DIRECT 2 /* type with variable */
219 #define IO_BUF_SIZE 8192
221 typedef struct BufferedFile {
222 uint8_t *buf_ptr;
223 uint8_t *buf_end;
224 int fd;
225 int line_num; /* current line number - here to simplify code */
226 int ifndef_macro; /* #ifndef macro / #endif search */
227 int ifndef_macro_saved; /* saved ifndef_macro */
228 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
229 char inc_type; /* type of include */
230 char inc_filename[512]; /* filename specified by the user */
231 char filename[1024]; /* current filename - here to simplify code */
232 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
233 } BufferedFile;
235 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
236 #define CH_EOF (-1) /* end of file */
238 /* parsing state (used to save parser state to reparse part of the
239 source several times) */
240 typedef struct ParseState {
241 int *macro_ptr;
242 int line_num;
243 int tok;
244 CValue tokc;
245 } ParseState;
247 /* used to record tokens */
248 typedef struct TokenString {
249 int *str;
250 int len;
251 int allocated_len;
252 int last_line_num;
253 } TokenString;
255 /* include file cache, used to find files faster and also to eliminate
256 inclusion if the include file is protected by #ifndef ... #endif */
257 typedef struct CachedInclude {
258 int ifndef_macro;
259 char type; /* '"' or '>' to give include type */
260 char filename[1]; /* path specified in #include */
261 } CachedInclude;
263 /* parser */
264 static struct BufferedFile *file;
265 static int ch, tok;
266 static CValue tokc;
267 static CString tokcstr; /* current parsed string, if any */
268 /* additional informations about token */
269 static int tok_flags;
270 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
271 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
272 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
274 static int *macro_ptr, *macro_ptr_allocated;
275 static int *unget_saved_macro_ptr;
276 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
277 static int unget_buffer_enabled;
278 static int parse_flags;
279 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
280 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
281 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
282 token. line feed is also
283 returned at eof */
285 static Section *text_section, *data_section, *bss_section; /* predefined sections */
286 static Section *cur_text_section; /* current section where function code is
287 generated */
288 /* bound check related sections */
289 static Section *bounds_section; /* contains global data bound description */
290 static Section *lbounds_section; /* contains local data bound description */
291 /* symbol sections */
292 static Section *symtab_section, *strtab_section;
294 /* debug sections */
295 static Section *stab_section, *stabstr_section;
297 /* loc : local variable index
298 ind : output code index
299 rsym: return symbol
300 anon_sym: anonymous symbol index
302 static int rsym, anon_sym, ind, loc;
303 /* expression generation modifiers */
304 static int const_wanted; /* true if constant wanted */
305 static int nocode_wanted; /* true if no code generation wanted for an expression */
306 static int global_expr; /* true if compound literals must be allocated
307 globally (used during initializers parsing */
308 static CType func_vt; /* current function return type (used by return
309 instruction) */
310 static int func_vc;
311 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
312 static int tok_ident;
313 static TokenSym **table_ident;
314 static TokenSym *hash_ident[TOK_HASH_SIZE];
315 static char token_buf[STRING_MAX_SIZE + 1];
316 static char *funcname;
317 static Sym *global_stack, *local_stack;
318 static Sym *define_stack;
319 static Sym *global_label_stack, *local_label_stack;
321 static SValue vstack[VSTACK_SIZE], *vtop;
322 /* some predefined types */
323 static CType char_pointer_type, func_old_type, int_type;
324 /* true if isid(c) || isnum(c) */
325 static unsigned char isidnum_table[256];
327 /* compile with debug symbol (and use them if error during execution) */
328 static int do_debug = 0;
330 /* compile with built-in memory and bounds checker */
331 static int do_bounds_check = 0;
333 /* display benchmark infos */
334 #if !defined(LIBTCC)
335 static int do_bench = 0;
336 #endif
337 static int total_lines;
338 static int total_bytes;
340 /* use GNU C extensions */
341 static int gnu_ext = 1;
343 /* use Tiny C extensions */
344 static int tcc_ext = 1;
346 /* max number of callers shown if error */
347 static int num_callers = 6;
348 static const char **rt_bound_error_msg;
350 /* XXX: get rid of this ASAP */
351 static struct TCCState *tcc_state;
353 /* give the path of the tcc libraries */
354 static const char *tcc_lib_path = CONFIG_TCC_LIBDIR "/tcc";
356 struct TCCState {
357 int output_type;
359 BufferedFile **include_stack_ptr;
360 int *ifdef_stack_ptr;
362 /* include file handling */
363 char **include_paths;
364 int nb_include_paths;
365 char **sysinclude_paths;
366 int nb_sysinclude_paths;
367 CachedInclude **cached_includes;
368 int nb_cached_includes;
370 char **library_paths;
371 int nb_library_paths;
373 /* array of all loaded dlls (including those referenced by loaded
374 dlls) */
375 DLLReference **loaded_dlls;
376 int nb_loaded_dlls;
378 /* sections */
379 Section **sections;
380 int nb_sections; /* number of sections, including first dummy section */
382 /* got handling */
383 Section *got;
384 Section *plt;
385 unsigned long *got_offsets;
386 int nb_got_offsets;
387 /* give the correspondance from symtab indexes to dynsym indexes */
388 int *symtab_to_dynsym;
390 /* temporary dynamic symbol sections (for dll loading) */
391 Section *dynsymtab_section;
392 /* exported dynamic symbol section */
393 Section *dynsym;
395 int nostdinc; /* if true, no standard headers are added */
396 int nostdlib; /* if true, no standard libraries are added */
398 /* if true, static linking is performed */
399 int static_link;
401 /* if true, all symbols are exported */
402 int rdynamic;
404 /* if true, only link in referenced objects from archive */
405 int alacarte_link;
407 /* warning switches */
408 int warn_write_strings;
409 int warn_unsupported;
410 int warn_error;
411 int warn_none;
413 /* error handling */
414 void *error_opaque;
415 void (*error_func)(void *opaque, const char *msg);
416 int error_set_jmp_enabled;
417 jmp_buf error_jmp_buf;
418 int nb_errors;
420 /* tiny assembler state */
421 Sym *asm_labels;
423 /* see include_stack_ptr */
424 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
426 /* see ifdef_stack_ptr */
427 int ifdef_stack[IFDEF_STACK_SIZE];
430 /* The current value can be: */
431 #define VT_VALMASK 0x00ff
432 #define VT_CONST 0x00f0 /* constant in vc
433 (must be first non register value) */
434 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
435 #define VT_LOCAL 0x00f2 /* offset on stack */
436 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
437 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
438 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
439 #define VT_LVAL 0x0100 /* var is an lvalue */
440 #define VT_SYM 0x0200 /* a symbol value is added */
441 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
442 char/short stored in integer registers) */
443 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
444 dereferencing value */
445 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
446 bounding function call point is in vc */
447 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
448 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
449 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
450 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
452 /* types */
453 #define VT_INT 0 /* integer type */
454 #define VT_BYTE 1 /* signed byte type */
455 #define VT_SHORT 2 /* short type */
456 #define VT_VOID 3 /* void type */
457 #define VT_PTR 4 /* pointer */
458 #define VT_ENUM 5 /* enum definition */
459 #define VT_FUNC 6 /* function type */
460 #define VT_STRUCT 7 /* struct/union definition */
461 #define VT_FLOAT 8 /* IEEE float */
462 #define VT_DOUBLE 9 /* IEEE double */
463 #define VT_LDOUBLE 10 /* IEEE long double */
464 #define VT_BOOL 11 /* ISOC99 boolean type */
465 #define VT_LLONG 12 /* 64 bit integer */
466 #define VT_LONG 13 /* long integer (NEVER USED as type, only
467 during parsing) */
468 #define VT_BTYPE 0x000f /* mask for basic type */
469 #define VT_UNSIGNED 0x0010 /* unsigned type */
470 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
471 #define VT_BITFIELD 0x0040 /* bitfield modifier */
472 #define VT_CONSTANT 0x0800 /* const modifier */
473 #define VT_VOLATILE 0x1000 /* volatile modifier */
475 /* storage */
476 #define VT_EXTERN 0x00000080 /* extern definition */
477 #define VT_STATIC 0x00000100 /* static variable */
478 #define VT_TYPEDEF 0x00000200 /* typedef definition */
479 #define VT_INLINE 0x00000400 /* inline definition */
481 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
483 /* type mask (except storage) */
484 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
485 #define VT_TYPE (~(VT_STORAGE))
487 /* token values */
489 /* warning: the following compare tokens depend on i386 asm code */
490 #define TOK_ULT 0x92
491 #define TOK_UGE 0x93
492 #define TOK_EQ 0x94
493 #define TOK_NE 0x95
494 #define TOK_ULE 0x96
495 #define TOK_UGT 0x97
496 #define TOK_LT 0x9c
497 #define TOK_GE 0x9d
498 #define TOK_LE 0x9e
499 #define TOK_GT 0x9f
501 #define TOK_LAND 0xa0
502 #define TOK_LOR 0xa1
504 #define TOK_DEC 0xa2
505 #define TOK_MID 0xa3 /* inc/dec, to void constant */
506 #define TOK_INC 0xa4
507 #define TOK_UDIV 0xb0 /* unsigned division */
508 #define TOK_UMOD 0xb1 /* unsigned modulo */
509 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
510 #define TOK_CINT 0xb3 /* number in tokc */
511 #define TOK_CCHAR 0xb4 /* char constant in tokc */
512 #define TOK_STR 0xb5 /* pointer to string in tokc */
513 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
514 #define TOK_LCHAR 0xb7
515 #define TOK_LSTR 0xb8
516 #define TOK_CFLOAT 0xb9 /* float constant */
517 #define TOK_LINENUM 0xba /* line number info */
518 #define TOK_CDOUBLE 0xc0 /* double constant */
519 #define TOK_CLDOUBLE 0xc1 /* long double constant */
520 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
521 #define TOK_ADDC1 0xc3 /* add with carry generation */
522 #define TOK_ADDC2 0xc4 /* add with carry use */
523 #define TOK_SUBC1 0xc5 /* add with carry generation */
524 #define TOK_SUBC2 0xc6 /* add with carry use */
525 #define TOK_CUINT 0xc8 /* unsigned int constant */
526 #define TOK_CLLONG 0xc9 /* long long constant */
527 #define TOK_CULLONG 0xca /* unsigned long long constant */
528 #define TOK_ARROW 0xcb
529 #define TOK_DOTS 0xcc /* three dots */
530 #define TOK_SHR 0xcd /* unsigned shift right */
531 #define TOK_PPNUM 0xce /* preprocessor number */
533 #define TOK_SHL 0x01 /* shift left */
534 #define TOK_SAR 0x02 /* signed shift right */
536 /* assignement operators : normal operator or 0x80 */
537 #define TOK_A_MOD 0xa5
538 #define TOK_A_AND 0xa6
539 #define TOK_A_MUL 0xaa
540 #define TOK_A_ADD 0xab
541 #define TOK_A_SUB 0xad
542 #define TOK_A_DIV 0xaf
543 #define TOK_A_XOR 0xde
544 #define TOK_A_OR 0xfc
545 #define TOK_A_SHL 0x81
546 #define TOK_A_SAR 0x82
548 #ifndef offsetof
549 #define offsetof(type, field) ((size_t) &((type *)0)->field)
550 #endif
552 #ifndef countof
553 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
554 #endif
556 /* WARNING: the content of this string encodes token numbers */
557 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";
559 #define TOK_EOF (-1) /* end of file */
560 #define TOK_LINEFEED 10 /* line feed */
562 /* all identificators and strings have token above that */
563 #define TOK_IDENT 256
565 /* only used for i386 asm opcodes definitions */
566 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
568 #define DEF_BWL(x) \
569 DEF(TOK_ASM_ ## x ## b, #x "b") \
570 DEF(TOK_ASM_ ## x ## w, #x "w") \
571 DEF(TOK_ASM_ ## x ## l, #x "l") \
572 DEF(TOK_ASM_ ## x, #x)
574 #define DEF_WL(x) \
575 DEF(TOK_ASM_ ## x ## w, #x "w") \
576 DEF(TOK_ASM_ ## x ## l, #x "l") \
577 DEF(TOK_ASM_ ## x, #x)
579 #define DEF_FP1(x) \
580 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
581 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
582 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
583 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
585 #define DEF_FP(x) \
586 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
587 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
588 DEF_FP1(x)
590 #define DEF_ASMTEST(x) \
591 DEF_ASM(x ## o) \
592 DEF_ASM(x ## no) \
593 DEF_ASM(x ## b) \
594 DEF_ASM(x ## c) \
595 DEF_ASM(x ## nae) \
596 DEF_ASM(x ## nb) \
597 DEF_ASM(x ## nc) \
598 DEF_ASM(x ## ae) \
599 DEF_ASM(x ## e) \
600 DEF_ASM(x ## z) \
601 DEF_ASM(x ## ne) \
602 DEF_ASM(x ## nz) \
603 DEF_ASM(x ## be) \
604 DEF_ASM(x ## na) \
605 DEF_ASM(x ## nbe) \
606 DEF_ASM(x ## a) \
607 DEF_ASM(x ## s) \
608 DEF_ASM(x ## ns) \
609 DEF_ASM(x ## p) \
610 DEF_ASM(x ## pe) \
611 DEF_ASM(x ## np) \
612 DEF_ASM(x ## po) \
613 DEF_ASM(x ## l) \
614 DEF_ASM(x ## nge) \
615 DEF_ASM(x ## nl) \
616 DEF_ASM(x ## ge) \
617 DEF_ASM(x ## le) \
618 DEF_ASM(x ## ng) \
619 DEF_ASM(x ## nle) \
620 DEF_ASM(x ## g)
622 #define TOK_ASM_int TOK_INT
624 enum {
625 TOK_LAST = TOK_IDENT - 1,
626 #define DEF(id, str) id,
627 #include "tcctok.h"
628 #undef DEF
631 static const char tcc_keywords[] =
632 #define DEF(id, str) str "\0"
633 #include "tcctok.h"
634 #undef DEF
637 #define TOK_UIDENT TOK_DEFINE
639 #ifdef WIN32
640 #define snprintf _snprintf
641 #define vsnprintf _vsnprintf
642 #endif
644 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
645 /* currently incorrect */
646 long double strtold(const char *nptr, char **endptr)
648 return (long double)strtod(nptr, endptr);
650 float strtof(const char *nptr, char **endptr)
652 return (float)strtod(nptr, endptr);
654 #else
655 /* XXX: need to define this to use them in non ISOC99 context */
656 extern float strtof (const char *__nptr, char **__endptr);
657 extern long double strtold (const char *__nptr, char **__endptr);
658 #endif
660 static char *pstrcpy(char *buf, int buf_size, const char *s);
661 static char *pstrcat(char *buf, int buf_size, const char *s);
663 static void next(void);
664 static void next_nomacro(void);
665 static void parse_expr_type(CType *type);
666 static void expr_type(CType *type);
667 static void unary_type(CType *type);
668 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
669 int case_reg, int is_expr);
670 static int expr_const(void);
671 static void expr_eq(void);
672 static void gexpr(void);
673 static void decl(int l);
674 static void decl_initializer(CType *type, Section *sec, unsigned long c,
675 int first, int size_only);
676 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
677 int has_init, int v, int scope);
678 int gv(int rc);
679 void gv2(int rc1, int rc2);
680 void move_reg(int r, int s);
681 void save_regs(int n);
682 void save_reg(int r);
683 void vpop(void);
684 void vswap(void);
685 void vdup(void);
686 int get_reg(int rc);
688 static void macro_subst(TokenString *tok_str, Sym **nested_list,
689 const int *macro_str, int can_read_stream);
690 int save_reg_forced(int r);
691 void gen_op(int op);
692 void force_charshort_cast(int t);
693 static void gen_cast(CType *type);
694 void vstore(void);
695 static Sym *sym_find(int v);
696 static Sym *sym_push(int v, CType *type, int r, int c);
698 /* type handling */
699 static int type_size(CType *type, int *a);
700 static inline CType *pointed_type(CType *type);
701 static int pointed_size(CType *type);
702 static int lvalue_type(int t);
703 static int parse_btype(CType *type, AttributeDef *ad);
704 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
705 static int is_compatible_types(CType *type1, CType *type2);
707 void error(const char *fmt, ...);
708 void vpushi(int v);
709 void vset(CType *type, int r, int v);
710 void type_to_str(char *buf, int buf_size,
711 CType *type, const char *varstr);
712 char *get_tok_str(int v, CValue *cv);
713 static Sym *get_sym_ref(CType *type, Section *sec,
714 unsigned long offset, unsigned long size);
715 static Sym *external_global_sym(int v, CType *type, int r);
717 /* section generation */
718 static void section_realloc(Section *sec, unsigned long new_size);
719 static void *section_ptr_add(Section *sec, unsigned long size);
720 static void put_extern_sym(Sym *sym, Section *section,
721 unsigned long value, unsigned long size);
722 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
723 static int put_elf_str(Section *s, const char *sym);
724 static int put_elf_sym(Section *s,
725 unsigned long value, unsigned long size,
726 int info, int other, int shndx, const char *name);
727 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
728 int info, int sh_num, const char *name);
729 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
730 int type, int symbol);
731 static void put_stabs(const char *str, int type, int other, int desc,
732 unsigned long value);
733 static void put_stabs_r(const char *str, int type, int other, int desc,
734 unsigned long value, Section *sec, int sym_index);
735 static void put_stabn(int type, int other, int desc, int value);
736 static void put_stabd(int type, int other, int desc);
737 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
739 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
740 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
741 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
743 /* tccasm.c */
745 #ifdef CONFIG_TCC_ASM
747 typedef struct ExprValue {
748 uint32_t v;
749 Sym *sym;
750 } ExprValue;
752 #define MAX_ASM_OPERANDS 30
754 typedef struct ASMOperand {
755 int id; /* GCC 3 optionnal identifier (0 if number only supported */
756 char *constraint;
757 char asm_str[16]; /* computed asm string for operand */
758 SValue *vt; /* C value of the expression */
759 int ref_index; /* if >= 0, gives reference to a output constraint */
760 int priority; /* priority, used to assign registers */
761 int reg; /* if >= 0, register number used for this operand */
762 int is_llong; /* true if double register value */
763 } ASMOperand;
765 static void asm_expr(TCCState *s1, ExprValue *pe);
766 static int asm_int_expr(TCCState *s1);
767 static int find_constraint(ASMOperand *operands, int nb_operands,
768 const char *name, const char **pp);
770 static int tcc_assemble(TCCState *s1, int do_preprocess);
772 #endif
774 static void asm_instr(void);
776 /* true if float/double/long double type */
777 static inline int is_float(int t)
779 int bt;
780 bt = t & VT_BTYPE;
781 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
784 #ifdef TCC_TARGET_I386
785 #include "i386-gen.c"
786 #endif
788 #ifdef CONFIG_TCC_STATIC
790 #define RTLD_LAZY 0x001
791 #define RTLD_NOW 0x002
792 #define RTLD_GLOBAL 0x100
793 #define RTLD_DEFAULT NULL
795 /* dummy function for profiling */
796 void *dlopen(const char *filename, int flag)
798 return NULL;
801 const char *dlerror(void)
803 return "error";
806 typedef struct TCCSyms {
807 char *str;
808 void *ptr;
809 } TCCSyms;
811 #define TCCSYM(a) { #a, &a, },
813 /* add the symbol you want here if no dynamic linking is done */
814 static TCCSyms tcc_syms[] = {
815 TCCSYM(printf)
816 TCCSYM(fprintf)
817 TCCSYM(fopen)
818 TCCSYM(fclose)
819 { NULL, NULL },
822 void *dlsym(void *handle, const char *symbol)
824 TCCSyms *p;
825 p = tcc_syms;
826 while (p->str != NULL) {
827 if (!strcmp(p->str, symbol))
828 return p->ptr;
829 p++;
831 return NULL;
834 #endif
836 /********************************************************/
838 /* we use our own 'finite' function to avoid potential problems with
839 non standard math libs */
840 /* XXX: endianness dependent */
841 int ieee_finite(double d)
843 int *p = (int *)&d;
844 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
847 /* copy a string and truncate it. */
848 static char *pstrcpy(char *buf, int buf_size, const char *s)
850 char *q, *q_end;
851 int c;
853 if (buf_size > 0) {
854 q = buf;
855 q_end = buf + buf_size - 1;
856 while (q < q_end) {
857 c = *s++;
858 if (c == '\0')
859 break;
860 *q++ = c;
862 *q = '\0';
864 return buf;
867 /* strcat and truncate. */
868 static char *pstrcat(char *buf, int buf_size, const char *s)
870 int len;
871 len = strlen(buf);
872 if (len < buf_size)
873 pstrcpy(buf + len, buf_size - len, s);
874 return buf;
877 /* memory management */
878 #ifdef MEM_DEBUG
879 int mem_cur_size;
880 int mem_max_size;
881 #endif
883 static inline void tcc_free(void *ptr)
885 #ifdef MEM_DEBUG
886 mem_cur_size -= malloc_usable_size(ptr);
887 #endif
888 free(ptr);
891 static void *tcc_malloc(unsigned long size)
893 void *ptr;
894 ptr = malloc(size);
895 if (!ptr && size)
896 error("memory full");
897 #ifdef MEM_DEBUG
898 mem_cur_size += malloc_usable_size(ptr);
899 if (mem_cur_size > mem_max_size)
900 mem_max_size = mem_cur_size;
901 #endif
902 return ptr;
905 static void *tcc_mallocz(unsigned long size)
907 void *ptr;
908 ptr = tcc_malloc(size);
909 memset(ptr, 0, size);
910 return ptr;
913 static inline void *tcc_realloc(void *ptr, unsigned long size)
915 void *ptr1;
916 #ifdef MEM_DEBUG
917 mem_cur_size -= malloc_usable_size(ptr);
918 #endif
919 ptr1 = realloc(ptr, size);
920 #ifdef MEM_DEBUG
921 /* NOTE: count not correct if alloc error, but not critical */
922 mem_cur_size += malloc_usable_size(ptr1);
923 if (mem_cur_size > mem_max_size)
924 mem_max_size = mem_cur_size;
925 #endif
926 return ptr1;
929 static char *tcc_strdup(const char *str)
931 char *ptr;
932 ptr = tcc_malloc(strlen(str) + 1);
933 strcpy(ptr, str);
934 return ptr;
937 #define free(p) use_tcc_free(p)
938 #define malloc(s) use_tcc_malloc(s)
939 #define realloc(p, s) use_tcc_realloc(p, s)
941 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
943 int nb, nb_alloc;
944 void **pp;
946 nb = *nb_ptr;
947 pp = *ptab;
948 /* every power of two we double array size */
949 if ((nb & (nb - 1)) == 0) {
950 if (!nb)
951 nb_alloc = 1;
952 else
953 nb_alloc = nb * 2;
954 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
955 if (!pp)
956 error("memory full");
957 *ptab = pp;
959 pp[nb++] = data;
960 *nb_ptr = nb;
963 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
965 Section *sec;
967 sec = tcc_mallocz(sizeof(Section) + strlen(name));
968 strcpy(sec->name, name);
969 sec->sh_type = sh_type;
970 sec->sh_flags = sh_flags;
971 switch(sh_type) {
972 case SHT_HASH:
973 case SHT_REL:
974 case SHT_DYNSYM:
975 case SHT_SYMTAB:
976 case SHT_DYNAMIC:
977 sec->sh_addralign = 4;
978 break;
979 case SHT_STRTAB:
980 sec->sh_addralign = 1;
981 break;
982 default:
983 sec->sh_addralign = 32; /* default conservative alignment */
984 break;
987 /* only add section if not private */
988 if (!(sh_flags & SHF_PRIVATE)) {
989 sec->sh_num = s1->nb_sections;
990 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
992 return sec;
995 static void free_section(Section *s)
997 tcc_free(s->data);
998 tcc_free(s);
1001 /* realloc section and set its content to zero */
1002 static void section_realloc(Section *sec, unsigned long new_size)
1004 unsigned long size;
1005 unsigned char *data;
1007 size = sec->data_allocated;
1008 if (size == 0)
1009 size = 1;
1010 while (size < new_size)
1011 size = size * 2;
1012 data = tcc_realloc(sec->data, size);
1013 if (!data)
1014 error("memory full");
1015 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1016 sec->data = data;
1017 sec->data_allocated = size;
1020 /* reserve at least 'size' bytes in section 'sec' from
1021 sec->data_offset. */
1022 static void *section_ptr_add(Section *sec, unsigned long size)
1024 unsigned long offset, offset1;
1026 offset = sec->data_offset;
1027 offset1 = offset + size;
1028 if (offset1 > sec->data_allocated)
1029 section_realloc(sec, offset1);
1030 sec->data_offset = offset1;
1031 return sec->data + offset;
1034 /* return a reference to a section, and create it if it does not
1035 exists */
1036 Section *find_section(TCCState *s1, const char *name)
1038 Section *sec;
1039 int i;
1040 for(i = 1; i < s1->nb_sections; i++) {
1041 sec = s1->sections[i];
1042 if (!strcmp(name, sec->name))
1043 return sec;
1045 /* sections are created as PROGBITS */
1046 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1049 /* update sym->c so that it points to an external symbol in section
1050 'section' with value 'value' */
1051 static void put_extern_sym(Sym *sym, Section *section,
1052 unsigned long value, unsigned long size)
1054 int sym_type, sym_bind, sh_num, info;
1055 Elf32_Sym *esym;
1056 const char *name;
1058 if (section)
1059 sh_num = section->sh_num;
1060 else
1061 sh_num = SHN_UNDEF;
1062 if (!sym->c) {
1063 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1064 sym_type = STT_FUNC;
1065 else
1066 sym_type = STT_OBJECT;
1067 if (sym->type.t & VT_STATIC)
1068 sym_bind = STB_LOCAL;
1069 else
1070 sym_bind = STB_GLOBAL;
1072 name = get_tok_str(sym->v, NULL);
1073 #ifdef CONFIG_TCC_BCHECK
1074 if (do_bounds_check) {
1075 char buf[32];
1077 /* XXX: avoid doing that for statics ? */
1078 /* if bound checking is activated, we change some function
1079 names by adding the "__bound" prefix */
1080 switch(sym->v) {
1081 #if 0
1082 /* XXX: we rely only on malloc hooks */
1083 case TOK_malloc:
1084 case TOK_free:
1085 case TOK_realloc:
1086 case TOK_memalign:
1087 case TOK_calloc:
1088 #endif
1089 case TOK_memcpy:
1090 case TOK_memmove:
1091 case TOK_memset:
1092 case TOK_strlen:
1093 case TOK_strcpy:
1094 strcpy(buf, "__bound_");
1095 strcat(buf, name);
1096 name = buf;
1097 break;
1100 #endif
1101 info = ELF32_ST_INFO(sym_bind, sym_type);
1102 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1103 } else {
1104 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1105 esym->st_value = value;
1106 esym->st_size = size;
1107 esym->st_shndx = sh_num;
1111 /* add a new relocation entry to symbol 'sym' in section 's' */
1112 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1114 if (!sym->c)
1115 put_extern_sym(sym, NULL, 0, 0);
1116 /* now we can add ELF relocation info */
1117 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1120 static inline int isid(int c)
1122 return (c >= 'a' && c <= 'z') ||
1123 (c >= 'A' && c <= 'Z') ||
1124 c == '_';
1127 static inline int isnum(int c)
1129 return c >= '0' && c <= '9';
1132 static inline int isoct(int c)
1134 return c >= '0' && c <= '7';
1137 static inline int toup(int c)
1139 if (c >= 'a' && c <= 'z')
1140 return c - 'a' + 'A';
1141 else
1142 return c;
1145 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1147 int len;
1148 len = strlen(buf);
1149 vsnprintf(buf + len, buf_size - len, fmt, ap);
1152 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1154 va_list ap;
1155 va_start(ap, fmt);
1156 strcat_vprintf(buf, buf_size, fmt, ap);
1157 va_end(ap);
1160 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1162 char buf[2048];
1163 BufferedFile **f;
1165 buf[0] = '\0';
1166 if (file) {
1167 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1168 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1169 (*f)->filename, (*f)->line_num);
1170 if (file->line_num > 0) {
1171 strcat_printf(buf, sizeof(buf),
1172 "%s:%d: ", file->filename, file->line_num);
1173 } else {
1174 strcat_printf(buf, sizeof(buf),
1175 "%s: ", file->filename);
1177 } else {
1178 strcat_printf(buf, sizeof(buf),
1179 "tcc: ");
1181 if (is_warning)
1182 strcat_printf(buf, sizeof(buf), "warning: ");
1183 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1185 if (!s1->error_func) {
1186 /* default case: stderr */
1187 fprintf(stderr, "%s\n", buf);
1188 } else {
1189 s1->error_func(s1->error_opaque, buf);
1191 if (!is_warning || s1->warn_error)
1192 s1->nb_errors++;
1195 #ifdef LIBTCC
1196 void tcc_set_error_func(TCCState *s, void *error_opaque,
1197 void (*error_func)(void *opaque, const char *msg))
1199 s->error_opaque = error_opaque;
1200 s->error_func = error_func;
1202 #endif
1204 /* error without aborting current compilation */
1205 void error_noabort(const char *fmt, ...)
1207 TCCState *s1 = tcc_state;
1208 va_list ap;
1210 va_start(ap, fmt);
1211 error1(s1, 0, fmt, ap);
1212 va_end(ap);
1215 void error(const char *fmt, ...)
1217 TCCState *s1 = tcc_state;
1218 va_list ap;
1220 va_start(ap, fmt);
1221 error1(s1, 0, fmt, ap);
1222 va_end(ap);
1223 /* better than nothing: in some cases, we accept to handle errors */
1224 if (s1->error_set_jmp_enabled) {
1225 longjmp(s1->error_jmp_buf, 1);
1226 } else {
1227 /* XXX: eliminate this someday */
1228 exit(1);
1232 void expect(const char *msg)
1234 error("%s expected", msg);
1237 void warning(const char *fmt, ...)
1239 TCCState *s1 = tcc_state;
1240 va_list ap;
1242 if (s1->warn_none)
1243 return;
1245 va_start(ap, fmt);
1246 error1(s1, 1, fmt, ap);
1247 va_end(ap);
1250 void skip(int c)
1252 if (tok != c)
1253 error("'%c' expected", c);
1254 next();
1257 static void test_lvalue(void)
1259 if (!(vtop->r & VT_LVAL))
1260 expect("lvalue");
1263 /* allocate a new token */
1264 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1266 TokenSym *ts, **ptable;
1267 int i;
1269 if (tok_ident >= SYM_FIRST_ANOM)
1270 error("memory full");
1272 /* expand token table if needed */
1273 i = tok_ident - TOK_IDENT;
1274 if ((i % TOK_ALLOC_INCR) == 0) {
1275 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1276 if (!ptable)
1277 error("memory full");
1278 table_ident = ptable;
1281 ts = tcc_malloc(sizeof(TokenSym) + len);
1282 table_ident[i] = ts;
1283 ts->tok = tok_ident++;
1284 ts->sym_define = NULL;
1285 ts->sym_label = NULL;
1286 ts->sym_struct = NULL;
1287 ts->sym_identifier = NULL;
1288 ts->len = len;
1289 ts->hash_next = NULL;
1290 memcpy(ts->str, str, len);
1291 ts->str[len] = '\0';
1292 *pts = ts;
1293 return ts;
1296 #define TOK_HASH_INIT 1
1297 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1299 /* find a token and add it if not found */
1300 static TokenSym *tok_alloc(const char *str, int len)
1302 TokenSym *ts, **pts;
1303 int i;
1304 unsigned int h;
1306 h = TOK_HASH_INIT;
1307 for(i=0;i<len;i++)
1308 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1309 h &= (TOK_HASH_SIZE - 1);
1311 pts = &hash_ident[h];
1312 for(;;) {
1313 ts = *pts;
1314 if (!ts)
1315 break;
1316 if (ts->len == len && !memcmp(ts->str, str, len))
1317 return ts;
1318 pts = &(ts->hash_next);
1320 return tok_alloc_new(pts, str, len);
1323 /* CString handling */
1325 static void cstr_realloc(CString *cstr, int new_size)
1327 int size;
1328 void *data;
1330 size = cstr->size_allocated;
1331 if (size == 0)
1332 size = 8; /* no need to allocate a too small first string */
1333 while (size < new_size)
1334 size = size * 2;
1335 data = tcc_realloc(cstr->data_allocated, size);
1336 if (!data)
1337 error("memory full");
1338 cstr->data_allocated = data;
1339 cstr->size_allocated = size;
1340 cstr->data = data;
1343 /* add a byte */
1344 static void cstr_ccat(CString *cstr, int ch)
1346 int size;
1347 size = cstr->size + 1;
1348 if (size > cstr->size_allocated)
1349 cstr_realloc(cstr, size);
1350 ((unsigned char *)cstr->data)[size - 1] = ch;
1351 cstr->size = size;
1354 static void cstr_cat(CString *cstr, const char *str)
1356 int c;
1357 for(;;) {
1358 c = *str;
1359 if (c == '\0')
1360 break;
1361 cstr_ccat(cstr, c);
1362 str++;
1366 /* add a wide char */
1367 static void cstr_wccat(CString *cstr, int ch)
1369 int size;
1370 size = cstr->size + sizeof(int);
1371 if (size > cstr->size_allocated)
1372 cstr_realloc(cstr, size);
1373 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1374 cstr->size = size;
1377 static void cstr_new(CString *cstr)
1379 memset(cstr, 0, sizeof(CString));
1382 /* free string and reset it to NULL */
1383 static void cstr_free(CString *cstr)
1385 tcc_free(cstr->data_allocated);
1386 cstr_new(cstr);
1389 #define cstr_reset(cstr) cstr_free(cstr)
1391 static CString *cstr_dup(CString *cstr1)
1393 CString *cstr;
1394 int size;
1396 cstr = tcc_malloc(sizeof(CString));
1397 size = cstr1->size;
1398 cstr->size = size;
1399 cstr->size_allocated = size;
1400 cstr->data_allocated = tcc_malloc(size);
1401 cstr->data = cstr->data_allocated;
1402 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1403 return cstr;
1406 /* XXX: unicode ? */
1407 static void add_char(CString *cstr, int c)
1409 if (c == '\'' || c == '\"' || c == '\\') {
1410 /* XXX: could be more precise if char or string */
1411 cstr_ccat(cstr, '\\');
1413 if (c >= 32 && c <= 126) {
1414 cstr_ccat(cstr, c);
1415 } else {
1416 cstr_ccat(cstr, '\\');
1417 if (c == '\n') {
1418 cstr_ccat(cstr, 'n');
1419 } else {
1420 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1421 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1422 cstr_ccat(cstr, '0' + (c & 7));
1427 /* XXX: buffer overflow */
1428 /* XXX: float tokens */
1429 char *get_tok_str(int v, CValue *cv)
1431 static char buf[STRING_MAX_SIZE + 1];
1432 static CString cstr_buf;
1433 CString *cstr;
1434 unsigned char *q;
1435 char *p;
1436 int i, len;
1438 /* NOTE: to go faster, we give a fixed buffer for small strings */
1439 cstr_reset(&cstr_buf);
1440 cstr_buf.data = buf;
1441 cstr_buf.size_allocated = sizeof(buf);
1442 p = buf;
1444 switch(v) {
1445 case TOK_CINT:
1446 case TOK_CUINT:
1447 /* XXX: not quite exact, but only useful for testing */
1448 sprintf(p, "%u", cv->ui);
1449 break;
1450 case TOK_CLLONG:
1451 case TOK_CULLONG:
1452 /* XXX: not quite exact, but only useful for testing */
1453 sprintf(p, "%Lu", cv->ull);
1454 break;
1455 case TOK_CCHAR:
1456 case TOK_LCHAR:
1457 cstr_ccat(&cstr_buf, '\'');
1458 add_char(&cstr_buf, cv->i);
1459 cstr_ccat(&cstr_buf, '\'');
1460 cstr_ccat(&cstr_buf, '\0');
1461 break;
1462 case TOK_PPNUM:
1463 cstr = cv->cstr;
1464 len = cstr->size - 1;
1465 for(i=0;i<len;i++)
1466 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1467 cstr_ccat(&cstr_buf, '\0');
1468 break;
1469 case TOK_STR:
1470 case TOK_LSTR:
1471 cstr = cv->cstr;
1472 cstr_ccat(&cstr_buf, '\"');
1473 if (v == TOK_STR) {
1474 len = cstr->size - 1;
1475 for(i=0;i<len;i++)
1476 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1477 } else {
1478 len = (cstr->size / sizeof(int)) - 1;
1479 for(i=0;i<len;i++)
1480 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1482 cstr_ccat(&cstr_buf, '\"');
1483 cstr_ccat(&cstr_buf, '\0');
1484 break;
1485 case TOK_LT:
1486 v = '<';
1487 goto addv;
1488 case TOK_GT:
1489 v = '>';
1490 goto addv;
1491 case TOK_A_SHL:
1492 return strcpy(p, "<<=");
1493 case TOK_A_SAR:
1494 return strcpy(p, ">>=");
1495 default:
1496 if (v < TOK_IDENT) {
1497 /* search in two bytes table */
1498 q = tok_two_chars;
1499 while (*q) {
1500 if (q[2] == v) {
1501 *p++ = q[0];
1502 *p++ = q[1];
1503 *p = '\0';
1504 return buf;
1506 q += 3;
1508 addv:
1509 *p++ = v;
1510 *p = '\0';
1511 } else if (v < tok_ident) {
1512 return table_ident[v - TOK_IDENT]->str;
1513 } else if (v >= SYM_FIRST_ANOM) {
1514 /* special name for anonymous symbol */
1515 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1516 } else {
1517 /* should never happen */
1518 return NULL;
1520 break;
1522 return cstr_buf.data;
1525 /* push, without hashing */
1526 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1528 Sym *s;
1529 s = tcc_malloc(sizeof(Sym));
1530 s->v = v;
1531 s->type.t = t;
1532 s->c = c;
1533 s->next = NULL;
1534 /* add in stack */
1535 s->prev = *ps;
1536 *ps = s;
1537 return s;
1540 /* find a symbol and return its associated structure. 's' is the top
1541 of the symbol stack */
1542 static Sym *sym_find2(Sym *s, int v)
1544 while (s) {
1545 if (s->v == v)
1546 return s;
1547 s = s->prev;
1549 return NULL;
1552 /* structure lookup */
1553 static inline Sym *struct_find(int v)
1555 v -= TOK_IDENT;
1556 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1557 return NULL;
1558 return table_ident[v]->sym_struct;
1561 /* find an identifier */
1562 static inline Sym *sym_find(int v)
1564 v -= TOK_IDENT;
1565 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1566 return NULL;
1567 return table_ident[v]->sym_identifier;
1570 /* push a given symbol on the symbol stack */
1571 static Sym *sym_push(int v, CType *type, int r, int c)
1573 Sym *s, **ps;
1574 TokenSym *ts;
1576 if (local_stack)
1577 ps = &local_stack;
1578 else
1579 ps = &global_stack;
1580 s = sym_push2(ps, v, type->t, c);
1581 s->type.ref = type->ref;
1582 s->r = r;
1583 /* don't record fields or anonymous symbols */
1584 /* XXX: simplify */
1585 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1586 /* record symbol in token array */
1587 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1588 if (v & SYM_STRUCT)
1589 ps = &ts->sym_struct;
1590 else
1591 ps = &ts->sym_identifier;
1592 s->prev_tok = *ps;
1593 *ps = s;
1595 return s;
1598 /* push a global identifier */
1599 static Sym *global_identifier_push(int v, int t, int c)
1601 Sym *s, **ps;
1602 s = sym_push2(&global_stack, v, t, c);
1603 /* don't record anonymous symbol */
1604 if (v < SYM_FIRST_ANOM) {
1605 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1606 /* modify the top most local identifier, so that
1607 sym_identifier will point to 's' when popped */
1608 while (*ps != NULL)
1609 ps = &(*ps)->prev_tok;
1610 s->prev_tok = NULL;
1611 *ps = s;
1613 return s;
1616 /* pop symbols until top reaches 'b' */
1617 static void sym_pop(Sym **ptop, Sym *b)
1619 Sym *s, *ss, **ps;
1620 TokenSym *ts;
1621 int v;
1623 s = *ptop;
1624 while(s != b) {
1625 ss = s->prev;
1626 v = s->v;
1627 /* remove symbol in token array */
1628 /* XXX: simplify */
1629 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1630 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1631 if (v & SYM_STRUCT)
1632 ps = &ts->sym_struct;
1633 else
1634 ps = &ts->sym_identifier;
1635 *ps = s->prev_tok;
1637 tcc_free(s);
1638 s = ss;
1640 *ptop = b;
1643 /* I/O layer */
1645 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1647 int fd;
1648 BufferedFile *bf;
1650 fd = open(filename, O_RDONLY);
1651 if (fd < 0)
1652 return NULL;
1653 bf = tcc_malloc(sizeof(BufferedFile));
1654 if (!bf) {
1655 close(fd);
1656 return NULL;
1658 bf->fd = fd;
1659 bf->buf_ptr = bf->buffer;
1660 bf->buf_end = bf->buffer;
1661 bf->buffer[0] = CH_EOB; /* put eob symbol */
1662 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1663 bf->line_num = 1;
1664 bf->ifndef_macro = 0;
1665 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1666 // printf("opening '%s'\n", filename);
1667 return bf;
1670 void tcc_close(BufferedFile *bf)
1672 total_lines += bf->line_num;
1673 close(bf->fd);
1674 tcc_free(bf);
1677 /* fill input buffer and peek next char */
1678 static int tcc_peekc_slow(BufferedFile *bf)
1680 int len;
1681 /* only tries to read if really end of buffer */
1682 if (bf->buf_ptr >= bf->buf_end) {
1683 if (bf->fd != -1) {
1684 #if defined(PARSE_DEBUG)
1685 len = 8;
1686 #else
1687 len = IO_BUF_SIZE;
1688 #endif
1689 len = read(bf->fd, bf->buffer, len);
1690 if (len < 0)
1691 len = 0;
1692 } else {
1693 len = 0;
1695 total_bytes += len;
1696 bf->buf_ptr = bf->buffer;
1697 bf->buf_end = bf->buffer + len;
1698 *bf->buf_end = CH_EOB;
1700 if (bf->buf_ptr < bf->buf_end) {
1701 return bf->buf_ptr[0];
1702 } else {
1703 bf->buf_ptr = bf->buf_end;
1704 return CH_EOF;
1708 /* return the current character, handling end of block if necessary
1709 (but not stray) */
1710 static int handle_eob(void)
1712 return tcc_peekc_slow(file);
1715 /* read next char from current input file and handle end of input buffer */
1716 static inline void inp(void)
1718 ch = *(++(file->buf_ptr));
1719 /* end of buffer/file handling */
1720 if (ch == CH_EOB)
1721 ch = handle_eob();
1724 /* handle '\[\r]\n' */
1725 static void handle_stray(void)
1727 while (ch == '\\') {
1728 inp();
1729 if (ch == '\n') {
1730 file->line_num++;
1731 inp();
1732 } else if (ch == '\r') {
1733 inp();
1734 if (ch != '\n')
1735 goto fail;
1736 file->line_num++;
1737 inp();
1738 } else {
1739 fail:
1740 error("stray '\\' in program");
1745 /* skip the stray and handle the \\n case. Output an error if
1746 incorrect char after the stray */
1747 static int handle_stray1(uint8_t *p)
1749 int c;
1751 if (p >= file->buf_end) {
1752 file->buf_ptr = p;
1753 c = handle_eob();
1754 p = file->buf_ptr;
1755 if (c == '\\')
1756 goto parse_stray;
1757 } else {
1758 parse_stray:
1759 file->buf_ptr = p;
1760 ch = *p;
1761 handle_stray();
1762 p = file->buf_ptr;
1763 c = *p;
1765 return c;
1768 /* handle just the EOB case, but not stray */
1769 #define PEEKC_EOB(c, p)\
1771 p++;\
1772 c = *p;\
1773 if (c == '\\') {\
1774 file->buf_ptr = p;\
1775 c = handle_eob();\
1776 p = file->buf_ptr;\
1780 /* handle the complicated stray case */
1781 #define PEEKC(c, p)\
1783 p++;\
1784 c = *p;\
1785 if (c == '\\') {\
1786 c = handle_stray1(p);\
1787 p = file->buf_ptr;\
1791 /* input with '\[\r]\n' handling. Note that this function cannot
1792 handle other characters after '\', so you cannot call it inside
1793 strings or comments */
1794 static void minp(void)
1796 inp();
1797 if (ch == '\\')
1798 handle_stray();
1802 /* single line C++ comments */
1803 static uint8_t *parse_line_comment(uint8_t *p)
1805 int c;
1807 p++;
1808 for(;;) {
1809 c = *p;
1810 if (c == '\n' || c == CH_EOF) {
1811 break;
1812 } else if (c == '\\') {
1813 PEEKC_EOB(c, p);
1814 if (c == '\n') {
1815 file->line_num++;
1816 PEEKC_EOB(c, p);
1817 } else if (c == '\r') {
1818 PEEKC_EOB(c, p);
1819 if (c == '\n') {
1820 file->line_num++;
1821 PEEKC_EOB(c, p);
1824 } else {
1825 p++;
1828 return p;
1831 /* C comments */
1832 static uint8_t *parse_comment(uint8_t *p)
1834 int c;
1836 p++;
1837 for(;;) {
1838 /* fast skip loop */
1839 for(;;) {
1840 c = *p;
1841 if (c == '\n' || c == '*' || c == '\\')
1842 break;
1843 p++;
1844 c = *p;
1845 if (c == '\n' || c == '*' || c == '\\')
1846 break;
1847 p++;
1849 /* now we can handle all the cases */
1850 if (c == '\n') {
1851 file->line_num++;
1852 p++;
1853 } else if (c == '*') {
1854 p++;
1855 for(;;) {
1856 c = *p;
1857 if (c == '*') {
1858 p++;
1859 } else if (c == '/') {
1860 goto end_of_comment;
1861 } else if (c == '\\') {
1862 file->buf_ptr = p;
1863 c = handle_eob();
1864 p = file->buf_ptr;
1865 if (c == '\\') {
1866 /* skip '\[\r]\n', otherwise just skip the stray */
1867 while (c == '\\') {
1868 PEEKC_EOB(c, p);
1869 if (c == '\n') {
1870 file->line_num++;
1871 PEEKC_EOB(c, p);
1872 } else if (c == '\r') {
1873 PEEKC_EOB(c, p);
1874 if (c == '\n') {
1875 file->line_num++;
1876 PEEKC_EOB(c, p);
1878 } else {
1879 goto after_star;
1883 } else {
1884 break;
1887 after_star: ;
1888 } else {
1889 /* stray, eob or eof */
1890 file->buf_ptr = p;
1891 c = handle_eob();
1892 p = file->buf_ptr;
1893 if (c == CH_EOF) {
1894 error("unexpected end of file in comment");
1895 } else if (c == '\\') {
1896 p++;
1900 end_of_comment:
1901 p++;
1902 return p;
1905 #define cinp minp
1907 /* space exlcuding newline */
1908 static inline int is_space(int ch)
1910 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1913 static inline void skip_spaces(void)
1915 while (is_space(ch))
1916 cinp();
1919 /* parse a string without interpreting escapes */
1920 static uint8_t *parse_pp_string(uint8_t *p,
1921 int sep, CString *str)
1923 int c;
1924 p++;
1925 for(;;) {
1926 c = *p;
1927 if (c == sep) {
1928 break;
1929 } else if (c == '\\') {
1930 file->buf_ptr = p;
1931 c = handle_eob();
1932 p = file->buf_ptr;
1933 if (c == CH_EOF) {
1934 unterminated_string:
1935 /* XXX: indicate line number of start of string */
1936 error("missing terminating %c character", sep);
1937 } else if (c == '\\') {
1938 /* escape : just skip \[\r]\n */
1939 PEEKC_EOB(c, p);
1940 if (c == '\n') {
1941 file->line_num++;
1942 p++;
1943 } else if (c == '\r') {
1944 PEEKC_EOB(c, p);
1945 if (c != '\n')
1946 expect("'\n' after '\r'");
1947 file->line_num++;
1948 p++;
1949 } else if (c == CH_EOF) {
1950 goto unterminated_string;
1951 } else {
1952 if (str) {
1953 cstr_ccat(str, '\\');
1954 cstr_ccat(str, c);
1956 p++;
1959 } else if (c == '\n') {
1960 file->line_num++;
1961 goto add_char;
1962 } else if (c == '\r') {
1963 PEEKC_EOB(c, p);
1964 if (c != '\n') {
1965 cstr_ccat(str, '\r');
1966 } else {
1967 file->line_num++;
1968 goto add_char;
1970 } else {
1971 add_char:
1972 if (str)
1973 cstr_ccat(str, c);
1974 p++;
1977 p++;
1978 return p;
1981 /* skip block of text until #else, #elif or #endif. skip also pairs of
1982 #if/#endif */
1983 void preprocess_skip(void)
1985 int a, start_of_line, c;
1986 uint8_t *p;
1988 p = file->buf_ptr;
1989 start_of_line = 1;
1990 a = 0;
1991 for(;;) {
1992 redo_no_start:
1993 c = *p;
1994 switch(c) {
1995 case ' ':
1996 case '\t':
1997 case '\f':
1998 case '\v':
1999 case '\r':
2000 p++;
2001 goto redo_no_start;
2002 case '\n':
2003 start_of_line = 1;
2004 file->line_num++;
2005 p++;
2006 goto redo_no_start;
2007 case '\\':
2008 file->buf_ptr = p;
2009 c = handle_eob();
2010 if (c == CH_EOF) {
2011 expect("#endif");
2012 } else if (c == '\\') {
2013 /* XXX: incorrect: should not give an error */
2014 ch = file->buf_ptr[0];
2015 handle_stray();
2017 p = file->buf_ptr;
2018 goto redo_no_start;
2019 /* skip strings */
2020 case '\"':
2021 case '\'':
2022 p = parse_pp_string(p, c, NULL);
2023 break;
2024 /* skip comments */
2025 case '/':
2026 file->buf_ptr = p;
2027 ch = *p;
2028 minp();
2029 p = file->buf_ptr;
2030 if (ch == '*') {
2031 p = parse_comment(p);
2032 } else if (ch == '/') {
2033 p = parse_line_comment(p);
2035 break;
2037 case '#':
2038 p++;
2039 if (start_of_line) {
2040 file->buf_ptr = p;
2041 next_nomacro();
2042 p = file->buf_ptr;
2043 if (a == 0 &&
2044 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2045 goto the_end;
2046 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2047 a++;
2048 else if (tok == TOK_ENDIF)
2049 a--;
2051 break;
2052 default:
2053 p++;
2054 break;
2056 start_of_line = 0;
2058 the_end: ;
2059 file->buf_ptr = p;
2062 /* ParseState handling */
2064 /* XXX: currently, no include file info is stored. Thus, we cannot display
2065 accurate messages if the function or data definition spans multiple
2066 files */
2068 /* save current parse state in 's' */
2069 void save_parse_state(ParseState *s)
2071 s->line_num = file->line_num;
2072 s->macro_ptr = macro_ptr;
2073 s->tok = tok;
2074 s->tokc = tokc;
2077 /* restore parse state from 's' */
2078 void restore_parse_state(ParseState *s)
2080 file->line_num = s->line_num;
2081 macro_ptr = s->macro_ptr;
2082 tok = s->tok;
2083 tokc = s->tokc;
2086 /* return the number of additional 'ints' necessary to store the
2087 token */
2088 static inline int tok_ext_size(int t)
2090 switch(t) {
2091 /* 4 bytes */
2092 case TOK_CINT:
2093 case TOK_CUINT:
2094 case TOK_CCHAR:
2095 case TOK_LCHAR:
2096 case TOK_STR:
2097 case TOK_LSTR:
2098 case TOK_CFLOAT:
2099 case TOK_LINENUM:
2100 case TOK_PPNUM:
2101 return 1;
2102 case TOK_CDOUBLE:
2103 case TOK_CLLONG:
2104 case TOK_CULLONG:
2105 return 2;
2106 case TOK_CLDOUBLE:
2107 return LDOUBLE_SIZE / 4;
2108 default:
2109 return 0;
2113 /* token string handling */
2115 static inline void tok_str_new(TokenString *s)
2117 s->str = NULL;
2118 s->len = 0;
2119 s->allocated_len = 0;
2120 s->last_line_num = -1;
2123 static void tok_str_free(int *str)
2125 const int *p;
2126 CString *cstr;
2127 int t;
2129 p = str;
2130 for(;;) {
2131 t = *p;
2132 /* NOTE: we test zero separately so that GCC can generate a
2133 table for the following switch */
2134 if (t == 0)
2135 break;
2136 switch(t) {
2137 case TOK_CINT:
2138 case TOK_CUINT:
2139 case TOK_CCHAR:
2140 case TOK_LCHAR:
2141 case TOK_CFLOAT:
2142 case TOK_LINENUM:
2143 p += 2;
2144 break;
2145 case TOK_PPNUM:
2146 case TOK_STR:
2147 case TOK_LSTR:
2148 /* XXX: use a macro to be portable on 64 bit ? */
2149 cstr = (CString *)p[1];
2150 cstr_free(cstr);
2151 tcc_free(cstr);
2152 p += 2;
2153 break;
2154 case TOK_CDOUBLE:
2155 case TOK_CLLONG:
2156 case TOK_CULLONG:
2157 p += 3;
2158 break;
2159 case TOK_CLDOUBLE:
2160 p += 1 + (LDOUBLE_SIZE / 4);
2161 break;
2162 default:
2163 p++;
2164 break;
2167 tcc_free(str);
2170 static int *tok_str_realloc(TokenString *s)
2172 int *str, len;
2174 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2175 str = tcc_realloc(s->str, len * sizeof(int));
2176 if (!str)
2177 error("memory full");
2178 s->allocated_len = len;
2179 s->str = str;
2180 return str;
2183 static void tok_str_add(TokenString *s, int t)
2185 int len, *str;
2187 len = s->len;
2188 str = s->str;
2189 if (len >= s->allocated_len)
2190 str = tok_str_realloc(s);
2191 str[len++] = t;
2192 s->len = len;
2195 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2197 int len, *str;
2199 len = s->len;
2200 str = s->str;
2202 /* allocate space for worst case */
2203 if (len + TOK_MAX_SIZE > s->allocated_len)
2204 str = tok_str_realloc(s);
2205 str[len++] = t;
2206 switch(t) {
2207 case TOK_CINT:
2208 case TOK_CUINT:
2209 case TOK_CCHAR:
2210 case TOK_LCHAR:
2211 case TOK_CFLOAT:
2212 case TOK_LINENUM:
2213 str[len++] = cv->tab[0];
2214 break;
2215 case TOK_PPNUM:
2216 case TOK_STR:
2217 case TOK_LSTR:
2218 str[len++] = (int)cstr_dup(cv->cstr);
2219 break;
2220 case TOK_CDOUBLE:
2221 case TOK_CLLONG:
2222 case TOK_CULLONG:
2223 str[len++] = cv->tab[0];
2224 str[len++] = cv->tab[1];
2225 break;
2226 case TOK_CLDOUBLE:
2227 #if LDOUBLE_SIZE == 12
2228 str[len++] = cv->tab[0];
2229 str[len++] = cv->tab[1];
2230 str[len++] = cv->tab[2];
2231 #else
2232 #error add long double size support
2233 #endif
2234 break;
2235 default:
2236 break;
2238 s->len = len;
2241 /* add the current parse token in token string 's' */
2242 static void tok_str_add_tok(TokenString *s)
2244 CValue cval;
2246 /* save line number info */
2247 if (file->line_num != s->last_line_num) {
2248 s->last_line_num = file->line_num;
2249 cval.i = s->last_line_num;
2250 tok_str_add2(s, TOK_LINENUM, &cval);
2252 tok_str_add2(s, tok, &tokc);
2255 #if LDOUBLE_SIZE == 12
2256 #define LDOUBLE_GET(p, cv) \
2257 cv.tab[0] = p[0]; \
2258 cv.tab[1] = p[1]; \
2259 cv.tab[2] = p[2];
2260 #else
2261 #error add long double size support
2262 #endif
2265 /* get a token from an integer array and increment pointer
2266 accordingly. we code it as a macro to avoid pointer aliasing. */
2267 #define TOK_GET(t, p, cv) \
2269 t = *p++; \
2270 switch(t) { \
2271 case TOK_CINT: \
2272 case TOK_CUINT: \
2273 case TOK_CCHAR: \
2274 case TOK_LCHAR: \
2275 case TOK_CFLOAT: \
2276 case TOK_LINENUM: \
2277 case TOK_STR: \
2278 case TOK_LSTR: \
2279 case TOK_PPNUM: \
2280 cv.tab[0] = *p++; \
2281 break; \
2282 case TOK_CDOUBLE: \
2283 case TOK_CLLONG: \
2284 case TOK_CULLONG: \
2285 cv.tab[0] = p[0]; \
2286 cv.tab[1] = p[1]; \
2287 p += 2; \
2288 break; \
2289 case TOK_CLDOUBLE: \
2290 LDOUBLE_GET(p, cv); \
2291 p += LDOUBLE_SIZE / 4; \
2292 break; \
2293 default: \
2294 break; \
2298 /* defines handling */
2299 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2301 Sym *s;
2303 s = sym_push2(&define_stack, v, macro_type, (int)str);
2304 s->next = first_arg;
2305 table_ident[v - TOK_IDENT]->sym_define = s;
2308 /* undefined a define symbol. Its name is just set to zero */
2309 static void define_undef(Sym *s)
2311 int v;
2312 v = s->v;
2313 if (v >= TOK_IDENT && v < tok_ident)
2314 table_ident[v - TOK_IDENT]->sym_define = NULL;
2315 s->v = 0;
2318 static inline Sym *define_find(int v)
2320 v -= TOK_IDENT;
2321 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2322 return NULL;
2323 return table_ident[v]->sym_define;
2326 /* free define stack until top reaches 'b' */
2327 static void free_defines(Sym *b)
2329 Sym *top, *top1;
2330 int v;
2332 top = define_stack;
2333 while (top != b) {
2334 top1 = top->prev;
2335 /* do not free args or predefined defines */
2336 if (top->c)
2337 tok_str_free((int *)top->c);
2338 v = top->v;
2339 if (v >= TOK_IDENT && v < tok_ident)
2340 table_ident[v - TOK_IDENT]->sym_define = NULL;
2341 tcc_free(top);
2342 top = top1;
2344 define_stack = b;
2347 /* label lookup */
2348 static Sym *label_find(int v)
2350 v -= TOK_IDENT;
2351 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2352 return NULL;
2353 return table_ident[v]->sym_label;
2356 static Sym *label_push(Sym **ptop, int v, int flags)
2358 Sym *s, **ps;
2359 s = sym_push2(ptop, v, 0, 0);
2360 s->r = flags;
2361 ps = &table_ident[v - TOK_IDENT]->sym_label;
2362 if (ptop == &global_label_stack) {
2363 /* modify the top most local identifier, so that
2364 sym_identifier will point to 's' when popped */
2365 while (*ps != NULL)
2366 ps = &(*ps)->prev_tok;
2368 s->prev_tok = *ps;
2369 *ps = s;
2370 return s;
2373 /* pop labels until element last is reached. Look if any labels are
2374 undefined. Define symbols if '&&label' was used. */
2375 static void label_pop(Sym **ptop, Sym *slast)
2377 Sym *s, *s1;
2378 for(s = *ptop; s != slast; s = s1) {
2379 s1 = s->prev;
2380 if (s->r == LABEL_DECLARED) {
2381 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2382 } else if (s->r == LABEL_FORWARD) {
2383 error("label '%s' used but not defined",
2384 get_tok_str(s->v, NULL));
2385 } else {
2386 if (s->c) {
2387 /* define corresponding symbol. A size of
2388 1 is put. */
2389 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2392 /* remove label */
2393 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2394 tcc_free(s);
2396 *ptop = slast;
2399 /* eval an expression for #if/#elif */
2400 static int expr_preprocess(void)
2402 int c, t;
2403 TokenString str;
2405 tok_str_new(&str);
2406 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2407 next(); /* do macro subst */
2408 if (tok == TOK_DEFINED) {
2409 next_nomacro();
2410 t = tok;
2411 if (t == '(')
2412 next_nomacro();
2413 c = define_find(tok) != 0;
2414 if (t == '(')
2415 next_nomacro();
2416 tok = TOK_CINT;
2417 tokc.i = c;
2418 } else if (tok >= TOK_IDENT) {
2419 /* if undefined macro */
2420 tok = TOK_CINT;
2421 tokc.i = 0;
2423 tok_str_add_tok(&str);
2425 tok_str_add(&str, -1); /* simulate end of file */
2426 tok_str_add(&str, 0);
2427 /* now evaluate C constant expression */
2428 macro_ptr = str.str;
2429 next();
2430 c = expr_const();
2431 macro_ptr = NULL;
2432 tok_str_free(str.str);
2433 return c != 0;
2436 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2437 static void tok_print(int *str)
2439 int t;
2440 CValue cval;
2442 while (1) {
2443 TOK_GET(t, str, cval);
2444 if (!t)
2445 break;
2446 printf(" %s", get_tok_str(t, &cval));
2448 printf("\n");
2450 #endif
2452 /* parse after #define */
2453 static void parse_define(void)
2455 Sym *s, *first, **ps;
2456 int v, t, varg, is_vaargs, c;
2457 TokenString str;
2459 v = tok;
2460 if (v < TOK_IDENT)
2461 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2462 /* XXX: should check if same macro (ANSI) */
2463 first = NULL;
2464 t = MACRO_OBJ;
2465 /* '(' must be just after macro definition for MACRO_FUNC */
2466 c = file->buf_ptr[0];
2467 if (c == '\\')
2468 c = handle_stray1(file->buf_ptr);
2469 if (c == '(') {
2470 next_nomacro();
2471 next_nomacro();
2472 ps = &first;
2473 while (tok != ')') {
2474 varg = tok;
2475 next_nomacro();
2476 is_vaargs = 0;
2477 if (varg == TOK_DOTS) {
2478 varg = TOK___VA_ARGS__;
2479 is_vaargs = 1;
2480 } else if (tok == TOK_DOTS && gnu_ext) {
2481 is_vaargs = 1;
2482 next_nomacro();
2484 if (varg < TOK_IDENT)
2485 error("badly punctuated parameter list");
2486 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2487 *ps = s;
2488 ps = &s->next;
2489 if (tok != ',')
2490 break;
2491 next_nomacro();
2493 t = MACRO_FUNC;
2495 tok_str_new(&str);
2496 next_nomacro();
2497 /* EOF testing necessary for '-D' handling */
2498 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2499 tok_str_add2(&str, tok, &tokc);
2500 next_nomacro();
2502 tok_str_add(&str, 0);
2503 #ifdef PP_DEBUG
2504 printf("define %s %d: ", get_tok_str(v, NULL), t);
2505 tok_print(str.str);
2506 #endif
2507 define_push(v, t, str.str, first);
2510 /* XXX: use a token or a hash table to accelerate matching ? */
2511 static CachedInclude *search_cached_include(TCCState *s1,
2512 int type, const char *filename)
2514 CachedInclude *e;
2515 int i;
2517 for(i = 0;i < s1->nb_cached_includes; i++) {
2518 e = s1->cached_includes[i];
2519 if (e->type == type && !strcmp(e->filename, filename))
2520 return e;
2522 return NULL;
2525 static inline void add_cached_include(TCCState *s1, int type,
2526 const char *filename, int ifndef_macro)
2528 CachedInclude *e;
2530 if (search_cached_include(s1, type, filename))
2531 return;
2532 #ifdef INC_DEBUG
2533 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2534 #endif
2535 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2536 if (!e)
2537 return;
2538 e->type = type;
2539 strcpy(e->filename, filename);
2540 e->ifndef_macro = ifndef_macro;
2541 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2544 /* is_bof is true if first non space token at beginning of file */
2545 static void preprocess(int is_bof)
2547 TCCState *s1 = tcc_state;
2548 int size, i, c, n, saved_parse_flags;
2549 char buf[1024], *q, *p;
2550 char buf1[1024];
2551 BufferedFile *f;
2552 Sym *s;
2553 CachedInclude *e;
2555 saved_parse_flags = parse_flags;
2556 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2557 PARSE_FLAG_LINEFEED;
2558 next_nomacro();
2559 redo:
2560 switch(tok) {
2561 case TOK_DEFINE:
2562 next_nomacro();
2563 parse_define();
2564 break;
2565 case TOK_UNDEF:
2566 next_nomacro();
2567 s = define_find(tok);
2568 /* undefine symbol by putting an invalid name */
2569 if (s)
2570 define_undef(s);
2571 break;
2572 case TOK_INCLUDE:
2573 ch = file->buf_ptr[0];
2574 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2575 skip_spaces();
2576 if (ch == '<') {
2577 c = '>';
2578 goto read_name;
2579 } else if (ch == '\"') {
2580 c = ch;
2581 read_name:
2582 /* XXX: better stray handling */
2583 minp();
2584 q = buf;
2585 while (ch != c && ch != '\n' && ch != CH_EOF) {
2586 if ((q - buf) < sizeof(buf) - 1)
2587 *q++ = ch;
2588 minp();
2590 *q = '\0';
2591 minp();
2592 #if 0
2593 /* eat all spaces and comments after include */
2594 /* XXX: slightly incorrect */
2595 while (ch1 != '\n' && ch1 != CH_EOF)
2596 inp();
2597 #endif
2598 } else {
2599 /* computed #include : either we have only strings or
2600 we have anything enclosed in '<>' */
2601 next();
2602 buf[0] = '\0';
2603 if (tok == TOK_STR) {
2604 while (tok != TOK_LINEFEED) {
2605 if (tok != TOK_STR) {
2606 include_syntax:
2607 error("'#include' expects \"FILENAME\" or <FILENAME>");
2609 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2610 next();
2612 c = '\"';
2613 } else {
2614 int len;
2615 while (tok != TOK_LINEFEED) {
2616 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2617 next();
2619 len = strlen(buf);
2620 /* check syntax and remove '<>' */
2621 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2622 goto include_syntax;
2623 memmove(buf, buf + 1, len - 2);
2624 buf[len - 2] = '\0';
2625 c = '>';
2629 e = search_cached_include(s1, c, buf);
2630 if (e && define_find(e->ifndef_macro)) {
2631 /* no need to parse the include because the 'ifndef macro'
2632 is defined */
2633 #ifdef INC_DEBUG
2634 printf("%s: skipping %s\n", file->filename, buf);
2635 #endif
2636 } else {
2637 if (c == '\"') {
2638 /* first search in current dir if "header.h" */
2639 size = 0;
2640 p = strrchr(file->filename, '/');
2641 if (p)
2642 size = p + 1 - file->filename;
2643 if (size > sizeof(buf1) - 1)
2644 size = sizeof(buf1) - 1;
2645 memcpy(buf1, file->filename, size);
2646 buf1[size] = '\0';
2647 pstrcat(buf1, sizeof(buf1), buf);
2648 f = tcc_open(s1, buf1);
2649 if (f)
2650 goto found;
2652 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2653 error("#include recursion too deep");
2654 /* now search in all the include paths */
2655 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2656 for(i = 0; i < n; i++) {
2657 const char *path;
2658 if (i < s1->nb_include_paths)
2659 path = s1->include_paths[i];
2660 else
2661 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2662 pstrcpy(buf1, sizeof(buf1), path);
2663 pstrcat(buf1, sizeof(buf1), "/");
2664 pstrcat(buf1, sizeof(buf1), buf);
2665 f = tcc_open(s1, buf1);
2666 if (f)
2667 goto found;
2669 error("include file '%s' not found", buf);
2670 f = NULL;
2671 found:
2672 #ifdef INC_DEBUG
2673 printf("%s: including %s\n", file->filename, buf1);
2674 #endif
2675 f->inc_type = c;
2676 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2677 /* push current file in stack */
2678 /* XXX: fix current line init */
2679 *s1->include_stack_ptr++ = file;
2680 file = f;
2681 /* add include file debug info */
2682 if (do_debug) {
2683 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2685 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2686 ch = file->buf_ptr[0];
2687 goto the_end;
2689 break;
2690 case TOK_IFNDEF:
2691 c = 1;
2692 goto do_ifdef;
2693 case TOK_IF:
2694 c = expr_preprocess();
2695 goto do_if;
2696 case TOK_IFDEF:
2697 c = 0;
2698 do_ifdef:
2699 next_nomacro();
2700 if (tok < TOK_IDENT)
2701 error("invalid argument for '#if%sdef'", c ? "n" : "");
2702 if (is_bof) {
2703 if (c) {
2704 #ifdef INC_DEBUG
2705 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2706 #endif
2707 file->ifndef_macro = tok;
2710 c = (define_find(tok) != 0) ^ c;
2711 do_if:
2712 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2713 error("memory full");
2714 *s1->ifdef_stack_ptr++ = c;
2715 goto test_skip;
2716 case TOK_ELSE:
2717 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2718 error("#else without matching #if");
2719 if (s1->ifdef_stack_ptr[-1] & 2)
2720 error("#else after #else");
2721 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2722 goto test_skip;
2723 case TOK_ELIF:
2724 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2725 error("#elif without matching #if");
2726 c = s1->ifdef_stack_ptr[-1];
2727 if (c > 1)
2728 error("#elif after #else");
2729 /* last #if/#elif expression was true: we skip */
2730 if (c == 1)
2731 goto skip;
2732 c = expr_preprocess();
2733 s1->ifdef_stack_ptr[-1] = c;
2734 test_skip:
2735 if (!(c & 1)) {
2736 skip:
2737 preprocess_skip();
2738 is_bof = 0;
2739 goto redo;
2741 break;
2742 case TOK_ENDIF:
2743 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2744 error("#endif without matching #if");
2745 s1->ifdef_stack_ptr--;
2746 /* '#ifndef macro' was at the start of file. Now we check if
2747 an '#endif' is exactly at the end of file */
2748 if (file->ifndef_macro &&
2749 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2750 file->ifndef_macro_saved = file->ifndef_macro;
2751 /* need to set to zero to avoid false matches if another
2752 #ifndef at middle of file */
2753 file->ifndef_macro = 0;
2754 while (tok != TOK_LINEFEED)
2755 next_nomacro();
2756 tok_flags |= TOK_FLAG_ENDIF;
2757 goto the_end;
2759 break;
2760 case TOK_LINE:
2761 next();
2762 if (tok != TOK_CINT)
2763 error("#line");
2764 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2765 next();
2766 if (tok != TOK_LINEFEED) {
2767 if (tok != TOK_STR)
2768 error("#line");
2769 pstrcpy(file->filename, sizeof(file->filename),
2770 (char *)tokc.cstr->data);
2772 break;
2773 case TOK_ERROR:
2774 case TOK_WARNING:
2775 c = tok;
2776 ch = file->buf_ptr[0];
2777 skip_spaces();
2778 q = buf;
2779 while (ch != '\n' && ch != CH_EOF) {
2780 if ((q - buf) < sizeof(buf) - 1)
2781 *q++ = ch;
2782 minp();
2784 *q = '\0';
2785 if (c == TOK_ERROR)
2786 error("#error %s", buf);
2787 else
2788 warning("#warning %s", buf);
2789 break;
2790 case TOK_PRAGMA:
2791 /* ignored */
2792 break;
2793 default:
2794 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2795 /* '!' is ignored to allow C scripts. numbers are ignored
2796 to emulate cpp behaviour */
2797 } else {
2798 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2800 break;
2802 /* ignore other preprocess commands or #! for C scripts */
2803 while (tok != TOK_LINEFEED)
2804 next_nomacro();
2805 the_end:
2806 parse_flags = saved_parse_flags;
2809 /* evaluate escape codes in a string. */
2810 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2812 int c, n;
2813 const char *p;
2815 p = buf;
2816 for(;;) {
2817 c = *p;
2818 if (c == '\0')
2819 break;
2820 if (c == '\\') {
2821 p++;
2822 /* escape */
2823 c = *p;
2824 switch(c) {
2825 case '0': case '1': case '2': case '3':
2826 case '4': case '5': case '6': case '7':
2827 /* at most three octal digits */
2828 n = c - '0';
2829 p++;
2830 c = *p;
2831 if (isoct(c)) {
2832 n = n * 8 + c - '0';
2833 p++;
2834 c = *p;
2835 if (isoct(c)) {
2836 n = n * 8 + c - '0';
2837 p++;
2840 c = n;
2841 goto add_char_nonext;
2842 case 'x':
2843 p++;
2844 n = 0;
2845 for(;;) {
2846 c = *p;
2847 if (c >= 'a' && c <= 'f')
2848 c = c - 'a' + 10;
2849 else if (c >= 'A' && c <= 'F')
2850 c = c - 'A' + 10;
2851 else if (isnum(c))
2852 c = c - '0';
2853 else
2854 break;
2855 n = n * 16 + c;
2856 p++;
2858 c = n;
2859 goto add_char_nonext;
2860 case 'a':
2861 c = '\a';
2862 break;
2863 case 'b':
2864 c = '\b';
2865 break;
2866 case 'f':
2867 c = '\f';
2868 break;
2869 case 'n':
2870 c = '\n';
2871 break;
2872 case 'r':
2873 c = '\r';
2874 break;
2875 case 't':
2876 c = '\t';
2877 break;
2878 case 'v':
2879 c = '\v';
2880 break;
2881 case 'e':
2882 if (!gnu_ext)
2883 goto invalid_escape;
2884 c = 27;
2885 break;
2886 case '\'':
2887 case '\"':
2888 case '\\':
2889 case '?':
2890 break;
2891 default:
2892 invalid_escape:
2893 error("invalid escaped char");
2896 p++;
2897 add_char_nonext:
2898 if (!is_long)
2899 cstr_ccat(outstr, c);
2900 else
2901 cstr_wccat(outstr, c);
2903 /* add a trailing '\0' */
2904 if (!is_long)
2905 cstr_ccat(outstr, '\0');
2906 else
2907 cstr_wccat(outstr, '\0');
2910 /* we use 64 bit numbers */
2911 #define BN_SIZE 2
2913 /* bn = (bn << shift) | or_val */
2914 void bn_lshift(unsigned int *bn, int shift, int or_val)
2916 int i;
2917 unsigned int v;
2918 for(i=0;i<BN_SIZE;i++) {
2919 v = bn[i];
2920 bn[i] = (v << shift) | or_val;
2921 or_val = v >> (32 - shift);
2925 void bn_zero(unsigned int *bn)
2927 int i;
2928 for(i=0;i<BN_SIZE;i++) {
2929 bn[i] = 0;
2933 /* parse number in null terminated string 'p' and return it in the
2934 current token */
2935 void parse_number(const char *p)
2937 int b, t, shift, frac_bits, s, exp_val, ch;
2938 char *q;
2939 unsigned int bn[BN_SIZE];
2940 double d;
2942 /* number */
2943 q = token_buf;
2944 ch = *p++;
2945 t = ch;
2946 ch = *p++;
2947 *q++ = t;
2948 b = 10;
2949 if (t == '.') {
2950 goto float_frac_parse;
2951 } else if (t == '0') {
2952 if (ch == 'x' || ch == 'X') {
2953 q--;
2954 ch = *p++;
2955 b = 16;
2956 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2957 q--;
2958 ch = *p++;
2959 b = 2;
2962 /* parse all digits. cannot check octal numbers at this stage
2963 because of floating point constants */
2964 while (1) {
2965 if (ch >= 'a' && ch <= 'f')
2966 t = ch - 'a' + 10;
2967 else if (ch >= 'A' && ch <= 'F')
2968 t = ch - 'A' + 10;
2969 else if (isnum(ch))
2970 t = ch - '0';
2971 else
2972 break;
2973 if (t >= b)
2974 break;
2975 if (q >= token_buf + STRING_MAX_SIZE) {
2976 num_too_long:
2977 error("number too long");
2979 *q++ = ch;
2980 ch = *p++;
2982 if (ch == '.' ||
2983 ((ch == 'e' || ch == 'E') && b == 10) ||
2984 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
2985 if (b != 10) {
2986 /* NOTE: strtox should support that for hexa numbers, but
2987 non ISOC99 libcs do not support it, so we prefer to do
2988 it by hand */
2989 /* hexadecimal or binary floats */
2990 /* XXX: handle overflows */
2991 *q = '\0';
2992 if (b == 16)
2993 shift = 4;
2994 else
2995 shift = 2;
2996 bn_zero(bn);
2997 q = token_buf;
2998 while (1) {
2999 t = *q++;
3000 if (t == '\0') {
3001 break;
3002 } else if (t >= 'a') {
3003 t = t - 'a' + 10;
3004 } else if (t >= 'A') {
3005 t = t - 'A' + 10;
3006 } else {
3007 t = t - '0';
3009 bn_lshift(bn, shift, t);
3011 frac_bits = 0;
3012 if (ch == '.') {
3013 ch = *p++;
3014 while (1) {
3015 t = ch;
3016 if (t >= 'a' && t <= 'f') {
3017 t = t - 'a' + 10;
3018 } else if (t >= 'A' && t <= 'F') {
3019 t = t - 'A' + 10;
3020 } else if (t >= '0' && t <= '9') {
3021 t = t - '0';
3022 } else {
3023 break;
3025 if (t >= b)
3026 error("invalid digit");
3027 bn_lshift(bn, shift, t);
3028 frac_bits += shift;
3029 ch = *p++;
3032 if (ch != 'p' && ch != 'P')
3033 expect("exponent");
3034 ch = *p++;
3035 s = 1;
3036 exp_val = 0;
3037 if (ch == '+') {
3038 ch = *p++;
3039 } else if (ch == '-') {
3040 s = -1;
3041 ch = *p++;
3043 if (ch < '0' || ch > '9')
3044 expect("exponent digits");
3045 while (ch >= '0' && ch <= '9') {
3046 exp_val = exp_val * 10 + ch - '0';
3047 ch = *p++;
3049 exp_val = exp_val * s;
3051 /* now we can generate the number */
3052 /* XXX: should patch directly float number */
3053 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3054 d = ldexp(d, exp_val - frac_bits);
3055 t = toup(ch);
3056 if (t == 'F') {
3057 ch = *p++;
3058 tok = TOK_CFLOAT;
3059 /* float : should handle overflow */
3060 tokc.f = (float)d;
3061 } else if (t == 'L') {
3062 ch = *p++;
3063 tok = TOK_CLDOUBLE;
3064 /* XXX: not large enough */
3065 tokc.ld = (long double)d;
3066 } else {
3067 tok = TOK_CDOUBLE;
3068 tokc.d = d;
3070 } else {
3071 /* decimal floats */
3072 if (ch == '.') {
3073 if (q >= token_buf + STRING_MAX_SIZE)
3074 goto num_too_long;
3075 *q++ = ch;
3076 ch = *p++;
3077 float_frac_parse:
3078 while (ch >= '0' && ch <= '9') {
3079 if (q >= token_buf + STRING_MAX_SIZE)
3080 goto num_too_long;
3081 *q++ = ch;
3082 ch = *p++;
3085 if (ch == 'e' || ch == 'E') {
3086 if (q >= token_buf + STRING_MAX_SIZE)
3087 goto num_too_long;
3088 *q++ = ch;
3089 ch = *p++;
3090 if (ch == '-' || ch == '+') {
3091 if (q >= token_buf + STRING_MAX_SIZE)
3092 goto num_too_long;
3093 *q++ = ch;
3094 ch = *p++;
3096 if (ch < '0' || ch > '9')
3097 expect("exponent digits");
3098 while (ch >= '0' && ch <= '9') {
3099 if (q >= token_buf + STRING_MAX_SIZE)
3100 goto num_too_long;
3101 *q++ = ch;
3102 ch = *p++;
3105 *q = '\0';
3106 t = toup(ch);
3107 errno = 0;
3108 if (t == 'F') {
3109 ch = *p++;
3110 tok = TOK_CFLOAT;
3111 tokc.f = strtof(token_buf, NULL);
3112 } else if (t == 'L') {
3113 ch = *p++;
3114 tok = TOK_CLDOUBLE;
3115 tokc.ld = strtold(token_buf, NULL);
3116 } else {
3117 tok = TOK_CDOUBLE;
3118 tokc.d = strtod(token_buf, NULL);
3121 } else {
3122 unsigned long long n, n1;
3123 int lcount, ucount;
3125 /* integer number */
3126 *q = '\0';
3127 q = token_buf;
3128 if (b == 10 && *q == '0') {
3129 b = 8;
3130 q++;
3132 n = 0;
3133 while(1) {
3134 t = *q++;
3135 /* no need for checks except for base 10 / 8 errors */
3136 if (t == '\0') {
3137 break;
3138 } else if (t >= 'a') {
3139 t = t - 'a' + 10;
3140 } else if (t >= 'A') {
3141 t = t - 'A' + 10;
3142 } else {
3143 t = t - '0';
3144 if (t >= b)
3145 error("invalid digit");
3147 n1 = n;
3148 n = n * b + t;
3149 /* detect overflow */
3150 /* XXX: this test is not reliable */
3151 if (n < n1)
3152 error("integer constant overflow");
3155 /* XXX: not exactly ANSI compliant */
3156 if ((n & 0xffffffff00000000LL) != 0) {
3157 if ((n >> 63) != 0)
3158 tok = TOK_CULLONG;
3159 else
3160 tok = TOK_CLLONG;
3161 } else if (n > 0x7fffffff) {
3162 tok = TOK_CUINT;
3163 } else {
3164 tok = TOK_CINT;
3166 lcount = 0;
3167 ucount = 0;
3168 for(;;) {
3169 t = toup(ch);
3170 if (t == 'L') {
3171 if (lcount >= 2)
3172 error("three 'l's in integer constant");
3173 lcount++;
3174 if (lcount == 2) {
3175 if (tok == TOK_CINT)
3176 tok = TOK_CLLONG;
3177 else if (tok == TOK_CUINT)
3178 tok = TOK_CULLONG;
3180 ch = *p++;
3181 } else if (t == 'U') {
3182 if (ucount >= 1)
3183 error("two 'u's in integer constant");
3184 ucount++;
3185 if (tok == TOK_CINT)
3186 tok = TOK_CUINT;
3187 else if (tok == TOK_CLLONG)
3188 tok = TOK_CULLONG;
3189 ch = *p++;
3190 } else {
3191 break;
3194 if (tok == TOK_CINT || tok == TOK_CUINT)
3195 tokc.ui = n;
3196 else
3197 tokc.ull = n;
3202 #define PARSE2(c1, tok1, c2, tok2) \
3203 case c1: \
3204 PEEKC(c, p); \
3205 if (c == c2) { \
3206 p++; \
3207 tok = tok2; \
3208 } else { \
3209 tok = tok1; \
3211 break;
3213 /* return next token without macro substitution */
3214 static inline void next_nomacro1(void)
3216 int t, c, is_long;
3217 TokenSym *ts;
3218 uint8_t *p, *p1;
3219 unsigned int h;
3221 p = file->buf_ptr;
3222 redo_no_start:
3223 c = *p;
3224 switch(c) {
3225 case ' ':
3226 case '\t':
3227 case '\f':
3228 case '\v':
3229 case '\r':
3230 p++;
3231 goto redo_no_start;
3233 case '\\':
3234 /* first look if it is in fact an end of buffer */
3235 if (p >= file->buf_end) {
3236 file->buf_ptr = p;
3237 handle_eob();
3238 p = file->buf_ptr;
3239 if (p >= file->buf_end)
3240 goto parse_eof;
3241 else
3242 goto redo_no_start;
3243 } else {
3244 file->buf_ptr = p;
3245 ch = *p;
3246 handle_stray();
3247 p = file->buf_ptr;
3248 goto redo_no_start;
3250 parse_eof:
3252 TCCState *s1 = tcc_state;
3253 if (parse_flags & PARSE_FLAG_LINEFEED) {
3254 tok = TOK_LINEFEED;
3255 } else if (s1->include_stack_ptr == s1->include_stack ||
3256 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3257 /* no include left : end of file. */
3258 tok = TOK_EOF;
3259 } else {
3260 /* pop include file */
3262 /* test if previous '#endif' was after a #ifdef at
3263 start of file */
3264 if (tok_flags & TOK_FLAG_ENDIF) {
3265 #ifdef INC_DEBUG
3266 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3267 #endif
3268 add_cached_include(s1, file->inc_type, file->inc_filename,
3269 file->ifndef_macro_saved);
3272 /* add end of include file debug info */
3273 if (do_debug) {
3274 put_stabd(N_EINCL, 0, 0);
3276 /* pop include stack */
3277 tcc_close(file);
3278 s1->include_stack_ptr--;
3279 file = *s1->include_stack_ptr;
3280 p = file->buf_ptr;
3281 goto redo_no_start;
3284 break;
3286 case '\n':
3287 if (parse_flags & PARSE_FLAG_LINEFEED) {
3288 tok = TOK_LINEFEED;
3289 } else {
3290 file->line_num++;
3291 tok_flags |= TOK_FLAG_BOL;
3292 p++;
3293 goto redo_no_start;
3295 break;
3297 case '#':
3298 /* XXX: simplify */
3299 PEEKC(c, p);
3300 if ((tok_flags & TOK_FLAG_BOL) &&
3301 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3302 file->buf_ptr = p;
3303 preprocess(tok_flags & TOK_FLAG_BOF);
3304 p = file->buf_ptr;
3305 goto redo_no_start;
3306 } else {
3307 if (c == '#') {
3308 p++;
3309 tok = TOK_TWOSHARPS;
3310 } else {
3311 tok = '#';
3314 break;
3316 case 'a': case 'b': case 'c': case 'd':
3317 case 'e': case 'f': case 'g': case 'h':
3318 case 'i': case 'j': case 'k': case 'l':
3319 case 'm': case 'n': case 'o': case 'p':
3320 case 'q': case 'r': case 's': case 't':
3321 case 'u': case 'v': case 'w': case 'x':
3322 case 'y': case 'z':
3323 case 'A': case 'B': case 'C': case 'D':
3324 case 'E': case 'F': case 'G': case 'H':
3325 case 'I': case 'J': case 'K':
3326 case 'M': case 'N': case 'O': case 'P':
3327 case 'Q': case 'R': case 'S': case 'T':
3328 case 'U': case 'V': case 'W': case 'X':
3329 case 'Y': case 'Z':
3330 case '_':
3331 parse_ident_fast:
3332 p1 = p;
3333 h = TOK_HASH_INIT;
3334 h = TOK_HASH_FUNC(h, c);
3335 p++;
3336 for(;;) {
3337 c = *p;
3338 if (!isidnum_table[c])
3339 break;
3340 h = TOK_HASH_FUNC(h, c);
3341 p++;
3343 if (c != '\\') {
3344 TokenSym **pts;
3345 int len;
3347 /* fast case : no stray found, so we have the full token
3348 and we have already hashed it */
3349 len = p - p1;
3350 h &= (TOK_HASH_SIZE - 1);
3351 pts = &hash_ident[h];
3352 for(;;) {
3353 ts = *pts;
3354 if (!ts)
3355 break;
3356 if (ts->len == len && !memcmp(ts->str, p1, len))
3357 goto token_found;
3358 pts = &(ts->hash_next);
3360 ts = tok_alloc_new(pts, p1, len);
3361 token_found: ;
3362 } else {
3363 /* slower case */
3364 cstr_reset(&tokcstr);
3366 while (p1 < p) {
3367 cstr_ccat(&tokcstr, *p1);
3368 p1++;
3370 p--;
3371 PEEKC(c, p);
3372 parse_ident_slow:
3373 while (isidnum_table[c]) {
3374 cstr_ccat(&tokcstr, c);
3375 PEEKC(c, p);
3377 ts = tok_alloc(tokcstr.data, tokcstr.size);
3379 tok = ts->tok;
3380 break;
3381 case 'L':
3382 t = p[1];
3383 if (t != '\\' && t != '\'' && t != '\"') {
3384 /* fast case */
3385 goto parse_ident_fast;
3386 } else {
3387 PEEKC(c, p);
3388 if (c == '\'' || c == '\"') {
3389 is_long = 1;
3390 goto str_const;
3391 } else {
3392 cstr_reset(&tokcstr);
3393 cstr_ccat(&tokcstr, 'L');
3394 goto parse_ident_slow;
3397 break;
3398 case '0': case '1': case '2': case '3':
3399 case '4': case '5': case '6': case '7':
3400 case '8': case '9':
3402 cstr_reset(&tokcstr);
3403 /* after the first digit, accept digits, alpha, '.' or sign if
3404 prefixed by 'eEpP' */
3405 parse_num:
3406 for(;;) {
3407 t = c;
3408 cstr_ccat(&tokcstr, c);
3409 PEEKC(c, p);
3410 if (!(isnum(c) || isid(c) || c == '.' ||
3411 ((c == '+' || c == '-') &&
3412 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3413 break;
3415 /* We add a trailing '\0' to ease parsing */
3416 cstr_ccat(&tokcstr, '\0');
3417 tokc.cstr = &tokcstr;
3418 tok = TOK_PPNUM;
3419 break;
3420 case '.':
3421 /* special dot handling because it can also start a number */
3422 PEEKC(c, p);
3423 if (isnum(c)) {
3424 cstr_reset(&tokcstr);
3425 cstr_ccat(&tokcstr, '.');
3426 goto parse_num;
3427 } else if (c == '.') {
3428 PEEKC(c, p);
3429 if (c != '.')
3430 expect("'.'");
3431 PEEKC(c, p);
3432 tok = TOK_DOTS;
3433 } else {
3434 tok = '.';
3436 break;
3437 case '\'':
3438 case '\"':
3439 is_long = 0;
3440 str_const:
3442 CString str;
3443 int sep;
3445 sep = c;
3447 /* parse the string */
3448 cstr_new(&str);
3449 p = parse_pp_string(p, sep, &str);
3450 cstr_ccat(&str, '\0');
3452 /* eval the escape (should be done as TOK_PPNUM) */
3453 cstr_reset(&tokcstr);
3454 parse_escape_string(&tokcstr, str.data, is_long);
3455 cstr_free(&str);
3457 if (sep == '\'') {
3458 int char_size;
3459 /* XXX: make it portable */
3460 if (!is_long)
3461 char_size = 1;
3462 else
3463 char_size = sizeof(int);
3464 if (tokcstr.size <= char_size)
3465 error("empty character constant");
3466 if (tokcstr.size > 2 * char_size)
3467 warning("multi-character character constant");
3468 if (!is_long) {
3469 tokc.i = *(int8_t *)tokcstr.data;
3470 tok = TOK_CCHAR;
3471 } else {
3472 tokc.i = *(int *)tokcstr.data;
3473 tok = TOK_LCHAR;
3475 } else {
3476 tokc.cstr = &tokcstr;
3477 if (!is_long)
3478 tok = TOK_STR;
3479 else
3480 tok = TOK_LSTR;
3483 break;
3485 case '<':
3486 PEEKC(c, p);
3487 if (c == '=') {
3488 p++;
3489 tok = TOK_LE;
3490 } else if (c == '<') {
3491 PEEKC(c, p);
3492 if (c == '=') {
3493 p++;
3494 tok = TOK_A_SHL;
3495 } else {
3496 tok = TOK_SHL;
3498 } else {
3499 tok = TOK_LT;
3501 break;
3503 case '>':
3504 PEEKC(c, p);
3505 if (c == '=') {
3506 p++;
3507 tok = TOK_GE;
3508 } else if (c == '>') {
3509 PEEKC(c, p);
3510 if (c == '=') {
3511 p++;
3512 tok = TOK_A_SAR;
3513 } else {
3514 tok = TOK_SAR;
3516 } else {
3517 tok = TOK_GT;
3519 break;
3521 case '&':
3522 PEEKC(c, p);
3523 if (c == '&') {
3524 p++;
3525 tok = TOK_LAND;
3526 } else if (c == '=') {
3527 p++;
3528 tok = TOK_A_AND;
3529 } else {
3530 tok = '&';
3532 break;
3534 case '|':
3535 PEEKC(c, p);
3536 if (c == '|') {
3537 p++;
3538 tok = TOK_LOR;
3539 } else if (c == '=') {
3540 p++;
3541 tok = TOK_A_OR;
3542 } else {
3543 tok = '|';
3545 break;
3547 case '+':
3548 PEEKC(c, p);
3549 if (c == '+') {
3550 p++;
3551 tok = TOK_INC;
3552 } else if (c == '=') {
3553 p++;
3554 tok = TOK_A_ADD;
3555 } else {
3556 tok = '+';
3558 break;
3560 case '-':
3561 PEEKC(c, p);
3562 if (c == '-') {
3563 p++;
3564 tok = TOK_DEC;
3565 } else if (c == '=') {
3566 p++;
3567 tok = TOK_A_SUB;
3568 } else if (c == '>') {
3569 p++;
3570 tok = TOK_ARROW;
3571 } else {
3572 tok = '-';
3574 break;
3576 PARSE2('!', '!', '=', TOK_NE)
3577 PARSE2('=', '=', '=', TOK_EQ)
3578 PARSE2('*', '*', '=', TOK_A_MUL)
3579 PARSE2('%', '%', '=', TOK_A_MOD)
3580 PARSE2('^', '^', '=', TOK_A_XOR)
3582 /* comments or operator */
3583 case '/':
3584 PEEKC(c, p);
3585 if (c == '*') {
3586 p = parse_comment(p);
3587 goto redo_no_start;
3588 } else if (c == '/') {
3589 p = parse_line_comment(p);
3590 goto redo_no_start;
3591 } else if (c == '=') {
3592 p++;
3593 tok = TOK_A_DIV;
3594 } else {
3595 tok = '/';
3597 break;
3599 /* simple tokens */
3600 case '(':
3601 case ')':
3602 case '[':
3603 case ']':
3604 case '{':
3605 case '}':
3606 case ',':
3607 case ';':
3608 case ':':
3609 case '?':
3610 case '~':
3611 case '$': /* only used in assembler */
3612 tok = c;
3613 p++;
3614 break;
3615 default:
3616 error("unrecognized character \\x%02x", c);
3617 break;
3619 file->buf_ptr = p;
3620 tok_flags = 0;
3621 #if defined(PARSE_DEBUG)
3622 printf("token = %s\n", get_tok_str(tok, &tokc));
3623 #endif
3626 /* return next token without macro substitution. Can read input from
3627 macro_ptr buffer */
3628 static void next_nomacro(void)
3630 if (macro_ptr) {
3631 redo:
3632 tok = *macro_ptr;
3633 if (tok) {
3634 TOK_GET(tok, macro_ptr, tokc);
3635 if (tok == TOK_LINENUM) {
3636 file->line_num = tokc.i;
3637 goto redo;
3640 } else {
3641 next_nomacro1();
3645 /* substitute args in macro_str and return allocated string */
3646 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3648 int *st, last_tok, t, notfirst;
3649 Sym *s;
3650 CValue cval;
3651 TokenString str;
3652 CString cstr;
3654 tok_str_new(&str);
3655 last_tok = 0;
3656 while(1) {
3657 TOK_GET(t, macro_str, cval);
3658 if (!t)
3659 break;
3660 if (t == '#') {
3661 /* stringize */
3662 TOK_GET(t, macro_str, cval);
3663 if (!t)
3664 break;
3665 s = sym_find2(args, t);
3666 if (s) {
3667 cstr_new(&cstr);
3668 st = (int *)s->c;
3669 notfirst = 0;
3670 while (*st) {
3671 if (notfirst)
3672 cstr_ccat(&cstr, ' ');
3673 TOK_GET(t, st, cval);
3674 cstr_cat(&cstr, get_tok_str(t, &cval));
3675 notfirst = 1;
3677 cstr_ccat(&cstr, '\0');
3678 #ifdef PP_DEBUG
3679 printf("stringize: %s\n", (char *)cstr.data);
3680 #endif
3681 /* add string */
3682 cval.cstr = &cstr;
3683 tok_str_add2(&str, TOK_STR, &cval);
3684 cstr_free(&cstr);
3685 } else {
3686 tok_str_add2(&str, t, &cval);
3688 } else if (t >= TOK_IDENT) {
3689 s = sym_find2(args, t);
3690 if (s) {
3691 st = (int *)s->c;
3692 /* if '##' is present before or after, no arg substitution */
3693 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3694 /* special case for var arg macros : ## eats the
3695 ',' if empty VA_ARGS variable. */
3696 /* XXX: test of the ',' is not 100%
3697 reliable. should fix it to avoid security
3698 problems */
3699 if (gnu_ext && s->type.t &&
3700 last_tok == TOK_TWOSHARPS &&
3701 str.len >= 2 && str.str[str.len - 2] == ',') {
3702 if (*st == 0) {
3703 /* suppress ',' '##' */
3704 str.len -= 2;
3705 } else {
3706 /* suppress '##' and add variable */
3707 str.len--;
3708 goto add_var;
3710 } else {
3711 int t1;
3712 add_var:
3713 for(;;) {
3714 TOK_GET(t1, st, cval);
3715 if (!t1)
3716 break;
3717 tok_str_add2(&str, t1, &cval);
3720 } else {
3721 /* NOTE: the stream cannot be read when macro
3722 substituing an argument */
3723 macro_subst(&str, nested_list, st, 0);
3725 } else {
3726 tok_str_add(&str, t);
3728 } else {
3729 tok_str_add2(&str, t, &cval);
3731 last_tok = t;
3733 tok_str_add(&str, 0);
3734 return str.str;
3737 static char const ab_month_name[12][4] =
3739 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3740 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3743 /* do macro substitution of current token with macro 's' and add
3744 result to (tok_str,tok_len). 'nested_list' is the list of all
3745 macros we got inside to avoid recursing. Return non zero if no
3746 substitution needs to be done */
3747 static int macro_subst_tok(TokenString *tok_str,
3748 Sym **nested_list, Sym *s, int can_read_stream)
3750 Sym *args, *sa, *sa1;
3751 int mstr_allocated, parlevel, *mstr, t;
3752 TokenString str;
3753 char *cstrval;
3754 CValue cval;
3755 CString cstr;
3757 /* if symbol is a macro, prepare substitution */
3759 /* special macros */
3760 if (tok == TOK___LINE__) {
3761 cval.i = file->line_num;
3762 tok_str_add2(tok_str, TOK_CINT, &cval);
3763 } else if (tok == TOK___FILE__) {
3764 cstrval = file->filename;
3765 goto add_cstr;
3766 tok_str_add2(tok_str, TOK_STR, &cval);
3767 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3768 time_t ti;
3769 struct tm *tm;
3770 char buf[64];
3772 time(&ti);
3773 tm = localtime(&ti);
3774 if (tok == TOK___DATE__) {
3775 snprintf(buf, sizeof(buf), "%s %2d %d",
3776 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3777 } else {
3778 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3779 tm->tm_hour, tm->tm_min, tm->tm_sec);
3781 cstrval = buf;
3782 add_cstr:
3783 cstr_new(&cstr);
3784 cstr_cat(&cstr, cstrval);
3785 cstr_ccat(&cstr, '\0');
3786 cval.cstr = &cstr;
3787 tok_str_add2(tok_str, TOK_STR, &cval);
3788 cstr_free(&cstr);
3789 } else {
3790 mstr = (int *)s->c;
3791 mstr_allocated = 0;
3792 if (s->type.t == MACRO_FUNC) {
3793 /* NOTE: we do not use next_nomacro to avoid eating the
3794 next token. XXX: find better solution */
3795 if (macro_ptr) {
3796 t = *macro_ptr;
3797 if (t == 0 && can_read_stream) {
3798 /* end of macro stream: we must look at the token
3799 after in the file */
3800 macro_ptr = NULL;
3801 goto parse_stream;
3803 } else {
3804 parse_stream:
3805 /* XXX: incorrect with comments */
3806 ch = file->buf_ptr[0];
3807 while (is_space(ch) || ch == '\n')
3808 cinp();
3809 t = ch;
3811 if (t != '(') /* no macro subst */
3812 return -1;
3814 /* argument macro */
3815 next_nomacro();
3816 next_nomacro();
3817 args = NULL;
3818 sa = s->next;
3819 /* NOTE: empty args are allowed, except if no args */
3820 for(;;) {
3821 /* handle '()' case */
3822 if (!args && !sa && tok == ')')
3823 break;
3824 if (!sa)
3825 error("macro '%s' used with too many args",
3826 get_tok_str(s->v, 0));
3827 tok_str_new(&str);
3828 parlevel = 0;
3829 /* NOTE: non zero sa->t indicates VA_ARGS */
3830 while ((parlevel > 0 ||
3831 (tok != ')' &&
3832 (tok != ',' || sa->type.t))) &&
3833 tok != -1) {
3834 if (tok == '(')
3835 parlevel++;
3836 else if (tok == ')')
3837 parlevel--;
3838 tok_str_add2(&str, tok, &tokc);
3839 next_nomacro();
3841 tok_str_add(&str, 0);
3842 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3843 sa = sa->next;
3844 if (tok == ')') {
3845 /* special case for gcc var args: add an empty
3846 var arg argument if it is omitted */
3847 if (sa && sa->type.t && gnu_ext)
3848 continue;
3849 else
3850 break;
3852 if (tok != ',')
3853 expect(",");
3854 next_nomacro();
3856 if (sa) {
3857 error("macro '%s' used with too few args",
3858 get_tok_str(s->v, 0));
3861 /* now subst each arg */
3862 mstr = macro_arg_subst(nested_list, mstr, args);
3863 /* free memory */
3864 sa = args;
3865 while (sa) {
3866 sa1 = sa->prev;
3867 tok_str_free((int *)sa->c);
3868 tcc_free(sa);
3869 sa = sa1;
3871 mstr_allocated = 1;
3873 sym_push2(nested_list, s->v, 0, 0);
3874 macro_subst(tok_str, nested_list, mstr, 1);
3875 /* pop nested defined symbol */
3876 sa1 = *nested_list;
3877 *nested_list = sa1->prev;
3878 tcc_free(sa1);
3879 if (mstr_allocated)
3880 tok_str_free(mstr);
3882 return 0;
3885 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3886 return the resulting string (which must be freed). */
3887 static inline int *macro_twosharps(const int *macro_str)
3889 TokenSym *ts;
3890 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3891 int t;
3892 const char *p1, *p2;
3893 CValue cval;
3894 TokenString macro_str1;
3895 CString cstr;
3897 start_macro_ptr = macro_str;
3898 /* we search the first '##' */
3899 for(;;) {
3900 macro_ptr1 = macro_str;
3901 TOK_GET(t, macro_str, cval);
3902 /* nothing more to do if end of string */
3903 if (t == 0)
3904 return NULL;
3905 if (*macro_str == TOK_TWOSHARPS)
3906 break;
3909 /* we saw '##', so we need more processing to handle it */
3910 cstr_new(&cstr);
3911 tok_str_new(&macro_str1);
3912 tok = t;
3913 tokc = cval;
3915 /* add all tokens seen so far */
3916 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
3917 TOK_GET(t, ptr, cval);
3918 tok_str_add2(&macro_str1, t, &cval);
3920 saved_macro_ptr = macro_ptr;
3921 /* XXX: get rid of the use of macro_ptr here */
3922 macro_ptr = (int *)macro_str;
3923 for(;;) {
3924 while (*macro_ptr == TOK_TWOSHARPS) {
3925 macro_ptr++;
3926 macro_ptr1 = macro_ptr;
3927 t = *macro_ptr;
3928 if (t) {
3929 TOK_GET(t, macro_ptr, cval);
3930 /* We concatenate the two tokens if we have an
3931 identifier or a preprocessing number */
3932 cstr_reset(&cstr);
3933 p1 = get_tok_str(tok, &tokc);
3934 cstr_cat(&cstr, p1);
3935 p2 = get_tok_str(t, &cval);
3936 cstr_cat(&cstr, p2);
3937 cstr_ccat(&cstr, '\0');
3939 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3940 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3941 if (tok == TOK_PPNUM) {
3942 /* if number, then create a number token */
3943 /* NOTE: no need to allocate because
3944 tok_str_add2() does it */
3945 tokc.cstr = &cstr;
3946 } else {
3947 /* if identifier, we must do a test to
3948 validate we have a correct identifier */
3949 if (t == TOK_PPNUM) {
3950 const char *p;
3951 int c;
3953 p = p2;
3954 for(;;) {
3955 c = *p;
3956 if (c == '\0')
3957 break;
3958 p++;
3959 if (!isnum(c) && !isid(c))
3960 goto error_pasting;
3963 ts = tok_alloc(cstr.data, strlen(cstr.data));
3964 tok = ts->tok; /* modify current token */
3966 } else {
3967 const char *str = cstr.data;
3968 const unsigned char *q;
3970 /* we look for a valid token */
3971 /* XXX: do more extensive checks */
3972 if (!strcmp(str, ">>=")) {
3973 tok = TOK_A_SAR;
3974 } else if (!strcmp(str, "<<=")) {
3975 tok = TOK_A_SHL;
3976 } else if (strlen(str) == 2) {
3977 /* search in two bytes table */
3978 q = tok_two_chars;
3979 for(;;) {
3980 if (!*q)
3981 goto error_pasting;
3982 if (q[0] == str[0] && q[1] == str[1])
3983 break;
3984 q += 3;
3986 tok = q[2];
3987 } else {
3988 error_pasting:
3989 /* NOTE: because get_tok_str use a static buffer,
3990 we must save it */
3991 cstr_reset(&cstr);
3992 p1 = get_tok_str(tok, &tokc);
3993 cstr_cat(&cstr, p1);
3994 cstr_ccat(&cstr, '\0');
3995 p2 = get_tok_str(t, &cval);
3996 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
3997 /* cannot merge tokens: just add them separately */
3998 tok_str_add2(&macro_str1, tok, &tokc);
3999 /* XXX: free associated memory ? */
4000 tok = t;
4001 tokc = cval;
4006 tok_str_add2(&macro_str1, tok, &tokc);
4007 next_nomacro();
4008 if (tok == 0)
4009 break;
4011 macro_ptr = (int *)saved_macro_ptr;
4012 cstr_free(&cstr);
4013 tok_str_add(&macro_str1, 0);
4014 return macro_str1.str;
4018 /* do macro substitution of macro_str and add result to
4019 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4020 inside to avoid recursing. */
4021 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4022 const int *macro_str, int can_read_stream)
4024 Sym *s;
4025 int *saved_macro_ptr, *macro_str1;
4026 const int *ptr;
4027 int t, ret;
4028 CValue cval;
4030 /* first scan for '##' operator handling */
4031 ptr = macro_str;
4032 macro_str1 = macro_twosharps(ptr);
4033 if (macro_str1)
4034 ptr = macro_str1;
4035 while (1) {
4036 /* NOTE: ptr == NULL can only happen if tokens are read from
4037 file stream due to a macro function call */
4038 if (ptr == NULL)
4039 break;
4040 TOK_GET(t, ptr, cval);
4041 if (t == 0)
4042 break;
4043 s = define_find(t);
4044 if (s != NULL) {
4045 /* if nested substitution, do nothing */
4046 if (sym_find2(*nested_list, t))
4047 goto no_subst;
4048 saved_macro_ptr = macro_ptr;
4049 macro_ptr = (int *)ptr;
4050 tok = t;
4051 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4052 ptr = (int *)macro_ptr;
4053 macro_ptr = saved_macro_ptr;
4054 if (ret != 0)
4055 goto no_subst;
4056 } else {
4057 no_subst:
4058 tok_str_add2(tok_str, t, &cval);
4061 if (macro_str1)
4062 tok_str_free(macro_str1);
4065 /* return next token with macro substitution */
4066 static void next(void)
4068 Sym *nested_list, *s;
4069 TokenString str;
4071 redo:
4072 next_nomacro();
4073 if (!macro_ptr) {
4074 /* if not reading from macro substituted string, then try
4075 to substitute macros */
4076 if (tok >= TOK_IDENT &&
4077 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4078 s = define_find(tok);
4079 if (s) {
4080 /* we have a macro: we try to substitute */
4081 tok_str_new(&str);
4082 nested_list = NULL;
4083 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4084 /* substitution done, NOTE: maybe empty */
4085 tok_str_add(&str, 0);
4086 macro_ptr = str.str;
4087 macro_ptr_allocated = str.str;
4088 goto redo;
4092 } else {
4093 if (tok == 0) {
4094 /* end of macro or end of unget buffer */
4095 if (unget_buffer_enabled) {
4096 macro_ptr = unget_saved_macro_ptr;
4097 unget_buffer_enabled = 0;
4098 } else {
4099 /* end of macro string: free it */
4100 tok_str_free(macro_ptr_allocated);
4101 macro_ptr = NULL;
4103 goto redo;
4107 /* convert preprocessor tokens into C tokens */
4108 if (tok == TOK_PPNUM &&
4109 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4110 parse_number((char *)tokc.cstr->data);
4114 /* push back current token and set current token to 'last_tok'. Only
4115 identifier case handled for labels. */
4116 static inline void unget_tok(int last_tok)
4118 int i, n;
4119 int *q;
4120 unget_saved_macro_ptr = macro_ptr;
4121 unget_buffer_enabled = 1;
4122 q = unget_saved_buffer;
4123 macro_ptr = q;
4124 *q++ = tok;
4125 n = tok_ext_size(tok) - 1;
4126 for(i=0;i<n;i++)
4127 *q++ = tokc.tab[i];
4128 *q = 0; /* end of token string */
4129 tok = last_tok;
4133 void swap(int *p, int *q)
4135 int t;
4136 t = *p;
4137 *p = *q;
4138 *q = t;
4141 void vsetc(CType *type, int r, CValue *vc)
4143 int v;
4145 if (vtop >= vstack + VSTACK_SIZE)
4146 error("memory full");
4147 /* cannot let cpu flags if other instruction are generated. Also
4148 avoid leaving VT_JMP anywhere except on the top of the stack
4149 because it would complicate the code generator. */
4150 if (vtop >= vstack) {
4151 v = vtop->r & VT_VALMASK;
4152 if (v == VT_CMP || (v & ~1) == VT_JMP)
4153 gv(RC_INT);
4155 vtop++;
4156 vtop->type = *type;
4157 vtop->r = r;
4158 vtop->r2 = VT_CONST;
4159 vtop->c = *vc;
4162 /* push integer constant */
4163 void vpushi(int v)
4165 CValue cval;
4166 cval.i = v;
4167 vsetc(&int_type, VT_CONST, &cval);
4170 /* Return a static symbol pointing to a section */
4171 static Sym *get_sym_ref(CType *type, Section *sec,
4172 unsigned long offset, unsigned long size)
4174 int v;
4175 Sym *sym;
4177 v = anon_sym++;
4178 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4179 sym->type.ref = type->ref;
4180 sym->r = VT_CONST | VT_SYM;
4181 put_extern_sym(sym, sec, offset, size);
4182 return sym;
4185 /* push a reference to a section offset by adding a dummy symbol */
4186 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4188 CValue cval;
4190 cval.ul = 0;
4191 vsetc(type, VT_CONST | VT_SYM, &cval);
4192 vtop->sym = get_sym_ref(type, sec, offset, size);
4195 /* define a new external reference to a symbol 'v' of type 'u' */
4196 static Sym *external_global_sym(int v, CType *type, int r)
4198 Sym *s;
4200 s = sym_find(v);
4201 if (!s) {
4202 /* push forward reference */
4203 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4204 s->type.ref = type->ref;
4205 s->r = r | VT_CONST | VT_SYM;
4207 return s;
4210 /* define a new external reference to a symbol 'v' of type 'u' */
4211 static Sym *external_sym(int v, CType *type, int r)
4213 Sym *s;
4215 s = sym_find(v);
4216 if (!s) {
4217 /* push forward reference */
4218 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4219 s->type.t |= VT_EXTERN;
4220 } else {
4221 if (!is_compatible_types(&s->type, type))
4222 error("incompatible types for redefinition of '%s'",
4223 get_tok_str(v, NULL));
4225 return s;
4228 /* push a reference to global symbol v */
4229 static void vpush_global_sym(CType *type, int v)
4231 Sym *sym;
4232 CValue cval;
4234 sym = external_global_sym(v, type, 0);
4235 cval.ul = 0;
4236 vsetc(type, VT_CONST | VT_SYM, &cval);
4237 vtop->sym = sym;
4240 void vset(CType *type, int r, int v)
4242 CValue cval;
4244 cval.i = v;
4245 vsetc(type, r, &cval);
4248 void vseti(int r, int v)
4250 CType type;
4251 type.t = VT_INT;
4252 vset(&type, r, v);
4255 void vswap(void)
4257 SValue tmp;
4259 tmp = vtop[0];
4260 vtop[0] = vtop[-1];
4261 vtop[-1] = tmp;
4264 void vpushv(SValue *v)
4266 if (vtop >= vstack + VSTACK_SIZE)
4267 error("memory full");
4268 vtop++;
4269 *vtop = *v;
4272 void vdup(void)
4274 vpushv(vtop);
4277 /* save r to the memory stack, and mark it as being free */
4278 void save_reg(int r)
4280 int l, saved, size, align;
4281 SValue *p, sv;
4282 CType *type;
4284 /* modify all stack values */
4285 saved = 0;
4286 l = 0;
4287 for(p=vstack;p<=vtop;p++) {
4288 if ((p->r & VT_VALMASK) == r ||
4289 (p->r2 & VT_VALMASK) == r) {
4290 /* must save value on stack if not already done */
4291 if (!saved) {
4292 /* NOTE: must reload 'r' because r might be equal to r2 */
4293 r = p->r & VT_VALMASK;
4294 /* store register in the stack */
4295 type = &p->type;
4296 if ((p->r & VT_LVAL) ||
4297 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4298 type = &int_type;
4299 size = type_size(type, &align);
4300 loc = (loc - size) & -align;
4301 sv.type.t = type->t;
4302 sv.r = VT_LOCAL | VT_LVAL;
4303 sv.c.ul = loc;
4304 store(r, &sv);
4305 #ifdef TCC_TARGET_I386
4306 /* x86 specific: need to pop fp register ST0 if saved */
4307 if (r == TREG_ST0) {
4308 o(0xd9dd); /* fstp %st(1) */
4310 #endif
4311 /* special long long case */
4312 if ((type->t & VT_BTYPE) == VT_LLONG) {
4313 sv.c.ul += 4;
4314 store(p->r2, &sv);
4316 l = loc;
4317 saved = 1;
4319 /* mark that stack entry as being saved on the stack */
4320 if (p->r & VT_LVAL) {
4321 /* also clear the bounded flag because the
4322 relocation address of the function was stored in
4323 p->c.ul */
4324 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4325 } else {
4326 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4328 p->r2 = VT_CONST;
4329 p->c.ul = l;
4334 /* find a free register of class 'rc'. If none, save one register */
4335 int get_reg(int rc)
4337 int r;
4338 SValue *p;
4340 /* find a free register */
4341 for(r=0;r<NB_REGS;r++) {
4342 if (reg_classes[r] & rc) {
4343 for(p=vstack;p<=vtop;p++) {
4344 if ((p->r & VT_VALMASK) == r ||
4345 (p->r2 & VT_VALMASK) == r)
4346 goto notfound;
4348 return r;
4350 notfound: ;
4353 /* no register left : free the first one on the stack (VERY
4354 IMPORTANT to start from the bottom to ensure that we don't
4355 spill registers used in gen_opi()) */
4356 for(p=vstack;p<=vtop;p++) {
4357 r = p->r & VT_VALMASK;
4358 if (r < VT_CONST && (reg_classes[r] & rc))
4359 goto save_found;
4360 /* also look at second register (if long long) */
4361 r = p->r2 & VT_VALMASK;
4362 if (r < VT_CONST && (reg_classes[r] & rc)) {
4363 save_found:
4364 save_reg(r);
4365 return r;
4368 /* Should never comes here */
4369 return -1;
4372 /* save registers up to (vtop - n) stack entry */
4373 void save_regs(int n)
4375 int r;
4376 SValue *p, *p1;
4377 p1 = vtop - n;
4378 for(p = vstack;p <= p1; p++) {
4379 r = p->r & VT_VALMASK;
4380 if (r < VT_CONST) {
4381 save_reg(r);
4386 /* move register 's' to 'r', and flush previous value of r to memory
4387 if needed */
4388 void move_reg(int r, int s)
4390 SValue sv;
4392 if (r != s) {
4393 save_reg(r);
4394 sv.type.t = VT_INT;
4395 sv.r = s;
4396 sv.c.ul = 0;
4397 load(r, &sv);
4401 /* get address of vtop (vtop MUST BE an lvalue) */
4402 void gaddrof(void)
4404 vtop->r &= ~VT_LVAL;
4405 /* tricky: if saved lvalue, then we can go back to lvalue */
4406 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4407 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4410 #ifdef CONFIG_TCC_BCHECK
4411 /* generate lvalue bound code */
4412 void gbound(void)
4414 int lval_type;
4415 CType type1;
4417 vtop->r &= ~VT_MUSTBOUND;
4418 /* if lvalue, then use checking code before dereferencing */
4419 if (vtop->r & VT_LVAL) {
4420 /* if not VT_BOUNDED value, then make one */
4421 if (!(vtop->r & VT_BOUNDED)) {
4422 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4423 /* must save type because we must set it to int to get pointer */
4424 type1 = vtop->type;
4425 vtop->type.t = VT_INT;
4426 gaddrof();
4427 vpushi(0);
4428 gen_bounded_ptr_add();
4429 vtop->r |= lval_type;
4430 vtop->type = type1;
4432 /* then check for dereferencing */
4433 gen_bounded_ptr_deref();
4436 #endif
4438 /* store vtop a register belonging to class 'rc'. lvalues are
4439 converted to values. Cannot be used if cannot be converted to
4440 register value (such as structures). */
4441 int gv(int rc)
4443 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4444 unsigned long long ll;
4446 /* NOTE: get_reg can modify vstack[] */
4447 if (vtop->type.t & VT_BITFIELD) {
4448 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4449 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4450 /* remove bit field info to avoid loops */
4451 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4452 /* generate shifts */
4453 vpushi(32 - (bit_pos + bit_size));
4454 gen_op(TOK_SHL);
4455 vpushi(32 - bit_size);
4456 /* NOTE: transformed to SHR if unsigned */
4457 gen_op(TOK_SAR);
4458 r = gv(rc);
4459 } else {
4460 if (is_float(vtop->type.t) &&
4461 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4462 Sym *sym;
4463 int *ptr;
4464 unsigned long offset;
4466 /* XXX: unify with initializers handling ? */
4467 /* CPUs usually cannot use float constants, so we store them
4468 generically in data segment */
4469 size = type_size(&vtop->type, &align);
4470 offset = (data_section->data_offset + align - 1) & -align;
4471 data_section->data_offset = offset;
4472 /* XXX: not portable yet */
4473 ptr = section_ptr_add(data_section, size);
4474 size = size >> 2;
4475 for(i=0;i<size;i++)
4476 ptr[i] = vtop->c.tab[i];
4477 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4478 vtop->r |= VT_LVAL | VT_SYM;
4479 vtop->sym = sym;
4480 vtop->c.ul = 0;
4482 #ifdef CONFIG_TCC_BCHECK
4483 if (vtop->r & VT_MUSTBOUND)
4484 gbound();
4485 #endif
4487 r = vtop->r & VT_VALMASK;
4488 /* need to reload if:
4489 - constant
4490 - lvalue (need to dereference pointer)
4491 - already a register, but not in the right class */
4492 if (r >= VT_CONST ||
4493 (vtop->r & VT_LVAL) ||
4494 !(reg_classes[r] & rc) ||
4495 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4496 !(reg_classes[vtop->r2] & rc))) {
4497 r = get_reg(rc);
4498 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4499 /* two register type load : expand to two words
4500 temporarily */
4501 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4502 /* load constant */
4503 ll = vtop->c.ull;
4504 vtop->c.ui = ll; /* first word */
4505 load(r, vtop);
4506 vtop->r = r; /* save register value */
4507 vpushi(ll >> 32); /* second word */
4508 } else if (r >= VT_CONST ||
4509 (vtop->r & VT_LVAL)) {
4510 /* load from memory */
4511 load(r, vtop);
4512 vdup();
4513 vtop[-1].r = r; /* save register value */
4514 /* increment pointer to get second word */
4515 vtop->type.t = VT_INT;
4516 gaddrof();
4517 vpushi(4);
4518 gen_op('+');
4519 vtop->r |= VT_LVAL;
4520 } else {
4521 /* move registers */
4522 load(r, vtop);
4523 vdup();
4524 vtop[-1].r = r; /* save register value */
4525 vtop->r = vtop[-1].r2;
4527 /* allocate second register */
4528 rc2 = RC_INT;
4529 if (rc == RC_IRET)
4530 rc2 = RC_LRET;
4531 r2 = get_reg(rc2);
4532 load(r2, vtop);
4533 vpop();
4534 /* write second register */
4535 vtop->r2 = r2;
4536 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4537 int t1, t;
4538 /* lvalue of scalar type : need to use lvalue type
4539 because of possible cast */
4540 t = vtop->type.t;
4541 t1 = t;
4542 /* compute memory access type */
4543 if (vtop->r & VT_LVAL_BYTE)
4544 t = VT_BYTE;
4545 else if (vtop->r & VT_LVAL_SHORT)
4546 t = VT_SHORT;
4547 if (vtop->r & VT_LVAL_UNSIGNED)
4548 t |= VT_UNSIGNED;
4549 vtop->type.t = t;
4550 load(r, vtop);
4551 /* restore wanted type */
4552 vtop->type.t = t1;
4553 } else {
4554 /* one register type load */
4555 load(r, vtop);
4558 vtop->r = r;
4560 return r;
4563 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4564 void gv2(int rc1, int rc2)
4566 int v;
4568 /* generate more generic register first. But VT_JMP or VT_CMP
4569 values must be generated first in all cases to avoid possible
4570 reload errors */
4571 v = vtop[0].r & VT_VALMASK;
4572 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4573 vswap();
4574 gv(rc1);
4575 vswap();
4576 gv(rc2);
4577 /* test if reload is needed for first register */
4578 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4579 vswap();
4580 gv(rc1);
4581 vswap();
4583 } else {
4584 gv(rc2);
4585 vswap();
4586 gv(rc1);
4587 vswap();
4588 /* test if reload is needed for first register */
4589 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4590 gv(rc2);
4595 /* expand long long on stack in two int registers */
4596 void lexpand(void)
4598 int u;
4600 u = vtop->type.t & VT_UNSIGNED;
4601 gv(RC_INT);
4602 vdup();
4603 vtop[0].r = vtop[-1].r2;
4604 vtop[0].r2 = VT_CONST;
4605 vtop[-1].r2 = VT_CONST;
4606 vtop[0].type.t = VT_INT | u;
4607 vtop[-1].type.t = VT_INT | u;
4610 /* build a long long from two ints */
4611 void lbuild(int t)
4613 gv2(RC_INT, RC_INT);
4614 vtop[-1].r2 = vtop[0].r;
4615 vtop[-1].type.t = t;
4616 vpop();
4619 /* rotate n first stack elements to the bottom
4620 I1 ... In -> I2 ... In I1 [top is right]
4622 void vrotb(int n)
4624 int i;
4625 SValue tmp;
4627 tmp = vtop[-n + 1];
4628 for(i=-n+1;i!=0;i++)
4629 vtop[i] = vtop[i+1];
4630 vtop[0] = tmp;
4633 /* rotate n first stack elements to the top
4634 I1 ... In -> In I1 ... I(n-1) [top is right]
4636 void vrott(int n)
4638 int i;
4639 SValue tmp;
4641 tmp = vtop[0];
4642 for(i = 0;i < n - 1; i++)
4643 vtop[-i] = vtop[-i - 1];
4644 vtop[-n + 1] = tmp;
4647 /* pop stack value */
4648 void vpop(void)
4650 int v;
4651 v = vtop->r & VT_VALMASK;
4652 #ifdef TCC_TARGET_I386
4653 /* for x86, we need to pop the FP stack */
4654 if (v == TREG_ST0 && !nocode_wanted) {
4655 o(0xd9dd); /* fstp %st(1) */
4656 } else
4657 #endif
4658 if (v == VT_JMP || v == VT_JMPI) {
4659 /* need to put correct jump if && or || without test */
4660 gsym(vtop->c.ul);
4662 vtop--;
4665 /* convert stack entry to register and duplicate its value in another
4666 register */
4667 void gv_dup(void)
4669 int rc, t, r, r1;
4670 SValue sv;
4672 t = vtop->type.t;
4673 if ((t & VT_BTYPE) == VT_LLONG) {
4674 lexpand();
4675 gv_dup();
4676 vswap();
4677 vrotb(3);
4678 gv_dup();
4679 vrotb(4);
4680 /* stack: H L L1 H1 */
4681 lbuild(t);
4682 vrotb(3);
4683 vrotb(3);
4684 vswap();
4685 lbuild(t);
4686 vswap();
4687 } else {
4688 /* duplicate value */
4689 rc = RC_INT;
4690 sv.type.t = VT_INT;
4691 if (is_float(t)) {
4692 rc = RC_FLOAT;
4693 sv.type.t = t;
4695 r = gv(rc);
4696 r1 = get_reg(rc);
4697 sv.r = r;
4698 sv.c.ul = 0;
4699 load(r1, &sv); /* move r to r1 */
4700 vdup();
4701 /* duplicates value */
4702 vtop->r = r1;
4706 /* generate CPU independent (unsigned) long long operations */
4707 void gen_opl(int op)
4709 int t, a, b, op1, c, i;
4710 int func;
4711 SValue tmp;
4713 switch(op) {
4714 case '/':
4715 case TOK_PDIV:
4716 func = TOK___divdi3;
4717 goto gen_func;
4718 case TOK_UDIV:
4719 func = TOK___udivdi3;
4720 goto gen_func;
4721 case '%':
4722 func = TOK___moddi3;
4723 goto gen_func;
4724 case TOK_UMOD:
4725 func = TOK___umoddi3;
4726 gen_func:
4727 /* call generic long long function */
4728 vpush_global_sym(&func_old_type, func);
4729 vrott(3);
4730 gfunc_call(2);
4731 vpushi(0);
4732 vtop->r = REG_IRET;
4733 vtop->r2 = REG_LRET;
4734 break;
4735 case '^':
4736 case '&':
4737 case '|':
4738 case '*':
4739 case '+':
4740 case '-':
4741 t = vtop->type.t;
4742 vswap();
4743 lexpand();
4744 vrotb(3);
4745 lexpand();
4746 /* stack: L1 H1 L2 H2 */
4747 tmp = vtop[0];
4748 vtop[0] = vtop[-3];
4749 vtop[-3] = tmp;
4750 tmp = vtop[-2];
4751 vtop[-2] = vtop[-3];
4752 vtop[-3] = tmp;
4753 vswap();
4754 /* stack: H1 H2 L1 L2 */
4755 if (op == '*') {
4756 vpushv(vtop - 1);
4757 vpushv(vtop - 1);
4758 gen_op(TOK_UMULL);
4759 lexpand();
4760 /* stack: H1 H2 L1 L2 ML MH */
4761 for(i=0;i<4;i++)
4762 vrotb(6);
4763 /* stack: ML MH H1 H2 L1 L2 */
4764 tmp = vtop[0];
4765 vtop[0] = vtop[-2];
4766 vtop[-2] = tmp;
4767 /* stack: ML MH H1 L2 H2 L1 */
4768 gen_op('*');
4769 vrotb(3);
4770 vrotb(3);
4771 gen_op('*');
4772 /* stack: ML MH M1 M2 */
4773 gen_op('+');
4774 gen_op('+');
4775 } else if (op == '+' || op == '-') {
4776 /* XXX: add non carry method too (for MIPS or alpha) */
4777 if (op == '+')
4778 op1 = TOK_ADDC1;
4779 else
4780 op1 = TOK_SUBC1;
4781 gen_op(op1);
4782 /* stack: H1 H2 (L1 op L2) */
4783 vrotb(3);
4784 vrotb(3);
4785 gen_op(op1 + 1); /* TOK_xxxC2 */
4786 } else {
4787 gen_op(op);
4788 /* stack: H1 H2 (L1 op L2) */
4789 vrotb(3);
4790 vrotb(3);
4791 /* stack: (L1 op L2) H1 H2 */
4792 gen_op(op);
4793 /* stack: (L1 op L2) (H1 op H2) */
4795 /* stack: L H */
4796 lbuild(t);
4797 break;
4798 case TOK_SAR:
4799 case TOK_SHR:
4800 case TOK_SHL:
4801 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4802 t = vtop[-1].type.t;
4803 vswap();
4804 lexpand();
4805 vrotb(3);
4806 /* stack: L H shift */
4807 c = (int)vtop->c.i;
4808 /* constant: simpler */
4809 /* NOTE: all comments are for SHL. the other cases are
4810 done by swaping words */
4811 vpop();
4812 if (op != TOK_SHL)
4813 vswap();
4814 if (c >= 32) {
4815 /* stack: L H */
4816 vpop();
4817 if (c > 32) {
4818 vpushi(c - 32);
4819 gen_op(op);
4821 if (op != TOK_SAR) {
4822 vpushi(0);
4823 } else {
4824 gv_dup();
4825 vpushi(31);
4826 gen_op(TOK_SAR);
4828 vswap();
4829 } else {
4830 vswap();
4831 gv_dup();
4832 /* stack: H L L */
4833 vpushi(c);
4834 gen_op(op);
4835 vswap();
4836 vpushi(32 - c);
4837 if (op == TOK_SHL)
4838 gen_op(TOK_SHR);
4839 else
4840 gen_op(TOK_SHL);
4841 vrotb(3);
4842 /* stack: L L H */
4843 vpushi(c);
4844 if (op == TOK_SHL)
4845 gen_op(TOK_SHL);
4846 else
4847 gen_op(TOK_SHR);
4848 gen_op('|');
4850 if (op != TOK_SHL)
4851 vswap();
4852 lbuild(t);
4853 } else {
4854 /* XXX: should provide a faster fallback on x86 ? */
4855 switch(op) {
4856 case TOK_SAR:
4857 func = TOK___sardi3;
4858 goto gen_func;
4859 case TOK_SHR:
4860 func = TOK___shrdi3;
4861 goto gen_func;
4862 case TOK_SHL:
4863 func = TOK___shldi3;
4864 goto gen_func;
4867 break;
4868 default:
4869 /* compare operations */
4870 t = vtop->type.t;
4871 vswap();
4872 lexpand();
4873 vrotb(3);
4874 lexpand();
4875 /* stack: L1 H1 L2 H2 */
4876 tmp = vtop[-1];
4877 vtop[-1] = vtop[-2];
4878 vtop[-2] = tmp;
4879 /* stack: L1 L2 H1 H2 */
4880 /* compare high */
4881 op1 = op;
4882 /* when values are equal, we need to compare low words. since
4883 the jump is inverted, we invert the test too. */
4884 if (op1 == TOK_LT)
4885 op1 = TOK_LE;
4886 else if (op1 == TOK_GT)
4887 op1 = TOK_GE;
4888 else if (op1 == TOK_ULT)
4889 op1 = TOK_ULE;
4890 else if (op1 == TOK_UGT)
4891 op1 = TOK_UGE;
4892 a = 0;
4893 b = 0;
4894 gen_op(op1);
4895 if (op1 != TOK_NE) {
4896 a = gtst(1, 0);
4898 if (op != TOK_EQ) {
4899 /* generate non equal test */
4900 /* XXX: NOT PORTABLE yet */
4901 if (a == 0) {
4902 b = gtst(0, 0);
4903 } else {
4904 #ifdef TCC_TARGET_I386
4905 b = psym(0x850f, 0);
4906 #else
4907 error("not implemented");
4908 #endif
4911 /* compare low. Always unsigned */
4912 op1 = op;
4913 if (op1 == TOK_LT)
4914 op1 = TOK_ULT;
4915 else if (op1 == TOK_LE)
4916 op1 = TOK_ULE;
4917 else if (op1 == TOK_GT)
4918 op1 = TOK_UGT;
4919 else if (op1 == TOK_GE)
4920 op1 = TOK_UGE;
4921 gen_op(op1);
4922 a = gtst(1, a);
4923 gsym(b);
4924 vseti(VT_JMPI, a);
4925 break;
4929 /* handle integer constant optimizations and various machine
4930 independent opt */
4931 void gen_opic(int op)
4933 int fc, c1, c2, n;
4934 SValue *v1, *v2;
4936 v1 = vtop - 1;
4937 v2 = vtop;
4938 /* currently, we cannot do computations with forward symbols */
4939 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4940 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4941 if (c1 && c2) {
4942 fc = v2->c.i;
4943 switch(op) {
4944 case '+': v1->c.i += fc; break;
4945 case '-': v1->c.i -= fc; break;
4946 case '&': v1->c.i &= fc; break;
4947 case '^': v1->c.i ^= fc; break;
4948 case '|': v1->c.i |= fc; break;
4949 case '*': v1->c.i *= fc; break;
4951 case TOK_PDIV:
4952 case '/':
4953 case '%':
4954 case TOK_UDIV:
4955 case TOK_UMOD:
4956 /* if division by zero, generate explicit division */
4957 if (fc == 0) {
4958 if (const_wanted)
4959 error("division by zero in constant");
4960 goto general_case;
4962 switch(op) {
4963 default: v1->c.i /= fc; break;
4964 case '%': v1->c.i %= fc; break;
4965 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
4966 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
4968 break;
4969 case TOK_SHL: v1->c.i <<= fc; break;
4970 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
4971 case TOK_SAR: v1->c.i >>= fc; break;
4972 /* tests */
4973 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
4974 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
4975 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
4976 case TOK_NE: v1->c.i = v1->c.i != fc; break;
4977 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
4978 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
4979 case TOK_LT: v1->c.i = v1->c.i < fc; break;
4980 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
4981 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
4982 case TOK_GT: v1->c.i = v1->c.i > fc; break;
4983 /* logical */
4984 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
4985 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
4986 default:
4987 goto general_case;
4989 vtop--;
4990 } else {
4991 /* if commutative ops, put c2 as constant */
4992 if (c1 && (op == '+' || op == '&' || op == '^' ||
4993 op == '|' || op == '*')) {
4994 vswap();
4995 swap(&c1, &c2);
4997 fc = vtop->c.i;
4998 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
4999 op == TOK_PDIV) &&
5000 fc == 1) ||
5001 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5002 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5003 fc == 0) ||
5004 (op == '&' &&
5005 fc == -1))) {
5006 /* nothing to do */
5007 vtop--;
5008 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5009 /* try to use shifts instead of muls or divs */
5010 if (fc > 0 && (fc & (fc - 1)) == 0) {
5011 n = -1;
5012 while (fc) {
5013 fc >>= 1;
5014 n++;
5016 vtop->c.i = n;
5017 if (op == '*')
5018 op = TOK_SHL;
5019 else if (op == TOK_PDIV)
5020 op = TOK_SAR;
5021 else
5022 op = TOK_SHR;
5024 goto general_case;
5025 } else if (c2 && (op == '+' || op == '-') &&
5026 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5027 (VT_CONST | VT_SYM)) {
5028 /* symbol + constant case */
5029 if (op == '-')
5030 fc = -fc;
5031 vtop--;
5032 vtop->c.i += fc;
5033 } else {
5034 general_case:
5035 if (!nocode_wanted) {
5036 /* call low level op generator */
5037 gen_opi(op);
5038 } else {
5039 vtop--;
5045 /* generate a floating point operation with constant propagation */
5046 void gen_opif(int op)
5048 int c1, c2;
5049 SValue *v1, *v2;
5050 long double f1, f2;
5052 v1 = vtop - 1;
5053 v2 = vtop;
5054 /* currently, we cannot do computations with forward symbols */
5055 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5056 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5057 if (c1 && c2) {
5058 if (v1->type.t == VT_FLOAT) {
5059 f1 = v1->c.f;
5060 f2 = v2->c.f;
5061 } else if (v1->type.t == VT_DOUBLE) {
5062 f1 = v1->c.d;
5063 f2 = v2->c.d;
5064 } else {
5065 f1 = v1->c.ld;
5066 f2 = v2->c.ld;
5069 /* NOTE: we only do constant propagation if finite number (not
5070 NaN or infinity) (ANSI spec) */
5071 if (!ieee_finite(f1) || !ieee_finite(f2))
5072 goto general_case;
5074 switch(op) {
5075 case '+': f1 += f2; break;
5076 case '-': f1 -= f2; break;
5077 case '*': f1 *= f2; break;
5078 case '/':
5079 if (f2 == 0.0) {
5080 if (const_wanted)
5081 error("division by zero in constant");
5082 goto general_case;
5084 f1 /= f2;
5085 break;
5086 /* XXX: also handles tests ? */
5087 default:
5088 goto general_case;
5090 /* XXX: overflow test ? */
5091 if (v1->type.t == VT_FLOAT) {
5092 v1->c.f = f1;
5093 } else if (v1->type.t == VT_DOUBLE) {
5094 v1->c.d = f1;
5095 } else {
5096 v1->c.ld = f1;
5098 vtop--;
5099 } else {
5100 general_case:
5101 if (!nocode_wanted) {
5102 gen_opf(op);
5103 } else {
5104 vtop--;
5109 static int pointed_size(CType *type)
5111 int align;
5112 return type_size(pointed_type(type), &align);
5115 static inline int is_null_pointer(SValue *p)
5117 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5118 return 0;
5119 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5120 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5123 static inline int is_integer_btype(int bt)
5125 return (bt == VT_BYTE || bt == VT_SHORT ||
5126 bt == VT_INT || bt == VT_LLONG);
5129 /* check types for comparison or substraction of pointers */
5130 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5132 CType *type1, *type2, tmp_type1, tmp_type2;
5133 int bt1, bt2;
5135 /* null pointers are accepted for all comparisons as gcc */
5136 if (is_null_pointer(p1) || is_null_pointer(p2))
5137 return;
5138 type1 = &p1->type;
5139 type2 = &p2->type;
5140 bt1 = type1->t & VT_BTYPE;
5141 bt2 = type2->t & VT_BTYPE;
5142 /* accept comparison between pointer and integer with a warning */
5143 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5144 warning("comparison between pointer and integer");
5145 return;
5148 /* both must be pointers or implicit function pointers */
5149 if (bt1 == VT_PTR) {
5150 type1 = pointed_type(type1);
5151 } else if (bt1 != VT_FUNC)
5152 goto invalid_operands;
5154 if (bt2 == VT_PTR) {
5155 type2 = pointed_type(type2);
5156 } else if (bt2 != VT_FUNC) {
5157 invalid_operands:
5158 error("invalid operands to binary %s", get_tok_str(op, NULL));
5160 if ((type1->t & VT_BTYPE) == VT_VOID ||
5161 (type2->t & VT_BTYPE) == VT_VOID)
5162 return;
5163 tmp_type1 = *type1;
5164 tmp_type2 = *type2;
5165 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5166 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5167 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5168 /* gcc-like error if '-' is used */
5169 if (op == '-')
5170 goto invalid_operands;
5171 else
5172 warning("comparison of distinct pointer types lacks a cast");
5176 /* generic gen_op: handles types problems */
5177 void gen_op(int op)
5179 int u, t1, t2, bt1, bt2, t;
5180 CType type1;
5182 t1 = vtop[-1].type.t;
5183 t2 = vtop[0].type.t;
5184 bt1 = t1 & VT_BTYPE;
5185 bt2 = t2 & VT_BTYPE;
5187 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5188 /* at least one operand is a pointer */
5189 /* relationnal op: must be both pointers */
5190 if (op >= TOK_ULT && op <= TOK_GT) {
5191 check_comparison_pointer_types(vtop - 1, vtop, op);
5192 /* pointers are handled are unsigned */
5193 t = VT_INT | VT_UNSIGNED;
5194 goto std_op;
5196 /* if both pointers, then it must be the '-' op */
5197 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5198 if (op != '-')
5199 error("cannot use pointers here");
5200 check_comparison_pointer_types(vtop - 1, vtop, op);
5201 /* XXX: check that types are compatible */
5202 u = pointed_size(&vtop[-1].type);
5203 gen_opic(op);
5204 /* set to integer type */
5205 vtop->type.t = VT_INT;
5206 vpushi(u);
5207 gen_op(TOK_PDIV);
5208 } else {
5209 /* exactly one pointer : must be '+' or '-'. */
5210 if (op != '-' && op != '+')
5211 error("cannot use pointers here");
5212 /* Put pointer as first operand */
5213 if (bt2 == VT_PTR) {
5214 vswap();
5215 swap(&t1, &t2);
5217 type1 = vtop[-1].type;
5218 /* XXX: cast to int ? (long long case) */
5219 vpushi(pointed_size(&vtop[-1].type));
5220 gen_op('*');
5221 #ifdef CONFIG_TCC_BCHECK
5222 /* if evaluating constant expression, no code should be
5223 generated, so no bound check */
5224 if (do_bounds_check && !const_wanted) {
5225 /* if bounded pointers, we generate a special code to
5226 test bounds */
5227 if (op == '-') {
5228 vpushi(0);
5229 vswap();
5230 gen_op('-');
5232 gen_bounded_ptr_add();
5233 } else
5234 #endif
5236 gen_opic(op);
5238 /* put again type if gen_opic() swaped operands */
5239 vtop->type = type1;
5241 } else if (is_float(bt1) || is_float(bt2)) {
5242 /* compute bigger type and do implicit casts */
5243 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5244 t = VT_LDOUBLE;
5245 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5246 t = VT_DOUBLE;
5247 } else {
5248 t = VT_FLOAT;
5250 /* floats can only be used for a few operations */
5251 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5252 (op < TOK_ULT || op > TOK_GT))
5253 error("invalid operands for binary operation");
5254 goto std_op;
5255 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5256 /* cast to biggest op */
5257 t = VT_LLONG;
5258 /* convert to unsigned if it does not fit in a long long */
5259 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5260 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5261 t |= VT_UNSIGNED;
5262 goto std_op;
5263 } else {
5264 /* integer operations */
5265 t = VT_INT;
5266 /* convert to unsigned if it does not fit in an integer */
5267 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5268 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5269 t |= VT_UNSIGNED;
5270 std_op:
5271 /* XXX: currently, some unsigned operations are explicit, so
5272 we modify them here */
5273 if (t & VT_UNSIGNED) {
5274 if (op == TOK_SAR)
5275 op = TOK_SHR;
5276 else if (op == '/')
5277 op = TOK_UDIV;
5278 else if (op == '%')
5279 op = TOK_UMOD;
5280 else if (op == TOK_LT)
5281 op = TOK_ULT;
5282 else if (op == TOK_GT)
5283 op = TOK_UGT;
5284 else if (op == TOK_LE)
5285 op = TOK_ULE;
5286 else if (op == TOK_GE)
5287 op = TOK_UGE;
5289 vswap();
5290 type1.t = t;
5291 gen_cast(&type1);
5292 vswap();
5293 /* special case for shifts and long long: we keep the shift as
5294 an integer */
5295 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5296 type1.t = VT_INT;
5297 gen_cast(&type1);
5298 if (is_float(t))
5299 gen_opif(op);
5300 else if ((t & VT_BTYPE) == VT_LLONG)
5301 gen_opl(op);
5302 else
5303 gen_opic(op);
5304 if (op >= TOK_ULT && op <= TOK_GT) {
5305 /* relationnal op: the result is an int */
5306 vtop->type.t = VT_INT;
5307 } else {
5308 vtop->type.t = t;
5313 /* generic itof for unsigned long long case */
5314 void gen_cvt_itof1(int t)
5316 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5317 (VT_LLONG | VT_UNSIGNED)) {
5319 if (t == VT_FLOAT)
5320 vpush_global_sym(&func_old_type, TOK___ulltof);
5321 else if (t == VT_DOUBLE)
5322 vpush_global_sym(&func_old_type, TOK___ulltod);
5323 else
5324 vpush_global_sym(&func_old_type, TOK___ulltold);
5325 vrott(2);
5326 gfunc_call(1);
5327 vpushi(0);
5328 vtop->r = REG_FRET;
5329 } else {
5330 gen_cvt_itof(t);
5334 /* generic ftoi for unsigned long long case */
5335 void gen_cvt_ftoi1(int t)
5337 int st;
5339 if (t == (VT_LLONG | VT_UNSIGNED)) {
5340 /* not handled natively */
5341 st = vtop->type.t & VT_BTYPE;
5342 if (st == VT_FLOAT)
5343 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5344 else if (st == VT_DOUBLE)
5345 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5346 else
5347 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5348 vrott(2);
5349 gfunc_call(1);
5350 vpushi(0);
5351 vtop->r = REG_IRET;
5352 vtop->r2 = REG_LRET;
5353 } else {
5354 gen_cvt_ftoi(t);
5358 /* force char or short cast */
5359 void force_charshort_cast(int t)
5361 int bits, dbt;
5362 dbt = t & VT_BTYPE;
5363 /* XXX: add optimization if lvalue : just change type and offset */
5364 if (dbt == VT_BYTE)
5365 bits = 8;
5366 else
5367 bits = 16;
5368 if (t & VT_UNSIGNED) {
5369 vpushi((1 << bits) - 1);
5370 gen_op('&');
5371 } else {
5372 bits = 32 - bits;
5373 vpushi(bits);
5374 gen_op(TOK_SHL);
5375 vpushi(bits);
5376 gen_op(TOK_SAR);
5380 /* cast 'vtop' to 'type' */
5381 static void gen_cast(CType *type)
5383 int sbt, dbt, sf, df, c;
5385 /* special delayed cast for char/short */
5386 /* XXX: in some cases (multiple cascaded casts), it may still
5387 be incorrect */
5388 if (vtop->r & VT_MUSTCAST) {
5389 vtop->r &= ~VT_MUSTCAST;
5390 force_charshort_cast(vtop->type.t);
5393 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5394 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5396 if (sbt != dbt && !nocode_wanted) {
5397 sf = is_float(sbt);
5398 df = is_float(dbt);
5399 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5400 if (sf && df) {
5401 /* convert from fp to fp */
5402 if (c) {
5403 /* constant case: we can do it now */
5404 /* XXX: in ISOC, cannot do it if error in convert */
5405 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5406 vtop->c.f = (float)vtop->c.d;
5407 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5408 vtop->c.f = (float)vtop->c.ld;
5409 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5410 vtop->c.d = (double)vtop->c.f;
5411 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5412 vtop->c.d = (double)vtop->c.ld;
5413 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5414 vtop->c.ld = (long double)vtop->c.f;
5415 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5416 vtop->c.ld = (long double)vtop->c.d;
5417 } else {
5418 /* non constant case: generate code */
5419 gen_cvt_ftof(dbt);
5421 } else if (df) {
5422 /* convert int to fp */
5423 if (c) {
5424 switch(sbt) {
5425 case VT_LLONG | VT_UNSIGNED:
5426 case VT_LLONG:
5427 /* XXX: add const cases for long long */
5428 goto do_itof;
5429 case VT_INT | VT_UNSIGNED:
5430 switch(dbt) {
5431 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5432 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5433 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5435 break;
5436 default:
5437 switch(dbt) {
5438 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5439 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5440 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5442 break;
5444 } else {
5445 do_itof:
5446 gen_cvt_itof1(dbt);
5448 } else if (sf) {
5449 /* convert fp to int */
5450 /* we handle char/short/etc... with generic code */
5451 if (dbt != (VT_INT | VT_UNSIGNED) &&
5452 dbt != (VT_LLONG | VT_UNSIGNED) &&
5453 dbt != VT_LLONG)
5454 dbt = VT_INT;
5455 if (c) {
5456 switch(dbt) {
5457 case VT_LLONG | VT_UNSIGNED:
5458 case VT_LLONG:
5459 /* XXX: add const cases for long long */
5460 goto do_ftoi;
5461 case VT_INT | VT_UNSIGNED:
5462 switch(sbt) {
5463 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5464 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5465 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5467 break;
5468 default:
5469 /* int case */
5470 switch(sbt) {
5471 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5472 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5473 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5475 break;
5477 } else {
5478 do_ftoi:
5479 gen_cvt_ftoi1(dbt);
5481 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5482 /* additional cast for char/short/bool... */
5483 vtop->type.t = dbt;
5484 gen_cast(type);
5486 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5487 if ((sbt & VT_BTYPE) != VT_LLONG) {
5488 /* scalar to long long */
5489 if (c) {
5490 if (sbt == (VT_INT | VT_UNSIGNED))
5491 vtop->c.ll = vtop->c.ui;
5492 else
5493 vtop->c.ll = vtop->c.i;
5494 } else {
5495 /* machine independent conversion */
5496 gv(RC_INT);
5497 /* generate high word */
5498 if (sbt == (VT_INT | VT_UNSIGNED)) {
5499 vpushi(0);
5500 gv(RC_INT);
5501 } else {
5502 gv_dup();
5503 vpushi(31);
5504 gen_op(TOK_SAR);
5506 /* patch second register */
5507 vtop[-1].r2 = vtop->r;
5508 vpop();
5511 } else if (dbt == VT_BOOL) {
5512 /* scalar to bool */
5513 vpushi(0);
5514 gen_op(TOK_NE);
5515 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5516 (dbt & VT_BTYPE) == VT_SHORT) {
5517 force_charshort_cast(dbt);
5518 } else if ((dbt & VT_BTYPE) == VT_INT) {
5519 /* scalar to int */
5520 if (sbt == VT_LLONG) {
5521 /* from long long: just take low order word */
5522 lexpand();
5523 vpop();
5525 /* if lvalue and single word type, nothing to do because
5526 the lvalue already contains the real type size (see
5527 VT_LVAL_xxx constants) */
5530 vtop->type = *type;
5533 /* return type size. Put alignment at 'a' */
5534 static int type_size(CType *type, int *a)
5536 Sym *s;
5537 int bt;
5539 bt = type->t & VT_BTYPE;
5540 if (bt == VT_STRUCT) {
5541 /* struct/union */
5542 s = type->ref;
5543 *a = s->r;
5544 return s->c;
5545 } else if (bt == VT_PTR) {
5546 if (type->t & VT_ARRAY) {
5547 s = type->ref;
5548 return type_size(&s->type, a) * s->c;
5549 } else {
5550 *a = PTR_SIZE;
5551 return PTR_SIZE;
5553 } else if (bt == VT_LDOUBLE) {
5554 *a = LDOUBLE_ALIGN;
5555 return LDOUBLE_SIZE;
5556 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5557 *a = 4; /* XXX: i386 specific */
5558 return 8;
5559 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5560 *a = 4;
5561 return 4;
5562 } else if (bt == VT_SHORT) {
5563 *a = 2;
5564 return 2;
5565 } else {
5566 /* char, void, function, _Bool */
5567 *a = 1;
5568 return 1;
5572 /* return the pointed type of t */
5573 static inline CType *pointed_type(CType *type)
5575 return &type->ref->type;
5578 /* modify type so that its it is a pointer to type. */
5579 static void mk_pointer(CType *type)
5581 Sym *s;
5582 s = sym_push(SYM_FIELD, type, 0, -1);
5583 type->t = VT_PTR | (type->t & ~VT_TYPE);
5584 type->ref = s;
5587 /* compare function types. OLD functions match any new functions */
5588 static int is_compatible_func(CType *type1, CType *type2)
5590 Sym *s1, *s2;
5592 s1 = type1->ref;
5593 s2 = type2->ref;
5594 if (!is_compatible_types(&s1->type, &s2->type))
5595 return 0;
5596 /* XXX: not complete */
5597 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5598 return 1;
5599 if (s1->c != s2->c)
5600 return 0;
5601 while (s1 != NULL) {
5602 if (s2 == NULL)
5603 return 0;
5604 if (!is_compatible_types(&s1->type, &s2->type))
5605 return 0;
5606 s1 = s1->next;
5607 s2 = s2->next;
5609 if (s2)
5610 return 0;
5611 return 1;
5614 /* return true if type1 and type2 are exactly the same (including
5615 qualifiers).
5617 - enums are not checked as gcc __builtin_types_compatible_p ()
5619 static int is_compatible_types(CType *type1, CType *type2)
5621 int bt1, t1, t2;
5623 t1 = type1->t & VT_TYPE;
5624 t2 = type2->t & VT_TYPE;
5625 /* XXX: bitfields ? */
5626 if (t1 != t2)
5627 return 0;
5628 /* test more complicated cases */
5629 bt1 = t1 & VT_BTYPE;
5630 if (bt1 == VT_PTR) {
5631 type1 = pointed_type(type1);
5632 type2 = pointed_type(type2);
5633 return is_compatible_types(type1, type2);
5634 } else if (bt1 == VT_STRUCT) {
5635 return (type1->ref == type2->ref);
5636 } else if (bt1 == VT_FUNC) {
5637 return is_compatible_func(type1, type2);
5638 } else {
5639 return 1;
5643 /* print a type. If 'varstr' is not NULL, then the variable is also
5644 printed in the type */
5645 /* XXX: union */
5646 /* XXX: add array and function pointers */
5647 void type_to_str(char *buf, int buf_size,
5648 CType *type, const char *varstr)
5650 int bt, v, t;
5651 Sym *s, *sa;
5652 char buf1[256];
5653 const char *tstr;
5655 t = type->t & VT_TYPE;
5656 bt = t & VT_BTYPE;
5657 buf[0] = '\0';
5658 if (t & VT_CONSTANT)
5659 pstrcat(buf, buf_size, "const ");
5660 if (t & VT_VOLATILE)
5661 pstrcat(buf, buf_size, "volatile ");
5662 if (t & VT_UNSIGNED)
5663 pstrcat(buf, buf_size, "unsigned ");
5664 switch(bt) {
5665 case VT_VOID:
5666 tstr = "void";
5667 goto add_tstr;
5668 case VT_BOOL:
5669 tstr = "_Bool";
5670 goto add_tstr;
5671 case VT_BYTE:
5672 tstr = "char";
5673 goto add_tstr;
5674 case VT_SHORT:
5675 tstr = "short";
5676 goto add_tstr;
5677 case VT_INT:
5678 tstr = "int";
5679 goto add_tstr;
5680 case VT_LONG:
5681 tstr = "long";
5682 goto add_tstr;
5683 case VT_LLONG:
5684 tstr = "long long";
5685 goto add_tstr;
5686 case VT_FLOAT:
5687 tstr = "float";
5688 goto add_tstr;
5689 case VT_DOUBLE:
5690 tstr = "double";
5691 goto add_tstr;
5692 case VT_LDOUBLE:
5693 tstr = "long double";
5694 add_tstr:
5695 pstrcat(buf, buf_size, tstr);
5696 break;
5697 case VT_ENUM:
5698 case VT_STRUCT:
5699 if (bt == VT_STRUCT)
5700 tstr = "struct ";
5701 else
5702 tstr = "enum ";
5703 pstrcat(buf, buf_size, tstr);
5704 v = type->ref->v & ~SYM_STRUCT;
5705 if (v >= SYM_FIRST_ANOM)
5706 pstrcat(buf, buf_size, "<anonymous>");
5707 else
5708 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5709 break;
5710 case VT_FUNC:
5711 s = type->ref;
5712 type_to_str(buf, buf_size, &s->type, varstr);
5713 pstrcat(buf, buf_size, "(");
5714 sa = s->next;
5715 while (sa != NULL) {
5716 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5717 pstrcat(buf, buf_size, buf1);
5718 sa = sa->next;
5719 if (sa)
5720 pstrcat(buf, buf_size, ", ");
5722 pstrcat(buf, buf_size, ")");
5723 goto no_var;
5724 case VT_PTR:
5725 s = type->ref;
5726 pstrcpy(buf1, sizeof(buf1), "*");
5727 if (varstr)
5728 pstrcat(buf1, sizeof(buf1), varstr);
5729 type_to_str(buf, buf_size, &s->type, buf1);
5730 goto no_var;
5732 if (varstr) {
5733 pstrcat(buf, buf_size, " ");
5734 pstrcat(buf, buf_size, varstr);
5736 no_var: ;
5739 /* verify type compatibility to store vtop in 'dt' type, and generate
5740 casts if needed. */
5741 static void gen_assign_cast(CType *dt)
5743 CType *st, *type1, *type2, tmp_type1, tmp_type2;
5744 char buf1[256], buf2[256];
5745 int dbt, sbt;
5747 st = &vtop->type; /* source type */
5748 dbt = dt->t & VT_BTYPE;
5749 sbt = st->t & VT_BTYPE;
5750 if (dt->t & VT_CONSTANT)
5751 warning("assignment of read-only location");
5752 switch(dbt) {
5753 case VT_PTR:
5754 /* special cases for pointers */
5755 /* '0' can also be a pointer */
5756 if (is_null_pointer(vtop))
5757 goto type_ok;
5758 /* accept implicit pointer to integer cast with warning */
5759 if (is_integer_btype(sbt)) {
5760 warning("assignment makes pointer from integer without a cast");
5761 goto type_ok;
5763 type1 = pointed_type(dt);
5764 /* a function is implicitely a function pointer */
5765 if (sbt == VT_FUNC) {
5766 if ((type1->t & VT_BTYPE) != VT_VOID &&
5767 !is_compatible_types(pointed_type(dt), st))
5768 goto error;
5769 else
5770 goto type_ok;
5772 if (sbt != VT_PTR)
5773 goto error;
5774 type2 = pointed_type(st);
5775 if ((type1->t & VT_BTYPE) == VT_VOID ||
5776 (type2->t & VT_BTYPE) == VT_VOID) {
5777 /* void * can match anything */
5778 } else {
5779 /* exact type match, except for unsigned */
5780 tmp_type1 = *type1;
5781 tmp_type2 = *type2;
5782 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5783 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5784 if (!is_compatible_types(&tmp_type1, &tmp_type2))
5785 goto error;
5787 /* check const and volatile */
5788 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
5789 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
5790 warning("assignment discards qualifiers from pointer target type");
5791 break;
5792 case VT_BYTE:
5793 case VT_SHORT:
5794 case VT_INT:
5795 case VT_LLONG:
5796 if (sbt == VT_PTR || sbt == VT_FUNC) {
5797 warning("assignment makes integer from pointer without a cast");
5799 /* XXX: more tests */
5800 break;
5801 case VT_STRUCT:
5802 if (!is_compatible_types(dt, st)) {
5803 error:
5804 type_to_str(buf1, sizeof(buf1), st, NULL);
5805 type_to_str(buf2, sizeof(buf2), dt, NULL);
5806 error("cannot cast '%s' to '%s'", buf1, buf2);
5808 break;
5810 type_ok:
5811 gen_cast(dt);
5814 /* store vtop in lvalue pushed on stack */
5815 void vstore(void)
5817 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5819 ft = vtop[-1].type.t;
5820 sbt = vtop->type.t & VT_BTYPE;
5821 dbt = ft & VT_BTYPE;
5822 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5823 (sbt == VT_INT && dbt == VT_SHORT)) {
5824 /* optimize char/short casts */
5825 delayed_cast = VT_MUSTCAST;
5826 vtop->type.t = ft & VT_TYPE;
5827 /* XXX: factorize */
5828 if (ft & VT_CONSTANT)
5829 warning("assignment of read-only location");
5830 } else {
5831 delayed_cast = 0;
5832 gen_assign_cast(&vtop[-1].type);
5835 if (sbt == VT_STRUCT) {
5836 /* if structure, only generate pointer */
5837 /* structure assignment : generate memcpy */
5838 /* XXX: optimize if small size */
5839 if (!nocode_wanted) {
5840 size = type_size(&vtop->type, &align);
5842 vpush_global_sym(&func_old_type, TOK_memcpy);
5844 /* destination */
5845 vpushv(vtop - 2);
5846 vtop->type.t = VT_INT;
5847 gaddrof();
5848 /* source */
5849 vpushv(vtop - 2);
5850 vtop->type.t = VT_INT;
5851 gaddrof();
5852 /* type size */
5853 vpushi(size);
5854 gfunc_call(3);
5856 vswap();
5857 vpop();
5858 } else {
5859 vswap();
5860 vpop();
5862 /* leave source on stack */
5863 } else if (ft & VT_BITFIELD) {
5864 /* bitfield store handling */
5865 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5866 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5867 /* remove bit field info to avoid loops */
5868 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5870 /* duplicate destination */
5871 vdup();
5872 vtop[-1] = vtop[-2];
5874 /* mask and shift source */
5875 vpushi((1 << bit_size) - 1);
5876 gen_op('&');
5877 vpushi(bit_pos);
5878 gen_op(TOK_SHL);
5879 /* load destination, mask and or with source */
5880 vswap();
5881 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5882 gen_op('&');
5883 gen_op('|');
5884 /* store result */
5885 vstore();
5886 } else {
5887 #ifdef CONFIG_TCC_BCHECK
5888 /* bound check case */
5889 if (vtop[-1].r & VT_MUSTBOUND) {
5890 vswap();
5891 gbound();
5892 vswap();
5894 #endif
5895 if (!nocode_wanted) {
5896 rc = RC_INT;
5897 if (is_float(ft))
5898 rc = RC_FLOAT;
5899 r = gv(rc); /* generate value */
5900 /* if lvalue was saved on stack, must read it */
5901 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5902 SValue sv;
5903 t = get_reg(RC_INT);
5904 sv.type.t = VT_INT;
5905 sv.r = VT_LOCAL | VT_LVAL;
5906 sv.c.ul = vtop[-1].c.ul;
5907 load(t, &sv);
5908 vtop[-1].r = t | VT_LVAL;
5910 store(r, vtop - 1);
5911 /* two word case handling : store second register at word + 4 */
5912 if ((ft & VT_BTYPE) == VT_LLONG) {
5913 vswap();
5914 /* convert to int to increment easily */
5915 vtop->type.t = VT_INT;
5916 gaddrof();
5917 vpushi(4);
5918 gen_op('+');
5919 vtop->r |= VT_LVAL;
5920 vswap();
5921 /* XXX: it works because r2 is spilled last ! */
5922 store(vtop->r2, vtop - 1);
5925 vswap();
5926 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5927 vtop->r |= delayed_cast;
5931 /* post defines POST/PRE add. c is the token ++ or -- */
5932 void inc(int post, int c)
5934 test_lvalue();
5935 vdup(); /* save lvalue */
5936 if (post) {
5937 gv_dup(); /* duplicate value */
5938 vrotb(3);
5939 vrotb(3);
5941 /* add constant */
5942 vpushi(c - TOK_MID);
5943 gen_op('+');
5944 vstore(); /* store value */
5945 if (post)
5946 vpop(); /* if post op, return saved value */
5949 /* Parse GNUC __attribute__ extension. Currently, the following
5950 extensions are recognized:
5951 - aligned(n) : set data/function alignment.
5952 - section(x) : generate data/code in this section.
5953 - unused : currently ignored, but may be used someday.
5955 static void parse_attribute(AttributeDef *ad)
5957 int t, n;
5959 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
5960 next();
5961 skip('(');
5962 skip('(');
5963 while (tok != ')') {
5964 if (tok < TOK_IDENT)
5965 expect("attribute name");
5966 t = tok;
5967 next();
5968 switch(t) {
5969 case TOK_SECTION1:
5970 case TOK_SECTION2:
5971 skip('(');
5972 if (tok != TOK_STR)
5973 expect("section name");
5974 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
5975 next();
5976 skip(')');
5977 break;
5978 case TOK_ALIGNED1:
5979 case TOK_ALIGNED2:
5980 if (tok == '(') {
5981 next();
5982 n = expr_const();
5983 if (n <= 0 || (n & (n - 1)) != 0)
5984 error("alignment must be a positive power of two");
5985 skip(')');
5986 } else {
5987 n = MAX_ALIGN;
5989 ad->aligned = n;
5990 break;
5991 case TOK_UNUSED1:
5992 case TOK_UNUSED2:
5993 /* currently, no need to handle it because tcc does not
5994 track unused objects */
5995 break;
5996 case TOK_NORETURN1:
5997 case TOK_NORETURN2:
5998 /* currently, no need to handle it because tcc does not
5999 track unused objects */
6000 break;
6001 case TOK_CDECL1:
6002 case TOK_CDECL2:
6003 case TOK_CDECL3:
6004 ad->func_call = FUNC_CDECL;
6005 break;
6006 case TOK_STDCALL1:
6007 case TOK_STDCALL2:
6008 case TOK_STDCALL3:
6009 ad->func_call = FUNC_STDCALL;
6010 break;
6011 default:
6012 if (tcc_state->warn_unsupported)
6013 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6014 /* skip parameters */
6015 /* XXX: skip parenthesis too */
6016 if (tok == '(') {
6017 next();
6018 while (tok != ')' && tok != -1)
6019 next();
6020 next();
6022 break;
6024 if (tok != ',')
6025 break;
6026 next();
6028 skip(')');
6029 skip(')');
6033 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6034 static void struct_decl(CType *type, int u)
6036 int a, v, size, align, maxalign, c, offset;
6037 int bit_size, bit_pos, bsize, bt, lbit_pos;
6038 Sym *s, *ss, **ps;
6039 AttributeDef ad;
6040 CType type1, btype;
6042 a = tok; /* save decl type */
6043 next();
6044 if (tok != '{') {
6045 v = tok;
6046 next();
6047 /* struct already defined ? return it */
6048 if (v < TOK_IDENT)
6049 expect("struct/union/enum name");
6050 s = struct_find(v);
6051 if (s) {
6052 if (s->type.t != a)
6053 error("invalid type");
6054 goto do_decl;
6056 } else {
6057 v = anon_sym++;
6059 type1.t = a;
6060 /* we put an undefined size for struct/union */
6061 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6062 s->r = 0; /* default alignment is zero as gcc */
6063 /* put struct/union/enum name in type */
6064 do_decl:
6065 type->t = u;
6066 type->ref = s;
6068 if (tok == '{') {
6069 next();
6070 if (s->c != -1)
6071 error("struct/union/enum already defined");
6072 /* cannot be empty */
6073 c = 0;
6074 /* non empty enums are not allowed */
6075 if (a == TOK_ENUM) {
6076 for(;;) {
6077 v = tok;
6078 if (v < TOK_UIDENT)
6079 expect("identifier");
6080 next();
6081 if (tok == '=') {
6082 next();
6083 c = expr_const();
6085 /* enum symbols have static storage */
6086 ss = sym_push(v, &int_type, VT_CONST, c);
6087 ss->type.t |= VT_STATIC;
6088 if (tok != ',')
6089 break;
6090 next();
6091 c++;
6092 /* NOTE: we accept a trailing comma */
6093 if (tok == '}')
6094 break;
6096 skip('}');
6097 } else {
6098 maxalign = 1;
6099 ps = &s->next;
6100 bit_pos = 0;
6101 offset = 0;
6102 while (tok != '}') {
6103 parse_btype(&btype, &ad);
6104 while (1) {
6105 bit_size = -1;
6106 v = 0;
6107 type1 = btype;
6108 if (tok != ':') {
6109 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6110 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6111 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6112 error("invalid type for '%s'",
6113 get_tok_str(v, NULL));
6115 if (tok == ':') {
6116 next();
6117 bit_size = expr_const();
6118 /* XXX: handle v = 0 case for messages */
6119 if (bit_size < 0)
6120 error("negative width in bit-field '%s'",
6121 get_tok_str(v, NULL));
6122 if (v && bit_size == 0)
6123 error("zero width for bit-field '%s'",
6124 get_tok_str(v, NULL));
6126 size = type_size(&type1, &align);
6127 lbit_pos = 0;
6128 if (bit_size >= 0) {
6129 bt = type1.t & VT_BTYPE;
6130 if (bt != VT_INT &&
6131 bt != VT_BYTE &&
6132 bt != VT_SHORT &&
6133 bt != VT_ENUM)
6134 error("bitfields must have scalar type");
6135 bsize = size * 8;
6136 if (bit_size > bsize) {
6137 error("width of '%s' exceeds its type",
6138 get_tok_str(v, NULL));
6139 } else if (bit_size == bsize) {
6140 /* no need for bit fields */
6141 bit_pos = 0;
6142 } else if (bit_size == 0) {
6143 /* XXX: what to do if only padding in a
6144 structure ? */
6145 /* zero size: means to pad */
6146 if (bit_pos > 0)
6147 bit_pos = bsize;
6148 } else {
6149 /* we do not have enough room ? */
6150 if ((bit_pos + bit_size) > bsize)
6151 bit_pos = 0;
6152 lbit_pos = bit_pos;
6153 /* XXX: handle LSB first */
6154 type1.t |= VT_BITFIELD |
6155 (bit_pos << VT_STRUCT_SHIFT) |
6156 (bit_size << (VT_STRUCT_SHIFT + 6));
6157 bit_pos += bit_size;
6159 } else {
6160 bit_pos = 0;
6162 if (v) {
6163 /* add new memory data only if starting
6164 bit field */
6165 if (lbit_pos == 0) {
6166 if (a == TOK_STRUCT) {
6167 c = (c + align - 1) & -align;
6168 offset = c;
6169 c += size;
6170 } else {
6171 offset = 0;
6172 if (size > c)
6173 c = size;
6175 if (align > maxalign)
6176 maxalign = align;
6178 #if 0
6179 printf("add field %s offset=%d",
6180 get_tok_str(v, NULL), offset);
6181 if (type1.t & VT_BITFIELD) {
6182 printf(" pos=%d size=%d",
6183 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6184 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6186 printf("\n");
6187 #endif
6188 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6189 *ps = ss;
6190 ps = &ss->next;
6192 if (tok == ';' || tok == TOK_EOF)
6193 break;
6194 skip(',');
6196 skip(';');
6198 skip('}');
6199 /* store size and alignment */
6200 s->c = (c + maxalign - 1) & -maxalign;
6201 s->r = maxalign;
6206 /* return 0 if no type declaration. otherwise, return the basic type
6207 and skip it.
6209 static int parse_btype(CType *type, AttributeDef *ad)
6211 int t, u, type_found, typespec_found;
6212 Sym *s;
6213 CType type1;
6215 memset(ad, 0, sizeof(AttributeDef));
6216 type_found = 0;
6217 typespec_found = 0;
6218 t = 0;
6219 while(1) {
6220 switch(tok) {
6221 case TOK_EXTENSION:
6222 /* currently, we really ignore extension */
6223 next();
6224 continue;
6226 /* basic types */
6227 case TOK_CHAR:
6228 u = VT_BYTE;
6229 basic_type:
6230 next();
6231 basic_type1:
6232 if ((t & VT_BTYPE) != 0)
6233 error("too many basic types");
6234 t |= u;
6235 typespec_found = 1;
6236 break;
6237 case TOK_VOID:
6238 u = VT_VOID;
6239 goto basic_type;
6240 case TOK_SHORT:
6241 u = VT_SHORT;
6242 goto basic_type;
6243 case TOK_INT:
6244 next();
6245 typespec_found = 1;
6246 break;
6247 case TOK_LONG:
6248 next();
6249 if ((t & VT_BTYPE) == VT_DOUBLE) {
6250 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6251 } else if ((t & VT_BTYPE) == VT_LONG) {
6252 t = (t & ~VT_BTYPE) | VT_LLONG;
6253 } else {
6254 u = VT_LONG;
6255 goto basic_type1;
6257 break;
6258 case TOK_BOOL:
6259 u = VT_BOOL;
6260 goto basic_type;
6261 case TOK_FLOAT:
6262 u = VT_FLOAT;
6263 goto basic_type;
6264 case TOK_DOUBLE:
6265 next();
6266 if ((t & VT_BTYPE) == VT_LONG) {
6267 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6268 } else {
6269 u = VT_DOUBLE;
6270 goto basic_type1;
6272 break;
6273 case TOK_ENUM:
6274 struct_decl(&type1, VT_ENUM);
6275 basic_type2:
6276 u = type1.t;
6277 type->ref = type1.ref;
6278 goto basic_type1;
6279 case TOK_STRUCT:
6280 case TOK_UNION:
6281 struct_decl(&type1, VT_STRUCT);
6282 goto basic_type2;
6284 /* type modifiers */
6285 case TOK_CONST1:
6286 case TOK_CONST2:
6287 case TOK_CONST3:
6288 t |= VT_CONSTANT;
6289 next();
6290 break;
6291 case TOK_VOLATILE1:
6292 case TOK_VOLATILE2:
6293 case TOK_VOLATILE3:
6294 t |= VT_VOLATILE;
6295 next();
6296 break;
6297 case TOK_SIGNED1:
6298 case TOK_SIGNED2:
6299 case TOK_SIGNED3:
6300 typespec_found = 1;
6301 case TOK_REGISTER:
6302 case TOK_AUTO:
6303 case TOK_RESTRICT1:
6304 case TOK_RESTRICT2:
6305 case TOK_RESTRICT3:
6306 next();
6307 break;
6308 case TOK_UNSIGNED:
6309 t |= VT_UNSIGNED;
6310 next();
6311 typespec_found = 1;
6312 break;
6314 /* storage */
6315 case TOK_EXTERN:
6316 t |= VT_EXTERN;
6317 next();
6318 break;
6319 case TOK_STATIC:
6320 t |= VT_STATIC;
6321 next();
6322 break;
6323 case TOK_TYPEDEF:
6324 t |= VT_TYPEDEF;
6325 next();
6326 break;
6327 case TOK_INLINE1:
6328 case TOK_INLINE2:
6329 case TOK_INLINE3:
6330 t |= VT_INLINE;
6331 next();
6332 break;
6334 /* GNUC attribute */
6335 case TOK_ATTRIBUTE1:
6336 case TOK_ATTRIBUTE2:
6337 parse_attribute(ad);
6338 break;
6339 /* GNUC typeof */
6340 case TOK_TYPEOF1:
6341 case TOK_TYPEOF2:
6342 case TOK_TYPEOF3:
6343 next();
6344 parse_expr_type(&type1);
6345 goto basic_type2;
6346 default:
6347 if (typespec_found)
6348 goto the_end;
6349 s = sym_find(tok);
6350 if (!s || !(s->type.t & VT_TYPEDEF))
6351 goto the_end;
6352 t |= (s->type.t & ~VT_TYPEDEF);
6353 type->ref = s->type.ref;
6354 next();
6355 break;
6357 type_found = 1;
6359 the_end:
6360 /* long is never used as type */
6361 if ((t & VT_BTYPE) == VT_LONG)
6362 t = (t & ~VT_BTYPE) | VT_INT;
6363 type->t = t;
6364 return type_found;
6367 /* convert a function parameter type (array to pointer and function to
6368 function pointer) */
6369 static inline void convert_parameter_type(CType *pt)
6371 /* array must be transformed to pointer according to ANSI C */
6372 pt->t &= ~VT_ARRAY;
6373 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6374 mk_pointer(pt);
6378 static void post_type(CType *type, AttributeDef *ad)
6380 int n, l, t1;
6381 Sym **plast, *s, *first;
6382 AttributeDef ad1;
6383 CType pt;
6385 if (tok == '(') {
6386 /* function declaration */
6387 next();
6388 l = 0;
6389 first = NULL;
6390 plast = &first;
6391 while (tok != ')') {
6392 /* read param name and compute offset */
6393 if (l != FUNC_OLD) {
6394 if (!parse_btype(&pt, &ad1)) {
6395 if (l) {
6396 error("invalid type");
6397 } else {
6398 l = FUNC_OLD;
6399 goto old_proto;
6402 l = FUNC_NEW;
6403 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6404 break;
6405 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6406 if ((pt.t & VT_BTYPE) == VT_VOID)
6407 error("parameter declared as void");
6408 } else {
6409 old_proto:
6410 n = tok;
6411 pt.t = VT_INT;
6412 next();
6414 convert_parameter_type(&pt);
6415 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6416 *plast = s;
6417 plast = &s->next;
6418 if (tok == ',') {
6419 next();
6420 if (l == FUNC_NEW && tok == TOK_DOTS) {
6421 l = FUNC_ELLIPSIS;
6422 next();
6423 break;
6427 /* if no parameters, then old type prototype */
6428 if (l == 0)
6429 l = FUNC_OLD;
6430 skip(')');
6431 t1 = type->t & VT_STORAGE;
6432 /* NOTE: const is ignored in returned type as it has a special
6433 meaning in gcc / C++ */
6434 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6435 post_type(type, ad);
6436 /* we push a anonymous symbol which will contain the function prototype */
6437 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6438 s->next = first;
6439 type->t = t1 | VT_FUNC;
6440 type->ref = s;
6441 } else if (tok == '[') {
6442 /* array definition */
6443 next();
6444 n = -1;
6445 if (tok != ']') {
6446 n = expr_const();
6447 if (n < 0)
6448 error("invalid array size");
6450 skip(']');
6451 /* parse next post type */
6452 t1 = type->t & VT_STORAGE;
6453 type->t &= ~VT_STORAGE;
6454 post_type(type, ad);
6456 /* we push a anonymous symbol which will contain the array
6457 element type */
6458 s = sym_push(SYM_FIELD, type, 0, n);
6459 type->t = t1 | VT_ARRAY | VT_PTR;
6460 type->ref = s;
6464 /* Parse a type declaration (except basic type), and return the type
6465 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6466 expected. 'type' should contain the basic type. 'ad' is the
6467 attribute definition of the basic type. It can be modified by
6468 type_decl().
6470 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6472 Sym *s;
6473 CType type1, *type2;
6474 int qualifiers;
6476 while (tok == '*') {
6477 qualifiers = 0;
6478 redo:
6479 next();
6480 switch(tok) {
6481 case TOK_CONST1:
6482 case TOK_CONST2:
6483 case TOK_CONST3:
6484 qualifiers |= VT_CONSTANT;
6485 goto redo;
6486 case TOK_VOLATILE1:
6487 case TOK_VOLATILE2:
6488 case TOK_VOLATILE3:
6489 qualifiers |= VT_VOLATILE;
6490 goto redo;
6491 case TOK_RESTRICT1:
6492 case TOK_RESTRICT2:
6493 case TOK_RESTRICT3:
6494 goto redo;
6496 mk_pointer(type);
6497 type->t |= qualifiers;
6500 /* XXX: clarify attribute handling */
6501 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6502 parse_attribute(ad);
6504 /* recursive type */
6505 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6506 type1.t = 0; /* XXX: same as int */
6507 if (tok == '(') {
6508 next();
6509 /* XXX: this is not correct to modify 'ad' at this point, but
6510 the syntax is not clear */
6511 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6512 parse_attribute(ad);
6513 type_decl(&type1, ad, v, td);
6514 skip(')');
6515 } else {
6516 /* type identifier */
6517 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6518 *v = tok;
6519 next();
6520 } else {
6521 if (!(td & TYPE_ABSTRACT))
6522 expect("identifier");
6523 *v = 0;
6526 post_type(type, ad);
6527 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6528 parse_attribute(ad);
6529 if (!type1.t)
6530 return;
6531 /* append type at the end of type1 */
6532 type2 = &type1;
6533 for(;;) {
6534 s = type2->ref;
6535 type2 = &s->type;
6536 if (!type2->t) {
6537 *type2 = *type;
6538 break;
6541 *type = type1;
6544 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6545 static int lvalue_type(int t)
6547 int bt, r;
6548 r = VT_LVAL;
6549 bt = t & VT_BTYPE;
6550 if (bt == VT_BYTE || bt == VT_BOOL)
6551 r |= VT_LVAL_BYTE;
6552 else if (bt == VT_SHORT)
6553 r |= VT_LVAL_SHORT;
6554 else
6555 return r;
6556 if (t & VT_UNSIGNED)
6557 r |= VT_LVAL_UNSIGNED;
6558 return r;
6561 /* indirection with full error checking and bound check */
6562 static void indir(void)
6564 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6565 expect("pointer");
6566 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6567 gv(RC_INT);
6568 vtop->type = *pointed_type(&vtop->type);
6569 /* an array is never an lvalue */
6570 if (!(vtop->type.t & VT_ARRAY)) {
6571 vtop->r |= lvalue_type(vtop->type.t);
6572 /* if bound checking, the referenced pointer must be checked */
6573 if (do_bounds_check)
6574 vtop->r |= VT_MUSTBOUND;
6578 /* pass a parameter to a function and do type checking and casting */
6579 static void gfunc_param_typed(Sym *func, Sym *arg)
6581 int func_type;
6582 CType type;
6584 func_type = func->c;
6585 if (func_type == FUNC_OLD ||
6586 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6587 /* default casting : only need to convert float to double */
6588 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6589 type.t = VT_DOUBLE;
6590 gen_cast(&type);
6592 } else if (arg == NULL) {
6593 error("too many arguments to function");
6594 } else {
6595 type = arg->type;
6596 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6597 gen_assign_cast(&type);
6601 /* parse an expression of the form '(type)' or '(expr)' and return its
6602 type */
6603 static void parse_expr_type(CType *type)
6605 int n;
6606 AttributeDef ad;
6608 skip('(');
6609 if (parse_btype(type, &ad)) {
6610 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6611 } else {
6612 expr_type(type);
6614 skip(')');
6617 static void parse_type(CType *type)
6619 AttributeDef ad;
6620 int n;
6622 if (!parse_btype(type, &ad)) {
6623 expect("type");
6625 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6628 static void vpush_tokc(int t)
6630 CType type;
6631 type.t = t;
6632 vsetc(&type, VT_CONST, &tokc);
6635 static void unary(void)
6637 int n, t, align, size, r;
6638 CType type;
6639 Sym *s;
6640 AttributeDef ad;
6642 /* XXX: GCC 2.95.3 does not generate a table although it should be
6643 better here */
6644 tok_next:
6645 switch(tok) {
6646 case TOK_EXTENSION:
6647 next();
6648 goto tok_next;
6649 case TOK_CINT:
6650 case TOK_CCHAR:
6651 case TOK_LCHAR:
6652 vpushi(tokc.i);
6653 next();
6654 break;
6655 case TOK_CUINT:
6656 vpush_tokc(VT_INT | VT_UNSIGNED);
6657 next();
6658 break;
6659 case TOK_CLLONG:
6660 vpush_tokc(VT_LLONG);
6661 next();
6662 break;
6663 case TOK_CULLONG:
6664 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6665 next();
6666 break;
6667 case TOK_CFLOAT:
6668 vpush_tokc(VT_FLOAT);
6669 next();
6670 break;
6671 case TOK_CDOUBLE:
6672 vpush_tokc(VT_DOUBLE);
6673 next();
6674 break;
6675 case TOK_CLDOUBLE:
6676 vpush_tokc(VT_LDOUBLE);
6677 next();
6678 break;
6679 case TOK___FUNCTION__:
6680 if (!gnu_ext)
6681 goto tok_identifier;
6682 /* fall thru */
6683 case TOK___FUNC__:
6685 void *ptr;
6686 int len;
6687 /* special function name identifier */
6688 len = strlen(funcname) + 1;
6689 /* generate char[len] type */
6690 type.t = VT_BYTE;
6691 mk_pointer(&type);
6692 type.t |= VT_ARRAY;
6693 type.ref->c = len;
6694 vpush_ref(&type, data_section, data_section->data_offset, len);
6695 ptr = section_ptr_add(data_section, len);
6696 memcpy(ptr, funcname, len);
6697 next();
6699 break;
6700 case TOK_LSTR:
6701 t = VT_INT;
6702 goto str_init;
6703 case TOK_STR:
6704 /* string parsing */
6705 t = VT_BYTE;
6706 str_init:
6707 if (tcc_state->warn_write_strings)
6708 t |= VT_CONSTANT;
6709 type.t = t;
6710 mk_pointer(&type);
6711 type.t |= VT_ARRAY;
6712 memset(&ad, 0, sizeof(AttributeDef));
6713 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6714 break;
6715 case '(':
6716 next();
6717 /* cast ? */
6718 if (parse_btype(&type, &ad)) {
6719 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6720 skip(')');
6721 /* check ISOC99 compound literal */
6722 if (tok == '{') {
6723 /* data is allocated locally by default */
6724 if (global_expr)
6725 r = VT_CONST;
6726 else
6727 r = VT_LOCAL;
6728 /* all except arrays are lvalues */
6729 if (!(type.t & VT_ARRAY))
6730 r |= lvalue_type(type.t);
6731 memset(&ad, 0, sizeof(AttributeDef));
6732 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6733 } else {
6734 unary();
6735 gen_cast(&type);
6737 } else if (tok == '{') {
6738 /* save all registers */
6739 save_regs(0);
6740 /* statement expression : we do not accept break/continue
6741 inside as GCC does */
6742 block(NULL, NULL, NULL, NULL, 0, 1);
6743 skip(')');
6744 } else {
6745 gexpr();
6746 skip(')');
6748 break;
6749 case '*':
6750 next();
6751 unary();
6752 indir();
6753 break;
6754 case '&':
6755 next();
6756 unary();
6757 /* functions names must be treated as function pointers,
6758 except for unary '&' and sizeof. Since we consider that
6759 functions are not lvalues, we only have to handle it
6760 there and in function calls. */
6761 /* arrays can also be used although they are not lvalues */
6762 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6763 !(vtop->type.t & VT_ARRAY))
6764 test_lvalue();
6765 mk_pointer(&vtop->type);
6766 gaddrof();
6767 break;
6768 case '!':
6769 next();
6770 unary();
6771 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6772 vtop->c.i = !vtop->c.i;
6773 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6774 vtop->c.i = vtop->c.i ^ 1;
6775 else
6776 vseti(VT_JMP, gtst(1, 0));
6777 break;
6778 case '~':
6779 next();
6780 unary();
6781 vpushi(-1);
6782 gen_op('^');
6783 break;
6784 case '+':
6785 next();
6786 /* in order to force cast, we add zero */
6787 unary();
6788 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6789 error("pointer not accepted for unary plus");
6790 vpushi(0);
6791 gen_op('+');
6792 break;
6793 case TOK_SIZEOF:
6794 case TOK_ALIGNOF1:
6795 case TOK_ALIGNOF2:
6796 t = tok;
6797 next();
6798 if (tok == '(') {
6799 parse_expr_type(&type);
6800 } else {
6801 unary_type(&type);
6803 size = type_size(&type, &align);
6804 if (t == TOK_SIZEOF) {
6805 if (size < 0)
6806 error("sizeof applied to an incomplete type");
6807 vpushi(size);
6808 } else {
6809 vpushi(align);
6811 break;
6813 case TOK_builtin_types_compatible_p:
6815 CType type1, type2;
6816 next();
6817 skip('(');
6818 parse_type(&type1);
6819 skip(',');
6820 parse_type(&type2);
6821 skip(')');
6822 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6823 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6824 vpushi(is_compatible_types(&type1, &type2));
6826 break;
6827 case TOK_builtin_constant_p:
6829 int saved_nocode_wanted, res;
6830 next();
6831 skip('(');
6832 saved_nocode_wanted = nocode_wanted;
6833 nocode_wanted = 1;
6834 gexpr();
6835 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6836 vpop();
6837 nocode_wanted = saved_nocode_wanted;
6838 skip(')');
6839 vpushi(res);
6841 break;
6842 case TOK_INC:
6843 case TOK_DEC:
6844 t = tok;
6845 next();
6846 unary();
6847 inc(0, t);
6848 break;
6849 case '-':
6850 next();
6851 vpushi(0);
6852 unary();
6853 gen_op('-');
6854 break;
6855 case TOK_LAND:
6856 if (!gnu_ext)
6857 goto tok_identifier;
6858 next();
6859 /* allow to take the address of a label */
6860 if (tok < TOK_UIDENT)
6861 expect("label identifier");
6862 s = label_find(tok);
6863 if (!s) {
6864 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6865 } else {
6866 if (s->r == LABEL_DECLARED)
6867 s->r = LABEL_FORWARD;
6869 if (!s->type.t) {
6870 s->type.t = VT_VOID;
6871 mk_pointer(&s->type);
6872 s->type.t |= VT_STATIC;
6874 vset(&s->type, VT_CONST | VT_SYM, 0);
6875 vtop->sym = s;
6876 next();
6877 break;
6878 default:
6879 tok_identifier:
6880 t = tok;
6881 next();
6882 if (t < TOK_UIDENT)
6883 expect("identifier");
6884 s = sym_find(t);
6885 if (!s) {
6886 if (tok != '(')
6887 error("'%s' undeclared", get_tok_str(t, NULL));
6888 /* for simple function calls, we tolerate undeclared
6889 external reference to int() function */
6890 s = external_global_sym(t, &func_old_type, 0);
6892 vset(&s->type, s->r, s->c);
6893 /* if forward reference, we must point to s */
6894 if (vtop->r & VT_SYM) {
6895 vtop->sym = s;
6896 vtop->c.ul = 0;
6898 break;
6901 /* post operations */
6902 while (1) {
6903 if (tok == TOK_INC || tok == TOK_DEC) {
6904 inc(1, tok);
6905 next();
6906 } else if (tok == '.' || tok == TOK_ARROW) {
6907 /* field */
6908 if (tok == TOK_ARROW)
6909 indir();
6910 test_lvalue();
6911 gaddrof();
6912 next();
6913 /* expect pointer on structure */
6914 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6915 expect("struct or union");
6916 s = vtop->type.ref;
6917 /* find field */
6918 tok |= SYM_FIELD;
6919 while ((s = s->next) != NULL) {
6920 if (s->v == tok)
6921 break;
6923 if (!s)
6924 error("field not found");
6925 /* add field offset to pointer */
6926 vtop->type = char_pointer_type; /* change type to 'char *' */
6927 vpushi(s->c);
6928 gen_op('+');
6929 /* change type to field type, and set to lvalue */
6930 vtop->type = s->type;
6931 /* an array is never an lvalue */
6932 if (!(vtop->type.t & VT_ARRAY)) {
6933 vtop->r |= lvalue_type(vtop->type.t);
6934 /* if bound checking, the referenced pointer must be checked */
6935 if (do_bounds_check)
6936 vtop->r |= VT_MUSTBOUND;
6938 next();
6939 } else if (tok == '[') {
6940 next();
6941 gexpr();
6942 gen_op('+');
6943 indir();
6944 skip(']');
6945 } else if (tok == '(') {
6946 SValue ret;
6947 Sym *sa;
6948 int nb_args;
6950 /* function call */
6951 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
6952 /* pointer test (no array accepted) */
6953 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
6954 vtop->type = *pointed_type(&vtop->type);
6955 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
6956 goto error_func;
6957 } else {
6958 error_func:
6959 expect("function pointer");
6961 } else {
6962 vtop->r &= ~VT_LVAL; /* no lvalue */
6964 /* get return type */
6965 s = vtop->type.ref;
6966 next();
6967 sa = s->next; /* first parameter */
6968 nb_args = 0;
6969 /* compute first implicit argument if a structure is returned */
6970 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
6971 /* get some space for the returned structure */
6972 size = type_size(&s->type, &align);
6973 loc = (loc - size) & -align;
6974 ret.type = s->type;
6975 ret.r = VT_LOCAL | VT_LVAL;
6976 /* pass it as 'int' to avoid structure arg passing
6977 problems */
6978 vseti(VT_LOCAL, loc);
6979 ret.c = vtop->c;
6980 nb_args++;
6981 } else {
6982 ret.type = s->type;
6983 ret.r2 = VT_CONST;
6984 /* return in register */
6985 if (is_float(ret.type.t)) {
6986 ret.r = REG_FRET;
6987 } else {
6988 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
6989 ret.r2 = REG_LRET;
6990 ret.r = REG_IRET;
6992 ret.c.i = 0;
6994 if (tok != ')') {
6995 for(;;) {
6996 expr_eq();
6997 gfunc_param_typed(s, sa);
6998 nb_args++;
6999 if (sa)
7000 sa = sa->next;
7001 if (tok == ')')
7002 break;
7003 skip(',');
7006 if (sa)
7007 error("too few arguments to function");
7008 skip(')');
7009 if (!nocode_wanted) {
7010 gfunc_call(nb_args);
7011 } else {
7012 vtop -= (nb_args + 1);
7014 /* return value */
7015 vsetc(&ret.type, ret.r, &ret.c);
7016 vtop->r2 = ret.r2;
7017 } else {
7018 break;
7023 static void uneq(void)
7025 int t;
7027 unary();
7028 if (tok == '=' ||
7029 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7030 tok == TOK_A_XOR || tok == TOK_A_OR ||
7031 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7032 test_lvalue();
7033 t = tok;
7034 next();
7035 if (t == '=') {
7036 expr_eq();
7037 } else {
7038 vdup();
7039 expr_eq();
7040 gen_op(t & 0x7f);
7042 vstore();
7046 static void expr_prod(void)
7048 int t;
7050 uneq();
7051 while (tok == '*' || tok == '/' || tok == '%') {
7052 t = tok;
7053 next();
7054 uneq();
7055 gen_op(t);
7059 static void expr_sum(void)
7061 int t;
7063 expr_prod();
7064 while (tok == '+' || tok == '-') {
7065 t = tok;
7066 next();
7067 expr_prod();
7068 gen_op(t);
7072 static void expr_shift(void)
7074 int t;
7076 expr_sum();
7077 while (tok == TOK_SHL || tok == TOK_SAR) {
7078 t = tok;
7079 next();
7080 expr_sum();
7081 gen_op(t);
7085 static void expr_cmp(void)
7087 int t;
7089 expr_shift();
7090 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7091 tok == TOK_ULT || tok == TOK_UGE) {
7092 t = tok;
7093 next();
7094 expr_shift();
7095 gen_op(t);
7099 static void expr_cmpeq(void)
7101 int t;
7103 expr_cmp();
7104 while (tok == TOK_EQ || tok == TOK_NE) {
7105 t = tok;
7106 next();
7107 expr_cmp();
7108 gen_op(t);
7112 static void expr_and(void)
7114 expr_cmpeq();
7115 while (tok == '&') {
7116 next();
7117 expr_cmpeq();
7118 gen_op('&');
7122 static void expr_xor(void)
7124 expr_and();
7125 while (tok == '^') {
7126 next();
7127 expr_and();
7128 gen_op('^');
7132 static void expr_or(void)
7134 expr_xor();
7135 while (tok == '|') {
7136 next();
7137 expr_xor();
7138 gen_op('|');
7142 /* XXX: fix this mess */
7143 static void expr_land_const(void)
7145 expr_or();
7146 while (tok == TOK_LAND) {
7147 next();
7148 expr_or();
7149 gen_op(TOK_LAND);
7153 /* XXX: fix this mess */
7154 static void expr_lor_const(void)
7156 expr_land_const();
7157 while (tok == TOK_LOR) {
7158 next();
7159 expr_land_const();
7160 gen_op(TOK_LOR);
7164 /* only used if non constant */
7165 static void expr_land(void)
7167 int t;
7169 expr_or();
7170 if (tok == TOK_LAND) {
7171 t = 0;
7172 for(;;) {
7173 t = gtst(1, t);
7174 if (tok != TOK_LAND) {
7175 vseti(VT_JMPI, t);
7176 break;
7178 next();
7179 expr_or();
7184 static void expr_lor(void)
7186 int t;
7188 expr_land();
7189 if (tok == TOK_LOR) {
7190 t = 0;
7191 for(;;) {
7192 t = gtst(0, t);
7193 if (tok != TOK_LOR) {
7194 vseti(VT_JMP, t);
7195 break;
7197 next();
7198 expr_land();
7203 /* XXX: better constant handling */
7204 static void expr_eq(void)
7206 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7207 SValue sv;
7208 CType type, type1, type2;
7210 if (const_wanted) {
7211 int c1, c;
7212 expr_lor_const();
7213 if (tok == '?') {
7214 c = vtop->c.i;
7215 vpop();
7216 next();
7217 if (tok == ':' && gnu_ext) {
7218 c1 = c;
7219 } else {
7220 gexpr();
7221 c1 = vtop->c.i;
7222 vpop();
7224 skip(':');
7225 expr_eq();
7226 if (c)
7227 vtop->c.i = c1;
7229 } else {
7230 expr_lor();
7231 if (tok == '?') {
7232 next();
7233 if (vtop != vstack) {
7234 /* needed to avoid having different registers saved in
7235 each branch */
7236 if (is_float(vtop->type.t))
7237 rc = RC_FLOAT;
7238 else
7239 rc = RC_INT;
7240 gv(rc);
7241 save_regs(1);
7243 if (tok == ':' && gnu_ext) {
7244 gv_dup();
7245 tt = gtst(1, 0);
7246 } else {
7247 tt = gtst(1, 0);
7248 gexpr();
7250 type1 = vtop->type;
7251 sv = *vtop; /* save value to handle it later */
7252 vtop--; /* no vpop so that FP stack is not flushed */
7253 skip(':');
7254 u = gjmp(0);
7255 gsym(tt);
7256 expr_eq();
7257 type2 = vtop->type;
7259 t1 = type1.t;
7260 bt1 = t1 & VT_BTYPE;
7261 t2 = type2.t;
7262 bt2 = t2 & VT_BTYPE;
7263 /* cast operands to correct type according to ISOC rules */
7264 if (is_float(bt1) || is_float(bt2)) {
7265 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7266 type.t = VT_LDOUBLE;
7267 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7268 type.t = VT_DOUBLE;
7269 } else {
7270 type.t = VT_FLOAT;
7272 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7273 /* cast to biggest op */
7274 type.t = VT_LLONG;
7275 /* convert to unsigned if it does not fit in a long long */
7276 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7277 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7278 type.t |= VT_UNSIGNED;
7279 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7280 /* XXX: test pointer compatibility */
7281 type = type1;
7282 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7283 /* XXX: test structure compatibility */
7284 type = type1;
7285 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7286 /* NOTE: as an extension, we accept void on only one side */
7287 type.t = VT_VOID;
7288 } else {
7289 /* integer operations */
7290 type.t = VT_INT;
7291 /* convert to unsigned if it does not fit in an integer */
7292 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7293 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7294 type.t |= VT_UNSIGNED;
7297 /* now we convert second operand */
7298 gen_cast(&type);
7299 rc = RC_INT;
7300 if (is_float(type.t)) {
7301 rc = RC_FLOAT;
7302 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7303 /* for long longs, we use fixed registers to avoid having
7304 to handle a complicated move */
7305 rc = RC_IRET;
7308 r2 = gv(rc);
7309 /* this is horrible, but we must also convert first
7310 operand */
7311 tt = gjmp(0);
7312 gsym(u);
7313 /* put again first value and cast it */
7314 *vtop = sv;
7315 gen_cast(&type);
7316 r1 = gv(rc);
7317 move_reg(r2, r1);
7318 vtop->r = r2;
7319 gsym(tt);
7324 static void gexpr(void)
7326 while (1) {
7327 expr_eq();
7328 if (tok != ',')
7329 break;
7330 vpop();
7331 next();
7335 /* parse an expression and return its type without any side effect. */
7336 static void expr_type(CType *type)
7338 int saved_nocode_wanted;
7340 saved_nocode_wanted = nocode_wanted;
7341 nocode_wanted = 1;
7342 gexpr();
7343 *type = vtop->type;
7344 vpop();
7345 nocode_wanted = saved_nocode_wanted;
7348 /* parse a unary expression and return its type without any side
7349 effect. */
7350 static void unary_type(CType *type)
7352 int a;
7354 a = nocode_wanted;
7355 nocode_wanted = 1;
7356 unary();
7357 *type = vtop->type;
7358 vpop();
7359 nocode_wanted = a;
7362 /* parse a constant expression and return value in vtop. */
7363 static void expr_const1(void)
7365 int a;
7366 a = const_wanted;
7367 const_wanted = 1;
7368 expr_eq();
7369 const_wanted = a;
7372 /* parse an integer constant and return its value. */
7373 static int expr_const(void)
7375 int c;
7376 expr_const1();
7377 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7378 expect("constant expression");
7379 c = vtop->c.i;
7380 vpop();
7381 return c;
7384 /* return the label token if current token is a label, otherwise
7385 return zero */
7386 static int is_label(void)
7388 int last_tok;
7390 /* fast test first */
7391 if (tok < TOK_UIDENT)
7392 return 0;
7393 /* no need to save tokc because tok is an identifier */
7394 last_tok = tok;
7395 next();
7396 if (tok == ':') {
7397 next();
7398 return last_tok;
7399 } else {
7400 unget_tok(last_tok);
7401 return 0;
7405 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7406 int case_reg, int is_expr)
7408 int a, b, c, d;
7409 Sym *s;
7411 /* generate line number info */
7412 if (do_debug &&
7413 (last_line_num != file->line_num || last_ind != ind)) {
7414 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7415 last_ind = ind;
7416 last_line_num = file->line_num;
7419 if (is_expr) {
7420 /* default return value is (void) */
7421 vpushi(0);
7422 vtop->type.t = VT_VOID;
7425 if (tok == TOK_IF) {
7426 /* if test */
7427 next();
7428 skip('(');
7429 gexpr();
7430 skip(')');
7431 a = gtst(1, 0);
7432 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7433 c = tok;
7434 if (c == TOK_ELSE) {
7435 next();
7436 d = gjmp(0);
7437 gsym(a);
7438 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7439 gsym(d); /* patch else jmp */
7440 } else
7441 gsym(a);
7442 } else if (tok == TOK_WHILE) {
7443 next();
7444 d = ind;
7445 skip('(');
7446 gexpr();
7447 skip(')');
7448 a = gtst(1, 0);
7449 b = 0;
7450 block(&a, &b, case_sym, def_sym, case_reg, 0);
7451 gjmp_addr(d);
7452 gsym(a);
7453 gsym_addr(b, d);
7454 } else if (tok == '{') {
7455 Sym *llabel;
7457 next();
7458 /* record local declaration stack position */
7459 s = local_stack;
7460 llabel = local_label_stack;
7461 /* handle local labels declarations */
7462 if (tok == TOK_LABEL) {
7463 next();
7464 for(;;) {
7465 if (tok < TOK_UIDENT)
7466 expect("label identifier");
7467 label_push(&local_label_stack, tok, LABEL_DECLARED);
7468 next();
7469 if (tok == ',') {
7470 next();
7471 } else {
7472 skip(';');
7473 break;
7477 while (tok != '}') {
7478 decl(VT_LOCAL);
7479 if (tok != '}') {
7480 if (is_expr)
7481 vpop();
7482 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7485 /* pop locally defined labels */
7486 label_pop(&local_label_stack, llabel);
7487 /* pop locally defined symbols */
7488 sym_pop(&local_stack, s);
7489 next();
7490 } else if (tok == TOK_RETURN) {
7491 next();
7492 if (tok != ';') {
7493 gexpr();
7494 gen_assign_cast(&func_vt);
7495 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7496 CType type;
7497 /* if returning structure, must copy it to implicit
7498 first pointer arg location */
7499 type = func_vt;
7500 mk_pointer(&type);
7501 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7502 indir();
7503 vswap();
7504 /* copy structure value to pointer */
7505 vstore();
7506 } else if (is_float(func_vt.t)) {
7507 gv(RC_FRET);
7508 } else {
7509 gv(RC_IRET);
7511 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7513 skip(';');
7514 rsym = gjmp(rsym); /* jmp */
7515 } else if (tok == TOK_BREAK) {
7516 /* compute jump */
7517 if (!bsym)
7518 error("cannot break");
7519 *bsym = gjmp(*bsym);
7520 next();
7521 skip(';');
7522 } else if (tok == TOK_CONTINUE) {
7523 /* compute jump */
7524 if (!csym)
7525 error("cannot continue");
7526 *csym = gjmp(*csym);
7527 next();
7528 skip(';');
7529 } else if (tok == TOK_FOR) {
7530 int e;
7531 next();
7532 skip('(');
7533 if (tok != ';') {
7534 gexpr();
7535 vpop();
7537 skip(';');
7538 d = ind;
7539 c = ind;
7540 a = 0;
7541 b = 0;
7542 if (tok != ';') {
7543 gexpr();
7544 a = gtst(1, 0);
7546 skip(';');
7547 if (tok != ')') {
7548 e = gjmp(0);
7549 c = ind;
7550 gexpr();
7551 vpop();
7552 gjmp_addr(d);
7553 gsym(e);
7555 skip(')');
7556 block(&a, &b, case_sym, def_sym, case_reg, 0);
7557 gjmp_addr(c);
7558 gsym(a);
7559 gsym_addr(b, c);
7560 } else
7561 if (tok == TOK_DO) {
7562 next();
7563 a = 0;
7564 b = 0;
7565 d = ind;
7566 block(&a, &b, case_sym, def_sym, case_reg, 0);
7567 skip(TOK_WHILE);
7568 skip('(');
7569 gsym(b);
7570 gexpr();
7571 c = gtst(0, 0);
7572 gsym_addr(c, d);
7573 skip(')');
7574 gsym(a);
7575 skip(';');
7576 } else
7577 if (tok == TOK_SWITCH) {
7578 next();
7579 skip('(');
7580 gexpr();
7581 /* XXX: other types than integer */
7582 case_reg = gv(RC_INT);
7583 vpop();
7584 skip(')');
7585 a = 0;
7586 b = gjmp(0); /* jump to first case */
7587 c = 0;
7588 block(&a, csym, &b, &c, case_reg, 0);
7589 /* if no default, jmp after switch */
7590 if (c == 0)
7591 c = ind;
7592 /* default label */
7593 gsym_addr(b, c);
7594 /* break label */
7595 gsym(a);
7596 } else
7597 if (tok == TOK_CASE) {
7598 int v1, v2;
7599 if (!case_sym)
7600 expect("switch");
7601 next();
7602 v1 = expr_const();
7603 v2 = v1;
7604 if (gnu_ext && tok == TOK_DOTS) {
7605 next();
7606 v2 = expr_const();
7607 if (v2 < v1)
7608 warning("empty case range");
7610 /* since a case is like a label, we must skip it with a jmp */
7611 b = gjmp(0);
7612 gsym(*case_sym);
7613 vseti(case_reg, 0);
7614 vpushi(v1);
7615 if (v1 == v2) {
7616 gen_op(TOK_EQ);
7617 *case_sym = gtst(1, 0);
7618 } else {
7619 gen_op(TOK_GE);
7620 *case_sym = gtst(1, 0);
7621 vseti(case_reg, 0);
7622 vpushi(v2);
7623 gen_op(TOK_LE);
7624 *case_sym = gtst(1, *case_sym);
7626 gsym(b);
7627 skip(':');
7628 is_expr = 0;
7629 goto block_after_label;
7630 } else
7631 if (tok == TOK_DEFAULT) {
7632 next();
7633 skip(':');
7634 if (!def_sym)
7635 expect("switch");
7636 if (*def_sym)
7637 error("too many 'default'");
7638 *def_sym = ind;
7639 is_expr = 0;
7640 goto block_after_label;
7641 } else
7642 if (tok == TOK_GOTO) {
7643 next();
7644 if (tok == '*' && gnu_ext) {
7645 /* computed goto */
7646 next();
7647 gexpr();
7648 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7649 expect("pointer");
7650 ggoto();
7651 } else if (tok >= TOK_UIDENT) {
7652 s = label_find(tok);
7653 /* put forward definition if needed */
7654 if (!s) {
7655 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7656 } else {
7657 if (s->r == LABEL_DECLARED)
7658 s->r = LABEL_FORWARD;
7660 /* label already defined */
7661 if (s->r & LABEL_FORWARD)
7662 s->next = (void *)gjmp((long)s->next);
7663 else
7664 gjmp_addr((long)s->next);
7665 next();
7666 } else {
7667 expect("label identifier");
7669 skip(';');
7670 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7671 asm_instr();
7672 } else {
7673 b = is_label();
7674 if (b) {
7675 /* label case */
7676 s = label_find(b);
7677 if (s) {
7678 if (s->r == LABEL_DEFINED)
7679 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7680 gsym((long)s->next);
7681 s->r = LABEL_DEFINED;
7682 } else {
7683 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7685 s->next = (void *)ind;
7686 /* we accept this, but it is a mistake */
7687 block_after_label:
7688 if (tok == '}') {
7689 warning("deprecated use of label at end of compound statement");
7690 } else {
7691 if (is_expr)
7692 vpop();
7693 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7695 } else {
7696 /* expression case */
7697 if (tok != ';') {
7698 if (is_expr) {
7699 vpop();
7700 gexpr();
7701 } else {
7702 gexpr();
7703 vpop();
7706 skip(';');
7711 /* t is the array or struct type. c is the array or struct
7712 address. cur_index/cur_field is the pointer to the current
7713 value. 'size_only' is true if only size info is needed (only used
7714 in arrays) */
7715 static void decl_designator(CType *type, Section *sec, unsigned long c,
7716 int *cur_index, Sym **cur_field,
7717 int size_only)
7719 Sym *s, *f;
7720 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7721 CType type1;
7723 notfirst = 0;
7724 elem_size = 0;
7725 nb_elems = 1;
7726 if (gnu_ext && (l = is_label()) != 0)
7727 goto struct_field;
7728 while (tok == '[' || tok == '.') {
7729 if (tok == '[') {
7730 if (!(type->t & VT_ARRAY))
7731 expect("array type");
7732 s = type->ref;
7733 next();
7734 index = expr_const();
7735 if (index < 0 || (s->c >= 0 && index >= s->c))
7736 expect("invalid index");
7737 if (tok == TOK_DOTS && gnu_ext) {
7738 next();
7739 index_last = expr_const();
7740 if (index_last < 0 ||
7741 (s->c >= 0 && index_last >= s->c) ||
7742 index_last < index)
7743 expect("invalid index");
7744 } else {
7745 index_last = index;
7747 skip(']');
7748 if (!notfirst)
7749 *cur_index = index_last;
7750 type = pointed_type(type);
7751 elem_size = type_size(type, &align);
7752 c += index * elem_size;
7753 /* NOTE: we only support ranges for last designator */
7754 nb_elems = index_last - index + 1;
7755 if (nb_elems != 1) {
7756 notfirst = 1;
7757 break;
7759 } else {
7760 next();
7761 l = tok;
7762 next();
7763 struct_field:
7764 if ((type->t & VT_BTYPE) != VT_STRUCT)
7765 expect("struct/union type");
7766 s = type->ref;
7767 l |= SYM_FIELD;
7768 f = s->next;
7769 while (f) {
7770 if (f->v == l)
7771 break;
7772 f = f->next;
7774 if (!f)
7775 expect("field");
7776 if (!notfirst)
7777 *cur_field = f;
7778 /* XXX: fix this mess by using explicit storage field */
7779 type1 = f->type;
7780 type1.t |= (type->t & ~VT_TYPE);
7781 type = &type1;
7782 c += f->c;
7784 notfirst = 1;
7786 if (notfirst) {
7787 if (tok == '=') {
7788 next();
7789 } else {
7790 if (!gnu_ext)
7791 expect("=");
7793 } else {
7794 if (type->t & VT_ARRAY) {
7795 index = *cur_index;
7796 type = pointed_type(type);
7797 c += index * type_size(type, &align);
7798 } else {
7799 f = *cur_field;
7800 if (!f)
7801 error("too many field init");
7802 /* XXX: fix this mess by using explicit storage field */
7803 type1 = f->type;
7804 type1.t |= (type->t & ~VT_TYPE);
7805 type = &type1;
7806 c += f->c;
7809 decl_initializer(type, sec, c, 0, size_only);
7811 /* XXX: make it more general */
7812 if (!size_only && nb_elems > 1) {
7813 unsigned long c_end;
7814 uint8_t *src, *dst;
7815 int i;
7817 if (!sec)
7818 error("range init not supported yet for dynamic storage");
7819 c_end = c + nb_elems * elem_size;
7820 if (c_end > sec->data_allocated)
7821 section_realloc(sec, c_end);
7822 src = sec->data + c;
7823 dst = src;
7824 for(i = 1; i < nb_elems; i++) {
7825 dst += elem_size;
7826 memcpy(dst, src, elem_size);
7831 #define EXPR_VAL 0
7832 #define EXPR_CONST 1
7833 #define EXPR_ANY 2
7835 /* store a value or an expression directly in global data or in local array */
7836 static void init_putv(CType *type, Section *sec, unsigned long c,
7837 int v, int expr_type)
7839 int saved_global_expr, bt, bit_pos, bit_size;
7840 void *ptr;
7841 unsigned long long bit_mask;
7842 CType dtype;
7844 switch(expr_type) {
7845 case EXPR_VAL:
7846 vpushi(v);
7847 break;
7848 case EXPR_CONST:
7849 /* compound literals must be allocated globally in this case */
7850 saved_global_expr = global_expr;
7851 global_expr = 1;
7852 expr_const1();
7853 global_expr = saved_global_expr;
7854 /* NOTE: symbols are accepted */
7855 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
7856 error("initializer element is not constant");
7857 break;
7858 case EXPR_ANY:
7859 expr_eq();
7860 break;
7863 dtype = *type;
7864 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7866 if (sec) {
7867 /* XXX: not portable */
7868 /* XXX: generate error if incorrect relocation */
7869 gen_assign_cast(&dtype);
7870 bt = type->t & VT_BTYPE;
7871 ptr = sec->data + c;
7872 /* XXX: make code faster ? */
7873 if (!(type->t & VT_BITFIELD)) {
7874 bit_pos = 0;
7875 bit_size = 32;
7876 bit_mask = -1LL;
7877 } else {
7878 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
7879 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
7880 bit_mask = (1LL << bit_size) - 1;
7882 if ((vtop->r & VT_SYM) &&
7883 (bt == VT_BYTE ||
7884 bt == VT_SHORT ||
7885 bt == VT_DOUBLE ||
7886 bt == VT_LDOUBLE ||
7887 bt == VT_LLONG ||
7888 (bt == VT_INT && bit_size != 32)))
7889 error("initializer element is not computable at load time");
7890 switch(bt) {
7891 case VT_BYTE:
7892 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7893 break;
7894 case VT_SHORT:
7895 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7896 break;
7897 case VT_DOUBLE:
7898 *(double *)ptr = vtop->c.d;
7899 break;
7900 case VT_LDOUBLE:
7901 *(long double *)ptr = vtop->c.ld;
7902 break;
7903 case VT_LLONG:
7904 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
7905 break;
7906 default:
7907 if (vtop->r & VT_SYM) {
7908 greloc(sec, vtop->sym, c, R_DATA_32);
7910 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7911 break;
7913 vtop--;
7914 } else {
7915 vset(&dtype, VT_LOCAL, c);
7916 vswap();
7917 vstore();
7918 vpop();
7922 /* put zeros for variable based init */
7923 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
7925 if (sec) {
7926 /* nothing to do because globals are already set to zero */
7927 } else {
7928 vpush_global_sym(&func_old_type, TOK_memset);
7929 vseti(VT_LOCAL, c);
7930 vpushi(0);
7931 vpushi(size);
7932 gfunc_call(3);
7936 /* 't' contains the type and storage info. 'c' is the offset of the
7937 object in section 'sec'. If 'sec' is NULL, it means stack based
7938 allocation. 'first' is true if array '{' must be read (multi
7939 dimension implicit array init handling). 'size_only' is true if
7940 size only evaluation is wanted (only for arrays). */
7941 static void decl_initializer(CType *type, Section *sec, unsigned long c,
7942 int first, int size_only)
7944 int index, array_length, n, no_oblock, nb, parlevel, i;
7945 int size1, align1, expr_type;
7946 Sym *s, *f;
7947 CType *t1;
7949 if (type->t & VT_ARRAY) {
7950 s = type->ref;
7951 n = s->c;
7952 array_length = 0;
7953 t1 = pointed_type(type);
7954 size1 = type_size(t1, &align1);
7956 no_oblock = 1;
7957 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
7958 tok == '{') {
7959 skip('{');
7960 no_oblock = 0;
7963 /* only parse strings here if correct type (otherwise: handle
7964 them as ((w)char *) expressions */
7965 if ((tok == TOK_LSTR &&
7966 (t1->t & VT_BTYPE) == VT_INT) ||
7967 (tok == TOK_STR &&
7968 (t1->t & VT_BTYPE) == VT_BYTE)) {
7969 while (tok == TOK_STR || tok == TOK_LSTR) {
7970 int cstr_len, ch;
7971 CString *cstr;
7973 cstr = tokc.cstr;
7974 /* compute maximum number of chars wanted */
7975 if (tok == TOK_STR)
7976 cstr_len = cstr->size;
7977 else
7978 cstr_len = cstr->size / sizeof(int);
7979 cstr_len--;
7980 nb = cstr_len;
7981 if (n >= 0 && nb > (n - array_length))
7982 nb = n - array_length;
7983 if (!size_only) {
7984 if (cstr_len > nb)
7985 warning("initializer-string for array is too long");
7986 /* in order to go faster for common case (char
7987 string in global variable, we handle it
7988 specifically */
7989 if (sec && tok == TOK_STR && size1 == 1) {
7990 memcpy(sec->data + c + array_length, cstr->data, nb);
7991 } else {
7992 for(i=0;i<nb;i++) {
7993 if (tok == TOK_STR)
7994 ch = ((unsigned char *)cstr->data)[i];
7995 else
7996 ch = ((int *)cstr->data)[i];
7997 init_putv(t1, sec, c + (array_length + i) * size1,
7998 ch, EXPR_VAL);
8002 array_length += nb;
8003 next();
8005 /* only add trailing zero if enough storage (no
8006 warning in this case since it is standard) */
8007 if (n < 0 || array_length < n) {
8008 if (!size_only) {
8009 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8011 array_length++;
8013 } else {
8014 index = 0;
8015 while (tok != '}') {
8016 decl_designator(type, sec, c, &index, NULL, size_only);
8017 if (n >= 0 && index >= n)
8018 error("index too large");
8019 /* must put zero in holes (note that doing it that way
8020 ensures that it even works with designators) */
8021 if (!size_only && array_length < index) {
8022 init_putz(t1, sec, c + array_length * size1,
8023 (index - array_length) * size1);
8025 index++;
8026 if (index > array_length)
8027 array_length = index;
8028 /* special test for multi dimensional arrays (may not
8029 be strictly correct if designators are used at the
8030 same time) */
8031 if (index >= n && no_oblock)
8032 break;
8033 if (tok == '}')
8034 break;
8035 skip(',');
8038 if (!no_oblock)
8039 skip('}');
8040 /* put zeros at the end */
8041 if (!size_only && n >= 0 && array_length < n) {
8042 init_putz(t1, sec, c + array_length * size1,
8043 (n - array_length) * size1);
8045 /* patch type size if needed */
8046 if (n < 0)
8047 s->c = array_length;
8048 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8049 (sec || !first || tok == '{')) {
8050 int par_count;
8052 /* NOTE: the previous test is a specific case for automatic
8053 struct/union init */
8054 /* XXX: union needs only one init */
8056 /* XXX: this test is incorrect for local initializers
8057 beginning with ( without {. It would be much more difficult
8058 to do it correctly (ideally, the expression parser should
8059 be used in all cases) */
8060 par_count = 0;
8061 if (tok == '(') {
8062 AttributeDef ad1;
8063 CType type1;
8064 next();
8065 while (tok == '(') {
8066 par_count++;
8067 next();
8069 if (!parse_btype(&type1, &ad1))
8070 expect("cast");
8071 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8072 #if 0
8073 if (!is_assignable_types(type, &type1))
8074 error("invalid type for cast");
8075 #endif
8076 skip(')');
8078 no_oblock = 1;
8079 if (first || tok == '{') {
8080 skip('{');
8081 no_oblock = 0;
8083 s = type->ref;
8084 f = s->next;
8085 array_length = 0;
8086 index = 0;
8087 n = s->c;
8088 while (tok != '}') {
8089 decl_designator(type, sec, c, NULL, &f, size_only);
8090 index = f->c;
8091 if (!size_only && array_length < index) {
8092 init_putz(type, sec, c + array_length,
8093 index - array_length);
8095 index = index + type_size(&f->type, &align1);
8096 if (index > array_length)
8097 array_length = index;
8098 f = f->next;
8099 if (no_oblock && f == NULL)
8100 break;
8101 if (tok == '}')
8102 break;
8103 skip(',');
8105 /* put zeros at the end */
8106 if (!size_only && array_length < n) {
8107 init_putz(type, sec, c + array_length,
8108 n - array_length);
8110 if (!no_oblock)
8111 skip('}');
8112 while (par_count) {
8113 skip(')');
8114 par_count--;
8116 } else if (tok == '{') {
8117 next();
8118 decl_initializer(type, sec, c, first, size_only);
8119 skip('}');
8120 } else if (size_only) {
8121 /* just skip expression */
8122 parlevel = 0;
8123 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8124 tok != -1) {
8125 if (tok == '(')
8126 parlevel++;
8127 else if (tok == ')')
8128 parlevel--;
8129 next();
8131 } else {
8132 /* currently, we always use constant expression for globals
8133 (may change for scripting case) */
8134 expr_type = EXPR_CONST;
8135 if (!sec)
8136 expr_type = EXPR_ANY;
8137 init_putv(type, sec, c, 0, expr_type);
8141 /* parse an initializer for type 't' if 'has_init' is non zero, and
8142 allocate space in local or global data space ('r' is either
8143 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8144 variable 'v' of scope 'scope' is declared before initializers are
8145 parsed. If 'v' is zero, then a reference to the new object is put
8146 in the value stack. If 'has_init' is 2, a special parsing is done
8147 to handle string constants. */
8148 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8149 int has_init, int v, int scope)
8151 int size, align, addr, data_offset;
8152 int level;
8153 ParseState saved_parse_state;
8154 TokenString init_str;
8155 Section *sec;
8157 size = type_size(type, &align);
8158 /* If unknown size, we must evaluate it before
8159 evaluating initializers because
8160 initializers can generate global data too
8161 (e.g. string pointers or ISOC99 compound
8162 literals). It also simplifies local
8163 initializers handling */
8164 tok_str_new(&init_str);
8165 if (size < 0) {
8166 if (!has_init)
8167 error("unknown type size");
8168 /* get all init string */
8169 if (has_init == 2) {
8170 /* only get strings */
8171 while (tok == TOK_STR || tok == TOK_LSTR) {
8172 tok_str_add_tok(&init_str);
8173 next();
8175 } else {
8176 level = 0;
8177 while (level > 0 || (tok != ',' && tok != ';')) {
8178 if (tok < 0)
8179 error("unexpected end of file in initializer");
8180 tok_str_add_tok(&init_str);
8181 if (tok == '{')
8182 level++;
8183 else if (tok == '}') {
8184 if (level == 0)
8185 break;
8186 level--;
8188 next();
8191 tok_str_add(&init_str, -1);
8192 tok_str_add(&init_str, 0);
8194 /* compute size */
8195 save_parse_state(&saved_parse_state);
8197 macro_ptr = init_str.str;
8198 next();
8199 decl_initializer(type, NULL, 0, 1, 1);
8200 /* prepare second initializer parsing */
8201 macro_ptr = init_str.str;
8202 next();
8204 /* if still unknown size, error */
8205 size = type_size(type, &align);
8206 if (size < 0)
8207 error("unknown type size");
8209 /* take into account specified alignment if bigger */
8210 if (ad->aligned > align)
8211 align = ad->aligned;
8212 if ((r & VT_VALMASK) == VT_LOCAL) {
8213 sec = NULL;
8214 if (do_bounds_check && (type->t & VT_ARRAY))
8215 loc--;
8216 loc = (loc - size) & -align;
8217 addr = loc;
8218 /* handles bounds */
8219 /* XXX: currently, since we do only one pass, we cannot track
8220 '&' operators, so we add only arrays */
8221 if (do_bounds_check && (type->t & VT_ARRAY)) {
8222 unsigned long *bounds_ptr;
8223 /* add padding between regions */
8224 loc--;
8225 /* then add local bound info */
8226 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8227 bounds_ptr[0] = addr;
8228 bounds_ptr[1] = size;
8230 if (v) {
8231 /* local variable */
8232 sym_push(v, type, r, addr);
8233 } else {
8234 /* push local reference */
8235 vset(type, r, addr);
8237 } else {
8238 Sym *sym;
8240 sym = NULL;
8241 if (v && scope == VT_CONST) {
8242 /* see if the symbol was already defined */
8243 sym = sym_find(v);
8244 if (sym) {
8245 if (!is_compatible_types(&sym->type, type))
8246 error("incompatible types for redefinition of '%s'",
8247 get_tok_str(v, NULL));
8248 if (sym->type.t & VT_EXTERN) {
8249 /* if the variable is extern, it was not allocated */
8250 sym->type.t &= ~VT_EXTERN;
8251 } else {
8252 /* we accept several definitions of the same
8253 global variable. this is tricky, because we
8254 must play with the SHN_COMMON type of the symbol */
8255 /* XXX: should check if the variable was already
8256 initialized. It is incorrect to initialized it
8257 twice */
8258 /* no init data, we won't add more to the symbol */
8259 if (!has_init)
8260 goto no_alloc;
8265 /* allocate symbol in corresponding section */
8266 sec = ad->section;
8267 if (!sec) {
8268 if (has_init)
8269 sec = data_section;
8271 if (sec) {
8272 data_offset = sec->data_offset;
8273 data_offset = (data_offset + align - 1) & -align;
8274 addr = data_offset;
8275 /* very important to increment global pointer at this time
8276 because initializers themselves can create new initializers */
8277 data_offset += size;
8278 /* add padding if bound check */
8279 if (do_bounds_check)
8280 data_offset++;
8281 sec->data_offset = data_offset;
8282 /* allocate section space to put the data */
8283 if (sec->sh_type != SHT_NOBITS &&
8284 data_offset > sec->data_allocated)
8285 section_realloc(sec, data_offset);
8286 } else {
8287 addr = 0; /* avoid warning */
8290 if (v) {
8291 if (scope == VT_CONST) {
8292 if (!sym)
8293 goto do_def;
8294 } else {
8295 do_def:
8296 sym = sym_push(v, type, r | VT_SYM, 0);
8298 /* update symbol definition */
8299 if (sec) {
8300 put_extern_sym(sym, sec, addr, size);
8301 } else {
8302 Elf32_Sym *esym;
8303 /* put a common area */
8304 put_extern_sym(sym, NULL, align, size);
8305 /* XXX: find a nicer way */
8306 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8307 esym->st_shndx = SHN_COMMON;
8309 } else {
8310 CValue cval;
8312 /* push global reference */
8313 sym = get_sym_ref(type, sec, addr, size);
8314 cval.ul = 0;
8315 vsetc(type, VT_CONST | VT_SYM, &cval);
8316 vtop->sym = sym;
8319 /* handles bounds now because the symbol must be defined
8320 before for the relocation */
8321 if (do_bounds_check) {
8322 unsigned long *bounds_ptr;
8324 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8325 /* then add global bound info */
8326 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8327 bounds_ptr[0] = 0; /* relocated */
8328 bounds_ptr[1] = size;
8331 if (has_init) {
8332 decl_initializer(type, sec, addr, 1, 0);
8333 /* restore parse state if needed */
8334 if (init_str.str) {
8335 tok_str_free(init_str.str);
8336 restore_parse_state(&saved_parse_state);
8339 no_alloc: ;
8342 void put_func_debug(Sym *sym)
8344 char buf[512];
8346 /* stabs info */
8347 /* XXX: we put here a dummy type */
8348 snprintf(buf, sizeof(buf), "%s:%c1",
8349 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8350 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8351 cur_text_section, sym->c);
8352 last_ind = 0;
8353 last_line_num = 0;
8356 /* not finished : try to put some local vars in registers */
8357 //#define CONFIG_REG_VARS
8359 #ifdef CONFIG_REG_VARS
8360 void add_var_ref(int t)
8362 printf("%s:%d: &%s\n",
8363 file->filename, file->line_num,
8364 get_tok_str(t, NULL));
8367 /* first pass on a function with heuristic to extract variable usage
8368 and pointer references to local variables for register allocation */
8369 void analyse_function(void)
8371 int level, t;
8373 for(;;) {
8374 if (tok == -1)
8375 break;
8376 /* any symbol coming after '&' is considered as being a
8377 variable whose reference is taken. It is highly unaccurate
8378 but it is difficult to do better without a complete parse */
8379 if (tok == '&') {
8380 next();
8381 /* if '& number', then no need to examine next tokens */
8382 if (tok == TOK_CINT ||
8383 tok == TOK_CUINT ||
8384 tok == TOK_CLLONG ||
8385 tok == TOK_CULLONG) {
8386 continue;
8387 } else if (tok >= TOK_UIDENT) {
8388 /* if '& ident [' or '& ident ->', then ident address
8389 is not needed */
8390 t = tok;
8391 next();
8392 if (tok != '[' && tok != TOK_ARROW)
8393 add_var_ref(t);
8394 } else {
8395 level = 0;
8396 while (tok != '}' && tok != ';' &&
8397 !((tok == ',' || tok == ')') && level == 0)) {
8398 if (tok >= TOK_UIDENT) {
8399 add_var_ref(tok);
8400 } else if (tok == '(') {
8401 level++;
8402 } else if (tok == ')') {
8403 level--;
8405 next();
8408 } else {
8409 next();
8413 #endif
8415 /* parse an old style function declaration list */
8416 /* XXX: check multiple parameter */
8417 static void func_decl_list(Sym *func_sym)
8419 AttributeDef ad;
8420 int v;
8421 Sym *s;
8422 CType btype, type;
8424 /* parse each declaration */
8425 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8426 if (!parse_btype(&btype, &ad))
8427 expect("declaration list");
8428 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8429 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8430 tok == ';') {
8431 /* we accept no variable after */
8432 } else {
8433 for(;;) {
8434 type = btype;
8435 type_decl(&type, &ad, &v, TYPE_DIRECT);
8436 /* find parameter in function parameter list */
8437 s = func_sym->next;
8438 while (s != NULL) {
8439 if ((s->v & ~SYM_FIELD) == v)
8440 goto found;
8441 s = s->next;
8443 error("declaration for parameter '%s' but no such parameter",
8444 get_tok_str(v, NULL));
8445 found:
8446 /* check that no storage specifier except 'register' was given */
8447 if (type.t & VT_STORAGE)
8448 error("storage class specified for '%s'", get_tok_str(v, NULL));
8449 convert_parameter_type(&type);
8450 /* we can add the type (NOTE: it could be local to the function) */
8451 s->type = type;
8452 /* accept other parameters */
8453 if (tok == ',')
8454 next();
8455 else
8456 break;
8459 skip(';');
8463 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8464 static void decl(int l)
8466 int v, has_init, r;
8467 CType type, btype;
8468 Sym *sym;
8469 AttributeDef ad;
8471 while (1) {
8472 if (!parse_btype(&btype, &ad)) {
8473 /* skip redundant ';' */
8474 /* XXX: find more elegant solution */
8475 if (tok == ';') {
8476 next();
8477 continue;
8479 /* special test for old K&R protos without explicit int
8480 type. Only accepted when defining global data */
8481 if (l == VT_LOCAL || tok < TOK_DEFINE)
8482 break;
8483 btype.t = VT_INT;
8485 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8486 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8487 tok == ';') {
8488 /* we accept no variable after */
8489 next();
8490 continue;
8492 while (1) { /* iterate thru each declaration */
8493 type = btype;
8494 type_decl(&type, &ad, &v, TYPE_DIRECT);
8495 #if 0
8497 char buf[500];
8498 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8499 printf("type = '%s'\n", buf);
8501 #endif
8502 if ((type.t & VT_BTYPE) == VT_FUNC) {
8503 /* if old style function prototype, we accept a
8504 declaration list */
8505 sym = type.ref;
8506 if (sym->c == FUNC_OLD)
8507 func_decl_list(sym);
8510 if (tok == '{') {
8511 #ifdef CONFIG_REG_VARS
8512 TokenString func_str;
8513 ParseState saved_parse_state;
8514 int block_level;
8515 #endif
8517 if (l == VT_LOCAL)
8518 error("cannot use local functions");
8519 if (!(type.t & VT_FUNC))
8520 expect("function definition");
8522 /* reject abstract declarators in function definition */
8523 sym = type.ref;
8524 while ((sym = sym->next) != NULL)
8525 if (!(sym->v & ~SYM_FIELD))
8526 expect("identifier");
8528 /* XXX: cannot do better now: convert extern line to static inline */
8529 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8530 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8532 #ifdef CONFIG_REG_VARS
8533 /* parse all function code and record it */
8535 tok_str_new(&func_str);
8537 block_level = 0;
8538 for(;;) {
8539 int t;
8540 if (tok == -1)
8541 error("unexpected end of file");
8542 tok_str_add_tok(&func_str);
8543 t = tok;
8544 next();
8545 if (t == '{') {
8546 block_level++;
8547 } else if (t == '}') {
8548 block_level--;
8549 if (block_level == 0)
8550 break;
8553 tok_str_add(&func_str, -1);
8554 tok_str_add(&func_str, 0);
8556 save_parse_state(&saved_parse_state);
8558 macro_ptr = func_str.str;
8559 next();
8560 analyse_function();
8561 #endif
8563 /* compute text section */
8564 cur_text_section = ad.section;
8565 if (!cur_text_section)
8566 cur_text_section = text_section;
8567 ind = cur_text_section->data_offset;
8568 funcname = get_tok_str(v, NULL);
8569 sym = sym_find(v);
8570 if (sym) {
8571 /* if symbol is already defined, then put complete type */
8572 sym->type = type;
8573 } else {
8574 /* put function symbol */
8575 sym = global_identifier_push(v, type.t, 0);
8576 sym->type.ref = type.ref;
8578 /* NOTE: we patch the symbol size later */
8579 put_extern_sym(sym, cur_text_section, ind, 0);
8580 func_ind = ind;
8581 sym->r = VT_SYM | VT_CONST;
8582 /* put debug symbol */
8583 if (do_debug)
8584 put_func_debug(sym);
8585 /* push a dummy symbol to enable local sym storage */
8586 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8587 gfunc_prolog(&type);
8588 loc = 0;
8589 rsym = 0;
8590 #ifdef CONFIG_REG_VARS
8591 macro_ptr = func_str.str;
8592 next();
8593 #endif
8594 block(NULL, NULL, NULL, NULL, 0, 0);
8595 gsym(rsym);
8596 gfunc_epilog();
8597 cur_text_section->data_offset = ind;
8598 label_pop(&global_label_stack, NULL);
8599 sym_pop(&local_stack, NULL); /* reset local stack */
8600 /* end of function */
8601 /* patch symbol size */
8602 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8603 ind - func_ind;
8604 if (do_debug) {
8605 put_stabn(N_FUN, 0, 0, ind - func_ind);
8607 funcname = ""; /* for safety */
8608 func_vt.t = VT_VOID; /* for safety */
8609 ind = 0; /* for safety */
8611 #ifdef CONFIG_REG_VARS
8612 tok_str_free(func_str.str);
8613 restore_parse_state(&saved_parse_state);
8614 #endif
8615 break;
8616 } else {
8617 if (btype.t & VT_TYPEDEF) {
8618 /* save typedefed type */
8619 /* XXX: test storage specifiers ? */
8620 sym = sym_push(v, &type, 0, 0);
8621 sym->type.t |= VT_TYPEDEF;
8622 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8623 /* external function definition */
8624 external_sym(v, &type, 0);
8625 } else {
8626 /* not lvalue if array */
8627 r = 0;
8628 if (!(type.t & VT_ARRAY))
8629 r |= lvalue_type(type.t);
8630 has_init = (tok == '=');
8631 if ((btype.t & VT_EXTERN) ||
8632 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8633 !has_init && l == VT_CONST && type.ref->c < 0)) {
8634 /* external variable */
8635 /* NOTE: as GCC, uninitialized global static
8636 arrays of null size are considered as
8637 extern */
8638 external_sym(v, &type, r);
8639 } else {
8640 if (type.t & VT_STATIC)
8641 r |= VT_CONST;
8642 else
8643 r |= l;
8644 if (has_init)
8645 next();
8646 decl_initializer_alloc(&type, &ad, r,
8647 has_init, v, l);
8650 if (tok != ',') {
8651 skip(';');
8652 break;
8654 next();
8660 /* better than nothing, but needs extension to handle '-E' option
8661 correctly too */
8662 static void preprocess_init(TCCState *s1)
8664 s1->include_stack_ptr = s1->include_stack;
8665 /* XXX: move that before to avoid having to initialize
8666 file->ifdef_stack_ptr ? */
8667 s1->ifdef_stack_ptr = s1->ifdef_stack;
8668 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8670 /* XXX: not ANSI compliant: bound checking says error */
8671 vtop = vstack - 1;
8674 /* compile the C file opened in 'file'. Return non zero if errors. */
8675 static int tcc_compile(TCCState *s1)
8677 Sym *define_start;
8678 char buf[512];
8679 volatile int section_sym;
8681 #ifdef INC_DEBUG
8682 printf("%s: **** new file\n", file->filename);
8683 #endif
8684 preprocess_init(s1);
8686 funcname = "";
8687 anon_sym = SYM_FIRST_ANOM;
8689 /* file info: full path + filename */
8690 section_sym = 0; /* avoid warning */
8691 if (do_debug) {
8692 section_sym = put_elf_sym(symtab_section, 0, 0,
8693 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8694 text_section->sh_num, NULL);
8695 getcwd(buf, sizeof(buf));
8696 pstrcat(buf, sizeof(buf), "/");
8697 put_stabs_r(buf, N_SO, 0, 0,
8698 text_section->data_offset, text_section, section_sym);
8699 put_stabs_r(file->filename, N_SO, 0, 0,
8700 text_section->data_offset, text_section, section_sym);
8702 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8703 symbols can be safely used */
8704 put_elf_sym(symtab_section, 0, 0,
8705 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8706 SHN_ABS, file->filename);
8708 /* define some often used types */
8709 int_type.t = VT_INT;
8711 char_pointer_type.t = VT_BYTE;
8712 mk_pointer(&char_pointer_type);
8714 func_old_type.t = VT_FUNC;
8715 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8717 #if 0
8718 /* define 'void *alloca(unsigned int)' builtin function */
8720 Sym *s1;
8722 p = anon_sym++;
8723 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8724 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8725 s1->next = NULL;
8726 sym->next = s1;
8727 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8729 #endif
8731 define_start = define_stack;
8733 if (setjmp(s1->error_jmp_buf) == 0) {
8734 s1->nb_errors = 0;
8735 s1->error_set_jmp_enabled = 1;
8737 ch = file->buf_ptr[0];
8738 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8739 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8740 next();
8741 decl(VT_CONST);
8742 if (tok != TOK_EOF)
8743 expect("declaration");
8745 /* end of translation unit info */
8746 if (do_debug) {
8747 put_stabs_r(NULL, N_SO, 0, 0,
8748 text_section->data_offset, text_section, section_sym);
8751 s1->error_set_jmp_enabled = 0;
8753 /* reset define stack, but leave -Dsymbols (may be incorrect if
8754 they are undefined) */
8755 free_defines(define_start);
8757 sym_pop(&global_stack, NULL);
8759 return s1->nb_errors != 0 ? -1 : 0;
8762 #ifdef LIBTCC
8763 int tcc_compile_string(TCCState *s, const char *str)
8765 BufferedFile bf1, *bf = &bf1;
8766 int ret, len;
8767 char *buf;
8769 /* init file structure */
8770 bf->fd = -1;
8771 /* XXX: avoid copying */
8772 len = strlen(str);
8773 buf = tcc_malloc(len + 1);
8774 if (!buf)
8775 return -1;
8776 memcpy(buf, str, len);
8777 buf[len] = CH_EOB;
8778 bf->buf_ptr = buf;
8779 bf->buf_end = buf + len;
8780 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8781 bf->line_num = 1;
8782 file = bf;
8784 ret = tcc_compile(s);
8786 tcc_free(buf);
8788 /* currently, no need to close */
8789 return ret;
8791 #endif
8793 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8794 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8796 BufferedFile bf1, *bf = &bf1;
8798 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8799 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8800 /* default value */
8801 if (!value)
8802 value = "1";
8803 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8805 /* init file structure */
8806 bf->fd = -1;
8807 bf->buf_ptr = bf->buffer;
8808 bf->buf_end = bf->buffer + strlen(bf->buffer);
8809 *bf->buf_end = CH_EOB;
8810 bf->filename[0] = '\0';
8811 bf->line_num = 1;
8812 file = bf;
8814 s1->include_stack_ptr = s1->include_stack;
8816 /* parse with define parser */
8817 ch = file->buf_ptr[0];
8818 next_nomacro();
8819 parse_define();
8820 file = NULL;
8823 /* undefine a preprocessor symbol */
8824 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8826 TokenSym *ts;
8827 Sym *s;
8828 ts = tok_alloc(sym, strlen(sym));
8829 s = define_find(ts->tok);
8830 /* undefine symbol by putting an invalid name */
8831 if (s)
8832 define_undef(s);
8835 #ifdef CONFIG_TCC_ASM
8837 #include "i386-asm.c"
8838 #include "tccasm.c"
8840 #else
8841 static void asm_instr(void)
8843 error("inline asm() not supported");
8845 #endif
8847 #include "tccelf.c"
8849 /* print the position in the source file of PC value 'pc' by reading
8850 the stabs debug information */
8851 static void rt_printline(unsigned long wanted_pc)
8853 Stab_Sym *sym, *sym_end;
8854 char func_name[128], last_func_name[128];
8855 unsigned long func_addr, last_pc, pc;
8856 const char *incl_files[INCLUDE_STACK_SIZE];
8857 int incl_index, len, last_line_num, i;
8858 const char *str, *p;
8860 fprintf(stderr, "0x%08lx:", wanted_pc);
8862 func_name[0] = '\0';
8863 func_addr = 0;
8864 incl_index = 0;
8865 last_func_name[0] = '\0';
8866 last_pc = 0xffffffff;
8867 last_line_num = 1;
8868 sym = (Stab_Sym *)stab_section->data + 1;
8869 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
8870 while (sym < sym_end) {
8871 switch(sym->n_type) {
8872 /* function start or end */
8873 case N_FUN:
8874 if (sym->n_strx == 0) {
8875 /* we test if between last line and end of function */
8876 pc = sym->n_value + func_addr;
8877 if (wanted_pc >= last_pc && wanted_pc < pc)
8878 goto found;
8879 func_name[0] = '\0';
8880 func_addr = 0;
8881 } else {
8882 str = stabstr_section->data + sym->n_strx;
8883 p = strchr(str, ':');
8884 if (!p) {
8885 pstrcpy(func_name, sizeof(func_name), str);
8886 } else {
8887 len = p - str;
8888 if (len > sizeof(func_name) - 1)
8889 len = sizeof(func_name) - 1;
8890 memcpy(func_name, str, len);
8891 func_name[len] = '\0';
8893 func_addr = sym->n_value;
8895 break;
8896 /* line number info */
8897 case N_SLINE:
8898 pc = sym->n_value + func_addr;
8899 if (wanted_pc >= last_pc && wanted_pc < pc)
8900 goto found;
8901 last_pc = pc;
8902 last_line_num = sym->n_desc;
8903 /* XXX: slow! */
8904 strcpy(last_func_name, func_name);
8905 break;
8906 /* include files */
8907 case N_BINCL:
8908 str = stabstr_section->data + sym->n_strx;
8909 add_incl:
8910 if (incl_index < INCLUDE_STACK_SIZE) {
8911 incl_files[incl_index++] = str;
8913 break;
8914 case N_EINCL:
8915 if (incl_index > 1)
8916 incl_index--;
8917 break;
8918 case N_SO:
8919 if (sym->n_strx == 0) {
8920 incl_index = 0; /* end of translation unit */
8921 } else {
8922 str = stabstr_section->data + sym->n_strx;
8923 /* do not add path */
8924 len = strlen(str);
8925 if (len > 0 && str[len - 1] != '/')
8926 goto add_incl;
8928 break;
8930 sym++;
8933 /* second pass: we try symtab symbols (no line number info) */
8934 incl_index = 0;
8936 Elf32_Sym *sym, *sym_end;
8937 int type;
8939 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
8940 for(sym = (Elf32_Sym *)symtab_section->data + 1;
8941 sym < sym_end;
8942 sym++) {
8943 type = ELF32_ST_TYPE(sym->st_info);
8944 if (type == STT_FUNC) {
8945 if (wanted_pc >= sym->st_value &&
8946 wanted_pc < sym->st_value + sym->st_size) {
8947 pstrcpy(last_func_name, sizeof(last_func_name),
8948 strtab_section->data + sym->st_name);
8949 goto found;
8954 /* did not find any info: */
8955 fprintf(stderr, " ???\n");
8956 return;
8957 found:
8958 if (last_func_name[0] != '\0') {
8959 fprintf(stderr, " %s()", last_func_name);
8961 if (incl_index > 0) {
8962 fprintf(stderr, " (%s:%d",
8963 incl_files[incl_index - 1], last_line_num);
8964 for(i = incl_index - 2; i >= 0; i--)
8965 fprintf(stderr, ", included from %s", incl_files[i]);
8966 fprintf(stderr, ")");
8968 fprintf(stderr, "\n");
8971 #ifndef WIN32
8973 #ifdef __i386__
8975 /* fix for glibc 2.1 */
8976 #ifndef REG_EIP
8977 #define REG_EIP EIP
8978 #define REG_EBP EBP
8979 #endif
8981 /* return the PC at frame level 'level'. Return non zero if not found */
8982 static int rt_get_caller_pc(unsigned long *paddr,
8983 ucontext_t *uc, int level)
8985 unsigned long fp;
8986 int i;
8988 if (level == 0) {
8989 #ifdef __FreeBSD__
8990 *paddr = uc->uc_mcontext.mc_eip;
8991 #else
8992 *paddr = uc->uc_mcontext.gregs[REG_EIP];
8993 #endif
8994 return 0;
8995 } else {
8996 #ifdef __FreeBSD__
8997 fp = uc->uc_mcontext.mc_ebp;
8998 #else
8999 fp = uc->uc_mcontext.gregs[REG_EBP];
9000 #endif
9001 for(i=1;i<level;i++) {
9002 /* XXX: check address validity with program info */
9003 if (fp <= 0x1000 || fp >= 0xc0000000)
9004 return -1;
9005 fp = ((unsigned long *)fp)[0];
9007 *paddr = ((unsigned long *)fp)[1];
9008 return 0;
9011 #else
9012 #error add arch specific rt_get_caller_pc()
9013 #endif
9015 /* emit a run time error at position 'pc' */
9016 void rt_error(ucontext_t *uc, const char *fmt, ...)
9018 va_list ap;
9019 unsigned long pc;
9020 int i;
9022 va_start(ap, fmt);
9023 fprintf(stderr, "Runtime error: ");
9024 vfprintf(stderr, fmt, ap);
9025 fprintf(stderr, "\n");
9026 for(i=0;i<num_callers;i++) {
9027 if (rt_get_caller_pc(&pc, uc, i) < 0)
9028 break;
9029 if (i == 0)
9030 fprintf(stderr, "at ");
9031 else
9032 fprintf(stderr, "by ");
9033 rt_printline(pc);
9035 exit(255);
9036 va_end(ap);
9039 /* signal handler for fatal errors */
9040 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9042 ucontext_t *uc = puc;
9044 switch(signum) {
9045 case SIGFPE:
9046 switch(siginf->si_code) {
9047 case FPE_INTDIV:
9048 case FPE_FLTDIV:
9049 rt_error(uc, "division by zero");
9050 break;
9051 default:
9052 rt_error(uc, "floating point exception");
9053 break;
9055 break;
9056 case SIGBUS:
9057 case SIGSEGV:
9058 if (rt_bound_error_msg && *rt_bound_error_msg)
9059 rt_error(uc, *rt_bound_error_msg);
9060 else
9061 rt_error(uc, "dereferencing invalid pointer");
9062 break;
9063 case SIGILL:
9064 rt_error(uc, "illegal instruction");
9065 break;
9066 case SIGABRT:
9067 rt_error(uc, "abort() called");
9068 break;
9069 default:
9070 rt_error(uc, "caught signal %d", signum);
9071 break;
9073 exit(255);
9075 #endif
9077 /* do all relocations (needed before using tcc_get_symbol()) */
9078 int tcc_relocate(TCCState *s1)
9080 Section *s;
9081 int i;
9083 s1->nb_errors = 0;
9085 tcc_add_runtime(s1);
9087 relocate_common_syms();
9089 /* compute relocation address : section are relocated in place. We
9090 also alloc the bss space */
9091 for(i = 1; i < s1->nb_sections; i++) {
9092 s = s1->sections[i];
9093 if (s->sh_flags & SHF_ALLOC) {
9094 if (s->sh_type == SHT_NOBITS)
9095 s->data = tcc_mallocz(s->data_offset);
9096 s->sh_addr = (unsigned long)s->data;
9100 relocate_syms(s1, 1);
9102 if (s1->nb_errors != 0)
9103 return -1;
9105 /* relocate each section */
9106 for(i = 1; i < s1->nb_sections; i++) {
9107 s = s1->sections[i];
9108 if (s->reloc)
9109 relocate_section(s1, s);
9111 return 0;
9114 /* launch the compiled program with the given arguments */
9115 int tcc_run(TCCState *s1, int argc, char **argv)
9117 int (*prog_main)(int, char **);
9119 if (tcc_relocate(s1) < 0)
9120 return -1;
9122 prog_main = tcc_get_symbol_err(s1, "main");
9124 if (do_debug) {
9125 #ifdef WIN32
9126 error("debug mode currently not available for Windows");
9127 #else
9128 struct sigaction sigact;
9129 /* install TCC signal handlers to print debug info on fatal
9130 runtime errors */
9131 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9132 sigact.sa_sigaction = sig_error;
9133 sigemptyset(&sigact.sa_mask);
9134 sigaction(SIGFPE, &sigact, NULL);
9135 sigaction(SIGILL, &sigact, NULL);
9136 sigaction(SIGSEGV, &sigact, NULL);
9137 sigaction(SIGBUS, &sigact, NULL);
9138 sigaction(SIGABRT, &sigact, NULL);
9139 #endif
9142 #ifdef CONFIG_TCC_BCHECK
9143 if (do_bounds_check) {
9144 void (*bound_init)(void);
9146 /* set error function */
9147 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9148 "__bound_error_msg");
9150 /* XXX: use .init section so that it also work in binary ? */
9151 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9152 bound_init();
9154 #endif
9155 return (*prog_main)(argc, argv);
9158 TCCState *tcc_new(void)
9160 const char *p, *r;
9161 TCCState *s;
9162 TokenSym *ts;
9163 int i, c;
9165 s = tcc_mallocz(sizeof(TCCState));
9166 if (!s)
9167 return NULL;
9168 tcc_state = s;
9169 s->output_type = TCC_OUTPUT_MEMORY;
9171 /* init isid table */
9172 for(i=0;i<256;i++)
9173 isidnum_table[i] = isid(i) || isnum(i);
9175 /* add all tokens */
9176 table_ident = NULL;
9177 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9179 tok_ident = TOK_IDENT;
9180 p = tcc_keywords;
9181 while (*p) {
9182 r = p;
9183 for(;;) {
9184 c = *r++;
9185 if (c == '\0')
9186 break;
9188 ts = tok_alloc(p, r - p - 1);
9189 p = r;
9192 /* we add dummy defines for some special macros to speed up tests
9193 and to have working defined() */
9194 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9195 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9196 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9197 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9199 /* standard defines */
9200 tcc_define_symbol(s, "__STDC__", NULL);
9201 #if defined(TCC_TARGET_I386)
9202 tcc_define_symbol(s, "__i386__", NULL);
9203 #endif
9204 #if defined(linux)
9205 tcc_define_symbol(s, "__linux__", NULL);
9206 tcc_define_symbol(s, "linux", NULL);
9207 #endif
9208 /* tiny C specific defines */
9209 tcc_define_symbol(s, "__TINYC__", NULL);
9211 /* tiny C & gcc defines */
9212 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9213 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9214 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9216 /* default library paths */
9217 tcc_add_library_path(s, "/usr/local/lib");
9218 tcc_add_library_path(s, "/usr/lib");
9219 tcc_add_library_path(s, "/lib");
9221 /* no section zero */
9222 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9224 /* create standard sections */
9225 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9226 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9227 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9229 /* symbols are always generated for linking stage */
9230 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9231 ".strtab",
9232 ".hashtab", SHF_PRIVATE);
9233 strtab_section = symtab_section->link;
9235 /* private symbol table for dynamic symbols */
9236 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9237 ".dynstrtab",
9238 ".dynhashtab", SHF_PRIVATE);
9239 s->alacarte_link = 1;
9240 return s;
9243 void tcc_delete(TCCState *s1)
9245 int i, n;
9247 /* free -D defines */
9248 free_defines(NULL);
9250 /* free tokens */
9251 n = tok_ident - TOK_IDENT;
9252 for(i = 0; i < n; i++)
9253 tcc_free(table_ident[i]);
9254 tcc_free(table_ident);
9256 /* free all sections */
9258 free_section(symtab_section->hash);
9260 free_section(s1->dynsymtab_section->hash);
9261 free_section(s1->dynsymtab_section->link);
9262 free_section(s1->dynsymtab_section);
9264 for(i = 1; i < s1->nb_sections; i++)
9265 free_section(s1->sections[i]);
9266 tcc_free(s1->sections);
9268 /* free loaded dlls array */
9269 for(i = 0; i < s1->nb_loaded_dlls; i++)
9270 tcc_free(s1->loaded_dlls[i]);
9271 tcc_free(s1->loaded_dlls);
9273 /* library paths */
9274 for(i = 0; i < s1->nb_library_paths; i++)
9275 tcc_free(s1->library_paths[i]);
9276 tcc_free(s1->library_paths);
9278 /* cached includes */
9279 for(i = 0; i < s1->nb_cached_includes; i++)
9280 tcc_free(s1->cached_includes[i]);
9281 tcc_free(s1->cached_includes);
9283 for(i = 0; i < s1->nb_include_paths; i++)
9284 tcc_free(s1->include_paths[i]);
9285 tcc_free(s1->include_paths);
9287 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9288 tcc_free(s1->sysinclude_paths[i]);
9289 tcc_free(s1->sysinclude_paths);
9291 tcc_free(s1);
9294 int tcc_add_include_path(TCCState *s1, const char *pathname)
9296 char *pathname1;
9298 pathname1 = tcc_strdup(pathname);
9299 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9300 return 0;
9303 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9305 char *pathname1;
9307 pathname1 = tcc_strdup(pathname);
9308 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9309 return 0;
9312 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9314 const char *ext, *filename1;
9315 Elf32_Ehdr ehdr;
9316 int fd, ret;
9317 BufferedFile *saved_file;
9319 /* find source file type with extension */
9320 filename1 = strrchr(filename, '/');
9321 if (filename1)
9322 filename1++;
9323 else
9324 filename1 = filename;
9325 ext = strrchr(filename1, '.');
9326 if (ext)
9327 ext++;
9329 /* open the file */
9330 saved_file = file;
9331 file = tcc_open(s1, filename);
9332 if (!file) {
9333 if (flags & AFF_PRINT_ERROR) {
9334 error_noabort("file '%s' not found", filename);
9336 ret = -1;
9337 goto fail1;
9340 if (!ext || !strcmp(ext, "c")) {
9341 /* C file assumed */
9342 ret = tcc_compile(s1);
9343 } else
9344 #ifdef CONFIG_TCC_ASM
9345 if (!strcmp(ext, "S")) {
9346 /* preprocessed assembler */
9347 ret = tcc_assemble(s1, 1);
9348 } else if (!strcmp(ext, "s")) {
9349 /* non preprocessed assembler */
9350 ret = tcc_assemble(s1, 0);
9351 } else
9352 #endif
9354 fd = file->fd;
9355 /* assume executable format: auto guess file type */
9356 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
9357 error_noabort("could not read header");
9358 goto fail;
9360 lseek(fd, 0, SEEK_SET);
9362 if (ehdr.e_ident[0] == ELFMAG0 &&
9363 ehdr.e_ident[1] == ELFMAG1 &&
9364 ehdr.e_ident[2] == ELFMAG2 &&
9365 ehdr.e_ident[3] == ELFMAG3) {
9366 file->line_num = 0; /* do not display line number if error */
9367 if (ehdr.e_type == ET_REL) {
9368 ret = tcc_load_object_file(s1, fd, 0);
9369 } else if (ehdr.e_type == ET_DYN) {
9370 ret = tcc_load_dll(s1, fd, filename,
9371 (flags & AFF_REFERENCED_DLL) != 0);
9372 } else {
9373 error_noabort("unrecognized ELF file");
9374 goto fail;
9376 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9377 file->line_num = 0; /* do not display line number if error */
9378 ret = tcc_load_archive(s1, fd);
9379 } else {
9380 /* as GNU ld, consider it is an ld script if not recognized */
9381 ret = tcc_load_ldscript(s1);
9382 if (ret < 0) {
9383 error_noabort("unrecognized file type");
9384 goto fail;
9388 the_end:
9389 tcc_close(file);
9390 fail1:
9391 file = saved_file;
9392 return ret;
9393 fail:
9394 ret = -1;
9395 goto the_end;
9398 int tcc_add_file(TCCState *s, const char *filename)
9400 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9403 int tcc_add_library_path(TCCState *s, const char *pathname)
9405 char *pathname1;
9407 pathname1 = tcc_strdup(pathname);
9408 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9409 return 0;
9412 /* find and load a dll. Return non zero if not found */
9413 /* XXX: add '-rpath' option support ? */
9414 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9416 char buf[1024];
9417 int i;
9419 for(i = 0; i < s->nb_library_paths; i++) {
9420 snprintf(buf, sizeof(buf), "%s/%s",
9421 s->library_paths[i], filename);
9422 if (tcc_add_file_internal(s, buf, flags) == 0)
9423 return 0;
9425 return -1;
9428 /* the library name is the same as the argument of the '-l' option */
9429 int tcc_add_library(TCCState *s, const char *libraryname)
9431 char buf[1024];
9432 int i;
9433 void *h;
9435 /* first we look for the dynamic library if not static linking */
9436 if (!s->static_link) {
9437 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9438 /* if we output to memory, then we simply we dlopen(). */
9439 if (s->output_type == TCC_OUTPUT_MEMORY) {
9440 /* Since the libc is already loaded, we don't need to load it again */
9441 if (!strcmp(libraryname, "c"))
9442 return 0;
9443 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
9444 if (h)
9445 return 0;
9446 } else {
9447 if (tcc_add_dll(s, buf, 0) == 0)
9448 return 0;
9452 /* then we look for the static library */
9453 for(i = 0; i < s->nb_library_paths; i++) {
9454 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9455 s->library_paths[i], libraryname);
9456 if (tcc_add_file_internal(s, buf, 0) == 0)
9457 return 0;
9459 return -1;
9462 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9464 add_elf_sym(symtab_section, val, 0,
9465 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9466 SHN_ABS, name);
9467 return 0;
9470 int tcc_set_output_type(TCCState *s, int output_type)
9472 char buf[1024];
9474 s->output_type = output_type;
9476 if (!s->nostdinc) {
9477 /* default include paths */
9478 /* XXX: reverse order needed if -isystem support */
9479 tcc_add_sysinclude_path(s, "/usr/local/include");
9480 tcc_add_sysinclude_path(s, "/usr/include");
9481 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9482 tcc_add_sysinclude_path(s, buf);
9485 /* if bound checking, then add corresponding sections */
9486 #ifdef CONFIG_TCC_BCHECK
9487 if (do_bounds_check) {
9488 /* define symbol */
9489 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9490 /* create bounds sections */
9491 bounds_section = new_section(s, ".bounds",
9492 SHT_PROGBITS, SHF_ALLOC);
9493 lbounds_section = new_section(s, ".lbounds",
9494 SHT_PROGBITS, SHF_ALLOC);
9496 #endif
9498 /* add debug sections */
9499 if (do_debug) {
9500 /* stab symbols */
9501 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9502 stab_section->sh_entsize = sizeof(Stab_Sym);
9503 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9504 put_elf_str(stabstr_section, "");
9505 stab_section->link = stabstr_section;
9506 /* put first entry */
9507 put_stabs("", 0, 0, 0, 0);
9510 /* add libc crt1/crti objects */
9511 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9512 !s->nostdlib) {
9513 if (output_type != TCC_OUTPUT_DLL)
9514 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9515 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9517 return 0;
9520 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9522 typedef struct WarningDef {
9523 int offset;
9524 int flags;
9525 const char *name;
9526 } WarningDef;
9528 static const WarningDef warning_defs[] = {
9529 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9530 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9531 { offsetof(TCCState, warn_error), 0, "error" },
9534 /* set/reset a warning */
9535 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9537 int i;
9538 const WarningDef *p;
9539 if (!strcmp(warning_name, "all")) {
9540 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9541 if (p->flags & WD_ALL)
9542 *(int *)((uint8_t *)s + p->offset) = 1;
9544 } else {
9545 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9546 if (!strcmp(warning_name, p->name))
9547 goto found;
9549 return -1;
9550 found:
9551 *(int *)((uint8_t *)s + p->offset) = value;
9553 return 0;
9556 #if !defined(LIBTCC)
9558 /* extract the basename of a file */
9559 static const char *tcc_basename(const char *name)
9561 const char *p;
9562 p = strrchr(name, '/');
9563 #ifdef WIN32
9564 if (!p)
9565 p = strrchr(name, '\\');
9566 #endif
9567 if (!p)
9568 p = name;
9569 else
9570 p++;
9571 return p;
9574 static int64_t getclock_us(void)
9576 #ifdef WIN32
9577 struct _timeb tb;
9578 _ftime(&tb);
9579 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9580 #else
9581 struct timeval tv;
9582 gettimeofday(&tv, NULL);
9583 return tv.tv_sec * 1000000LL + tv.tv_usec;
9584 #endif
9587 void help(void)
9589 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2003 Fabrice Bellard\n"
9590 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9591 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9592 " [infile1 infile2...] [-run infile args...]\n"
9593 "\n"
9594 "General options:\n"
9595 " -v display current version\n"
9596 " -c compile only - generate an object file\n"
9597 " -o outfile set output filename\n"
9598 " -Bdir set tcc internal library path\n"
9599 " -bench output compilation statistics\n"
9600 " -run run compiled source\n"
9601 " -Wwarning set or reset (with 'no-' prefix) 'warning'\n"
9602 " -w disable all warnings\n"
9603 "Preprocessor options:\n"
9604 " -Idir add include path 'dir'\n"
9605 " -Dsym[=val] define 'sym' with value 'val'\n"
9606 " -Usym undefine 'sym'\n"
9607 "Linker options:\n"
9608 " -Ldir add library path 'dir'\n"
9609 " -llib link with dynamic or static library 'lib'\n"
9610 " -shared generate a shared library\n"
9611 " -static static linking\n"
9612 " -rdynamic export all global symbols to dynamic linker\n"
9613 " -r relocatable output\n"
9614 "Debugger options:\n"
9615 " -g generate runtime debug info\n"
9616 #ifdef CONFIG_TCC_BCHECK
9617 " -b compile with built-in memory and bounds checker (implies -g)\n"
9618 #endif
9619 " -bt N show N callers in stack traces\n"
9623 #define TCC_OPTION_HAS_ARG 0x0001
9624 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9626 typedef struct TCCOption {
9627 const char *name;
9628 uint16_t index;
9629 uint16_t flags;
9630 } TCCOption;
9632 enum {
9633 TCC_OPTION_HELP,
9634 TCC_OPTION_I,
9635 TCC_OPTION_D,
9636 TCC_OPTION_U,
9637 TCC_OPTION_L,
9638 TCC_OPTION_B,
9639 TCC_OPTION_l,
9640 TCC_OPTION_bench,
9641 TCC_OPTION_bt,
9642 TCC_OPTION_b,
9643 TCC_OPTION_g,
9644 TCC_OPTION_c,
9645 TCC_OPTION_static,
9646 TCC_OPTION_shared,
9647 TCC_OPTION_o,
9648 TCC_OPTION_r,
9649 TCC_OPTION_W,
9650 TCC_OPTION_O,
9651 TCC_OPTION_m,
9652 TCC_OPTION_f,
9653 TCC_OPTION_nostdinc,
9654 TCC_OPTION_nostdlib,
9655 TCC_OPTION_print_search_dirs,
9656 TCC_OPTION_rdynamic,
9657 TCC_OPTION_run,
9658 TCC_OPTION_v,
9659 TCC_OPTION_w,
9662 static const TCCOption tcc_options[] = {
9663 { "h", TCC_OPTION_HELP, 0 },
9664 { "?", TCC_OPTION_HELP, 0 },
9665 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9666 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9667 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9668 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9669 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9670 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9671 { "bench", TCC_OPTION_bench, 0 },
9672 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9673 #ifdef CONFIG_TCC_BCHECK
9674 { "b", TCC_OPTION_b, 0 },
9675 #endif
9676 { "g", TCC_OPTION_g, 0 },
9677 { "c", TCC_OPTION_c, 0 },
9678 { "static", TCC_OPTION_static, 0 },
9679 { "shared", TCC_OPTION_shared, 0 },
9680 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9681 { "run", TCC_OPTION_run, 0 },
9682 { "rdynamic", TCC_OPTION_rdynamic, 0 },
9683 { "r", TCC_OPTION_r, 0 },
9684 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9685 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9686 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9687 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9688 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9689 { "nostdlib", TCC_OPTION_nostdlib, 0 },
9690 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9691 { "v", TCC_OPTION_v, 0 },
9692 { "w", TCC_OPTION_w, 0 },
9693 { NULL },
9696 int main(int argc, char **argv)
9698 char *r;
9699 int optind, output_type, multiple_files, i, reloc_output;
9700 TCCState *s;
9701 char **files;
9702 int nb_files, nb_libraries, nb_objfiles, dminus, ret;
9703 char objfilename[1024];
9704 int64_t start_time = 0;
9705 const TCCOption *popt;
9706 const char *optarg, *p1, *r1, *outfile;
9707 int print_search_dirs;
9709 s = tcc_new();
9710 output_type = TCC_OUTPUT_EXE;
9712 optind = 1;
9713 outfile = NULL;
9714 multiple_files = 1;
9715 dminus = 0;
9716 files = NULL;
9717 nb_files = 0;
9718 nb_libraries = 0;
9719 reloc_output = 0;
9720 print_search_dirs = 0;
9721 while (1) {
9722 if (optind >= argc) {
9723 if (nb_files == 0 && !print_search_dirs)
9724 goto show_help;
9725 else
9726 break;
9728 r = argv[optind++];
9729 if (r[0] != '-') {
9730 /* add a new file */
9731 dynarray_add((void ***)&files, &nb_files, r);
9732 if (!multiple_files) {
9733 optind--;
9734 /* argv[0] will be this file */
9735 break;
9737 } else {
9738 /* find option in table (match only the first chars */
9739 popt = tcc_options;
9740 for(;;) {
9741 p1 = popt->name;
9742 if (p1 == NULL)
9743 error("invalid option -- '%s'", r);
9744 r1 = r + 1;
9745 for(;;) {
9746 if (*p1 == '\0')
9747 goto option_found;
9748 if (*r1 != *p1)
9749 break;
9750 p1++;
9751 r1++;
9753 popt++;
9755 option_found:
9756 if (popt->flags & TCC_OPTION_HAS_ARG) {
9757 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
9758 optarg = r1;
9759 } else {
9760 if (optind >= argc)
9761 error("argument to '%s' is missing", r);
9762 optarg = argv[optind++];
9764 } else {
9765 if (*r1 != '\0')
9766 goto show_help;
9767 optarg = NULL;
9770 switch(popt->index) {
9771 case TCC_OPTION_HELP:
9772 show_help:
9773 help();
9774 return 1;
9775 case TCC_OPTION_I:
9776 if (tcc_add_include_path(s, optarg) < 0)
9777 error("too many include paths");
9778 break;
9779 case TCC_OPTION_D:
9781 char *sym, *value;
9782 sym = (char *)optarg;
9783 value = strchr(sym, '=');
9784 if (value) {
9785 *value = '\0';
9786 value++;
9788 tcc_define_symbol(s, sym, value);
9790 break;
9791 case TCC_OPTION_U:
9792 tcc_undefine_symbol(s, optarg);
9793 break;
9794 case TCC_OPTION_L:
9795 tcc_add_library_path(s, optarg);
9796 break;
9797 case TCC_OPTION_B:
9798 /* set tcc utilities path (mainly for tcc development) */
9799 tcc_lib_path = optarg;
9800 break;
9801 case TCC_OPTION_l:
9802 dynarray_add((void ***)&files, &nb_files, r);
9803 nb_libraries++;
9804 break;
9805 case TCC_OPTION_bench:
9806 do_bench = 1;
9807 break;
9808 case TCC_OPTION_bt:
9809 num_callers = atoi(optarg);
9810 break;
9811 #ifdef CONFIG_TCC_BCHECK
9812 case TCC_OPTION_b:
9813 do_bounds_check = 1;
9814 do_debug = 1;
9815 break;
9816 #endif
9817 case TCC_OPTION_g:
9818 do_debug = 1;
9819 break;
9820 case TCC_OPTION_c:
9821 multiple_files = 1;
9822 output_type = TCC_OUTPUT_OBJ;
9823 break;
9824 case TCC_OPTION_static:
9825 s->static_link = 1;
9826 break;
9827 case TCC_OPTION_shared:
9828 output_type = TCC_OUTPUT_DLL;
9829 break;
9830 case TCC_OPTION_o:
9831 multiple_files = 1;
9832 outfile = optarg;
9833 break;
9834 case TCC_OPTION_r:
9835 /* generate a .o merging several output files */
9836 reloc_output = 1;
9837 output_type = TCC_OUTPUT_OBJ;
9838 break;
9839 case TCC_OPTION_nostdinc:
9840 s->nostdinc = 1;
9841 break;
9842 case TCC_OPTION_nostdlib:
9843 s->nostdlib = 1;
9844 break;
9845 case TCC_OPTION_print_search_dirs:
9846 print_search_dirs = 1;
9847 break;
9848 case TCC_OPTION_run:
9849 multiple_files = 0;
9850 output_type = TCC_OUTPUT_MEMORY;
9851 break;
9852 case TCC_OPTION_v:
9853 printf("tcc version %s\n", TCC_VERSION);
9854 return 0;
9855 case TCC_OPTION_W:
9857 const char *p = optarg;
9858 int value;
9859 value = 1;
9860 if (p[0] == 'n' && p[1] == 'o' && p[2] == '-') {
9861 p += 2;
9862 value = 0;
9864 if (tcc_set_warning(s, p, value) < 0 && s->warn_unsupported)
9865 goto unsupported_option;
9867 break;
9868 case TCC_OPTION_w:
9869 s->warn_none = 1;
9870 break;
9871 case TCC_OPTION_rdynamic:
9872 s->rdynamic = 1;
9873 break;
9874 default:
9875 if (s->warn_unsupported) {
9876 unsupported_option:
9877 warning("unsupported option '%s'", r);
9879 break;
9883 if (print_search_dirs) {
9884 /* enough for Linux kernel */
9885 printf("install: %s/\n", tcc_lib_path);
9886 return 0;
9889 nb_objfiles = nb_files - nb_libraries;
9891 /* if outfile provided without other options, we output an
9892 executable */
9893 if (outfile && output_type == TCC_OUTPUT_MEMORY)
9894 output_type = TCC_OUTPUT_EXE;
9896 /* check -c consistency : only single file handled. XXX: checks file type */
9897 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9898 /* accepts only a single input file */
9899 if (nb_objfiles != 1)
9900 error("cannot specify multiple files with -c");
9901 if (nb_libraries != 0)
9902 error("cannot specify libraries with -c");
9905 /* compute default outfile name */
9906 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
9907 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9908 char *ext;
9909 /* strip path */
9910 pstrcpy(objfilename, sizeof(objfilename) - 1,
9911 tcc_basename(files[0]));
9912 /* add .o extension */
9913 ext = strrchr(objfilename, '.');
9914 if (!ext)
9915 goto default_outfile;
9916 strcpy(ext + 1, "o");
9917 } else {
9918 default_outfile:
9919 pstrcpy(objfilename, sizeof(objfilename), "a.out");
9921 outfile = objfilename;
9924 if (do_bench) {
9925 start_time = getclock_us();
9928 tcc_set_output_type(s, output_type);
9930 /* compile or add each files or library */
9931 for(i = 0;i < nb_files; i++) {
9932 const char *filename;
9934 filename = files[i];
9935 if (filename[0] == '-') {
9936 if (tcc_add_library(s, filename + 2) < 0)
9937 error("cannot find %s", filename);
9938 } else {
9939 if (tcc_add_file(s, filename) < 0) {
9940 ret = 1;
9941 goto the_end;
9946 /* free all files */
9947 tcc_free(files);
9949 if (do_bench) {
9950 double total_time;
9951 total_time = (double)(getclock_us() - start_time) / 1000000.0;
9952 if (total_time < 0.001)
9953 total_time = 0.001;
9954 if (total_bytes < 1)
9955 total_bytes = 1;
9956 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
9957 tok_ident - TOK_IDENT, total_lines, total_bytes,
9958 total_time, (int)(total_lines / total_time),
9959 total_bytes / total_time / 1000000.0);
9962 if (s->output_type != TCC_OUTPUT_MEMORY) {
9963 tcc_output_file(s, outfile);
9964 ret = 0;
9965 } else {
9966 ret = tcc_run(s, argc - optind, argv + optind);
9968 the_end:
9969 /* XXX: cannot do it with bound checking because of the malloc hooks */
9970 if (!do_bounds_check)
9971 tcc_delete(s);
9973 #ifdef MEM_DEBUG
9974 if (do_bench) {
9975 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
9977 #endif
9978 return ret;
9981 #endif