changed tcc_get_symbol() prototype
[tinycc.git] / tcc.c
blob68bf046163eda23ebaca5ad9e02ed077f2c49728
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[64]; /* 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;
412 /* error handling */
413 void *error_opaque;
414 void (*error_func)(void *opaque, const char *msg);
415 int error_set_jmp_enabled;
416 jmp_buf error_jmp_buf;
417 int nb_errors;
419 /* tiny assembler state */
420 Sym *asm_labels;
422 /* see include_stack_ptr */
423 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
425 /* see ifdef_stack_ptr */
426 int ifdef_stack[IFDEF_STACK_SIZE];
429 /* The current value can be: */
430 #define VT_VALMASK 0x00ff
431 #define VT_CONST 0x00f0 /* constant in vc
432 (must be first non register value) */
433 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
434 #define VT_LOCAL 0x00f2 /* offset on stack */
435 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
436 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
437 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
438 #define VT_LVAL 0x0100 /* var is an lvalue */
439 #define VT_SYM 0x0200 /* a symbol value is added */
440 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
441 char/short stored in integer registers) */
442 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
443 dereferencing value */
444 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
445 bounding function call point is in vc */
446 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
447 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
448 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
449 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
451 /* types */
452 #define VT_INT 0 /* integer type */
453 #define VT_BYTE 1 /* signed byte type */
454 #define VT_SHORT 2 /* short type */
455 #define VT_VOID 3 /* void type */
456 #define VT_PTR 4 /* pointer */
457 #define VT_ENUM 5 /* enum definition */
458 #define VT_FUNC 6 /* function type */
459 #define VT_STRUCT 7 /* struct/union definition */
460 #define VT_FLOAT 8 /* IEEE float */
461 #define VT_DOUBLE 9 /* IEEE double */
462 #define VT_LDOUBLE 10 /* IEEE long double */
463 #define VT_BOOL 11 /* ISOC99 boolean type */
464 #define VT_LLONG 12 /* 64 bit integer */
465 #define VT_LONG 13 /* long integer (NEVER USED as type, only
466 during parsing) */
467 #define VT_BTYPE 0x000f /* mask for basic type */
468 #define VT_UNSIGNED 0x0010 /* unsigned type */
469 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
470 #define VT_BITFIELD 0x0040 /* bitfield modifier */
471 #define VT_CONSTANT 0x0800 /* const modifier */
472 #define VT_VOLATILE 0x1000 /* volatile modifier */
474 /* storage */
475 #define VT_EXTERN 0x00000080 /* extern definition */
476 #define VT_STATIC 0x00000100 /* static variable */
477 #define VT_TYPEDEF 0x00000200 /* typedef definition */
478 #define VT_INLINE 0x00000400 /* inline definition */
480 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
482 /* type mask (except storage) */
483 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
484 #define VT_TYPE (~(VT_STORAGE))
486 /* token values */
488 /* warning: the following compare tokens depend on i386 asm code */
489 #define TOK_ULT 0x92
490 #define TOK_UGE 0x93
491 #define TOK_EQ 0x94
492 #define TOK_NE 0x95
493 #define TOK_ULE 0x96
494 #define TOK_UGT 0x97
495 #define TOK_LT 0x9c
496 #define TOK_GE 0x9d
497 #define TOK_LE 0x9e
498 #define TOK_GT 0x9f
500 #define TOK_LAND 0xa0
501 #define TOK_LOR 0xa1
503 #define TOK_DEC 0xa2
504 #define TOK_MID 0xa3 /* inc/dec, to void constant */
505 #define TOK_INC 0xa4
506 #define TOK_UDIV 0xb0 /* unsigned division */
507 #define TOK_UMOD 0xb1 /* unsigned modulo */
508 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
509 #define TOK_CINT 0xb3 /* number in tokc */
510 #define TOK_CCHAR 0xb4 /* char constant in tokc */
511 #define TOK_STR 0xb5 /* pointer to string in tokc */
512 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
513 #define TOK_LCHAR 0xb7
514 #define TOK_LSTR 0xb8
515 #define TOK_CFLOAT 0xb9 /* float constant */
516 #define TOK_LINENUM 0xba /* line number info */
517 #define TOK_CDOUBLE 0xc0 /* double constant */
518 #define TOK_CLDOUBLE 0xc1 /* long double constant */
519 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
520 #define TOK_ADDC1 0xc3 /* add with carry generation */
521 #define TOK_ADDC2 0xc4 /* add with carry use */
522 #define TOK_SUBC1 0xc5 /* add with carry generation */
523 #define TOK_SUBC2 0xc6 /* add with carry use */
524 #define TOK_CUINT 0xc8 /* unsigned int constant */
525 #define TOK_CLLONG 0xc9 /* long long constant */
526 #define TOK_CULLONG 0xca /* unsigned long long constant */
527 #define TOK_ARROW 0xcb
528 #define TOK_DOTS 0xcc /* three dots */
529 #define TOK_SHR 0xcd /* unsigned shift right */
530 #define TOK_PPNUM 0xce /* preprocessor number */
532 #define TOK_SHL 0x01 /* shift left */
533 #define TOK_SAR 0x02 /* signed shift right */
535 /* assignement operators : normal operator or 0x80 */
536 #define TOK_A_MOD 0xa5
537 #define TOK_A_AND 0xa6
538 #define TOK_A_MUL 0xaa
539 #define TOK_A_ADD 0xab
540 #define TOK_A_SUB 0xad
541 #define TOK_A_DIV 0xaf
542 #define TOK_A_XOR 0xde
543 #define TOK_A_OR 0xfc
544 #define TOK_A_SHL 0x81
545 #define TOK_A_SAR 0x82
547 #ifndef offsetof
548 #define offsetof(type, field) ((size_t) &((type *)0)->field)
549 #endif
551 #ifndef countof
552 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
553 #endif
555 /* WARNING: the content of this string encodes token numbers */
556 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";
558 #define TOK_EOF (-1) /* end of file */
559 #define TOK_LINEFEED 10 /* line feed */
561 /* all identificators and strings have token above that */
562 #define TOK_IDENT 256
564 /* only used for i386 asm opcodes definitions */
565 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
567 #define DEF_BWL(x) \
568 DEF(TOK_ASM_ ## x ## b, #x "b") \
569 DEF(TOK_ASM_ ## x ## w, #x "w") \
570 DEF(TOK_ASM_ ## x ## l, #x "l") \
571 DEF(TOK_ASM_ ## x, #x)
573 #define DEF_WL(x) \
574 DEF(TOK_ASM_ ## x ## w, #x "w") \
575 DEF(TOK_ASM_ ## x ## l, #x "l") \
576 DEF(TOK_ASM_ ## x, #x)
578 #define DEF_FP1(x) \
579 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
580 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
581 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
582 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
584 #define DEF_FP(x) \
585 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
586 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
587 DEF_FP1(x)
589 #define DEF_ASMTEST(x) \
590 DEF_ASM(x ## o) \
591 DEF_ASM(x ## no) \
592 DEF_ASM(x ## b) \
593 DEF_ASM(x ## c) \
594 DEF_ASM(x ## nae) \
595 DEF_ASM(x ## nb) \
596 DEF_ASM(x ## nc) \
597 DEF_ASM(x ## ae) \
598 DEF_ASM(x ## e) \
599 DEF_ASM(x ## z) \
600 DEF_ASM(x ## ne) \
601 DEF_ASM(x ## nz) \
602 DEF_ASM(x ## be) \
603 DEF_ASM(x ## na) \
604 DEF_ASM(x ## nbe) \
605 DEF_ASM(x ## a) \
606 DEF_ASM(x ## s) \
607 DEF_ASM(x ## ns) \
608 DEF_ASM(x ## p) \
609 DEF_ASM(x ## pe) \
610 DEF_ASM(x ## np) \
611 DEF_ASM(x ## po) \
612 DEF_ASM(x ## l) \
613 DEF_ASM(x ## nge) \
614 DEF_ASM(x ## nl) \
615 DEF_ASM(x ## ge) \
616 DEF_ASM(x ## le) \
617 DEF_ASM(x ## ng) \
618 DEF_ASM(x ## nle) \
619 DEF_ASM(x ## g)
621 #define TOK_ASM_int TOK_INT
623 enum {
624 TOK_LAST = TOK_IDENT - 1,
625 #define DEF(id, str) id,
626 #include "tcctok.h"
627 #undef DEF
630 static const char tcc_keywords[] =
631 #define DEF(id, str) str "\0"
632 #include "tcctok.h"
633 #undef DEF
636 #define TOK_UIDENT TOK_DEFINE
638 #ifdef WIN32
639 #define snprintf _snprintf
640 #define vsnprintf _vsnprintf
641 #endif
643 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
644 /* currently incorrect */
645 long double strtold(const char *nptr, char **endptr)
647 return (long double)strtod(nptr, endptr);
649 float strtof(const char *nptr, char **endptr)
651 return (float)strtod(nptr, endptr);
653 #else
654 /* XXX: need to define this to use them in non ISOC99 context */
655 extern float strtof (const char *__nptr, char **__endptr);
656 extern long double strtold (const char *__nptr, char **__endptr);
657 #endif
659 static char *pstrcpy(char *buf, int buf_size, const char *s);
660 static char *pstrcat(char *buf, int buf_size, const char *s);
662 static void next(void);
663 static void next_nomacro(void);
664 static void parse_expr_type(CType *type);
665 static void expr_type(CType *type);
666 static void unary_type(CType *type);
667 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
668 int case_reg, int is_expr);
669 static int expr_const(void);
670 static void expr_eq(void);
671 static void gexpr(void);
672 static void decl(int l);
673 static void decl_initializer(CType *type, Section *sec, unsigned long c,
674 int first, int size_only);
675 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
676 int has_init, int v, int scope);
677 int gv(int rc);
678 void gv2(int rc1, int rc2);
679 void move_reg(int r, int s);
680 void save_regs(int n);
681 void save_reg(int r);
682 void vpop(void);
683 void vswap(void);
684 void vdup(void);
685 int get_reg(int rc);
687 static void macro_subst(TokenString *tok_str, Sym **nested_list,
688 const int *macro_str, int can_read_stream);
689 int save_reg_forced(int r);
690 void gen_op(int op);
691 void force_charshort_cast(int t);
692 static void gen_cast(CType *type);
693 void vstore(void);
694 static Sym *sym_find(int v);
695 static Sym *sym_push(int v, CType *type, int r, int c);
697 /* type handling */
698 static int type_size(CType *type, int *a);
699 static inline CType *pointed_type(CType *type);
700 static int pointed_size(CType *type);
701 static int lvalue_type(int t);
702 static int parse_btype(CType *type, AttributeDef *ad);
703 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
704 static int is_compatible_types(CType *type1, CType *type2);
706 void error(const char *fmt, ...);
707 void vpushi(int v);
708 void vset(CType *type, int r, int v);
709 void type_to_str(char *buf, int buf_size,
710 CType *type, const char *varstr);
711 char *get_tok_str(int v, CValue *cv);
712 static Sym *get_sym_ref(CType *type, Section *sec,
713 unsigned long offset, unsigned long size);
714 static Sym *external_global_sym(int v, CType *type, int r);
716 /* section generation */
717 static void section_realloc(Section *sec, unsigned long new_size);
718 static void *section_ptr_add(Section *sec, unsigned long size);
719 static void put_extern_sym(Sym *sym, Section *section,
720 unsigned long value, unsigned long size);
721 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
722 static int put_elf_str(Section *s, const char *sym);
723 static int put_elf_sym(Section *s,
724 unsigned long value, unsigned long size,
725 int info, int other, int shndx, const char *name);
726 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
727 int info, int sh_num, const char *name);
728 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
729 int type, int symbol);
730 static void put_stabs(const char *str, int type, int other, int desc,
731 unsigned long value);
732 static void put_stabs_r(const char *str, int type, int other, int desc,
733 unsigned long value, Section *sec, int sym_index);
734 static void put_stabn(int type, int other, int desc, int value);
735 static void put_stabd(int type, int other, int desc);
736 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
738 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
739 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
740 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
742 /* tccasm.c */
744 #ifdef CONFIG_TCC_ASM
746 typedef struct ExprValue {
747 uint32_t v;
748 Sym *sym;
749 } ExprValue;
751 #define MAX_ASM_OPERANDS 30
753 typedef struct ASMOperand {
754 int id; /* GCC 3 optionnal identifier (0 if number only supported */
755 char *constraint;
756 char asm_str[16]; /* computed asm string for operand */
757 SValue *vt; /* C value of the expression */
758 int ref_index; /* if >= 0, gives reference to a output constraint */
759 int priority; /* priority, used to assign registers */
760 int reg; /* if >= 0, register number used for this operand */
761 int is_llong; /* true if double register value */
762 } ASMOperand;
764 static void asm_expr(TCCState *s1, ExprValue *pe);
765 static int asm_int_expr(TCCState *s1);
766 static int find_constraint(ASMOperand *operands, int nb_operands,
767 const char *name, const char **pp);
769 static int tcc_assemble(TCCState *s1, int do_preprocess);
771 #endif
773 static void asm_instr(void);
775 /* true if float/double/long double type */
776 static inline int is_float(int t)
778 int bt;
779 bt = t & VT_BTYPE;
780 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
783 #ifdef TCC_TARGET_I386
784 #include "i386-gen.c"
785 #endif
787 #ifdef CONFIG_TCC_STATIC
789 #define RTLD_LAZY 0x001
790 #define RTLD_NOW 0x002
791 #define RTLD_GLOBAL 0x100
792 #define RTLD_DEFAULT NULL
794 /* dummy function for profiling */
795 void *dlopen(const char *filename, int flag)
797 return NULL;
800 const char *dlerror(void)
802 return "error";
805 typedef struct TCCSyms {
806 char *str;
807 void *ptr;
808 } TCCSyms;
810 #define TCCSYM(a) { #a, &a, },
812 /* add the symbol you want here if no dynamic linking is done */
813 static TCCSyms tcc_syms[] = {
814 TCCSYM(printf)
815 TCCSYM(fprintf)
816 TCCSYM(fopen)
817 TCCSYM(fclose)
818 { NULL, NULL },
821 void *dlsym(void *handle, const char *symbol)
823 TCCSyms *p;
824 p = tcc_syms;
825 while (p->str != NULL) {
826 if (!strcmp(p->str, symbol))
827 return p->ptr;
828 p++;
830 return NULL;
833 #endif
835 /********************************************************/
837 /* we use our own 'finite' function to avoid potential problems with
838 non standard math libs */
839 /* XXX: endianness dependent */
840 int ieee_finite(double d)
842 int *p = (int *)&d;
843 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
846 /* copy a string and truncate it. */
847 static char *pstrcpy(char *buf, int buf_size, const char *s)
849 char *q, *q_end;
850 int c;
852 if (buf_size > 0) {
853 q = buf;
854 q_end = buf + buf_size - 1;
855 while (q < q_end) {
856 c = *s++;
857 if (c == '\0')
858 break;
859 *q++ = c;
861 *q = '\0';
863 return buf;
866 /* strcat and truncate. */
867 static char *pstrcat(char *buf, int buf_size, const char *s)
869 int len;
870 len = strlen(buf);
871 if (len < buf_size)
872 pstrcpy(buf + len, buf_size - len, s);
873 return buf;
876 /* memory management */
877 #ifdef MEM_DEBUG
878 int mem_cur_size;
879 int mem_max_size;
880 #endif
882 static inline void tcc_free(void *ptr)
884 #ifdef MEM_DEBUG
885 mem_cur_size -= malloc_usable_size(ptr);
886 #endif
887 free(ptr);
890 static void *tcc_malloc(unsigned long size)
892 void *ptr;
893 ptr = malloc(size);
894 if (!ptr && size)
895 error("memory full");
896 #ifdef MEM_DEBUG
897 mem_cur_size += malloc_usable_size(ptr);
898 if (mem_cur_size > mem_max_size)
899 mem_max_size = mem_cur_size;
900 #endif
901 return ptr;
904 static void *tcc_mallocz(unsigned long size)
906 void *ptr;
907 ptr = tcc_malloc(size);
908 memset(ptr, 0, size);
909 return ptr;
912 static inline void *tcc_realloc(void *ptr, unsigned long size)
914 void *ptr1;
915 #ifdef MEM_DEBUG
916 mem_cur_size -= malloc_usable_size(ptr);
917 #endif
918 ptr1 = realloc(ptr, size);
919 #ifdef MEM_DEBUG
920 /* NOTE: count not correct if alloc error, but not critical */
921 mem_cur_size += malloc_usable_size(ptr1);
922 if (mem_cur_size > mem_max_size)
923 mem_max_size = mem_cur_size;
924 #endif
925 return ptr1;
928 static char *tcc_strdup(const char *str)
930 char *ptr;
931 ptr = tcc_malloc(strlen(str) + 1);
932 strcpy(ptr, str);
933 return ptr;
936 #define free(p) use_tcc_free(p)
937 #define malloc(s) use_tcc_malloc(s)
938 #define realloc(p, s) use_tcc_realloc(p, s)
940 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
942 int nb, nb_alloc;
943 void **pp;
945 nb = *nb_ptr;
946 pp = *ptab;
947 /* every power of two we double array size */
948 if ((nb & (nb - 1)) == 0) {
949 if (!nb)
950 nb_alloc = 1;
951 else
952 nb_alloc = nb * 2;
953 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
954 if (!pp)
955 error("memory full");
956 *ptab = pp;
958 pp[nb++] = data;
959 *nb_ptr = nb;
962 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
964 Section *sec;
966 sec = tcc_mallocz(sizeof(Section));
967 pstrcpy(sec->name, sizeof(sec->name), name);
968 sec->sh_type = sh_type;
969 sec->sh_flags = sh_flags;
970 switch(sh_type) {
971 case SHT_HASH:
972 case SHT_REL:
973 case SHT_DYNSYM:
974 case SHT_SYMTAB:
975 case SHT_DYNAMIC:
976 sec->sh_addralign = 4;
977 break;
978 case SHT_STRTAB:
979 sec->sh_addralign = 1;
980 break;
981 default:
982 sec->sh_addralign = 32; /* default conservative alignment */
983 break;
986 /* only add section if not private */
987 if (!(sh_flags & SHF_PRIVATE)) {
988 sec->sh_num = s1->nb_sections;
989 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
991 return sec;
994 static void free_section(Section *s)
996 tcc_free(s->data);
997 tcc_free(s);
1000 /* realloc section and set its content to zero */
1001 static void section_realloc(Section *sec, unsigned long new_size)
1003 unsigned long size;
1004 unsigned char *data;
1006 size = sec->data_allocated;
1007 if (size == 0)
1008 size = 1;
1009 while (size < new_size)
1010 size = size * 2;
1011 data = tcc_realloc(sec->data, size);
1012 if (!data)
1013 error("memory full");
1014 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1015 sec->data = data;
1016 sec->data_allocated = size;
1019 /* reserve at least 'size' bytes in section 'sec' from
1020 sec->data_offset. */
1021 static void *section_ptr_add(Section *sec, unsigned long size)
1023 unsigned long offset, offset1;
1025 offset = sec->data_offset;
1026 offset1 = offset + size;
1027 if (offset1 > sec->data_allocated)
1028 section_realloc(sec, offset1);
1029 sec->data_offset = offset1;
1030 return sec->data + offset;
1033 /* return a reference to a section, and create it if it does not
1034 exists */
1035 Section *find_section(TCCState *s1, const char *name)
1037 Section *sec;
1038 int i;
1039 for(i = 1; i < s1->nb_sections; i++) {
1040 sec = s1->sections[i];
1041 if (!strcmp(name, sec->name))
1042 return sec;
1044 /* sections are created as PROGBITS */
1045 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1048 /* update sym->c so that it points to an external symbol in section
1049 'section' with value 'value' */
1050 static void put_extern_sym(Sym *sym, Section *section,
1051 unsigned long value, unsigned long size)
1053 int sym_type, sym_bind, sh_num, info;
1054 Elf32_Sym *esym;
1055 const char *name;
1057 if (section)
1058 sh_num = section->sh_num;
1059 else
1060 sh_num = SHN_UNDEF;
1061 if (!sym->c) {
1062 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1063 sym_type = STT_FUNC;
1064 else
1065 sym_type = STT_OBJECT;
1066 if (sym->type.t & VT_STATIC)
1067 sym_bind = STB_LOCAL;
1068 else
1069 sym_bind = STB_GLOBAL;
1071 name = get_tok_str(sym->v, NULL);
1072 #ifdef CONFIG_TCC_BCHECK
1073 if (do_bounds_check) {
1074 char buf[32];
1076 /* XXX: avoid doing that for statics ? */
1077 /* if bound checking is activated, we change some function
1078 names by adding the "__bound" prefix */
1079 switch(sym->v) {
1080 #if 0
1081 /* XXX: we rely only on malloc hooks */
1082 case TOK_malloc:
1083 case TOK_free:
1084 case TOK_realloc:
1085 case TOK_memalign:
1086 case TOK_calloc:
1087 #endif
1088 case TOK_memcpy:
1089 case TOK_memmove:
1090 case TOK_memset:
1091 case TOK_strlen:
1092 case TOK_strcpy:
1093 strcpy(buf, "__bound_");
1094 strcat(buf, name);
1095 name = buf;
1096 break;
1099 #endif
1100 info = ELF32_ST_INFO(sym_bind, sym_type);
1101 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1102 } else {
1103 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1104 esym->st_value = value;
1105 esym->st_size = size;
1106 esym->st_shndx = sh_num;
1110 /* add a new relocation entry to symbol 'sym' in section 's' */
1111 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1113 if (!sym->c)
1114 put_extern_sym(sym, NULL, 0, 0);
1115 /* now we can add ELF relocation info */
1116 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1119 static inline int isid(int c)
1121 return (c >= 'a' && c <= 'z') ||
1122 (c >= 'A' && c <= 'Z') ||
1123 c == '_';
1126 static inline int isnum(int c)
1128 return c >= '0' && c <= '9';
1131 static inline int isoct(int c)
1133 return c >= '0' && c <= '7';
1136 static inline int toup(int c)
1138 if (c >= 'a' && c <= 'z')
1139 return c - 'a' + 'A';
1140 else
1141 return c;
1144 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1146 int len;
1147 len = strlen(buf);
1148 vsnprintf(buf + len, buf_size - len, fmt, ap);
1151 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1153 va_list ap;
1154 va_start(ap, fmt);
1155 strcat_vprintf(buf, buf_size, fmt, ap);
1156 va_end(ap);
1159 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1161 char buf[2048];
1162 BufferedFile **f;
1164 buf[0] = '\0';
1165 if (file) {
1166 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1167 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1168 (*f)->filename, (*f)->line_num);
1169 if (file->line_num > 0) {
1170 strcat_printf(buf, sizeof(buf),
1171 "%s:%d: ", file->filename, file->line_num);
1172 } else {
1173 strcat_printf(buf, sizeof(buf),
1174 "%s: ", file->filename);
1176 } else {
1177 strcat_printf(buf, sizeof(buf),
1178 "tcc: ");
1180 if (is_warning)
1181 strcat_printf(buf, sizeof(buf), "warning: ");
1182 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1184 if (!s1->error_func) {
1185 /* default case: stderr */
1186 fprintf(stderr, "%s\n", buf);
1187 } else {
1188 s1->error_func(s1->error_opaque, buf);
1190 if (!is_warning || s1->warn_error)
1191 s1->nb_errors++;
1194 #ifdef LIBTCC
1195 void tcc_set_error_func(TCCState *s, void *error_opaque,
1196 void (*error_func)(void *opaque, const char *msg))
1198 s->error_opaque = error_opaque;
1199 s->error_func = error_func;
1201 #endif
1203 /* error without aborting current compilation */
1204 void error_noabort(const char *fmt, ...)
1206 TCCState *s1 = tcc_state;
1207 va_list ap;
1209 va_start(ap, fmt);
1210 error1(s1, 0, fmt, ap);
1211 va_end(ap);
1214 void error(const char *fmt, ...)
1216 TCCState *s1 = tcc_state;
1217 va_list ap;
1219 va_start(ap, fmt);
1220 error1(s1, 0, fmt, ap);
1221 va_end(ap);
1222 /* better than nothing: in some cases, we accept to handle errors */
1223 if (s1->error_set_jmp_enabled) {
1224 longjmp(s1->error_jmp_buf, 1);
1225 } else {
1226 /* XXX: eliminate this someday */
1227 exit(1);
1231 void expect(const char *msg)
1233 error("%s expected", msg);
1236 void warning(const char *fmt, ...)
1238 TCCState *s1 = tcc_state;
1239 va_list ap;
1241 va_start(ap, fmt);
1242 error1(s1, 1, fmt, ap);
1243 va_end(ap);
1246 void skip(int c)
1248 if (tok != c)
1249 error("'%c' expected", c);
1250 next();
1253 static void test_lvalue(void)
1255 if (!(vtop->r & VT_LVAL))
1256 expect("lvalue");
1259 /* allocate a new token */
1260 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1262 TokenSym *ts, **ptable;
1263 int i;
1265 if (tok_ident >= SYM_FIRST_ANOM)
1266 error("memory full");
1268 /* expand token table if needed */
1269 i = tok_ident - TOK_IDENT;
1270 if ((i % TOK_ALLOC_INCR) == 0) {
1271 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1272 if (!ptable)
1273 error("memory full");
1274 table_ident = ptable;
1277 ts = tcc_malloc(sizeof(TokenSym) + len);
1278 table_ident[i] = ts;
1279 ts->tok = tok_ident++;
1280 ts->sym_define = NULL;
1281 ts->sym_label = NULL;
1282 ts->sym_struct = NULL;
1283 ts->sym_identifier = NULL;
1284 ts->len = len;
1285 ts->hash_next = NULL;
1286 memcpy(ts->str, str, len);
1287 ts->str[len] = '\0';
1288 *pts = ts;
1289 return ts;
1292 #define TOK_HASH_INIT 1
1293 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1295 /* find a token and add it if not found */
1296 static TokenSym *tok_alloc(const char *str, int len)
1298 TokenSym *ts, **pts;
1299 int i;
1300 unsigned int h;
1302 h = TOK_HASH_INIT;
1303 for(i=0;i<len;i++)
1304 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1305 h &= (TOK_HASH_SIZE - 1);
1307 pts = &hash_ident[h];
1308 for(;;) {
1309 ts = *pts;
1310 if (!ts)
1311 break;
1312 if (ts->len == len && !memcmp(ts->str, str, len))
1313 return ts;
1314 pts = &(ts->hash_next);
1316 return tok_alloc_new(pts, str, len);
1319 /* CString handling */
1321 static void cstr_realloc(CString *cstr, int new_size)
1323 int size;
1324 void *data;
1326 size = cstr->size_allocated;
1327 if (size == 0)
1328 size = 8; /* no need to allocate a too small first string */
1329 while (size < new_size)
1330 size = size * 2;
1331 data = tcc_realloc(cstr->data_allocated, size);
1332 if (!data)
1333 error("memory full");
1334 cstr->data_allocated = data;
1335 cstr->size_allocated = size;
1336 cstr->data = data;
1339 /* add a byte */
1340 static void cstr_ccat(CString *cstr, int ch)
1342 int size;
1343 size = cstr->size + 1;
1344 if (size > cstr->size_allocated)
1345 cstr_realloc(cstr, size);
1346 ((unsigned char *)cstr->data)[size - 1] = ch;
1347 cstr->size = size;
1350 static void cstr_cat(CString *cstr, const char *str)
1352 int c;
1353 for(;;) {
1354 c = *str;
1355 if (c == '\0')
1356 break;
1357 cstr_ccat(cstr, c);
1358 str++;
1362 /* add a wide char */
1363 static void cstr_wccat(CString *cstr, int ch)
1365 int size;
1366 size = cstr->size + sizeof(int);
1367 if (size > cstr->size_allocated)
1368 cstr_realloc(cstr, size);
1369 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1370 cstr->size = size;
1373 static void cstr_new(CString *cstr)
1375 memset(cstr, 0, sizeof(CString));
1378 /* free string and reset it to NULL */
1379 static void cstr_free(CString *cstr)
1381 tcc_free(cstr->data_allocated);
1382 cstr_new(cstr);
1385 #define cstr_reset(cstr) cstr_free(cstr)
1387 static CString *cstr_dup(CString *cstr1)
1389 CString *cstr;
1390 int size;
1392 cstr = tcc_malloc(sizeof(CString));
1393 size = cstr1->size;
1394 cstr->size = size;
1395 cstr->size_allocated = size;
1396 cstr->data_allocated = tcc_malloc(size);
1397 cstr->data = cstr->data_allocated;
1398 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1399 return cstr;
1402 /* XXX: unicode ? */
1403 static void add_char(CString *cstr, int c)
1405 if (c == '\'' || c == '\"' || c == '\\') {
1406 /* XXX: could be more precise if char or string */
1407 cstr_ccat(cstr, '\\');
1409 if (c >= 32 && c <= 126) {
1410 cstr_ccat(cstr, c);
1411 } else {
1412 cstr_ccat(cstr, '\\');
1413 if (c == '\n') {
1414 cstr_ccat(cstr, 'n');
1415 } else {
1416 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1417 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1418 cstr_ccat(cstr, '0' + (c & 7));
1423 /* XXX: buffer overflow */
1424 /* XXX: float tokens */
1425 char *get_tok_str(int v, CValue *cv)
1427 static char buf[STRING_MAX_SIZE + 1];
1428 static CString cstr_buf;
1429 CString *cstr;
1430 unsigned char *q;
1431 char *p;
1432 int i, len;
1434 /* NOTE: to go faster, we give a fixed buffer for small strings */
1435 cstr_reset(&cstr_buf);
1436 cstr_buf.data = buf;
1437 cstr_buf.size_allocated = sizeof(buf);
1438 p = buf;
1440 switch(v) {
1441 case TOK_CINT:
1442 case TOK_CUINT:
1443 /* XXX: not quite exact, but only useful for testing */
1444 sprintf(p, "%u", cv->ui);
1445 break;
1446 case TOK_CLLONG:
1447 case TOK_CULLONG:
1448 /* XXX: not quite exact, but only useful for testing */
1449 sprintf(p, "%Lu", cv->ull);
1450 break;
1451 case TOK_CCHAR:
1452 case TOK_LCHAR:
1453 cstr_ccat(&cstr_buf, '\'');
1454 add_char(&cstr_buf, cv->i);
1455 cstr_ccat(&cstr_buf, '\'');
1456 cstr_ccat(&cstr_buf, '\0');
1457 break;
1458 case TOK_PPNUM:
1459 cstr = cv->cstr;
1460 len = cstr->size - 1;
1461 for(i=0;i<len;i++)
1462 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1463 cstr_ccat(&cstr_buf, '\0');
1464 break;
1465 case TOK_STR:
1466 case TOK_LSTR:
1467 cstr = cv->cstr;
1468 cstr_ccat(&cstr_buf, '\"');
1469 if (v == TOK_STR) {
1470 len = cstr->size - 1;
1471 for(i=0;i<len;i++)
1472 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1473 } else {
1474 len = (cstr->size / sizeof(int)) - 1;
1475 for(i=0;i<len;i++)
1476 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1478 cstr_ccat(&cstr_buf, '\"');
1479 cstr_ccat(&cstr_buf, '\0');
1480 break;
1481 case TOK_LT:
1482 v = '<';
1483 goto addv;
1484 case TOK_GT:
1485 v = '>';
1486 goto addv;
1487 case TOK_A_SHL:
1488 return strcpy(p, "<<=");
1489 case TOK_A_SAR:
1490 return strcpy(p, ">>=");
1491 default:
1492 if (v < TOK_IDENT) {
1493 /* search in two bytes table */
1494 q = tok_two_chars;
1495 while (*q) {
1496 if (q[2] == v) {
1497 *p++ = q[0];
1498 *p++ = q[1];
1499 *p = '\0';
1500 return buf;
1502 q += 3;
1504 addv:
1505 *p++ = v;
1506 *p = '\0';
1507 } else if (v < tok_ident) {
1508 return table_ident[v - TOK_IDENT]->str;
1509 } else if (v >= SYM_FIRST_ANOM) {
1510 /* special name for anonymous symbol */
1511 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1512 } else {
1513 /* should never happen */
1514 return NULL;
1516 break;
1518 return cstr_buf.data;
1521 /* push, without hashing */
1522 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1524 Sym *s;
1525 s = tcc_malloc(sizeof(Sym));
1526 s->v = v;
1527 s->type.t = t;
1528 s->c = c;
1529 s->next = NULL;
1530 /* add in stack */
1531 s->prev = *ps;
1532 *ps = s;
1533 return s;
1536 /* find a symbol and return its associated structure. 's' is the top
1537 of the symbol stack */
1538 static Sym *sym_find2(Sym *s, int v)
1540 while (s) {
1541 if (s->v == v)
1542 return s;
1543 s = s->prev;
1545 return NULL;
1548 /* structure lookup */
1549 static inline Sym *struct_find(int v)
1551 v -= TOK_IDENT;
1552 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1553 return NULL;
1554 return table_ident[v]->sym_struct;
1557 /* find an identifier */
1558 static inline Sym *sym_find(int v)
1560 v -= TOK_IDENT;
1561 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1562 return NULL;
1563 return table_ident[v]->sym_identifier;
1566 /* push a given symbol on the symbol stack */
1567 static Sym *sym_push(int v, CType *type, int r, int c)
1569 Sym *s, **ps;
1570 TokenSym *ts;
1572 if (local_stack)
1573 ps = &local_stack;
1574 else
1575 ps = &global_stack;
1576 s = sym_push2(ps, v, type->t, c);
1577 s->type.ref = type->ref;
1578 s->r = r;
1579 /* don't record fields or anonymous symbols */
1580 /* XXX: simplify */
1581 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1582 /* record symbol in token array */
1583 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1584 if (v & SYM_STRUCT)
1585 ps = &ts->sym_struct;
1586 else
1587 ps = &ts->sym_identifier;
1588 s->prev_tok = *ps;
1589 *ps = s;
1591 return s;
1594 /* push a global identifier */
1595 static Sym *global_identifier_push(int v, int t, int c)
1597 Sym *s, **ps;
1598 s = sym_push2(&global_stack, v, t, c);
1599 /* don't record anonymous symbol */
1600 if (v < SYM_FIRST_ANOM) {
1601 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1602 /* modify the top most local identifier, so that
1603 sym_identifier will point to 's' when popped */
1604 while (*ps != NULL)
1605 ps = &(*ps)->prev_tok;
1606 s->prev_tok = NULL;
1607 *ps = s;
1609 return s;
1612 /* pop symbols until top reaches 'b' */
1613 static void sym_pop(Sym **ptop, Sym *b)
1615 Sym *s, *ss, **ps;
1616 TokenSym *ts;
1617 int v;
1619 s = *ptop;
1620 while(s != b) {
1621 ss = s->prev;
1622 v = s->v;
1623 /* remove symbol in token array */
1624 /* XXX: simplify */
1625 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1626 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1627 if (v & SYM_STRUCT)
1628 ps = &ts->sym_struct;
1629 else
1630 ps = &ts->sym_identifier;
1631 *ps = s->prev_tok;
1633 tcc_free(s);
1634 s = ss;
1636 *ptop = b;
1639 /* I/O layer */
1641 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1643 int fd;
1644 BufferedFile *bf;
1646 fd = open(filename, O_RDONLY);
1647 if (fd < 0)
1648 return NULL;
1649 bf = tcc_malloc(sizeof(BufferedFile));
1650 if (!bf) {
1651 close(fd);
1652 return NULL;
1654 bf->fd = fd;
1655 bf->buf_ptr = bf->buffer;
1656 bf->buf_end = bf->buffer;
1657 bf->buffer[0] = CH_EOB; /* put eob symbol */
1658 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1659 bf->line_num = 1;
1660 bf->ifndef_macro = 0;
1661 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1662 // printf("opening '%s'\n", filename);
1663 return bf;
1666 void tcc_close(BufferedFile *bf)
1668 total_lines += bf->line_num;
1669 close(bf->fd);
1670 tcc_free(bf);
1673 /* fill input buffer and peek next char */
1674 static int tcc_peekc_slow(BufferedFile *bf)
1676 int len;
1677 /* only tries to read if really end of buffer */
1678 if (bf->buf_ptr >= bf->buf_end) {
1679 if (bf->fd != -1) {
1680 #if defined(PARSE_DEBUG)
1681 len = 8;
1682 #else
1683 len = IO_BUF_SIZE;
1684 #endif
1685 len = read(bf->fd, bf->buffer, len);
1686 if (len < 0)
1687 len = 0;
1688 } else {
1689 len = 0;
1691 total_bytes += len;
1692 bf->buf_ptr = bf->buffer;
1693 bf->buf_end = bf->buffer + len;
1694 *bf->buf_end = CH_EOB;
1696 if (bf->buf_ptr < bf->buf_end) {
1697 return bf->buf_ptr[0];
1698 } else {
1699 bf->buf_ptr = bf->buf_end;
1700 return CH_EOF;
1704 /* return the current character, handling end of block if necessary
1705 (but not stray) */
1706 static int handle_eob(void)
1708 return tcc_peekc_slow(file);
1711 /* read next char from current input file and handle end of input buffer */
1712 static inline void inp(void)
1714 ch = *(++(file->buf_ptr));
1715 /* end of buffer/file handling */
1716 if (ch == CH_EOB)
1717 ch = handle_eob();
1720 /* handle '\[\r]\n' */
1721 static void handle_stray(void)
1723 while (ch == '\\') {
1724 inp();
1725 if (ch == '\n') {
1726 file->line_num++;
1727 inp();
1728 } else if (ch == '\r') {
1729 inp();
1730 if (ch != '\n')
1731 goto fail;
1732 file->line_num++;
1733 inp();
1734 } else {
1735 fail:
1736 error("stray '\\' in program");
1741 /* skip the stray and handle the \\n case. Output an error if
1742 incorrect char after the stray */
1743 static int handle_stray1(uint8_t *p)
1745 int c;
1747 if (p >= file->buf_end) {
1748 file->buf_ptr = p;
1749 c = handle_eob();
1750 p = file->buf_ptr;
1751 if (c == '\\')
1752 goto parse_stray;
1753 } else {
1754 parse_stray:
1755 file->buf_ptr = p;
1756 ch = *p;
1757 handle_stray();
1758 p = file->buf_ptr;
1759 c = *p;
1761 return c;
1764 /* handle just the EOB case, but not stray */
1765 #define PEEKC_EOB(c, p)\
1767 p++;\
1768 c = *p;\
1769 if (c == '\\') {\
1770 file->buf_ptr = p;\
1771 c = handle_eob();\
1772 p = file->buf_ptr;\
1776 /* handle the complicated stray case */
1777 #define PEEKC(c, p)\
1779 p++;\
1780 c = *p;\
1781 if (c == '\\') {\
1782 c = handle_stray1(p);\
1783 p = file->buf_ptr;\
1787 /* input with '\[\r]\n' handling. Note that this function cannot
1788 handle other characters after '\', so you cannot call it inside
1789 strings or comments */
1790 static void minp(void)
1792 inp();
1793 if (ch == '\\')
1794 handle_stray();
1798 /* single line C++ comments */
1799 static uint8_t *parse_line_comment(uint8_t *p)
1801 int c;
1803 p++;
1804 for(;;) {
1805 c = *p;
1806 if (c == '\n' || c == CH_EOF) {
1807 break;
1808 } else if (c == '\\') {
1809 PEEKC_EOB(c, p);
1810 if (c == '\n') {
1811 file->line_num++;
1812 PEEKC_EOB(c, p);
1813 } else if (c == '\r') {
1814 PEEKC_EOB(c, p);
1815 if (c == '\n') {
1816 file->line_num++;
1817 PEEKC_EOB(c, p);
1820 } else {
1821 p++;
1824 return p;
1827 /* C comments */
1828 static uint8_t *parse_comment(uint8_t *p)
1830 int c;
1832 p++;
1833 for(;;) {
1834 /* fast skip loop */
1835 for(;;) {
1836 c = *p;
1837 if (c == '\n' || c == '*' || c == '\\')
1838 break;
1839 p++;
1840 c = *p;
1841 if (c == '\n' || c == '*' || c == '\\')
1842 break;
1843 p++;
1845 /* now we can handle all the cases */
1846 if (c == '\n') {
1847 file->line_num++;
1848 p++;
1849 } else if (c == '*') {
1850 p++;
1851 for(;;) {
1852 c = *p;
1853 if (c == '*') {
1854 p++;
1855 } else if (c == '/') {
1856 goto end_of_comment;
1857 } else if (c == '\\') {
1858 file->buf_ptr = p;
1859 c = handle_eob();
1860 p = file->buf_ptr;
1861 if (c == '\\') {
1862 /* skip '\[\r]\n', otherwise just skip the stray */
1863 while (c == '\\') {
1864 PEEKC_EOB(c, p);
1865 if (c == '\n') {
1866 file->line_num++;
1867 PEEKC_EOB(c, p);
1868 } else if (c == '\r') {
1869 PEEKC_EOB(c, p);
1870 if (c == '\n') {
1871 file->line_num++;
1872 PEEKC_EOB(c, p);
1874 } else {
1875 goto after_star;
1879 } else {
1880 break;
1883 after_star: ;
1884 } else {
1885 /* stray, eob or eof */
1886 file->buf_ptr = p;
1887 c = handle_eob();
1888 p = file->buf_ptr;
1889 if (c == CH_EOF) {
1890 error("unexpected end of file in comment");
1891 } else if (c == '\\') {
1892 p++;
1896 end_of_comment:
1897 p++;
1898 return p;
1901 #define cinp minp
1903 /* space exlcuding newline */
1904 static inline int is_space(int ch)
1906 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1909 static inline void skip_spaces(void)
1911 while (is_space(ch))
1912 cinp();
1915 /* parse a string without interpreting escapes */
1916 static uint8_t *parse_pp_string(uint8_t *p,
1917 int sep, CString *str)
1919 int c;
1920 p++;
1921 for(;;) {
1922 c = *p;
1923 if (c == sep) {
1924 break;
1925 } else if (c == '\\') {
1926 file->buf_ptr = p;
1927 c = handle_eob();
1928 p = file->buf_ptr;
1929 if (c == CH_EOF) {
1930 unterminated_string:
1931 /* XXX: indicate line number of start of string */
1932 error("missing terminating %c character", sep);
1933 } else if (c == '\\') {
1934 /* escape : just skip \[\r]\n */
1935 PEEKC_EOB(c, p);
1936 if (c == '\n') {
1937 file->line_num++;
1938 p++;
1939 } else if (c == '\r') {
1940 PEEKC_EOB(c, p);
1941 if (c != '\n')
1942 expect("'\n' after '\r'");
1943 file->line_num++;
1944 p++;
1945 } else if (c == CH_EOF) {
1946 goto unterminated_string;
1947 } else {
1948 if (str) {
1949 cstr_ccat(str, '\\');
1950 cstr_ccat(str, c);
1952 p++;
1955 } else if (c == '\n') {
1956 file->line_num++;
1957 goto add_char;
1958 } else if (c == '\r') {
1959 PEEKC_EOB(c, p);
1960 if (c != '\n') {
1961 cstr_ccat(str, '\r');
1962 } else {
1963 file->line_num++;
1964 goto add_char;
1966 } else {
1967 add_char:
1968 if (str)
1969 cstr_ccat(str, c);
1970 p++;
1973 p++;
1974 return p;
1977 /* skip block of text until #else, #elif or #endif. skip also pairs of
1978 #if/#endif */
1979 void preprocess_skip(void)
1981 int a, start_of_line, c;
1982 uint8_t *p;
1984 p = file->buf_ptr;
1985 start_of_line = 1;
1986 a = 0;
1987 for(;;) {
1988 redo_no_start:
1989 c = *p;
1990 switch(c) {
1991 case ' ':
1992 case '\t':
1993 case '\f':
1994 case '\v':
1995 case '\r':
1996 p++;
1997 goto redo_no_start;
1998 case '\n':
1999 start_of_line = 1;
2000 file->line_num++;
2001 p++;
2002 goto redo_no_start;
2003 case '\\':
2004 file->buf_ptr = p;
2005 c = handle_eob();
2006 if (c == CH_EOF) {
2007 expect("#endif");
2008 } else if (c == '\\') {
2009 /* XXX: incorrect: should not give an error */
2010 ch = file->buf_ptr[0];
2011 handle_stray();
2013 p = file->buf_ptr;
2014 goto redo_no_start;
2015 /* skip strings */
2016 case '\"':
2017 case '\'':
2018 p = parse_pp_string(p, c, NULL);
2019 break;
2020 /* skip comments */
2021 case '/':
2022 file->buf_ptr = p;
2023 ch = *p;
2024 minp();
2025 p = file->buf_ptr;
2026 if (ch == '*') {
2027 p = parse_comment(p);
2028 } else if (ch == '/') {
2029 p = parse_line_comment(p);
2031 break;
2033 case '#':
2034 p++;
2035 if (start_of_line) {
2036 file->buf_ptr = p;
2037 next_nomacro();
2038 p = file->buf_ptr;
2039 if (a == 0 &&
2040 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2041 goto the_end;
2042 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2043 a++;
2044 else if (tok == TOK_ENDIF)
2045 a--;
2047 break;
2048 default:
2049 p++;
2050 break;
2052 start_of_line = 0;
2054 the_end: ;
2055 file->buf_ptr = p;
2058 /* ParseState handling */
2060 /* XXX: currently, no include file info is stored. Thus, we cannot display
2061 accurate messages if the function or data definition spans multiple
2062 files */
2064 /* save current parse state in 's' */
2065 void save_parse_state(ParseState *s)
2067 s->line_num = file->line_num;
2068 s->macro_ptr = macro_ptr;
2069 s->tok = tok;
2070 s->tokc = tokc;
2073 /* restore parse state from 's' */
2074 void restore_parse_state(ParseState *s)
2076 file->line_num = s->line_num;
2077 macro_ptr = s->macro_ptr;
2078 tok = s->tok;
2079 tokc = s->tokc;
2082 /* return the number of additional 'ints' necessary to store the
2083 token */
2084 static inline int tok_ext_size(int t)
2086 switch(t) {
2087 /* 4 bytes */
2088 case TOK_CINT:
2089 case TOK_CUINT:
2090 case TOK_CCHAR:
2091 case TOK_LCHAR:
2092 case TOK_STR:
2093 case TOK_LSTR:
2094 case TOK_CFLOAT:
2095 case TOK_LINENUM:
2096 case TOK_PPNUM:
2097 return 1;
2098 case TOK_CDOUBLE:
2099 case TOK_CLLONG:
2100 case TOK_CULLONG:
2101 return 2;
2102 case TOK_CLDOUBLE:
2103 return LDOUBLE_SIZE / 4;
2104 default:
2105 return 0;
2109 /* token string handling */
2111 static inline void tok_str_new(TokenString *s)
2113 s->str = NULL;
2114 s->len = 0;
2115 s->allocated_len = 0;
2116 s->last_line_num = -1;
2119 static void tok_str_free(int *str)
2121 const int *p;
2122 CString *cstr;
2123 int t;
2125 p = str;
2126 for(;;) {
2127 t = *p;
2128 /* NOTE: we test zero separately so that GCC can generate a
2129 table for the following switch */
2130 if (t == 0)
2131 break;
2132 switch(t) {
2133 case TOK_CINT:
2134 case TOK_CUINT:
2135 case TOK_CCHAR:
2136 case TOK_LCHAR:
2137 case TOK_CFLOAT:
2138 case TOK_LINENUM:
2139 p += 2;
2140 break;
2141 case TOK_PPNUM:
2142 case TOK_STR:
2143 case TOK_LSTR:
2144 /* XXX: use a macro to be portable on 64 bit ? */
2145 cstr = (CString *)p[1];
2146 cstr_free(cstr);
2147 tcc_free(cstr);
2148 p += 2;
2149 break;
2150 case TOK_CDOUBLE:
2151 case TOK_CLLONG:
2152 case TOK_CULLONG:
2153 p += 3;
2154 break;
2155 case TOK_CLDOUBLE:
2156 p += 1 + (LDOUBLE_SIZE / 4);
2157 break;
2158 default:
2159 p++;
2160 break;
2163 tcc_free(str);
2166 static int *tok_str_realloc(TokenString *s)
2168 int *str, len;
2170 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2171 str = tcc_realloc(s->str, len * sizeof(int));
2172 if (!str)
2173 error("memory full");
2174 s->allocated_len = len;
2175 s->str = str;
2176 return str;
2179 static void tok_str_add(TokenString *s, int t)
2181 int len, *str;
2183 len = s->len;
2184 str = s->str;
2185 if (len >= s->allocated_len)
2186 str = tok_str_realloc(s);
2187 str[len++] = t;
2188 s->len = len;
2191 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2193 int len, *str;
2195 len = s->len;
2196 str = s->str;
2198 /* allocate space for worst case */
2199 if (len + TOK_MAX_SIZE > s->allocated_len)
2200 str = tok_str_realloc(s);
2201 str[len++] = t;
2202 switch(t) {
2203 case TOK_CINT:
2204 case TOK_CUINT:
2205 case TOK_CCHAR:
2206 case TOK_LCHAR:
2207 case TOK_CFLOAT:
2208 case TOK_LINENUM:
2209 str[len++] = cv->tab[0];
2210 break;
2211 case TOK_PPNUM:
2212 case TOK_STR:
2213 case TOK_LSTR:
2214 str[len++] = (int)cstr_dup(cv->cstr);
2215 break;
2216 case TOK_CDOUBLE:
2217 case TOK_CLLONG:
2218 case TOK_CULLONG:
2219 str[len++] = cv->tab[0];
2220 str[len++] = cv->tab[1];
2221 break;
2222 case TOK_CLDOUBLE:
2223 #if LDOUBLE_SIZE == 12
2224 str[len++] = cv->tab[0];
2225 str[len++] = cv->tab[1];
2226 str[len++] = cv->tab[2];
2227 #else
2228 #error add long double size support
2229 #endif
2230 break;
2231 default:
2232 break;
2234 s->len = len;
2237 /* add the current parse token in token string 's' */
2238 static void tok_str_add_tok(TokenString *s)
2240 CValue cval;
2242 /* save line number info */
2243 if (file->line_num != s->last_line_num) {
2244 s->last_line_num = file->line_num;
2245 cval.i = s->last_line_num;
2246 tok_str_add2(s, TOK_LINENUM, &cval);
2248 tok_str_add2(s, tok, &tokc);
2251 #if LDOUBLE_SIZE == 12
2252 #define LDOUBLE_GET(p, cv) \
2253 cv.tab[0] = p[0]; \
2254 cv.tab[1] = p[1]; \
2255 cv.tab[2] = p[2];
2256 #else
2257 #error add long double size support
2258 #endif
2261 /* get a token from an integer array and increment pointer
2262 accordingly. we code it as a macro to avoid pointer aliasing. */
2263 #define TOK_GET(t, p, cv) \
2265 t = *p++; \
2266 switch(t) { \
2267 case TOK_CINT: \
2268 case TOK_CUINT: \
2269 case TOK_CCHAR: \
2270 case TOK_LCHAR: \
2271 case TOK_CFLOAT: \
2272 case TOK_LINENUM: \
2273 case TOK_STR: \
2274 case TOK_LSTR: \
2275 case TOK_PPNUM: \
2276 cv.tab[0] = *p++; \
2277 break; \
2278 case TOK_CDOUBLE: \
2279 case TOK_CLLONG: \
2280 case TOK_CULLONG: \
2281 cv.tab[0] = p[0]; \
2282 cv.tab[1] = p[1]; \
2283 p += 2; \
2284 break; \
2285 case TOK_CLDOUBLE: \
2286 LDOUBLE_GET(p, cv); \
2287 p += LDOUBLE_SIZE / 4; \
2288 break; \
2289 default: \
2290 break; \
2294 /* defines handling */
2295 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2297 Sym *s;
2299 s = sym_push2(&define_stack, v, macro_type, (int)str);
2300 s->next = first_arg;
2301 table_ident[v - TOK_IDENT]->sym_define = s;
2304 /* undefined a define symbol. Its name is just set to zero */
2305 static void define_undef(Sym *s)
2307 int v;
2308 v = s->v;
2309 if (v >= TOK_IDENT && v < tok_ident)
2310 table_ident[v - TOK_IDENT]->sym_define = NULL;
2311 s->v = 0;
2314 static inline Sym *define_find(int v)
2316 v -= TOK_IDENT;
2317 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2318 return NULL;
2319 return table_ident[v]->sym_define;
2322 /* free define stack until top reaches 'b' */
2323 static void free_defines(Sym *b)
2325 Sym *top, *top1;
2326 int v;
2328 top = define_stack;
2329 while (top != b) {
2330 top1 = top->prev;
2331 /* do not free args or predefined defines */
2332 if (top->c)
2333 tok_str_free((int *)top->c);
2334 v = top->v;
2335 if (v >= TOK_IDENT && v < tok_ident)
2336 table_ident[v - TOK_IDENT]->sym_define = NULL;
2337 tcc_free(top);
2338 top = top1;
2340 define_stack = b;
2343 /* label lookup */
2344 static Sym *label_find(int v)
2346 v -= TOK_IDENT;
2347 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2348 return NULL;
2349 return table_ident[v]->sym_label;
2352 static Sym *label_push(Sym **ptop, int v, int flags)
2354 Sym *s, **ps;
2355 s = sym_push2(ptop, v, 0, 0);
2356 s->r = flags;
2357 ps = &table_ident[v - TOK_IDENT]->sym_label;
2358 if (ptop == &global_label_stack) {
2359 /* modify the top most local identifier, so that
2360 sym_identifier will point to 's' when popped */
2361 while (*ps != NULL)
2362 ps = &(*ps)->prev_tok;
2364 s->prev_tok = *ps;
2365 *ps = s;
2366 return s;
2369 /* pop labels until element last is reached. Look if any labels are
2370 undefined. Define symbols if '&&label' was used. */
2371 static void label_pop(Sym **ptop, Sym *slast)
2373 Sym *s, *s1;
2374 for(s = *ptop; s != slast; s = s1) {
2375 s1 = s->prev;
2376 if (s->r == LABEL_DECLARED) {
2377 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2378 } else if (s->r == LABEL_FORWARD) {
2379 error("label '%s' used but not defined",
2380 get_tok_str(s->v, NULL));
2381 } else {
2382 if (s->c) {
2383 /* define corresponding symbol. A size of
2384 1 is put. */
2385 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2388 /* remove label */
2389 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2390 tcc_free(s);
2392 *ptop = slast;
2395 /* eval an expression for #if/#elif */
2396 static int expr_preprocess(void)
2398 int c, t;
2399 TokenString str;
2401 tok_str_new(&str);
2402 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2403 next(); /* do macro subst */
2404 if (tok == TOK_DEFINED) {
2405 next_nomacro();
2406 t = tok;
2407 if (t == '(')
2408 next_nomacro();
2409 c = define_find(tok) != 0;
2410 if (t == '(')
2411 next_nomacro();
2412 tok = TOK_CINT;
2413 tokc.i = c;
2414 } else if (tok >= TOK_IDENT) {
2415 /* if undefined macro */
2416 tok = TOK_CINT;
2417 tokc.i = 0;
2419 tok_str_add_tok(&str);
2421 tok_str_add(&str, -1); /* simulate end of file */
2422 tok_str_add(&str, 0);
2423 /* now evaluate C constant expression */
2424 macro_ptr = str.str;
2425 next();
2426 c = expr_const();
2427 macro_ptr = NULL;
2428 tok_str_free(str.str);
2429 return c != 0;
2432 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2433 static void tok_print(int *str)
2435 int t;
2436 CValue cval;
2438 while (1) {
2439 TOK_GET(t, str, cval);
2440 if (!t)
2441 break;
2442 printf(" %s", get_tok_str(t, &cval));
2444 printf("\n");
2446 #endif
2448 /* parse after #define */
2449 static void parse_define(void)
2451 Sym *s, *first, **ps;
2452 int v, t, varg, is_vaargs, c;
2453 TokenString str;
2455 v = tok;
2456 if (v < TOK_IDENT)
2457 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2458 /* XXX: should check if same macro (ANSI) */
2459 first = NULL;
2460 t = MACRO_OBJ;
2461 /* '(' must be just after macro definition for MACRO_FUNC */
2462 c = file->buf_ptr[0];
2463 if (c == '\\')
2464 c = handle_stray1(file->buf_ptr);
2465 if (c == '(') {
2466 next_nomacro();
2467 next_nomacro();
2468 ps = &first;
2469 while (tok != ')') {
2470 varg = tok;
2471 next_nomacro();
2472 is_vaargs = 0;
2473 if (varg == TOK_DOTS) {
2474 varg = TOK___VA_ARGS__;
2475 is_vaargs = 1;
2476 } else if (tok == TOK_DOTS && gnu_ext) {
2477 is_vaargs = 1;
2478 next_nomacro();
2480 if (varg < TOK_IDENT)
2481 error("badly punctuated parameter list");
2482 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2483 *ps = s;
2484 ps = &s->next;
2485 if (tok != ',')
2486 break;
2487 next_nomacro();
2489 t = MACRO_FUNC;
2491 tok_str_new(&str);
2492 next_nomacro();
2493 /* EOF testing necessary for '-D' handling */
2494 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2495 tok_str_add2(&str, tok, &tokc);
2496 next_nomacro();
2498 tok_str_add(&str, 0);
2499 #ifdef PP_DEBUG
2500 printf("define %s %d: ", get_tok_str(v, NULL), t);
2501 tok_print(str.str);
2502 #endif
2503 define_push(v, t, str.str, first);
2506 /* XXX: use a token or a hash table to accelerate matching ? */
2507 static CachedInclude *search_cached_include(TCCState *s1,
2508 int type, const char *filename)
2510 CachedInclude *e;
2511 int i;
2513 for(i = 0;i < s1->nb_cached_includes; i++) {
2514 e = s1->cached_includes[i];
2515 if (e->type == type && !strcmp(e->filename, filename))
2516 return e;
2518 return NULL;
2521 static inline void add_cached_include(TCCState *s1, int type,
2522 const char *filename, int ifndef_macro)
2524 CachedInclude *e;
2526 if (search_cached_include(s1, type, filename))
2527 return;
2528 #ifdef INC_DEBUG
2529 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2530 #endif
2531 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2532 if (!e)
2533 return;
2534 e->type = type;
2535 strcpy(e->filename, filename);
2536 e->ifndef_macro = ifndef_macro;
2537 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2540 /* is_bof is true if first non space token at beginning of file */
2541 static void preprocess(int is_bof)
2543 TCCState *s1 = tcc_state;
2544 int size, i, c, n, saved_parse_flags;
2545 char buf[1024], *q, *p;
2546 char buf1[1024];
2547 BufferedFile *f;
2548 Sym *s;
2549 CachedInclude *e;
2551 saved_parse_flags = parse_flags;
2552 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2553 PARSE_FLAG_LINEFEED;
2554 next_nomacro();
2555 redo:
2556 switch(tok) {
2557 case TOK_DEFINE:
2558 next_nomacro();
2559 parse_define();
2560 break;
2561 case TOK_UNDEF:
2562 next_nomacro();
2563 s = define_find(tok);
2564 /* undefine symbol by putting an invalid name */
2565 if (s)
2566 define_undef(s);
2567 break;
2568 case TOK_INCLUDE:
2569 ch = file->buf_ptr[0];
2570 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2571 skip_spaces();
2572 if (ch == '<') {
2573 c = '>';
2574 goto read_name;
2575 } else if (ch == '\"') {
2576 c = ch;
2577 read_name:
2578 /* XXX: better stray handling */
2579 minp();
2580 q = buf;
2581 while (ch != c && ch != '\n' && ch != CH_EOF) {
2582 if ((q - buf) < sizeof(buf) - 1)
2583 *q++ = ch;
2584 minp();
2586 *q = '\0';
2587 minp();
2588 #if 0
2589 /* eat all spaces and comments after include */
2590 /* XXX: slightly incorrect */
2591 while (ch1 != '\n' && ch1 != CH_EOF)
2592 inp();
2593 #endif
2594 } else {
2595 /* computed #include : either we have only strings or
2596 we have anything enclosed in '<>' */
2597 next();
2598 buf[0] = '\0';
2599 if (tok == TOK_STR) {
2600 while (tok != TOK_LINEFEED) {
2601 if (tok != TOK_STR) {
2602 include_syntax:
2603 error("'#include' expects \"FILENAME\" or <FILENAME>");
2605 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2606 next();
2608 c = '\"';
2609 } else {
2610 int len;
2611 while (tok != TOK_LINEFEED) {
2612 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2613 next();
2615 len = strlen(buf);
2616 /* check syntax and remove '<>' */
2617 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2618 goto include_syntax;
2619 memmove(buf, buf + 1, len - 2);
2620 buf[len - 2] = '\0';
2621 c = '>';
2625 e = search_cached_include(s1, c, buf);
2626 if (e && define_find(e->ifndef_macro)) {
2627 /* no need to parse the include because the 'ifndef macro'
2628 is defined */
2629 #ifdef INC_DEBUG
2630 printf("%s: skipping %s\n", file->filename, buf);
2631 #endif
2632 } else {
2633 if (c == '\"') {
2634 /* first search in current dir if "header.h" */
2635 size = 0;
2636 p = strrchr(file->filename, '/');
2637 if (p)
2638 size = p + 1 - file->filename;
2639 if (size > sizeof(buf1) - 1)
2640 size = sizeof(buf1) - 1;
2641 memcpy(buf1, file->filename, size);
2642 buf1[size] = '\0';
2643 pstrcat(buf1, sizeof(buf1), buf);
2644 f = tcc_open(s1, buf1);
2645 if (f)
2646 goto found;
2648 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2649 error("#include recursion too deep");
2650 /* now search in all the include paths */
2651 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2652 for(i = 0; i < n; i++) {
2653 const char *path;
2654 if (i < s1->nb_include_paths)
2655 path = s1->include_paths[i];
2656 else
2657 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2658 pstrcpy(buf1, sizeof(buf1), path);
2659 pstrcat(buf1, sizeof(buf1), "/");
2660 pstrcat(buf1, sizeof(buf1), buf);
2661 f = tcc_open(s1, buf1);
2662 if (f)
2663 goto found;
2665 error("include file '%s' not found", buf);
2666 f = NULL;
2667 found:
2668 #ifdef INC_DEBUG
2669 printf("%s: including %s\n", file->filename, buf1);
2670 #endif
2671 f->inc_type = c;
2672 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2673 /* push current file in stack */
2674 /* XXX: fix current line init */
2675 *s1->include_stack_ptr++ = file;
2676 file = f;
2677 /* add include file debug info */
2678 if (do_debug) {
2679 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2681 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2682 ch = file->buf_ptr[0];
2683 goto the_end;
2685 break;
2686 case TOK_IFNDEF:
2687 c = 1;
2688 goto do_ifdef;
2689 case TOK_IF:
2690 c = expr_preprocess();
2691 goto do_if;
2692 case TOK_IFDEF:
2693 c = 0;
2694 do_ifdef:
2695 next_nomacro();
2696 if (tok < TOK_IDENT)
2697 error("invalid argument for '#if%sdef'", c ? "n" : "");
2698 if (is_bof) {
2699 if (c) {
2700 #ifdef INC_DEBUG
2701 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2702 #endif
2703 file->ifndef_macro = tok;
2706 c = (define_find(tok) != 0) ^ c;
2707 do_if:
2708 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2709 error("memory full");
2710 *s1->ifdef_stack_ptr++ = c;
2711 goto test_skip;
2712 case TOK_ELSE:
2713 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2714 error("#else without matching #if");
2715 if (s1->ifdef_stack_ptr[-1] & 2)
2716 error("#else after #else");
2717 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2718 goto test_skip;
2719 case TOK_ELIF:
2720 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2721 error("#elif without matching #if");
2722 c = s1->ifdef_stack_ptr[-1];
2723 if (c > 1)
2724 error("#elif after #else");
2725 /* last #if/#elif expression was true: we skip */
2726 if (c == 1)
2727 goto skip;
2728 c = expr_preprocess();
2729 s1->ifdef_stack_ptr[-1] = c;
2730 test_skip:
2731 if (!(c & 1)) {
2732 skip:
2733 preprocess_skip();
2734 is_bof = 0;
2735 goto redo;
2737 break;
2738 case TOK_ENDIF:
2739 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2740 error("#endif without matching #if");
2741 s1->ifdef_stack_ptr--;
2742 /* '#ifndef macro' was at the start of file. Now we check if
2743 an '#endif' is exactly at the end of file */
2744 if (file->ifndef_macro &&
2745 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2746 file->ifndef_macro_saved = file->ifndef_macro;
2747 /* need to set to zero to avoid false matches if another
2748 #ifndef at middle of file */
2749 file->ifndef_macro = 0;
2750 while (tok != TOK_LINEFEED)
2751 next_nomacro();
2752 tok_flags |= TOK_FLAG_ENDIF;
2753 goto the_end;
2755 break;
2756 case TOK_LINE:
2757 next();
2758 if (tok != TOK_CINT)
2759 error("#line");
2760 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2761 next();
2762 if (tok != TOK_LINEFEED) {
2763 if (tok != TOK_STR)
2764 error("#line");
2765 pstrcpy(file->filename, sizeof(file->filename),
2766 (char *)tokc.cstr->data);
2768 break;
2769 case TOK_ERROR:
2770 case TOK_WARNING:
2771 c = tok;
2772 ch = file->buf_ptr[0];
2773 skip_spaces();
2774 q = buf;
2775 while (ch != '\n' && ch != CH_EOF) {
2776 if ((q - buf) < sizeof(buf) - 1)
2777 *q++ = ch;
2778 minp();
2780 *q = '\0';
2781 if (c == TOK_ERROR)
2782 error("#error %s", buf);
2783 else
2784 warning("#warning %s", buf);
2785 break;
2786 case TOK_PRAGMA:
2787 /* ignored */
2788 break;
2789 default:
2790 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2791 /* '!' is ignored to allow C scripts. numbers are ignored
2792 to emulate cpp behaviour */
2793 } else {
2794 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2796 break;
2798 /* ignore other preprocess commands or #! for C scripts */
2799 while (tok != TOK_LINEFEED)
2800 next_nomacro();
2801 the_end:
2802 parse_flags = saved_parse_flags;
2805 /* evaluate escape codes in a string. */
2806 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2808 int c, n;
2809 const char *p;
2811 p = buf;
2812 for(;;) {
2813 c = *p;
2814 if (c == '\0')
2815 break;
2816 if (c == '\\') {
2817 p++;
2818 /* escape */
2819 c = *p;
2820 switch(c) {
2821 case '0': case '1': case '2': case '3':
2822 case '4': case '5': case '6': case '7':
2823 /* at most three octal digits */
2824 n = c - '0';
2825 p++;
2826 c = *p;
2827 if (isoct(c)) {
2828 n = n * 8 + c - '0';
2829 p++;
2830 c = *p;
2831 if (isoct(c)) {
2832 n = n * 8 + c - '0';
2833 p++;
2836 c = n;
2837 goto add_char_nonext;
2838 case 'x':
2839 p++;
2840 n = 0;
2841 for(;;) {
2842 c = *p;
2843 if (c >= 'a' && c <= 'f')
2844 c = c - 'a' + 10;
2845 else if (c >= 'A' && c <= 'F')
2846 c = c - 'A' + 10;
2847 else if (isnum(c))
2848 c = c - '0';
2849 else
2850 break;
2851 n = n * 16 + c;
2852 p++;
2854 c = n;
2855 goto add_char_nonext;
2856 case 'a':
2857 c = '\a';
2858 break;
2859 case 'b':
2860 c = '\b';
2861 break;
2862 case 'f':
2863 c = '\f';
2864 break;
2865 case 'n':
2866 c = '\n';
2867 break;
2868 case 'r':
2869 c = '\r';
2870 break;
2871 case 't':
2872 c = '\t';
2873 break;
2874 case 'v':
2875 c = '\v';
2876 break;
2877 case 'e':
2878 if (!gnu_ext)
2879 goto invalid_escape;
2880 c = 27;
2881 break;
2882 case '\'':
2883 case '\"':
2884 case '\\':
2885 case '?':
2886 break;
2887 default:
2888 invalid_escape:
2889 error("invalid escaped char");
2892 p++;
2893 add_char_nonext:
2894 if (!is_long)
2895 cstr_ccat(outstr, c);
2896 else
2897 cstr_wccat(outstr, c);
2899 /* add a trailing '\0' */
2900 if (!is_long)
2901 cstr_ccat(outstr, '\0');
2902 else
2903 cstr_wccat(outstr, '\0');
2906 /* we use 64 bit numbers */
2907 #define BN_SIZE 2
2909 /* bn = (bn << shift) | or_val */
2910 void bn_lshift(unsigned int *bn, int shift, int or_val)
2912 int i;
2913 unsigned int v;
2914 for(i=0;i<BN_SIZE;i++) {
2915 v = bn[i];
2916 bn[i] = (v << shift) | or_val;
2917 or_val = v >> (32 - shift);
2921 void bn_zero(unsigned int *bn)
2923 int i;
2924 for(i=0;i<BN_SIZE;i++) {
2925 bn[i] = 0;
2929 /* parse number in null terminated string 'p' and return it in the
2930 current token */
2931 void parse_number(const char *p)
2933 int b, t, shift, frac_bits, s, exp_val, ch;
2934 char *q;
2935 unsigned int bn[BN_SIZE];
2936 double d;
2938 /* number */
2939 q = token_buf;
2940 ch = *p++;
2941 t = ch;
2942 ch = *p++;
2943 *q++ = t;
2944 b = 10;
2945 if (t == '.') {
2946 goto float_frac_parse;
2947 } else if (t == '0') {
2948 if (ch == 'x' || ch == 'X') {
2949 q--;
2950 ch = *p++;
2951 b = 16;
2952 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2953 q--;
2954 ch = *p++;
2955 b = 2;
2958 /* parse all digits. cannot check octal numbers at this stage
2959 because of floating point constants */
2960 while (1) {
2961 if (ch >= 'a' && ch <= 'f')
2962 t = ch - 'a' + 10;
2963 else if (ch >= 'A' && ch <= 'F')
2964 t = ch - 'A' + 10;
2965 else if (isnum(ch))
2966 t = ch - '0';
2967 else
2968 break;
2969 if (t >= b)
2970 break;
2971 if (q >= token_buf + STRING_MAX_SIZE) {
2972 num_too_long:
2973 error("number too long");
2975 *q++ = ch;
2976 ch = *p++;
2978 if (ch == '.' ||
2979 ((ch == 'e' || ch == 'E') && b == 10) ||
2980 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
2981 if (b != 10) {
2982 /* NOTE: strtox should support that for hexa numbers, but
2983 non ISOC99 libcs do not support it, so we prefer to do
2984 it by hand */
2985 /* hexadecimal or binary floats */
2986 /* XXX: handle overflows */
2987 *q = '\0';
2988 if (b == 16)
2989 shift = 4;
2990 else
2991 shift = 2;
2992 bn_zero(bn);
2993 q = token_buf;
2994 while (1) {
2995 t = *q++;
2996 if (t == '\0') {
2997 break;
2998 } else if (t >= 'a') {
2999 t = t - 'a' + 10;
3000 } else if (t >= 'A') {
3001 t = t - 'A' + 10;
3002 } else {
3003 t = t - '0';
3005 bn_lshift(bn, shift, t);
3007 frac_bits = 0;
3008 if (ch == '.') {
3009 ch = *p++;
3010 while (1) {
3011 t = ch;
3012 if (t >= 'a' && t <= 'f') {
3013 t = t - 'a' + 10;
3014 } else if (t >= 'A' && t <= 'F') {
3015 t = t - 'A' + 10;
3016 } else if (t >= '0' && t <= '9') {
3017 t = t - '0';
3018 } else {
3019 break;
3021 if (t >= b)
3022 error("invalid digit");
3023 bn_lshift(bn, shift, t);
3024 frac_bits += shift;
3025 ch = *p++;
3028 if (ch != 'p' && ch != 'P')
3029 expect("exponent");
3030 ch = *p++;
3031 s = 1;
3032 exp_val = 0;
3033 if (ch == '+') {
3034 ch = *p++;
3035 } else if (ch == '-') {
3036 s = -1;
3037 ch = *p++;
3039 if (ch < '0' || ch > '9')
3040 expect("exponent digits");
3041 while (ch >= '0' && ch <= '9') {
3042 exp_val = exp_val * 10 + ch - '0';
3043 ch = *p++;
3045 exp_val = exp_val * s;
3047 /* now we can generate the number */
3048 /* XXX: should patch directly float number */
3049 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3050 d = ldexp(d, exp_val - frac_bits);
3051 t = toup(ch);
3052 if (t == 'F') {
3053 ch = *p++;
3054 tok = TOK_CFLOAT;
3055 /* float : should handle overflow */
3056 tokc.f = (float)d;
3057 } else if (t == 'L') {
3058 ch = *p++;
3059 tok = TOK_CLDOUBLE;
3060 /* XXX: not large enough */
3061 tokc.ld = (long double)d;
3062 } else {
3063 tok = TOK_CDOUBLE;
3064 tokc.d = d;
3066 } else {
3067 /* decimal floats */
3068 if (ch == '.') {
3069 if (q >= token_buf + STRING_MAX_SIZE)
3070 goto num_too_long;
3071 *q++ = ch;
3072 ch = *p++;
3073 float_frac_parse:
3074 while (ch >= '0' && ch <= '9') {
3075 if (q >= token_buf + STRING_MAX_SIZE)
3076 goto num_too_long;
3077 *q++ = ch;
3078 ch = *p++;
3081 if (ch == 'e' || ch == 'E') {
3082 if (q >= token_buf + STRING_MAX_SIZE)
3083 goto num_too_long;
3084 *q++ = ch;
3085 ch = *p++;
3086 if (ch == '-' || ch == '+') {
3087 if (q >= token_buf + STRING_MAX_SIZE)
3088 goto num_too_long;
3089 *q++ = ch;
3090 ch = *p++;
3092 if (ch < '0' || ch > '9')
3093 expect("exponent digits");
3094 while (ch >= '0' && ch <= '9') {
3095 if (q >= token_buf + STRING_MAX_SIZE)
3096 goto num_too_long;
3097 *q++ = ch;
3098 ch = *p++;
3101 *q = '\0';
3102 t = toup(ch);
3103 errno = 0;
3104 if (t == 'F') {
3105 ch = *p++;
3106 tok = TOK_CFLOAT;
3107 tokc.f = strtof(token_buf, NULL);
3108 } else if (t == 'L') {
3109 ch = *p++;
3110 tok = TOK_CLDOUBLE;
3111 tokc.ld = strtold(token_buf, NULL);
3112 } else {
3113 tok = TOK_CDOUBLE;
3114 tokc.d = strtod(token_buf, NULL);
3117 } else {
3118 unsigned long long n, n1;
3119 int lcount, ucount;
3121 /* integer number */
3122 *q = '\0';
3123 q = token_buf;
3124 if (b == 10 && *q == '0') {
3125 b = 8;
3126 q++;
3128 n = 0;
3129 while(1) {
3130 t = *q++;
3131 /* no need for checks except for base 10 / 8 errors */
3132 if (t == '\0') {
3133 break;
3134 } else if (t >= 'a') {
3135 t = t - 'a' + 10;
3136 } else if (t >= 'A') {
3137 t = t - 'A' + 10;
3138 } else {
3139 t = t - '0';
3140 if (t >= b)
3141 error("invalid digit");
3143 n1 = n;
3144 n = n * b + t;
3145 /* detect overflow */
3146 /* XXX: this test is not reliable */
3147 if (n < n1)
3148 error("integer constant overflow");
3151 /* XXX: not exactly ANSI compliant */
3152 if ((n & 0xffffffff00000000LL) != 0) {
3153 if ((n >> 63) != 0)
3154 tok = TOK_CULLONG;
3155 else
3156 tok = TOK_CLLONG;
3157 } else if (n > 0x7fffffff) {
3158 tok = TOK_CUINT;
3159 } else {
3160 tok = TOK_CINT;
3162 lcount = 0;
3163 ucount = 0;
3164 for(;;) {
3165 t = toup(ch);
3166 if (t == 'L') {
3167 if (lcount >= 2)
3168 error("three 'l's in integer constant");
3169 lcount++;
3170 if (lcount == 2) {
3171 if (tok == TOK_CINT)
3172 tok = TOK_CLLONG;
3173 else if (tok == TOK_CUINT)
3174 tok = TOK_CULLONG;
3176 ch = *p++;
3177 } else if (t == 'U') {
3178 if (ucount >= 1)
3179 error("two 'u's in integer constant");
3180 ucount++;
3181 if (tok == TOK_CINT)
3182 tok = TOK_CUINT;
3183 else if (tok == TOK_CLLONG)
3184 tok = TOK_CULLONG;
3185 ch = *p++;
3186 } else {
3187 break;
3190 if (tok == TOK_CINT || tok == TOK_CUINT)
3191 tokc.ui = n;
3192 else
3193 tokc.ull = n;
3198 #define PARSE2(c1, tok1, c2, tok2) \
3199 case c1: \
3200 PEEKC(c, p); \
3201 if (c == c2) { \
3202 p++; \
3203 tok = tok2; \
3204 } else { \
3205 tok = tok1; \
3207 break;
3209 /* return next token without macro substitution */
3210 static inline void next_nomacro1(void)
3212 int t, c, is_long;
3213 TokenSym *ts;
3214 uint8_t *p, *p1;
3215 unsigned int h;
3217 p = file->buf_ptr;
3218 redo_no_start:
3219 c = *p;
3220 switch(c) {
3221 case ' ':
3222 case '\t':
3223 case '\f':
3224 case '\v':
3225 case '\r':
3226 p++;
3227 goto redo_no_start;
3229 case '\\':
3230 /* first look if it is in fact an end of buffer */
3231 if (p >= file->buf_end) {
3232 file->buf_ptr = p;
3233 handle_eob();
3234 p = file->buf_ptr;
3235 if (p >= file->buf_end)
3236 goto parse_eof;
3237 else
3238 goto redo_no_start;
3239 } else {
3240 file->buf_ptr = p;
3241 ch = *p;
3242 handle_stray();
3243 p = file->buf_ptr;
3244 goto redo_no_start;
3246 parse_eof:
3248 TCCState *s1 = tcc_state;
3249 if (parse_flags & PARSE_FLAG_LINEFEED) {
3250 tok = TOK_LINEFEED;
3251 } else if (s1->include_stack_ptr == s1->include_stack ||
3252 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3253 /* no include left : end of file. */
3254 tok = TOK_EOF;
3255 } else {
3256 /* pop include file */
3258 /* test if previous '#endif' was after a #ifdef at
3259 start of file */
3260 if (tok_flags & TOK_FLAG_ENDIF) {
3261 #ifdef INC_DEBUG
3262 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3263 #endif
3264 add_cached_include(s1, file->inc_type, file->inc_filename,
3265 file->ifndef_macro_saved);
3268 /* add end of include file debug info */
3269 if (do_debug) {
3270 put_stabd(N_EINCL, 0, 0);
3272 /* pop include stack */
3273 tcc_close(file);
3274 s1->include_stack_ptr--;
3275 file = *s1->include_stack_ptr;
3276 p = file->buf_ptr;
3277 goto redo_no_start;
3280 break;
3282 case '\n':
3283 if (parse_flags & PARSE_FLAG_LINEFEED) {
3284 tok = TOK_LINEFEED;
3285 } else {
3286 file->line_num++;
3287 tok_flags |= TOK_FLAG_BOL;
3288 p++;
3289 goto redo_no_start;
3291 break;
3293 case '#':
3294 /* XXX: simplify */
3295 PEEKC(c, p);
3296 if ((tok_flags & TOK_FLAG_BOL) &&
3297 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3298 file->buf_ptr = p;
3299 preprocess(tok_flags & TOK_FLAG_BOF);
3300 p = file->buf_ptr;
3301 goto redo_no_start;
3302 } else {
3303 if (c == '#') {
3304 p++;
3305 tok = TOK_TWOSHARPS;
3306 } else {
3307 tok = '#';
3310 break;
3312 case 'a': case 'b': case 'c': case 'd':
3313 case 'e': case 'f': case 'g': case 'h':
3314 case 'i': case 'j': case 'k': case 'l':
3315 case 'm': case 'n': case 'o': case 'p':
3316 case 'q': case 'r': case 's': case 't':
3317 case 'u': case 'v': case 'w': case 'x':
3318 case 'y': case 'z':
3319 case 'A': case 'B': case 'C': case 'D':
3320 case 'E': case 'F': case 'G': case 'H':
3321 case 'I': case 'J': case 'K':
3322 case 'M': case 'N': case 'O': case 'P':
3323 case 'Q': case 'R': case 'S': case 'T':
3324 case 'U': case 'V': case 'W': case 'X':
3325 case 'Y': case 'Z':
3326 case '_':
3327 parse_ident_fast:
3328 p1 = p;
3329 h = TOK_HASH_INIT;
3330 h = TOK_HASH_FUNC(h, c);
3331 p++;
3332 for(;;) {
3333 c = *p;
3334 if (!isidnum_table[c])
3335 break;
3336 h = TOK_HASH_FUNC(h, c);
3337 p++;
3339 if (c != '\\') {
3340 TokenSym **pts;
3341 int len;
3343 /* fast case : no stray found, so we have the full token
3344 and we have already hashed it */
3345 len = p - p1;
3346 h &= (TOK_HASH_SIZE - 1);
3347 pts = &hash_ident[h];
3348 for(;;) {
3349 ts = *pts;
3350 if (!ts)
3351 break;
3352 if (ts->len == len && !memcmp(ts->str, p1, len))
3353 goto token_found;
3354 pts = &(ts->hash_next);
3356 ts = tok_alloc_new(pts, p1, len);
3357 token_found: ;
3358 } else {
3359 /* slower case */
3360 cstr_reset(&tokcstr);
3362 while (p1 < p) {
3363 cstr_ccat(&tokcstr, *p1);
3364 p1++;
3366 p--;
3367 PEEKC(c, p);
3368 parse_ident_slow:
3369 while (isidnum_table[c]) {
3370 cstr_ccat(&tokcstr, c);
3371 PEEKC(c, p);
3373 ts = tok_alloc(tokcstr.data, tokcstr.size);
3375 tok = ts->tok;
3376 break;
3377 case 'L':
3378 t = p[1];
3379 if (t != '\\' && t != '\'' && t != '\"') {
3380 /* fast case */
3381 goto parse_ident_fast;
3382 } else {
3383 PEEKC(c, p);
3384 if (c == '\'' || c == '\"') {
3385 is_long = 1;
3386 goto str_const;
3387 } else {
3388 cstr_reset(&tokcstr);
3389 cstr_ccat(&tokcstr, 'L');
3390 goto parse_ident_slow;
3393 break;
3394 case '0': case '1': case '2': case '3':
3395 case '4': case '5': case '6': case '7':
3396 case '8': case '9':
3398 cstr_reset(&tokcstr);
3399 /* after the first digit, accept digits, alpha, '.' or sign if
3400 prefixed by 'eEpP' */
3401 parse_num:
3402 for(;;) {
3403 t = c;
3404 cstr_ccat(&tokcstr, c);
3405 PEEKC(c, p);
3406 if (!(isnum(c) || isid(c) || c == '.' ||
3407 ((c == '+' || c == '-') &&
3408 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3409 break;
3411 /* We add a trailing '\0' to ease parsing */
3412 cstr_ccat(&tokcstr, '\0');
3413 tokc.cstr = &tokcstr;
3414 tok = TOK_PPNUM;
3415 break;
3416 case '.':
3417 /* special dot handling because it can also start a number */
3418 PEEKC(c, p);
3419 if (isnum(c)) {
3420 cstr_reset(&tokcstr);
3421 cstr_ccat(&tokcstr, '.');
3422 goto parse_num;
3423 } else if (c == '.') {
3424 PEEKC(c, p);
3425 if (c != '.')
3426 expect("'.'");
3427 PEEKC(c, p);
3428 tok = TOK_DOTS;
3429 } else {
3430 tok = '.';
3432 break;
3433 case '\'':
3434 case '\"':
3435 is_long = 0;
3436 str_const:
3438 CString str;
3439 int sep;
3441 sep = c;
3443 /* parse the string */
3444 cstr_new(&str);
3445 p = parse_pp_string(p, sep, &str);
3446 cstr_ccat(&str, '\0');
3448 /* eval the escape (should be done as TOK_PPNUM) */
3449 cstr_reset(&tokcstr);
3450 parse_escape_string(&tokcstr, str.data, is_long);
3451 cstr_free(&str);
3453 if (sep == '\'') {
3454 int char_size;
3455 /* XXX: make it portable */
3456 if (!is_long)
3457 char_size = 1;
3458 else
3459 char_size = sizeof(int);
3460 if (tokcstr.size <= char_size)
3461 error("empty character constant");
3462 if (tokcstr.size > 2 * char_size)
3463 warning("multi-character character constant");
3464 if (!is_long) {
3465 tokc.i = *(int8_t *)tokcstr.data;
3466 tok = TOK_CCHAR;
3467 } else {
3468 tokc.i = *(int *)tokcstr.data;
3469 tok = TOK_LCHAR;
3471 } else {
3472 tokc.cstr = &tokcstr;
3473 if (!is_long)
3474 tok = TOK_STR;
3475 else
3476 tok = TOK_LSTR;
3479 break;
3481 case '<':
3482 PEEKC(c, p);
3483 if (c == '=') {
3484 p++;
3485 tok = TOK_LE;
3486 } else if (c == '<') {
3487 PEEKC(c, p);
3488 if (c == '=') {
3489 p++;
3490 tok = TOK_A_SHL;
3491 } else {
3492 tok = TOK_SHL;
3494 } else {
3495 tok = TOK_LT;
3497 break;
3499 case '>':
3500 PEEKC(c, p);
3501 if (c == '=') {
3502 p++;
3503 tok = TOK_GE;
3504 } else if (c == '>') {
3505 PEEKC(c, p);
3506 if (c == '=') {
3507 p++;
3508 tok = TOK_A_SAR;
3509 } else {
3510 tok = TOK_SAR;
3512 } else {
3513 tok = TOK_GT;
3515 break;
3517 case '&':
3518 PEEKC(c, p);
3519 if (c == '&') {
3520 p++;
3521 tok = TOK_LAND;
3522 } else if (c == '=') {
3523 p++;
3524 tok = TOK_A_AND;
3525 } else {
3526 tok = '&';
3528 break;
3530 case '|':
3531 PEEKC(c, p);
3532 if (c == '|') {
3533 p++;
3534 tok = TOK_LOR;
3535 } else if (c == '=') {
3536 p++;
3537 tok = TOK_A_OR;
3538 } else {
3539 tok = '|';
3541 break;
3543 case '+':
3544 PEEKC(c, p);
3545 if (c == '+') {
3546 p++;
3547 tok = TOK_INC;
3548 } else if (c == '=') {
3549 p++;
3550 tok = TOK_A_ADD;
3551 } else {
3552 tok = '+';
3554 break;
3556 case '-':
3557 PEEKC(c, p);
3558 if (c == '-') {
3559 p++;
3560 tok = TOK_DEC;
3561 } else if (c == '=') {
3562 p++;
3563 tok = TOK_A_SUB;
3564 } else if (c == '>') {
3565 p++;
3566 tok = TOK_ARROW;
3567 } else {
3568 tok = '-';
3570 break;
3572 PARSE2('!', '!', '=', TOK_NE)
3573 PARSE2('=', '=', '=', TOK_EQ)
3574 PARSE2('*', '*', '=', TOK_A_MUL)
3575 PARSE2('%', '%', '=', TOK_A_MOD)
3576 PARSE2('^', '^', '=', TOK_A_XOR)
3578 /* comments or operator */
3579 case '/':
3580 PEEKC(c, p);
3581 if (c == '*') {
3582 p = parse_comment(p);
3583 goto redo_no_start;
3584 } else if (c == '/') {
3585 p = parse_line_comment(p);
3586 goto redo_no_start;
3587 } else if (c == '=') {
3588 p++;
3589 tok = TOK_A_DIV;
3590 } else {
3591 tok = '/';
3593 break;
3595 /* simple tokens */
3596 case '(':
3597 case ')':
3598 case '[':
3599 case ']':
3600 case '{':
3601 case '}':
3602 case ',':
3603 case ';':
3604 case ':':
3605 case '?':
3606 case '~':
3607 case '$': /* only used in assembler */
3608 tok = c;
3609 p++;
3610 break;
3611 default:
3612 error("unrecognized character \\x%02x", c);
3613 break;
3615 file->buf_ptr = p;
3616 tok_flags = 0;
3617 #if defined(PARSE_DEBUG)
3618 printf("token = %s\n", get_tok_str(tok, &tokc));
3619 #endif
3622 /* return next token without macro substitution. Can read input from
3623 macro_ptr buffer */
3624 static void next_nomacro(void)
3626 if (macro_ptr) {
3627 redo:
3628 tok = *macro_ptr;
3629 if (tok) {
3630 TOK_GET(tok, macro_ptr, tokc);
3631 if (tok == TOK_LINENUM) {
3632 file->line_num = tokc.i;
3633 goto redo;
3636 } else {
3637 next_nomacro1();
3641 /* substitute args in macro_str and return allocated string */
3642 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3644 int *st, last_tok, t, notfirst;
3645 Sym *s;
3646 CValue cval;
3647 TokenString str;
3648 CString cstr;
3650 tok_str_new(&str);
3651 last_tok = 0;
3652 while(1) {
3653 TOK_GET(t, macro_str, cval);
3654 if (!t)
3655 break;
3656 if (t == '#') {
3657 /* stringize */
3658 TOK_GET(t, macro_str, cval);
3659 if (!t)
3660 break;
3661 s = sym_find2(args, t);
3662 if (s) {
3663 cstr_new(&cstr);
3664 st = (int *)s->c;
3665 notfirst = 0;
3666 while (*st) {
3667 if (notfirst)
3668 cstr_ccat(&cstr, ' ');
3669 TOK_GET(t, st, cval);
3670 cstr_cat(&cstr, get_tok_str(t, &cval));
3671 notfirst = 1;
3673 cstr_ccat(&cstr, '\0');
3674 #ifdef PP_DEBUG
3675 printf("stringize: %s\n", (char *)cstr.data);
3676 #endif
3677 /* add string */
3678 cval.cstr = &cstr;
3679 tok_str_add2(&str, TOK_STR, &cval);
3680 cstr_free(&cstr);
3681 } else {
3682 tok_str_add2(&str, t, &cval);
3684 } else if (t >= TOK_IDENT) {
3685 s = sym_find2(args, t);
3686 if (s) {
3687 st = (int *)s->c;
3688 /* if '##' is present before or after, no arg substitution */
3689 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3690 /* special case for var arg macros : ## eats the
3691 ',' if empty VA_ARGS variable. */
3692 /* XXX: test of the ',' is not 100%
3693 reliable. should fix it to avoid security
3694 problems */
3695 if (gnu_ext && s->type.t &&
3696 last_tok == TOK_TWOSHARPS &&
3697 str.len >= 2 && str.str[str.len - 2] == ',') {
3698 if (*st == 0) {
3699 /* suppress ',' '##' */
3700 str.len -= 2;
3701 } else {
3702 /* suppress '##' and add variable */
3703 str.len--;
3704 goto add_var;
3706 } else {
3707 int t1;
3708 add_var:
3709 for(;;) {
3710 TOK_GET(t1, st, cval);
3711 if (!t1)
3712 break;
3713 tok_str_add2(&str, t1, &cval);
3716 } else {
3717 /* NOTE: the stream cannot be read when macro
3718 substituing an argument */
3719 macro_subst(&str, nested_list, st, 0);
3721 } else {
3722 tok_str_add(&str, t);
3724 } else {
3725 tok_str_add2(&str, t, &cval);
3727 last_tok = t;
3729 tok_str_add(&str, 0);
3730 return str.str;
3733 static char const ab_month_name[12][4] =
3735 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3736 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3739 /* do macro substitution of current token with macro 's' and add
3740 result to (tok_str,tok_len). 'nested_list' is the list of all
3741 macros we got inside to avoid recursing. Return non zero if no
3742 substitution needs to be done */
3743 static int macro_subst_tok(TokenString *tok_str,
3744 Sym **nested_list, Sym *s, int can_read_stream)
3746 Sym *args, *sa, *sa1;
3747 int mstr_allocated, parlevel, *mstr, t;
3748 TokenString str;
3749 char *cstrval;
3750 CValue cval;
3751 CString cstr;
3753 /* if symbol is a macro, prepare substitution */
3755 /* special macros */
3756 if (tok == TOK___LINE__) {
3757 cval.i = file->line_num;
3758 tok_str_add2(tok_str, TOK_CINT, &cval);
3759 } else if (tok == TOK___FILE__) {
3760 cstrval = file->filename;
3761 goto add_cstr;
3762 tok_str_add2(tok_str, TOK_STR, &cval);
3763 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3764 time_t ti;
3765 struct tm *tm;
3766 char buf[64];
3768 time(&ti);
3769 tm = localtime(&ti);
3770 if (tok == TOK___DATE__) {
3771 snprintf(buf, sizeof(buf), "%s %2d %d",
3772 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3773 } else {
3774 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3775 tm->tm_hour, tm->tm_min, tm->tm_sec);
3777 cstrval = buf;
3778 add_cstr:
3779 cstr_new(&cstr);
3780 cstr_cat(&cstr, cstrval);
3781 cstr_ccat(&cstr, '\0');
3782 cval.cstr = &cstr;
3783 tok_str_add2(tok_str, TOK_STR, &cval);
3784 cstr_free(&cstr);
3785 } else {
3786 mstr = (int *)s->c;
3787 mstr_allocated = 0;
3788 if (s->type.t == MACRO_FUNC) {
3789 /* NOTE: we do not use next_nomacro to avoid eating the
3790 next token. XXX: find better solution */
3791 if (macro_ptr) {
3792 t = *macro_ptr;
3793 if (t == 0 && can_read_stream) {
3794 /* end of macro stream: we must look at the token
3795 after in the file */
3796 macro_ptr = NULL;
3797 goto parse_stream;
3799 } else {
3800 parse_stream:
3801 /* XXX: incorrect with comments */
3802 ch = file->buf_ptr[0];
3803 while (is_space(ch) || ch == '\n')
3804 cinp();
3805 t = ch;
3807 if (t != '(') /* no macro subst */
3808 return -1;
3810 /* argument macro */
3811 next_nomacro();
3812 next_nomacro();
3813 args = NULL;
3814 sa = s->next;
3815 /* NOTE: empty args are allowed, except if no args */
3816 for(;;) {
3817 /* handle '()' case */
3818 if (!args && !sa && tok == ')')
3819 break;
3820 if (!sa)
3821 error("macro '%s' used with too many args",
3822 get_tok_str(s->v, 0));
3823 tok_str_new(&str);
3824 parlevel = 0;
3825 /* NOTE: non zero sa->t indicates VA_ARGS */
3826 while ((parlevel > 0 ||
3827 (tok != ')' &&
3828 (tok != ',' || sa->type.t))) &&
3829 tok != -1) {
3830 if (tok == '(')
3831 parlevel++;
3832 else if (tok == ')')
3833 parlevel--;
3834 tok_str_add2(&str, tok, &tokc);
3835 next_nomacro();
3837 tok_str_add(&str, 0);
3838 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3839 sa = sa->next;
3840 if (tok == ')') {
3841 /* special case for gcc var args: add an empty
3842 var arg argument if it is omitted */
3843 if (sa && sa->type.t && gnu_ext)
3844 continue;
3845 else
3846 break;
3848 if (tok != ',')
3849 expect(",");
3850 next_nomacro();
3852 if (sa) {
3853 error("macro '%s' used with too few args",
3854 get_tok_str(s->v, 0));
3857 /* now subst each arg */
3858 mstr = macro_arg_subst(nested_list, mstr, args);
3859 /* free memory */
3860 sa = args;
3861 while (sa) {
3862 sa1 = sa->prev;
3863 tok_str_free((int *)sa->c);
3864 tcc_free(sa);
3865 sa = sa1;
3867 mstr_allocated = 1;
3869 sym_push2(nested_list, s->v, 0, 0);
3870 macro_subst(tok_str, nested_list, mstr, 1);
3871 /* pop nested defined symbol */
3872 sa1 = *nested_list;
3873 *nested_list = sa1->prev;
3874 tcc_free(sa1);
3875 if (mstr_allocated)
3876 tok_str_free(mstr);
3878 return 0;
3881 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3882 return the resulting string (which must be freed). */
3883 static inline int *macro_twosharps(const int *macro_str)
3885 TokenSym *ts;
3886 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3887 int t;
3888 const char *p1, *p2;
3889 CValue cval;
3890 TokenString macro_str1;
3891 CString cstr;
3893 start_macro_ptr = macro_str;
3894 /* we search the first '##' */
3895 for(;;) {
3896 macro_ptr1 = macro_str;
3897 TOK_GET(t, macro_str, cval);
3898 /* nothing more to do if end of string */
3899 if (t == 0)
3900 return NULL;
3901 if (*macro_str == TOK_TWOSHARPS)
3902 break;
3905 /* we saw '##', so we need more processing to handle it */
3906 cstr_new(&cstr);
3907 tok_str_new(&macro_str1);
3908 tok = t;
3909 tokc = cval;
3911 /* add all tokens seen so far */
3912 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
3913 TOK_GET(t, ptr, cval);
3914 tok_str_add2(&macro_str1, t, &cval);
3916 saved_macro_ptr = macro_ptr;
3917 /* XXX: get rid of the use of macro_ptr here */
3918 macro_ptr = (int *)macro_str;
3919 for(;;) {
3920 while (*macro_ptr == TOK_TWOSHARPS) {
3921 macro_ptr++;
3922 macro_ptr1 = macro_ptr;
3923 t = *macro_ptr;
3924 if (t) {
3925 TOK_GET(t, macro_ptr, cval);
3926 /* We concatenate the two tokens if we have an
3927 identifier or a preprocessing number */
3928 cstr_reset(&cstr);
3929 p1 = get_tok_str(tok, &tokc);
3930 cstr_cat(&cstr, p1);
3931 p2 = get_tok_str(t, &cval);
3932 cstr_cat(&cstr, p2);
3933 cstr_ccat(&cstr, '\0');
3935 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3936 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3937 if (tok == TOK_PPNUM) {
3938 /* if number, then create a number token */
3939 /* NOTE: no need to allocate because
3940 tok_str_add2() does it */
3941 tokc.cstr = &cstr;
3942 } else {
3943 /* if identifier, we must do a test to
3944 validate we have a correct identifier */
3945 if (t == TOK_PPNUM) {
3946 const char *p;
3947 int c;
3949 p = p2;
3950 for(;;) {
3951 c = *p;
3952 if (c == '\0')
3953 break;
3954 p++;
3955 if (!isnum(c) && !isid(c))
3956 goto error_pasting;
3959 ts = tok_alloc(cstr.data, strlen(cstr.data));
3960 tok = ts->tok; /* modify current token */
3962 } else {
3963 const char *str = cstr.data;
3964 const unsigned char *q;
3966 /* we look for a valid token */
3967 /* XXX: do more extensive checks */
3968 if (!strcmp(str, ">>=")) {
3969 tok = TOK_A_SAR;
3970 } else if (!strcmp(str, "<<=")) {
3971 tok = TOK_A_SHL;
3972 } else if (strlen(str) == 2) {
3973 /* search in two bytes table */
3974 q = tok_two_chars;
3975 for(;;) {
3976 if (!*q)
3977 goto error_pasting;
3978 if (q[0] == str[0] && q[1] == str[1])
3979 break;
3980 q += 3;
3982 tok = q[2];
3983 } else {
3984 error_pasting:
3985 /* NOTE: because get_tok_str use a static buffer,
3986 we must save it */
3987 cstr_reset(&cstr);
3988 p1 = get_tok_str(tok, &tokc);
3989 cstr_cat(&cstr, p1);
3990 cstr_ccat(&cstr, '\0');
3991 p2 = get_tok_str(t, &cval);
3992 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
3993 /* cannot merge tokens: just add them separately */
3994 tok_str_add2(&macro_str1, tok, &tokc);
3995 /* XXX: free associated memory ? */
3996 tok = t;
3997 tokc = cval;
4002 tok_str_add2(&macro_str1, tok, &tokc);
4003 next_nomacro();
4004 if (tok == 0)
4005 break;
4007 macro_ptr = (int *)saved_macro_ptr;
4008 cstr_free(&cstr);
4009 tok_str_add(&macro_str1, 0);
4010 return macro_str1.str;
4014 /* do macro substitution of macro_str and add result to
4015 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4016 inside to avoid recursing. */
4017 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4018 const int *macro_str, int can_read_stream)
4020 Sym *s;
4021 int *saved_macro_ptr, *macro_str1;
4022 const int *ptr;
4023 int t, ret;
4024 CValue cval;
4026 /* first scan for '##' operator handling */
4027 ptr = macro_str;
4028 macro_str1 = macro_twosharps(ptr);
4029 if (macro_str1)
4030 ptr = macro_str1;
4031 while (1) {
4032 /* NOTE: ptr == NULL can only happen if tokens are read from
4033 file stream due to a macro function call */
4034 if (ptr == NULL)
4035 break;
4036 TOK_GET(t, ptr, cval);
4037 if (t == 0)
4038 break;
4039 s = define_find(t);
4040 if (s != NULL) {
4041 /* if nested substitution, do nothing */
4042 if (sym_find2(*nested_list, t))
4043 goto no_subst;
4044 saved_macro_ptr = macro_ptr;
4045 macro_ptr = (int *)ptr;
4046 tok = t;
4047 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4048 ptr = (int *)macro_ptr;
4049 macro_ptr = saved_macro_ptr;
4050 if (ret != 0)
4051 goto no_subst;
4052 } else {
4053 no_subst:
4054 tok_str_add2(tok_str, t, &cval);
4057 if (macro_str1)
4058 tok_str_free(macro_str1);
4061 /* return next token with macro substitution */
4062 static void next(void)
4064 Sym *nested_list, *s;
4065 TokenString str;
4067 redo:
4068 next_nomacro();
4069 if (!macro_ptr) {
4070 /* if not reading from macro substituted string, then try
4071 to substitute macros */
4072 if (tok >= TOK_IDENT &&
4073 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4074 s = define_find(tok);
4075 if (s) {
4076 /* we have a macro: we try to substitute */
4077 tok_str_new(&str);
4078 nested_list = NULL;
4079 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4080 /* substitution done, NOTE: maybe empty */
4081 tok_str_add(&str, 0);
4082 macro_ptr = str.str;
4083 macro_ptr_allocated = str.str;
4084 goto redo;
4088 } else {
4089 if (tok == 0) {
4090 /* end of macro or end of unget buffer */
4091 if (unget_buffer_enabled) {
4092 macro_ptr = unget_saved_macro_ptr;
4093 unget_buffer_enabled = 0;
4094 } else {
4095 /* end of macro string: free it */
4096 tok_str_free(macro_ptr_allocated);
4097 macro_ptr = NULL;
4099 goto redo;
4103 /* convert preprocessor tokens into C tokens */
4104 if (tok == TOK_PPNUM &&
4105 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4106 parse_number((char *)tokc.cstr->data);
4110 /* push back current token and set current token to 'last_tok'. Only
4111 identifier case handled for labels. */
4112 static inline void unget_tok(int last_tok)
4114 int i, n;
4115 int *q;
4116 unget_saved_macro_ptr = macro_ptr;
4117 unget_buffer_enabled = 1;
4118 q = unget_saved_buffer;
4119 macro_ptr = q;
4120 *q++ = tok;
4121 n = tok_ext_size(tok) - 1;
4122 for(i=0;i<n;i++)
4123 *q++ = tokc.tab[i];
4124 *q = 0; /* end of token string */
4125 tok = last_tok;
4129 void swap(int *p, int *q)
4131 int t;
4132 t = *p;
4133 *p = *q;
4134 *q = t;
4137 void vsetc(CType *type, int r, CValue *vc)
4139 int v;
4141 if (vtop >= vstack + VSTACK_SIZE)
4142 error("memory full");
4143 /* cannot let cpu flags if other instruction are generated. Also
4144 avoid leaving VT_JMP anywhere except on the top of the stack
4145 because it would complicate the code generator. */
4146 if (vtop >= vstack) {
4147 v = vtop->r & VT_VALMASK;
4148 if (v == VT_CMP || (v & ~1) == VT_JMP)
4149 gv(RC_INT);
4151 vtop++;
4152 vtop->type = *type;
4153 vtop->r = r;
4154 vtop->r2 = VT_CONST;
4155 vtop->c = *vc;
4158 /* push integer constant */
4159 void vpushi(int v)
4161 CValue cval;
4162 cval.i = v;
4163 vsetc(&int_type, VT_CONST, &cval);
4166 /* Return a static symbol pointing to a section */
4167 static Sym *get_sym_ref(CType *type, Section *sec,
4168 unsigned long offset, unsigned long size)
4170 int v;
4171 Sym *sym;
4173 v = anon_sym++;
4174 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4175 sym->type.ref = type->ref;
4176 sym->r = VT_CONST | VT_SYM;
4177 put_extern_sym(sym, sec, offset, size);
4178 return sym;
4181 /* push a reference to a section offset by adding a dummy symbol */
4182 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4184 CValue cval;
4186 cval.ul = 0;
4187 vsetc(type, VT_CONST | VT_SYM, &cval);
4188 vtop->sym = get_sym_ref(type, sec, offset, size);
4191 /* define a new external reference to a symbol 'v' of type 'u' */
4192 static Sym *external_global_sym(int v, CType *type, int r)
4194 Sym *s;
4196 s = sym_find(v);
4197 if (!s) {
4198 /* push forward reference */
4199 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4200 s->type.ref = type->ref;
4201 s->r = r | VT_CONST | VT_SYM;
4203 return s;
4206 /* define a new external reference to a symbol 'v' of type 'u' */
4207 static Sym *external_sym(int v, CType *type, int r)
4209 Sym *s;
4211 s = sym_find(v);
4212 if (!s) {
4213 /* push forward reference */
4214 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4215 s->type.t |= VT_EXTERN;
4216 } else {
4217 if (!is_compatible_types(&s->type, type))
4218 error("incompatible types for redefinition of '%s'",
4219 get_tok_str(v, NULL));
4221 return s;
4224 /* push a reference to global symbol v */
4225 static void vpush_global_sym(CType *type, int v)
4227 Sym *sym;
4228 CValue cval;
4230 sym = external_global_sym(v, type, 0);
4231 cval.ul = 0;
4232 vsetc(type, VT_CONST | VT_SYM, &cval);
4233 vtop->sym = sym;
4236 void vset(CType *type, int r, int v)
4238 CValue cval;
4240 cval.i = v;
4241 vsetc(type, r, &cval);
4244 void vseti(int r, int v)
4246 CType type;
4247 type.t = VT_INT;
4248 vset(&type, r, v);
4251 void vswap(void)
4253 SValue tmp;
4255 tmp = vtop[0];
4256 vtop[0] = vtop[-1];
4257 vtop[-1] = tmp;
4260 void vpushv(SValue *v)
4262 if (vtop >= vstack + VSTACK_SIZE)
4263 error("memory full");
4264 vtop++;
4265 *vtop = *v;
4268 void vdup(void)
4270 vpushv(vtop);
4273 /* save r to the memory stack, and mark it as being free */
4274 void save_reg(int r)
4276 int l, saved, size, align;
4277 SValue *p, sv;
4278 CType *type;
4280 /* modify all stack values */
4281 saved = 0;
4282 l = 0;
4283 for(p=vstack;p<=vtop;p++) {
4284 if ((p->r & VT_VALMASK) == r ||
4285 (p->r2 & VT_VALMASK) == r) {
4286 /* must save value on stack if not already done */
4287 if (!saved) {
4288 /* NOTE: must reload 'r' because r might be equal to r2 */
4289 r = p->r & VT_VALMASK;
4290 /* store register in the stack */
4291 type = &p->type;
4292 if ((p->r & VT_LVAL) ||
4293 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4294 type = &int_type;
4295 size = type_size(type, &align);
4296 loc = (loc - size) & -align;
4297 sv.type.t = type->t;
4298 sv.r = VT_LOCAL | VT_LVAL;
4299 sv.c.ul = loc;
4300 store(r, &sv);
4301 #ifdef TCC_TARGET_I386
4302 /* x86 specific: need to pop fp register ST0 if saved */
4303 if (r == TREG_ST0) {
4304 o(0xd9dd); /* fstp %st(1) */
4306 #endif
4307 /* special long long case */
4308 if ((type->t & VT_BTYPE) == VT_LLONG) {
4309 sv.c.ul += 4;
4310 store(p->r2, &sv);
4312 l = loc;
4313 saved = 1;
4315 /* mark that stack entry as being saved on the stack */
4316 if (p->r & VT_LVAL) {
4317 /* also clear the bounded flag because the
4318 relocation address of the function was stored in
4319 p->c.ul */
4320 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4321 } else {
4322 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4324 p->r2 = VT_CONST;
4325 p->c.ul = l;
4330 /* find a free register of class 'rc'. If none, save one register */
4331 int get_reg(int rc)
4333 int r;
4334 SValue *p;
4336 /* find a free register */
4337 for(r=0;r<NB_REGS;r++) {
4338 if (reg_classes[r] & rc) {
4339 for(p=vstack;p<=vtop;p++) {
4340 if ((p->r & VT_VALMASK) == r ||
4341 (p->r2 & VT_VALMASK) == r)
4342 goto notfound;
4344 return r;
4346 notfound: ;
4349 /* no register left : free the first one on the stack (VERY
4350 IMPORTANT to start from the bottom to ensure that we don't
4351 spill registers used in gen_opi()) */
4352 for(p=vstack;p<=vtop;p++) {
4353 r = p->r & VT_VALMASK;
4354 if (r < VT_CONST && (reg_classes[r] & rc))
4355 goto save_found;
4356 /* also look at second register (if long long) */
4357 r = p->r2 & VT_VALMASK;
4358 if (r < VT_CONST && (reg_classes[r] & rc)) {
4359 save_found:
4360 save_reg(r);
4361 return r;
4364 /* Should never comes here */
4365 return -1;
4368 /* save registers up to (vtop - n) stack entry */
4369 void save_regs(int n)
4371 int r;
4372 SValue *p, *p1;
4373 p1 = vtop - n;
4374 for(p = vstack;p <= p1; p++) {
4375 r = p->r & VT_VALMASK;
4376 if (r < VT_CONST) {
4377 save_reg(r);
4382 /* move register 's' to 'r', and flush previous value of r to memory
4383 if needed */
4384 void move_reg(int r, int s)
4386 SValue sv;
4388 if (r != s) {
4389 save_reg(r);
4390 sv.type.t = VT_INT;
4391 sv.r = s;
4392 sv.c.ul = 0;
4393 load(r, &sv);
4397 /* get address of vtop (vtop MUST BE an lvalue) */
4398 void gaddrof(void)
4400 vtop->r &= ~VT_LVAL;
4401 /* tricky: if saved lvalue, then we can go back to lvalue */
4402 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4403 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4406 #ifdef CONFIG_TCC_BCHECK
4407 /* generate lvalue bound code */
4408 void gbound(void)
4410 int lval_type;
4411 CType type1;
4413 vtop->r &= ~VT_MUSTBOUND;
4414 /* if lvalue, then use checking code before dereferencing */
4415 if (vtop->r & VT_LVAL) {
4416 /* if not VT_BOUNDED value, then make one */
4417 if (!(vtop->r & VT_BOUNDED)) {
4418 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4419 /* must save type because we must set it to int to get pointer */
4420 type1 = vtop->type;
4421 vtop->type.t = VT_INT;
4422 gaddrof();
4423 vpushi(0);
4424 gen_bounded_ptr_add();
4425 vtop->r |= lval_type;
4426 vtop->type = type1;
4428 /* then check for dereferencing */
4429 gen_bounded_ptr_deref();
4432 #endif
4434 /* store vtop a register belonging to class 'rc'. lvalues are
4435 converted to values. Cannot be used if cannot be converted to
4436 register value (such as structures). */
4437 int gv(int rc)
4439 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4440 unsigned long long ll;
4442 /* NOTE: get_reg can modify vstack[] */
4443 if (vtop->type.t & VT_BITFIELD) {
4444 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4445 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4446 /* remove bit field info to avoid loops */
4447 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4448 /* generate shifts */
4449 vpushi(32 - (bit_pos + bit_size));
4450 gen_op(TOK_SHL);
4451 vpushi(32 - bit_size);
4452 /* NOTE: transformed to SHR if unsigned */
4453 gen_op(TOK_SAR);
4454 r = gv(rc);
4455 } else {
4456 if (is_float(vtop->type.t) &&
4457 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4458 Sym *sym;
4459 int *ptr;
4460 unsigned long offset;
4462 /* XXX: unify with initializers handling ? */
4463 /* CPUs usually cannot use float constants, so we store them
4464 generically in data segment */
4465 size = type_size(&vtop->type, &align);
4466 offset = (data_section->data_offset + align - 1) & -align;
4467 data_section->data_offset = offset;
4468 /* XXX: not portable yet */
4469 ptr = section_ptr_add(data_section, size);
4470 size = size >> 2;
4471 for(i=0;i<size;i++)
4472 ptr[i] = vtop->c.tab[i];
4473 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4474 vtop->r |= VT_LVAL | VT_SYM;
4475 vtop->sym = sym;
4476 vtop->c.ul = 0;
4478 #ifdef CONFIG_TCC_BCHECK
4479 if (vtop->r & VT_MUSTBOUND)
4480 gbound();
4481 #endif
4483 r = vtop->r & VT_VALMASK;
4484 /* need to reload if:
4485 - constant
4486 - lvalue (need to dereference pointer)
4487 - already a register, but not in the right class */
4488 if (r >= VT_CONST ||
4489 (vtop->r & VT_LVAL) ||
4490 !(reg_classes[r] & rc) ||
4491 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4492 !(reg_classes[vtop->r2] & rc))) {
4493 r = get_reg(rc);
4494 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4495 /* two register type load : expand to two words
4496 temporarily */
4497 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4498 /* load constant */
4499 ll = vtop->c.ull;
4500 vtop->c.ui = ll; /* first word */
4501 load(r, vtop);
4502 vtop->r = r; /* save register value */
4503 vpushi(ll >> 32); /* second word */
4504 } else if (r >= VT_CONST ||
4505 (vtop->r & VT_LVAL)) {
4506 /* load from memory */
4507 load(r, vtop);
4508 vdup();
4509 vtop[-1].r = r; /* save register value */
4510 /* increment pointer to get second word */
4511 vtop->type.t = VT_INT;
4512 gaddrof();
4513 vpushi(4);
4514 gen_op('+');
4515 vtop->r |= VT_LVAL;
4516 } else {
4517 /* move registers */
4518 load(r, vtop);
4519 vdup();
4520 vtop[-1].r = r; /* save register value */
4521 vtop->r = vtop[-1].r2;
4523 /* allocate second register */
4524 rc2 = RC_INT;
4525 if (rc == RC_IRET)
4526 rc2 = RC_LRET;
4527 r2 = get_reg(rc2);
4528 load(r2, vtop);
4529 vpop();
4530 /* write second register */
4531 vtop->r2 = r2;
4532 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4533 int t1, t;
4534 /* lvalue of scalar type : need to use lvalue type
4535 because of possible cast */
4536 t = vtop->type.t;
4537 t1 = t;
4538 /* compute memory access type */
4539 if (vtop->r & VT_LVAL_BYTE)
4540 t = VT_BYTE;
4541 else if (vtop->r & VT_LVAL_SHORT)
4542 t = VT_SHORT;
4543 if (vtop->r & VT_LVAL_UNSIGNED)
4544 t |= VT_UNSIGNED;
4545 vtop->type.t = t;
4546 load(r, vtop);
4547 /* restore wanted type */
4548 vtop->type.t = t1;
4549 } else {
4550 /* one register type load */
4551 load(r, vtop);
4554 vtop->r = r;
4556 return r;
4559 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4560 void gv2(int rc1, int rc2)
4562 int v;
4564 /* generate more generic register first. But VT_JMP or VT_CMP
4565 values must be generated first in all cases to avoid possible
4566 reload errors */
4567 v = vtop[0].r & VT_VALMASK;
4568 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4569 vswap();
4570 gv(rc1);
4571 vswap();
4572 gv(rc2);
4573 /* test if reload is needed for first register */
4574 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4575 vswap();
4576 gv(rc1);
4577 vswap();
4579 } else {
4580 gv(rc2);
4581 vswap();
4582 gv(rc1);
4583 vswap();
4584 /* test if reload is needed for first register */
4585 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4586 gv(rc2);
4591 /* expand long long on stack in two int registers */
4592 void lexpand(void)
4594 int u;
4596 u = vtop->type.t & VT_UNSIGNED;
4597 gv(RC_INT);
4598 vdup();
4599 vtop[0].r = vtop[-1].r2;
4600 vtop[0].r2 = VT_CONST;
4601 vtop[-1].r2 = VT_CONST;
4602 vtop[0].type.t = VT_INT | u;
4603 vtop[-1].type.t = VT_INT | u;
4606 /* build a long long from two ints */
4607 void lbuild(int t)
4609 gv2(RC_INT, RC_INT);
4610 vtop[-1].r2 = vtop[0].r;
4611 vtop[-1].type.t = t;
4612 vpop();
4615 /* rotate n first stack elements to the bottom
4616 I1 ... In -> I2 ... In I1 [top is right]
4618 void vrotb(int n)
4620 int i;
4621 SValue tmp;
4623 tmp = vtop[-n + 1];
4624 for(i=-n+1;i!=0;i++)
4625 vtop[i] = vtop[i+1];
4626 vtop[0] = tmp;
4629 /* rotate n first stack elements to the top
4630 I1 ... In -> In I1 ... I(n-1) [top is right]
4632 void vrott(int n)
4634 int i;
4635 SValue tmp;
4637 tmp = vtop[0];
4638 for(i = 0;i < n - 1; i++)
4639 vtop[-i] = vtop[-i - 1];
4640 vtop[-n + 1] = tmp;
4643 /* pop stack value */
4644 void vpop(void)
4646 int v;
4647 v = vtop->r & VT_VALMASK;
4648 #ifdef TCC_TARGET_I386
4649 /* for x86, we need to pop the FP stack */
4650 if (v == TREG_ST0 && !nocode_wanted) {
4651 o(0xd9dd); /* fstp %st(1) */
4652 } else
4653 #endif
4654 if (v == VT_JMP || v == VT_JMPI) {
4655 /* need to put correct jump if && or || without test */
4656 gsym(vtop->c.ul);
4658 vtop--;
4661 /* convert stack entry to register and duplicate its value in another
4662 register */
4663 void gv_dup(void)
4665 int rc, t, r, r1;
4666 SValue sv;
4668 t = vtop->type.t;
4669 if ((t & VT_BTYPE) == VT_LLONG) {
4670 lexpand();
4671 gv_dup();
4672 vswap();
4673 vrotb(3);
4674 gv_dup();
4675 vrotb(4);
4676 /* stack: H L L1 H1 */
4677 lbuild(t);
4678 vrotb(3);
4679 vrotb(3);
4680 vswap();
4681 lbuild(t);
4682 vswap();
4683 } else {
4684 /* duplicate value */
4685 rc = RC_INT;
4686 sv.type.t = VT_INT;
4687 if (is_float(t)) {
4688 rc = RC_FLOAT;
4689 sv.type.t = t;
4691 r = gv(rc);
4692 r1 = get_reg(rc);
4693 sv.r = r;
4694 sv.c.ul = 0;
4695 load(r1, &sv); /* move r to r1 */
4696 vdup();
4697 /* duplicates value */
4698 vtop->r = r1;
4702 /* generate CPU independent (unsigned) long long operations */
4703 void gen_opl(int op)
4705 int t, a, b, op1, c, i;
4706 int func;
4707 SValue tmp;
4709 switch(op) {
4710 case '/':
4711 case TOK_PDIV:
4712 func = TOK___divdi3;
4713 goto gen_func;
4714 case TOK_UDIV:
4715 func = TOK___udivdi3;
4716 goto gen_func;
4717 case '%':
4718 func = TOK___moddi3;
4719 goto gen_func;
4720 case TOK_UMOD:
4721 func = TOK___umoddi3;
4722 gen_func:
4723 /* call generic long long function */
4724 vpush_global_sym(&func_old_type, func);
4725 vrott(3);
4726 gfunc_call(2);
4727 vpushi(0);
4728 vtop->r = REG_IRET;
4729 vtop->r2 = REG_LRET;
4730 break;
4731 case '^':
4732 case '&':
4733 case '|':
4734 case '*':
4735 case '+':
4736 case '-':
4737 t = vtop->type.t;
4738 vswap();
4739 lexpand();
4740 vrotb(3);
4741 lexpand();
4742 /* stack: L1 H1 L2 H2 */
4743 tmp = vtop[0];
4744 vtop[0] = vtop[-3];
4745 vtop[-3] = tmp;
4746 tmp = vtop[-2];
4747 vtop[-2] = vtop[-3];
4748 vtop[-3] = tmp;
4749 vswap();
4750 /* stack: H1 H2 L1 L2 */
4751 if (op == '*') {
4752 vpushv(vtop - 1);
4753 vpushv(vtop - 1);
4754 gen_op(TOK_UMULL);
4755 lexpand();
4756 /* stack: H1 H2 L1 L2 ML MH */
4757 for(i=0;i<4;i++)
4758 vrotb(6);
4759 /* stack: ML MH H1 H2 L1 L2 */
4760 tmp = vtop[0];
4761 vtop[0] = vtop[-2];
4762 vtop[-2] = tmp;
4763 /* stack: ML MH H1 L2 H2 L1 */
4764 gen_op('*');
4765 vrotb(3);
4766 vrotb(3);
4767 gen_op('*');
4768 /* stack: ML MH M1 M2 */
4769 gen_op('+');
4770 gen_op('+');
4771 } else if (op == '+' || op == '-') {
4772 /* XXX: add non carry method too (for MIPS or alpha) */
4773 if (op == '+')
4774 op1 = TOK_ADDC1;
4775 else
4776 op1 = TOK_SUBC1;
4777 gen_op(op1);
4778 /* stack: H1 H2 (L1 op L2) */
4779 vrotb(3);
4780 vrotb(3);
4781 gen_op(op1 + 1); /* TOK_xxxC2 */
4782 } else {
4783 gen_op(op);
4784 /* stack: H1 H2 (L1 op L2) */
4785 vrotb(3);
4786 vrotb(3);
4787 /* stack: (L1 op L2) H1 H2 */
4788 gen_op(op);
4789 /* stack: (L1 op L2) (H1 op H2) */
4791 /* stack: L H */
4792 lbuild(t);
4793 break;
4794 case TOK_SAR:
4795 case TOK_SHR:
4796 case TOK_SHL:
4797 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4798 t = vtop[-1].type.t;
4799 vswap();
4800 lexpand();
4801 vrotb(3);
4802 /* stack: L H shift */
4803 c = (int)vtop->c.i;
4804 /* constant: simpler */
4805 /* NOTE: all comments are for SHL. the other cases are
4806 done by swaping words */
4807 vpop();
4808 if (op != TOK_SHL)
4809 vswap();
4810 if (c >= 32) {
4811 /* stack: L H */
4812 vpop();
4813 if (c > 32) {
4814 vpushi(c - 32);
4815 gen_op(op);
4817 if (op != TOK_SAR) {
4818 vpushi(0);
4819 } else {
4820 gv_dup();
4821 vpushi(31);
4822 gen_op(TOK_SAR);
4824 vswap();
4825 } else {
4826 vswap();
4827 gv_dup();
4828 /* stack: H L L */
4829 vpushi(c);
4830 gen_op(op);
4831 vswap();
4832 vpushi(32 - c);
4833 if (op == TOK_SHL)
4834 gen_op(TOK_SHR);
4835 else
4836 gen_op(TOK_SHL);
4837 vrotb(3);
4838 /* stack: L L H */
4839 vpushi(c);
4840 if (op == TOK_SHL)
4841 gen_op(TOK_SHL);
4842 else
4843 gen_op(TOK_SHR);
4844 gen_op('|');
4846 if (op != TOK_SHL)
4847 vswap();
4848 lbuild(t);
4849 } else {
4850 /* XXX: should provide a faster fallback on x86 ? */
4851 switch(op) {
4852 case TOK_SAR:
4853 func = TOK___sardi3;
4854 goto gen_func;
4855 case TOK_SHR:
4856 func = TOK___shrdi3;
4857 goto gen_func;
4858 case TOK_SHL:
4859 func = TOK___shldi3;
4860 goto gen_func;
4863 break;
4864 default:
4865 /* compare operations */
4866 t = vtop->type.t;
4867 vswap();
4868 lexpand();
4869 vrotb(3);
4870 lexpand();
4871 /* stack: L1 H1 L2 H2 */
4872 tmp = vtop[-1];
4873 vtop[-1] = vtop[-2];
4874 vtop[-2] = tmp;
4875 /* stack: L1 L2 H1 H2 */
4876 /* compare high */
4877 op1 = op;
4878 /* when values are equal, we need to compare low words. since
4879 the jump is inverted, we invert the test too. */
4880 if (op1 == TOK_LT)
4881 op1 = TOK_LE;
4882 else if (op1 == TOK_GT)
4883 op1 = TOK_GE;
4884 else if (op1 == TOK_ULT)
4885 op1 = TOK_ULE;
4886 else if (op1 == TOK_UGT)
4887 op1 = TOK_UGE;
4888 a = 0;
4889 b = 0;
4890 gen_op(op1);
4891 if (op1 != TOK_NE) {
4892 a = gtst(1, 0);
4894 if (op != TOK_EQ) {
4895 /* generate non equal test */
4896 /* XXX: NOT PORTABLE yet */
4897 if (a == 0) {
4898 b = gtst(0, 0);
4899 } else {
4900 #ifdef TCC_TARGET_I386
4901 b = psym(0x850f, 0);
4902 #else
4903 error("not implemented");
4904 #endif
4907 /* compare low. Always unsigned */
4908 op1 = op;
4909 if (op1 == TOK_LT)
4910 op1 = TOK_ULT;
4911 else if (op1 == TOK_LE)
4912 op1 = TOK_ULE;
4913 else if (op1 == TOK_GT)
4914 op1 = TOK_UGT;
4915 else if (op1 == TOK_GE)
4916 op1 = TOK_UGE;
4917 gen_op(op1);
4918 a = gtst(1, a);
4919 gsym(b);
4920 vseti(VT_JMPI, a);
4921 break;
4925 /* handle integer constant optimizations and various machine
4926 independent opt */
4927 void gen_opic(int op)
4929 int fc, c1, c2, n;
4930 SValue *v1, *v2;
4932 v1 = vtop - 1;
4933 v2 = vtop;
4934 /* currently, we cannot do computations with forward symbols */
4935 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4936 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4937 if (c1 && c2) {
4938 fc = v2->c.i;
4939 switch(op) {
4940 case '+': v1->c.i += fc; break;
4941 case '-': v1->c.i -= fc; break;
4942 case '&': v1->c.i &= fc; break;
4943 case '^': v1->c.i ^= fc; break;
4944 case '|': v1->c.i |= fc; break;
4945 case '*': v1->c.i *= fc; break;
4947 case TOK_PDIV:
4948 case '/':
4949 case '%':
4950 case TOK_UDIV:
4951 case TOK_UMOD:
4952 /* if division by zero, generate explicit division */
4953 if (fc == 0) {
4954 if (const_wanted)
4955 error("division by zero in constant");
4956 goto general_case;
4958 switch(op) {
4959 default: v1->c.i /= fc; break;
4960 case '%': v1->c.i %= fc; break;
4961 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
4962 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
4964 break;
4965 case TOK_SHL: v1->c.i <<= fc; break;
4966 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
4967 case TOK_SAR: v1->c.i >>= fc; break;
4968 /* tests */
4969 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
4970 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
4971 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
4972 case TOK_NE: v1->c.i = v1->c.i != fc; break;
4973 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
4974 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
4975 case TOK_LT: v1->c.i = v1->c.i < fc; break;
4976 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
4977 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
4978 case TOK_GT: v1->c.i = v1->c.i > fc; break;
4979 /* logical */
4980 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
4981 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
4982 default:
4983 goto general_case;
4985 vtop--;
4986 } else {
4987 /* if commutative ops, put c2 as constant */
4988 if (c1 && (op == '+' || op == '&' || op == '^' ||
4989 op == '|' || op == '*')) {
4990 vswap();
4991 swap(&c1, &c2);
4993 fc = vtop->c.i;
4994 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
4995 op == TOK_PDIV) &&
4996 fc == 1) ||
4997 ((op == '+' || op == '-' || op == '|' || op == '^' ||
4998 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
4999 fc == 0) ||
5000 (op == '&' &&
5001 fc == -1))) {
5002 /* nothing to do */
5003 vtop--;
5004 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5005 /* try to use shifts instead of muls or divs */
5006 if (fc > 0 && (fc & (fc - 1)) == 0) {
5007 n = -1;
5008 while (fc) {
5009 fc >>= 1;
5010 n++;
5012 vtop->c.i = n;
5013 if (op == '*')
5014 op = TOK_SHL;
5015 else if (op == TOK_PDIV)
5016 op = TOK_SAR;
5017 else
5018 op = TOK_SHR;
5020 goto general_case;
5021 } else if (c2 && (op == '+' || op == '-') &&
5022 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5023 (VT_CONST | VT_SYM)) {
5024 /* symbol + constant case */
5025 if (op == '-')
5026 fc = -fc;
5027 vtop--;
5028 vtop->c.i += fc;
5029 } else {
5030 general_case:
5031 if (!nocode_wanted) {
5032 /* call low level op generator */
5033 gen_opi(op);
5034 } else {
5035 vtop--;
5041 /* generate a floating point operation with constant propagation */
5042 void gen_opif(int op)
5044 int c1, c2;
5045 SValue *v1, *v2;
5046 long double f1, f2;
5048 v1 = vtop - 1;
5049 v2 = vtop;
5050 /* currently, we cannot do computations with forward symbols */
5051 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5052 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5053 if (c1 && c2) {
5054 if (v1->type.t == VT_FLOAT) {
5055 f1 = v1->c.f;
5056 f2 = v2->c.f;
5057 } else if (v1->type.t == VT_DOUBLE) {
5058 f1 = v1->c.d;
5059 f2 = v2->c.d;
5060 } else {
5061 f1 = v1->c.ld;
5062 f2 = v2->c.ld;
5065 /* NOTE: we only do constant propagation if finite number (not
5066 NaN or infinity) (ANSI spec) */
5067 if (!ieee_finite(f1) || !ieee_finite(f2))
5068 goto general_case;
5070 switch(op) {
5071 case '+': f1 += f2; break;
5072 case '-': f1 -= f2; break;
5073 case '*': f1 *= f2; break;
5074 case '/':
5075 if (f2 == 0.0) {
5076 if (const_wanted)
5077 error("division by zero in constant");
5078 goto general_case;
5080 f1 /= f2;
5081 break;
5082 /* XXX: also handles tests ? */
5083 default:
5084 goto general_case;
5086 /* XXX: overflow test ? */
5087 if (v1->type.t == VT_FLOAT) {
5088 v1->c.f = f1;
5089 } else if (v1->type.t == VT_DOUBLE) {
5090 v1->c.d = f1;
5091 } else {
5092 v1->c.ld = f1;
5094 vtop--;
5095 } else {
5096 general_case:
5097 if (!nocode_wanted) {
5098 gen_opf(op);
5099 } else {
5100 vtop--;
5105 static int pointed_size(CType *type)
5107 int align;
5108 return type_size(pointed_type(type), &align);
5111 static inline int is_null_pointer(SValue *p)
5113 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5114 return 0;
5115 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5116 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5119 static inline int is_integer_btype(int bt)
5121 return (bt == VT_BYTE || bt == VT_SHORT ||
5122 bt == VT_INT || bt == VT_LLONG);
5125 /* check types for comparison or substraction of pointers */
5126 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5128 CType *type1, *type2, tmp_type1, tmp_type2;
5129 int bt1, bt2;
5131 /* null pointers are accepted for all comparisons as gcc */
5132 if (is_null_pointer(p1) || is_null_pointer(p2))
5133 return;
5134 type1 = &p1->type;
5135 type2 = &p2->type;
5136 bt1 = type1->t & VT_BTYPE;
5137 bt2 = type2->t & VT_BTYPE;
5138 /* accept comparison between pointer and integer with a warning */
5139 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5140 warning("comparison between pointer and integer");
5141 return;
5144 /* both must be pointers or implicit function pointers */
5145 if (bt1 == VT_PTR) {
5146 type1 = pointed_type(type1);
5147 } else if (bt1 != VT_FUNC)
5148 goto invalid_operands;
5150 if (bt2 == VT_PTR) {
5151 type2 = pointed_type(type2);
5152 } else if (bt2 != VT_FUNC) {
5153 invalid_operands:
5154 error("invalid operands to binary %s", get_tok_str(op, NULL));
5156 if ((type1->t & VT_BTYPE) == VT_VOID ||
5157 (type2->t & VT_BTYPE) == VT_VOID)
5158 return;
5159 tmp_type1 = *type1;
5160 tmp_type2 = *type2;
5161 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5162 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5163 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5164 /* gcc-like error if '-' is used */
5165 if (op == '-')
5166 goto invalid_operands;
5167 else
5168 warning("comparison of distinct pointer types lacks a cast");
5172 /* generic gen_op: handles types problems */
5173 void gen_op(int op)
5175 int u, t1, t2, bt1, bt2, t;
5176 CType type1;
5178 t1 = vtop[-1].type.t;
5179 t2 = vtop[0].type.t;
5180 bt1 = t1 & VT_BTYPE;
5181 bt2 = t2 & VT_BTYPE;
5183 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5184 /* at least one operand is a pointer */
5185 /* relationnal op: must be both pointers */
5186 if (op >= TOK_ULT && op <= TOK_GT) {
5187 check_comparison_pointer_types(vtop - 1, vtop, op);
5188 /* pointers are handled are unsigned */
5189 t = VT_INT | VT_UNSIGNED;
5190 goto std_op;
5192 /* if both pointers, then it must be the '-' op */
5193 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5194 if (op != '-')
5195 error("cannot use pointers here");
5196 check_comparison_pointer_types(vtop - 1, vtop, op);
5197 /* XXX: check that types are compatible */
5198 u = pointed_size(&vtop[-1].type);
5199 gen_opic(op);
5200 /* set to integer type */
5201 vtop->type.t = VT_INT;
5202 vpushi(u);
5203 gen_op(TOK_PDIV);
5204 } else {
5205 /* exactly one pointer : must be '+' or '-'. */
5206 if (op != '-' && op != '+')
5207 error("cannot use pointers here");
5208 /* Put pointer as first operand */
5209 if (bt2 == VT_PTR) {
5210 vswap();
5211 swap(&t1, &t2);
5213 type1 = vtop[-1].type;
5214 /* XXX: cast to int ? (long long case) */
5215 vpushi(pointed_size(&vtop[-1].type));
5216 gen_op('*');
5217 #ifdef CONFIG_TCC_BCHECK
5218 /* if evaluating constant expression, no code should be
5219 generated, so no bound check */
5220 if (do_bounds_check && !const_wanted) {
5221 /* if bounded pointers, we generate a special code to
5222 test bounds */
5223 if (op == '-') {
5224 vpushi(0);
5225 vswap();
5226 gen_op('-');
5228 gen_bounded_ptr_add();
5229 } else
5230 #endif
5232 gen_opic(op);
5234 /* put again type if gen_opic() swaped operands */
5235 vtop->type = type1;
5237 } else if (is_float(bt1) || is_float(bt2)) {
5238 /* compute bigger type and do implicit casts */
5239 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5240 t = VT_LDOUBLE;
5241 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5242 t = VT_DOUBLE;
5243 } else {
5244 t = VT_FLOAT;
5246 /* floats can only be used for a few operations */
5247 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5248 (op < TOK_ULT || op > TOK_GT))
5249 error("invalid operands for binary operation");
5250 goto std_op;
5251 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5252 /* cast to biggest op */
5253 t = VT_LLONG;
5254 /* convert to unsigned if it does not fit in a long long */
5255 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5256 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5257 t |= VT_UNSIGNED;
5258 goto std_op;
5259 } else {
5260 /* integer operations */
5261 t = VT_INT;
5262 /* convert to unsigned if it does not fit in an integer */
5263 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5264 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5265 t |= VT_UNSIGNED;
5266 std_op:
5267 /* XXX: currently, some unsigned operations are explicit, so
5268 we modify them here */
5269 if (t & VT_UNSIGNED) {
5270 if (op == TOK_SAR)
5271 op = TOK_SHR;
5272 else if (op == '/')
5273 op = TOK_UDIV;
5274 else if (op == '%')
5275 op = TOK_UMOD;
5276 else if (op == TOK_LT)
5277 op = TOK_ULT;
5278 else if (op == TOK_GT)
5279 op = TOK_UGT;
5280 else if (op == TOK_LE)
5281 op = TOK_ULE;
5282 else if (op == TOK_GE)
5283 op = TOK_UGE;
5285 vswap();
5286 type1.t = t;
5287 gen_cast(&type1);
5288 vswap();
5289 /* special case for shifts and long long: we keep the shift as
5290 an integer */
5291 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5292 type1.t = VT_INT;
5293 gen_cast(&type1);
5294 if (is_float(t))
5295 gen_opif(op);
5296 else if ((t & VT_BTYPE) == VT_LLONG)
5297 gen_opl(op);
5298 else
5299 gen_opic(op);
5300 if (op >= TOK_ULT && op <= TOK_GT) {
5301 /* relationnal op: the result is an int */
5302 vtop->type.t = VT_INT;
5303 } else {
5304 vtop->type.t = t;
5309 /* generic itof for unsigned long long case */
5310 void gen_cvt_itof1(int t)
5312 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5313 (VT_LLONG | VT_UNSIGNED)) {
5315 if (t == VT_FLOAT)
5316 vpush_global_sym(&func_old_type, TOK___ulltof);
5317 else if (t == VT_DOUBLE)
5318 vpush_global_sym(&func_old_type, TOK___ulltod);
5319 else
5320 vpush_global_sym(&func_old_type, TOK___ulltold);
5321 vrott(2);
5322 gfunc_call(1);
5323 vpushi(0);
5324 vtop->r = REG_FRET;
5325 } else {
5326 gen_cvt_itof(t);
5330 /* generic ftoi for unsigned long long case */
5331 void gen_cvt_ftoi1(int t)
5333 int st;
5335 if (t == (VT_LLONG | VT_UNSIGNED)) {
5336 /* not handled natively */
5337 st = vtop->type.t & VT_BTYPE;
5338 if (st == VT_FLOAT)
5339 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5340 else if (st == VT_DOUBLE)
5341 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5342 else
5343 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5344 vrott(2);
5345 gfunc_call(1);
5346 vpushi(0);
5347 vtop->r = REG_IRET;
5348 vtop->r2 = REG_LRET;
5349 } else {
5350 gen_cvt_ftoi(t);
5354 /* force char or short cast */
5355 void force_charshort_cast(int t)
5357 int bits, dbt;
5358 dbt = t & VT_BTYPE;
5359 /* XXX: add optimization if lvalue : just change type and offset */
5360 if (dbt == VT_BYTE)
5361 bits = 8;
5362 else
5363 bits = 16;
5364 if (t & VT_UNSIGNED) {
5365 vpushi((1 << bits) - 1);
5366 gen_op('&');
5367 } else {
5368 bits = 32 - bits;
5369 vpushi(bits);
5370 gen_op(TOK_SHL);
5371 vpushi(bits);
5372 gen_op(TOK_SAR);
5376 /* cast 'vtop' to 'type' */
5377 static void gen_cast(CType *type)
5379 int sbt, dbt, sf, df, c;
5381 /* special delayed cast for char/short */
5382 /* XXX: in some cases (multiple cascaded casts), it may still
5383 be incorrect */
5384 if (vtop->r & VT_MUSTCAST) {
5385 vtop->r &= ~VT_MUSTCAST;
5386 force_charshort_cast(vtop->type.t);
5389 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5390 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5392 if (sbt != dbt && !nocode_wanted) {
5393 sf = is_float(sbt);
5394 df = is_float(dbt);
5395 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5396 if (sf && df) {
5397 /* convert from fp to fp */
5398 if (c) {
5399 /* constant case: we can do it now */
5400 /* XXX: in ISOC, cannot do it if error in convert */
5401 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5402 vtop->c.f = (float)vtop->c.d;
5403 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5404 vtop->c.f = (float)vtop->c.ld;
5405 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5406 vtop->c.d = (double)vtop->c.f;
5407 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5408 vtop->c.d = (double)vtop->c.ld;
5409 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5410 vtop->c.ld = (long double)vtop->c.f;
5411 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5412 vtop->c.ld = (long double)vtop->c.d;
5413 } else {
5414 /* non constant case: generate code */
5415 gen_cvt_ftof(dbt);
5417 } else if (df) {
5418 /* convert int to fp */
5419 if (c) {
5420 switch(sbt) {
5421 case VT_LLONG | VT_UNSIGNED:
5422 case VT_LLONG:
5423 /* XXX: add const cases for long long */
5424 goto do_itof;
5425 case VT_INT | VT_UNSIGNED:
5426 switch(dbt) {
5427 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5428 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5429 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5431 break;
5432 default:
5433 switch(dbt) {
5434 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5435 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5436 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5438 break;
5440 } else {
5441 do_itof:
5442 gen_cvt_itof1(dbt);
5444 } else if (sf) {
5445 /* convert fp to int */
5446 /* we handle char/short/etc... with generic code */
5447 if (dbt != (VT_INT | VT_UNSIGNED) &&
5448 dbt != (VT_LLONG | VT_UNSIGNED) &&
5449 dbt != VT_LLONG)
5450 dbt = VT_INT;
5451 if (c) {
5452 switch(dbt) {
5453 case VT_LLONG | VT_UNSIGNED:
5454 case VT_LLONG:
5455 /* XXX: add const cases for long long */
5456 goto do_ftoi;
5457 case VT_INT | VT_UNSIGNED:
5458 switch(sbt) {
5459 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5460 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5461 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5463 break;
5464 default:
5465 /* int case */
5466 switch(sbt) {
5467 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5468 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5469 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5471 break;
5473 } else {
5474 do_ftoi:
5475 gen_cvt_ftoi1(dbt);
5477 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5478 /* additional cast for char/short/bool... */
5479 vtop->type.t = dbt;
5480 gen_cast(type);
5482 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5483 if ((sbt & VT_BTYPE) != VT_LLONG) {
5484 /* scalar to long long */
5485 if (c) {
5486 if (sbt == (VT_INT | VT_UNSIGNED))
5487 vtop->c.ll = vtop->c.ui;
5488 else
5489 vtop->c.ll = vtop->c.i;
5490 } else {
5491 /* machine independent conversion */
5492 gv(RC_INT);
5493 /* generate high word */
5494 if (sbt == (VT_INT | VT_UNSIGNED)) {
5495 vpushi(0);
5496 gv(RC_INT);
5497 } else {
5498 gv_dup();
5499 vpushi(31);
5500 gen_op(TOK_SAR);
5502 /* patch second register */
5503 vtop[-1].r2 = vtop->r;
5504 vpop();
5507 } else if (dbt == VT_BOOL) {
5508 /* scalar to bool */
5509 vpushi(0);
5510 gen_op(TOK_NE);
5511 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5512 (dbt & VT_BTYPE) == VT_SHORT) {
5513 force_charshort_cast(dbt);
5514 } else if ((dbt & VT_BTYPE) == VT_INT) {
5515 /* scalar to int */
5516 if (sbt == VT_LLONG) {
5517 /* from long long: just take low order word */
5518 lexpand();
5519 vpop();
5521 /* if lvalue and single word type, nothing to do because
5522 the lvalue already contains the real type size (see
5523 VT_LVAL_xxx constants) */
5526 vtop->type = *type;
5529 /* return type size. Put alignment at 'a' */
5530 static int type_size(CType *type, int *a)
5532 Sym *s;
5533 int bt;
5535 bt = type->t & VT_BTYPE;
5536 if (bt == VT_STRUCT) {
5537 /* struct/union */
5538 s = type->ref;
5539 *a = s->r;
5540 return s->c;
5541 } else if (bt == VT_PTR) {
5542 if (type->t & VT_ARRAY) {
5543 s = type->ref;
5544 return type_size(&s->type, a) * s->c;
5545 } else {
5546 *a = PTR_SIZE;
5547 return PTR_SIZE;
5549 } else if (bt == VT_LDOUBLE) {
5550 *a = LDOUBLE_ALIGN;
5551 return LDOUBLE_SIZE;
5552 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5553 *a = 4; /* XXX: i386 specific */
5554 return 8;
5555 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5556 *a = 4;
5557 return 4;
5558 } else if (bt == VT_SHORT) {
5559 *a = 2;
5560 return 2;
5561 } else {
5562 /* char, void, function, _Bool */
5563 *a = 1;
5564 return 1;
5568 /* return the pointed type of t */
5569 static inline CType *pointed_type(CType *type)
5571 return &type->ref->type;
5574 /* modify type so that its it is a pointer to type. */
5575 static void mk_pointer(CType *type)
5577 Sym *s;
5578 s = sym_push(SYM_FIELD, type, 0, -1);
5579 type->t = VT_PTR | (type->t & ~VT_TYPE);
5580 type->ref = s;
5583 /* compare function types. OLD functions match any new functions */
5584 static int is_compatible_func(CType *type1, CType *type2)
5586 Sym *s1, *s2;
5588 s1 = type1->ref;
5589 s2 = type2->ref;
5590 if (!is_compatible_types(&s1->type, &s2->type))
5591 return 0;
5592 /* XXX: not complete */
5593 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5594 return 1;
5595 if (s1->c != s2->c)
5596 return 0;
5597 while (s1 != NULL) {
5598 if (s2 == NULL)
5599 return 0;
5600 if (!is_compatible_types(&s1->type, &s2->type))
5601 return 0;
5602 s1 = s1->next;
5603 s2 = s2->next;
5605 if (s2)
5606 return 0;
5607 return 1;
5610 /* return true if type1 and type2 are exactly the same (including
5611 qualifiers).
5613 - enums are not checked as gcc __builtin_types_compatible_p ()
5615 static int is_compatible_types(CType *type1, CType *type2)
5617 int bt1, t1, t2;
5619 t1 = type1->t & VT_TYPE;
5620 t2 = type2->t & VT_TYPE;
5621 /* XXX: bitfields ? */
5622 if (t1 != t2)
5623 return 0;
5624 /* test more complicated cases */
5625 bt1 = t1 & VT_BTYPE;
5626 if (bt1 == VT_PTR) {
5627 type1 = pointed_type(type1);
5628 type2 = pointed_type(type2);
5629 return is_compatible_types(type1, type2);
5630 } else if (bt1 == VT_STRUCT) {
5631 return (type1->ref == type2->ref);
5632 } else if (bt1 == VT_FUNC) {
5633 return is_compatible_func(type1, type2);
5634 } else {
5635 return 1;
5639 /* print a type. If 'varstr' is not NULL, then the variable is also
5640 printed in the type */
5641 /* XXX: union */
5642 /* XXX: add array and function pointers */
5643 void type_to_str(char *buf, int buf_size,
5644 CType *type, const char *varstr)
5646 int bt, v, t;
5647 Sym *s, *sa;
5648 char buf1[256];
5649 const char *tstr;
5651 t = type->t & VT_TYPE;
5652 bt = t & VT_BTYPE;
5653 buf[0] = '\0';
5654 if (t & VT_CONSTANT)
5655 pstrcat(buf, buf_size, "const ");
5656 if (t & VT_VOLATILE)
5657 pstrcat(buf, buf_size, "volatile ");
5658 if (t & VT_UNSIGNED)
5659 pstrcat(buf, buf_size, "unsigned ");
5660 switch(bt) {
5661 case VT_VOID:
5662 tstr = "void";
5663 goto add_tstr;
5664 case VT_BOOL:
5665 tstr = "_Bool";
5666 goto add_tstr;
5667 case VT_BYTE:
5668 tstr = "char";
5669 goto add_tstr;
5670 case VT_SHORT:
5671 tstr = "short";
5672 goto add_tstr;
5673 case VT_INT:
5674 tstr = "int";
5675 goto add_tstr;
5676 case VT_LONG:
5677 tstr = "long";
5678 goto add_tstr;
5679 case VT_LLONG:
5680 tstr = "long long";
5681 goto add_tstr;
5682 case VT_FLOAT:
5683 tstr = "float";
5684 goto add_tstr;
5685 case VT_DOUBLE:
5686 tstr = "double";
5687 goto add_tstr;
5688 case VT_LDOUBLE:
5689 tstr = "long double";
5690 add_tstr:
5691 pstrcat(buf, buf_size, tstr);
5692 break;
5693 case VT_ENUM:
5694 case VT_STRUCT:
5695 if (bt == VT_STRUCT)
5696 tstr = "struct ";
5697 else
5698 tstr = "enum ";
5699 pstrcat(buf, buf_size, tstr);
5700 v = type->ref->v & ~SYM_STRUCT;
5701 if (v >= SYM_FIRST_ANOM)
5702 pstrcat(buf, buf_size, "<anonymous>");
5703 else
5704 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5705 break;
5706 case VT_FUNC:
5707 s = type->ref;
5708 type_to_str(buf, buf_size, &s->type, varstr);
5709 pstrcat(buf, buf_size, "(");
5710 sa = s->next;
5711 while (sa != NULL) {
5712 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5713 pstrcat(buf, buf_size, buf1);
5714 sa = sa->next;
5715 if (sa)
5716 pstrcat(buf, buf_size, ", ");
5718 pstrcat(buf, buf_size, ")");
5719 goto no_var;
5720 case VT_PTR:
5721 s = type->ref;
5722 pstrcpy(buf1, sizeof(buf1), "*");
5723 if (varstr)
5724 pstrcat(buf1, sizeof(buf1), varstr);
5725 type_to_str(buf, buf_size, &s->type, buf1);
5726 goto no_var;
5728 if (varstr) {
5729 pstrcat(buf, buf_size, " ");
5730 pstrcat(buf, buf_size, varstr);
5732 no_var: ;
5735 /* verify type compatibility to store vtop in 'dt' type, and generate
5736 casts if needed. */
5737 static void gen_assign_cast(CType *dt)
5739 CType *st, *type1, *type2, tmp_type1, tmp_type2;
5740 char buf1[256], buf2[256];
5741 int dbt, sbt;
5743 st = &vtop->type; /* source type */
5744 dbt = dt->t & VT_BTYPE;
5745 sbt = st->t & VT_BTYPE;
5746 if (dt->t & VT_CONSTANT)
5747 warning("assignment of read-only location");
5748 switch(dbt) {
5749 case VT_PTR:
5750 /* special cases for pointers */
5751 /* '0' can also be a pointer */
5752 if (is_null_pointer(vtop))
5753 goto type_ok;
5754 /* accept implicit pointer to integer cast with warning */
5755 if (is_integer_btype(sbt)) {
5756 warning("assignment makes pointer from integer without a cast");
5757 goto type_ok;
5759 type1 = pointed_type(dt);
5760 /* a function is implicitely a function pointer */
5761 if (sbt == VT_FUNC) {
5762 if ((type1->t & VT_BTYPE) != VT_VOID &&
5763 !is_compatible_types(pointed_type(dt), st))
5764 goto error;
5765 else
5766 goto type_ok;
5768 if (sbt != VT_PTR)
5769 goto error;
5770 type2 = pointed_type(st);
5771 if ((type1->t & VT_BTYPE) == VT_VOID ||
5772 (type2->t & VT_BTYPE) == VT_VOID) {
5773 /* void * can match anything */
5774 } else {
5775 /* exact type match, except for unsigned */
5776 tmp_type1 = *type1;
5777 tmp_type2 = *type2;
5778 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5779 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5780 if (!is_compatible_types(&tmp_type1, &tmp_type2))
5781 goto error;
5783 /* check const and volatile */
5784 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
5785 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
5786 warning("assignment discards qualifiers from pointer target type");
5787 break;
5788 case VT_BYTE:
5789 case VT_SHORT:
5790 case VT_INT:
5791 case VT_LLONG:
5792 if (sbt == VT_PTR || sbt == VT_FUNC) {
5793 warning("assignment makes integer from pointer without a cast");
5795 /* XXX: more tests */
5796 break;
5797 case VT_STRUCT:
5798 if (!is_compatible_types(dt, st)) {
5799 error:
5800 type_to_str(buf1, sizeof(buf1), st, NULL);
5801 type_to_str(buf2, sizeof(buf2), dt, NULL);
5802 error("cannot cast '%s' to '%s'", buf1, buf2);
5804 break;
5806 type_ok:
5807 gen_cast(dt);
5810 /* store vtop in lvalue pushed on stack */
5811 void vstore(void)
5813 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5815 ft = vtop[-1].type.t;
5816 sbt = vtop->type.t & VT_BTYPE;
5817 dbt = ft & VT_BTYPE;
5818 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5819 (sbt == VT_INT && dbt == VT_SHORT)) {
5820 /* optimize char/short casts */
5821 delayed_cast = VT_MUSTCAST;
5822 vtop->type.t = ft & VT_TYPE;
5823 /* XXX: factorize */
5824 if (ft & VT_CONSTANT)
5825 warning("assignment of read-only location");
5826 } else {
5827 delayed_cast = 0;
5828 gen_assign_cast(&vtop[-1].type);
5831 if (sbt == VT_STRUCT) {
5832 /* if structure, only generate pointer */
5833 /* structure assignment : generate memcpy */
5834 /* XXX: optimize if small size */
5835 if (!nocode_wanted) {
5836 size = type_size(&vtop->type, &align);
5838 vpush_global_sym(&func_old_type, TOK_memcpy);
5840 /* destination */
5841 vpushv(vtop - 2);
5842 vtop->type.t = VT_INT;
5843 gaddrof();
5844 /* source */
5845 vpushv(vtop - 2);
5846 vtop->type.t = VT_INT;
5847 gaddrof();
5848 /* type size */
5849 vpushi(size);
5850 gfunc_call(3);
5852 vswap();
5853 vpop();
5854 } else {
5855 vswap();
5856 vpop();
5858 /* leave source on stack */
5859 } else if (ft & VT_BITFIELD) {
5860 /* bitfield store handling */
5861 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5862 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5863 /* remove bit field info to avoid loops */
5864 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5866 /* duplicate destination */
5867 vdup();
5868 vtop[-1] = vtop[-2];
5870 /* mask and shift source */
5871 vpushi((1 << bit_size) - 1);
5872 gen_op('&');
5873 vpushi(bit_pos);
5874 gen_op(TOK_SHL);
5875 /* load destination, mask and or with source */
5876 vswap();
5877 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5878 gen_op('&');
5879 gen_op('|');
5880 /* store result */
5881 vstore();
5882 } else {
5883 #ifdef CONFIG_TCC_BCHECK
5884 /* bound check case */
5885 if (vtop[-1].r & VT_MUSTBOUND) {
5886 vswap();
5887 gbound();
5888 vswap();
5890 #endif
5891 if (!nocode_wanted) {
5892 rc = RC_INT;
5893 if (is_float(ft))
5894 rc = RC_FLOAT;
5895 r = gv(rc); /* generate value */
5896 /* if lvalue was saved on stack, must read it */
5897 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5898 SValue sv;
5899 t = get_reg(RC_INT);
5900 sv.type.t = VT_INT;
5901 sv.r = VT_LOCAL | VT_LVAL;
5902 sv.c.ul = vtop[-1].c.ul;
5903 load(t, &sv);
5904 vtop[-1].r = t | VT_LVAL;
5906 store(r, vtop - 1);
5907 /* two word case handling : store second register at word + 4 */
5908 if ((ft & VT_BTYPE) == VT_LLONG) {
5909 vswap();
5910 /* convert to int to increment easily */
5911 vtop->type.t = VT_INT;
5912 gaddrof();
5913 vpushi(4);
5914 gen_op('+');
5915 vtop->r |= VT_LVAL;
5916 vswap();
5917 /* XXX: it works because r2 is spilled last ! */
5918 store(vtop->r2, vtop - 1);
5921 vswap();
5922 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5923 vtop->r |= delayed_cast;
5927 /* post defines POST/PRE add. c is the token ++ or -- */
5928 void inc(int post, int c)
5930 test_lvalue();
5931 vdup(); /* save lvalue */
5932 if (post) {
5933 gv_dup(); /* duplicate value */
5934 vrotb(3);
5935 vrotb(3);
5937 /* add constant */
5938 vpushi(c - TOK_MID);
5939 gen_op('+');
5940 vstore(); /* store value */
5941 if (post)
5942 vpop(); /* if post op, return saved value */
5945 /* Parse GNUC __attribute__ extension. Currently, the following
5946 extensions are recognized:
5947 - aligned(n) : set data/function alignment.
5948 - section(x) : generate data/code in this section.
5949 - unused : currently ignored, but may be used someday.
5951 static void parse_attribute(AttributeDef *ad)
5953 int t, n;
5955 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
5956 next();
5957 skip('(');
5958 skip('(');
5959 while (tok != ')') {
5960 if (tok < TOK_IDENT)
5961 expect("attribute name");
5962 t = tok;
5963 next();
5964 switch(t) {
5965 case TOK_SECTION1:
5966 case TOK_SECTION2:
5967 skip('(');
5968 if (tok != TOK_STR)
5969 expect("section name");
5970 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
5971 next();
5972 skip(')');
5973 break;
5974 case TOK_ALIGNED1:
5975 case TOK_ALIGNED2:
5976 if (tok == '(') {
5977 next();
5978 n = expr_const();
5979 if (n <= 0 || (n & (n - 1)) != 0)
5980 error("alignment must be a positive power of two");
5981 skip(')');
5982 } else {
5983 n = MAX_ALIGN;
5985 ad->aligned = n;
5986 break;
5987 case TOK_UNUSED1:
5988 case TOK_UNUSED2:
5989 /* currently, no need to handle it because tcc does not
5990 track unused objects */
5991 break;
5992 case TOK_NORETURN1:
5993 case TOK_NORETURN2:
5994 /* currently, no need to handle it because tcc does not
5995 track unused objects */
5996 break;
5997 case TOK_CDECL1:
5998 case TOK_CDECL2:
5999 case TOK_CDECL3:
6000 ad->func_call = FUNC_CDECL;
6001 break;
6002 case TOK_STDCALL1:
6003 case TOK_STDCALL2:
6004 case TOK_STDCALL3:
6005 ad->func_call = FUNC_STDCALL;
6006 break;
6007 default:
6008 if (tcc_state->warn_unsupported)
6009 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6010 /* skip parameters */
6011 /* XXX: skip parenthesis too */
6012 if (tok == '(') {
6013 next();
6014 while (tok != ')' && tok != -1)
6015 next();
6016 next();
6018 break;
6020 if (tok != ',')
6021 break;
6022 next();
6024 skip(')');
6025 skip(')');
6029 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6030 static void struct_decl(CType *type, int u)
6032 int a, v, size, align, maxalign, c, offset;
6033 int bit_size, bit_pos, bsize, bt, lbit_pos;
6034 Sym *s, *ss, **ps;
6035 AttributeDef ad;
6036 CType type1, btype;
6038 a = tok; /* save decl type */
6039 next();
6040 if (tok != '{') {
6041 v = tok;
6042 next();
6043 /* struct already defined ? return it */
6044 if (v < TOK_IDENT)
6045 expect("struct/union/enum name");
6046 s = struct_find(v);
6047 if (s) {
6048 if (s->type.t != a)
6049 error("invalid type");
6050 goto do_decl;
6052 } else {
6053 v = anon_sym++;
6055 type1.t = a;
6056 /* we put an undefined size for struct/union */
6057 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6058 s->r = 0; /* default alignment is zero as gcc */
6059 /* put struct/union/enum name in type */
6060 do_decl:
6061 type->t = u;
6062 type->ref = s;
6064 if (tok == '{') {
6065 next();
6066 if (s->c != -1)
6067 error("struct/union/enum already defined");
6068 /* cannot be empty */
6069 c = 0;
6070 /* non empty enums are not allowed */
6071 if (a == TOK_ENUM) {
6072 for(;;) {
6073 v = tok;
6074 if (v < TOK_UIDENT)
6075 expect("identifier");
6076 next();
6077 if (tok == '=') {
6078 next();
6079 c = expr_const();
6081 /* enum symbols have static storage */
6082 ss = sym_push(v, &int_type, VT_CONST, c);
6083 ss->type.t |= VT_STATIC;
6084 if (tok != ',')
6085 break;
6086 next();
6087 c++;
6088 /* NOTE: we accept a trailing comma */
6089 if (tok == '}')
6090 break;
6092 skip('}');
6093 } else {
6094 maxalign = 1;
6095 ps = &s->next;
6096 bit_pos = 0;
6097 offset = 0;
6098 while (tok != '}') {
6099 parse_btype(&btype, &ad);
6100 while (1) {
6101 bit_size = -1;
6102 v = 0;
6103 type1 = btype;
6104 if (tok != ':') {
6105 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6106 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6107 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6108 error("invalid type for '%s'",
6109 get_tok_str(v, NULL));
6111 if (tok == ':') {
6112 next();
6113 bit_size = expr_const();
6114 /* XXX: handle v = 0 case for messages */
6115 if (bit_size < 0)
6116 error("negative width in bit-field '%s'",
6117 get_tok_str(v, NULL));
6118 if (v && bit_size == 0)
6119 error("zero width for bit-field '%s'",
6120 get_tok_str(v, NULL));
6122 size = type_size(&type1, &align);
6123 lbit_pos = 0;
6124 if (bit_size >= 0) {
6125 bt = type1.t & VT_BTYPE;
6126 if (bt != VT_INT &&
6127 bt != VT_BYTE &&
6128 bt != VT_SHORT &&
6129 bt != VT_ENUM)
6130 error("bitfields must have scalar type");
6131 bsize = size * 8;
6132 if (bit_size > bsize) {
6133 error("width of '%s' exceeds its type",
6134 get_tok_str(v, NULL));
6135 } else if (bit_size == bsize) {
6136 /* no need for bit fields */
6137 bit_pos = 0;
6138 } else if (bit_size == 0) {
6139 /* XXX: what to do if only padding in a
6140 structure ? */
6141 /* zero size: means to pad */
6142 if (bit_pos > 0)
6143 bit_pos = bsize;
6144 } else {
6145 /* we do not have enough room ? */
6146 if ((bit_pos + bit_size) > bsize)
6147 bit_pos = 0;
6148 lbit_pos = bit_pos;
6149 /* XXX: handle LSB first */
6150 type1.t |= VT_BITFIELD |
6151 (bit_pos << VT_STRUCT_SHIFT) |
6152 (bit_size << (VT_STRUCT_SHIFT + 6));
6153 bit_pos += bit_size;
6155 } else {
6156 bit_pos = 0;
6158 if (v) {
6159 /* add new memory data only if starting
6160 bit field */
6161 if (lbit_pos == 0) {
6162 if (a == TOK_STRUCT) {
6163 c = (c + align - 1) & -align;
6164 offset = c;
6165 c += size;
6166 } else {
6167 offset = 0;
6168 if (size > c)
6169 c = size;
6171 if (align > maxalign)
6172 maxalign = align;
6174 #if 0
6175 printf("add field %s offset=%d",
6176 get_tok_str(v, NULL), offset);
6177 if (type1.t & VT_BITFIELD) {
6178 printf(" pos=%d size=%d",
6179 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6180 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6182 printf("\n");
6183 #endif
6184 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6185 *ps = ss;
6186 ps = &ss->next;
6188 if (tok == ';' || tok == TOK_EOF)
6189 break;
6190 skip(',');
6192 skip(';');
6194 skip('}');
6195 /* store size and alignment */
6196 s->c = (c + maxalign - 1) & -maxalign;
6197 s->r = maxalign;
6202 /* return 0 if no type declaration. otherwise, return the basic type
6203 and skip it.
6205 static int parse_btype(CType *type, AttributeDef *ad)
6207 int t, u, type_found, typespec_found;
6208 Sym *s;
6209 CType type1;
6211 memset(ad, 0, sizeof(AttributeDef));
6212 type_found = 0;
6213 typespec_found = 0;
6214 t = 0;
6215 while(1) {
6216 switch(tok) {
6217 case TOK_EXTENSION:
6218 /* currently, we really ignore extension */
6219 next();
6220 continue;
6222 /* basic types */
6223 case TOK_CHAR:
6224 u = VT_BYTE;
6225 basic_type:
6226 next();
6227 basic_type1:
6228 if ((t & VT_BTYPE) != 0)
6229 error("too many basic types");
6230 t |= u;
6231 typespec_found = 1;
6232 break;
6233 case TOK_VOID:
6234 u = VT_VOID;
6235 goto basic_type;
6236 case TOK_SHORT:
6237 u = VT_SHORT;
6238 goto basic_type;
6239 case TOK_INT:
6240 next();
6241 typespec_found = 1;
6242 break;
6243 case TOK_LONG:
6244 next();
6245 if ((t & VT_BTYPE) == VT_DOUBLE) {
6246 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6247 } else if ((t & VT_BTYPE) == VT_LONG) {
6248 t = (t & ~VT_BTYPE) | VT_LLONG;
6249 } else {
6250 u = VT_LONG;
6251 goto basic_type1;
6253 break;
6254 case TOK_BOOL:
6255 u = VT_BOOL;
6256 goto basic_type;
6257 case TOK_FLOAT:
6258 u = VT_FLOAT;
6259 goto basic_type;
6260 case TOK_DOUBLE:
6261 next();
6262 if ((t & VT_BTYPE) == VT_LONG) {
6263 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6264 } else {
6265 u = VT_DOUBLE;
6266 goto basic_type1;
6268 break;
6269 case TOK_ENUM:
6270 struct_decl(&type1, VT_ENUM);
6271 basic_type2:
6272 u = type1.t;
6273 type->ref = type1.ref;
6274 goto basic_type1;
6275 case TOK_STRUCT:
6276 case TOK_UNION:
6277 struct_decl(&type1, VT_STRUCT);
6278 goto basic_type2;
6280 /* type modifiers */
6281 case TOK_CONST1:
6282 case TOK_CONST2:
6283 case TOK_CONST3:
6284 t |= VT_CONSTANT;
6285 next();
6286 break;
6287 case TOK_VOLATILE1:
6288 case TOK_VOLATILE2:
6289 case TOK_VOLATILE3:
6290 t |= VT_VOLATILE;
6291 next();
6292 break;
6293 case TOK_SIGNED1:
6294 case TOK_SIGNED2:
6295 case TOK_SIGNED3:
6296 typespec_found = 1;
6297 case TOK_REGISTER:
6298 case TOK_AUTO:
6299 case TOK_RESTRICT1:
6300 case TOK_RESTRICT2:
6301 case TOK_RESTRICT3:
6302 next();
6303 break;
6304 case TOK_UNSIGNED:
6305 t |= VT_UNSIGNED;
6306 next();
6307 typespec_found = 1;
6308 break;
6310 /* storage */
6311 case TOK_EXTERN:
6312 t |= VT_EXTERN;
6313 next();
6314 break;
6315 case TOK_STATIC:
6316 t |= VT_STATIC;
6317 next();
6318 break;
6319 case TOK_TYPEDEF:
6320 t |= VT_TYPEDEF;
6321 next();
6322 break;
6323 case TOK_INLINE1:
6324 case TOK_INLINE2:
6325 case TOK_INLINE3:
6326 t |= VT_INLINE;
6327 next();
6328 break;
6330 /* GNUC attribute */
6331 case TOK_ATTRIBUTE1:
6332 case TOK_ATTRIBUTE2:
6333 parse_attribute(ad);
6334 break;
6335 /* GNUC typeof */
6336 case TOK_TYPEOF1:
6337 case TOK_TYPEOF2:
6338 case TOK_TYPEOF3:
6339 next();
6340 parse_expr_type(&type1);
6341 goto basic_type2;
6342 default:
6343 if (typespec_found)
6344 goto the_end;
6345 s = sym_find(tok);
6346 if (!s || !(s->type.t & VT_TYPEDEF))
6347 goto the_end;
6348 t |= (s->type.t & ~VT_TYPEDEF);
6349 type->ref = s->type.ref;
6350 next();
6351 break;
6353 type_found = 1;
6355 the_end:
6356 /* long is never used as type */
6357 if ((t & VT_BTYPE) == VT_LONG)
6358 t = (t & ~VT_BTYPE) | VT_INT;
6359 type->t = t;
6360 return type_found;
6363 /* convert a function parameter type (array to pointer and function to
6364 function pointer) */
6365 static inline void convert_parameter_type(CType *pt)
6367 /* array must be transformed to pointer according to ANSI C */
6368 pt->t &= ~VT_ARRAY;
6369 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6370 mk_pointer(pt);
6374 static void post_type(CType *type, AttributeDef *ad)
6376 int n, l, t1;
6377 Sym **plast, *s, *first;
6378 AttributeDef ad1;
6379 CType pt;
6381 if (tok == '(') {
6382 /* function declaration */
6383 next();
6384 l = 0;
6385 first = NULL;
6386 plast = &first;
6387 while (tok != ')') {
6388 /* read param name and compute offset */
6389 if (l != FUNC_OLD) {
6390 if (!parse_btype(&pt, &ad1)) {
6391 if (l) {
6392 error("invalid type");
6393 } else {
6394 l = FUNC_OLD;
6395 goto old_proto;
6398 l = FUNC_NEW;
6399 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6400 break;
6401 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6402 if ((pt.t & VT_BTYPE) == VT_VOID)
6403 error("parameter declared as void");
6404 } else {
6405 old_proto:
6406 n = tok;
6407 pt.t = VT_INT;
6408 next();
6410 convert_parameter_type(&pt);
6411 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6412 *plast = s;
6413 plast = &s->next;
6414 if (tok == ',') {
6415 next();
6416 if (l == FUNC_NEW && tok == TOK_DOTS) {
6417 l = FUNC_ELLIPSIS;
6418 next();
6419 break;
6423 /* if no parameters, then old type prototype */
6424 if (l == 0)
6425 l = FUNC_OLD;
6426 skip(')');
6427 t1 = type->t & VT_STORAGE;
6428 /* NOTE: const is ignored in returned type as it has a special
6429 meaning in gcc / C++ */
6430 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6431 post_type(type, ad);
6432 /* we push a anonymous symbol which will contain the function prototype */
6433 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6434 s->next = first;
6435 type->t = t1 | VT_FUNC;
6436 type->ref = s;
6437 } else if (tok == '[') {
6438 /* array definition */
6439 next();
6440 n = -1;
6441 if (tok != ']') {
6442 n = expr_const();
6443 if (n < 0)
6444 error("invalid array size");
6446 skip(']');
6447 /* parse next post type */
6448 t1 = type->t & VT_STORAGE;
6449 type->t &= ~VT_STORAGE;
6450 post_type(type, ad);
6452 /* we push a anonymous symbol which will contain the array
6453 element type */
6454 s = sym_push(SYM_FIELD, type, 0, n);
6455 type->t = t1 | VT_ARRAY | VT_PTR;
6456 type->ref = s;
6460 /* Parse a type declaration (except basic type), and return the type
6461 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6462 expected. 'type' should contain the basic type. 'ad' is the
6463 attribute definition of the basic type. It can be modified by
6464 type_decl().
6466 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6468 Sym *s;
6469 CType type1, *type2;
6470 int qualifiers;
6472 while (tok == '*') {
6473 qualifiers = 0;
6474 redo:
6475 next();
6476 switch(tok) {
6477 case TOK_CONST1:
6478 case TOK_CONST2:
6479 case TOK_CONST3:
6480 qualifiers |= VT_CONSTANT;
6481 goto redo;
6482 case TOK_VOLATILE1:
6483 case TOK_VOLATILE2:
6484 case TOK_VOLATILE3:
6485 qualifiers |= VT_VOLATILE;
6486 goto redo;
6487 case TOK_RESTRICT1:
6488 case TOK_RESTRICT2:
6489 case TOK_RESTRICT3:
6490 goto redo;
6492 mk_pointer(type);
6493 type->t |= qualifiers;
6496 /* XXX: clarify attribute handling */
6497 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6498 parse_attribute(ad);
6500 /* recursive type */
6501 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6502 type1.t = 0; /* XXX: same as int */
6503 if (tok == '(') {
6504 next();
6505 /* XXX: this is not correct to modify 'ad' at this point, but
6506 the syntax is not clear */
6507 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6508 parse_attribute(ad);
6509 type_decl(&type1, ad, v, td);
6510 skip(')');
6511 } else {
6512 /* type identifier */
6513 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6514 *v = tok;
6515 next();
6516 } else {
6517 if (!(td & TYPE_ABSTRACT))
6518 expect("identifier");
6519 *v = 0;
6522 post_type(type, ad);
6523 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6524 parse_attribute(ad);
6525 if (!type1.t)
6526 return;
6527 /* append type at the end of type1 */
6528 type2 = &type1;
6529 for(;;) {
6530 s = type2->ref;
6531 type2 = &s->type;
6532 if (!type2->t) {
6533 *type2 = *type;
6534 break;
6537 *type = type1;
6540 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6541 static int lvalue_type(int t)
6543 int bt, r;
6544 r = VT_LVAL;
6545 bt = t & VT_BTYPE;
6546 if (bt == VT_BYTE || bt == VT_BOOL)
6547 r |= VT_LVAL_BYTE;
6548 else if (bt == VT_SHORT)
6549 r |= VT_LVAL_SHORT;
6550 else
6551 return r;
6552 if (t & VT_UNSIGNED)
6553 r |= VT_LVAL_UNSIGNED;
6554 return r;
6557 /* indirection with full error checking and bound check */
6558 static void indir(void)
6560 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6561 expect("pointer");
6562 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6563 gv(RC_INT);
6564 vtop->type = *pointed_type(&vtop->type);
6565 /* an array is never an lvalue */
6566 if (!(vtop->type.t & VT_ARRAY)) {
6567 vtop->r |= lvalue_type(vtop->type.t);
6568 /* if bound checking, the referenced pointer must be checked */
6569 if (do_bounds_check)
6570 vtop->r |= VT_MUSTBOUND;
6574 /* pass a parameter to a function and do type checking and casting */
6575 static void gfunc_param_typed(Sym *func, Sym *arg)
6577 int func_type;
6578 CType type;
6580 func_type = func->c;
6581 if (func_type == FUNC_OLD ||
6582 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6583 /* default casting : only need to convert float to double */
6584 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6585 type.t = VT_DOUBLE;
6586 gen_cast(&type);
6588 } else if (arg == NULL) {
6589 error("too many arguments to function");
6590 } else {
6591 type = arg->type;
6592 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6593 gen_assign_cast(&type);
6597 /* parse an expression of the form '(type)' or '(expr)' and return its
6598 type */
6599 static void parse_expr_type(CType *type)
6601 int n;
6602 AttributeDef ad;
6604 skip('(');
6605 if (parse_btype(type, &ad)) {
6606 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6607 } else {
6608 expr_type(type);
6610 skip(')');
6613 static void parse_type(CType *type)
6615 AttributeDef ad;
6616 int n;
6618 if (!parse_btype(type, &ad)) {
6619 expect("type");
6621 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6624 static void vpush_tokc(int t)
6626 CType type;
6627 type.t = t;
6628 vsetc(&type, VT_CONST, &tokc);
6631 static void unary(void)
6633 int n, t, align, size, r;
6634 CType type;
6635 Sym *s;
6636 AttributeDef ad;
6638 /* XXX: GCC 2.95.3 does not generate a table although it should be
6639 better here */
6640 tok_next:
6641 switch(tok) {
6642 case TOK_EXTENSION:
6643 next();
6644 goto tok_next;
6645 case TOK_CINT:
6646 case TOK_CCHAR:
6647 case TOK_LCHAR:
6648 vpushi(tokc.i);
6649 next();
6650 break;
6651 case TOK_CUINT:
6652 vpush_tokc(VT_INT | VT_UNSIGNED);
6653 next();
6654 break;
6655 case TOK_CLLONG:
6656 vpush_tokc(VT_LLONG);
6657 next();
6658 break;
6659 case TOK_CULLONG:
6660 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6661 next();
6662 break;
6663 case TOK_CFLOAT:
6664 vpush_tokc(VT_FLOAT);
6665 next();
6666 break;
6667 case TOK_CDOUBLE:
6668 vpush_tokc(VT_DOUBLE);
6669 next();
6670 break;
6671 case TOK_CLDOUBLE:
6672 vpush_tokc(VT_LDOUBLE);
6673 next();
6674 break;
6675 case TOK___FUNCTION__:
6676 if (!gnu_ext)
6677 goto tok_identifier;
6678 /* fall thru */
6679 case TOK___FUNC__:
6681 void *ptr;
6682 int len;
6683 /* special function name identifier */
6684 len = strlen(funcname) + 1;
6685 /* generate char[len] type */
6686 type.t = VT_BYTE;
6687 mk_pointer(&type);
6688 type.t |= VT_ARRAY;
6689 type.ref->c = len;
6690 vpush_ref(&type, data_section, data_section->data_offset, len);
6691 ptr = section_ptr_add(data_section, len);
6692 memcpy(ptr, funcname, len);
6693 next();
6695 break;
6696 case TOK_LSTR:
6697 t = VT_INT;
6698 goto str_init;
6699 case TOK_STR:
6700 /* string parsing */
6701 t = VT_BYTE;
6702 str_init:
6703 if (tcc_state->warn_write_strings)
6704 t |= VT_CONSTANT;
6705 type.t = t;
6706 mk_pointer(&type);
6707 type.t |= VT_ARRAY;
6708 memset(&ad, 0, sizeof(AttributeDef));
6709 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6710 break;
6711 case '(':
6712 next();
6713 /* cast ? */
6714 if (parse_btype(&type, &ad)) {
6715 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6716 skip(')');
6717 /* check ISOC99 compound literal */
6718 if (tok == '{') {
6719 /* data is allocated locally by default */
6720 if (global_expr)
6721 r = VT_CONST;
6722 else
6723 r = VT_LOCAL;
6724 /* all except arrays are lvalues */
6725 if (!(type.t & VT_ARRAY))
6726 r |= lvalue_type(type.t);
6727 memset(&ad, 0, sizeof(AttributeDef));
6728 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6729 } else {
6730 unary();
6731 gen_cast(&type);
6733 } else if (tok == '{') {
6734 /* save all registers */
6735 save_regs(0);
6736 /* statement expression : we do not accept break/continue
6737 inside as GCC does */
6738 block(NULL, NULL, NULL, NULL, 0, 1);
6739 skip(')');
6740 } else {
6741 gexpr();
6742 skip(')');
6744 break;
6745 case '*':
6746 next();
6747 unary();
6748 indir();
6749 break;
6750 case '&':
6751 next();
6752 unary();
6753 /* functions names must be treated as function pointers,
6754 except for unary '&' and sizeof. Since we consider that
6755 functions are not lvalues, we only have to handle it
6756 there and in function calls. */
6757 /* arrays can also be used although they are not lvalues */
6758 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6759 !(vtop->type.t & VT_ARRAY))
6760 test_lvalue();
6761 mk_pointer(&vtop->type);
6762 gaddrof();
6763 break;
6764 case '!':
6765 next();
6766 unary();
6767 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6768 vtop->c.i = !vtop->c.i;
6769 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6770 vtop->c.i = vtop->c.i ^ 1;
6771 else
6772 vseti(VT_JMP, gtst(1, 0));
6773 break;
6774 case '~':
6775 next();
6776 unary();
6777 vpushi(-1);
6778 gen_op('^');
6779 break;
6780 case '+':
6781 next();
6782 /* in order to force cast, we add zero */
6783 unary();
6784 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6785 error("pointer not accepted for unary plus");
6786 vpushi(0);
6787 gen_op('+');
6788 break;
6789 case TOK_SIZEOF:
6790 case TOK_ALIGNOF1:
6791 case TOK_ALIGNOF2:
6792 t = tok;
6793 next();
6794 if (tok == '(') {
6795 parse_expr_type(&type);
6796 } else {
6797 unary_type(&type);
6799 size = type_size(&type, &align);
6800 if (t == TOK_SIZEOF) {
6801 if (size < 0)
6802 error("sizeof applied to an incomplete type");
6803 vpushi(size);
6804 } else {
6805 vpushi(align);
6807 break;
6809 case TOK_builtin_types_compatible_p:
6811 CType type1, type2;
6812 next();
6813 skip('(');
6814 parse_type(&type1);
6815 skip(',');
6816 parse_type(&type2);
6817 skip(')');
6818 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6819 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6820 vpushi(is_compatible_types(&type1, &type2));
6822 break;
6823 case TOK_builtin_constant_p:
6825 int saved_nocode_wanted, res;
6826 next();
6827 skip('(');
6828 saved_nocode_wanted = nocode_wanted;
6829 nocode_wanted = 1;
6830 gexpr();
6831 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6832 vpop();
6833 nocode_wanted = saved_nocode_wanted;
6834 skip(')');
6835 vpushi(res);
6837 break;
6838 case TOK_INC:
6839 case TOK_DEC:
6840 t = tok;
6841 next();
6842 unary();
6843 inc(0, t);
6844 break;
6845 case '-':
6846 next();
6847 vpushi(0);
6848 unary();
6849 gen_op('-');
6850 break;
6851 case TOK_LAND:
6852 if (!gnu_ext)
6853 goto tok_identifier;
6854 next();
6855 /* allow to take the address of a label */
6856 if (tok < TOK_UIDENT)
6857 expect("label identifier");
6858 s = label_find(tok);
6859 if (!s) {
6860 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6861 } else {
6862 if (s->r == LABEL_DECLARED)
6863 s->r = LABEL_FORWARD;
6865 if (!s->type.t) {
6866 s->type.t = VT_VOID;
6867 mk_pointer(&s->type);
6868 s->type.t |= VT_STATIC;
6870 vset(&s->type, VT_CONST | VT_SYM, 0);
6871 vtop->sym = s;
6872 next();
6873 break;
6874 default:
6875 tok_identifier:
6876 t = tok;
6877 next();
6878 if (t < TOK_UIDENT)
6879 expect("identifier");
6880 s = sym_find(t);
6881 if (!s) {
6882 if (tok != '(')
6883 error("'%s' undeclared", get_tok_str(t, NULL));
6884 /* for simple function calls, we tolerate undeclared
6885 external reference to int() function */
6886 s = external_global_sym(t, &func_old_type, 0);
6888 vset(&s->type, s->r, s->c);
6889 /* if forward reference, we must point to s */
6890 if (vtop->r & VT_SYM) {
6891 vtop->sym = s;
6892 vtop->c.ul = 0;
6894 break;
6897 /* post operations */
6898 while (1) {
6899 if (tok == TOK_INC || tok == TOK_DEC) {
6900 inc(1, tok);
6901 next();
6902 } else if (tok == '.' || tok == TOK_ARROW) {
6903 /* field */
6904 if (tok == TOK_ARROW)
6905 indir();
6906 test_lvalue();
6907 gaddrof();
6908 next();
6909 /* expect pointer on structure */
6910 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6911 expect("struct or union");
6912 s = vtop->type.ref;
6913 /* find field */
6914 tok |= SYM_FIELD;
6915 while ((s = s->next) != NULL) {
6916 if (s->v == tok)
6917 break;
6919 if (!s)
6920 error("field not found");
6921 /* add field offset to pointer */
6922 vtop->type = char_pointer_type; /* change type to 'char *' */
6923 vpushi(s->c);
6924 gen_op('+');
6925 /* change type to field type, and set to lvalue */
6926 vtop->type = s->type;
6927 /* an array is never an lvalue */
6928 if (!(vtop->type.t & VT_ARRAY)) {
6929 vtop->r |= lvalue_type(vtop->type.t);
6930 /* if bound checking, the referenced pointer must be checked */
6931 if (do_bounds_check)
6932 vtop->r |= VT_MUSTBOUND;
6934 next();
6935 } else if (tok == '[') {
6936 next();
6937 gexpr();
6938 gen_op('+');
6939 indir();
6940 skip(']');
6941 } else if (tok == '(') {
6942 SValue ret;
6943 Sym *sa;
6944 int nb_args;
6946 /* function call */
6947 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
6948 /* pointer test (no array accepted) */
6949 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
6950 vtop->type = *pointed_type(&vtop->type);
6951 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
6952 goto error_func;
6953 } else {
6954 error_func:
6955 expect("function pointer");
6957 } else {
6958 vtop->r &= ~VT_LVAL; /* no lvalue */
6960 /* get return type */
6961 s = vtop->type.ref;
6962 next();
6963 sa = s->next; /* first parameter */
6964 nb_args = 0;
6965 /* compute first implicit argument if a structure is returned */
6966 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
6967 /* get some space for the returned structure */
6968 size = type_size(&s->type, &align);
6969 loc = (loc - size) & -align;
6970 ret.type = s->type;
6971 ret.r = VT_LOCAL | VT_LVAL;
6972 /* pass it as 'int' to avoid structure arg passing
6973 problems */
6974 vseti(VT_LOCAL, loc);
6975 ret.c = vtop->c;
6976 nb_args++;
6977 } else {
6978 ret.type = s->type;
6979 ret.r2 = VT_CONST;
6980 /* return in register */
6981 if (is_float(ret.type.t)) {
6982 ret.r = REG_FRET;
6983 } else {
6984 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
6985 ret.r2 = REG_LRET;
6986 ret.r = REG_IRET;
6988 ret.c.i = 0;
6990 if (tok != ')') {
6991 for(;;) {
6992 expr_eq();
6993 gfunc_param_typed(s, sa);
6994 nb_args++;
6995 if (sa)
6996 sa = sa->next;
6997 if (tok == ')')
6998 break;
6999 skip(',');
7002 if (sa)
7003 error("too few arguments to function");
7004 skip(')');
7005 if (!nocode_wanted) {
7006 gfunc_call(nb_args);
7007 } else {
7008 vtop -= (nb_args + 1);
7010 /* return value */
7011 vsetc(&ret.type, ret.r, &ret.c);
7012 vtop->r2 = ret.r2;
7013 } else {
7014 break;
7019 static void uneq(void)
7021 int t;
7023 unary();
7024 if (tok == '=' ||
7025 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7026 tok == TOK_A_XOR || tok == TOK_A_OR ||
7027 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7028 test_lvalue();
7029 t = tok;
7030 next();
7031 if (t == '=') {
7032 expr_eq();
7033 } else {
7034 vdup();
7035 expr_eq();
7036 gen_op(t & 0x7f);
7038 vstore();
7042 static void expr_prod(void)
7044 int t;
7046 uneq();
7047 while (tok == '*' || tok == '/' || tok == '%') {
7048 t = tok;
7049 next();
7050 uneq();
7051 gen_op(t);
7055 static void expr_sum(void)
7057 int t;
7059 expr_prod();
7060 while (tok == '+' || tok == '-') {
7061 t = tok;
7062 next();
7063 expr_prod();
7064 gen_op(t);
7068 static void expr_shift(void)
7070 int t;
7072 expr_sum();
7073 while (tok == TOK_SHL || tok == TOK_SAR) {
7074 t = tok;
7075 next();
7076 expr_sum();
7077 gen_op(t);
7081 static void expr_cmp(void)
7083 int t;
7085 expr_shift();
7086 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7087 tok == TOK_ULT || tok == TOK_UGE) {
7088 t = tok;
7089 next();
7090 expr_shift();
7091 gen_op(t);
7095 static void expr_cmpeq(void)
7097 int t;
7099 expr_cmp();
7100 while (tok == TOK_EQ || tok == TOK_NE) {
7101 t = tok;
7102 next();
7103 expr_cmp();
7104 gen_op(t);
7108 static void expr_and(void)
7110 expr_cmpeq();
7111 while (tok == '&') {
7112 next();
7113 expr_cmpeq();
7114 gen_op('&');
7118 static void expr_xor(void)
7120 expr_and();
7121 while (tok == '^') {
7122 next();
7123 expr_and();
7124 gen_op('^');
7128 static void expr_or(void)
7130 expr_xor();
7131 while (tok == '|') {
7132 next();
7133 expr_xor();
7134 gen_op('|');
7138 /* XXX: fix this mess */
7139 static void expr_land_const(void)
7141 expr_or();
7142 while (tok == TOK_LAND) {
7143 next();
7144 expr_or();
7145 gen_op(TOK_LAND);
7149 /* XXX: fix this mess */
7150 static void expr_lor_const(void)
7152 expr_land_const();
7153 while (tok == TOK_LOR) {
7154 next();
7155 expr_land_const();
7156 gen_op(TOK_LOR);
7160 /* only used if non constant */
7161 static void expr_land(void)
7163 int t;
7165 expr_or();
7166 if (tok == TOK_LAND) {
7167 t = 0;
7168 for(;;) {
7169 t = gtst(1, t);
7170 if (tok != TOK_LAND) {
7171 vseti(VT_JMPI, t);
7172 break;
7174 next();
7175 expr_or();
7180 static void expr_lor(void)
7182 int t;
7184 expr_land();
7185 if (tok == TOK_LOR) {
7186 t = 0;
7187 for(;;) {
7188 t = gtst(0, t);
7189 if (tok != TOK_LOR) {
7190 vseti(VT_JMP, t);
7191 break;
7193 next();
7194 expr_land();
7199 /* XXX: better constant handling */
7200 static void expr_eq(void)
7202 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7203 SValue sv;
7204 CType type, type1, type2;
7206 if (const_wanted) {
7207 int c1, c;
7208 expr_lor_const();
7209 if (tok == '?') {
7210 c = vtop->c.i;
7211 vpop();
7212 next();
7213 if (tok == ':' && gnu_ext) {
7214 c1 = c;
7215 } else {
7216 gexpr();
7217 c1 = vtop->c.i;
7218 vpop();
7220 skip(':');
7221 expr_eq();
7222 if (c)
7223 vtop->c.i = c1;
7225 } else {
7226 expr_lor();
7227 if (tok == '?') {
7228 next();
7229 if (vtop != vstack) {
7230 /* needed to avoid having different registers saved in
7231 each branch */
7232 if (is_float(vtop->type.t))
7233 rc = RC_FLOAT;
7234 else
7235 rc = RC_INT;
7236 gv(rc);
7237 save_regs(1);
7239 if (tok == ':' && gnu_ext) {
7240 gv_dup();
7241 tt = gtst(1, 0);
7242 } else {
7243 tt = gtst(1, 0);
7244 gexpr();
7246 type1 = vtop->type;
7247 sv = *vtop; /* save value to handle it later */
7248 vtop--; /* no vpop so that FP stack is not flushed */
7249 skip(':');
7250 u = gjmp(0);
7251 gsym(tt);
7252 expr_eq();
7253 type2 = vtop->type;
7255 t1 = type1.t;
7256 bt1 = t1 & VT_BTYPE;
7257 t2 = type2.t;
7258 bt2 = t2 & VT_BTYPE;
7259 /* cast operands to correct type according to ISOC rules */
7260 if (is_float(bt1) || is_float(bt2)) {
7261 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7262 type.t = VT_LDOUBLE;
7263 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7264 type.t = VT_DOUBLE;
7265 } else {
7266 type.t = VT_FLOAT;
7268 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7269 /* cast to biggest op */
7270 type.t = VT_LLONG;
7271 /* convert to unsigned if it does not fit in a long long */
7272 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7273 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7274 type.t |= VT_UNSIGNED;
7275 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7276 /* XXX: test pointer compatibility */
7277 type = type1;
7278 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7279 /* XXX: test structure compatibility */
7280 type = type1;
7281 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7282 /* NOTE: as an extension, we accept void on only one side */
7283 type.t = VT_VOID;
7284 } else {
7285 /* integer operations */
7286 type.t = VT_INT;
7287 /* convert to unsigned if it does not fit in an integer */
7288 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7289 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7290 type.t |= VT_UNSIGNED;
7293 /* now we convert second operand */
7294 gen_cast(&type);
7295 rc = RC_INT;
7296 if (is_float(type.t)) {
7297 rc = RC_FLOAT;
7298 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7299 /* for long longs, we use fixed registers to avoid having
7300 to handle a complicated move */
7301 rc = RC_IRET;
7304 r2 = gv(rc);
7305 /* this is horrible, but we must also convert first
7306 operand */
7307 tt = gjmp(0);
7308 gsym(u);
7309 /* put again first value and cast it */
7310 *vtop = sv;
7311 gen_cast(&type);
7312 r1 = gv(rc);
7313 move_reg(r2, r1);
7314 vtop->r = r2;
7315 gsym(tt);
7320 static void gexpr(void)
7322 while (1) {
7323 expr_eq();
7324 if (tok != ',')
7325 break;
7326 vpop();
7327 next();
7331 /* parse an expression and return its type without any side effect. */
7332 static void expr_type(CType *type)
7334 int saved_nocode_wanted;
7336 saved_nocode_wanted = nocode_wanted;
7337 nocode_wanted = 1;
7338 gexpr();
7339 *type = vtop->type;
7340 vpop();
7341 nocode_wanted = saved_nocode_wanted;
7344 /* parse a unary expression and return its type without any side
7345 effect. */
7346 static void unary_type(CType *type)
7348 int a;
7350 a = nocode_wanted;
7351 nocode_wanted = 1;
7352 unary();
7353 *type = vtop->type;
7354 vpop();
7355 nocode_wanted = a;
7358 /* parse a constant expression and return value in vtop. */
7359 static void expr_const1(void)
7361 int a;
7362 a = const_wanted;
7363 const_wanted = 1;
7364 expr_eq();
7365 const_wanted = a;
7368 /* parse an integer constant and return its value. */
7369 static int expr_const(void)
7371 int c;
7372 expr_const1();
7373 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7374 expect("constant expression");
7375 c = vtop->c.i;
7376 vpop();
7377 return c;
7380 /* return the label token if current token is a label, otherwise
7381 return zero */
7382 static int is_label(void)
7384 int last_tok;
7386 /* fast test first */
7387 if (tok < TOK_UIDENT)
7388 return 0;
7389 /* no need to save tokc because tok is an identifier */
7390 last_tok = tok;
7391 next();
7392 if (tok == ':') {
7393 next();
7394 return last_tok;
7395 } else {
7396 unget_tok(last_tok);
7397 return 0;
7401 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7402 int case_reg, int is_expr)
7404 int a, b, c, d;
7405 Sym *s;
7407 /* generate line number info */
7408 if (do_debug &&
7409 (last_line_num != file->line_num || last_ind != ind)) {
7410 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7411 last_ind = ind;
7412 last_line_num = file->line_num;
7415 if (is_expr) {
7416 /* default return value is (void) */
7417 vpushi(0);
7418 vtop->type.t = VT_VOID;
7421 if (tok == TOK_IF) {
7422 /* if test */
7423 next();
7424 skip('(');
7425 gexpr();
7426 skip(')');
7427 a = gtst(1, 0);
7428 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7429 c = tok;
7430 if (c == TOK_ELSE) {
7431 next();
7432 d = gjmp(0);
7433 gsym(a);
7434 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7435 gsym(d); /* patch else jmp */
7436 } else
7437 gsym(a);
7438 } else if (tok == TOK_WHILE) {
7439 next();
7440 d = ind;
7441 skip('(');
7442 gexpr();
7443 skip(')');
7444 a = gtst(1, 0);
7445 b = 0;
7446 block(&a, &b, case_sym, def_sym, case_reg, 0);
7447 gjmp_addr(d);
7448 gsym(a);
7449 gsym_addr(b, d);
7450 } else if (tok == '{') {
7451 Sym *llabel;
7453 next();
7454 /* record local declaration stack position */
7455 s = local_stack;
7456 llabel = local_label_stack;
7457 /* handle local labels declarations */
7458 if (tok == TOK_LABEL) {
7459 next();
7460 for(;;) {
7461 if (tok < TOK_UIDENT)
7462 expect("label identifier");
7463 label_push(&local_label_stack, tok, LABEL_DECLARED);
7464 next();
7465 if (tok == ',') {
7466 next();
7467 } else {
7468 skip(';');
7469 break;
7473 while (tok != '}') {
7474 decl(VT_LOCAL);
7475 if (tok != '}') {
7476 if (is_expr)
7477 vpop();
7478 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7481 /* pop locally defined labels */
7482 label_pop(&local_label_stack, llabel);
7483 /* pop locally defined symbols */
7484 sym_pop(&local_stack, s);
7485 next();
7486 } else if (tok == TOK_RETURN) {
7487 next();
7488 if (tok != ';') {
7489 gexpr();
7490 gen_assign_cast(&func_vt);
7491 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7492 CType type;
7493 /* if returning structure, must copy it to implicit
7494 first pointer arg location */
7495 type = func_vt;
7496 mk_pointer(&type);
7497 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7498 indir();
7499 vswap();
7500 /* copy structure value to pointer */
7501 vstore();
7502 } else if (is_float(func_vt.t)) {
7503 gv(RC_FRET);
7504 } else {
7505 gv(RC_IRET);
7507 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7509 skip(';');
7510 rsym = gjmp(rsym); /* jmp */
7511 } else if (tok == TOK_BREAK) {
7512 /* compute jump */
7513 if (!bsym)
7514 error("cannot break");
7515 *bsym = gjmp(*bsym);
7516 next();
7517 skip(';');
7518 } else if (tok == TOK_CONTINUE) {
7519 /* compute jump */
7520 if (!csym)
7521 error("cannot continue");
7522 *csym = gjmp(*csym);
7523 next();
7524 skip(';');
7525 } else if (tok == TOK_FOR) {
7526 int e;
7527 next();
7528 skip('(');
7529 if (tok != ';') {
7530 gexpr();
7531 vpop();
7533 skip(';');
7534 d = ind;
7535 c = ind;
7536 a = 0;
7537 b = 0;
7538 if (tok != ';') {
7539 gexpr();
7540 a = gtst(1, 0);
7542 skip(';');
7543 if (tok != ')') {
7544 e = gjmp(0);
7545 c = ind;
7546 gexpr();
7547 vpop();
7548 gjmp_addr(d);
7549 gsym(e);
7551 skip(')');
7552 block(&a, &b, case_sym, def_sym, case_reg, 0);
7553 gjmp_addr(c);
7554 gsym(a);
7555 gsym_addr(b, c);
7556 } else
7557 if (tok == TOK_DO) {
7558 next();
7559 a = 0;
7560 b = 0;
7561 d = ind;
7562 block(&a, &b, case_sym, def_sym, case_reg, 0);
7563 skip(TOK_WHILE);
7564 skip('(');
7565 gsym(b);
7566 gexpr();
7567 c = gtst(0, 0);
7568 gsym_addr(c, d);
7569 skip(')');
7570 gsym(a);
7571 skip(';');
7572 } else
7573 if (tok == TOK_SWITCH) {
7574 next();
7575 skip('(');
7576 gexpr();
7577 /* XXX: other types than integer */
7578 case_reg = gv(RC_INT);
7579 vpop();
7580 skip(')');
7581 a = 0;
7582 b = gjmp(0); /* jump to first case */
7583 c = 0;
7584 block(&a, csym, &b, &c, case_reg, 0);
7585 /* if no default, jmp after switch */
7586 if (c == 0)
7587 c = ind;
7588 /* default label */
7589 gsym_addr(b, c);
7590 /* break label */
7591 gsym(a);
7592 } else
7593 if (tok == TOK_CASE) {
7594 int v1, v2;
7595 if (!case_sym)
7596 expect("switch");
7597 next();
7598 v1 = expr_const();
7599 v2 = v1;
7600 if (gnu_ext && tok == TOK_DOTS) {
7601 next();
7602 v2 = expr_const();
7603 if (v2 < v1)
7604 warning("empty case range");
7606 /* since a case is like a label, we must skip it with a jmp */
7607 b = gjmp(0);
7608 gsym(*case_sym);
7609 vseti(case_reg, 0);
7610 vpushi(v1);
7611 if (v1 == v2) {
7612 gen_op(TOK_EQ);
7613 *case_sym = gtst(1, 0);
7614 } else {
7615 gen_op(TOK_GE);
7616 *case_sym = gtst(1, 0);
7617 vseti(case_reg, 0);
7618 vpushi(v2);
7619 gen_op(TOK_LE);
7620 *case_sym = gtst(1, *case_sym);
7622 gsym(b);
7623 skip(':');
7624 is_expr = 0;
7625 goto block_after_label;
7626 } else
7627 if (tok == TOK_DEFAULT) {
7628 next();
7629 skip(':');
7630 if (!def_sym)
7631 expect("switch");
7632 if (*def_sym)
7633 error("too many 'default'");
7634 *def_sym = ind;
7635 is_expr = 0;
7636 goto block_after_label;
7637 } else
7638 if (tok == TOK_GOTO) {
7639 next();
7640 if (tok == '*' && gnu_ext) {
7641 /* computed goto */
7642 next();
7643 gexpr();
7644 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7645 expect("pointer");
7646 ggoto();
7647 } else if (tok >= TOK_UIDENT) {
7648 s = label_find(tok);
7649 /* put forward definition if needed */
7650 if (!s) {
7651 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7652 } else {
7653 if (s->r == LABEL_DECLARED)
7654 s->r = LABEL_FORWARD;
7656 /* label already defined */
7657 if (s->r & LABEL_FORWARD)
7658 s->next = (void *)gjmp((long)s->next);
7659 else
7660 gjmp_addr((long)s->next);
7661 next();
7662 } else {
7663 expect("label identifier");
7665 skip(';');
7666 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7667 asm_instr();
7668 } else {
7669 b = is_label();
7670 if (b) {
7671 /* label case */
7672 s = label_find(b);
7673 if (s) {
7674 if (s->r == LABEL_DEFINED)
7675 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7676 gsym((long)s->next);
7677 s->r = LABEL_DEFINED;
7678 } else {
7679 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7681 s->next = (void *)ind;
7682 /* we accept this, but it is a mistake */
7683 block_after_label:
7684 if (tok == '}') {
7685 warning("deprecated use of label at end of compound statement");
7686 } else {
7687 if (is_expr)
7688 vpop();
7689 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7691 } else {
7692 /* expression case */
7693 if (tok != ';') {
7694 if (is_expr) {
7695 vpop();
7696 gexpr();
7697 } else {
7698 gexpr();
7699 vpop();
7702 skip(';');
7707 /* t is the array or struct type. c is the array or struct
7708 address. cur_index/cur_field is the pointer to the current
7709 value. 'size_only' is true if only size info is needed (only used
7710 in arrays) */
7711 static void decl_designator(CType *type, Section *sec, unsigned long c,
7712 int *cur_index, Sym **cur_field,
7713 int size_only)
7715 Sym *s, *f;
7716 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7717 CType type1;
7719 notfirst = 0;
7720 elem_size = 0;
7721 nb_elems = 1;
7722 if (gnu_ext && (l = is_label()) != 0)
7723 goto struct_field;
7724 while (tok == '[' || tok == '.') {
7725 if (tok == '[') {
7726 if (!(type->t & VT_ARRAY))
7727 expect("array type");
7728 s = type->ref;
7729 next();
7730 index = expr_const();
7731 if (index < 0 || (s->c >= 0 && index >= s->c))
7732 expect("invalid index");
7733 if (tok == TOK_DOTS && gnu_ext) {
7734 next();
7735 index_last = expr_const();
7736 if (index_last < 0 ||
7737 (s->c >= 0 && index_last >= s->c) ||
7738 index_last < index)
7739 expect("invalid index");
7740 } else {
7741 index_last = index;
7743 skip(']');
7744 if (!notfirst)
7745 *cur_index = index_last;
7746 type = pointed_type(type);
7747 elem_size = type_size(type, &align);
7748 c += index * elem_size;
7749 /* NOTE: we only support ranges for last designator */
7750 nb_elems = index_last - index + 1;
7751 if (nb_elems != 1) {
7752 notfirst = 1;
7753 break;
7755 } else {
7756 next();
7757 l = tok;
7758 next();
7759 struct_field:
7760 if ((type->t & VT_BTYPE) != VT_STRUCT)
7761 expect("struct/union type");
7762 s = type->ref;
7763 l |= SYM_FIELD;
7764 f = s->next;
7765 while (f) {
7766 if (f->v == l)
7767 break;
7768 f = f->next;
7770 if (!f)
7771 expect("field");
7772 if (!notfirst)
7773 *cur_field = f;
7774 /* XXX: fix this mess by using explicit storage field */
7775 type1 = f->type;
7776 type1.t |= (type->t & ~VT_TYPE);
7777 type = &type1;
7778 c += f->c;
7780 notfirst = 1;
7782 if (notfirst) {
7783 if (tok == '=') {
7784 next();
7785 } else {
7786 if (!gnu_ext)
7787 expect("=");
7789 } else {
7790 if (type->t & VT_ARRAY) {
7791 index = *cur_index;
7792 type = pointed_type(type);
7793 c += index * type_size(type, &align);
7794 } else {
7795 f = *cur_field;
7796 if (!f)
7797 error("too many field init");
7798 /* XXX: fix this mess by using explicit storage field */
7799 type1 = f->type;
7800 type1.t |= (type->t & ~VT_TYPE);
7801 type = &type1;
7802 c += f->c;
7805 decl_initializer(type, sec, c, 0, size_only);
7807 /* XXX: make it more general */
7808 if (!size_only && nb_elems > 1) {
7809 unsigned long c_end;
7810 uint8_t *src, *dst;
7811 int i;
7813 if (!sec)
7814 error("range init not supported yet for dynamic storage");
7815 c_end = c + nb_elems * elem_size;
7816 if (c_end > sec->data_allocated)
7817 section_realloc(sec, c_end);
7818 src = sec->data + c;
7819 dst = src;
7820 for(i = 1; i < nb_elems; i++) {
7821 dst += elem_size;
7822 memcpy(dst, src, elem_size);
7827 #define EXPR_VAL 0
7828 #define EXPR_CONST 1
7829 #define EXPR_ANY 2
7831 /* store a value or an expression directly in global data or in local array */
7832 static void init_putv(CType *type, Section *sec, unsigned long c,
7833 int v, int expr_type)
7835 int saved_global_expr, bt, bit_pos, bit_size;
7836 void *ptr;
7837 unsigned long long bit_mask;
7838 CType dtype;
7840 switch(expr_type) {
7841 case EXPR_VAL:
7842 vpushi(v);
7843 break;
7844 case EXPR_CONST:
7845 /* compound literals must be allocated globally in this case */
7846 saved_global_expr = global_expr;
7847 global_expr = 1;
7848 expr_const1();
7849 global_expr = saved_global_expr;
7850 /* NOTE: symbols are accepted */
7851 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
7852 error("initializer element is not constant");
7853 break;
7854 case EXPR_ANY:
7855 expr_eq();
7856 break;
7859 dtype = *type;
7860 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7862 if (sec) {
7863 /* XXX: not portable */
7864 /* XXX: generate error if incorrect relocation */
7865 gen_assign_cast(&dtype);
7866 bt = type->t & VT_BTYPE;
7867 ptr = sec->data + c;
7868 /* XXX: make code faster ? */
7869 if (!(type->t & VT_BITFIELD)) {
7870 bit_pos = 0;
7871 bit_size = 32;
7872 bit_mask = -1LL;
7873 } else {
7874 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
7875 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
7876 bit_mask = (1LL << bit_size) - 1;
7878 if ((vtop->r & VT_SYM) &&
7879 (bt == VT_BYTE ||
7880 bt == VT_SHORT ||
7881 bt == VT_DOUBLE ||
7882 bt == VT_LDOUBLE ||
7883 bt == VT_LLONG ||
7884 (bt == VT_INT && bit_size != 32)))
7885 error("initializer element is not computable at load time");
7886 switch(bt) {
7887 case VT_BYTE:
7888 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7889 break;
7890 case VT_SHORT:
7891 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7892 break;
7893 case VT_DOUBLE:
7894 *(double *)ptr = vtop->c.d;
7895 break;
7896 case VT_LDOUBLE:
7897 *(long double *)ptr = vtop->c.ld;
7898 break;
7899 case VT_LLONG:
7900 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
7901 break;
7902 default:
7903 if (vtop->r & VT_SYM) {
7904 greloc(sec, vtop->sym, c, R_DATA_32);
7906 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7907 break;
7909 vtop--;
7910 } else {
7911 vset(&dtype, VT_LOCAL, c);
7912 vswap();
7913 vstore();
7914 vpop();
7918 /* put zeros for variable based init */
7919 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
7921 if (sec) {
7922 /* nothing to do because globals are already set to zero */
7923 } else {
7924 vpush_global_sym(&func_old_type, TOK_memset);
7925 vseti(VT_LOCAL, c);
7926 vpushi(0);
7927 vpushi(size);
7928 gfunc_call(3);
7932 /* 't' contains the type and storage info. 'c' is the offset of the
7933 object in section 'sec'. If 'sec' is NULL, it means stack based
7934 allocation. 'first' is true if array '{' must be read (multi
7935 dimension implicit array init handling). 'size_only' is true if
7936 size only evaluation is wanted (only for arrays). */
7937 static void decl_initializer(CType *type, Section *sec, unsigned long c,
7938 int first, int size_only)
7940 int index, array_length, n, no_oblock, nb, parlevel, i;
7941 int size1, align1, expr_type;
7942 Sym *s, *f;
7943 CType *t1;
7945 if (type->t & VT_ARRAY) {
7946 s = type->ref;
7947 n = s->c;
7948 array_length = 0;
7949 t1 = pointed_type(type);
7950 size1 = type_size(t1, &align1);
7952 no_oblock = 1;
7953 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
7954 tok == '{') {
7955 skip('{');
7956 no_oblock = 0;
7959 /* only parse strings here if correct type (otherwise: handle
7960 them as ((w)char *) expressions */
7961 if ((tok == TOK_LSTR &&
7962 (t1->t & VT_BTYPE) == VT_INT) ||
7963 (tok == TOK_STR &&
7964 (t1->t & VT_BTYPE) == VT_BYTE)) {
7965 while (tok == TOK_STR || tok == TOK_LSTR) {
7966 int cstr_len, ch;
7967 CString *cstr;
7969 cstr = tokc.cstr;
7970 /* compute maximum number of chars wanted */
7971 if (tok == TOK_STR)
7972 cstr_len = cstr->size;
7973 else
7974 cstr_len = cstr->size / sizeof(int);
7975 cstr_len--;
7976 nb = cstr_len;
7977 if (n >= 0 && nb > (n - array_length))
7978 nb = n - array_length;
7979 if (!size_only) {
7980 if (cstr_len > nb)
7981 warning("initializer-string for array is too long");
7982 /* in order to go faster for common case (char
7983 string in global variable, we handle it
7984 specifically */
7985 if (sec && tok == TOK_STR && size1 == 1) {
7986 memcpy(sec->data + c + array_length, cstr->data, nb);
7987 } else {
7988 for(i=0;i<nb;i++) {
7989 if (tok == TOK_STR)
7990 ch = ((unsigned char *)cstr->data)[i];
7991 else
7992 ch = ((int *)cstr->data)[i];
7993 init_putv(t1, sec, c + (array_length + i) * size1,
7994 ch, EXPR_VAL);
7998 array_length += nb;
7999 next();
8001 /* only add trailing zero if enough storage (no
8002 warning in this case since it is standard) */
8003 if (n < 0 || array_length < n) {
8004 if (!size_only) {
8005 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8007 array_length++;
8009 } else {
8010 index = 0;
8011 while (tok != '}') {
8012 decl_designator(type, sec, c, &index, NULL, size_only);
8013 if (n >= 0 && index >= n)
8014 error("index too large");
8015 /* must put zero in holes (note that doing it that way
8016 ensures that it even works with designators) */
8017 if (!size_only && array_length < index) {
8018 init_putz(t1, sec, c + array_length * size1,
8019 (index - array_length) * size1);
8021 index++;
8022 if (index > array_length)
8023 array_length = index;
8024 /* special test for multi dimensional arrays (may not
8025 be strictly correct if designators are used at the
8026 same time) */
8027 if (index >= n && no_oblock)
8028 break;
8029 if (tok == '}')
8030 break;
8031 skip(',');
8034 if (!no_oblock)
8035 skip('}');
8036 /* put zeros at the end */
8037 if (!size_only && n >= 0 && array_length < n) {
8038 init_putz(t1, sec, c + array_length * size1,
8039 (n - array_length) * size1);
8041 /* patch type size if needed */
8042 if (n < 0)
8043 s->c = array_length;
8044 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8045 (sec || !first || tok == '{')) {
8046 int par_count;
8048 /* NOTE: the previous test is a specific case for automatic
8049 struct/union init */
8050 /* XXX: union needs only one init */
8052 /* XXX: this test is incorrect for local initializers
8053 beginning with ( without {. It would be much more difficult
8054 to do it correctly (ideally, the expression parser should
8055 be used in all cases) */
8056 par_count = 0;
8057 if (tok == '(') {
8058 AttributeDef ad1;
8059 CType type1;
8060 next();
8061 while (tok == '(') {
8062 par_count++;
8063 next();
8065 if (!parse_btype(&type1, &ad1))
8066 expect("cast");
8067 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8068 #if 0
8069 if (!is_assignable_types(type, &type1))
8070 error("invalid type for cast");
8071 #endif
8072 skip(')');
8074 no_oblock = 1;
8075 if (first || tok == '{') {
8076 skip('{');
8077 no_oblock = 0;
8079 s = type->ref;
8080 f = s->next;
8081 array_length = 0;
8082 index = 0;
8083 n = s->c;
8084 while (tok != '}') {
8085 decl_designator(type, sec, c, NULL, &f, size_only);
8086 index = f->c;
8087 if (!size_only && array_length < index) {
8088 init_putz(type, sec, c + array_length,
8089 index - array_length);
8091 index = index + type_size(&f->type, &align1);
8092 if (index > array_length)
8093 array_length = index;
8094 f = f->next;
8095 if (no_oblock && f == NULL)
8096 break;
8097 if (tok == '}')
8098 break;
8099 skip(',');
8101 /* put zeros at the end */
8102 if (!size_only && array_length < n) {
8103 init_putz(type, sec, c + array_length,
8104 n - array_length);
8106 if (!no_oblock)
8107 skip('}');
8108 while (par_count) {
8109 skip(')');
8110 par_count--;
8112 } else if (tok == '{') {
8113 next();
8114 decl_initializer(type, sec, c, first, size_only);
8115 skip('}');
8116 } else if (size_only) {
8117 /* just skip expression */
8118 parlevel = 0;
8119 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8120 tok != -1) {
8121 if (tok == '(')
8122 parlevel++;
8123 else if (tok == ')')
8124 parlevel--;
8125 next();
8127 } else {
8128 /* currently, we always use constant expression for globals
8129 (may change for scripting case) */
8130 expr_type = EXPR_CONST;
8131 if (!sec)
8132 expr_type = EXPR_ANY;
8133 init_putv(type, sec, c, 0, expr_type);
8137 /* parse an initializer for type 't' if 'has_init' is non zero, and
8138 allocate space in local or global data space ('r' is either
8139 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8140 variable 'v' of scope 'scope' is declared before initializers are
8141 parsed. If 'v' is zero, then a reference to the new object is put
8142 in the value stack. If 'has_init' is 2, a special parsing is done
8143 to handle string constants. */
8144 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8145 int has_init, int v, int scope)
8147 int size, align, addr, data_offset;
8148 int level;
8149 ParseState saved_parse_state;
8150 TokenString init_str;
8151 Section *sec;
8153 size = type_size(type, &align);
8154 /* If unknown size, we must evaluate it before
8155 evaluating initializers because
8156 initializers can generate global data too
8157 (e.g. string pointers or ISOC99 compound
8158 literals). It also simplifies local
8159 initializers handling */
8160 tok_str_new(&init_str);
8161 if (size < 0) {
8162 if (!has_init)
8163 error("unknown type size");
8164 /* get all init string */
8165 if (has_init == 2) {
8166 /* only get strings */
8167 while (tok == TOK_STR || tok == TOK_LSTR) {
8168 tok_str_add_tok(&init_str);
8169 next();
8171 } else {
8172 level = 0;
8173 while (level > 0 || (tok != ',' && tok != ';')) {
8174 if (tok < 0)
8175 error("unexpected end of file in initializer");
8176 tok_str_add_tok(&init_str);
8177 if (tok == '{')
8178 level++;
8179 else if (tok == '}') {
8180 if (level == 0)
8181 break;
8182 level--;
8184 next();
8187 tok_str_add(&init_str, -1);
8188 tok_str_add(&init_str, 0);
8190 /* compute size */
8191 save_parse_state(&saved_parse_state);
8193 macro_ptr = init_str.str;
8194 next();
8195 decl_initializer(type, NULL, 0, 1, 1);
8196 /* prepare second initializer parsing */
8197 macro_ptr = init_str.str;
8198 next();
8200 /* if still unknown size, error */
8201 size = type_size(type, &align);
8202 if (size < 0)
8203 error("unknown type size");
8205 /* take into account specified alignment if bigger */
8206 if (ad->aligned > align)
8207 align = ad->aligned;
8208 if ((r & VT_VALMASK) == VT_LOCAL) {
8209 sec = NULL;
8210 if (do_bounds_check && (type->t & VT_ARRAY))
8211 loc--;
8212 loc = (loc - size) & -align;
8213 addr = loc;
8214 /* handles bounds */
8215 /* XXX: currently, since we do only one pass, we cannot track
8216 '&' operators, so we add only arrays */
8217 if (do_bounds_check && (type->t & VT_ARRAY)) {
8218 unsigned long *bounds_ptr;
8219 /* add padding between regions */
8220 loc--;
8221 /* then add local bound info */
8222 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8223 bounds_ptr[0] = addr;
8224 bounds_ptr[1] = size;
8226 if (v) {
8227 /* local variable */
8228 sym_push(v, type, r, addr);
8229 } else {
8230 /* push local reference */
8231 vset(type, r, addr);
8233 } else {
8234 Sym *sym;
8236 sym = NULL;
8237 if (v && scope == VT_CONST) {
8238 /* see if the symbol was already defined */
8239 sym = sym_find(v);
8240 if (sym) {
8241 if (!is_compatible_types(&sym->type, type))
8242 error("incompatible types for redefinition of '%s'",
8243 get_tok_str(v, NULL));
8244 if (sym->type.t & VT_EXTERN) {
8245 /* if the variable is extern, it was not allocated */
8246 sym->type.t &= ~VT_EXTERN;
8247 } else {
8248 /* we accept several definitions of the same
8249 global variable. this is tricky, because we
8250 must play with the SHN_COMMON type of the symbol */
8251 /* XXX: should check if the variable was already
8252 initialized. It is incorrect to initialized it
8253 twice */
8254 /* no init data, we won't add more to the symbol */
8255 if (!has_init)
8256 goto no_alloc;
8261 /* allocate symbol in corresponding section */
8262 sec = ad->section;
8263 if (!sec) {
8264 if (has_init)
8265 sec = data_section;
8267 if (sec) {
8268 data_offset = sec->data_offset;
8269 data_offset = (data_offset + align - 1) & -align;
8270 addr = data_offset;
8271 /* very important to increment global pointer at this time
8272 because initializers themselves can create new initializers */
8273 data_offset += size;
8274 /* add padding if bound check */
8275 if (do_bounds_check)
8276 data_offset++;
8277 sec->data_offset = data_offset;
8278 /* allocate section space to put the data */
8279 if (sec->sh_type != SHT_NOBITS &&
8280 data_offset > sec->data_allocated)
8281 section_realloc(sec, data_offset);
8282 } else {
8283 addr = 0; /* avoid warning */
8286 if (v) {
8287 if (scope == VT_CONST) {
8288 if (!sym)
8289 goto do_def;
8290 } else {
8291 do_def:
8292 sym = sym_push(v, type, r | VT_SYM, 0);
8294 /* update symbol definition */
8295 if (sec) {
8296 put_extern_sym(sym, sec, addr, size);
8297 } else {
8298 Elf32_Sym *esym;
8299 /* put a common area */
8300 put_extern_sym(sym, NULL, align, size);
8301 /* XXX: find a nicer way */
8302 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8303 esym->st_shndx = SHN_COMMON;
8305 } else {
8306 CValue cval;
8308 /* push global reference */
8309 sym = get_sym_ref(type, sec, addr, size);
8310 cval.ul = 0;
8311 vsetc(type, VT_CONST | VT_SYM, &cval);
8312 vtop->sym = sym;
8315 /* handles bounds now because the symbol must be defined
8316 before for the relocation */
8317 if (do_bounds_check) {
8318 unsigned long *bounds_ptr;
8320 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8321 /* then add global bound info */
8322 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8323 bounds_ptr[0] = 0; /* relocated */
8324 bounds_ptr[1] = size;
8327 if (has_init) {
8328 decl_initializer(type, sec, addr, 1, 0);
8329 /* restore parse state if needed */
8330 if (init_str.str) {
8331 tok_str_free(init_str.str);
8332 restore_parse_state(&saved_parse_state);
8335 no_alloc: ;
8338 void put_func_debug(Sym *sym)
8340 char buf[512];
8342 /* stabs info */
8343 /* XXX: we put here a dummy type */
8344 snprintf(buf, sizeof(buf), "%s:%c1",
8345 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8346 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8347 cur_text_section, sym->c);
8348 last_ind = 0;
8349 last_line_num = 0;
8352 /* not finished : try to put some local vars in registers */
8353 //#define CONFIG_REG_VARS
8355 #ifdef CONFIG_REG_VARS
8356 void add_var_ref(int t)
8358 printf("%s:%d: &%s\n",
8359 file->filename, file->line_num,
8360 get_tok_str(t, NULL));
8363 /* first pass on a function with heuristic to extract variable usage
8364 and pointer references to local variables for register allocation */
8365 void analyse_function(void)
8367 int level, t;
8369 for(;;) {
8370 if (tok == -1)
8371 break;
8372 /* any symbol coming after '&' is considered as being a
8373 variable whose reference is taken. It is highly unaccurate
8374 but it is difficult to do better without a complete parse */
8375 if (tok == '&') {
8376 next();
8377 /* if '& number', then no need to examine next tokens */
8378 if (tok == TOK_CINT ||
8379 tok == TOK_CUINT ||
8380 tok == TOK_CLLONG ||
8381 tok == TOK_CULLONG) {
8382 continue;
8383 } else if (tok >= TOK_UIDENT) {
8384 /* if '& ident [' or '& ident ->', then ident address
8385 is not needed */
8386 t = tok;
8387 next();
8388 if (tok != '[' && tok != TOK_ARROW)
8389 add_var_ref(t);
8390 } else {
8391 level = 0;
8392 while (tok != '}' && tok != ';' &&
8393 !((tok == ',' || tok == ')') && level == 0)) {
8394 if (tok >= TOK_UIDENT) {
8395 add_var_ref(tok);
8396 } else if (tok == '(') {
8397 level++;
8398 } else if (tok == ')') {
8399 level--;
8401 next();
8404 } else {
8405 next();
8409 #endif
8411 /* parse an old style function declaration list */
8412 /* XXX: check multiple parameter */
8413 static void func_decl_list(Sym *func_sym)
8415 AttributeDef ad;
8416 int v;
8417 Sym *s;
8418 CType btype, type;
8420 /* parse each declaration */
8421 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8422 if (!parse_btype(&btype, &ad))
8423 expect("declaration list");
8424 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8425 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8426 tok == ';') {
8427 /* we accept no variable after */
8428 } else {
8429 for(;;) {
8430 type = btype;
8431 type_decl(&type, &ad, &v, TYPE_DIRECT);
8432 /* find parameter in function parameter list */
8433 s = func_sym->next;
8434 while (s != NULL) {
8435 if ((s->v & ~SYM_FIELD) == v)
8436 goto found;
8437 s = s->next;
8439 error("declaration for parameter '%s' but no such parameter",
8440 get_tok_str(v, NULL));
8441 found:
8442 /* check that no storage specifier except 'register' was given */
8443 if (type.t & VT_STORAGE)
8444 error("storage class specified for '%s'", get_tok_str(v, NULL));
8445 convert_parameter_type(&type);
8446 /* we can add the type (NOTE: it could be local to the function) */
8447 s->type = type;
8448 /* accept other parameters */
8449 if (tok == ',')
8450 next();
8451 else
8452 break;
8455 skip(';');
8459 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8460 static void decl(int l)
8462 int v, has_init, r;
8463 CType type, btype;
8464 Sym *sym;
8465 AttributeDef ad;
8467 while (1) {
8468 if (!parse_btype(&btype, &ad)) {
8469 /* skip redundant ';' */
8470 /* XXX: find more elegant solution */
8471 if (tok == ';') {
8472 next();
8473 continue;
8475 /* special test for old K&R protos without explicit int
8476 type. Only accepted when defining global data */
8477 if (l == VT_LOCAL || tok < TOK_DEFINE)
8478 break;
8479 btype.t = VT_INT;
8481 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8482 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8483 tok == ';') {
8484 /* we accept no variable after */
8485 next();
8486 continue;
8488 while (1) { /* iterate thru each declaration */
8489 type = btype;
8490 type_decl(&type, &ad, &v, TYPE_DIRECT);
8491 #if 0
8493 char buf[500];
8494 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8495 printf("type = '%s'\n", buf);
8497 #endif
8498 if ((type.t & VT_BTYPE) == VT_FUNC) {
8499 /* if old style function prototype, we accept a
8500 declaration list */
8501 sym = type.ref;
8502 if (sym->c == FUNC_OLD)
8503 func_decl_list(sym);
8506 if (tok == '{') {
8507 #ifdef CONFIG_REG_VARS
8508 TokenString func_str;
8509 ParseState saved_parse_state;
8510 int block_level;
8511 #endif
8513 if (l == VT_LOCAL)
8514 error("cannot use local functions");
8515 if (!(type.t & VT_FUNC))
8516 expect("function definition");
8518 /* reject abstract declarators in function definition */
8519 sym = type.ref;
8520 while ((sym = sym->next) != NULL)
8521 if (!(sym->v & ~SYM_FIELD))
8522 expect("identifier");
8524 /* XXX: cannot do better now: convert extern line to static inline */
8525 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8526 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8528 #ifdef CONFIG_REG_VARS
8529 /* parse all function code and record it */
8531 tok_str_new(&func_str);
8533 block_level = 0;
8534 for(;;) {
8535 int t;
8536 if (tok == -1)
8537 error("unexpected end of file");
8538 tok_str_add_tok(&func_str);
8539 t = tok;
8540 next();
8541 if (t == '{') {
8542 block_level++;
8543 } else if (t == '}') {
8544 block_level--;
8545 if (block_level == 0)
8546 break;
8549 tok_str_add(&func_str, -1);
8550 tok_str_add(&func_str, 0);
8552 save_parse_state(&saved_parse_state);
8554 macro_ptr = func_str.str;
8555 next();
8556 analyse_function();
8557 #endif
8559 /* compute text section */
8560 cur_text_section = ad.section;
8561 if (!cur_text_section)
8562 cur_text_section = text_section;
8563 ind = cur_text_section->data_offset;
8564 funcname = get_tok_str(v, NULL);
8565 sym = sym_find(v);
8566 if (sym) {
8567 /* if symbol is already defined, then put complete type */
8568 sym->type = type;
8569 } else {
8570 /* put function symbol */
8571 sym = global_identifier_push(v, type.t, 0);
8572 sym->type.ref = type.ref;
8574 /* NOTE: we patch the symbol size later */
8575 put_extern_sym(sym, cur_text_section, ind, 0);
8576 func_ind = ind;
8577 sym->r = VT_SYM | VT_CONST;
8578 /* put debug symbol */
8579 if (do_debug)
8580 put_func_debug(sym);
8581 /* push a dummy symbol to enable local sym storage */
8582 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8583 gfunc_prolog(&type);
8584 loc = 0;
8585 rsym = 0;
8586 #ifdef CONFIG_REG_VARS
8587 macro_ptr = func_str.str;
8588 next();
8589 #endif
8590 block(NULL, NULL, NULL, NULL, 0, 0);
8591 gsym(rsym);
8592 gfunc_epilog();
8593 cur_text_section->data_offset = ind;
8594 label_pop(&global_label_stack, NULL);
8595 sym_pop(&local_stack, NULL); /* reset local stack */
8596 /* end of function */
8597 /* patch symbol size */
8598 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8599 ind - func_ind;
8600 if (do_debug) {
8601 put_stabn(N_FUN, 0, 0, ind - func_ind);
8603 funcname = ""; /* for safety */
8604 func_vt.t = VT_VOID; /* for safety */
8605 ind = 0; /* for safety */
8607 #ifdef CONFIG_REG_VARS
8608 tok_str_free(func_str.str);
8609 restore_parse_state(&saved_parse_state);
8610 #endif
8611 break;
8612 } else {
8613 if (btype.t & VT_TYPEDEF) {
8614 /* save typedefed type */
8615 /* XXX: test storage specifiers ? */
8616 sym = sym_push(v, &type, 0, 0);
8617 sym->type.t |= VT_TYPEDEF;
8618 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8619 /* external function definition */
8620 external_sym(v, &type, 0);
8621 } else {
8622 /* not lvalue if array */
8623 r = 0;
8624 if (!(type.t & VT_ARRAY))
8625 r |= lvalue_type(type.t);
8626 has_init = (tok == '=');
8627 if ((btype.t & VT_EXTERN) ||
8628 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8629 !has_init && l == VT_CONST && type.ref->c < 0)) {
8630 /* external variable */
8631 /* NOTE: as GCC, uninitialized global static
8632 arrays of null size are considered as
8633 extern */
8634 external_sym(v, &type, r);
8635 } else {
8636 if (type.t & VT_STATIC)
8637 r |= VT_CONST;
8638 else
8639 r |= l;
8640 if (has_init)
8641 next();
8642 decl_initializer_alloc(&type, &ad, r,
8643 has_init, v, l);
8646 if (tok != ',') {
8647 skip(';');
8648 break;
8650 next();
8656 /* better than nothing, but needs extension to handle '-E' option
8657 correctly too */
8658 static void preprocess_init(TCCState *s1)
8660 s1->include_stack_ptr = s1->include_stack;
8661 /* XXX: move that before to avoid having to initialize
8662 file->ifdef_stack_ptr ? */
8663 s1->ifdef_stack_ptr = s1->ifdef_stack;
8664 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8666 /* XXX: not ANSI compliant: bound checking says error */
8667 vtop = vstack - 1;
8670 /* compile the C file opened in 'file'. Return non zero if errors. */
8671 static int tcc_compile(TCCState *s1)
8673 Sym *define_start;
8674 char buf[512];
8675 volatile int section_sym;
8677 #ifdef INC_DEBUG
8678 printf("%s: **** new file\n", file->filename);
8679 #endif
8680 preprocess_init(s1);
8682 funcname = "";
8683 anon_sym = SYM_FIRST_ANOM;
8685 /* file info: full path + filename */
8686 section_sym = 0; /* avoid warning */
8687 if (do_debug) {
8688 section_sym = put_elf_sym(symtab_section, 0, 0,
8689 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8690 text_section->sh_num, NULL);
8691 getcwd(buf, sizeof(buf));
8692 pstrcat(buf, sizeof(buf), "/");
8693 put_stabs_r(buf, N_SO, 0, 0,
8694 text_section->data_offset, text_section, section_sym);
8695 put_stabs_r(file->filename, N_SO, 0, 0,
8696 text_section->data_offset, text_section, section_sym);
8698 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8699 symbols can be safely used */
8700 put_elf_sym(symtab_section, 0, 0,
8701 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8702 SHN_ABS, file->filename);
8704 /* define some often used types */
8705 int_type.t = VT_INT;
8707 char_pointer_type.t = VT_BYTE;
8708 mk_pointer(&char_pointer_type);
8710 func_old_type.t = VT_FUNC;
8711 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8713 #if 0
8714 /* define 'void *alloca(unsigned int)' builtin function */
8716 Sym *s1;
8718 p = anon_sym++;
8719 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8720 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8721 s1->next = NULL;
8722 sym->next = s1;
8723 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8725 #endif
8727 define_start = define_stack;
8729 if (setjmp(s1->error_jmp_buf) == 0) {
8730 s1->nb_errors = 0;
8731 s1->error_set_jmp_enabled = 1;
8733 ch = file->buf_ptr[0];
8734 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8735 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8736 next();
8737 decl(VT_CONST);
8738 if (tok != TOK_EOF)
8739 expect("declaration");
8741 /* end of translation unit info */
8742 if (do_debug) {
8743 put_stabs_r(NULL, N_SO, 0, 0,
8744 text_section->data_offset, text_section, section_sym);
8747 s1->error_set_jmp_enabled = 0;
8749 /* reset define stack, but leave -Dsymbols (may be incorrect if
8750 they are undefined) */
8751 free_defines(define_start);
8753 sym_pop(&global_stack, NULL);
8755 return s1->nb_errors != 0 ? -1 : 0;
8758 #ifdef LIBTCC
8759 int tcc_compile_string(TCCState *s, const char *str)
8761 BufferedFile bf1, *bf = &bf1;
8762 int ret, len;
8763 char *buf;
8765 /* init file structure */
8766 bf->fd = -1;
8767 /* XXX: avoid copying */
8768 len = strlen(str);
8769 buf = tcc_malloc(len + 1);
8770 if (!buf)
8771 return -1;
8772 memcpy(buf, str, len);
8773 buf[len] = CH_EOB;
8774 bf->buf_ptr = buf;
8775 bf->buf_end = buf + len;
8776 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8777 bf->line_num = 1;
8778 file = bf;
8780 ret = tcc_compile(s);
8782 tcc_free(buf);
8784 /* currently, no need to close */
8785 return ret;
8787 #endif
8789 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8790 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8792 BufferedFile bf1, *bf = &bf1;
8794 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8795 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8796 /* default value */
8797 if (!value)
8798 value = "1";
8799 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8801 /* init file structure */
8802 bf->fd = -1;
8803 bf->buf_ptr = bf->buffer;
8804 bf->buf_end = bf->buffer + strlen(bf->buffer);
8805 *bf->buf_end = CH_EOB;
8806 bf->filename[0] = '\0';
8807 bf->line_num = 1;
8808 file = bf;
8810 s1->include_stack_ptr = s1->include_stack;
8812 /* parse with define parser */
8813 ch = file->buf_ptr[0];
8814 next_nomacro();
8815 parse_define();
8816 file = NULL;
8819 /* undefine a preprocessor symbol */
8820 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8822 TokenSym *ts;
8823 Sym *s;
8824 ts = tok_alloc(sym, strlen(sym));
8825 s = define_find(ts->tok);
8826 /* undefine symbol by putting an invalid name */
8827 if (s)
8828 define_undef(s);
8831 #ifdef CONFIG_TCC_ASM
8833 #include "i386-asm.c"
8834 #include "tccasm.c"
8836 #else
8837 static void asm_instr(void)
8839 error("inline asm() not supported");
8841 #endif
8843 #include "tccelf.c"
8845 /* print the position in the source file of PC value 'pc' by reading
8846 the stabs debug information */
8847 static void rt_printline(unsigned long wanted_pc)
8849 Stab_Sym *sym, *sym_end;
8850 char func_name[128], last_func_name[128];
8851 unsigned long func_addr, last_pc, pc;
8852 const char *incl_files[INCLUDE_STACK_SIZE];
8853 int incl_index, len, last_line_num, i;
8854 const char *str, *p;
8856 fprintf(stderr, "0x%08lx:", wanted_pc);
8858 func_name[0] = '\0';
8859 func_addr = 0;
8860 incl_index = 0;
8861 last_func_name[0] = '\0';
8862 last_pc = 0xffffffff;
8863 last_line_num = 1;
8864 sym = (Stab_Sym *)stab_section->data + 1;
8865 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
8866 while (sym < sym_end) {
8867 switch(sym->n_type) {
8868 /* function start or end */
8869 case N_FUN:
8870 if (sym->n_strx == 0) {
8871 /* we test if between last line and end of function */
8872 pc = sym->n_value + func_addr;
8873 if (wanted_pc >= last_pc && wanted_pc < pc)
8874 goto found;
8875 func_name[0] = '\0';
8876 func_addr = 0;
8877 } else {
8878 str = stabstr_section->data + sym->n_strx;
8879 p = strchr(str, ':');
8880 if (!p) {
8881 pstrcpy(func_name, sizeof(func_name), str);
8882 } else {
8883 len = p - str;
8884 if (len > sizeof(func_name) - 1)
8885 len = sizeof(func_name) - 1;
8886 memcpy(func_name, str, len);
8887 func_name[len] = '\0';
8889 func_addr = sym->n_value;
8891 break;
8892 /* line number info */
8893 case N_SLINE:
8894 pc = sym->n_value + func_addr;
8895 if (wanted_pc >= last_pc && wanted_pc < pc)
8896 goto found;
8897 last_pc = pc;
8898 last_line_num = sym->n_desc;
8899 /* XXX: slow! */
8900 strcpy(last_func_name, func_name);
8901 break;
8902 /* include files */
8903 case N_BINCL:
8904 str = stabstr_section->data + sym->n_strx;
8905 add_incl:
8906 if (incl_index < INCLUDE_STACK_SIZE) {
8907 incl_files[incl_index++] = str;
8909 break;
8910 case N_EINCL:
8911 if (incl_index > 1)
8912 incl_index--;
8913 break;
8914 case N_SO:
8915 if (sym->n_strx == 0) {
8916 incl_index = 0; /* end of translation unit */
8917 } else {
8918 str = stabstr_section->data + sym->n_strx;
8919 /* do not add path */
8920 len = strlen(str);
8921 if (len > 0 && str[len - 1] != '/')
8922 goto add_incl;
8924 break;
8926 sym++;
8929 /* second pass: we try symtab symbols (no line number info) */
8930 incl_index = 0;
8932 Elf32_Sym *sym, *sym_end;
8933 int type;
8935 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
8936 for(sym = (Elf32_Sym *)symtab_section->data + 1;
8937 sym < sym_end;
8938 sym++) {
8939 type = ELF32_ST_TYPE(sym->st_info);
8940 if (type == STT_FUNC) {
8941 if (wanted_pc >= sym->st_value &&
8942 wanted_pc < sym->st_value + sym->st_size) {
8943 pstrcpy(last_func_name, sizeof(last_func_name),
8944 strtab_section->data + sym->st_name);
8945 goto found;
8950 /* did not find any info: */
8951 fprintf(stderr, " ???\n");
8952 return;
8953 found:
8954 if (last_func_name[0] != '\0') {
8955 fprintf(stderr, " %s()", last_func_name);
8957 if (incl_index > 0) {
8958 fprintf(stderr, " (%s:%d",
8959 incl_files[incl_index - 1], last_line_num);
8960 for(i = incl_index - 2; i >= 0; i--)
8961 fprintf(stderr, ", included from %s", incl_files[i]);
8962 fprintf(stderr, ")");
8964 fprintf(stderr, "\n");
8967 #ifndef WIN32
8969 #ifdef __i386__
8971 /* fix for glibc 2.1 */
8972 #ifndef REG_EIP
8973 #define REG_EIP EIP
8974 #define REG_EBP EBP
8975 #endif
8977 /* return the PC at frame level 'level'. Return non zero if not found */
8978 static int rt_get_caller_pc(unsigned long *paddr,
8979 ucontext_t *uc, int level)
8981 unsigned long fp;
8982 int i;
8984 if (level == 0) {
8985 #ifdef __FreeBSD__
8986 *paddr = uc->uc_mcontext.mc_eip;
8987 #else
8988 *paddr = uc->uc_mcontext.gregs[REG_EIP];
8989 #endif
8990 return 0;
8991 } else {
8992 #ifdef __FreeBSD__
8993 fp = uc->uc_mcontext.mc_ebp;
8994 #else
8995 fp = uc->uc_mcontext.gregs[REG_EBP];
8996 #endif
8997 for(i=1;i<level;i++) {
8998 /* XXX: check address validity with program info */
8999 if (fp <= 0x1000 || fp >= 0xc0000000)
9000 return -1;
9001 fp = ((unsigned long *)fp)[0];
9003 *paddr = ((unsigned long *)fp)[1];
9004 return 0;
9007 #else
9008 #error add arch specific rt_get_caller_pc()
9009 #endif
9011 /* emit a run time error at position 'pc' */
9012 void rt_error(ucontext_t *uc, const char *fmt, ...)
9014 va_list ap;
9015 unsigned long pc;
9016 int i;
9018 va_start(ap, fmt);
9019 fprintf(stderr, "Runtime error: ");
9020 vfprintf(stderr, fmt, ap);
9021 fprintf(stderr, "\n");
9022 for(i=0;i<num_callers;i++) {
9023 if (rt_get_caller_pc(&pc, uc, i) < 0)
9024 break;
9025 if (i == 0)
9026 fprintf(stderr, "at ");
9027 else
9028 fprintf(stderr, "by ");
9029 rt_printline(pc);
9031 exit(255);
9032 va_end(ap);
9035 /* signal handler for fatal errors */
9036 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9038 ucontext_t *uc = puc;
9040 switch(signum) {
9041 case SIGFPE:
9042 switch(siginf->si_code) {
9043 case FPE_INTDIV:
9044 case FPE_FLTDIV:
9045 rt_error(uc, "division by zero");
9046 break;
9047 default:
9048 rt_error(uc, "floating point exception");
9049 break;
9051 break;
9052 case SIGBUS:
9053 case SIGSEGV:
9054 if (rt_bound_error_msg && *rt_bound_error_msg)
9055 rt_error(uc, *rt_bound_error_msg);
9056 else
9057 rt_error(uc, "dereferencing invalid pointer");
9058 break;
9059 case SIGILL:
9060 rt_error(uc, "illegal instruction");
9061 break;
9062 case SIGABRT:
9063 rt_error(uc, "abort() called");
9064 break;
9065 default:
9066 rt_error(uc, "caught signal %d", signum);
9067 break;
9069 exit(255);
9071 #endif
9073 /* do all relocations (needed before using tcc_get_symbol()) */
9074 int tcc_relocate(TCCState *s1)
9076 Section *s;
9077 int i;
9079 s1->nb_errors = 0;
9081 tcc_add_runtime(s1);
9083 relocate_common_syms();
9085 /* compute relocation address : section are relocated in place. We
9086 also alloc the bss space */
9087 for(i = 1; i < s1->nb_sections; i++) {
9088 s = s1->sections[i];
9089 if (s->sh_flags & SHF_ALLOC) {
9090 if (s->sh_type == SHT_NOBITS)
9091 s->data = tcc_mallocz(s->data_offset);
9092 s->sh_addr = (unsigned long)s->data;
9096 relocate_syms(s1, 1);
9098 if (s1->nb_errors != 0)
9099 return -1;
9101 /* relocate each section */
9102 for(i = 1; i < s1->nb_sections; i++) {
9103 s = s1->sections[i];
9104 if (s->reloc)
9105 relocate_section(s1, s);
9107 return 0;
9110 /* launch the compiled program with the given arguments */
9111 int tcc_run(TCCState *s1, int argc, char **argv)
9113 int (*prog_main)(int, char **);
9115 if (tcc_relocate(s1) < 0)
9116 return -1;
9118 prog_main = tcc_get_symbol_err(s1, "main");
9120 if (do_debug) {
9121 #ifdef WIN32
9122 error("debug mode currently not available for Windows");
9123 #else
9124 struct sigaction sigact;
9125 /* install TCC signal handlers to print debug info on fatal
9126 runtime errors */
9127 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9128 sigact.sa_sigaction = sig_error;
9129 sigemptyset(&sigact.sa_mask);
9130 sigaction(SIGFPE, &sigact, NULL);
9131 sigaction(SIGILL, &sigact, NULL);
9132 sigaction(SIGSEGV, &sigact, NULL);
9133 sigaction(SIGBUS, &sigact, NULL);
9134 sigaction(SIGABRT, &sigact, NULL);
9135 #endif
9138 #ifdef CONFIG_TCC_BCHECK
9139 if (do_bounds_check) {
9140 void (*bound_init)(void);
9142 /* set error function */
9143 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9144 "__bound_error_msg");
9146 /* XXX: use .init section so that it also work in binary ? */
9147 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9148 bound_init();
9150 #endif
9151 return (*prog_main)(argc, argv);
9154 TCCState *tcc_new(void)
9156 const char *p, *r;
9157 TCCState *s;
9158 TokenSym *ts;
9159 int i, c;
9161 s = tcc_mallocz(sizeof(TCCState));
9162 if (!s)
9163 return NULL;
9164 tcc_state = s;
9165 s->output_type = TCC_OUTPUT_MEMORY;
9167 /* init isid table */
9168 for(i=0;i<256;i++)
9169 isidnum_table[i] = isid(i) || isnum(i);
9171 /* add all tokens */
9172 table_ident = NULL;
9173 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9175 tok_ident = TOK_IDENT;
9176 p = tcc_keywords;
9177 while (*p) {
9178 r = p;
9179 for(;;) {
9180 c = *r++;
9181 if (c == '\0')
9182 break;
9184 ts = tok_alloc(p, r - p - 1);
9185 p = r;
9188 /* we add dummy defines for some special macros to speed up tests
9189 and to have working defined() */
9190 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9191 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9192 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9193 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9195 /* standard defines */
9196 tcc_define_symbol(s, "__STDC__", NULL);
9197 #if defined(TCC_TARGET_I386)
9198 tcc_define_symbol(s, "__i386__", NULL);
9199 #endif
9200 #if defined(linux)
9201 tcc_define_symbol(s, "__linux__", NULL);
9202 tcc_define_symbol(s, "linux", NULL);
9203 #endif
9204 /* tiny C specific defines */
9205 tcc_define_symbol(s, "__TINYC__", NULL);
9207 /* tiny C & gcc defines */
9208 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9209 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9210 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9212 /* default library paths */
9213 tcc_add_library_path(s, "/usr/local/lib");
9214 tcc_add_library_path(s, "/usr/lib");
9215 tcc_add_library_path(s, "/lib");
9217 /* no section zero */
9218 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9220 /* create standard sections */
9221 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9222 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9223 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9225 /* symbols are always generated for linking stage */
9226 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9227 ".strtab",
9228 ".hashtab", SHF_PRIVATE);
9229 strtab_section = symtab_section->link;
9231 /* private symbol table for dynamic symbols */
9232 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9233 ".dynstrtab",
9234 ".dynhashtab", SHF_PRIVATE);
9235 s->alacarte_link = 1;
9236 return s;
9239 void tcc_delete(TCCState *s1)
9241 int i, n;
9243 /* free -D defines */
9244 free_defines(NULL);
9246 /* free tokens */
9247 n = tok_ident - TOK_IDENT;
9248 for(i = 0; i < n; i++)
9249 tcc_free(table_ident[i]);
9250 tcc_free(table_ident);
9252 /* free all sections */
9254 free_section(symtab_section->hash);
9256 free_section(s1->dynsymtab_section->hash);
9257 free_section(s1->dynsymtab_section->link);
9258 free_section(s1->dynsymtab_section);
9260 for(i = 1; i < s1->nb_sections; i++)
9261 free_section(s1->sections[i]);
9262 tcc_free(s1->sections);
9264 /* free loaded dlls array */
9265 for(i = 0; i < s1->nb_loaded_dlls; i++)
9266 tcc_free(s1->loaded_dlls[i]);
9267 tcc_free(s1->loaded_dlls);
9269 /* library paths */
9270 for(i = 0; i < s1->nb_library_paths; i++)
9271 tcc_free(s1->library_paths[i]);
9272 tcc_free(s1->library_paths);
9274 /* cached includes */
9275 for(i = 0; i < s1->nb_cached_includes; i++)
9276 tcc_free(s1->cached_includes[i]);
9277 tcc_free(s1->cached_includes);
9279 for(i = 0; i < s1->nb_include_paths; i++)
9280 tcc_free(s1->include_paths[i]);
9281 tcc_free(s1->include_paths);
9283 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9284 tcc_free(s1->sysinclude_paths[i]);
9285 tcc_free(s1->sysinclude_paths);
9287 tcc_free(s1);
9290 int tcc_add_include_path(TCCState *s1, const char *pathname)
9292 char *pathname1;
9294 pathname1 = tcc_strdup(pathname);
9295 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9296 return 0;
9299 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9301 char *pathname1;
9303 pathname1 = tcc_strdup(pathname);
9304 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9305 return 0;
9308 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9310 const char *ext, *filename1;
9311 Elf32_Ehdr ehdr;
9312 int fd, ret;
9313 BufferedFile *saved_file;
9315 /* find source file type with extension */
9316 filename1 = strrchr(filename, '/');
9317 if (filename1)
9318 filename1++;
9319 else
9320 filename1 = filename;
9321 ext = strrchr(filename1, '.');
9322 if (ext)
9323 ext++;
9325 /* open the file */
9326 saved_file = file;
9327 file = tcc_open(s1, filename);
9328 if (!file) {
9329 if (flags & AFF_PRINT_ERROR) {
9330 error_noabort("file '%s' not found", filename);
9332 ret = -1;
9333 goto fail1;
9336 if (!ext || !strcmp(ext, "c")) {
9337 /* C file assumed */
9338 ret = tcc_compile(s1);
9339 } else
9340 #ifdef CONFIG_TCC_ASM
9341 if (!strcmp(ext, "S")) {
9342 /* preprocessed assembler */
9343 ret = tcc_assemble(s1, 1);
9344 } else if (!strcmp(ext, "s")) {
9345 /* non preprocessed assembler */
9346 ret = tcc_assemble(s1, 0);
9347 } else
9348 #endif
9350 fd = file->fd;
9351 /* assume executable format: auto guess file type */
9352 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
9353 error_noabort("could not read header");
9354 goto fail;
9356 lseek(fd, 0, SEEK_SET);
9358 if (ehdr.e_ident[0] == ELFMAG0 &&
9359 ehdr.e_ident[1] == ELFMAG1 &&
9360 ehdr.e_ident[2] == ELFMAG2 &&
9361 ehdr.e_ident[3] == ELFMAG3) {
9362 file->line_num = 0; /* do not display line number if error */
9363 if (ehdr.e_type == ET_REL) {
9364 ret = tcc_load_object_file(s1, fd, 0);
9365 } else if (ehdr.e_type == ET_DYN) {
9366 ret = tcc_load_dll(s1, fd, filename,
9367 (flags & AFF_REFERENCED_DLL) != 0);
9368 } else {
9369 error_noabort("unrecognized ELF file");
9370 goto fail;
9372 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9373 file->line_num = 0; /* do not display line number if error */
9374 ret = tcc_load_archive(s1, fd);
9375 } else {
9376 /* as GNU ld, consider it is an ld script if not recognized */
9377 ret = tcc_load_ldscript(s1);
9378 if (ret < 0) {
9379 error_noabort("unrecognized file type");
9380 goto fail;
9384 the_end:
9385 tcc_close(file);
9386 fail1:
9387 file = saved_file;
9388 return ret;
9389 fail:
9390 ret = -1;
9391 goto the_end;
9394 int tcc_add_file(TCCState *s, const char *filename)
9396 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9399 int tcc_add_library_path(TCCState *s, const char *pathname)
9401 char *pathname1;
9403 pathname1 = tcc_strdup(pathname);
9404 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9405 return 0;
9408 /* find and load a dll. Return non zero if not found */
9409 /* XXX: add '-rpath' option support ? */
9410 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9412 char buf[1024];
9413 int i;
9415 for(i = 0; i < s->nb_library_paths; i++) {
9416 snprintf(buf, sizeof(buf), "%s/%s",
9417 s->library_paths[i], filename);
9418 if (tcc_add_file_internal(s, buf, flags) == 0)
9419 return 0;
9421 return -1;
9424 /* the library name is the same as the argument of the '-l' option */
9425 int tcc_add_library(TCCState *s, const char *libraryname)
9427 char buf[1024];
9428 int i;
9429 void *h;
9431 /* first we look for the dynamic library if not static linking */
9432 if (!s->static_link) {
9433 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9434 /* if we output to memory, then we simply we dlopen(). */
9435 if (s->output_type == TCC_OUTPUT_MEMORY) {
9436 /* Since the libc is already loaded, we don't need to load it again */
9437 if (!strcmp(libraryname, "c"))
9438 return 0;
9439 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
9440 if (h)
9441 return 0;
9442 } else {
9443 if (tcc_add_dll(s, buf, 0) == 0)
9444 return 0;
9448 /* then we look for the static library */
9449 for(i = 0; i < s->nb_library_paths; i++) {
9450 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9451 s->library_paths[i], libraryname);
9452 if (tcc_add_file_internal(s, buf, 0) == 0)
9453 return 0;
9455 return -1;
9458 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9460 add_elf_sym(symtab_section, val, 0,
9461 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9462 SHN_ABS, name);
9463 return 0;
9466 int tcc_set_output_type(TCCState *s, int output_type)
9468 char buf[1024];
9470 s->output_type = output_type;
9472 if (!s->nostdinc) {
9473 /* default include paths */
9474 /* XXX: reverse order needed if -isystem support */
9475 tcc_add_sysinclude_path(s, "/usr/local/include");
9476 tcc_add_sysinclude_path(s, "/usr/include");
9477 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9478 tcc_add_sysinclude_path(s, buf);
9481 /* if bound checking, then add corresponding sections */
9482 #ifdef CONFIG_TCC_BCHECK
9483 if (do_bounds_check) {
9484 /* define symbol */
9485 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9486 /* create bounds sections */
9487 bounds_section = new_section(s, ".bounds",
9488 SHT_PROGBITS, SHF_ALLOC);
9489 lbounds_section = new_section(s, ".lbounds",
9490 SHT_PROGBITS, SHF_ALLOC);
9492 #endif
9494 /* add debug sections */
9495 if (do_debug) {
9496 /* stab symbols */
9497 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9498 stab_section->sh_entsize = sizeof(Stab_Sym);
9499 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9500 put_elf_str(stabstr_section, "");
9501 stab_section->link = stabstr_section;
9502 /* put first entry */
9503 put_stabs("", 0, 0, 0, 0);
9506 /* add libc crt1/crti objects */
9507 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9508 !s->nostdlib) {
9509 if (output_type != TCC_OUTPUT_DLL)
9510 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9511 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9513 return 0;
9516 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9518 typedef struct WarningDef {
9519 int offset;
9520 int flags;
9521 const char *name;
9522 } WarningDef;
9524 static const WarningDef warning_defs[] = {
9525 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9526 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9527 { offsetof(TCCState, warn_error), 0, "error" },
9530 /* set/reset a warning */
9531 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9533 int i;
9534 const WarningDef *p;
9535 if (!strcmp(warning_name, "all")) {
9536 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9537 if (p->flags & WD_ALL)
9538 *(int *)((uint8_t *)s + p->offset) = 1;
9540 } else {
9541 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9542 if (!strcmp(warning_name, p->name))
9543 goto found;
9545 return -1;
9546 found:
9547 *(int *)((uint8_t *)s + p->offset) = value;
9549 return 0;
9553 #if !defined(LIBTCC)
9555 /* extract the basename of a file */
9556 static const char *tcc_basename(const char *name)
9558 const char *p;
9559 p = strrchr(name, '/');
9560 #ifdef WIN32
9561 if (!p)
9562 p = strrchr(name, '\\');
9563 #endif
9564 if (!p)
9565 p = name;
9566 else
9567 p++;
9568 return p;
9571 static int64_t getclock_us(void)
9573 #ifdef WIN32
9574 struct _timeb tb;
9575 _ftime(&tb);
9576 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9577 #else
9578 struct timeval tv;
9579 gettimeofday(&tv, NULL);
9580 return tv.tv_sec * 1000000LL + tv.tv_usec;
9581 #endif
9584 void help(void)
9586 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2003 Fabrice Bellard\n"
9587 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9588 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9589 " [infile1 infile2...] [-run infile args...]\n"
9590 "\n"
9591 "General options:\n"
9592 " -v display current version\n"
9593 " -c compile only - generate an object file\n"
9594 " -o outfile set output filename\n"
9595 " -Bdir set tcc internal library path\n"
9596 " -bench output compilation statistics\n"
9597 " -run run compiled source\n"
9598 " -Wwarning set or reset (with 'no-' prefix) 'warning'\n"
9599 "Preprocessor options:\n"
9600 " -Idir add include path 'dir'\n"
9601 " -Dsym[=val] define 'sym' with value 'val'\n"
9602 " -Usym undefine 'sym'\n"
9603 "Linker options:\n"
9604 " -Ldir add library path 'dir'\n"
9605 " -llib link with dynamic or static library 'lib'\n"
9606 " -shared generate a shared library\n"
9607 " -static static linking\n"
9608 " -rdynamic export all global symbols to dynamic linker\n"
9609 " -r relocatable output\n"
9610 "Debugger options:\n"
9611 " -g generate runtime debug info\n"
9612 #ifdef CONFIG_TCC_BCHECK
9613 " -b compile with built-in memory and bounds checker (implies -g)\n"
9614 #endif
9615 " -bt N show N callers in stack traces\n"
9619 #define TCC_OPTION_HAS_ARG 0x0001
9620 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9622 typedef struct TCCOption {
9623 const char *name;
9624 uint16_t index;
9625 uint16_t flags;
9626 } TCCOption;
9628 enum {
9629 TCC_OPTION_HELP,
9630 TCC_OPTION_I,
9631 TCC_OPTION_D,
9632 TCC_OPTION_U,
9633 TCC_OPTION_L,
9634 TCC_OPTION_B,
9635 TCC_OPTION_l,
9636 TCC_OPTION_bench,
9637 TCC_OPTION_bt,
9638 TCC_OPTION_b,
9639 TCC_OPTION_g,
9640 TCC_OPTION_c,
9641 TCC_OPTION_static,
9642 TCC_OPTION_shared,
9643 TCC_OPTION_o,
9644 TCC_OPTION_r,
9645 TCC_OPTION_W,
9646 TCC_OPTION_O,
9647 TCC_OPTION_m,
9648 TCC_OPTION_f,
9649 TCC_OPTION_nostdinc,
9650 TCC_OPTION_nostdlib,
9651 TCC_OPTION_print_search_dirs,
9652 TCC_OPTION_rdynamic,
9653 TCC_OPTION_run,
9654 TCC_OPTION_v,
9657 static const TCCOption tcc_options[] = {
9658 { "h", TCC_OPTION_HELP, 0 },
9659 { "?", TCC_OPTION_HELP, 0 },
9660 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9661 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9662 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9663 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9664 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9665 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9666 { "bench", TCC_OPTION_bench, 0 },
9667 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9668 #ifdef CONFIG_TCC_BCHECK
9669 { "b", TCC_OPTION_b, 0 },
9670 #endif
9671 { "g", TCC_OPTION_g, 0 },
9672 { "c", TCC_OPTION_c, 0 },
9673 { "static", TCC_OPTION_static, 0 },
9674 { "shared", TCC_OPTION_shared, 0 },
9675 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9676 { "run", TCC_OPTION_run, 0 },
9677 { "rdynamic", TCC_OPTION_rdynamic, 0 },
9678 { "r", TCC_OPTION_r, 0 },
9679 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9680 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9681 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9682 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9683 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9684 { "nostdlib", TCC_OPTION_nostdlib, 0 },
9685 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9686 { "v", TCC_OPTION_v, 0 },
9687 { NULL },
9690 int main(int argc, char **argv)
9692 char *r;
9693 int optind, output_type, multiple_files, i, reloc_output;
9694 TCCState *s;
9695 char **files;
9696 int nb_files, nb_libraries, nb_objfiles, dminus, ret;
9697 char objfilename[1024];
9698 int64_t start_time = 0;
9699 const TCCOption *popt;
9700 const char *optarg, *p1, *r1, *outfile;
9701 int print_search_dirs;
9703 s = tcc_new();
9704 output_type = TCC_OUTPUT_EXE;
9706 optind = 1;
9707 outfile = NULL;
9708 multiple_files = 1;
9709 dminus = 0;
9710 files = NULL;
9711 nb_files = 0;
9712 nb_libraries = 0;
9713 reloc_output = 0;
9714 print_search_dirs = 0;
9715 while (1) {
9716 if (optind >= argc) {
9717 if (nb_files == 0 && !print_search_dirs)
9718 goto show_help;
9719 else
9720 break;
9722 r = argv[optind++];
9723 if (r[0] != '-') {
9724 /* add a new file */
9725 dynarray_add((void ***)&files, &nb_files, r);
9726 if (!multiple_files) {
9727 optind--;
9728 /* argv[0] will be this file */
9729 break;
9731 } else {
9732 /* find option in table (match only the first chars */
9733 popt = tcc_options;
9734 for(;;) {
9735 p1 = popt->name;
9736 if (p1 == NULL)
9737 error("invalid option -- '%s'", r);
9738 r1 = r + 1;
9739 for(;;) {
9740 if (*p1 == '\0')
9741 goto option_found;
9742 if (*r1 != *p1)
9743 break;
9744 p1++;
9745 r1++;
9747 popt++;
9749 option_found:
9750 if (popt->flags & TCC_OPTION_HAS_ARG) {
9751 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
9752 optarg = r1;
9753 } else {
9754 if (optind >= argc)
9755 error("argument to '%s' is missing", r);
9756 optarg = argv[optind++];
9758 } else {
9759 if (*r1 != '\0')
9760 goto show_help;
9761 optarg = NULL;
9764 switch(popt->index) {
9765 case TCC_OPTION_HELP:
9766 show_help:
9767 help();
9768 return 1;
9769 case TCC_OPTION_I:
9770 if (tcc_add_include_path(s, optarg) < 0)
9771 error("too many include paths");
9772 break;
9773 case TCC_OPTION_D:
9775 char *sym, *value;
9776 sym = (char *)optarg;
9777 value = strchr(sym, '=');
9778 if (value) {
9779 *value = '\0';
9780 value++;
9782 tcc_define_symbol(s, sym, value);
9784 break;
9785 case TCC_OPTION_U:
9786 tcc_undefine_symbol(s, optarg);
9787 break;
9788 case TCC_OPTION_L:
9789 tcc_add_library_path(s, optarg);
9790 break;
9791 case TCC_OPTION_B:
9792 /* set tcc utilities path (mainly for tcc development) */
9793 tcc_lib_path = optarg;
9794 break;
9795 case TCC_OPTION_l:
9796 dynarray_add((void ***)&files, &nb_files, r);
9797 nb_libraries++;
9798 break;
9799 case TCC_OPTION_bench:
9800 do_bench = 1;
9801 break;
9802 case TCC_OPTION_bt:
9803 num_callers = atoi(optarg);
9804 break;
9805 #ifdef CONFIG_TCC_BCHECK
9806 case TCC_OPTION_b:
9807 do_bounds_check = 1;
9808 do_debug = 1;
9809 break;
9810 #endif
9811 case TCC_OPTION_g:
9812 do_debug = 1;
9813 break;
9814 case TCC_OPTION_c:
9815 multiple_files = 1;
9816 output_type = TCC_OUTPUT_OBJ;
9817 break;
9818 case TCC_OPTION_static:
9819 s->static_link = 1;
9820 break;
9821 case TCC_OPTION_shared:
9822 output_type = TCC_OUTPUT_DLL;
9823 break;
9824 case TCC_OPTION_o:
9825 multiple_files = 1;
9826 outfile = optarg;
9827 break;
9828 case TCC_OPTION_r:
9829 /* generate a .o merging several output files */
9830 reloc_output = 1;
9831 output_type = TCC_OUTPUT_OBJ;
9832 break;
9833 case TCC_OPTION_nostdinc:
9834 s->nostdinc = 1;
9835 break;
9836 case TCC_OPTION_nostdlib:
9837 s->nostdlib = 1;
9838 break;
9839 case TCC_OPTION_print_search_dirs:
9840 print_search_dirs = 1;
9841 break;
9842 case TCC_OPTION_run:
9843 multiple_files = 0;
9844 output_type = TCC_OUTPUT_MEMORY;
9845 break;
9846 case TCC_OPTION_v:
9847 printf("tcc version %s\n", TCC_VERSION);
9848 return 0;
9849 case TCC_OPTION_W:
9851 const char *p = optarg;
9852 int value;
9853 value = 1;
9854 if (p[0] == 'n' && p[1] == 'o' && p[2] == '-') {
9855 p += 2;
9856 value = 0;
9858 if (tcc_set_warning(s, p, value) < 0 && s->warn_unsupported)
9859 goto unsupported_option;
9861 break;
9862 case TCC_OPTION_rdynamic:
9863 s->rdynamic = 1;
9864 break;
9865 default:
9866 if (s->warn_unsupported) {
9867 unsupported_option:
9868 warning("unsupported option '%s'", r);
9870 break;
9874 if (print_search_dirs) {
9875 /* enough for Linux kernel */
9876 printf("install: %s/\n", tcc_lib_path);
9877 return 0;
9880 nb_objfiles = nb_files - nb_libraries;
9882 /* if outfile provided without other options, we output an
9883 executable */
9884 if (outfile && output_type == TCC_OUTPUT_MEMORY)
9885 output_type = TCC_OUTPUT_EXE;
9887 /* check -c consistency : only single file handled. XXX: checks file type */
9888 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9889 /* accepts only a single input file */
9890 if (nb_objfiles != 1)
9891 error("cannot specify multiple files with -c");
9892 if (nb_libraries != 0)
9893 error("cannot specify libraries with -c");
9896 /* compute default outfile name */
9897 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
9898 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9899 char *ext;
9900 /* strip path */
9901 pstrcpy(objfilename, sizeof(objfilename) - 1,
9902 tcc_basename(files[0]));
9903 /* add .o extension */
9904 ext = strrchr(objfilename, '.');
9905 if (!ext)
9906 goto default_outfile;
9907 strcpy(ext + 1, "o");
9908 } else {
9909 default_outfile:
9910 pstrcpy(objfilename, sizeof(objfilename), "a.out");
9912 outfile = objfilename;
9915 if (do_bench) {
9916 start_time = getclock_us();
9919 tcc_set_output_type(s, output_type);
9921 /* compile or add each files or library */
9922 for(i = 0;i < nb_files; i++) {
9923 const char *filename;
9925 filename = files[i];
9926 if (filename[0] == '-') {
9927 if (tcc_add_library(s, filename + 2) < 0)
9928 error("cannot find %s", filename);
9929 } else {
9930 if (tcc_add_file(s, filename) < 0) {
9931 ret = 1;
9932 goto the_end;
9937 /* free all files */
9938 tcc_free(files);
9940 if (do_bench) {
9941 double total_time;
9942 total_time = (double)(getclock_us() - start_time) / 1000000.0;
9943 if (total_time < 0.001)
9944 total_time = 0.001;
9945 if (total_bytes < 1)
9946 total_bytes = 1;
9947 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
9948 tok_ident - TOK_IDENT, total_lines, total_bytes,
9949 total_time, (int)(total_lines / total_time),
9950 total_bytes / total_time / 1000000.0);
9953 if (s->output_type != TCC_OUTPUT_MEMORY) {
9954 tcc_output_file(s, outfile);
9955 ret = 0;
9956 } else {
9957 ret = tcc_run(s, argc - optind, argv + optind);
9959 the_end:
9960 /* XXX: cannot do it with bound checking because of the malloc hooks */
9961 if (!do_bounds_check)
9962 tcc_delete(s);
9964 #ifdef MEM_DEBUG
9965 if (do_bench) {
9966 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
9968 #endif
9969 return ret;
9972 #endif