alacarte linking (Dave Long)
[tinycc.git] / tcc.c
blob649944bfed8cbcdf9557814d9263910b74968247
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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, only link in referenced objects from archive */
402 int alacarte_link;
404 /* warning switches */
405 int warn_write_strings;
406 int warn_unsupported;
407 int warn_error;
409 /* error handling */
410 void *error_opaque;
411 void (*error_func)(void *opaque, const char *msg);
412 int error_set_jmp_enabled;
413 jmp_buf error_jmp_buf;
414 int nb_errors;
416 /* tiny assembler state */
417 Sym *asm_labels;
419 /* see include_stack_ptr */
420 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
422 /* see ifdef_stack_ptr */
423 int ifdef_stack[IFDEF_STACK_SIZE];
426 /* The current value can be: */
427 #define VT_VALMASK 0x00ff
428 #define VT_CONST 0x00f0 /* constant in vc
429 (must be first non register value) */
430 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
431 #define VT_LOCAL 0x00f2 /* offset on stack */
432 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
433 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
434 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
435 #define VT_LVAL 0x0100 /* var is an lvalue */
436 #define VT_SYM 0x0200 /* a symbol value is added */
437 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
438 char/short stored in integer registers) */
439 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
440 dereferencing value */
441 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
442 bounding function call point is in vc */
443 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
444 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
445 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
446 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
448 /* types */
449 #define VT_INT 0 /* integer type */
450 #define VT_BYTE 1 /* signed byte type */
451 #define VT_SHORT 2 /* short type */
452 #define VT_VOID 3 /* void type */
453 #define VT_PTR 4 /* pointer */
454 #define VT_ENUM 5 /* enum definition */
455 #define VT_FUNC 6 /* function type */
456 #define VT_STRUCT 7 /* struct/union definition */
457 #define VT_FLOAT 8 /* IEEE float */
458 #define VT_DOUBLE 9 /* IEEE double */
459 #define VT_LDOUBLE 10 /* IEEE long double */
460 #define VT_BOOL 11 /* ISOC99 boolean type */
461 #define VT_LLONG 12 /* 64 bit integer */
462 #define VT_LONG 13 /* long integer (NEVER USED as type, only
463 during parsing) */
464 #define VT_BTYPE 0x000f /* mask for basic type */
465 #define VT_UNSIGNED 0x0010 /* unsigned type */
466 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
467 #define VT_BITFIELD 0x0040 /* bitfield modifier */
468 #define VT_CONSTANT 0x0800 /* const modifier */
469 #define VT_VOLATILE 0x1000 /* volatile modifier */
471 /* storage */
472 #define VT_EXTERN 0x00000080 /* extern definition */
473 #define VT_STATIC 0x00000100 /* static variable */
474 #define VT_TYPEDEF 0x00000200 /* typedef definition */
475 #define VT_INLINE 0x00000400 /* inline definition */
477 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
479 /* type mask (except storage) */
480 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
481 #define VT_TYPE (~(VT_STORAGE))
483 /* token values */
485 /* warning: the following compare tokens depend on i386 asm code */
486 #define TOK_ULT 0x92
487 #define TOK_UGE 0x93
488 #define TOK_EQ 0x94
489 #define TOK_NE 0x95
490 #define TOK_ULE 0x96
491 #define TOK_UGT 0x97
492 #define TOK_LT 0x9c
493 #define TOK_GE 0x9d
494 #define TOK_LE 0x9e
495 #define TOK_GT 0x9f
497 #define TOK_LAND 0xa0
498 #define TOK_LOR 0xa1
500 #define TOK_DEC 0xa2
501 #define TOK_MID 0xa3 /* inc/dec, to void constant */
502 #define TOK_INC 0xa4
503 #define TOK_UDIV 0xb0 /* unsigned division */
504 #define TOK_UMOD 0xb1 /* unsigned modulo */
505 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
506 #define TOK_CINT 0xb3 /* number in tokc */
507 #define TOK_CCHAR 0xb4 /* char constant in tokc */
508 #define TOK_STR 0xb5 /* pointer to string in tokc */
509 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
510 #define TOK_LCHAR 0xb7
511 #define TOK_LSTR 0xb8
512 #define TOK_CFLOAT 0xb9 /* float constant */
513 #define TOK_LINENUM 0xba /* line number info */
514 #define TOK_CDOUBLE 0xc0 /* double constant */
515 #define TOK_CLDOUBLE 0xc1 /* long double constant */
516 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
517 #define TOK_ADDC1 0xc3 /* add with carry generation */
518 #define TOK_ADDC2 0xc4 /* add with carry use */
519 #define TOK_SUBC1 0xc5 /* add with carry generation */
520 #define TOK_SUBC2 0xc6 /* add with carry use */
521 #define TOK_CUINT 0xc8 /* unsigned int constant */
522 #define TOK_CLLONG 0xc9 /* long long constant */
523 #define TOK_CULLONG 0xca /* unsigned long long constant */
524 #define TOK_ARROW 0xcb
525 #define TOK_DOTS 0xcc /* three dots */
526 #define TOK_SHR 0xcd /* unsigned shift right */
527 #define TOK_PPNUM 0xce /* preprocessor number */
529 #define TOK_SHL 0x01 /* shift left */
530 #define TOK_SAR 0x02 /* signed shift right */
532 /* assignement operators : normal operator or 0x80 */
533 #define TOK_A_MOD 0xa5
534 #define TOK_A_AND 0xa6
535 #define TOK_A_MUL 0xaa
536 #define TOK_A_ADD 0xab
537 #define TOK_A_SUB 0xad
538 #define TOK_A_DIV 0xaf
539 #define TOK_A_XOR 0xde
540 #define TOK_A_OR 0xfc
541 #define TOK_A_SHL 0x81
542 #define TOK_A_SAR 0x82
544 #ifndef offsetof
545 #define offsetof(type, field) ((size_t) &((type *)0)->field)
546 #endif
548 #ifndef countof
549 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
550 #endif
552 /* WARNING: the content of this string encodes token numbers */
553 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";
555 #define TOK_EOF (-1) /* end of file */
556 #define TOK_LINEFEED 10 /* line feed */
558 /* all identificators and strings have token above that */
559 #define TOK_IDENT 256
561 /* only used for i386 asm opcodes definitions */
562 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
564 #define DEF_BWL(x) \
565 DEF(TOK_ASM_ ## x ## b, #x "b") \
566 DEF(TOK_ASM_ ## x ## w, #x "w") \
567 DEF(TOK_ASM_ ## x ## l, #x "l") \
568 DEF(TOK_ASM_ ## x, #x)
570 #define DEF_WL(x) \
571 DEF(TOK_ASM_ ## x ## w, #x "w") \
572 DEF(TOK_ASM_ ## x ## l, #x "l") \
573 DEF(TOK_ASM_ ## x, #x)
575 #define DEF_FP1(x) \
576 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
577 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
578 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
579 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
581 #define DEF_FP(x) \
582 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
583 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
584 DEF_FP1(x)
586 #define DEF_ASMTEST(x) \
587 DEF_ASM(x ## o) \
588 DEF_ASM(x ## no) \
589 DEF_ASM(x ## b) \
590 DEF_ASM(x ## c) \
591 DEF_ASM(x ## nae) \
592 DEF_ASM(x ## nb) \
593 DEF_ASM(x ## nc) \
594 DEF_ASM(x ## ae) \
595 DEF_ASM(x ## e) \
596 DEF_ASM(x ## z) \
597 DEF_ASM(x ## ne) \
598 DEF_ASM(x ## nz) \
599 DEF_ASM(x ## be) \
600 DEF_ASM(x ## na) \
601 DEF_ASM(x ## nbe) \
602 DEF_ASM(x ## a) \
603 DEF_ASM(x ## s) \
604 DEF_ASM(x ## ns) \
605 DEF_ASM(x ## p) \
606 DEF_ASM(x ## pe) \
607 DEF_ASM(x ## np) \
608 DEF_ASM(x ## po) \
609 DEF_ASM(x ## l) \
610 DEF_ASM(x ## nge) \
611 DEF_ASM(x ## nl) \
612 DEF_ASM(x ## ge) \
613 DEF_ASM(x ## le) \
614 DEF_ASM(x ## ng) \
615 DEF_ASM(x ## nle) \
616 DEF_ASM(x ## g)
618 #define TOK_ASM_int TOK_INT
620 enum {
621 TOK_LAST = TOK_IDENT - 1,
622 #define DEF(id, str) id,
623 #include "tcctok.h"
624 #undef DEF
627 static const char tcc_keywords[] =
628 #define DEF(id, str) str "\0"
629 #include "tcctok.h"
630 #undef DEF
633 #define TOK_UIDENT TOK_DEFINE
635 #ifdef WIN32
636 #define snprintf _snprintf
637 #define vsnprintf _vsnprintf
638 #endif
640 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
641 /* currently incorrect */
642 long double strtold(const char *nptr, char **endptr)
644 return (long double)strtod(nptr, endptr);
646 float strtof(const char *nptr, char **endptr)
648 return (float)strtod(nptr, endptr);
650 #else
651 /* XXX: need to define this to use them in non ISOC99 context */
652 extern float strtof (const char *__nptr, char **__endptr);
653 extern long double strtold (const char *__nptr, char **__endptr);
654 #endif
656 static char *pstrcpy(char *buf, int buf_size, const char *s);
657 static char *pstrcat(char *buf, int buf_size, const char *s);
659 static void next(void);
660 static void next_nomacro(void);
661 static void parse_expr_type(CType *type);
662 static void expr_type(CType *type);
663 static void unary_type(CType *type);
664 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
665 int case_reg, int is_expr);
666 static int expr_const(void);
667 static void expr_eq(void);
668 static void gexpr(void);
669 static void decl(int l);
670 static void decl_initializer(CType *type, Section *sec, unsigned long c,
671 int first, int size_only);
672 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
673 int has_init, int v, int scope);
674 int gv(int rc);
675 void gv2(int rc1, int rc2);
676 void move_reg(int r, int s);
677 void save_regs(int n);
678 void save_reg(int r);
679 void vpop(void);
680 void vswap(void);
681 void vdup(void);
682 int get_reg(int rc);
684 static void macro_subst(TokenString *tok_str,
685 Sym **nested_list, const int *macro_str);
686 int save_reg_forced(int r);
687 void gen_op(int op);
688 void force_charshort_cast(int t);
689 static void gen_cast(CType *type);
690 void vstore(void);
691 static Sym *sym_find(int v);
692 static Sym *sym_push(int v, CType *type, int r, int c);
694 /* type handling */
695 static int type_size(CType *type, int *a);
696 static inline CType *pointed_type(CType *type);
697 static int pointed_size(CType *type);
698 static int lvalue_type(int t);
699 static int parse_btype(CType *type, AttributeDef *ad);
700 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
701 static int is_compatible_types(CType *type1, CType *type2);
703 void error(const char *fmt, ...);
704 void vpushi(int v);
705 void vset(CType *type, int r, int v);
706 void type_to_str(char *buf, int buf_size,
707 CType *type, const char *varstr);
708 char *get_tok_str(int v, CValue *cv);
709 static Sym *get_sym_ref(CType *type, Section *sec,
710 unsigned long offset, unsigned long size);
711 static Sym *external_global_sym(int v, CType *type, int r);
713 /* section generation */
714 static void section_realloc(Section *sec, unsigned long new_size);
715 static void *section_ptr_add(Section *sec, unsigned long size);
716 static void put_extern_sym(Sym *sym, Section *section,
717 unsigned long value, unsigned long size);
718 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
719 static int put_elf_str(Section *s, const char *sym);
720 static int put_elf_sym(Section *s,
721 unsigned long value, unsigned long size,
722 int info, int other, int shndx, const char *name);
723 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
724 int info, int sh_num, const char *name);
725 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
726 int type, int symbol);
727 static void put_stabs(const char *str, int type, int other, int desc,
728 unsigned long value);
729 static void put_stabs_r(const char *str, int type, int other, int desc,
730 unsigned long value, Section *sec, int sym_index);
731 static void put_stabn(int type, int other, int desc, int value);
732 static void put_stabd(int type, int other, int desc);
733 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
735 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
736 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
737 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
739 /* tccasm.c */
741 #ifdef CONFIG_TCC_ASM
743 typedef struct ExprValue {
744 uint32_t v;
745 Sym *sym;
746 } ExprValue;
748 #define MAX_ASM_OPERANDS 30
750 typedef struct ASMOperand {
751 int id; /* GCC 3 optionnal identifier (0 if number only supported */
752 char *constraint;
753 char asm_str[16]; /* computed asm string for operand */
754 SValue *vt; /* C value of the expression */
755 int ref_index; /* if >= 0, gives reference to a output constraint */
756 int priority; /* priority, used to assign registers */
757 int reg; /* if >= 0, register number used for this operand */
758 int is_llong; /* true if double register value */
759 } ASMOperand;
761 static void asm_expr(TCCState *s1, ExprValue *pe);
762 static int asm_int_expr(TCCState *s1);
763 static int find_constraint(ASMOperand *operands, int nb_operands,
764 const char *name, const char **pp);
766 static int tcc_assemble(TCCState *s1, int do_preprocess);
768 #endif
770 static void asm_instr(void);
772 /* true if float/double/long double type */
773 static inline int is_float(int t)
775 int bt;
776 bt = t & VT_BTYPE;
777 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
780 #ifdef TCC_TARGET_I386
781 #include "i386-gen.c"
782 #endif
784 #ifdef CONFIG_TCC_STATIC
786 #define RTLD_LAZY 0x001
787 #define RTLD_NOW 0x002
788 #define RTLD_GLOBAL 0x100
789 #define RTLD_DEFAULT NULL
791 /* dummy function for profiling */
792 void *dlopen(const char *filename, int flag)
794 return NULL;
797 const char *dlerror(void)
799 return "error";
802 typedef struct TCCSyms {
803 char *str;
804 void *ptr;
805 } TCCSyms;
807 #define TCCSYM(a) { #a, &a, },
809 /* add the symbol you want here if no dynamic linking is done */
810 static TCCSyms tcc_syms[] = {
811 TCCSYM(printf)
812 TCCSYM(fprintf)
813 TCCSYM(fopen)
814 TCCSYM(fclose)
815 { NULL, NULL },
818 void *dlsym(void *handle, const char *symbol)
820 TCCSyms *p;
821 p = tcc_syms;
822 while (p->str != NULL) {
823 if (!strcmp(p->str, symbol))
824 return p->ptr;
825 p++;
827 return NULL;
830 #endif
832 /********************************************************/
834 /* we use our own 'finite' function to avoid potential problems with
835 non standard math libs */
836 /* XXX: endianness dependent */
837 int ieee_finite(double d)
839 int *p = (int *)&d;
840 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
843 /* copy a string and truncate it. */
844 static char *pstrcpy(char *buf, int buf_size, const char *s)
846 char *q, *q_end;
847 int c;
849 if (buf_size > 0) {
850 q = buf;
851 q_end = buf + buf_size - 1;
852 while (q < q_end) {
853 c = *s++;
854 if (c == '\0')
855 break;
856 *q++ = c;
858 *q = '\0';
860 return buf;
863 /* strcat and truncate. */
864 static char *pstrcat(char *buf, int buf_size, const char *s)
866 int len;
867 len = strlen(buf);
868 if (len < buf_size)
869 pstrcpy(buf + len, buf_size - len, s);
870 return buf;
873 /* memory management */
874 #ifdef MEM_DEBUG
875 int mem_cur_size;
876 int mem_max_size;
877 #endif
879 static inline void tcc_free(void *ptr)
881 #ifdef MEM_DEBUG
882 mem_cur_size -= malloc_usable_size(ptr);
883 #endif
884 free(ptr);
887 static void *tcc_malloc(unsigned long size)
889 void *ptr;
890 ptr = malloc(size);
891 if (!ptr && size)
892 error("memory full");
893 #ifdef MEM_DEBUG
894 mem_cur_size += malloc_usable_size(ptr);
895 if (mem_cur_size > mem_max_size)
896 mem_max_size = mem_cur_size;
897 #endif
898 return ptr;
901 static void *tcc_mallocz(unsigned long size)
903 void *ptr;
904 ptr = tcc_malloc(size);
905 memset(ptr, 0, size);
906 return ptr;
909 static inline void *tcc_realloc(void *ptr, unsigned long size)
911 void *ptr1;
912 #ifdef MEM_DEBUG
913 mem_cur_size -= malloc_usable_size(ptr);
914 #endif
915 ptr1 = realloc(ptr, size);
916 #ifdef MEM_DEBUG
917 /* NOTE: count not correct if alloc error, but not critical */
918 mem_cur_size += malloc_usable_size(ptr1);
919 if (mem_cur_size > mem_max_size)
920 mem_max_size = mem_cur_size;
921 #endif
922 return ptr1;
925 static char *tcc_strdup(const char *str)
927 char *ptr;
928 ptr = tcc_malloc(strlen(str) + 1);
929 strcpy(ptr, str);
930 return ptr;
933 #define free(p) use_tcc_free(p)
934 #define malloc(s) use_tcc_malloc(s)
935 #define realloc(p, s) use_tcc_realloc(p, s)
937 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
939 int nb, nb_alloc;
940 void **pp;
942 nb = *nb_ptr;
943 pp = *ptab;
944 /* every power of two we double array size */
945 if ((nb & (nb - 1)) == 0) {
946 if (!nb)
947 nb_alloc = 1;
948 else
949 nb_alloc = nb * 2;
950 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
951 if (!pp)
952 error("memory full");
953 *ptab = pp;
955 pp[nb++] = data;
956 *nb_ptr = nb;
959 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
961 Section *sec;
963 sec = tcc_mallocz(sizeof(Section));
964 pstrcpy(sec->name, sizeof(sec->name), name);
965 sec->sh_type = sh_type;
966 sec->sh_flags = sh_flags;
967 switch(sh_type) {
968 case SHT_HASH:
969 case SHT_REL:
970 case SHT_DYNSYM:
971 case SHT_SYMTAB:
972 case SHT_DYNAMIC:
973 sec->sh_addralign = 4;
974 break;
975 case SHT_STRTAB:
976 sec->sh_addralign = 1;
977 break;
978 default:
979 sec->sh_addralign = 32; /* default conservative alignment */
980 break;
983 /* only add section if not private */
984 if (!(sh_flags & SHF_PRIVATE)) {
985 sec->sh_num = s1->nb_sections;
986 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
988 return sec;
991 static void free_section(Section *s)
993 tcc_free(s->data);
994 tcc_free(s);
997 /* realloc section and set its content to zero */
998 static void section_realloc(Section *sec, unsigned long new_size)
1000 unsigned long size;
1001 unsigned char *data;
1003 size = sec->data_allocated;
1004 if (size == 0)
1005 size = 1;
1006 while (size < new_size)
1007 size = size * 2;
1008 data = tcc_realloc(sec->data, size);
1009 if (!data)
1010 error("memory full");
1011 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1012 sec->data = data;
1013 sec->data_allocated = size;
1016 /* reserve at least 'size' bytes in section 'sec' from
1017 sec->data_offset. */
1018 static void *section_ptr_add(Section *sec, unsigned long size)
1020 unsigned long offset, offset1;
1022 offset = sec->data_offset;
1023 offset1 = offset + size;
1024 if (offset1 > sec->data_allocated)
1025 section_realloc(sec, offset1);
1026 sec->data_offset = offset1;
1027 return sec->data + offset;
1030 /* return a reference to a section, and create it if it does not
1031 exists */
1032 Section *find_section(TCCState *s1, const char *name)
1034 Section *sec;
1035 int i;
1036 for(i = 1; i < s1->nb_sections; i++) {
1037 sec = s1->sections[i];
1038 if (!strcmp(name, sec->name))
1039 return sec;
1041 /* sections are created as PROGBITS */
1042 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1045 /* update sym->c so that it points to an external symbol in section
1046 'section' with value 'value' */
1047 static void put_extern_sym(Sym *sym, Section *section,
1048 unsigned long value, unsigned long size)
1050 int sym_type, sym_bind, sh_num, info;
1051 Elf32_Sym *esym;
1052 const char *name;
1054 if (section)
1055 sh_num = section->sh_num;
1056 else
1057 sh_num = SHN_UNDEF;
1058 if (!sym->c) {
1059 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1060 sym_type = STT_FUNC;
1061 else
1062 sym_type = STT_OBJECT;
1063 if (sym->type.t & VT_STATIC)
1064 sym_bind = STB_LOCAL;
1065 else
1066 sym_bind = STB_GLOBAL;
1068 name = get_tok_str(sym->v, NULL);
1069 #ifdef CONFIG_TCC_BCHECK
1070 if (do_bounds_check) {
1071 char buf[32];
1073 /* XXX: avoid doing that for statics ? */
1074 /* if bound checking is activated, we change some function
1075 names by adding the "__bound" prefix */
1076 switch(sym->v) {
1077 #if 0
1078 /* XXX: we rely only on malloc hooks */
1079 case TOK_malloc:
1080 case TOK_free:
1081 case TOK_realloc:
1082 case TOK_memalign:
1083 case TOK_calloc:
1084 #endif
1085 case TOK_memcpy:
1086 case TOK_memmove:
1087 case TOK_memset:
1088 case TOK_strlen:
1089 case TOK_strcpy:
1090 strcpy(buf, "__bound_");
1091 strcat(buf, name);
1092 name = buf;
1093 break;
1096 #endif
1097 info = ELF32_ST_INFO(sym_bind, sym_type);
1098 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1099 } else {
1100 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1101 esym->st_value = value;
1102 esym->st_size = size;
1103 esym->st_shndx = sh_num;
1107 /* add a new relocation entry to symbol 'sym' in section 's' */
1108 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1110 if (!sym->c)
1111 put_extern_sym(sym, NULL, 0, 0);
1112 /* now we can add ELF relocation info */
1113 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1116 static inline int isid(int c)
1118 return (c >= 'a' && c <= 'z') ||
1119 (c >= 'A' && c <= 'Z') ||
1120 c == '_';
1123 static inline int isnum(int c)
1125 return c >= '0' && c <= '9';
1128 static inline int isoct(int c)
1130 return c >= '0' && c <= '7';
1133 static inline int toup(int c)
1135 if (c >= 'a' && c <= 'z')
1136 return c - 'a' + 'A';
1137 else
1138 return c;
1141 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1143 int len;
1144 len = strlen(buf);
1145 vsnprintf(buf + len, buf_size - len, fmt, ap);
1148 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1150 va_list ap;
1151 va_start(ap, fmt);
1152 strcat_vprintf(buf, buf_size, fmt, ap);
1153 va_end(ap);
1156 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1158 char buf[2048];
1159 BufferedFile **f;
1161 buf[0] = '\0';
1162 if (file) {
1163 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1164 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1165 (*f)->filename, (*f)->line_num);
1166 if (file->line_num > 0) {
1167 strcat_printf(buf, sizeof(buf),
1168 "%s:%d: ", file->filename, file->line_num);
1169 } else {
1170 strcat_printf(buf, sizeof(buf),
1171 "%s: ", file->filename);
1173 } else {
1174 strcat_printf(buf, sizeof(buf),
1175 "tcc: ");
1177 if (is_warning)
1178 strcat_printf(buf, sizeof(buf), "warning: ");
1179 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1181 if (!s1->error_func) {
1182 /* default case: stderr */
1183 fprintf(stderr, "%s\n", buf);
1184 } else {
1185 s1->error_func(s1->error_opaque, buf);
1187 if (!is_warning || s1->warn_error)
1188 s1->nb_errors++;
1191 #ifdef LIBTCC
1192 void tcc_set_error_func(TCCState *s, void *error_opaque,
1193 void (*error_func)(void *opaque, const char *msg))
1195 s->error_opaque = error_opaque;
1196 s->error_func = error_func;
1198 #endif
1200 /* error without aborting current compilation */
1201 void error_noabort(const char *fmt, ...)
1203 TCCState *s1 = tcc_state;
1204 va_list ap;
1206 va_start(ap, fmt);
1207 error1(s1, 0, fmt, ap);
1208 va_end(ap);
1211 void error(const char *fmt, ...)
1213 TCCState *s1 = tcc_state;
1214 va_list ap;
1216 va_start(ap, fmt);
1217 error1(s1, 0, fmt, ap);
1218 va_end(ap);
1219 /* better than nothing: in some cases, we accept to handle errors */
1220 if (s1->error_set_jmp_enabled) {
1221 longjmp(s1->error_jmp_buf, 1);
1222 } else {
1223 /* XXX: eliminate this someday */
1224 exit(1);
1228 void expect(const char *msg)
1230 error("%s expected", msg);
1233 void warning(const char *fmt, ...)
1235 TCCState *s1 = tcc_state;
1236 va_list ap;
1238 va_start(ap, fmt);
1239 error1(s1, 1, fmt, ap);
1240 va_end(ap);
1243 void skip(int c)
1245 if (tok != c)
1246 error("'%c' expected", c);
1247 next();
1250 static void test_lvalue(void)
1252 if (!(vtop->r & VT_LVAL))
1253 expect("lvalue");
1256 /* allocate a new token */
1257 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1259 TokenSym *ts, **ptable;
1260 int i;
1262 if (tok_ident >= SYM_FIRST_ANOM)
1263 error("memory full");
1265 /* expand token table if needed */
1266 i = tok_ident - TOK_IDENT;
1267 if ((i % TOK_ALLOC_INCR) == 0) {
1268 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1269 if (!ptable)
1270 error("memory full");
1271 table_ident = ptable;
1274 ts = tcc_malloc(sizeof(TokenSym) + len);
1275 table_ident[i] = ts;
1276 ts->tok = tok_ident++;
1277 ts->sym_define = NULL;
1278 ts->sym_label = NULL;
1279 ts->sym_struct = NULL;
1280 ts->sym_identifier = NULL;
1281 ts->len = len;
1282 ts->hash_next = NULL;
1283 memcpy(ts->str, str, len);
1284 ts->str[len] = '\0';
1285 *pts = ts;
1286 return ts;
1289 #define TOK_HASH_INIT 1
1290 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1292 /* find a token and add it if not found */
1293 static TokenSym *tok_alloc(const char *str, int len)
1295 TokenSym *ts, **pts;
1296 int i;
1297 unsigned int h;
1299 h = TOK_HASH_INIT;
1300 for(i=0;i<len;i++)
1301 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1302 h &= (TOK_HASH_SIZE - 1);
1304 pts = &hash_ident[h];
1305 for(;;) {
1306 ts = *pts;
1307 if (!ts)
1308 break;
1309 if (ts->len == len && !memcmp(ts->str, str, len))
1310 return ts;
1311 pts = &(ts->hash_next);
1313 return tok_alloc_new(pts, str, len);
1316 /* CString handling */
1318 static void cstr_realloc(CString *cstr, int new_size)
1320 int size;
1321 void *data;
1323 size = cstr->size_allocated;
1324 if (size == 0)
1325 size = 8; /* no need to allocate a too small first string */
1326 while (size < new_size)
1327 size = size * 2;
1328 data = tcc_realloc(cstr->data_allocated, size);
1329 if (!data)
1330 error("memory full");
1331 cstr->data_allocated = data;
1332 cstr->size_allocated = size;
1333 cstr->data = data;
1336 /* add a byte */
1337 static void cstr_ccat(CString *cstr, int ch)
1339 int size;
1340 size = cstr->size + 1;
1341 if (size > cstr->size_allocated)
1342 cstr_realloc(cstr, size);
1343 ((unsigned char *)cstr->data)[size - 1] = ch;
1344 cstr->size = size;
1347 static void cstr_cat(CString *cstr, const char *str)
1349 int c;
1350 for(;;) {
1351 c = *str;
1352 if (c == '\0')
1353 break;
1354 cstr_ccat(cstr, c);
1355 str++;
1359 /* add a wide char */
1360 static void cstr_wccat(CString *cstr, int ch)
1362 int size;
1363 size = cstr->size + sizeof(int);
1364 if (size > cstr->size_allocated)
1365 cstr_realloc(cstr, size);
1366 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1367 cstr->size = size;
1370 static void cstr_new(CString *cstr)
1372 memset(cstr, 0, sizeof(CString));
1375 /* free string and reset it to NULL */
1376 static void cstr_free(CString *cstr)
1378 tcc_free(cstr->data_allocated);
1379 cstr_new(cstr);
1382 #define cstr_reset(cstr) cstr_free(cstr)
1384 static CString *cstr_dup(CString *cstr1)
1386 CString *cstr;
1387 int size;
1389 cstr = tcc_malloc(sizeof(CString));
1390 size = cstr1->size;
1391 cstr->size = size;
1392 cstr->size_allocated = size;
1393 cstr->data_allocated = tcc_malloc(size);
1394 cstr->data = cstr->data_allocated;
1395 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1396 return cstr;
1399 /* XXX: unicode ? */
1400 static void add_char(CString *cstr, int c)
1402 if (c == '\'' || c == '\"' || c == '\\') {
1403 /* XXX: could be more precise if char or string */
1404 cstr_ccat(cstr, '\\');
1406 if (c >= 32 && c <= 126) {
1407 cstr_ccat(cstr, c);
1408 } else {
1409 cstr_ccat(cstr, '\\');
1410 if (c == '\n') {
1411 cstr_ccat(cstr, 'n');
1412 } else {
1413 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1414 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1415 cstr_ccat(cstr, '0' + (c & 7));
1420 /* XXX: buffer overflow */
1421 /* XXX: float tokens */
1422 char *get_tok_str(int v, CValue *cv)
1424 static char buf[STRING_MAX_SIZE + 1];
1425 static CString cstr_buf;
1426 CString *cstr;
1427 unsigned char *q;
1428 char *p;
1429 int i, len;
1431 /* NOTE: to go faster, we give a fixed buffer for small strings */
1432 cstr_reset(&cstr_buf);
1433 cstr_buf.data = buf;
1434 cstr_buf.size_allocated = sizeof(buf);
1435 p = buf;
1437 switch(v) {
1438 case TOK_CINT:
1439 case TOK_CUINT:
1440 /* XXX: not quite exact, but only useful for testing */
1441 sprintf(p, "%u", cv->ui);
1442 break;
1443 case TOK_CLLONG:
1444 case TOK_CULLONG:
1445 /* XXX: not quite exact, but only useful for testing */
1446 sprintf(p, "%Lu", cv->ull);
1447 break;
1448 case TOK_CCHAR:
1449 case TOK_LCHAR:
1450 cstr_ccat(&cstr_buf, '\'');
1451 add_char(&cstr_buf, cv->i);
1452 cstr_ccat(&cstr_buf, '\'');
1453 cstr_ccat(&cstr_buf, '\0');
1454 break;
1455 case TOK_PPNUM:
1456 cstr = cv->cstr;
1457 len = cstr->size - 1;
1458 for(i=0;i<len;i++)
1459 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1460 cstr_ccat(&cstr_buf, '\0');
1461 break;
1462 case TOK_STR:
1463 case TOK_LSTR:
1464 cstr = cv->cstr;
1465 cstr_ccat(&cstr_buf, '\"');
1466 if (v == TOK_STR) {
1467 len = cstr->size - 1;
1468 for(i=0;i<len;i++)
1469 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1470 } else {
1471 len = (cstr->size / sizeof(int)) - 1;
1472 for(i=0;i<len;i++)
1473 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1475 cstr_ccat(&cstr_buf, '\"');
1476 cstr_ccat(&cstr_buf, '\0');
1477 break;
1478 case TOK_LT:
1479 v = '<';
1480 goto addv;
1481 case TOK_GT:
1482 v = '>';
1483 goto addv;
1484 case TOK_A_SHL:
1485 return strcpy(p, "<<=");
1486 case TOK_A_SAR:
1487 return strcpy(p, ">>=");
1488 default:
1489 if (v < TOK_IDENT) {
1490 /* search in two bytes table */
1491 q = tok_two_chars;
1492 while (*q) {
1493 if (q[2] == v) {
1494 *p++ = q[0];
1495 *p++ = q[1];
1496 *p = '\0';
1497 return buf;
1499 q += 3;
1501 addv:
1502 *p++ = v;
1503 *p = '\0';
1504 } else if (v < tok_ident) {
1505 return table_ident[v - TOK_IDENT]->str;
1506 } else if (v >= SYM_FIRST_ANOM) {
1507 /* special name for anonymous symbol */
1508 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1509 } else {
1510 /* should never happen */
1511 return NULL;
1513 break;
1515 return cstr_buf.data;
1518 /* push, without hashing */
1519 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1521 Sym *s;
1522 s = tcc_malloc(sizeof(Sym));
1523 s->v = v;
1524 s->type.t = t;
1525 s->c = c;
1526 s->next = NULL;
1527 /* add in stack */
1528 s->prev = *ps;
1529 *ps = s;
1530 return s;
1533 /* find a symbol and return its associated structure. 's' is the top
1534 of the symbol stack */
1535 static Sym *sym_find2(Sym *s, int v)
1537 while (s) {
1538 if (s->v == v)
1539 return s;
1540 s = s->prev;
1542 return NULL;
1545 /* structure lookup */
1546 static inline Sym *struct_find(int v)
1548 v -= TOK_IDENT;
1549 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1550 return NULL;
1551 return table_ident[v]->sym_struct;
1554 /* find an identifier */
1555 static inline Sym *sym_find(int v)
1557 v -= TOK_IDENT;
1558 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1559 return NULL;
1560 return table_ident[v]->sym_identifier;
1563 /* push a given symbol on the symbol stack */
1564 static Sym *sym_push(int v, CType *type, int r, int c)
1566 Sym *s, **ps;
1567 TokenSym *ts;
1569 if (local_stack)
1570 ps = &local_stack;
1571 else
1572 ps = &global_stack;
1573 s = sym_push2(ps, v, type->t, c);
1574 s->type.ref = type->ref;
1575 s->r = r;
1576 /* don't record fields or anonymous symbols */
1577 /* XXX: simplify */
1578 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1579 /* record symbol in token array */
1580 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1581 if (v & SYM_STRUCT)
1582 ps = &ts->sym_struct;
1583 else
1584 ps = &ts->sym_identifier;
1585 s->prev_tok = *ps;
1586 *ps = s;
1588 return s;
1591 /* push a global identifier */
1592 static Sym *global_identifier_push(int v, int t, int c)
1594 Sym *s, **ps;
1595 s = sym_push2(&global_stack, v, t, c);
1596 /* don't record anonymous symbol */
1597 if (v < SYM_FIRST_ANOM) {
1598 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1599 /* modify the top most local identifier, so that
1600 sym_identifier will point to 's' when popped */
1601 while (*ps != NULL)
1602 ps = &(*ps)->prev_tok;
1603 s->prev_tok = NULL;
1604 *ps = s;
1606 return s;
1609 /* pop symbols until top reaches 'b' */
1610 static void sym_pop(Sym **ptop, Sym *b)
1612 Sym *s, *ss, **ps;
1613 TokenSym *ts;
1614 int v;
1616 s = *ptop;
1617 while(s != b) {
1618 ss = s->prev;
1619 v = s->v;
1620 /* remove symbol in token array */
1621 /* XXX: simplify */
1622 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1623 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1624 if (v & SYM_STRUCT)
1625 ps = &ts->sym_struct;
1626 else
1627 ps = &ts->sym_identifier;
1628 *ps = s->prev_tok;
1630 tcc_free(s);
1631 s = ss;
1633 *ptop = b;
1636 /* I/O layer */
1638 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1640 int fd;
1641 BufferedFile *bf;
1643 fd = open(filename, O_RDONLY);
1644 if (fd < 0)
1645 return NULL;
1646 bf = tcc_malloc(sizeof(BufferedFile));
1647 if (!bf) {
1648 close(fd);
1649 return NULL;
1651 bf->fd = fd;
1652 bf->buf_ptr = bf->buffer;
1653 bf->buf_end = bf->buffer;
1654 bf->buffer[0] = CH_EOB; /* put eob symbol */
1655 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1656 bf->line_num = 1;
1657 bf->ifndef_macro = 0;
1658 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1659 // printf("opening '%s'\n", filename);
1660 return bf;
1663 void tcc_close(BufferedFile *bf)
1665 total_lines += bf->line_num;
1666 close(bf->fd);
1667 tcc_free(bf);
1670 /* fill input buffer and peek next char */
1671 static int tcc_peekc_slow(BufferedFile *bf)
1673 int len;
1674 /* only tries to read if really end of buffer */
1675 if (bf->buf_ptr >= bf->buf_end) {
1676 if (bf->fd != -1) {
1677 #if defined(PARSE_DEBUG)
1678 len = 8;
1679 #else
1680 len = IO_BUF_SIZE;
1681 #endif
1682 len = read(bf->fd, bf->buffer, len);
1683 if (len < 0)
1684 len = 0;
1685 } else {
1686 len = 0;
1688 total_bytes += len;
1689 bf->buf_ptr = bf->buffer;
1690 bf->buf_end = bf->buffer + len;
1691 *bf->buf_end = CH_EOB;
1693 if (bf->buf_ptr < bf->buf_end) {
1694 return bf->buf_ptr[0];
1695 } else {
1696 bf->buf_ptr = bf->buf_end;
1697 return CH_EOF;
1701 /* return the current character, handling end of block if necessary
1702 (but not stray) */
1703 static int handle_eob(void)
1705 return tcc_peekc_slow(file);
1708 /* read next char from current input file and handle end of input buffer */
1709 static inline void inp(void)
1711 ch = *(++(file->buf_ptr));
1712 /* end of buffer/file handling */
1713 if (ch == CH_EOB)
1714 ch = handle_eob();
1717 /* handle '\[\r]\n' */
1718 static void handle_stray(void)
1720 while (ch == '\\') {
1721 inp();
1722 if (ch == '\n') {
1723 file->line_num++;
1724 inp();
1725 } else if (ch == '\r') {
1726 inp();
1727 if (ch != '\n')
1728 goto fail;
1729 file->line_num++;
1730 inp();
1731 } else {
1732 fail:
1733 error("stray '\\' in program");
1738 /* skip the stray and handle the \\n case. Output an error if
1739 incorrect char after the stray */
1740 static int handle_stray1(uint8_t *p)
1742 int c;
1744 if (p >= file->buf_end) {
1745 file->buf_ptr = p;
1746 c = handle_eob();
1747 p = file->buf_ptr;
1748 if (c == '\\')
1749 goto parse_stray;
1750 } else {
1751 parse_stray:
1752 file->buf_ptr = p;
1753 ch = *p;
1754 handle_stray();
1755 p = file->buf_ptr;
1756 c = *p;
1758 return c;
1761 /* handle just the EOB case, but not stray */
1762 #define PEEKC_EOB(c, p)\
1764 p++;\
1765 c = *p;\
1766 if (c == '\\') {\
1767 file->buf_ptr = p;\
1768 c = handle_eob();\
1769 p = file->buf_ptr;\
1773 /* handle the complicated stray case */
1774 #define PEEKC(c, p)\
1776 p++;\
1777 c = *p;\
1778 if (c == '\\') {\
1779 c = handle_stray1(p);\
1780 p = file->buf_ptr;\
1784 /* input with '\[\r]\n' handling. Note that this function cannot
1785 handle other characters after '\', so you cannot call it inside
1786 strings or comments */
1787 static void minp(void)
1789 inp();
1790 if (ch == '\\')
1791 handle_stray();
1795 /* single line C++ comments */
1796 static uint8_t *parse_line_comment(uint8_t *p)
1798 int c;
1800 p++;
1801 for(;;) {
1802 c = *p;
1803 if (c == '\n' || c == CH_EOF) {
1804 break;
1805 } else if (c == '\\') {
1806 PEEKC_EOB(c, p);
1807 if (c == '\n') {
1808 file->line_num++;
1809 PEEKC_EOB(c, p);
1810 } else if (c == '\r') {
1811 PEEKC_EOB(c, p);
1812 if (c == '\n') {
1813 file->line_num++;
1814 PEEKC_EOB(c, p);
1817 } else {
1818 p++;
1821 return p;
1824 /* C comments */
1825 static uint8_t *parse_comment(uint8_t *p)
1827 int c;
1829 p++;
1830 for(;;) {
1831 /* fast skip loop */
1832 for(;;) {
1833 c = *p;
1834 if (c == '\n' || c == '*' || c == '\\')
1835 break;
1836 p++;
1837 c = *p;
1838 if (c == '\n' || c == '*' || c == '\\')
1839 break;
1840 p++;
1842 /* now we can handle all the cases */
1843 if (c == '\n') {
1844 file->line_num++;
1845 p++;
1846 } else if (c == '*') {
1847 p++;
1848 for(;;) {
1849 c = *p;
1850 if (c == '*') {
1851 p++;
1852 } else if (c == '/') {
1853 goto end_of_comment;
1854 } else if (c == '\\') {
1855 file->buf_ptr = p;
1856 c = handle_eob();
1857 p = file->buf_ptr;
1858 if (c == '\\') {
1859 /* skip '\[\r]\n', otherwise just skip the stray */
1860 while (c == '\\') {
1861 PEEKC_EOB(c, p);
1862 if (c == '\n') {
1863 file->line_num++;
1864 PEEKC_EOB(c, p);
1865 } else if (c == '\r') {
1866 PEEKC_EOB(c, p);
1867 if (c == '\n') {
1868 file->line_num++;
1869 PEEKC_EOB(c, p);
1871 } else {
1872 goto after_star;
1876 } else {
1877 break;
1880 after_star: ;
1881 } else {
1882 /* stray, eob or eof */
1883 file->buf_ptr = p;
1884 c = handle_eob();
1885 p = file->buf_ptr;
1886 if (c == CH_EOF) {
1887 error("unexpected end of file in comment");
1888 } else if (c == '\\') {
1889 p++;
1893 end_of_comment:
1894 p++;
1895 return p;
1898 #define cinp minp
1900 /* space exlcuding newline */
1901 static inline int is_space(int ch)
1903 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1906 static inline void skip_spaces(void)
1908 while (is_space(ch))
1909 cinp();
1912 /* parse a string without interpreting escapes */
1913 static uint8_t *parse_pp_string(uint8_t *p,
1914 int sep, CString *str)
1916 int c;
1917 p++;
1918 for(;;) {
1919 c = *p;
1920 if (c == sep) {
1921 break;
1922 } else if (c == '\\') {
1923 file->buf_ptr = p;
1924 c = handle_eob();
1925 p = file->buf_ptr;
1926 if (c == CH_EOF) {
1927 unterminated_string:
1928 /* XXX: indicate line number of start of string */
1929 error("missing terminating %c character", sep);
1930 } else if (c == '\\') {
1931 /* escape : just skip \[\r]\n */
1932 PEEKC_EOB(c, p);
1933 if (c == '\n') {
1934 file->line_num++;
1935 p++;
1936 } else if (c == '\r') {
1937 PEEKC_EOB(c, p);
1938 if (c != '\n')
1939 expect("'\n' after '\r'");
1940 file->line_num++;
1941 p++;
1942 } else if (c == CH_EOF) {
1943 goto unterminated_string;
1944 } else {
1945 if (str) {
1946 cstr_ccat(str, '\\');
1947 cstr_ccat(str, c);
1949 p++;
1952 } else if (c == '\n') {
1953 file->line_num++;
1954 goto add_char;
1955 } else if (c == '\r') {
1956 PEEKC_EOB(c, p);
1957 if (c != '\n') {
1958 cstr_ccat(str, '\r');
1959 } else {
1960 file->line_num++;
1961 goto add_char;
1963 } else {
1964 add_char:
1965 if (str)
1966 cstr_ccat(str, c);
1967 p++;
1970 p++;
1971 return p;
1974 /* skip block of text until #else, #elif or #endif. skip also pairs of
1975 #if/#endif */
1976 void preprocess_skip(void)
1978 int a, start_of_line, c;
1979 uint8_t *p;
1981 p = file->buf_ptr;
1982 start_of_line = 1;
1983 a = 0;
1984 for(;;) {
1985 redo_no_start:
1986 c = *p;
1987 switch(c) {
1988 case ' ':
1989 case '\t':
1990 case '\f':
1991 case '\v':
1992 case '\r':
1993 p++;
1994 goto redo_no_start;
1995 case '\n':
1996 start_of_line = 1;
1997 file->line_num++;
1998 p++;
1999 goto redo_no_start;
2000 case '\\':
2001 file->buf_ptr = p;
2002 c = handle_eob();
2003 if (c == CH_EOF) {
2004 expect("#endif");
2005 } else if (c == '\\') {
2006 /* XXX: incorrect: should not give an error */
2007 ch = file->buf_ptr[0];
2008 handle_stray();
2010 p = file->buf_ptr;
2011 goto redo_no_start;
2012 /* skip strings */
2013 case '\"':
2014 case '\'':
2015 p = parse_pp_string(p, c, NULL);
2016 break;
2017 /* skip comments */
2018 case '/':
2019 file->buf_ptr = p;
2020 ch = *p;
2021 minp();
2022 p = file->buf_ptr;
2023 if (ch == '*') {
2024 p = parse_comment(p);
2025 } else if (ch == '/') {
2026 p = parse_line_comment(p);
2028 break;
2030 case '#':
2031 p++;
2032 if (start_of_line) {
2033 file->buf_ptr = p;
2034 next_nomacro();
2035 p = file->buf_ptr;
2036 if (a == 0 &&
2037 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2038 goto the_end;
2039 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2040 a++;
2041 else if (tok == TOK_ENDIF)
2042 a--;
2044 break;
2045 default:
2046 p++;
2047 break;
2049 start_of_line = 0;
2051 the_end: ;
2052 file->buf_ptr = p;
2055 /* ParseState handling */
2057 /* XXX: currently, no include file info is stored. Thus, we cannot display
2058 accurate messages if the function or data definition spans multiple
2059 files */
2061 /* save current parse state in 's' */
2062 void save_parse_state(ParseState *s)
2064 s->line_num = file->line_num;
2065 s->macro_ptr = macro_ptr;
2066 s->tok = tok;
2067 s->tokc = tokc;
2070 /* restore parse state from 's' */
2071 void restore_parse_state(ParseState *s)
2073 file->line_num = s->line_num;
2074 macro_ptr = s->macro_ptr;
2075 tok = s->tok;
2076 tokc = s->tokc;
2079 /* return the number of additional 'ints' necessary to store the
2080 token */
2081 static inline int tok_ext_size(int t)
2083 switch(t) {
2084 /* 4 bytes */
2085 case TOK_CINT:
2086 case TOK_CUINT:
2087 case TOK_CCHAR:
2088 case TOK_LCHAR:
2089 case TOK_STR:
2090 case TOK_LSTR:
2091 case TOK_CFLOAT:
2092 case TOK_LINENUM:
2093 case TOK_PPNUM:
2094 return 1;
2095 case TOK_CDOUBLE:
2096 case TOK_CLLONG:
2097 case TOK_CULLONG:
2098 return 2;
2099 case TOK_CLDOUBLE:
2100 return LDOUBLE_SIZE / 4;
2101 default:
2102 return 0;
2106 /* token string handling */
2108 static inline void tok_str_new(TokenString *s)
2110 s->str = NULL;
2111 s->len = 0;
2112 s->allocated_len = 0;
2113 s->last_line_num = -1;
2116 static void tok_str_free(int *str)
2118 const int *p;
2119 CString *cstr;
2120 int t;
2122 p = str;
2123 for(;;) {
2124 t = *p;
2125 /* NOTE: we test zero separately so that GCC can generate a
2126 table for the following switch */
2127 if (t == 0)
2128 break;
2129 switch(t) {
2130 case TOK_CINT:
2131 case TOK_CUINT:
2132 case TOK_CCHAR:
2133 case TOK_LCHAR:
2134 case TOK_CFLOAT:
2135 case TOK_LINENUM:
2136 p += 2;
2137 break;
2138 case TOK_PPNUM:
2139 case TOK_STR:
2140 case TOK_LSTR:
2141 /* XXX: use a macro to be portable on 64 bit ? */
2142 cstr = (CString *)p[1];
2143 cstr_free(cstr);
2144 tcc_free(cstr);
2145 p += 2;
2146 break;
2147 case TOK_CDOUBLE:
2148 case TOK_CLLONG:
2149 case TOK_CULLONG:
2150 p += 3;
2151 break;
2152 case TOK_CLDOUBLE:
2153 p += 1 + (LDOUBLE_SIZE / 4);
2154 break;
2155 default:
2156 p++;
2157 break;
2160 tcc_free(str);
2163 static int *tok_str_realloc(TokenString *s)
2165 int *str, len;
2167 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2168 str = tcc_realloc(s->str, len * sizeof(int));
2169 if (!str)
2170 error("memory full");
2171 s->allocated_len = len;
2172 s->str = str;
2173 return str;
2176 static void tok_str_add(TokenString *s, int t)
2178 int len, *str;
2180 len = s->len;
2181 str = s->str;
2182 if (len >= s->allocated_len)
2183 str = tok_str_realloc(s);
2184 str[len++] = t;
2185 s->len = len;
2188 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2190 int len, *str;
2192 len = s->len;
2193 str = s->str;
2195 /* allocate space for worst case */
2196 if (len + TOK_MAX_SIZE > s->allocated_len)
2197 str = tok_str_realloc(s);
2198 str[len++] = t;
2199 switch(t) {
2200 case TOK_CINT:
2201 case TOK_CUINT:
2202 case TOK_CCHAR:
2203 case TOK_LCHAR:
2204 case TOK_CFLOAT:
2205 case TOK_LINENUM:
2206 str[len++] = cv->tab[0];
2207 break;
2208 case TOK_PPNUM:
2209 case TOK_STR:
2210 case TOK_LSTR:
2211 str[len++] = (int)cstr_dup(cv->cstr);
2212 break;
2213 case TOK_CDOUBLE:
2214 case TOK_CLLONG:
2215 case TOK_CULLONG:
2216 str[len++] = cv->tab[0];
2217 str[len++] = cv->tab[1];
2218 break;
2219 case TOK_CLDOUBLE:
2220 #if LDOUBLE_SIZE == 12
2221 str[len++] = cv->tab[0];
2222 str[len++] = cv->tab[1];
2223 str[len++] = cv->tab[2];
2224 #else
2225 #error add long double size support
2226 #endif
2227 break;
2228 default:
2229 break;
2231 s->len = len;
2234 /* add the current parse token in token string 's' */
2235 static void tok_str_add_tok(TokenString *s)
2237 CValue cval;
2239 /* save line number info */
2240 if (file->line_num != s->last_line_num) {
2241 s->last_line_num = file->line_num;
2242 cval.i = s->last_line_num;
2243 tok_str_add2(s, TOK_LINENUM, &cval);
2245 tok_str_add2(s, tok, &tokc);
2248 #if LDOUBLE_SIZE == 12
2249 #define LDOUBLE_GET(p, cv) \
2250 cv.tab[0] = p[0]; \
2251 cv.tab[1] = p[1]; \
2252 cv.tab[2] = p[2];
2253 #else
2254 #error add long double size support
2255 #endif
2258 /* get a token from an integer array and increment pointer
2259 accordingly. we code it as a macro to avoid pointer aliasing. */
2260 #define TOK_GET(t, p, cv) \
2262 t = *p++; \
2263 switch(t) { \
2264 case TOK_CINT: \
2265 case TOK_CUINT: \
2266 case TOK_CCHAR: \
2267 case TOK_LCHAR: \
2268 case TOK_CFLOAT: \
2269 case TOK_LINENUM: \
2270 case TOK_STR: \
2271 case TOK_LSTR: \
2272 case TOK_PPNUM: \
2273 cv.tab[0] = *p++; \
2274 break; \
2275 case TOK_CDOUBLE: \
2276 case TOK_CLLONG: \
2277 case TOK_CULLONG: \
2278 cv.tab[0] = p[0]; \
2279 cv.tab[1] = p[1]; \
2280 p += 2; \
2281 break; \
2282 case TOK_CLDOUBLE: \
2283 LDOUBLE_GET(p, cv); \
2284 p += LDOUBLE_SIZE / 4; \
2285 break; \
2286 default: \
2287 break; \
2291 /* defines handling */
2292 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2294 Sym *s;
2296 s = sym_push2(&define_stack, v, macro_type, (int)str);
2297 s->next = first_arg;
2298 table_ident[v - TOK_IDENT]->sym_define = s;
2301 /* undefined a define symbol. Its name is just set to zero */
2302 static void define_undef(Sym *s)
2304 int v;
2305 v = s->v;
2306 if (v >= TOK_IDENT && v < tok_ident)
2307 table_ident[v - TOK_IDENT]->sym_define = NULL;
2308 s->v = 0;
2311 static inline Sym *define_find(int v)
2313 v -= TOK_IDENT;
2314 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2315 return NULL;
2316 return table_ident[v]->sym_define;
2319 /* free define stack until top reaches 'b' */
2320 static void free_defines(Sym *b)
2322 Sym *top, *top1;
2323 int v;
2325 top = define_stack;
2326 while (top != b) {
2327 top1 = top->prev;
2328 /* do not free args or predefined defines */
2329 if (top->c)
2330 tok_str_free((int *)top->c);
2331 v = top->v;
2332 if (v >= TOK_IDENT && v < tok_ident)
2333 table_ident[v - TOK_IDENT]->sym_define = NULL;
2334 tcc_free(top);
2335 top = top1;
2337 define_stack = b;
2340 /* label lookup */
2341 static Sym *label_find(int v)
2343 v -= TOK_IDENT;
2344 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2345 return NULL;
2346 return table_ident[v]->sym_label;
2349 static Sym *label_push(Sym **ptop, int v, int flags)
2351 Sym *s, **ps;
2352 s = sym_push2(ptop, v, 0, 0);
2353 s->r = flags;
2354 ps = &table_ident[v - TOK_IDENT]->sym_label;
2355 if (ptop == &global_label_stack) {
2356 /* modify the top most local identifier, so that
2357 sym_identifier will point to 's' when popped */
2358 while (*ps != NULL)
2359 ps = &(*ps)->prev_tok;
2361 s->prev_tok = *ps;
2362 *ps = s;
2363 return s;
2366 /* pop labels until element last is reached. Look if any labels are
2367 undefined. Define symbols if '&&label' was used. */
2368 static void label_pop(Sym **ptop, Sym *slast)
2370 Sym *s, *s1;
2371 for(s = *ptop; s != slast; s = s1) {
2372 s1 = s->prev;
2373 if (s->r == LABEL_DECLARED) {
2374 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2375 } else if (s->r == LABEL_FORWARD) {
2376 error("label '%s' used but not defined",
2377 get_tok_str(s->v, NULL));
2378 } else {
2379 if (s->c) {
2380 /* define corresponding symbol. A size of
2381 1 is put. */
2382 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2385 /* remove label */
2386 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2387 tcc_free(s);
2389 *ptop = slast;
2392 /* eval an expression for #if/#elif */
2393 static int expr_preprocess(void)
2395 int c, t;
2396 TokenString str;
2398 tok_str_new(&str);
2399 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2400 next(); /* do macro subst */
2401 if (tok == TOK_DEFINED) {
2402 next_nomacro();
2403 t = tok;
2404 if (t == '(')
2405 next_nomacro();
2406 c = define_find(tok) != 0;
2407 if (t == '(')
2408 next_nomacro();
2409 tok = TOK_CINT;
2410 tokc.i = c;
2411 } else if (tok >= TOK_IDENT) {
2412 /* if undefined macro */
2413 tok = TOK_CINT;
2414 tokc.i = 0;
2416 tok_str_add_tok(&str);
2418 tok_str_add(&str, -1); /* simulate end of file */
2419 tok_str_add(&str, 0);
2420 /* now evaluate C constant expression */
2421 macro_ptr = str.str;
2422 next();
2423 c = expr_const();
2424 macro_ptr = NULL;
2425 tok_str_free(str.str);
2426 return c != 0;
2429 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2430 static void tok_print(int *str)
2432 int t;
2433 CValue cval;
2435 while (1) {
2436 TOK_GET(t, str, cval);
2437 if (!t)
2438 break;
2439 printf(" %s", get_tok_str(t, &cval));
2441 printf("\n");
2443 #endif
2445 /* parse after #define */
2446 static void parse_define(void)
2448 Sym *s, *first, **ps;
2449 int v, t, varg, is_vaargs, c;
2450 TokenString str;
2452 v = tok;
2453 if (v < TOK_IDENT)
2454 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2455 /* XXX: should check if same macro (ANSI) */
2456 first = NULL;
2457 t = MACRO_OBJ;
2458 /* '(' must be just after macro definition for MACRO_FUNC */
2459 c = file->buf_ptr[0];
2460 if (c == '\\')
2461 c = handle_stray1(file->buf_ptr);
2462 if (c == '(') {
2463 next_nomacro();
2464 next_nomacro();
2465 ps = &first;
2466 while (tok != ')') {
2467 varg = tok;
2468 next_nomacro();
2469 is_vaargs = 0;
2470 if (varg == TOK_DOTS) {
2471 varg = TOK___VA_ARGS__;
2472 is_vaargs = 1;
2473 } else if (tok == TOK_DOTS && gnu_ext) {
2474 is_vaargs = 1;
2475 next_nomacro();
2477 if (varg < TOK_IDENT)
2478 error("badly punctuated parameter list");
2479 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2480 *ps = s;
2481 ps = &s->next;
2482 if (tok != ',')
2483 break;
2484 next_nomacro();
2486 t = MACRO_FUNC;
2488 tok_str_new(&str);
2489 next_nomacro();
2490 /* EOF testing necessary for '-D' handling */
2491 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2492 tok_str_add2(&str, tok, &tokc);
2493 next_nomacro();
2495 tok_str_add(&str, 0);
2496 #ifdef PP_DEBUG
2497 printf("define %s %d: ", get_tok_str(v, NULL), t);
2498 tok_print(str.str);
2499 #endif
2500 define_push(v, t, str.str, first);
2503 /* XXX: use a token or a hash table to accelerate matching ? */
2504 static CachedInclude *search_cached_include(TCCState *s1,
2505 int type, const char *filename)
2507 CachedInclude *e;
2508 int i;
2510 for(i = 0;i < s1->nb_cached_includes; i++) {
2511 e = s1->cached_includes[i];
2512 if (e->type == type && !strcmp(e->filename, filename))
2513 return e;
2515 return NULL;
2518 static inline void add_cached_include(TCCState *s1, int type,
2519 const char *filename, int ifndef_macro)
2521 CachedInclude *e;
2523 if (search_cached_include(s1, type, filename))
2524 return;
2525 #ifdef INC_DEBUG
2526 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2527 #endif
2528 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2529 if (!e)
2530 return;
2531 e->type = type;
2532 strcpy(e->filename, filename);
2533 e->ifndef_macro = ifndef_macro;
2534 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2537 /* is_bof is true if first non space token at beginning of file */
2538 static void preprocess(int is_bof)
2540 TCCState *s1 = tcc_state;
2541 int size, i, c, n, saved_parse_flags;
2542 char buf[1024], *q, *p;
2543 char buf1[1024];
2544 BufferedFile *f;
2545 Sym *s;
2546 CachedInclude *e;
2548 saved_parse_flags = parse_flags;
2549 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2550 PARSE_FLAG_LINEFEED;
2551 next_nomacro();
2552 redo:
2553 switch(tok) {
2554 case TOK_DEFINE:
2555 next_nomacro();
2556 parse_define();
2557 break;
2558 case TOK_UNDEF:
2559 next_nomacro();
2560 s = define_find(tok);
2561 /* undefine symbol by putting an invalid name */
2562 if (s)
2563 define_undef(s);
2564 break;
2565 case TOK_INCLUDE:
2566 ch = file->buf_ptr[0];
2567 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2568 skip_spaces();
2569 if (ch == '<') {
2570 c = '>';
2571 goto read_name;
2572 } else if (ch == '\"') {
2573 c = ch;
2574 read_name:
2575 /* XXX: better stray handling */
2576 minp();
2577 q = buf;
2578 while (ch != c && ch != '\n' && ch != CH_EOF) {
2579 if ((q - buf) < sizeof(buf) - 1)
2580 *q++ = ch;
2581 minp();
2583 *q = '\0';
2584 minp();
2585 #if 0
2586 /* eat all spaces and comments after include */
2587 /* XXX: slightly incorrect */
2588 while (ch1 != '\n' && ch1 != CH_EOF)
2589 inp();
2590 #endif
2591 } else {
2592 /* computed #include : either we have only strings or
2593 we have anything enclosed in '<>' */
2594 next();
2595 buf[0] = '\0';
2596 if (tok == TOK_STR) {
2597 while (tok != TOK_LINEFEED) {
2598 if (tok != TOK_STR) {
2599 include_syntax:
2600 error("'#include' expects \"FILENAME\" or <FILENAME>");
2602 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2603 next();
2605 c = '\"';
2606 } else {
2607 int len;
2608 while (tok != TOK_LINEFEED) {
2609 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2610 next();
2612 len = strlen(buf);
2613 /* check syntax and remove '<>' */
2614 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2615 goto include_syntax;
2616 memmove(buf, buf + 1, len - 2);
2617 buf[len - 2] = '\0';
2618 c = '>';
2622 e = search_cached_include(s1, c, buf);
2623 if (e && define_find(e->ifndef_macro)) {
2624 /* no need to parse the include because the 'ifndef macro'
2625 is defined */
2626 #ifdef INC_DEBUG
2627 printf("%s: skipping %s\n", file->filename, buf);
2628 #endif
2629 } else {
2630 if (c == '\"') {
2631 /* first search in current dir if "header.h" */
2632 size = 0;
2633 p = strrchr(file->filename, '/');
2634 if (p)
2635 size = p + 1 - file->filename;
2636 if (size > sizeof(buf1) - 1)
2637 size = sizeof(buf1) - 1;
2638 memcpy(buf1, file->filename, size);
2639 buf1[size] = '\0';
2640 pstrcat(buf1, sizeof(buf1), buf);
2641 f = tcc_open(s1, buf1);
2642 if (f)
2643 goto found;
2645 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2646 error("#include recursion too deep");
2647 /* now search in all the include paths */
2648 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2649 for(i = 0; i < n; i++) {
2650 const char *path;
2651 if (i < s1->nb_include_paths)
2652 path = s1->include_paths[i];
2653 else
2654 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2655 pstrcpy(buf1, sizeof(buf1), path);
2656 pstrcat(buf1, sizeof(buf1), "/");
2657 pstrcat(buf1, sizeof(buf1), buf);
2658 f = tcc_open(s1, buf1);
2659 if (f)
2660 goto found;
2662 error("include file '%s' not found", buf);
2663 f = NULL;
2664 found:
2665 #ifdef INC_DEBUG
2666 printf("%s: including %s\n", file->filename, buf1);
2667 #endif
2668 f->inc_type = c;
2669 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2670 /* push current file in stack */
2671 /* XXX: fix current line init */
2672 *s1->include_stack_ptr++ = file;
2673 file = f;
2674 /* add include file debug info */
2675 if (do_debug) {
2676 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2678 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2679 ch = file->buf_ptr[0];
2680 goto the_end;
2682 break;
2683 case TOK_IFNDEF:
2684 c = 1;
2685 goto do_ifdef;
2686 case TOK_IF:
2687 c = expr_preprocess();
2688 goto do_if;
2689 case TOK_IFDEF:
2690 c = 0;
2691 do_ifdef:
2692 next_nomacro();
2693 if (tok < TOK_IDENT)
2694 error("invalid argument for '#if%sdef'", c ? "n" : "");
2695 if (is_bof) {
2696 if (c) {
2697 #ifdef INC_DEBUG
2698 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2699 #endif
2700 file->ifndef_macro = tok;
2703 c = (define_find(tok) != 0) ^ c;
2704 do_if:
2705 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2706 error("memory full");
2707 *s1->ifdef_stack_ptr++ = c;
2708 goto test_skip;
2709 case TOK_ELSE:
2710 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2711 error("#else without matching #if");
2712 if (s1->ifdef_stack_ptr[-1] & 2)
2713 error("#else after #else");
2714 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2715 goto test_skip;
2716 case TOK_ELIF:
2717 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2718 error("#elif without matching #if");
2719 c = s1->ifdef_stack_ptr[-1];
2720 if (c > 1)
2721 error("#elif after #else");
2722 /* last #if/#elif expression was true: we skip */
2723 if (c == 1)
2724 goto skip;
2725 c = expr_preprocess();
2726 s1->ifdef_stack_ptr[-1] = c;
2727 test_skip:
2728 if (!(c & 1)) {
2729 skip:
2730 preprocess_skip();
2731 is_bof = 0;
2732 goto redo;
2734 break;
2735 case TOK_ENDIF:
2736 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2737 error("#endif without matching #if");
2738 s1->ifdef_stack_ptr--;
2739 /* '#ifndef macro' was at the start of file. Now we check if
2740 an '#endif' is exactly at the end of file */
2741 if (file->ifndef_macro &&
2742 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2743 file->ifndef_macro_saved = file->ifndef_macro;
2744 /* need to set to zero to avoid false matches if another
2745 #ifndef at middle of file */
2746 file->ifndef_macro = 0;
2747 while (tok != TOK_LINEFEED)
2748 next_nomacro();
2749 tok_flags |= TOK_FLAG_ENDIF;
2750 goto the_end;
2752 break;
2753 case TOK_LINE:
2754 next();
2755 if (tok != TOK_CINT)
2756 error("#line");
2757 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2758 next();
2759 if (tok != TOK_LINEFEED) {
2760 if (tok != TOK_STR)
2761 error("#line");
2762 pstrcpy(file->filename, sizeof(file->filename),
2763 (char *)tokc.cstr->data);
2765 break;
2766 case TOK_ERROR:
2767 case TOK_WARNING:
2768 c = tok;
2769 ch = file->buf_ptr[0];
2770 skip_spaces();
2771 q = buf;
2772 while (ch != '\n' && ch != CH_EOF) {
2773 if ((q - buf) < sizeof(buf) - 1)
2774 *q++ = ch;
2775 minp();
2777 *q = '\0';
2778 if (c == TOK_ERROR)
2779 error("#error %s", buf);
2780 else
2781 warning("#warning %s", buf);
2782 break;
2783 case TOK_PRAGMA:
2784 /* ignored */
2785 break;
2786 default:
2787 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2788 /* '!' is ignored to allow C scripts. numbers are ignored
2789 to emulate cpp behaviour */
2790 } else {
2791 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2793 break;
2795 /* ignore other preprocess commands or #! for C scripts */
2796 while (tok != TOK_LINEFEED)
2797 next_nomacro();
2798 the_end:
2799 parse_flags = saved_parse_flags;
2802 /* evaluate escape codes in a string. */
2803 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2805 int c, n;
2806 const char *p;
2808 p = buf;
2809 for(;;) {
2810 c = *p;
2811 if (c == '\0')
2812 break;
2813 if (c == '\\') {
2814 p++;
2815 /* escape */
2816 c = *p;
2817 switch(c) {
2818 case '0': case '1': case '2': case '3':
2819 case '4': case '5': case '6': case '7':
2820 /* at most three octal digits */
2821 n = c - '0';
2822 p++;
2823 c = *p;
2824 if (isoct(c)) {
2825 n = n * 8 + c - '0';
2826 p++;
2827 c = *p;
2828 if (isoct(c)) {
2829 n = n * 8 + c - '0';
2830 p++;
2833 c = n;
2834 goto add_char_nonext;
2835 case 'x':
2836 p++;
2837 n = 0;
2838 for(;;) {
2839 c = *p;
2840 if (c >= 'a' && c <= 'f')
2841 c = c - 'a' + 10;
2842 else if (c >= 'A' && c <= 'F')
2843 c = c - 'A' + 10;
2844 else if (isnum(c))
2845 c = c - '0';
2846 else
2847 break;
2848 n = n * 16 + c;
2849 p++;
2851 c = n;
2852 goto add_char_nonext;
2853 case 'a':
2854 c = '\a';
2855 break;
2856 case 'b':
2857 c = '\b';
2858 break;
2859 case 'f':
2860 c = '\f';
2861 break;
2862 case 'n':
2863 c = '\n';
2864 break;
2865 case 'r':
2866 c = '\r';
2867 break;
2868 case 't':
2869 c = '\t';
2870 break;
2871 case 'v':
2872 c = '\v';
2873 break;
2874 case 'e':
2875 if (!gnu_ext)
2876 goto invalid_escape;
2877 c = 27;
2878 break;
2879 case '\'':
2880 case '\"':
2881 case '\\':
2882 case '?':
2883 break;
2884 default:
2885 invalid_escape:
2886 error("invalid escaped char");
2889 p++;
2890 add_char_nonext:
2891 if (!is_long)
2892 cstr_ccat(outstr, c);
2893 else
2894 cstr_wccat(outstr, c);
2896 /* add a trailing '\0' */
2897 if (!is_long)
2898 cstr_ccat(outstr, '\0');
2899 else
2900 cstr_wccat(outstr, '\0');
2903 /* we use 64 bit numbers */
2904 #define BN_SIZE 2
2906 /* bn = (bn << shift) | or_val */
2907 void bn_lshift(unsigned int *bn, int shift, int or_val)
2909 int i;
2910 unsigned int v;
2911 for(i=0;i<BN_SIZE;i++) {
2912 v = bn[i];
2913 bn[i] = (v << shift) | or_val;
2914 or_val = v >> (32 - shift);
2918 void bn_zero(unsigned int *bn)
2920 int i;
2921 for(i=0;i<BN_SIZE;i++) {
2922 bn[i] = 0;
2926 /* parse number in null terminated string 'p' and return it in the
2927 current token */
2928 void parse_number(const char *p)
2930 int b, t, shift, frac_bits, s, exp_val, ch;
2931 char *q;
2932 unsigned int bn[BN_SIZE];
2933 double d;
2935 /* number */
2936 q = token_buf;
2937 ch = *p++;
2938 t = ch;
2939 ch = *p++;
2940 *q++ = t;
2941 b = 10;
2942 if (t == '.') {
2943 goto float_frac_parse;
2944 } else if (t == '0') {
2945 if (ch == 'x' || ch == 'X') {
2946 q--;
2947 ch = *p++;
2948 b = 16;
2949 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2950 q--;
2951 ch = *p++;
2952 b = 2;
2955 /* parse all digits. cannot check octal numbers at this stage
2956 because of floating point constants */
2957 while (1) {
2958 if (ch >= 'a' && ch <= 'f')
2959 t = ch - 'a' + 10;
2960 else if (ch >= 'A' && ch <= 'F')
2961 t = ch - 'A' + 10;
2962 else if (isnum(ch))
2963 t = ch - '0';
2964 else
2965 break;
2966 if (t >= b)
2967 break;
2968 if (q >= token_buf + STRING_MAX_SIZE) {
2969 num_too_long:
2970 error("number too long");
2972 *q++ = ch;
2973 ch = *p++;
2975 if (ch == '.' ||
2976 ((ch == 'e' || ch == 'E') && b == 10) ||
2977 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
2978 if (b != 10) {
2979 /* NOTE: strtox should support that for hexa numbers, but
2980 non ISOC99 libcs do not support it, so we prefer to do
2981 it by hand */
2982 /* hexadecimal or binary floats */
2983 /* XXX: handle overflows */
2984 *q = '\0';
2985 if (b == 16)
2986 shift = 4;
2987 else
2988 shift = 2;
2989 bn_zero(bn);
2990 q = token_buf;
2991 while (1) {
2992 t = *q++;
2993 if (t == '\0') {
2994 break;
2995 } else if (t >= 'a') {
2996 t = t - 'a' + 10;
2997 } else if (t >= 'A') {
2998 t = t - 'A' + 10;
2999 } else {
3000 t = t - '0';
3002 bn_lshift(bn, shift, t);
3004 frac_bits = 0;
3005 if (ch == '.') {
3006 ch = *p++;
3007 while (1) {
3008 t = ch;
3009 if (t >= 'a' && t <= 'f') {
3010 t = t - 'a' + 10;
3011 } else if (t >= 'A' && t <= 'F') {
3012 t = t - 'A' + 10;
3013 } else if (t >= '0' && t <= '9') {
3014 t = t - '0';
3015 } else {
3016 break;
3018 if (t >= b)
3019 error("invalid digit");
3020 bn_lshift(bn, shift, t);
3021 frac_bits += shift;
3022 ch = *p++;
3025 if (ch != 'p' && ch != 'P')
3026 expect("exponent");
3027 ch = *p++;
3028 s = 1;
3029 exp_val = 0;
3030 if (ch == '+') {
3031 ch = *p++;
3032 } else if (ch == '-') {
3033 s = -1;
3034 ch = *p++;
3036 if (ch < '0' || ch > '9')
3037 expect("exponent digits");
3038 while (ch >= '0' && ch <= '9') {
3039 exp_val = exp_val * 10 + ch - '0';
3040 ch = *p++;
3042 exp_val = exp_val * s;
3044 /* now we can generate the number */
3045 /* XXX: should patch directly float number */
3046 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3047 d = ldexp(d, exp_val - frac_bits);
3048 t = toup(ch);
3049 if (t == 'F') {
3050 ch = *p++;
3051 tok = TOK_CFLOAT;
3052 /* float : should handle overflow */
3053 tokc.f = (float)d;
3054 } else if (t == 'L') {
3055 ch = *p++;
3056 tok = TOK_CLDOUBLE;
3057 /* XXX: not large enough */
3058 tokc.ld = (long double)d;
3059 } else {
3060 tok = TOK_CDOUBLE;
3061 tokc.d = d;
3063 } else {
3064 /* decimal floats */
3065 if (ch == '.') {
3066 if (q >= token_buf + STRING_MAX_SIZE)
3067 goto num_too_long;
3068 *q++ = ch;
3069 ch = *p++;
3070 float_frac_parse:
3071 while (ch >= '0' && ch <= '9') {
3072 if (q >= token_buf + STRING_MAX_SIZE)
3073 goto num_too_long;
3074 *q++ = ch;
3075 ch = *p++;
3078 if (ch == 'e' || ch == 'E') {
3079 if (q >= token_buf + STRING_MAX_SIZE)
3080 goto num_too_long;
3081 *q++ = ch;
3082 ch = *p++;
3083 if (ch == '-' || ch == '+') {
3084 if (q >= token_buf + STRING_MAX_SIZE)
3085 goto num_too_long;
3086 *q++ = ch;
3087 ch = *p++;
3089 if (ch < '0' || ch > '9')
3090 expect("exponent digits");
3091 while (ch >= '0' && ch <= '9') {
3092 if (q >= token_buf + STRING_MAX_SIZE)
3093 goto num_too_long;
3094 *q++ = ch;
3095 ch = *p++;
3098 *q = '\0';
3099 t = toup(ch);
3100 errno = 0;
3101 if (t == 'F') {
3102 ch = *p++;
3103 tok = TOK_CFLOAT;
3104 tokc.f = strtof(token_buf, NULL);
3105 } else if (t == 'L') {
3106 ch = *p++;
3107 tok = TOK_CLDOUBLE;
3108 tokc.ld = strtold(token_buf, NULL);
3109 } else {
3110 tok = TOK_CDOUBLE;
3111 tokc.d = strtod(token_buf, NULL);
3114 } else {
3115 unsigned long long n, n1;
3116 int lcount, ucount;
3118 /* integer number */
3119 *q = '\0';
3120 q = token_buf;
3121 if (b == 10 && *q == '0') {
3122 b = 8;
3123 q++;
3125 n = 0;
3126 while(1) {
3127 t = *q++;
3128 /* no need for checks except for base 10 / 8 errors */
3129 if (t == '\0') {
3130 break;
3131 } else if (t >= 'a') {
3132 t = t - 'a' + 10;
3133 } else if (t >= 'A') {
3134 t = t - 'A' + 10;
3135 } else {
3136 t = t - '0';
3137 if (t >= b)
3138 error("invalid digit");
3140 n1 = n;
3141 n = n * b + t;
3142 /* detect overflow */
3143 /* XXX: this test is not reliable */
3144 if (n < n1)
3145 error("integer constant overflow");
3148 /* XXX: not exactly ANSI compliant */
3149 if ((n & 0xffffffff00000000LL) != 0) {
3150 if ((n >> 63) != 0)
3151 tok = TOK_CULLONG;
3152 else
3153 tok = TOK_CLLONG;
3154 } else if (n > 0x7fffffff) {
3155 tok = TOK_CUINT;
3156 } else {
3157 tok = TOK_CINT;
3159 lcount = 0;
3160 ucount = 0;
3161 for(;;) {
3162 t = toup(ch);
3163 if (t == 'L') {
3164 if (lcount >= 2)
3165 error("three 'l's in integer constant");
3166 lcount++;
3167 if (lcount == 2) {
3168 if (tok == TOK_CINT)
3169 tok = TOK_CLLONG;
3170 else if (tok == TOK_CUINT)
3171 tok = TOK_CULLONG;
3173 ch = *p++;
3174 } else if (t == 'U') {
3175 if (ucount >= 1)
3176 error("two 'u's in integer constant");
3177 ucount++;
3178 if (tok == TOK_CINT)
3179 tok = TOK_CUINT;
3180 else if (tok == TOK_CLLONG)
3181 tok = TOK_CULLONG;
3182 ch = *p++;
3183 } else {
3184 break;
3187 if (tok == TOK_CINT || tok == TOK_CUINT)
3188 tokc.ui = n;
3189 else
3190 tokc.ull = n;
3195 #define PARSE2(c1, tok1, c2, tok2) \
3196 case c1: \
3197 PEEKC(c, p); \
3198 if (c == c2) { \
3199 p++; \
3200 tok = tok2; \
3201 } else { \
3202 tok = tok1; \
3204 break;
3206 /* return next token without macro substitution */
3207 static inline void next_nomacro1(void)
3209 int t, c, is_long;
3210 TokenSym *ts;
3211 uint8_t *p, *p1;
3212 unsigned int h;
3214 p = file->buf_ptr;
3215 redo_no_start:
3216 c = *p;
3217 switch(c) {
3218 case ' ':
3219 case '\t':
3220 case '\f':
3221 case '\v':
3222 case '\r':
3223 p++;
3224 goto redo_no_start;
3226 case '\\':
3227 /* first look if it is in fact an end of buffer */
3228 if (p >= file->buf_end) {
3229 file->buf_ptr = p;
3230 handle_eob();
3231 p = file->buf_ptr;
3232 if (p >= file->buf_end)
3233 goto parse_eof;
3234 else
3235 goto redo_no_start;
3236 } else {
3237 file->buf_ptr = p;
3238 ch = *p;
3239 handle_stray();
3240 p = file->buf_ptr;
3241 goto redo_no_start;
3243 parse_eof:
3245 TCCState *s1 = tcc_state;
3246 if (parse_flags & PARSE_FLAG_LINEFEED) {
3247 tok = TOK_LINEFEED;
3248 } else if (s1->include_stack_ptr == s1->include_stack ||
3249 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3250 /* no include left : end of file. */
3251 tok = TOK_EOF;
3252 } else {
3253 /* pop include file */
3255 /* test if previous '#endif' was after a #ifdef at
3256 start of file */
3257 if (tok_flags & TOK_FLAG_ENDIF) {
3258 #ifdef INC_DEBUG
3259 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3260 #endif
3261 add_cached_include(s1, file->inc_type, file->inc_filename,
3262 file->ifndef_macro_saved);
3265 /* add end of include file debug info */
3266 if (do_debug) {
3267 put_stabd(N_EINCL, 0, 0);
3269 /* pop include stack */
3270 tcc_close(file);
3271 s1->include_stack_ptr--;
3272 file = *s1->include_stack_ptr;
3273 p = file->buf_ptr;
3274 goto redo_no_start;
3277 break;
3279 case '\n':
3280 if (parse_flags & PARSE_FLAG_LINEFEED) {
3281 tok = TOK_LINEFEED;
3282 } else {
3283 file->line_num++;
3284 tok_flags |= TOK_FLAG_BOL;
3285 p++;
3286 goto redo_no_start;
3288 break;
3290 case '#':
3291 /* XXX: simplify */
3292 PEEKC(c, p);
3293 if ((tok_flags & TOK_FLAG_BOL) &&
3294 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3295 file->buf_ptr = p;
3296 preprocess(tok_flags & TOK_FLAG_BOF);
3297 p = file->buf_ptr;
3298 goto redo_no_start;
3299 } else {
3300 if (c == '#') {
3301 p++;
3302 tok = TOK_TWOSHARPS;
3303 } else {
3304 tok = '#';
3307 break;
3309 case 'a': case 'b': case 'c': case 'd':
3310 case 'e': case 'f': case 'g': case 'h':
3311 case 'i': case 'j': case 'k': case 'l':
3312 case 'm': case 'n': case 'o': case 'p':
3313 case 'q': case 'r': case 's': case 't':
3314 case 'u': case 'v': case 'w': case 'x':
3315 case 'y': case 'z':
3316 case 'A': case 'B': case 'C': case 'D':
3317 case 'E': case 'F': case 'G': case 'H':
3318 case 'I': case 'J': case 'K':
3319 case 'M': case 'N': case 'O': case 'P':
3320 case 'Q': case 'R': case 'S': case 'T':
3321 case 'U': case 'V': case 'W': case 'X':
3322 case 'Y': case 'Z':
3323 case '_':
3324 parse_ident_fast:
3325 p1 = p;
3326 h = TOK_HASH_INIT;
3327 h = TOK_HASH_FUNC(h, c);
3328 p++;
3329 for(;;) {
3330 c = *p;
3331 if (!isidnum_table[c])
3332 break;
3333 h = TOK_HASH_FUNC(h, c);
3334 p++;
3336 if (c != '\\') {
3337 TokenSym **pts;
3338 int len;
3340 /* fast case : no stray found, so we have the full token
3341 and we have already hashed it */
3342 len = p - p1;
3343 h &= (TOK_HASH_SIZE - 1);
3344 pts = &hash_ident[h];
3345 for(;;) {
3346 ts = *pts;
3347 if (!ts)
3348 break;
3349 if (ts->len == len && !memcmp(ts->str, p1, len))
3350 goto token_found;
3351 pts = &(ts->hash_next);
3353 ts = tok_alloc_new(pts, p1, len);
3354 token_found: ;
3355 } else {
3356 /* slower case */
3357 cstr_reset(&tokcstr);
3359 while (p1 < p) {
3360 cstr_ccat(&tokcstr, *p1);
3361 p1++;
3363 p--;
3364 PEEKC(c, p);
3365 parse_ident_slow:
3366 while (isidnum_table[c]) {
3367 cstr_ccat(&tokcstr, c);
3368 PEEKC(c, p);
3370 ts = tok_alloc(tokcstr.data, tokcstr.size);
3372 tok = ts->tok;
3373 break;
3374 case 'L':
3375 t = p[1];
3376 if (t != '\\' && t != '\'' && t != '\"') {
3377 /* fast case */
3378 goto parse_ident_fast;
3379 } else {
3380 PEEKC(c, p);
3381 if (c == '\'' || c == '\"') {
3382 is_long = 1;
3383 goto str_const;
3384 } else {
3385 cstr_reset(&tokcstr);
3386 cstr_ccat(&tokcstr, 'L');
3387 goto parse_ident_slow;
3390 break;
3391 case '0': case '1': case '2': case '3':
3392 case '4': case '5': case '6': case '7':
3393 case '8': case '9':
3395 cstr_reset(&tokcstr);
3396 /* after the first digit, accept digits, alpha, '.' or sign if
3397 prefixed by 'eEpP' */
3398 parse_num:
3399 for(;;) {
3400 t = c;
3401 cstr_ccat(&tokcstr, c);
3402 PEEKC(c, p);
3403 if (!(isnum(c) || isid(c) || c == '.' ||
3404 ((c == '+' || c == '-') &&
3405 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3406 break;
3408 /* We add a trailing '\0' to ease parsing */
3409 cstr_ccat(&tokcstr, '\0');
3410 tokc.cstr = &tokcstr;
3411 tok = TOK_PPNUM;
3412 break;
3413 case '.':
3414 /* special dot handling because it can also start a number */
3415 PEEKC(c, p);
3416 if (isnum(c)) {
3417 cstr_reset(&tokcstr);
3418 cstr_ccat(&tokcstr, '.');
3419 goto parse_num;
3420 } else if (c == '.') {
3421 PEEKC(c, p);
3422 if (c != '.')
3423 expect("'.'");
3424 PEEKC(c, p);
3425 tok = TOK_DOTS;
3426 } else {
3427 tok = '.';
3429 break;
3430 case '\'':
3431 case '\"':
3432 is_long = 0;
3433 str_const:
3435 CString str;
3436 int sep;
3438 sep = c;
3440 /* parse the string */
3441 cstr_new(&str);
3442 p = parse_pp_string(p, sep, &str);
3443 cstr_ccat(&str, '\0');
3445 /* eval the escape (should be done as TOK_PPNUM) */
3446 cstr_reset(&tokcstr);
3447 parse_escape_string(&tokcstr, str.data, is_long);
3448 cstr_free(&str);
3450 if (sep == '\'') {
3451 int char_size;
3452 /* XXX: make it portable */
3453 if (!is_long)
3454 char_size = 1;
3455 else
3456 char_size = sizeof(int);
3457 if (tokcstr.size <= char_size)
3458 error("empty character constant");
3459 if (tokcstr.size > 2 * char_size)
3460 warning("multi-character character constant");
3461 if (!is_long) {
3462 tokc.i = *(int8_t *)tokcstr.data;
3463 tok = TOK_CCHAR;
3464 } else {
3465 tokc.i = *(int *)tokcstr.data;
3466 tok = TOK_LCHAR;
3468 } else {
3469 tokc.cstr = &tokcstr;
3470 if (!is_long)
3471 tok = TOK_STR;
3472 else
3473 tok = TOK_LSTR;
3476 break;
3478 case '<':
3479 PEEKC(c, p);
3480 if (c == '=') {
3481 p++;
3482 tok = TOK_LE;
3483 } else if (c == '<') {
3484 PEEKC(c, p);
3485 if (c == '=') {
3486 p++;
3487 tok = TOK_A_SHL;
3488 } else {
3489 tok = TOK_SHL;
3491 } else {
3492 tok = TOK_LT;
3494 break;
3496 case '>':
3497 PEEKC(c, p);
3498 if (c == '=') {
3499 p++;
3500 tok = TOK_GE;
3501 } else if (c == '>') {
3502 PEEKC(c, p);
3503 if (c == '=') {
3504 p++;
3505 tok = TOK_A_SAR;
3506 } else {
3507 tok = TOK_SAR;
3509 } else {
3510 tok = TOK_GT;
3512 break;
3514 case '&':
3515 PEEKC(c, p);
3516 if (c == '&') {
3517 p++;
3518 tok = TOK_LAND;
3519 } else if (c == '=') {
3520 p++;
3521 tok = TOK_A_AND;
3522 } else {
3523 tok = '&';
3525 break;
3527 case '|':
3528 PEEKC(c, p);
3529 if (c == '|') {
3530 p++;
3531 tok = TOK_LOR;
3532 } else if (c == '=') {
3533 p++;
3534 tok = TOK_A_OR;
3535 } else {
3536 tok = '|';
3538 break;
3540 case '+':
3541 PEEKC(c, p);
3542 if (c == '+') {
3543 p++;
3544 tok = TOK_INC;
3545 } else if (c == '=') {
3546 p++;
3547 tok = TOK_A_ADD;
3548 } else {
3549 tok = '+';
3551 break;
3553 case '-':
3554 PEEKC(c, p);
3555 if (c == '-') {
3556 p++;
3557 tok = TOK_DEC;
3558 } else if (c == '=') {
3559 p++;
3560 tok = TOK_A_SUB;
3561 } else if (c == '>') {
3562 p++;
3563 tok = TOK_ARROW;
3564 } else {
3565 tok = '-';
3567 break;
3569 PARSE2('!', '!', '=', TOK_NE)
3570 PARSE2('=', '=', '=', TOK_EQ)
3571 PARSE2('*', '*', '=', TOK_A_MUL)
3572 PARSE2('%', '%', '=', TOK_A_MOD)
3573 PARSE2('^', '^', '=', TOK_A_XOR)
3575 /* comments or operator */
3576 case '/':
3577 PEEKC(c, p);
3578 if (c == '*') {
3579 p = parse_comment(p);
3580 goto redo_no_start;
3581 } else if (c == '/') {
3582 p = parse_line_comment(p);
3583 goto redo_no_start;
3584 } else if (c == '=') {
3585 p++;
3586 tok = TOK_A_DIV;
3587 } else {
3588 tok = '/';
3590 break;
3592 /* simple tokens */
3593 case '(':
3594 case ')':
3595 case '[':
3596 case ']':
3597 case '{':
3598 case '}':
3599 case ',':
3600 case ';':
3601 case ':':
3602 case '?':
3603 case '~':
3604 case '$': /* only used in assembler */
3605 tok = c;
3606 p++;
3607 break;
3608 default:
3609 error("unrecognized character \\x%02x", c);
3610 break;
3612 file->buf_ptr = p;
3613 tok_flags = 0;
3614 #if defined(PARSE_DEBUG)
3615 printf("token = %s\n", get_tok_str(tok, &tokc));
3616 #endif
3619 /* return next token without macro substitution. Can read input from
3620 macro_ptr buffer */
3621 static void next_nomacro(void)
3623 if (macro_ptr) {
3624 redo:
3625 tok = *macro_ptr;
3626 if (tok) {
3627 TOK_GET(tok, macro_ptr, tokc);
3628 if (tok == TOK_LINENUM) {
3629 file->line_num = tokc.i;
3630 goto redo;
3633 } else {
3634 next_nomacro1();
3638 /* substitute args in macro_str and return allocated string */
3639 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3641 int *st, last_tok, t, notfirst;
3642 Sym *s;
3643 CValue cval;
3644 TokenString str;
3645 CString cstr;
3647 tok_str_new(&str);
3648 last_tok = 0;
3649 while(1) {
3650 TOK_GET(t, macro_str, cval);
3651 if (!t)
3652 break;
3653 if (t == '#') {
3654 /* stringize */
3655 TOK_GET(t, macro_str, cval);
3656 if (!t)
3657 break;
3658 s = sym_find2(args, t);
3659 if (s) {
3660 cstr_new(&cstr);
3661 st = (int *)s->c;
3662 notfirst = 0;
3663 while (*st) {
3664 if (notfirst)
3665 cstr_ccat(&cstr, ' ');
3666 TOK_GET(t, st, cval);
3667 cstr_cat(&cstr, get_tok_str(t, &cval));
3668 notfirst = 1;
3670 cstr_ccat(&cstr, '\0');
3671 #ifdef PP_DEBUG
3672 printf("stringize: %s\n", (char *)cstr.data);
3673 #endif
3674 /* add string */
3675 cval.cstr = &cstr;
3676 tok_str_add2(&str, TOK_STR, &cval);
3677 cstr_free(&cstr);
3678 } else {
3679 tok_str_add2(&str, t, &cval);
3681 } else if (t >= TOK_IDENT) {
3682 s = sym_find2(args, t);
3683 if (s) {
3684 st = (int *)s->c;
3685 /* if '##' is present before or after, no arg substitution */
3686 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3687 /* special case for var arg macros : ## eats the
3688 ',' if empty VA_ARGS variable. */
3689 /* XXX: test of the ',' is not 100%
3690 reliable. should fix it to avoid security
3691 problems */
3692 if (gnu_ext && s->type.t &&
3693 last_tok == TOK_TWOSHARPS &&
3694 str.len >= 2 && str.str[str.len - 2] == ',') {
3695 if (*st == 0) {
3696 /* suppress ',' '##' */
3697 str.len -= 2;
3698 } else {
3699 /* suppress '##' and add variable */
3700 str.len--;
3701 goto add_var;
3703 } else {
3704 int t1;
3705 add_var:
3706 for(;;) {
3707 TOK_GET(t1, st, cval);
3708 if (!t1)
3709 break;
3710 tok_str_add2(&str, t1, &cval);
3713 } else {
3714 macro_subst(&str, nested_list, st);
3716 } else {
3717 tok_str_add(&str, t);
3719 } else {
3720 tok_str_add2(&str, t, &cval);
3722 last_tok = t;
3724 tok_str_add(&str, 0);
3725 return str.str;
3728 static char const ab_month_name[12][4] =
3730 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3731 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3734 /* do macro substitution of current token with macro 's' and add
3735 result to (tok_str,tok_len). 'nested_list' is the list of all
3736 macros we got inside to avoid recursing. Return non zero if no
3737 substitution needs to be done */
3738 static int macro_subst_tok(TokenString *tok_str,
3739 Sym **nested_list, Sym *s)
3741 Sym *args, *sa, *sa1;
3742 int mstr_allocated, parlevel, *mstr, t;
3743 TokenString str;
3744 char *cstrval;
3745 CValue cval;
3746 CString cstr;
3748 /* if symbol is a macro, prepare substitution */
3750 /* special macros */
3751 if (tok == TOK___LINE__) {
3752 cval.i = file->line_num;
3753 tok_str_add2(tok_str, TOK_CINT, &cval);
3754 } else if (tok == TOK___FILE__) {
3755 cstrval = file->filename;
3756 goto add_cstr;
3757 tok_str_add2(tok_str, TOK_STR, &cval);
3758 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3759 time_t ti;
3760 struct tm *tm;
3761 char buf[64];
3763 time(&ti);
3764 tm = localtime(&ti);
3765 if (tok == TOK___DATE__) {
3766 snprintf(buf, sizeof(buf), "%s %2d %d",
3767 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3768 } else {
3769 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3770 tm->tm_hour, tm->tm_min, tm->tm_sec);
3772 cstrval = buf;
3773 add_cstr:
3774 cstr_new(&cstr);
3775 cstr_cat(&cstr, cstrval);
3776 cstr_ccat(&cstr, '\0');
3777 cval.cstr = &cstr;
3778 tok_str_add2(tok_str, TOK_STR, &cval);
3779 cstr_free(&cstr);
3780 } else {
3781 mstr = (int *)s->c;
3782 mstr_allocated = 0;
3783 if (s->type.t == MACRO_FUNC) {
3784 /* NOTE: we do not use next_nomacro to avoid eating the
3785 next token. XXX: find better solution */
3786 if (macro_ptr) {
3787 t = *macro_ptr;
3788 if (t == 0) {
3789 /* end of macro stream: we must look at the token
3790 after in the file */
3791 macro_ptr = NULL;
3792 goto parse_stream;
3794 } else {
3795 parse_stream:
3796 /* XXX: incorrect with comments */
3797 ch = file->buf_ptr[0];
3798 while (is_space(ch) || ch == '\n')
3799 cinp();
3800 t = ch;
3802 if (t != '(') /* no macro subst */
3803 return -1;
3805 /* argument macro */
3806 next_nomacro();
3807 next_nomacro();
3808 args = NULL;
3809 sa = s->next;
3810 /* NOTE: empty args are allowed, except if no args */
3811 for(;;) {
3812 /* handle '()' case */
3813 if (!args && tok == ')')
3814 break;
3815 if (!sa)
3816 error("macro '%s' used with too many args",
3817 get_tok_str(s->v, 0));
3818 tok_str_new(&str);
3819 parlevel = 0;
3820 /* NOTE: non zero sa->t indicates VA_ARGS */
3821 while ((parlevel > 0 ||
3822 (tok != ')' &&
3823 (tok != ',' || sa->type.t))) &&
3824 tok != -1) {
3825 if (tok == '(')
3826 parlevel++;
3827 else if (tok == ')')
3828 parlevel--;
3829 tok_str_add2(&str, tok, &tokc);
3830 next_nomacro();
3832 tok_str_add(&str, 0);
3833 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3834 sa = sa->next;
3835 if (tok == ')') {
3836 /* special case for gcc var args: add an empty
3837 var arg argument if it is omitted */
3838 if (sa && sa->type.t && gnu_ext)
3839 continue;
3840 else
3841 break;
3843 if (tok != ',')
3844 expect(",");
3845 next_nomacro();
3847 if (sa) {
3848 error("macro '%s' used with too few args",
3849 get_tok_str(s->v, 0));
3852 /* now subst each arg */
3853 mstr = macro_arg_subst(nested_list, mstr, args);
3854 /* free memory */
3855 sa = args;
3856 while (sa) {
3857 sa1 = sa->prev;
3858 tok_str_free((int *)sa->c);
3859 tcc_free(sa);
3860 sa = sa1;
3862 mstr_allocated = 1;
3864 sym_push2(nested_list, s->v, 0, 0);
3865 macro_subst(tok_str, nested_list, mstr);
3866 /* pop nested defined symbol */
3867 sa1 = *nested_list;
3868 *nested_list = sa1->prev;
3869 tcc_free(sa1);
3870 if (mstr_allocated)
3871 tok_str_free(mstr);
3873 return 0;
3876 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3877 return the resulting string (which must be freed). */
3878 static inline int *macro_twosharps(const int *macro_str)
3880 TokenSym *ts;
3881 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3882 int t;
3883 const char *p1, *p2;
3884 CValue cval;
3885 TokenString macro_str1;
3886 CString cstr;
3888 start_macro_ptr = macro_str;
3889 /* we search the first '##' */
3890 for(;;) {
3891 macro_ptr1 = macro_str;
3892 TOK_GET(t, macro_str, cval);
3893 /* nothing more to do if end of string */
3894 if (t == 0)
3895 return NULL;
3896 if (*macro_str == TOK_TWOSHARPS)
3897 break;
3900 /* we saw '##', so we need more processing to handle it */
3901 cstr_new(&cstr);
3902 tok_str_new(&macro_str1);
3903 tok = t;
3904 tokc = cval;
3906 /* add all tokens seen so far */
3907 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
3908 TOK_GET(t, ptr, cval);
3909 tok_str_add2(&macro_str1, t, &cval);
3911 saved_macro_ptr = macro_ptr;
3912 /* XXX: get rid of the use of macro_ptr here */
3913 macro_ptr = (int *)macro_str;
3914 for(;;) {
3915 while (*macro_ptr == TOK_TWOSHARPS) {
3916 macro_ptr++;
3917 macro_ptr1 = macro_ptr;
3918 t = *macro_ptr;
3919 if (t) {
3920 TOK_GET(t, macro_ptr, cval);
3921 /* We concatenate the two tokens if we have an
3922 identifier or a preprocessing number */
3923 cstr_reset(&cstr);
3924 p1 = get_tok_str(tok, &tokc);
3925 cstr_cat(&cstr, p1);
3926 p2 = get_tok_str(t, &cval);
3927 cstr_cat(&cstr, p2);
3928 cstr_ccat(&cstr, '\0');
3930 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3931 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3932 if (tok == TOK_PPNUM) {
3933 /* if number, then create a number token */
3934 /* NOTE: no need to allocate because
3935 tok_str_add2() does it */
3936 tokc.cstr = &cstr;
3937 } else {
3938 /* if identifier, we must do a test to
3939 validate we have a correct identifier */
3940 if (t == TOK_PPNUM) {
3941 const char *p;
3942 int c;
3944 p = p2;
3945 for(;;) {
3946 c = *p;
3947 if (c == '\0')
3948 break;
3949 p++;
3950 if (!isnum(c) && !isid(c))
3951 goto error_pasting;
3954 ts = tok_alloc(cstr.data, strlen(cstr.data));
3955 tok = ts->tok; /* modify current token */
3957 } else {
3958 const char *str = cstr.data;
3959 const unsigned char *q;
3961 /* we look for a valid token */
3962 /* XXX: do more extensive checks */
3963 if (!strcmp(str, ">>=")) {
3964 tok = TOK_A_SAR;
3965 } else if (!strcmp(str, "<<=")) {
3966 tok = TOK_A_SHL;
3967 } else if (strlen(str) == 2) {
3968 /* search in two bytes table */
3969 q = tok_two_chars;
3970 for(;;) {
3971 if (!*q)
3972 goto error_pasting;
3973 if (q[0] == str[0] && q[1] == str[1])
3974 break;
3975 q += 3;
3977 tok = q[2];
3978 } else {
3979 error_pasting:
3980 /* NOTE: because get_tok_str use a static buffer,
3981 we must save it */
3982 cstr_reset(&cstr);
3983 p1 = get_tok_str(tok, &tokc);
3984 cstr_cat(&cstr, p1);
3985 cstr_ccat(&cstr, '\0');
3986 p2 = get_tok_str(t, &cval);
3987 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
3988 /* cannot merge tokens: just add them separately */
3989 tok_str_add2(&macro_str1, tok, &tokc);
3990 /* XXX: free associated memory ? */
3991 tok = t;
3992 tokc = cval;
3997 tok_str_add2(&macro_str1, tok, &tokc);
3998 next_nomacro();
3999 if (tok == 0)
4000 break;
4002 macro_ptr = (int *)saved_macro_ptr;
4003 cstr_free(&cstr);
4004 tok_str_add(&macro_str1, 0);
4005 return macro_str1.str;
4009 /* do macro substitution of macro_str and add result to
4010 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4011 inside to avoid recursing. */
4012 static void macro_subst(TokenString *tok_str,
4013 Sym **nested_list, const int *macro_str)
4015 Sym *s;
4016 int *saved_macro_ptr, *macro_str1;
4017 const int *ptr;
4018 int t, ret;
4019 CValue cval;
4021 /* first scan for '##' operator handling */
4022 ptr = macro_str;
4023 macro_str1 = macro_twosharps(ptr);
4024 if (macro_str1)
4025 ptr = macro_str1;
4026 while (1) {
4027 /* NOTE: ptr == NULL can only happen if tokens are read from
4028 file stream due to a macro function call */
4029 if (ptr == NULL)
4030 break;
4031 TOK_GET(t, ptr, cval);
4032 if (t == 0)
4033 break;
4034 s = define_find(t);
4035 if (s != NULL) {
4036 /* if nested substitution, do nothing */
4037 if (sym_find2(*nested_list, t))
4038 goto no_subst;
4039 saved_macro_ptr = macro_ptr;
4040 macro_ptr = (int *)ptr;
4041 tok = t;
4042 ret = macro_subst_tok(tok_str, nested_list, s);
4043 ptr = (int *)macro_ptr;
4044 macro_ptr = saved_macro_ptr;
4045 if (ret != 0)
4046 goto no_subst;
4047 } else {
4048 no_subst:
4049 tok_str_add2(tok_str, t, &cval);
4052 if (macro_str1)
4053 tok_str_free(macro_str1);
4056 /* return next token with macro substitution */
4057 static void next(void)
4059 Sym *nested_list, *s;
4060 TokenString str;
4062 redo:
4063 next_nomacro();
4064 if (!macro_ptr) {
4065 /* if not reading from macro substituted string, then try
4066 to substitute macros */
4067 if (tok >= TOK_IDENT &&
4068 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4069 s = define_find(tok);
4070 if (s) {
4071 /* we have a macro: we try to substitute */
4072 tok_str_new(&str);
4073 nested_list = NULL;
4074 if (macro_subst_tok(&str, &nested_list, s) == 0) {
4075 /* substitution done, NOTE: maybe empty */
4076 tok_str_add(&str, 0);
4077 macro_ptr = str.str;
4078 macro_ptr_allocated = str.str;
4079 goto redo;
4083 } else {
4084 if (tok == 0) {
4085 /* end of macro or end of unget buffer */
4086 if (unget_buffer_enabled) {
4087 macro_ptr = unget_saved_macro_ptr;
4088 unget_buffer_enabled = 0;
4089 } else {
4090 /* end of macro string: free it */
4091 tok_str_free(macro_ptr_allocated);
4092 macro_ptr = NULL;
4094 goto redo;
4098 /* convert preprocessor tokens into C tokens */
4099 if (tok == TOK_PPNUM &&
4100 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4101 parse_number((char *)tokc.cstr->data);
4105 /* push back current token and set current token to 'last_tok'. Only
4106 identifier case handled for labels. */
4107 static inline void unget_tok(int last_tok)
4109 int i, n;
4110 int *q;
4111 unget_saved_macro_ptr = macro_ptr;
4112 unget_buffer_enabled = 1;
4113 q = unget_saved_buffer;
4114 macro_ptr = q;
4115 *q++ = tok;
4116 n = tok_ext_size(tok) - 1;
4117 for(i=0;i<n;i++)
4118 *q++ = tokc.tab[i];
4119 *q = 0; /* end of token string */
4120 tok = last_tok;
4124 void swap(int *p, int *q)
4126 int t;
4127 t = *p;
4128 *p = *q;
4129 *q = t;
4132 void vsetc(CType *type, int r, CValue *vc)
4134 int v;
4136 if (vtop >= vstack + VSTACK_SIZE)
4137 error("memory full");
4138 /* cannot let cpu flags if other instruction are generated. Also
4139 avoid leaving VT_JMP anywhere except on the top of the stack
4140 because it would complicate the code generator. */
4141 if (vtop >= vstack) {
4142 v = vtop->r & VT_VALMASK;
4143 if (v == VT_CMP || (v & ~1) == VT_JMP)
4144 gv(RC_INT);
4146 vtop++;
4147 vtop->type = *type;
4148 vtop->r = r;
4149 vtop->r2 = VT_CONST;
4150 vtop->c = *vc;
4153 /* push integer constant */
4154 void vpushi(int v)
4156 CValue cval;
4157 cval.i = v;
4158 vsetc(&int_type, VT_CONST, &cval);
4161 /* Return a static symbol pointing to a section */
4162 static Sym *get_sym_ref(CType *type, Section *sec,
4163 unsigned long offset, unsigned long size)
4165 int v;
4166 Sym *sym;
4168 v = anon_sym++;
4169 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4170 sym->type.ref = type->ref;
4171 sym->r = VT_CONST | VT_SYM;
4172 put_extern_sym(sym, sec, offset, size);
4173 return sym;
4176 /* push a reference to a section offset by adding a dummy symbol */
4177 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4179 CValue cval;
4181 cval.ul = 0;
4182 vsetc(type, VT_CONST | VT_SYM, &cval);
4183 vtop->sym = get_sym_ref(type, sec, offset, size);
4186 /* define a new external reference to a symbol 'v' of type 'u' */
4187 static Sym *external_global_sym(int v, CType *type, int r)
4189 Sym *s;
4191 s = sym_find(v);
4192 if (!s) {
4193 /* push forward reference */
4194 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4195 s->type.ref = type->ref;
4196 s->r = r | VT_CONST | VT_SYM;
4198 return s;
4201 /* define a new external reference to a symbol 'v' of type 'u' */
4202 static Sym *external_sym(int v, CType *type, int r)
4204 Sym *s;
4206 s = sym_find(v);
4207 if (!s) {
4208 /* push forward reference */
4209 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4210 s->type.t |= VT_EXTERN;
4211 } else {
4212 if (!is_compatible_types(&s->type, type))
4213 error("incompatible types for redefinition of '%s'",
4214 get_tok_str(v, NULL));
4216 return s;
4219 /* push a reference to global symbol v */
4220 static void vpush_global_sym(CType *type, int v)
4222 Sym *sym;
4223 CValue cval;
4225 sym = external_global_sym(v, type, 0);
4226 cval.ul = 0;
4227 vsetc(type, VT_CONST | VT_SYM, &cval);
4228 vtop->sym = sym;
4231 void vset(CType *type, int r, int v)
4233 CValue cval;
4235 cval.i = v;
4236 vsetc(type, r, &cval);
4239 void vseti(int r, int v)
4241 CType type;
4242 type.t = VT_INT;
4243 vset(&type, r, v);
4246 void vswap(void)
4248 SValue tmp;
4250 tmp = vtop[0];
4251 vtop[0] = vtop[-1];
4252 vtop[-1] = tmp;
4255 void vpushv(SValue *v)
4257 if (vtop >= vstack + VSTACK_SIZE)
4258 error("memory full");
4259 vtop++;
4260 *vtop = *v;
4263 void vdup(void)
4265 vpushv(vtop);
4268 /* save r to the memory stack, and mark it as being free */
4269 void save_reg(int r)
4271 int l, saved, size, align;
4272 SValue *p, sv;
4273 CType *type;
4275 /* modify all stack values */
4276 saved = 0;
4277 l = 0;
4278 for(p=vstack;p<=vtop;p++) {
4279 if ((p->r & VT_VALMASK) == r ||
4280 (p->r2 & VT_VALMASK) == r) {
4281 /* must save value on stack if not already done */
4282 if (!saved) {
4283 /* NOTE: must reload 'r' because r might be equal to r2 */
4284 r = p->r & VT_VALMASK;
4285 /* store register in the stack */
4286 type = &p->type;
4287 if ((p->r & VT_LVAL) ||
4288 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4289 type = &int_type;
4290 size = type_size(type, &align);
4291 loc = (loc - size) & -align;
4292 sv.type.t = type->t;
4293 sv.r = VT_LOCAL | VT_LVAL;
4294 sv.c.ul = loc;
4295 store(r, &sv);
4296 #ifdef TCC_TARGET_I386
4297 /* x86 specific: need to pop fp register ST0 if saved */
4298 if (r == TREG_ST0) {
4299 o(0xd9dd); /* fstp %st(1) */
4301 #endif
4302 /* special long long case */
4303 if ((type->t & VT_BTYPE) == VT_LLONG) {
4304 sv.c.ul += 4;
4305 store(p->r2, &sv);
4307 l = loc;
4308 saved = 1;
4310 /* mark that stack entry as being saved on the stack */
4311 if (p->r & VT_LVAL) {
4312 /* also clear the bounded flag because the
4313 relocation address of the function was stored in
4314 p->c.ul */
4315 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4316 } else {
4317 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4319 p->r2 = VT_CONST;
4320 p->c.ul = l;
4325 /* find a free register of class 'rc'. If none, save one register */
4326 int get_reg(int rc)
4328 int r;
4329 SValue *p;
4331 /* find a free register */
4332 for(r=0;r<NB_REGS;r++) {
4333 if (reg_classes[r] & rc) {
4334 for(p=vstack;p<=vtop;p++) {
4335 if ((p->r & VT_VALMASK) == r ||
4336 (p->r2 & VT_VALMASK) == r)
4337 goto notfound;
4339 return r;
4341 notfound: ;
4344 /* no register left : free the first one on the stack (VERY
4345 IMPORTANT to start from the bottom to ensure that we don't
4346 spill registers used in gen_opi()) */
4347 for(p=vstack;p<=vtop;p++) {
4348 r = p->r & VT_VALMASK;
4349 if (r < VT_CONST && (reg_classes[r] & rc))
4350 goto save_found;
4351 /* also look at second register (if long long) */
4352 r = p->r2 & VT_VALMASK;
4353 if (r < VT_CONST && (reg_classes[r] & rc)) {
4354 save_found:
4355 save_reg(r);
4356 return r;
4359 /* Should never comes here */
4360 return -1;
4363 /* save registers up to (vtop - n) stack entry */
4364 void save_regs(int n)
4366 int r;
4367 SValue *p, *p1;
4368 p1 = vtop - n;
4369 for(p = vstack;p <= p1; p++) {
4370 r = p->r & VT_VALMASK;
4371 if (r < VT_CONST) {
4372 save_reg(r);
4377 /* move register 's' to 'r', and flush previous value of r to memory
4378 if needed */
4379 void move_reg(int r, int s)
4381 SValue sv;
4383 if (r != s) {
4384 save_reg(r);
4385 sv.type.t = VT_INT;
4386 sv.r = s;
4387 sv.c.ul = 0;
4388 load(r, &sv);
4392 /* get address of vtop (vtop MUST BE an lvalue) */
4393 void gaddrof(void)
4395 vtop->r &= ~VT_LVAL;
4396 /* tricky: if saved lvalue, then we can go back to lvalue */
4397 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4398 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4401 #ifdef CONFIG_TCC_BCHECK
4402 /* generate lvalue bound code */
4403 void gbound(void)
4405 int lval_type;
4406 CType type1;
4408 vtop->r &= ~VT_MUSTBOUND;
4409 /* if lvalue, then use checking code before dereferencing */
4410 if (vtop->r & VT_LVAL) {
4411 /* if not VT_BOUNDED value, then make one */
4412 if (!(vtop->r & VT_BOUNDED)) {
4413 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4414 /* must save type because we must set it to int to get pointer */
4415 type1 = vtop->type;
4416 vtop->type.t = VT_INT;
4417 gaddrof();
4418 vpushi(0);
4419 gen_bounded_ptr_add();
4420 vtop->r |= lval_type;
4421 vtop->type = type1;
4423 /* then check for dereferencing */
4424 gen_bounded_ptr_deref();
4427 #endif
4429 /* store vtop a register belonging to class 'rc'. lvalues are
4430 converted to values. Cannot be used if cannot be converted to
4431 register value (such as structures). */
4432 int gv(int rc)
4434 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4435 unsigned long long ll;
4437 /* NOTE: get_reg can modify vstack[] */
4438 if (vtop->type.t & VT_BITFIELD) {
4439 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4440 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4441 /* remove bit field info to avoid loops */
4442 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4443 /* generate shifts */
4444 vpushi(32 - (bit_pos + bit_size));
4445 gen_op(TOK_SHL);
4446 vpushi(32 - bit_size);
4447 /* NOTE: transformed to SHR if unsigned */
4448 gen_op(TOK_SAR);
4449 r = gv(rc);
4450 } else {
4451 if (is_float(vtop->type.t) &&
4452 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4453 Sym *sym;
4454 int *ptr;
4455 unsigned long offset;
4457 /* XXX: unify with initializers handling ? */
4458 /* CPUs usually cannot use float constants, so we store them
4459 generically in data segment */
4460 size = type_size(&vtop->type, &align);
4461 offset = (data_section->data_offset + align - 1) & -align;
4462 data_section->data_offset = offset;
4463 /* XXX: not portable yet */
4464 ptr = section_ptr_add(data_section, size);
4465 size = size >> 2;
4466 for(i=0;i<size;i++)
4467 ptr[i] = vtop->c.tab[i];
4468 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4469 vtop->r |= VT_LVAL | VT_SYM;
4470 vtop->sym = sym;
4471 vtop->c.ul = 0;
4473 #ifdef CONFIG_TCC_BCHECK
4474 if (vtop->r & VT_MUSTBOUND)
4475 gbound();
4476 #endif
4478 r = vtop->r & VT_VALMASK;
4479 /* need to reload if:
4480 - constant
4481 - lvalue (need to dereference pointer)
4482 - already a register, but not in the right class */
4483 if (r >= VT_CONST ||
4484 (vtop->r & VT_LVAL) ||
4485 !(reg_classes[r] & rc) ||
4486 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4487 !(reg_classes[vtop->r2] & rc))) {
4488 r = get_reg(rc);
4489 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4490 /* two register type load : expand to two words
4491 temporarily */
4492 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4493 /* load constant */
4494 ll = vtop->c.ull;
4495 vtop->c.ui = ll; /* first word */
4496 load(r, vtop);
4497 vtop->r = r; /* save register value */
4498 vpushi(ll >> 32); /* second word */
4499 } else if (r >= VT_CONST ||
4500 (vtop->r & VT_LVAL)) {
4501 /* load from memory */
4502 load(r, vtop);
4503 vdup();
4504 vtop[-1].r = r; /* save register value */
4505 /* increment pointer to get second word */
4506 vtop->type.t = VT_INT;
4507 gaddrof();
4508 vpushi(4);
4509 gen_op('+');
4510 vtop->r |= VT_LVAL;
4511 } else {
4512 /* move registers */
4513 load(r, vtop);
4514 vdup();
4515 vtop[-1].r = r; /* save register value */
4516 vtop->r = vtop[-1].r2;
4518 /* allocate second register */
4519 rc2 = RC_INT;
4520 if (rc == RC_IRET)
4521 rc2 = RC_LRET;
4522 r2 = get_reg(rc2);
4523 load(r2, vtop);
4524 vpop();
4525 /* write second register */
4526 vtop->r2 = r2;
4527 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4528 int t1, t;
4529 /* lvalue of scalar type : need to use lvalue type
4530 because of possible cast */
4531 t = vtop->type.t;
4532 t1 = t;
4533 /* compute memory access type */
4534 if (vtop->r & VT_LVAL_BYTE)
4535 t = VT_BYTE;
4536 else if (vtop->r & VT_LVAL_SHORT)
4537 t = VT_SHORT;
4538 if (vtop->r & VT_LVAL_UNSIGNED)
4539 t |= VT_UNSIGNED;
4540 vtop->type.t = t;
4541 load(r, vtop);
4542 /* restore wanted type */
4543 vtop->type.t = t1;
4544 } else {
4545 /* one register type load */
4546 load(r, vtop);
4549 vtop->r = r;
4551 return r;
4554 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4555 void gv2(int rc1, int rc2)
4557 int v;
4559 /* generate more generic register first. But VT_JMP or VT_CMP
4560 values must be generated first in all cases to avoid possible
4561 reload errors */
4562 v = vtop[0].r & VT_VALMASK;
4563 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4564 vswap();
4565 gv(rc1);
4566 vswap();
4567 gv(rc2);
4568 /* test if reload is needed for first register */
4569 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4570 vswap();
4571 gv(rc1);
4572 vswap();
4574 } else {
4575 gv(rc2);
4576 vswap();
4577 gv(rc1);
4578 vswap();
4579 /* test if reload is needed for first register */
4580 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4581 gv(rc2);
4586 /* expand long long on stack in two int registers */
4587 void lexpand(void)
4589 int u;
4591 u = vtop->type.t & VT_UNSIGNED;
4592 gv(RC_INT);
4593 vdup();
4594 vtop[0].r = vtop[-1].r2;
4595 vtop[0].r2 = VT_CONST;
4596 vtop[-1].r2 = VT_CONST;
4597 vtop[0].type.t = VT_INT | u;
4598 vtop[-1].type.t = VT_INT | u;
4601 /* build a long long from two ints */
4602 void lbuild(int t)
4604 gv2(RC_INT, RC_INT);
4605 vtop[-1].r2 = vtop[0].r;
4606 vtop[-1].type.t = t;
4607 vpop();
4610 /* rotate n first stack elements to the bottom
4611 I1 ... In -> I2 ... In I1 [top is right]
4613 void vrotb(int n)
4615 int i;
4616 SValue tmp;
4618 tmp = vtop[-n + 1];
4619 for(i=-n+1;i!=0;i++)
4620 vtop[i] = vtop[i+1];
4621 vtop[0] = tmp;
4624 /* rotate n first stack elements to the top
4625 I1 ... In -> In I1 ... I(n-1) [top is right]
4627 void vrott(int n)
4629 int i;
4630 SValue tmp;
4632 tmp = vtop[0];
4633 for(i = 0;i < n - 1; i++)
4634 vtop[-i] = vtop[-i - 1];
4635 vtop[-n + 1] = tmp;
4638 /* pop stack value */
4639 void vpop(void)
4641 int v;
4642 v = vtop->r & VT_VALMASK;
4643 #ifdef TCC_TARGET_I386
4644 /* for x86, we need to pop the FP stack */
4645 if (v == TREG_ST0 && !nocode_wanted) {
4646 o(0xd9dd); /* fstp %st(1) */
4647 } else
4648 #endif
4649 if (v == VT_JMP || v == VT_JMPI) {
4650 /* need to put correct jump if && or || without test */
4651 gsym(vtop->c.ul);
4653 vtop--;
4656 /* convert stack entry to register and duplicate its value in another
4657 register */
4658 void gv_dup(void)
4660 int rc, t, r, r1;
4661 SValue sv;
4663 t = vtop->type.t;
4664 if ((t & VT_BTYPE) == VT_LLONG) {
4665 lexpand();
4666 gv_dup();
4667 vswap();
4668 vrotb(3);
4669 gv_dup();
4670 vrotb(4);
4671 /* stack: H L L1 H1 */
4672 lbuild(t);
4673 vrotb(3);
4674 vrotb(3);
4675 vswap();
4676 lbuild(t);
4677 vswap();
4678 } else {
4679 /* duplicate value */
4680 rc = RC_INT;
4681 sv.type.t = VT_INT;
4682 if (is_float(t)) {
4683 rc = RC_FLOAT;
4684 sv.type.t = t;
4686 r = gv(rc);
4687 r1 = get_reg(rc);
4688 sv.r = r;
4689 sv.c.ul = 0;
4690 load(r1, &sv); /* move r to r1 */
4691 vdup();
4692 /* duplicates value */
4693 vtop->r = r1;
4697 /* generate CPU independent (unsigned) long long operations */
4698 void gen_opl(int op)
4700 int t, a, b, op1, c, i;
4701 int func;
4702 SValue tmp;
4704 switch(op) {
4705 case '/':
4706 case TOK_PDIV:
4707 func = TOK___divdi3;
4708 goto gen_func;
4709 case TOK_UDIV:
4710 func = TOK___udivdi3;
4711 goto gen_func;
4712 case '%':
4713 func = TOK___moddi3;
4714 goto gen_func;
4715 case TOK_UMOD:
4716 func = TOK___umoddi3;
4717 gen_func:
4718 /* call generic long long function */
4719 vpush_global_sym(&func_old_type, func);
4720 vrott(3);
4721 gfunc_call(2);
4722 vpushi(0);
4723 vtop->r = REG_IRET;
4724 vtop->r2 = REG_LRET;
4725 break;
4726 case '^':
4727 case '&':
4728 case '|':
4729 case '*':
4730 case '+':
4731 case '-':
4732 t = vtop->type.t;
4733 vswap();
4734 lexpand();
4735 vrotb(3);
4736 lexpand();
4737 /* stack: L1 H1 L2 H2 */
4738 tmp = vtop[0];
4739 vtop[0] = vtop[-3];
4740 vtop[-3] = tmp;
4741 tmp = vtop[-2];
4742 vtop[-2] = vtop[-3];
4743 vtop[-3] = tmp;
4744 vswap();
4745 /* stack: H1 H2 L1 L2 */
4746 if (op == '*') {
4747 vpushv(vtop - 1);
4748 vpushv(vtop - 1);
4749 gen_op(TOK_UMULL);
4750 lexpand();
4751 /* stack: H1 H2 L1 L2 ML MH */
4752 for(i=0;i<4;i++)
4753 vrotb(6);
4754 /* stack: ML MH H1 H2 L1 L2 */
4755 tmp = vtop[0];
4756 vtop[0] = vtop[-2];
4757 vtop[-2] = tmp;
4758 /* stack: ML MH H1 L2 H2 L1 */
4759 gen_op('*');
4760 vrotb(3);
4761 vrotb(3);
4762 gen_op('*');
4763 /* stack: ML MH M1 M2 */
4764 gen_op('+');
4765 gen_op('+');
4766 } else if (op == '+' || op == '-') {
4767 /* XXX: add non carry method too (for MIPS or alpha) */
4768 if (op == '+')
4769 op1 = TOK_ADDC1;
4770 else
4771 op1 = TOK_SUBC1;
4772 gen_op(op1);
4773 /* stack: H1 H2 (L1 op L2) */
4774 vrotb(3);
4775 vrotb(3);
4776 gen_op(op1 + 1); /* TOK_xxxC2 */
4777 } else {
4778 gen_op(op);
4779 /* stack: H1 H2 (L1 op L2) */
4780 vrotb(3);
4781 vrotb(3);
4782 /* stack: (L1 op L2) H1 H2 */
4783 gen_op(op);
4784 /* stack: (L1 op L2) (H1 op H2) */
4786 /* stack: L H */
4787 lbuild(t);
4788 break;
4789 case TOK_SAR:
4790 case TOK_SHR:
4791 case TOK_SHL:
4792 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4793 t = vtop[-1].type.t;
4794 vswap();
4795 lexpand();
4796 vrotb(3);
4797 /* stack: L H shift */
4798 c = (int)vtop->c.i;
4799 /* constant: simpler */
4800 /* NOTE: all comments are for SHL. the other cases are
4801 done by swaping words */
4802 vpop();
4803 if (op != TOK_SHL)
4804 vswap();
4805 if (c >= 32) {
4806 /* stack: L H */
4807 vpop();
4808 if (c > 32) {
4809 vpushi(c - 32);
4810 gen_op(op);
4812 if (op != TOK_SAR) {
4813 vpushi(0);
4814 } else {
4815 gv_dup();
4816 vpushi(31);
4817 gen_op(TOK_SAR);
4819 vswap();
4820 } else {
4821 vswap();
4822 gv_dup();
4823 /* stack: H L L */
4824 vpushi(c);
4825 gen_op(op);
4826 vswap();
4827 vpushi(32 - c);
4828 if (op == TOK_SHL)
4829 gen_op(TOK_SHR);
4830 else
4831 gen_op(TOK_SHL);
4832 vrotb(3);
4833 /* stack: L L H */
4834 vpushi(c);
4835 if (op == TOK_SHL)
4836 gen_op(TOK_SHL);
4837 else
4838 gen_op(TOK_SHR);
4839 gen_op('|');
4841 if (op != TOK_SHL)
4842 vswap();
4843 lbuild(t);
4844 } else {
4845 /* XXX: should provide a faster fallback on x86 ? */
4846 switch(op) {
4847 case TOK_SAR:
4848 func = TOK___sardi3;
4849 goto gen_func;
4850 case TOK_SHR:
4851 func = TOK___shrdi3;
4852 goto gen_func;
4853 case TOK_SHL:
4854 func = TOK___shldi3;
4855 goto gen_func;
4858 break;
4859 default:
4860 /* compare operations */
4861 t = vtop->type.t;
4862 vswap();
4863 lexpand();
4864 vrotb(3);
4865 lexpand();
4866 /* stack: L1 H1 L2 H2 */
4867 tmp = vtop[-1];
4868 vtop[-1] = vtop[-2];
4869 vtop[-2] = tmp;
4870 /* stack: L1 L2 H1 H2 */
4871 /* compare high */
4872 op1 = op;
4873 /* when values are equal, we need to compare low words. since
4874 the jump is inverted, we invert the test too. */
4875 if (op1 == TOK_LT)
4876 op1 = TOK_LE;
4877 else if (op1 == TOK_GT)
4878 op1 = TOK_GE;
4879 else if (op1 == TOK_ULT)
4880 op1 = TOK_ULE;
4881 else if (op1 == TOK_UGT)
4882 op1 = TOK_UGE;
4883 a = 0;
4884 b = 0;
4885 gen_op(op1);
4886 if (op1 != TOK_NE) {
4887 a = gtst(1, 0);
4889 if (op != TOK_EQ) {
4890 /* generate non equal test */
4891 /* XXX: NOT PORTABLE yet */
4892 if (a == 0) {
4893 b = gtst(0, 0);
4894 } else {
4895 #ifdef TCC_TARGET_I386
4896 b = psym(0x850f, 0);
4897 #else
4898 error("not implemented");
4899 #endif
4902 /* compare low. Always unsigned */
4903 op1 = op;
4904 if (op1 == TOK_LT)
4905 op1 = TOK_ULT;
4906 else if (op1 == TOK_LE)
4907 op1 = TOK_ULE;
4908 else if (op1 == TOK_GT)
4909 op1 = TOK_UGT;
4910 else if (op1 == TOK_GE)
4911 op1 = TOK_UGE;
4912 gen_op(op1);
4913 a = gtst(1, a);
4914 gsym(b);
4915 vseti(VT_JMPI, a);
4916 break;
4920 /* handle integer constant optimizations and various machine
4921 independent opt */
4922 void gen_opic(int op)
4924 int fc, c1, c2, n;
4925 SValue *v1, *v2;
4927 v1 = vtop - 1;
4928 v2 = vtop;
4929 /* currently, we cannot do computations with forward symbols */
4930 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4931 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4932 if (c1 && c2) {
4933 fc = v2->c.i;
4934 switch(op) {
4935 case '+': v1->c.i += fc; break;
4936 case '-': v1->c.i -= fc; break;
4937 case '&': v1->c.i &= fc; break;
4938 case '^': v1->c.i ^= fc; break;
4939 case '|': v1->c.i |= fc; break;
4940 case '*': v1->c.i *= fc; break;
4942 case TOK_PDIV:
4943 case '/':
4944 case '%':
4945 case TOK_UDIV:
4946 case TOK_UMOD:
4947 /* if division by zero, generate explicit division */
4948 if (fc == 0) {
4949 if (const_wanted)
4950 error("division by zero in constant");
4951 goto general_case;
4953 switch(op) {
4954 default: v1->c.i /= fc; break;
4955 case '%': v1->c.i %= fc; break;
4956 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
4957 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
4959 break;
4960 case TOK_SHL: v1->c.i <<= fc; break;
4961 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
4962 case TOK_SAR: v1->c.i >>= fc; break;
4963 /* tests */
4964 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
4965 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
4966 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
4967 case TOK_NE: v1->c.i = v1->c.i != fc; break;
4968 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
4969 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
4970 case TOK_LT: v1->c.i = v1->c.i < fc; break;
4971 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
4972 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
4973 case TOK_GT: v1->c.i = v1->c.i > fc; break;
4974 /* logical */
4975 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
4976 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
4977 default:
4978 goto general_case;
4980 vtop--;
4981 } else {
4982 /* if commutative ops, put c2 as constant */
4983 if (c1 && (op == '+' || op == '&' || op == '^' ||
4984 op == '|' || op == '*')) {
4985 vswap();
4986 swap(&c1, &c2);
4988 fc = vtop->c.i;
4989 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
4990 op == TOK_PDIV) &&
4991 fc == 1) ||
4992 ((op == '+' || op == '-' || op == '|' || op == '^' ||
4993 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
4994 fc == 0) ||
4995 (op == '&' &&
4996 fc == -1))) {
4997 /* nothing to do */
4998 vtop--;
4999 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5000 /* try to use shifts instead of muls or divs */
5001 if (fc > 0 && (fc & (fc - 1)) == 0) {
5002 n = -1;
5003 while (fc) {
5004 fc >>= 1;
5005 n++;
5007 vtop->c.i = n;
5008 if (op == '*')
5009 op = TOK_SHL;
5010 else if (op == TOK_PDIV)
5011 op = TOK_SAR;
5012 else
5013 op = TOK_SHR;
5015 goto general_case;
5016 } else if (c2 && (op == '+' || op == '-') &&
5017 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5018 (VT_CONST | VT_SYM)) {
5019 /* symbol + constant case */
5020 if (op == '-')
5021 fc = -fc;
5022 vtop--;
5023 vtop->c.i += fc;
5024 } else {
5025 general_case:
5026 if (!nocode_wanted) {
5027 /* call low level op generator */
5028 gen_opi(op);
5029 } else {
5030 vtop--;
5036 /* generate a floating point operation with constant propagation */
5037 void gen_opif(int op)
5039 int c1, c2;
5040 SValue *v1, *v2;
5041 long double f1, f2;
5043 v1 = vtop - 1;
5044 v2 = vtop;
5045 /* currently, we cannot do computations with forward symbols */
5046 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5047 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5048 if (c1 && c2) {
5049 if (v1->type.t == VT_FLOAT) {
5050 f1 = v1->c.f;
5051 f2 = v2->c.f;
5052 } else if (v1->type.t == VT_DOUBLE) {
5053 f1 = v1->c.d;
5054 f2 = v2->c.d;
5055 } else {
5056 f1 = v1->c.ld;
5057 f2 = v2->c.ld;
5060 /* NOTE: we only do constant propagation if finite number (not
5061 NaN or infinity) (ANSI spec) */
5062 if (!ieee_finite(f1) || !ieee_finite(f2))
5063 goto general_case;
5065 switch(op) {
5066 case '+': f1 += f2; break;
5067 case '-': f1 -= f2; break;
5068 case '*': f1 *= f2; break;
5069 case '/':
5070 if (f2 == 0.0) {
5071 if (const_wanted)
5072 error("division by zero in constant");
5073 goto general_case;
5075 f1 /= f2;
5076 break;
5077 /* XXX: also handles tests ? */
5078 default:
5079 goto general_case;
5081 /* XXX: overflow test ? */
5082 if (v1->type.t == VT_FLOAT) {
5083 v1->c.f = f1;
5084 } else if (v1->type.t == VT_DOUBLE) {
5085 v1->c.d = f1;
5086 } else {
5087 v1->c.ld = f1;
5089 vtop--;
5090 } else {
5091 general_case:
5092 if (!nocode_wanted) {
5093 gen_opf(op);
5094 } else {
5095 vtop--;
5100 static int pointed_size(CType *type)
5102 int align;
5103 return type_size(pointed_type(type), &align);
5106 static inline int is_null_pointer(SValue *p)
5108 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5109 return 0;
5110 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5111 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5114 static inline int is_integer_btype(int bt)
5116 return (bt == VT_BYTE || bt == VT_SHORT ||
5117 bt == VT_INT || bt == VT_LLONG);
5120 /* check types for comparison or substraction of pointers */
5121 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5123 CType *type1, *type2, tmp_type1, tmp_type2;
5124 int bt1, bt2;
5126 /* null pointers are accepted for all comparisons as gcc */
5127 if (is_null_pointer(p1) || is_null_pointer(p2))
5128 return;
5129 type1 = &p1->type;
5130 type2 = &p2->type;
5131 bt1 = type1->t & VT_BTYPE;
5132 bt2 = type2->t & VT_BTYPE;
5133 /* accept comparison between pointer and integer with a warning */
5134 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5135 warning("comparison between pointer and integer");
5136 return;
5139 /* both must be pointers or implicit function pointers */
5140 if (bt1 == VT_PTR) {
5141 type1 = pointed_type(type1);
5142 } else if (bt1 != VT_FUNC)
5143 goto invalid_operands;
5145 if (bt2 == VT_PTR) {
5146 type2 = pointed_type(type2);
5147 } else if (bt2 != VT_FUNC) {
5148 invalid_operands:
5149 error("invalid operands to binary %s", get_tok_str(op, NULL));
5151 if ((type1->t & VT_BTYPE) == VT_VOID ||
5152 (type2->t & VT_BTYPE) == VT_VOID)
5153 return;
5154 tmp_type1 = *type1;
5155 tmp_type2 = *type2;
5156 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5157 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5158 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5159 /* gcc-like error if '-' is used */
5160 if (op == '-')
5161 goto invalid_operands;
5162 else
5163 warning("comparison of distinct pointer types lacks a cast");
5167 /* generic gen_op: handles types problems */
5168 void gen_op(int op)
5170 int u, t1, t2, bt1, bt2, t;
5171 CType type1;
5173 t1 = vtop[-1].type.t;
5174 t2 = vtop[0].type.t;
5175 bt1 = t1 & VT_BTYPE;
5176 bt2 = t2 & VT_BTYPE;
5178 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5179 /* at least one operand is a pointer */
5180 /* relationnal op: must be both pointers */
5181 if (op >= TOK_ULT && op <= TOK_GT) {
5182 check_comparison_pointer_types(vtop - 1, vtop, op);
5183 /* pointers are handled are unsigned */
5184 t = VT_INT | VT_UNSIGNED;
5185 goto std_op;
5187 /* if both pointers, then it must be the '-' op */
5188 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5189 if (op != '-')
5190 error("cannot use pointers here");
5191 check_comparison_pointer_types(vtop - 1, vtop, op);
5192 /* XXX: check that types are compatible */
5193 u = pointed_size(&vtop[-1].type);
5194 gen_opic(op);
5195 /* set to integer type */
5196 vtop->type.t = VT_INT;
5197 vpushi(u);
5198 gen_op(TOK_PDIV);
5199 } else {
5200 /* exactly one pointer : must be '+' or '-'. */
5201 if (op != '-' && op != '+')
5202 error("cannot use pointers here");
5203 /* Put pointer as first operand */
5204 if (bt2 == VT_PTR) {
5205 vswap();
5206 swap(&t1, &t2);
5208 type1 = vtop[-1].type;
5209 /* XXX: cast to int ? (long long case) */
5210 vpushi(pointed_size(&vtop[-1].type));
5211 gen_op('*');
5212 #ifdef CONFIG_TCC_BCHECK
5213 /* if evaluating constant expression, no code should be
5214 generated, so no bound check */
5215 if (do_bounds_check && !const_wanted) {
5216 /* if bounded pointers, we generate a special code to
5217 test bounds */
5218 if (op == '-') {
5219 vpushi(0);
5220 vswap();
5221 gen_op('-');
5223 gen_bounded_ptr_add();
5224 } else
5225 #endif
5227 gen_opic(op);
5229 /* put again type if gen_opic() swaped operands */
5230 vtop->type = type1;
5232 } else if (is_float(bt1) || is_float(bt2)) {
5233 /* compute bigger type and do implicit casts */
5234 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5235 t = VT_LDOUBLE;
5236 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5237 t = VT_DOUBLE;
5238 } else {
5239 t = VT_FLOAT;
5241 /* floats can only be used for a few operations */
5242 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5243 (op < TOK_ULT || op > TOK_GT))
5244 error("invalid operands for binary operation");
5245 goto std_op;
5246 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5247 /* cast to biggest op */
5248 t = VT_LLONG;
5249 /* convert to unsigned if it does not fit in a long long */
5250 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5251 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5252 t |= VT_UNSIGNED;
5253 goto std_op;
5254 } else {
5255 /* integer operations */
5256 t = VT_INT;
5257 /* convert to unsigned if it does not fit in an integer */
5258 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5259 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5260 t |= VT_UNSIGNED;
5261 std_op:
5262 /* XXX: currently, some unsigned operations are explicit, so
5263 we modify them here */
5264 if (t & VT_UNSIGNED) {
5265 if (op == TOK_SAR)
5266 op = TOK_SHR;
5267 else if (op == '/')
5268 op = TOK_UDIV;
5269 else if (op == '%')
5270 op = TOK_UMOD;
5271 else if (op == TOK_LT)
5272 op = TOK_ULT;
5273 else if (op == TOK_GT)
5274 op = TOK_UGT;
5275 else if (op == TOK_LE)
5276 op = TOK_ULE;
5277 else if (op == TOK_GE)
5278 op = TOK_UGE;
5280 vswap();
5281 type1.t = t;
5282 gen_cast(&type1);
5283 vswap();
5284 /* special case for shifts and long long: we keep the shift as
5285 an integer */
5286 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5287 type1.t = VT_INT;
5288 gen_cast(&type1);
5289 if (is_float(t))
5290 gen_opif(op);
5291 else if ((t & VT_BTYPE) == VT_LLONG)
5292 gen_opl(op);
5293 else
5294 gen_opic(op);
5295 if (op >= TOK_ULT && op <= TOK_GT) {
5296 /* relationnal op: the result is an int */
5297 vtop->type.t = VT_INT;
5298 } else {
5299 vtop->type.t = t;
5304 /* generic itof for unsigned long long case */
5305 void gen_cvt_itof1(int t)
5307 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5308 (VT_LLONG | VT_UNSIGNED)) {
5310 if (t == VT_FLOAT)
5311 vpush_global_sym(&func_old_type, TOK___ulltof);
5312 else if (t == VT_DOUBLE)
5313 vpush_global_sym(&func_old_type, TOK___ulltod);
5314 else
5315 vpush_global_sym(&func_old_type, TOK___ulltold);
5316 vrott(2);
5317 gfunc_call(1);
5318 vpushi(0);
5319 vtop->r = REG_FRET;
5320 } else {
5321 gen_cvt_itof(t);
5325 /* generic ftoi for unsigned long long case */
5326 void gen_cvt_ftoi1(int t)
5328 int st;
5330 if (t == (VT_LLONG | VT_UNSIGNED)) {
5331 /* not handled natively */
5332 st = vtop->type.t & VT_BTYPE;
5333 if (st == VT_FLOAT)
5334 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5335 else if (st == VT_DOUBLE)
5336 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5337 else
5338 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5339 vrott(2);
5340 gfunc_call(1);
5341 vpushi(0);
5342 vtop->r = REG_IRET;
5343 vtop->r2 = REG_LRET;
5344 } else {
5345 gen_cvt_ftoi(t);
5349 /* force char or short cast */
5350 void force_charshort_cast(int t)
5352 int bits, dbt;
5353 dbt = t & VT_BTYPE;
5354 /* XXX: add optimization if lvalue : just change type and offset */
5355 if (dbt == VT_BYTE)
5356 bits = 8;
5357 else
5358 bits = 16;
5359 if (t & VT_UNSIGNED) {
5360 vpushi((1 << bits) - 1);
5361 gen_op('&');
5362 } else {
5363 bits = 32 - bits;
5364 vpushi(bits);
5365 gen_op(TOK_SHL);
5366 vpushi(bits);
5367 gen_op(TOK_SAR);
5371 /* cast 'vtop' to 'type' */
5372 static void gen_cast(CType *type)
5374 int sbt, dbt, sf, df, c;
5376 /* special delayed cast for char/short */
5377 /* XXX: in some cases (multiple cascaded casts), it may still
5378 be incorrect */
5379 if (vtop->r & VT_MUSTCAST) {
5380 vtop->r &= ~VT_MUSTCAST;
5381 force_charshort_cast(vtop->type.t);
5384 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5385 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5387 if (sbt != dbt && !nocode_wanted) {
5388 sf = is_float(sbt);
5389 df = is_float(dbt);
5390 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5391 if (sf && df) {
5392 /* convert from fp to fp */
5393 if (c) {
5394 /* constant case: we can do it now */
5395 /* XXX: in ISOC, cannot do it if error in convert */
5396 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5397 vtop->c.f = (float)vtop->c.d;
5398 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5399 vtop->c.f = (float)vtop->c.ld;
5400 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5401 vtop->c.d = (double)vtop->c.f;
5402 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5403 vtop->c.d = (double)vtop->c.ld;
5404 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5405 vtop->c.ld = (long double)vtop->c.f;
5406 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5407 vtop->c.ld = (long double)vtop->c.d;
5408 } else {
5409 /* non constant case: generate code */
5410 gen_cvt_ftof(dbt);
5412 } else if (df) {
5413 /* convert int to fp */
5414 if (c) {
5415 switch(sbt) {
5416 case VT_LLONG | VT_UNSIGNED:
5417 case VT_LLONG:
5418 /* XXX: add const cases for long long */
5419 goto do_itof;
5420 case VT_INT | VT_UNSIGNED:
5421 switch(dbt) {
5422 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5423 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5424 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5426 break;
5427 default:
5428 switch(dbt) {
5429 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5430 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5431 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5433 break;
5435 } else {
5436 do_itof:
5437 gen_cvt_itof1(dbt);
5439 } else if (sf) {
5440 /* convert fp to int */
5441 /* we handle char/short/etc... with generic code */
5442 if (dbt != (VT_INT | VT_UNSIGNED) &&
5443 dbt != (VT_LLONG | VT_UNSIGNED) &&
5444 dbt != VT_LLONG)
5445 dbt = VT_INT;
5446 if (c) {
5447 switch(dbt) {
5448 case VT_LLONG | VT_UNSIGNED:
5449 case VT_LLONG:
5450 /* XXX: add const cases for long long */
5451 goto do_ftoi;
5452 case VT_INT | VT_UNSIGNED:
5453 switch(sbt) {
5454 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5455 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5456 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5458 break;
5459 default:
5460 /* int case */
5461 switch(sbt) {
5462 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5463 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5464 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5466 break;
5468 } else {
5469 do_ftoi:
5470 gen_cvt_ftoi1(dbt);
5472 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5473 /* additional cast for char/short/bool... */
5474 vtop->type.t = dbt;
5475 gen_cast(type);
5477 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5478 if ((sbt & VT_BTYPE) != VT_LLONG) {
5479 /* scalar to long long */
5480 if (c) {
5481 if (sbt == (VT_INT | VT_UNSIGNED))
5482 vtop->c.ll = vtop->c.ui;
5483 else
5484 vtop->c.ll = vtop->c.i;
5485 } else {
5486 /* machine independent conversion */
5487 gv(RC_INT);
5488 /* generate high word */
5489 if (sbt == (VT_INT | VT_UNSIGNED)) {
5490 vpushi(0);
5491 gv(RC_INT);
5492 } else {
5493 gv_dup();
5494 vpushi(31);
5495 gen_op(TOK_SAR);
5497 /* patch second register */
5498 vtop[-1].r2 = vtop->r;
5499 vpop();
5502 } else if (dbt == VT_BOOL) {
5503 /* scalar to bool */
5504 vpushi(0);
5505 gen_op(TOK_NE);
5506 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5507 (dbt & VT_BTYPE) == VT_SHORT) {
5508 force_charshort_cast(dbt);
5509 } else if ((dbt & VT_BTYPE) == VT_INT) {
5510 /* scalar to int */
5511 if (sbt == VT_LLONG) {
5512 /* from long long: just take low order word */
5513 lexpand();
5514 vpop();
5516 /* if lvalue and single word type, nothing to do because
5517 the lvalue already contains the real type size (see
5518 VT_LVAL_xxx constants) */
5521 vtop->type = *type;
5524 /* return type size. Put alignment at 'a' */
5525 static int type_size(CType *type, int *a)
5527 Sym *s;
5528 int bt;
5530 bt = type->t & VT_BTYPE;
5531 if (bt == VT_STRUCT) {
5532 /* struct/union */
5533 s = type->ref;
5534 *a = s->r;
5535 return s->c;
5536 } else if (bt == VT_PTR) {
5537 if (type->t & VT_ARRAY) {
5538 s = type->ref;
5539 return type_size(&s->type, a) * s->c;
5540 } else {
5541 *a = PTR_SIZE;
5542 return PTR_SIZE;
5544 } else if (bt == VT_LDOUBLE) {
5545 *a = LDOUBLE_ALIGN;
5546 return LDOUBLE_SIZE;
5547 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5548 *a = 4; /* XXX: i386 specific */
5549 return 8;
5550 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5551 *a = 4;
5552 return 4;
5553 } else if (bt == VT_SHORT) {
5554 *a = 2;
5555 return 2;
5556 } else {
5557 /* char, void, function, _Bool */
5558 *a = 1;
5559 return 1;
5563 /* return the pointed type of t */
5564 static inline CType *pointed_type(CType *type)
5566 return &type->ref->type;
5569 /* modify type so that its it is a pointer to type. */
5570 static void mk_pointer(CType *type)
5572 Sym *s;
5573 s = sym_push(SYM_FIELD, type, 0, -1);
5574 type->t = VT_PTR | (type->t & ~VT_TYPE);
5575 type->ref = s;
5578 /* compare function types. OLD functions match any new functions */
5579 static int is_compatible_func(CType *type1, CType *type2)
5581 Sym *s1, *s2;
5583 s1 = type1->ref;
5584 s2 = type2->ref;
5585 if (!is_compatible_types(&s1->type, &s2->type))
5586 return 0;
5587 /* XXX: not complete */
5588 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5589 return 1;
5590 if (s1->c != s2->c)
5591 return 0;
5592 while (s1 != NULL) {
5593 if (s2 == NULL)
5594 return 0;
5595 if (!is_compatible_types(&s1->type, &s2->type))
5596 return 0;
5597 s1 = s1->next;
5598 s2 = s2->next;
5600 if (s2)
5601 return 0;
5602 return 1;
5605 /* return true if type1 and type2 are exactly the same (including
5606 qualifiers).
5608 - enums are not checked as gcc __builtin_types_compatible_p ()
5610 static int is_compatible_types(CType *type1, CType *type2)
5612 int bt1, t1, t2;
5614 t1 = type1->t & VT_TYPE;
5615 t2 = type2->t & VT_TYPE;
5616 /* XXX: bitfields ? */
5617 if (t1 != t2)
5618 return 0;
5619 /* test more complicated cases */
5620 bt1 = t1 & VT_BTYPE;
5621 if (bt1 == VT_PTR) {
5622 type1 = pointed_type(type1);
5623 type2 = pointed_type(type2);
5624 return is_compatible_types(type1, type2);
5625 } else if (bt1 == VT_STRUCT) {
5626 return (type1->ref == type2->ref);
5627 } else if (bt1 == VT_FUNC) {
5628 return is_compatible_func(type1, type2);
5629 } else {
5630 return 1;
5634 /* print a type. If 'varstr' is not NULL, then the variable is also
5635 printed in the type */
5636 /* XXX: union */
5637 /* XXX: add array and function pointers */
5638 void type_to_str(char *buf, int buf_size,
5639 CType *type, const char *varstr)
5641 int bt, v, t;
5642 Sym *s, *sa;
5643 char buf1[256];
5644 const char *tstr;
5646 t = type->t & VT_TYPE;
5647 bt = t & VT_BTYPE;
5648 buf[0] = '\0';
5649 if (t & VT_CONSTANT)
5650 pstrcat(buf, buf_size, "const ");
5651 if (t & VT_VOLATILE)
5652 pstrcat(buf, buf_size, "volatile ");
5653 if (t & VT_UNSIGNED)
5654 pstrcat(buf, buf_size, "unsigned ");
5655 switch(bt) {
5656 case VT_VOID:
5657 tstr = "void";
5658 goto add_tstr;
5659 case VT_BOOL:
5660 tstr = "_Bool";
5661 goto add_tstr;
5662 case VT_BYTE:
5663 tstr = "char";
5664 goto add_tstr;
5665 case VT_SHORT:
5666 tstr = "short";
5667 goto add_tstr;
5668 case VT_INT:
5669 tstr = "int";
5670 goto add_tstr;
5671 case VT_LONG:
5672 tstr = "long";
5673 goto add_tstr;
5674 case VT_LLONG:
5675 tstr = "long long";
5676 goto add_tstr;
5677 case VT_FLOAT:
5678 tstr = "float";
5679 goto add_tstr;
5680 case VT_DOUBLE:
5681 tstr = "double";
5682 goto add_tstr;
5683 case VT_LDOUBLE:
5684 tstr = "long double";
5685 add_tstr:
5686 pstrcat(buf, buf_size, tstr);
5687 break;
5688 case VT_ENUM:
5689 case VT_STRUCT:
5690 if (bt == VT_STRUCT)
5691 tstr = "struct ";
5692 else
5693 tstr = "enum ";
5694 pstrcat(buf, buf_size, tstr);
5695 v = type->ref->v & ~SYM_STRUCT;
5696 if (v >= SYM_FIRST_ANOM)
5697 pstrcat(buf, buf_size, "<anonymous>");
5698 else
5699 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5700 break;
5701 case VT_FUNC:
5702 s = type->ref;
5703 type_to_str(buf, buf_size, &s->type, varstr);
5704 pstrcat(buf, buf_size, "(");
5705 sa = s->next;
5706 while (sa != NULL) {
5707 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5708 pstrcat(buf, buf_size, buf1);
5709 sa = sa->next;
5710 if (sa)
5711 pstrcat(buf, buf_size, ", ");
5713 pstrcat(buf, buf_size, ")");
5714 goto no_var;
5715 case VT_PTR:
5716 s = type->ref;
5717 pstrcpy(buf1, sizeof(buf1), "*");
5718 if (varstr)
5719 pstrcat(buf1, sizeof(buf1), varstr);
5720 type_to_str(buf, buf_size, &s->type, buf1);
5721 goto no_var;
5723 if (varstr) {
5724 pstrcat(buf, buf_size, " ");
5725 pstrcat(buf, buf_size, varstr);
5727 no_var: ;
5730 /* verify type compatibility to store vtop in 'dt' type, and generate
5731 casts if needed. */
5732 static void gen_assign_cast(CType *dt)
5734 CType *st, *type1, *type2, tmp_type1, tmp_type2;
5735 char buf1[256], buf2[256];
5736 int dbt, sbt;
5738 st = &vtop->type; /* source type */
5739 dbt = dt->t & VT_BTYPE;
5740 sbt = st->t & VT_BTYPE;
5741 if (dt->t & VT_CONSTANT)
5742 warning("assignment of read-only location");
5743 switch(dbt) {
5744 case VT_PTR:
5745 /* special cases for pointers */
5746 /* '0' can also be a pointer */
5747 if (is_null_pointer(vtop))
5748 goto type_ok;
5749 /* accept implicit pointer to integer cast with warning */
5750 if (is_integer_btype(sbt)) {
5751 warning("assignment makes pointer from integer without a cast");
5752 goto type_ok;
5754 type1 = pointed_type(dt);
5755 /* a function is implicitely a function pointer */
5756 if (sbt == VT_FUNC) {
5757 if ((type1->t & VT_BTYPE) != VT_VOID &&
5758 !is_compatible_types(pointed_type(dt), st))
5759 goto error;
5760 else
5761 goto type_ok;
5763 if (sbt != VT_PTR)
5764 goto error;
5765 type2 = pointed_type(st);
5766 if ((type1->t & VT_BTYPE) == VT_VOID ||
5767 (type2->t & VT_BTYPE) == VT_VOID) {
5768 /* void * can match anything */
5769 } else {
5770 /* exact type match, except for unsigned */
5771 tmp_type1 = *type1;
5772 tmp_type2 = *type2;
5773 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5774 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5775 if (!is_compatible_types(&tmp_type1, &tmp_type2))
5776 goto error;
5778 /* check const and volatile */
5779 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
5780 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
5781 warning("assignment discards qualifiers from pointer target type");
5782 break;
5783 case VT_BYTE:
5784 case VT_SHORT:
5785 case VT_INT:
5786 case VT_LLONG:
5787 if (sbt == VT_PTR || sbt == VT_FUNC) {
5788 warning("assignment makes integer from pointer without a cast");
5790 /* XXX: more tests */
5791 break;
5792 case VT_STRUCT:
5793 if (!is_compatible_types(dt, st)) {
5794 error:
5795 type_to_str(buf1, sizeof(buf1), st, NULL);
5796 type_to_str(buf2, sizeof(buf2), dt, NULL);
5797 error("cannot cast '%s' to '%s'", buf1, buf2);
5799 break;
5801 type_ok:
5802 gen_cast(dt);
5805 /* store vtop in lvalue pushed on stack */
5806 void vstore(void)
5808 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5810 ft = vtop[-1].type.t;
5811 sbt = vtop->type.t & VT_BTYPE;
5812 dbt = ft & VT_BTYPE;
5813 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5814 (sbt == VT_INT && dbt == VT_SHORT)) {
5815 /* optimize char/short casts */
5816 delayed_cast = VT_MUSTCAST;
5817 vtop->type.t = ft & VT_TYPE;
5818 /* XXX: factorize */
5819 if (ft & VT_CONSTANT)
5820 warning("assignment of read-only location");
5821 } else {
5822 delayed_cast = 0;
5823 gen_assign_cast(&vtop[-1].type);
5826 if (sbt == VT_STRUCT) {
5827 /* if structure, only generate pointer */
5828 /* structure assignment : generate memcpy */
5829 /* XXX: optimize if small size */
5830 if (!nocode_wanted) {
5831 size = type_size(&vtop->type, &align);
5833 vpush_global_sym(&func_old_type, TOK_memcpy);
5835 /* destination */
5836 vpushv(vtop - 2);
5837 vtop->type.t = VT_INT;
5838 gaddrof();
5839 /* source */
5840 vpushv(vtop - 2);
5841 vtop->type.t = VT_INT;
5842 gaddrof();
5843 /* type size */
5844 vpushi(size);
5845 gfunc_call(3);
5847 vswap();
5848 vpop();
5849 } else {
5850 vswap();
5851 vpop();
5853 /* leave source on stack */
5854 } else if (ft & VT_BITFIELD) {
5855 /* bitfield store handling */
5856 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5857 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5858 /* remove bit field info to avoid loops */
5859 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5861 /* duplicate destination */
5862 vdup();
5863 vtop[-1] = vtop[-2];
5865 /* mask and shift source */
5866 vpushi((1 << bit_size) - 1);
5867 gen_op('&');
5868 vpushi(bit_pos);
5869 gen_op(TOK_SHL);
5870 /* load destination, mask and or with source */
5871 vswap();
5872 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5873 gen_op('&');
5874 gen_op('|');
5875 /* store result */
5876 vstore();
5877 } else {
5878 #ifdef CONFIG_TCC_BCHECK
5879 /* bound check case */
5880 if (vtop[-1].r & VT_MUSTBOUND) {
5881 vswap();
5882 gbound();
5883 vswap();
5885 #endif
5886 if (!nocode_wanted) {
5887 rc = RC_INT;
5888 if (is_float(ft))
5889 rc = RC_FLOAT;
5890 r = gv(rc); /* generate value */
5891 /* if lvalue was saved on stack, must read it */
5892 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5893 SValue sv;
5894 t = get_reg(RC_INT);
5895 sv.type.t = VT_INT;
5896 sv.r = VT_LOCAL | VT_LVAL;
5897 sv.c.ul = vtop[-1].c.ul;
5898 load(t, &sv);
5899 vtop[-1].r = t | VT_LVAL;
5901 store(r, vtop - 1);
5902 /* two word case handling : store second register at word + 4 */
5903 if ((ft & VT_BTYPE) == VT_LLONG) {
5904 vswap();
5905 /* convert to int to increment easily */
5906 vtop->type.t = VT_INT;
5907 gaddrof();
5908 vpushi(4);
5909 gen_op('+');
5910 vtop->r |= VT_LVAL;
5911 vswap();
5912 /* XXX: it works because r2 is spilled last ! */
5913 store(vtop->r2, vtop - 1);
5916 vswap();
5917 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5918 vtop->r |= delayed_cast;
5922 /* post defines POST/PRE add. c is the token ++ or -- */
5923 void inc(int post, int c)
5925 test_lvalue();
5926 vdup(); /* save lvalue */
5927 if (post) {
5928 gv_dup(); /* duplicate value */
5929 vrotb(3);
5930 vrotb(3);
5932 /* add constant */
5933 vpushi(c - TOK_MID);
5934 gen_op('+');
5935 vstore(); /* store value */
5936 if (post)
5937 vpop(); /* if post op, return saved value */
5940 /* Parse GNUC __attribute__ extension. Currently, the following
5941 extensions are recognized:
5942 - aligned(n) : set data/function alignment.
5943 - section(x) : generate data/code in this section.
5944 - unused : currently ignored, but may be used someday.
5946 static void parse_attribute(AttributeDef *ad)
5948 int t, n;
5950 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
5951 next();
5952 skip('(');
5953 skip('(');
5954 while (tok != ')') {
5955 if (tok < TOK_IDENT)
5956 expect("attribute name");
5957 t = tok;
5958 next();
5959 switch(t) {
5960 case TOK_SECTION1:
5961 case TOK_SECTION2:
5962 skip('(');
5963 if (tok != TOK_STR)
5964 expect("section name");
5965 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
5966 next();
5967 skip(')');
5968 break;
5969 case TOK_ALIGNED1:
5970 case TOK_ALIGNED2:
5971 if (tok == '(') {
5972 next();
5973 n = expr_const();
5974 if (n <= 0 || (n & (n - 1)) != 0)
5975 error("alignment must be a positive power of two");
5976 skip(')');
5977 } else {
5978 n = MAX_ALIGN;
5980 ad->aligned = n;
5981 break;
5982 case TOK_UNUSED1:
5983 case TOK_UNUSED2:
5984 /* currently, no need to handle it because tcc does not
5985 track unused objects */
5986 break;
5987 case TOK_NORETURN1:
5988 case TOK_NORETURN2:
5989 /* currently, no need to handle it because tcc does not
5990 track unused objects */
5991 break;
5992 case TOK_CDECL1:
5993 case TOK_CDECL2:
5994 case TOK_CDECL3:
5995 ad->func_call = FUNC_CDECL;
5996 break;
5997 case TOK_STDCALL1:
5998 case TOK_STDCALL2:
5999 case TOK_STDCALL3:
6000 ad->func_call = FUNC_STDCALL;
6001 break;
6002 default:
6003 if (tcc_state->warn_unsupported)
6004 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6005 /* skip parameters */
6006 /* XXX: skip parenthesis too */
6007 if (tok == '(') {
6008 next();
6009 while (tok != ')' && tok != -1)
6010 next();
6011 next();
6013 break;
6015 if (tok != ',')
6016 break;
6017 next();
6019 skip(')');
6020 skip(')');
6024 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6025 static void struct_decl(CType *type, int u)
6027 int a, v, size, align, maxalign, c, offset;
6028 int bit_size, bit_pos, bsize, bt, lbit_pos;
6029 Sym *s, *ss, **ps;
6030 AttributeDef ad;
6031 CType type1, btype;
6033 a = tok; /* save decl type */
6034 next();
6035 if (tok != '{') {
6036 v = tok;
6037 next();
6038 /* struct already defined ? return it */
6039 if (v < TOK_IDENT)
6040 expect("struct/union/enum name");
6041 s = struct_find(v);
6042 if (s) {
6043 if (s->type.t != a)
6044 error("invalid type");
6045 goto do_decl;
6047 } else {
6048 v = anon_sym++;
6050 type1.t = a;
6051 /* we put an undefined size for struct/union */
6052 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6053 s->r = 0; /* default alignment is zero as gcc */
6054 /* put struct/union/enum name in type */
6055 do_decl:
6056 type->t = u;
6057 type->ref = s;
6059 if (tok == '{') {
6060 next();
6061 if (s->c != -1)
6062 error("struct/union/enum already defined");
6063 /* cannot be empty */
6064 c = 0;
6065 /* non empty enums are not allowed */
6066 if (a == TOK_ENUM) {
6067 for(;;) {
6068 v = tok;
6069 if (v < TOK_UIDENT)
6070 expect("identifier");
6071 next();
6072 if (tok == '=') {
6073 next();
6074 c = expr_const();
6076 /* enum symbols have static storage */
6077 ss = sym_push(v, &int_type, VT_CONST, c);
6078 ss->type.t |= VT_STATIC;
6079 if (tok != ',')
6080 break;
6081 next();
6082 c++;
6083 /* NOTE: we accept a trailing comma */
6084 if (tok == '}')
6085 break;
6087 skip('}');
6088 } else {
6089 maxalign = 1;
6090 ps = &s->next;
6091 bit_pos = 0;
6092 offset = 0;
6093 while (tok != '}') {
6094 parse_btype(&btype, &ad);
6095 while (1) {
6096 bit_size = -1;
6097 v = 0;
6098 type1 = btype;
6099 if (tok != ':') {
6100 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6101 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6102 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6103 error("invalid type for '%s'",
6104 get_tok_str(v, NULL));
6106 if (tok == ':') {
6107 next();
6108 bit_size = expr_const();
6109 /* XXX: handle v = 0 case for messages */
6110 if (bit_size < 0)
6111 error("negative width in bit-field '%s'",
6112 get_tok_str(v, NULL));
6113 if (v && bit_size == 0)
6114 error("zero width for bit-field '%s'",
6115 get_tok_str(v, NULL));
6117 size = type_size(&type1, &align);
6118 lbit_pos = 0;
6119 if (bit_size >= 0) {
6120 bt = type1.t & VT_BTYPE;
6121 if (bt != VT_INT &&
6122 bt != VT_BYTE &&
6123 bt != VT_SHORT &&
6124 bt != VT_ENUM)
6125 error("bitfields must have scalar type");
6126 bsize = size * 8;
6127 if (bit_size > bsize) {
6128 error("width of '%s' exceeds its type",
6129 get_tok_str(v, NULL));
6130 } else if (bit_size == bsize) {
6131 /* no need for bit fields */
6132 bit_pos = 0;
6133 } else if (bit_size == 0) {
6134 /* XXX: what to do if only padding in a
6135 structure ? */
6136 /* zero size: means to pad */
6137 if (bit_pos > 0)
6138 bit_pos = bsize;
6139 } else {
6140 /* we do not have enough room ? */
6141 if ((bit_pos + bit_size) > bsize)
6142 bit_pos = 0;
6143 lbit_pos = bit_pos;
6144 /* XXX: handle LSB first */
6145 type1.t |= VT_BITFIELD |
6146 (bit_pos << VT_STRUCT_SHIFT) |
6147 (bit_size << (VT_STRUCT_SHIFT + 6));
6148 bit_pos += bit_size;
6150 } else {
6151 bit_pos = 0;
6153 if (v) {
6154 /* add new memory data only if starting
6155 bit field */
6156 if (lbit_pos == 0) {
6157 if (a == TOK_STRUCT) {
6158 c = (c + align - 1) & -align;
6159 offset = c;
6160 c += size;
6161 } else {
6162 offset = 0;
6163 if (size > c)
6164 c = size;
6166 if (align > maxalign)
6167 maxalign = align;
6169 #if 0
6170 printf("add field %s offset=%d",
6171 get_tok_str(v, NULL), offset);
6172 if (type1.t & VT_BITFIELD) {
6173 printf(" pos=%d size=%d",
6174 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6175 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6177 printf("\n");
6178 #endif
6179 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6180 *ps = ss;
6181 ps = &ss->next;
6183 if (tok == ';' || tok == TOK_EOF)
6184 break;
6185 skip(',');
6187 skip(';');
6189 skip('}');
6190 /* store size and alignment */
6191 s->c = (c + maxalign - 1) & -maxalign;
6192 s->r = maxalign;
6197 /* return 0 if no type declaration. otherwise, return the basic type
6198 and skip it.
6200 static int parse_btype(CType *type, AttributeDef *ad)
6202 int t, u, type_found;
6203 Sym *s;
6204 CType type1;
6206 memset(ad, 0, sizeof(AttributeDef));
6207 type_found = 0;
6208 t = 0;
6209 while(1) {
6210 switch(tok) {
6211 case TOK_EXTENSION:
6212 /* currently, we really ignore extension */
6213 next();
6214 continue;
6216 /* basic types */
6217 case TOK_CHAR:
6218 u = VT_BYTE;
6219 basic_type:
6220 next();
6221 basic_type1:
6222 if ((t & VT_BTYPE) != 0)
6223 error("too many basic types");
6224 t |= u;
6225 break;
6226 case TOK_VOID:
6227 u = VT_VOID;
6228 goto basic_type;
6229 case TOK_SHORT:
6230 u = VT_SHORT;
6231 goto basic_type;
6232 case TOK_INT:
6233 next();
6234 break;
6235 case TOK_LONG:
6236 next();
6237 if ((t & VT_BTYPE) == VT_DOUBLE) {
6238 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6239 } else if ((t & VT_BTYPE) == VT_LONG) {
6240 t = (t & ~VT_BTYPE) | VT_LLONG;
6241 } else {
6242 u = VT_LONG;
6243 goto basic_type1;
6245 break;
6246 case TOK_BOOL:
6247 u = VT_BOOL;
6248 goto basic_type;
6249 case TOK_FLOAT:
6250 u = VT_FLOAT;
6251 goto basic_type;
6252 case TOK_DOUBLE:
6253 next();
6254 if ((t & VT_BTYPE) == VT_LONG) {
6255 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6256 } else {
6257 u = VT_DOUBLE;
6258 goto basic_type1;
6260 break;
6261 case TOK_ENUM:
6262 struct_decl(&type1, VT_ENUM);
6263 basic_type2:
6264 u = type1.t;
6265 type->ref = type1.ref;
6266 goto basic_type1;
6267 case TOK_STRUCT:
6268 case TOK_UNION:
6269 struct_decl(&type1, VT_STRUCT);
6270 goto basic_type2;
6272 /* type modifiers */
6273 case TOK_CONST1:
6274 case TOK_CONST2:
6275 case TOK_CONST3:
6276 t |= VT_CONSTANT;
6277 next();
6278 break;
6279 case TOK_VOLATILE1:
6280 case TOK_VOLATILE2:
6281 case TOK_VOLATILE3:
6282 t |= VT_VOLATILE;
6283 next();
6284 break;
6285 case TOK_REGISTER:
6286 case TOK_SIGNED1:
6287 case TOK_SIGNED2:
6288 case TOK_SIGNED3:
6289 case TOK_AUTO:
6290 case TOK_RESTRICT1:
6291 case TOK_RESTRICT2:
6292 case TOK_RESTRICT3:
6293 next();
6294 break;
6295 case TOK_UNSIGNED:
6296 t |= VT_UNSIGNED;
6297 next();
6298 break;
6300 /* storage */
6301 case TOK_EXTERN:
6302 t |= VT_EXTERN;
6303 next();
6304 break;
6305 case TOK_STATIC:
6306 t |= VT_STATIC;
6307 next();
6308 break;
6309 case TOK_TYPEDEF:
6310 t |= VT_TYPEDEF;
6311 next();
6312 break;
6313 case TOK_INLINE1:
6314 case TOK_INLINE2:
6315 case TOK_INLINE3:
6316 t |= VT_INLINE;
6317 next();
6318 break;
6320 /* GNUC attribute */
6321 case TOK_ATTRIBUTE1:
6322 case TOK_ATTRIBUTE2:
6323 parse_attribute(ad);
6324 break;
6325 /* GNUC typeof */
6326 case TOK_TYPEOF1:
6327 case TOK_TYPEOF2:
6328 case TOK_TYPEOF3:
6329 next();
6330 parse_expr_type(&type1);
6331 goto basic_type2;
6332 default:
6333 s = sym_find(tok);
6334 if (!s || !(s->type.t & VT_TYPEDEF))
6335 goto the_end;
6336 t |= (s->type.t & ~VT_TYPEDEF);
6337 type->ref = s->type.ref;
6338 next();
6339 break;
6341 type_found = 1;
6343 the_end:
6344 /* long is never used as type */
6345 if ((t & VT_BTYPE) == VT_LONG)
6346 t = (t & ~VT_BTYPE) | VT_INT;
6347 type->t = t;
6348 return type_found;
6351 /* convert a function parameter type (array to pointer and function to
6352 function pointer) */
6353 static inline void convert_parameter_type(CType *pt)
6355 /* array must be transformed to pointer according to ANSI C */
6356 pt->t &= ~VT_ARRAY;
6357 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6358 mk_pointer(pt);
6362 static void post_type(CType *type, AttributeDef *ad)
6364 int n, l, t1;
6365 Sym **plast, *s, *first;
6366 AttributeDef ad1;
6367 CType pt;
6369 if (tok == '(') {
6370 /* function declaration */
6371 next();
6372 l = 0;
6373 first = NULL;
6374 plast = &first;
6375 while (tok != ')') {
6376 /* read param name and compute offset */
6377 if (l != FUNC_OLD) {
6378 if (!parse_btype(&pt, &ad1)) {
6379 if (l) {
6380 error("invalid type");
6381 } else {
6382 l = FUNC_OLD;
6383 goto old_proto;
6386 l = FUNC_NEW;
6387 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6388 break;
6389 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6390 if ((pt.t & VT_BTYPE) == VT_VOID)
6391 error("parameter declared as void");
6392 } else {
6393 old_proto:
6394 n = tok;
6395 pt.t = VT_INT;
6396 next();
6398 convert_parameter_type(&pt);
6399 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6400 *plast = s;
6401 plast = &s->next;
6402 if (tok == ',') {
6403 next();
6404 if (l == FUNC_NEW && tok == TOK_DOTS) {
6405 l = FUNC_ELLIPSIS;
6406 next();
6407 break;
6411 /* if no parameters, then old type prototype */
6412 if (l == 0)
6413 l = FUNC_OLD;
6414 skip(')');
6415 t1 = type->t & VT_STORAGE;
6416 /* NOTE: const is ignored in returned type as it has a special
6417 meaning in gcc / C++ */
6418 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6419 post_type(type, ad);
6420 /* we push a anonymous symbol which will contain the function prototype */
6421 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6422 s->next = first;
6423 type->t = t1 | VT_FUNC;
6424 type->ref = s;
6425 } else if (tok == '[') {
6426 /* array definition */
6427 next();
6428 n = -1;
6429 if (tok != ']') {
6430 n = expr_const();
6431 if (n < 0)
6432 error("invalid array size");
6434 skip(']');
6435 /* parse next post type */
6436 t1 = type->t & VT_STORAGE;
6437 type->t &= ~VT_STORAGE;
6438 post_type(type, ad);
6440 /* we push a anonymous symbol which will contain the array
6441 element type */
6442 s = sym_push(SYM_FIELD, type, 0, n);
6443 type->t = t1 | VT_ARRAY | VT_PTR;
6444 type->ref = s;
6448 /* Parse a type declaration (except basic type), and return the type
6449 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6450 expected. 'type' should contain the basic type. 'ad' is the
6451 attribute definition of the basic type. It can be modified by
6452 type_decl().
6454 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6456 Sym *s;
6457 CType type1, *type2;
6458 int qualifiers;
6460 while (tok == '*') {
6461 qualifiers = 0;
6462 redo:
6463 next();
6464 switch(tok) {
6465 case TOK_CONST1:
6466 case TOK_CONST2:
6467 case TOK_CONST3:
6468 qualifiers |= VT_CONSTANT;
6469 goto redo;
6470 case TOK_VOLATILE1:
6471 case TOK_VOLATILE2:
6472 case TOK_VOLATILE3:
6473 qualifiers |= VT_VOLATILE;
6474 goto redo;
6475 case TOK_RESTRICT1:
6476 case TOK_RESTRICT2:
6477 case TOK_RESTRICT3:
6478 goto redo;
6480 mk_pointer(type);
6481 type->t |= qualifiers;
6484 /* XXX: clarify attribute handling */
6485 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6486 parse_attribute(ad);
6488 /* recursive type */
6489 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6490 type1.t = 0; /* XXX: same as int */
6491 if (tok == '(') {
6492 next();
6493 /* XXX: this is not correct to modify 'ad' at this point, but
6494 the syntax is not clear */
6495 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6496 parse_attribute(ad);
6497 type_decl(&type1, ad, v, td);
6498 skip(')');
6499 } else {
6500 /* type identifier */
6501 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6502 *v = tok;
6503 next();
6504 } else {
6505 if (!(td & TYPE_ABSTRACT))
6506 expect("identifier");
6507 *v = 0;
6510 post_type(type, ad);
6511 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6512 parse_attribute(ad);
6513 if (!type1.t)
6514 return;
6515 /* append type at the end of type1 */
6516 type2 = &type1;
6517 for(;;) {
6518 s = type2->ref;
6519 type2 = &s->type;
6520 if (!type2->t) {
6521 *type2 = *type;
6522 break;
6525 *type = type1;
6528 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6529 static int lvalue_type(int t)
6531 int bt, r;
6532 r = VT_LVAL;
6533 bt = t & VT_BTYPE;
6534 if (bt == VT_BYTE || bt == VT_BOOL)
6535 r |= VT_LVAL_BYTE;
6536 else if (bt == VT_SHORT)
6537 r |= VT_LVAL_SHORT;
6538 else
6539 return r;
6540 if (t & VT_UNSIGNED)
6541 r |= VT_LVAL_UNSIGNED;
6542 return r;
6545 /* indirection with full error checking and bound check */
6546 static void indir(void)
6548 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6549 expect("pointer");
6550 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6551 gv(RC_INT);
6552 vtop->type = *pointed_type(&vtop->type);
6553 /* an array is never an lvalue */
6554 if (!(vtop->type.t & VT_ARRAY)) {
6555 vtop->r |= lvalue_type(vtop->type.t);
6556 /* if bound checking, the referenced pointer must be checked */
6557 if (do_bounds_check)
6558 vtop->r |= VT_MUSTBOUND;
6562 /* pass a parameter to a function and do type checking and casting */
6563 static void gfunc_param_typed(Sym *func, Sym *arg)
6565 int func_type;
6566 CType type;
6568 func_type = func->c;
6569 if (func_type == FUNC_OLD ||
6570 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6571 /* default casting : only need to convert float to double */
6572 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6573 type.t = VT_DOUBLE;
6574 gen_cast(&type);
6576 } else if (arg == NULL) {
6577 error("too many arguments to function");
6578 } else {
6579 gen_assign_cast(&arg->type);
6583 /* parse an expression of the form '(type)' or '(expr)' and return its
6584 type */
6585 static void parse_expr_type(CType *type)
6587 int n;
6588 AttributeDef ad;
6590 skip('(');
6591 if (parse_btype(type, &ad)) {
6592 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6593 } else {
6594 expr_type(type);
6596 skip(')');
6599 static void parse_type(CType *type)
6601 AttributeDef ad;
6602 int n;
6604 if (!parse_btype(type, &ad)) {
6605 expect("type");
6607 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6610 static void vpush_tokc(int t)
6612 CType type;
6613 type.t = t;
6614 vsetc(&type, VT_CONST, &tokc);
6617 static void unary(void)
6619 int n, t, align, size, r;
6620 CType type;
6621 Sym *s;
6622 AttributeDef ad;
6624 /* XXX: GCC 2.95.3 does not generate a table although it should be
6625 better here */
6626 tok_next:
6627 switch(tok) {
6628 case TOK_EXTENSION:
6629 next();
6630 goto tok_next;
6631 case TOK_CINT:
6632 case TOK_CCHAR:
6633 case TOK_LCHAR:
6634 vpushi(tokc.i);
6635 next();
6636 break;
6637 case TOK_CUINT:
6638 vpush_tokc(VT_INT | VT_UNSIGNED);
6639 next();
6640 break;
6641 case TOK_CLLONG:
6642 vpush_tokc(VT_LLONG);
6643 next();
6644 break;
6645 case TOK_CULLONG:
6646 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6647 next();
6648 break;
6649 case TOK_CFLOAT:
6650 vpush_tokc(VT_FLOAT);
6651 next();
6652 break;
6653 case TOK_CDOUBLE:
6654 vpush_tokc(VT_DOUBLE);
6655 next();
6656 break;
6657 case TOK_CLDOUBLE:
6658 vpush_tokc(VT_LDOUBLE);
6659 next();
6660 break;
6661 case TOK___FUNCTION__:
6662 if (!gnu_ext)
6663 goto tok_identifier;
6664 /* fall thru */
6665 case TOK___FUNC__:
6667 void *ptr;
6668 int len;
6669 /* special function name identifier */
6670 len = strlen(funcname) + 1;
6671 /* generate char[len] type */
6672 type.t = VT_BYTE;
6673 mk_pointer(&type);
6674 type.t |= VT_ARRAY;
6675 type.ref->c = len;
6676 vpush_ref(&type, data_section, data_section->data_offset, len);
6677 ptr = section_ptr_add(data_section, len);
6678 memcpy(ptr, funcname, len);
6679 next();
6681 break;
6682 case TOK_LSTR:
6683 t = VT_INT;
6684 goto str_init;
6685 case TOK_STR:
6686 /* string parsing */
6687 t = VT_BYTE;
6688 str_init:
6689 if (tcc_state->warn_write_strings)
6690 t |= VT_CONSTANT;
6691 type.t = t;
6692 mk_pointer(&type);
6693 type.t |= VT_ARRAY;
6694 memset(&ad, 0, sizeof(AttributeDef));
6695 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6696 break;
6697 case '(':
6698 next();
6699 /* cast ? */
6700 if (parse_btype(&type, &ad)) {
6701 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6702 skip(')');
6703 /* check ISOC99 compound literal */
6704 if (tok == '{') {
6705 /* data is allocated locally by default */
6706 if (global_expr)
6707 r = VT_CONST;
6708 else
6709 r = VT_LOCAL;
6710 /* all except arrays are lvalues */
6711 if (!(type.t & VT_ARRAY))
6712 r |= lvalue_type(type.t);
6713 memset(&ad, 0, sizeof(AttributeDef));
6714 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6715 } else {
6716 unary();
6717 gen_cast(&type);
6719 } else if (tok == '{') {
6720 /* save all registers */
6721 save_regs(0);
6722 /* statement expression : we do not accept break/continue
6723 inside as GCC does */
6724 block(NULL, NULL, NULL, NULL, 0, 1);
6725 skip(')');
6726 } else {
6727 gexpr();
6728 skip(')');
6730 break;
6731 case '*':
6732 next();
6733 unary();
6734 indir();
6735 break;
6736 case '&':
6737 next();
6738 unary();
6739 /* functions names must be treated as function pointers,
6740 except for unary '&' and sizeof. Since we consider that
6741 functions are not lvalues, we only have to handle it
6742 there and in function calls. */
6743 /* arrays can also be used although they are not lvalues */
6744 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6745 !(vtop->type.t & VT_ARRAY))
6746 test_lvalue();
6747 mk_pointer(&vtop->type);
6748 gaddrof();
6749 break;
6750 case '!':
6751 next();
6752 unary();
6753 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6754 vtop->c.i = !vtop->c.i;
6755 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6756 vtop->c.i = vtop->c.i ^ 1;
6757 else
6758 vseti(VT_JMP, gtst(1, 0));
6759 break;
6760 case '~':
6761 next();
6762 unary();
6763 vpushi(-1);
6764 gen_op('^');
6765 break;
6766 case '+':
6767 next();
6768 /* in order to force cast, we add zero */
6769 unary();
6770 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6771 error("pointer not accepted for unary plus");
6772 vpushi(0);
6773 gen_op('+');
6774 break;
6775 case TOK_SIZEOF:
6776 case TOK_ALIGNOF1:
6777 case TOK_ALIGNOF2:
6778 t = tok;
6779 next();
6780 if (tok == '(') {
6781 parse_expr_type(&type);
6782 } else {
6783 unary_type(&type);
6785 size = type_size(&type, &align);
6786 if (t == TOK_SIZEOF) {
6787 if (size < 0)
6788 error("sizeof applied to an incomplete type");
6789 vpushi(size);
6790 } else {
6791 vpushi(align);
6793 break;
6795 case TOK_builtin_types_compatible_p:
6797 CType type1, type2;
6798 next();
6799 skip('(');
6800 parse_type(&type1);
6801 skip(',');
6802 parse_type(&type2);
6803 skip(')');
6804 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6805 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6806 vpushi(is_compatible_types(&type1, &type2));
6808 break;
6809 case TOK_builtin_constant_p:
6811 int saved_nocode_wanted, res;
6812 next();
6813 skip('(');
6814 saved_nocode_wanted = nocode_wanted;
6815 nocode_wanted = 1;
6816 gexpr();
6817 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6818 vpop();
6819 nocode_wanted = saved_nocode_wanted;
6820 skip(')');
6821 vpushi(res);
6823 break;
6824 case TOK_INC:
6825 case TOK_DEC:
6826 t = tok;
6827 next();
6828 unary();
6829 inc(0, t);
6830 break;
6831 case '-':
6832 next();
6833 vpushi(0);
6834 unary();
6835 gen_op('-');
6836 break;
6837 case TOK_LAND:
6838 if (!gnu_ext)
6839 goto tok_identifier;
6840 next();
6841 /* allow to take the address of a label */
6842 if (tok < TOK_UIDENT)
6843 expect("label identifier");
6844 s = label_find(tok);
6845 if (!s) {
6846 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6847 } else {
6848 if (s->r == LABEL_DECLARED)
6849 s->r = LABEL_FORWARD;
6851 if (!s->type.t) {
6852 s->type.t = VT_VOID;
6853 mk_pointer(&s->type);
6854 s->type.t |= VT_STATIC;
6856 vset(&s->type, VT_CONST | VT_SYM, 0);
6857 vtop->sym = s;
6858 next();
6859 break;
6860 default:
6861 tok_identifier:
6862 t = tok;
6863 next();
6864 if (t < TOK_UIDENT)
6865 expect("identifier");
6866 s = sym_find(t);
6867 if (!s) {
6868 if (tok != '(')
6869 error("'%s' undeclared", get_tok_str(t, NULL));
6870 /* for simple function calls, we tolerate undeclared
6871 external reference to int() function */
6872 s = external_global_sym(t, &func_old_type, 0);
6874 vset(&s->type, s->r, s->c);
6875 /* if forward reference, we must point to s */
6876 if (vtop->r & VT_SYM) {
6877 vtop->sym = s;
6878 vtop->c.ul = 0;
6880 break;
6883 /* post operations */
6884 while (1) {
6885 if (tok == TOK_INC || tok == TOK_DEC) {
6886 inc(1, tok);
6887 next();
6888 } else if (tok == '.' || tok == TOK_ARROW) {
6889 /* field */
6890 if (tok == TOK_ARROW)
6891 indir();
6892 test_lvalue();
6893 gaddrof();
6894 next();
6895 /* expect pointer on structure */
6896 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6897 expect("struct or union");
6898 s = vtop->type.ref;
6899 /* find field */
6900 tok |= SYM_FIELD;
6901 while ((s = s->next) != NULL) {
6902 if (s->v == tok)
6903 break;
6905 if (!s)
6906 error("field not found");
6907 /* add field offset to pointer */
6908 vtop->type = char_pointer_type; /* change type to 'char *' */
6909 vpushi(s->c);
6910 gen_op('+');
6911 /* change type to field type, and set to lvalue */
6912 vtop->type = s->type;
6913 /* an array is never an lvalue */
6914 if (!(vtop->type.t & VT_ARRAY)) {
6915 vtop->r |= lvalue_type(vtop->type.t);
6916 /* if bound checking, the referenced pointer must be checked */
6917 if (do_bounds_check)
6918 vtop->r |= VT_MUSTBOUND;
6920 next();
6921 } else if (tok == '[') {
6922 next();
6923 gexpr();
6924 gen_op('+');
6925 indir();
6926 skip(']');
6927 } else if (tok == '(') {
6928 SValue ret;
6929 Sym *sa;
6930 int nb_args;
6932 /* function call */
6933 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
6934 /* pointer test (no array accepted) */
6935 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
6936 vtop->type = *pointed_type(&vtop->type);
6937 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
6938 goto error_func;
6939 } else {
6940 error_func:
6941 expect("function pointer");
6943 } else {
6944 vtop->r &= ~VT_LVAL; /* no lvalue */
6946 /* get return type */
6947 s = vtop->type.ref;
6948 next();
6949 sa = s->next; /* first parameter */
6950 nb_args = 0;
6951 /* compute first implicit argument if a structure is returned */
6952 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
6953 /* get some space for the returned structure */
6954 size = type_size(&s->type, &align);
6955 loc = (loc - size) & -align;
6956 ret.type = s->type;
6957 ret.r = VT_LOCAL | VT_LVAL;
6958 /* pass it as 'int' to avoid structure arg passing
6959 problems */
6960 vseti(VT_LOCAL, loc);
6961 ret.c = vtop->c;
6962 nb_args++;
6963 } else {
6964 ret.type = s->type;
6965 ret.r2 = VT_CONST;
6966 /* return in register */
6967 if (is_float(ret.type.t)) {
6968 ret.r = REG_FRET;
6969 } else {
6970 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
6971 ret.r2 = REG_LRET;
6972 ret.r = REG_IRET;
6974 ret.c.i = 0;
6976 if (tok != ')') {
6977 for(;;) {
6978 expr_eq();
6979 gfunc_param_typed(s, sa);
6980 nb_args++;
6981 if (sa)
6982 sa = sa->next;
6983 if (tok == ')')
6984 break;
6985 skip(',');
6988 if (sa)
6989 error("too few arguments to function");
6990 skip(')');
6991 if (!nocode_wanted) {
6992 gfunc_call(nb_args);
6993 } else {
6994 vtop -= (nb_args + 1);
6996 /* return value */
6997 vsetc(&ret.type, ret.r, &ret.c);
6998 vtop->r2 = ret.r2;
6999 } else {
7000 break;
7005 static void uneq(void)
7007 int t;
7009 unary();
7010 if (tok == '=' ||
7011 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7012 tok == TOK_A_XOR || tok == TOK_A_OR ||
7013 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7014 test_lvalue();
7015 t = tok;
7016 next();
7017 if (t == '=') {
7018 expr_eq();
7019 } else {
7020 vdup();
7021 expr_eq();
7022 gen_op(t & 0x7f);
7024 vstore();
7028 static void expr_prod(void)
7030 int t;
7032 uneq();
7033 while (tok == '*' || tok == '/' || tok == '%') {
7034 t = tok;
7035 next();
7036 uneq();
7037 gen_op(t);
7041 static void expr_sum(void)
7043 int t;
7045 expr_prod();
7046 while (tok == '+' || tok == '-') {
7047 t = tok;
7048 next();
7049 expr_prod();
7050 gen_op(t);
7054 static void expr_shift(void)
7056 int t;
7058 expr_sum();
7059 while (tok == TOK_SHL || tok == TOK_SAR) {
7060 t = tok;
7061 next();
7062 expr_sum();
7063 gen_op(t);
7067 static void expr_cmp(void)
7069 int t;
7071 expr_shift();
7072 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7073 tok == TOK_ULT || tok == TOK_UGE) {
7074 t = tok;
7075 next();
7076 expr_shift();
7077 gen_op(t);
7081 static void expr_cmpeq(void)
7083 int t;
7085 expr_cmp();
7086 while (tok == TOK_EQ || tok == TOK_NE) {
7087 t = tok;
7088 next();
7089 expr_cmp();
7090 gen_op(t);
7094 static void expr_and(void)
7096 expr_cmpeq();
7097 while (tok == '&') {
7098 next();
7099 expr_cmpeq();
7100 gen_op('&');
7104 static void expr_xor(void)
7106 expr_and();
7107 while (tok == '^') {
7108 next();
7109 expr_and();
7110 gen_op('^');
7114 static void expr_or(void)
7116 expr_xor();
7117 while (tok == '|') {
7118 next();
7119 expr_xor();
7120 gen_op('|');
7124 /* XXX: fix this mess */
7125 static void expr_land_const(void)
7127 expr_or();
7128 while (tok == TOK_LAND) {
7129 next();
7130 expr_or();
7131 gen_op(TOK_LAND);
7135 /* XXX: fix this mess */
7136 static void expr_lor_const(void)
7138 expr_land_const();
7139 while (tok == TOK_LOR) {
7140 next();
7141 expr_land_const();
7142 gen_op(TOK_LOR);
7146 /* only used if non constant */
7147 static void expr_land(void)
7149 int t;
7151 expr_or();
7152 if (tok == TOK_LAND) {
7153 t = 0;
7154 for(;;) {
7155 t = gtst(1, t);
7156 if (tok != TOK_LAND) {
7157 vseti(VT_JMPI, t);
7158 break;
7160 next();
7161 expr_or();
7166 static void expr_lor(void)
7168 int t;
7170 expr_land();
7171 if (tok == TOK_LOR) {
7172 t = 0;
7173 for(;;) {
7174 t = gtst(0, t);
7175 if (tok != TOK_LOR) {
7176 vseti(VT_JMP, t);
7177 break;
7179 next();
7180 expr_land();
7185 /* XXX: better constant handling */
7186 static void expr_eq(void)
7188 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7189 SValue sv;
7190 CType type, type1, type2;
7192 if (const_wanted) {
7193 int c1, c;
7194 expr_lor_const();
7195 if (tok == '?') {
7196 c = vtop->c.i;
7197 vpop();
7198 next();
7199 if (tok == ':' && gnu_ext) {
7200 c1 = c;
7201 } else {
7202 gexpr();
7203 c1 = vtop->c.i;
7204 vpop();
7206 skip(':');
7207 expr_eq();
7208 if (c)
7209 vtop->c.i = c1;
7211 } else {
7212 expr_lor();
7213 if (tok == '?') {
7214 next();
7215 if (vtop != vstack) {
7216 /* needed to avoid having different registers saved in
7217 each branch */
7218 if (is_float(vtop->type.t))
7219 rc = RC_FLOAT;
7220 else
7221 rc = RC_INT;
7222 gv(rc);
7223 save_regs(1);
7225 if (tok == ':' && gnu_ext) {
7226 gv_dup();
7227 tt = gtst(1, 0);
7228 } else {
7229 tt = gtst(1, 0);
7230 gexpr();
7232 type1 = vtop->type;
7233 sv = *vtop; /* save value to handle it later */
7234 vtop--; /* no vpop so that FP stack is not flushed */
7235 skip(':');
7236 u = gjmp(0);
7237 gsym(tt);
7238 expr_eq();
7239 type2 = vtop->type;
7241 t1 = type1.t;
7242 bt1 = t1 & VT_BTYPE;
7243 t2 = type2.t;
7244 bt2 = t2 & VT_BTYPE;
7245 /* cast operands to correct type according to ISOC rules */
7246 if (is_float(bt1) || is_float(bt2)) {
7247 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7248 type.t = VT_LDOUBLE;
7249 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7250 type.t = VT_DOUBLE;
7251 } else {
7252 type.t = VT_FLOAT;
7254 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7255 /* cast to biggest op */
7256 type.t = VT_LLONG;
7257 /* convert to unsigned if it does not fit in a long long */
7258 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7259 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7260 type.t |= VT_UNSIGNED;
7261 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7262 /* XXX: test pointer compatibility */
7263 type = type1;
7264 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7265 /* XXX: test structure compatibility */
7266 type = type1;
7267 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7268 /* NOTE: as an extension, we accept void on only one side */
7269 type.t = VT_VOID;
7270 } else {
7271 /* integer operations */
7272 type.t = VT_INT;
7273 /* convert to unsigned if it does not fit in an integer */
7274 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7275 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7276 type.t |= VT_UNSIGNED;
7279 /* now we convert second operand */
7280 gen_cast(&type);
7281 rc = RC_INT;
7282 if (is_float(type.t)) {
7283 rc = RC_FLOAT;
7284 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7285 /* for long longs, we use fixed registers to avoid having
7286 to handle a complicated move */
7287 rc = RC_IRET;
7290 r2 = gv(rc);
7291 /* this is horrible, but we must also convert first
7292 operand */
7293 tt = gjmp(0);
7294 gsym(u);
7295 /* put again first value and cast it */
7296 *vtop = sv;
7297 gen_cast(&type);
7298 r1 = gv(rc);
7299 move_reg(r2, r1);
7300 vtop->r = r2;
7301 gsym(tt);
7306 static void gexpr(void)
7308 while (1) {
7309 expr_eq();
7310 if (tok != ',')
7311 break;
7312 vpop();
7313 next();
7317 /* parse an expression and return its type without any side effect. */
7318 static void expr_type(CType *type)
7320 int saved_nocode_wanted;
7322 saved_nocode_wanted = nocode_wanted;
7323 nocode_wanted = 1;
7324 gexpr();
7325 *type = vtop->type;
7326 vpop();
7327 nocode_wanted = saved_nocode_wanted;
7330 /* parse a unary expression and return its type without any side
7331 effect. */
7332 static void unary_type(CType *type)
7334 int a;
7336 a = nocode_wanted;
7337 nocode_wanted = 1;
7338 unary();
7339 *type = vtop->type;
7340 vpop();
7341 nocode_wanted = a;
7344 /* parse a constant expression and return value in vtop. */
7345 static void expr_const1(void)
7347 int a;
7348 a = const_wanted;
7349 const_wanted = 1;
7350 expr_eq();
7351 const_wanted = a;
7354 /* parse an integer constant and return its value. */
7355 static int expr_const(void)
7357 int c;
7358 expr_const1();
7359 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7360 expect("constant expression");
7361 c = vtop->c.i;
7362 vpop();
7363 return c;
7366 /* return the label token if current token is a label, otherwise
7367 return zero */
7368 static int is_label(void)
7370 int last_tok;
7372 /* fast test first */
7373 if (tok < TOK_UIDENT)
7374 return 0;
7375 /* no need to save tokc because tok is an identifier */
7376 last_tok = tok;
7377 next();
7378 if (tok == ':') {
7379 next();
7380 return last_tok;
7381 } else {
7382 unget_tok(last_tok);
7383 return 0;
7387 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7388 int case_reg, int is_expr)
7390 int a, b, c, d;
7391 Sym *s;
7393 /* generate line number info */
7394 if (do_debug &&
7395 (last_line_num != file->line_num || last_ind != ind)) {
7396 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7397 last_ind = ind;
7398 last_line_num = file->line_num;
7401 if (is_expr) {
7402 /* default return value is (void) */
7403 vpushi(0);
7404 vtop->type.t = VT_VOID;
7407 if (tok == TOK_IF) {
7408 /* if test */
7409 next();
7410 skip('(');
7411 gexpr();
7412 skip(')');
7413 a = gtst(1, 0);
7414 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7415 c = tok;
7416 if (c == TOK_ELSE) {
7417 next();
7418 d = gjmp(0);
7419 gsym(a);
7420 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7421 gsym(d); /* patch else jmp */
7422 } else
7423 gsym(a);
7424 } else if (tok == TOK_WHILE) {
7425 next();
7426 d = ind;
7427 skip('(');
7428 gexpr();
7429 skip(')');
7430 a = gtst(1, 0);
7431 b = 0;
7432 block(&a, &b, case_sym, def_sym, case_reg, 0);
7433 gjmp_addr(d);
7434 gsym(a);
7435 gsym_addr(b, d);
7436 } else if (tok == '{') {
7437 Sym *llabel;
7439 next();
7440 /* record local declaration stack position */
7441 s = local_stack;
7442 llabel = local_label_stack;
7443 /* handle local labels declarations */
7444 if (tok == TOK_LABEL) {
7445 next();
7446 for(;;) {
7447 if (tok < TOK_UIDENT)
7448 expect("label identifier");
7449 label_push(&local_label_stack, tok, LABEL_DECLARED);
7450 next();
7451 if (tok == ',') {
7452 next();
7453 } else {
7454 skip(';');
7455 break;
7459 while (tok != '}') {
7460 decl(VT_LOCAL);
7461 if (tok != '}') {
7462 if (is_expr)
7463 vpop();
7464 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7467 /* pop locally defined labels */
7468 label_pop(&local_label_stack, llabel);
7469 /* pop locally defined symbols */
7470 sym_pop(&local_stack, s);
7471 next();
7472 } else if (tok == TOK_RETURN) {
7473 next();
7474 if (tok != ';') {
7475 gexpr();
7476 gen_assign_cast(&func_vt);
7477 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7478 CType type;
7479 /* if returning structure, must copy it to implicit
7480 first pointer arg location */
7481 type = func_vt;
7482 mk_pointer(&type);
7483 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7484 indir();
7485 vswap();
7486 /* copy structure value to pointer */
7487 vstore();
7488 } else if (is_float(func_vt.t)) {
7489 gv(RC_FRET);
7490 } else {
7491 gv(RC_IRET);
7493 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7495 skip(';');
7496 rsym = gjmp(rsym); /* jmp */
7497 } else if (tok == TOK_BREAK) {
7498 /* compute jump */
7499 if (!bsym)
7500 error("cannot break");
7501 *bsym = gjmp(*bsym);
7502 next();
7503 skip(';');
7504 } else if (tok == TOK_CONTINUE) {
7505 /* compute jump */
7506 if (!csym)
7507 error("cannot continue");
7508 *csym = gjmp(*csym);
7509 next();
7510 skip(';');
7511 } else if (tok == TOK_FOR) {
7512 int e;
7513 next();
7514 skip('(');
7515 if (tok != ';') {
7516 gexpr();
7517 vpop();
7519 skip(';');
7520 d = ind;
7521 c = ind;
7522 a = 0;
7523 b = 0;
7524 if (tok != ';') {
7525 gexpr();
7526 a = gtst(1, 0);
7528 skip(';');
7529 if (tok != ')') {
7530 e = gjmp(0);
7531 c = ind;
7532 gexpr();
7533 vpop();
7534 gjmp_addr(d);
7535 gsym(e);
7537 skip(')');
7538 block(&a, &b, case_sym, def_sym, case_reg, 0);
7539 gjmp_addr(c);
7540 gsym(a);
7541 gsym_addr(b, c);
7542 } else
7543 if (tok == TOK_DO) {
7544 next();
7545 a = 0;
7546 b = 0;
7547 d = ind;
7548 block(&a, &b, case_sym, def_sym, case_reg, 0);
7549 skip(TOK_WHILE);
7550 skip('(');
7551 gsym(b);
7552 gexpr();
7553 c = gtst(0, 0);
7554 gsym_addr(c, d);
7555 skip(')');
7556 gsym(a);
7557 skip(';');
7558 } else
7559 if (tok == TOK_SWITCH) {
7560 next();
7561 skip('(');
7562 gexpr();
7563 /* XXX: other types than integer */
7564 case_reg = gv(RC_INT);
7565 vpop();
7566 skip(')');
7567 a = 0;
7568 b = gjmp(0); /* jump to first case */
7569 c = 0;
7570 block(&a, csym, &b, &c, case_reg, 0);
7571 /* if no default, jmp after switch */
7572 if (c == 0)
7573 c = ind;
7574 /* default label */
7575 gsym_addr(b, c);
7576 /* break label */
7577 gsym(a);
7578 } else
7579 if (tok == TOK_CASE) {
7580 int v1, v2;
7581 if (!case_sym)
7582 expect("switch");
7583 next();
7584 v1 = expr_const();
7585 v2 = v1;
7586 if (gnu_ext && tok == TOK_DOTS) {
7587 next();
7588 v2 = expr_const();
7589 if (v2 < v1)
7590 warning("empty case range");
7592 /* since a case is like a label, we must skip it with a jmp */
7593 b = gjmp(0);
7594 gsym(*case_sym);
7595 vseti(case_reg, 0);
7596 vpushi(v1);
7597 if (v1 == v2) {
7598 gen_op(TOK_EQ);
7599 *case_sym = gtst(1, 0);
7600 } else {
7601 gen_op(TOK_GE);
7602 *case_sym = gtst(1, 0);
7603 vseti(case_reg, 0);
7604 vpushi(v2);
7605 gen_op(TOK_LE);
7606 *case_sym = gtst(1, *case_sym);
7608 gsym(b);
7609 skip(':');
7610 is_expr = 0;
7611 goto block_after_label;
7612 } else
7613 if (tok == TOK_DEFAULT) {
7614 next();
7615 skip(':');
7616 if (!def_sym)
7617 expect("switch");
7618 if (*def_sym)
7619 error("too many 'default'");
7620 *def_sym = ind;
7621 is_expr = 0;
7622 goto block_after_label;
7623 } else
7624 if (tok == TOK_GOTO) {
7625 next();
7626 if (tok == '*' && gnu_ext) {
7627 /* computed goto */
7628 next();
7629 gexpr();
7630 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7631 expect("pointer");
7632 ggoto();
7633 } else if (tok >= TOK_UIDENT) {
7634 s = label_find(tok);
7635 /* put forward definition if needed */
7636 if (!s) {
7637 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7638 } else {
7639 if (s->r == LABEL_DECLARED)
7640 s->r = LABEL_FORWARD;
7642 /* label already defined */
7643 if (s->r & LABEL_FORWARD)
7644 s->next = (void *)gjmp((long)s->next);
7645 else
7646 gjmp_addr((long)s->next);
7647 next();
7648 } else {
7649 expect("label identifier");
7651 skip(';');
7652 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7653 asm_instr();
7654 } else {
7655 b = is_label();
7656 if (b) {
7657 /* label case */
7658 s = label_find(b);
7659 if (s) {
7660 if (s->r == LABEL_DEFINED)
7661 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7662 gsym((long)s->next);
7663 s->r = LABEL_DEFINED;
7664 } else {
7665 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7667 s->next = (void *)ind;
7668 /* we accept this, but it is a mistake */
7669 block_after_label:
7670 if (tok == '}') {
7671 warning("deprecated use of label at end of compound statement");
7672 } else {
7673 if (is_expr)
7674 vpop();
7675 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7677 } else {
7678 /* expression case */
7679 if (tok != ';') {
7680 if (is_expr) {
7681 vpop();
7682 gexpr();
7683 } else {
7684 gexpr();
7685 vpop();
7688 skip(';');
7693 /* t is the array or struct type. c is the array or struct
7694 address. cur_index/cur_field is the pointer to the current
7695 value. 'size_only' is true if only size info is needed (only used
7696 in arrays) */
7697 static void decl_designator(CType *type, Section *sec, unsigned long c,
7698 int *cur_index, Sym **cur_field,
7699 int size_only)
7701 Sym *s, *f;
7702 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7703 CType type1;
7705 notfirst = 0;
7706 elem_size = 0;
7707 nb_elems = 1;
7708 if (gnu_ext && (l = is_label()) != 0)
7709 goto struct_field;
7710 while (tok == '[' || tok == '.') {
7711 if (tok == '[') {
7712 if (!(type->t & VT_ARRAY))
7713 expect("array type");
7714 s = type->ref;
7715 next();
7716 index = expr_const();
7717 if (index < 0 || (s->c >= 0 && index >= s->c))
7718 expect("invalid index");
7719 if (tok == TOK_DOTS && gnu_ext) {
7720 next();
7721 index_last = expr_const();
7722 if (index_last < 0 ||
7723 (s->c >= 0 && index_last >= s->c) ||
7724 index_last < index)
7725 expect("invalid index");
7726 } else {
7727 index_last = index;
7729 skip(']');
7730 if (!notfirst)
7731 *cur_index = index_last;
7732 type = pointed_type(type);
7733 elem_size = type_size(type, &align);
7734 c += index * elem_size;
7735 /* NOTE: we only support ranges for last designator */
7736 nb_elems = index_last - index + 1;
7737 if (nb_elems != 1) {
7738 notfirst = 1;
7739 break;
7741 } else {
7742 next();
7743 l = tok;
7744 next();
7745 struct_field:
7746 if ((type->t & VT_BTYPE) != VT_STRUCT)
7747 expect("struct/union type");
7748 s = type->ref;
7749 l |= SYM_FIELD;
7750 f = s->next;
7751 while (f) {
7752 if (f->v == l)
7753 break;
7754 f = f->next;
7756 if (!f)
7757 expect("field");
7758 if (!notfirst)
7759 *cur_field = f;
7760 /* XXX: fix this mess by using explicit storage field */
7761 type1 = f->type;
7762 type1.t |= (type->t & ~VT_TYPE);
7763 type = &type1;
7764 c += f->c;
7766 notfirst = 1;
7768 if (notfirst) {
7769 if (tok == '=') {
7770 next();
7771 } else {
7772 if (!gnu_ext)
7773 expect("=");
7775 } else {
7776 if (type->t & VT_ARRAY) {
7777 index = *cur_index;
7778 type = pointed_type(type);
7779 c += index * type_size(type, &align);
7780 } else {
7781 f = *cur_field;
7782 if (!f)
7783 error("too many field init");
7784 /* XXX: fix this mess by using explicit storage field */
7785 type1 = f->type;
7786 type1.t |= (type->t & ~VT_TYPE);
7787 type = &type1;
7788 c += f->c;
7791 decl_initializer(type, sec, c, 0, size_only);
7793 /* XXX: make it more general */
7794 if (!size_only && nb_elems > 1) {
7795 unsigned long c_end;
7796 uint8_t *src, *dst;
7797 int i;
7799 if (!sec)
7800 error("range init not supported yet for dynamic storage");
7801 c_end = c + nb_elems * elem_size;
7802 if (c_end > sec->data_allocated)
7803 section_realloc(sec, c_end);
7804 src = sec->data + c;
7805 dst = src;
7806 for(i = 1; i < nb_elems; i++) {
7807 dst += elem_size;
7808 memcpy(dst, src, elem_size);
7813 #define EXPR_VAL 0
7814 #define EXPR_CONST 1
7815 #define EXPR_ANY 2
7817 /* store a value or an expression directly in global data or in local array */
7818 static void init_putv(CType *type, Section *sec, unsigned long c,
7819 int v, int expr_type)
7821 int saved_global_expr, bt, bit_pos, bit_size;
7822 void *ptr;
7823 unsigned long long bit_mask;
7824 CType dtype;
7826 switch(expr_type) {
7827 case EXPR_VAL:
7828 vpushi(v);
7829 break;
7830 case EXPR_CONST:
7831 /* compound literals must be allocated globally in this case */
7832 saved_global_expr = global_expr;
7833 global_expr = 1;
7834 expr_const1();
7835 global_expr = saved_global_expr;
7836 /* NOTE: symbols are accepted */
7837 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
7838 error("initializer element is not constant");
7839 break;
7840 case EXPR_ANY:
7841 expr_eq();
7842 break;
7845 dtype = *type;
7846 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7848 if (sec) {
7849 /* XXX: not portable */
7850 /* XXX: generate error if incorrect relocation */
7851 gen_assign_cast(&dtype);
7852 bt = type->t & VT_BTYPE;
7853 ptr = sec->data + c;
7854 /* XXX: make code faster ? */
7855 if (!(type->t & VT_BITFIELD)) {
7856 bit_pos = 0;
7857 bit_size = 32;
7858 bit_mask = -1LL;
7859 } else {
7860 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
7861 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
7862 bit_mask = (1LL << bit_size) - 1;
7864 if ((vtop->r & VT_SYM) &&
7865 (bt == VT_BYTE ||
7866 bt == VT_SHORT ||
7867 bt == VT_DOUBLE ||
7868 bt == VT_LDOUBLE ||
7869 bt == VT_LLONG ||
7870 (bt == VT_INT && bit_size != 32)))
7871 error("initializer element is not computable at load time");
7872 switch(bt) {
7873 case VT_BYTE:
7874 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7875 break;
7876 case VT_SHORT:
7877 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7878 break;
7879 case VT_DOUBLE:
7880 *(double *)ptr = vtop->c.d;
7881 break;
7882 case VT_LDOUBLE:
7883 *(long double *)ptr = vtop->c.ld;
7884 break;
7885 case VT_LLONG:
7886 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
7887 break;
7888 default:
7889 if (vtop->r & VT_SYM) {
7890 greloc(sec, vtop->sym, c, R_DATA_32);
7892 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7893 break;
7895 vtop--;
7896 } else {
7897 vset(&dtype, VT_LOCAL, c);
7898 vswap();
7899 vstore();
7900 vpop();
7904 /* put zeros for variable based init */
7905 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
7907 if (sec) {
7908 /* nothing to do because globals are already set to zero */
7909 } else {
7910 vpush_global_sym(&func_old_type, TOK_memset);
7911 vseti(VT_LOCAL, c);
7912 vpushi(0);
7913 vpushi(size);
7914 gfunc_call(3);
7918 /* 't' contains the type and storage info. 'c' is the offset of the
7919 object in section 'sec'. If 'sec' is NULL, it means stack based
7920 allocation. 'first' is true if array '{' must be read (multi
7921 dimension implicit array init handling). 'size_only' is true if
7922 size only evaluation is wanted (only for arrays). */
7923 static void decl_initializer(CType *type, Section *sec, unsigned long c,
7924 int first, int size_only)
7926 int index, array_length, n, no_oblock, nb, parlevel, i;
7927 int size1, align1, expr_type;
7928 Sym *s, *f;
7929 CType *t1;
7931 if (type->t & VT_ARRAY) {
7932 s = type->ref;
7933 n = s->c;
7934 array_length = 0;
7935 t1 = pointed_type(type);
7936 size1 = type_size(t1, &align1);
7938 no_oblock = 1;
7939 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
7940 tok == '{') {
7941 skip('{');
7942 no_oblock = 0;
7945 /* only parse strings here if correct type (otherwise: handle
7946 them as ((w)char *) expressions */
7947 if ((tok == TOK_LSTR &&
7948 (t1->t & VT_BTYPE) == VT_INT) ||
7949 (tok == TOK_STR &&
7950 (t1->t & VT_BTYPE) == VT_BYTE)) {
7951 while (tok == TOK_STR || tok == TOK_LSTR) {
7952 int cstr_len, ch;
7953 CString *cstr;
7955 cstr = tokc.cstr;
7956 /* compute maximum number of chars wanted */
7957 if (tok == TOK_STR)
7958 cstr_len = cstr->size;
7959 else
7960 cstr_len = cstr->size / sizeof(int);
7961 cstr_len--;
7962 nb = cstr_len;
7963 if (n >= 0 && nb > (n - array_length))
7964 nb = n - array_length;
7965 if (!size_only) {
7966 if (cstr_len > nb)
7967 warning("initializer-string for array is too long");
7968 /* in order to go faster for common case (char
7969 string in global variable, we handle it
7970 specifically */
7971 if (sec && tok == TOK_STR && size1 == 1) {
7972 memcpy(sec->data + c + array_length, cstr->data, nb);
7973 } else {
7974 for(i=0;i<nb;i++) {
7975 if (tok == TOK_STR)
7976 ch = ((unsigned char *)cstr->data)[i];
7977 else
7978 ch = ((int *)cstr->data)[i];
7979 init_putv(t1, sec, c + (array_length + i) * size1,
7980 ch, EXPR_VAL);
7984 array_length += nb;
7985 next();
7987 /* only add trailing zero if enough storage (no
7988 warning in this case since it is standard) */
7989 if (n < 0 || array_length < n) {
7990 if (!size_only) {
7991 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
7993 array_length++;
7995 } else {
7996 index = 0;
7997 while (tok != '}') {
7998 decl_designator(type, sec, c, &index, NULL, size_only);
7999 if (n >= 0 && index >= n)
8000 error("index too large");
8001 /* must put zero in holes (note that doing it that way
8002 ensures that it even works with designators) */
8003 if (!size_only && array_length < index) {
8004 init_putz(t1, sec, c + array_length * size1,
8005 (index - array_length) * size1);
8007 index++;
8008 if (index > array_length)
8009 array_length = index;
8010 /* special test for multi dimensional arrays (may not
8011 be strictly correct if designators are used at the
8012 same time) */
8013 if (index >= n && no_oblock)
8014 break;
8015 if (tok == '}')
8016 break;
8017 skip(',');
8020 if (!no_oblock)
8021 skip('}');
8022 /* put zeros at the end */
8023 if (!size_only && n >= 0 && array_length < n) {
8024 init_putz(t1, sec, c + array_length * size1,
8025 (n - array_length) * size1);
8027 /* patch type size if needed */
8028 if (n < 0)
8029 s->c = array_length;
8030 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8031 (sec || !first || tok == '{')) {
8032 int par_count;
8034 /* NOTE: the previous test is a specific case for automatic
8035 struct/union init */
8036 /* XXX: union needs only one init */
8038 /* XXX: this test is incorrect for local initializers
8039 beginning with ( without {. It would be much more difficult
8040 to do it correctly (ideally, the expression parser should
8041 be used in all cases) */
8042 par_count = 0;
8043 if (tok == '(') {
8044 AttributeDef ad1;
8045 CType type1;
8046 next();
8047 while (tok == '(') {
8048 par_count++;
8049 next();
8051 if (!parse_btype(&type1, &ad1))
8052 expect("cast");
8053 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8054 #if 0
8055 if (!is_assignable_types(type, &type1))
8056 error("invalid type for cast");
8057 #endif
8058 skip(')');
8060 no_oblock = 1;
8061 if (first || tok == '{') {
8062 skip('{');
8063 no_oblock = 0;
8065 s = type->ref;
8066 f = s->next;
8067 array_length = 0;
8068 index = 0;
8069 n = s->c;
8070 while (tok != '}') {
8071 decl_designator(type, sec, c, NULL, &f, size_only);
8072 index = f->c;
8073 if (!size_only && array_length < index) {
8074 init_putz(type, sec, c + array_length,
8075 index - array_length);
8077 index = index + type_size(&f->type, &align1);
8078 if (index > array_length)
8079 array_length = index;
8080 f = f->next;
8081 if (no_oblock && f == NULL)
8082 break;
8083 if (tok == '}')
8084 break;
8085 skip(',');
8087 /* put zeros at the end */
8088 if (!size_only && array_length < n) {
8089 init_putz(type, sec, c + array_length,
8090 n - array_length);
8092 if (!no_oblock)
8093 skip('}');
8094 while (par_count) {
8095 skip(')');
8096 par_count--;
8098 } else if (tok == '{') {
8099 next();
8100 decl_initializer(type, sec, c, first, size_only);
8101 skip('}');
8102 } else if (size_only) {
8103 /* just skip expression */
8104 parlevel = 0;
8105 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8106 tok != -1) {
8107 if (tok == '(')
8108 parlevel++;
8109 else if (tok == ')')
8110 parlevel--;
8111 next();
8113 } else {
8114 /* currently, we always use constant expression for globals
8115 (may change for scripting case) */
8116 expr_type = EXPR_CONST;
8117 if (!sec)
8118 expr_type = EXPR_ANY;
8119 init_putv(type, sec, c, 0, expr_type);
8123 /* parse an initializer for type 't' if 'has_init' is non zero, and
8124 allocate space in local or global data space ('r' is either
8125 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8126 variable 'v' of scope 'scope' is declared before initializers are
8127 parsed. If 'v' is zero, then a reference to the new object is put
8128 in the value stack. If 'has_init' is 2, a special parsing is done
8129 to handle string constants. */
8130 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8131 int has_init, int v, int scope)
8133 int size, align, addr, data_offset;
8134 int level;
8135 ParseState saved_parse_state;
8136 TokenString init_str;
8137 Section *sec;
8139 size = type_size(type, &align);
8140 /* If unknown size, we must evaluate it before
8141 evaluating initializers because
8142 initializers can generate global data too
8143 (e.g. string pointers or ISOC99 compound
8144 literals). It also simplifies local
8145 initializers handling */
8146 tok_str_new(&init_str);
8147 if (size < 0) {
8148 if (!has_init)
8149 error("unknown type size");
8150 /* get all init string */
8151 if (has_init == 2) {
8152 /* only get strings */
8153 while (tok == TOK_STR || tok == TOK_LSTR) {
8154 tok_str_add_tok(&init_str);
8155 next();
8157 } else {
8158 level = 0;
8159 while (level > 0 || (tok != ',' && tok != ';')) {
8160 if (tok < 0)
8161 error("unexpected end of file in initializer");
8162 tok_str_add_tok(&init_str);
8163 if (tok == '{')
8164 level++;
8165 else if (tok == '}') {
8166 if (level == 0)
8167 break;
8168 level--;
8170 next();
8173 tok_str_add(&init_str, -1);
8174 tok_str_add(&init_str, 0);
8176 /* compute size */
8177 save_parse_state(&saved_parse_state);
8179 macro_ptr = init_str.str;
8180 next();
8181 decl_initializer(type, NULL, 0, 1, 1);
8182 /* prepare second initializer parsing */
8183 macro_ptr = init_str.str;
8184 next();
8186 /* if still unknown size, error */
8187 size = type_size(type, &align);
8188 if (size < 0)
8189 error("unknown type size");
8191 /* take into account specified alignment if bigger */
8192 if (ad->aligned > align)
8193 align = ad->aligned;
8194 if ((r & VT_VALMASK) == VT_LOCAL) {
8195 sec = NULL;
8196 if (do_bounds_check && (type->t & VT_ARRAY))
8197 loc--;
8198 loc = (loc - size) & -align;
8199 addr = loc;
8200 /* handles bounds */
8201 /* XXX: currently, since we do only one pass, we cannot track
8202 '&' operators, so we add only arrays */
8203 if (do_bounds_check && (type->t & VT_ARRAY)) {
8204 unsigned long *bounds_ptr;
8205 /* add padding between regions */
8206 loc--;
8207 /* then add local bound info */
8208 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8209 bounds_ptr[0] = addr;
8210 bounds_ptr[1] = size;
8212 if (v) {
8213 /* local variable */
8214 sym_push(v, type, r, addr);
8215 } else {
8216 /* push local reference */
8217 vset(type, r, addr);
8219 } else {
8220 Sym *sym;
8222 sym = NULL;
8223 if (v && scope == VT_CONST) {
8224 /* see if the symbol was already defined */
8225 sym = sym_find(v);
8226 if (sym) {
8227 if (!is_compatible_types(&sym->type, type))
8228 error("incompatible types for redefinition of '%s'",
8229 get_tok_str(v, NULL));
8230 if (sym->type.t & VT_EXTERN) {
8231 /* if the variable is extern, it was not allocated */
8232 sym->type.t &= ~VT_EXTERN;
8233 } else {
8234 /* we accept several definitions of the same
8235 global variable. this is tricky, because we
8236 must play with the SHN_COMMON type of the symbol */
8237 /* XXX: should check if the variable was already
8238 initialized. It is incorrect to initialized it
8239 twice */
8240 /* no init data, we won't add more to the symbol */
8241 if (!has_init)
8242 goto no_alloc;
8247 /* allocate symbol in corresponding section */
8248 sec = ad->section;
8249 if (!sec) {
8250 if (has_init)
8251 sec = data_section;
8253 if (sec) {
8254 data_offset = sec->data_offset;
8255 data_offset = (data_offset + align - 1) & -align;
8256 addr = data_offset;
8257 /* very important to increment global pointer at this time
8258 because initializers themselves can create new initializers */
8259 data_offset += size;
8260 /* add padding if bound check */
8261 if (do_bounds_check)
8262 data_offset++;
8263 sec->data_offset = data_offset;
8264 /* allocate section space to put the data */
8265 if (sec->sh_type != SHT_NOBITS &&
8266 data_offset > sec->data_allocated)
8267 section_realloc(sec, data_offset);
8268 } else {
8269 addr = 0; /* avoid warning */
8272 if (v) {
8273 if (scope == VT_CONST) {
8274 if (!sym)
8275 goto do_def;
8276 } else {
8277 do_def:
8278 sym = sym_push(v, type, r | VT_SYM, 0);
8280 /* update symbol definition */
8281 if (sec) {
8282 put_extern_sym(sym, sec, addr, size);
8283 } else {
8284 Elf32_Sym *esym;
8285 /* put a common area */
8286 put_extern_sym(sym, NULL, align, size);
8287 /* XXX: find a nicer way */
8288 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8289 esym->st_shndx = SHN_COMMON;
8291 } else {
8292 CValue cval;
8294 /* push global reference */
8295 sym = get_sym_ref(type, sec, addr, size);
8296 cval.ul = 0;
8297 vsetc(type, VT_CONST | VT_SYM, &cval);
8298 vtop->sym = sym;
8301 /* handles bounds now because the symbol must be defined
8302 before for the relocation */
8303 if (do_bounds_check) {
8304 unsigned long *bounds_ptr;
8306 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8307 /* then add global bound info */
8308 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8309 bounds_ptr[0] = 0; /* relocated */
8310 bounds_ptr[1] = size;
8313 if (has_init) {
8314 decl_initializer(type, sec, addr, 1, 0);
8315 /* restore parse state if needed */
8316 if (init_str.str) {
8317 tok_str_free(init_str.str);
8318 restore_parse_state(&saved_parse_state);
8321 no_alloc: ;
8324 void put_func_debug(Sym *sym)
8326 char buf[512];
8328 /* stabs info */
8329 /* XXX: we put here a dummy type */
8330 snprintf(buf, sizeof(buf), "%s:%c1",
8331 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8332 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8333 cur_text_section, sym->c);
8334 last_ind = 0;
8335 last_line_num = 0;
8338 /* not finished : try to put some local vars in registers */
8339 //#define CONFIG_REG_VARS
8341 #ifdef CONFIG_REG_VARS
8342 void add_var_ref(int t)
8344 printf("%s:%d: &%s\n",
8345 file->filename, file->line_num,
8346 get_tok_str(t, NULL));
8349 /* first pass on a function with heuristic to extract variable usage
8350 and pointer references to local variables for register allocation */
8351 void analyse_function(void)
8353 int level, t;
8355 for(;;) {
8356 if (tok == -1)
8357 break;
8358 /* any symbol coming after '&' is considered as being a
8359 variable whose reference is taken. It is highly unaccurate
8360 but it is difficult to do better without a complete parse */
8361 if (tok == '&') {
8362 next();
8363 /* if '& number', then no need to examine next tokens */
8364 if (tok == TOK_CINT ||
8365 tok == TOK_CUINT ||
8366 tok == TOK_CLLONG ||
8367 tok == TOK_CULLONG) {
8368 continue;
8369 } else if (tok >= TOK_UIDENT) {
8370 /* if '& ident [' or '& ident ->', then ident address
8371 is not needed */
8372 t = tok;
8373 next();
8374 if (tok != '[' && tok != TOK_ARROW)
8375 add_var_ref(t);
8376 } else {
8377 level = 0;
8378 while (tok != '}' && tok != ';' &&
8379 !((tok == ',' || tok == ')') && level == 0)) {
8380 if (tok >= TOK_UIDENT) {
8381 add_var_ref(tok);
8382 } else if (tok == '(') {
8383 level++;
8384 } else if (tok == ')') {
8385 level--;
8387 next();
8390 } else {
8391 next();
8395 #endif
8397 /* parse an old style function declaration list */
8398 /* XXX: check multiple parameter */
8399 static void func_decl_list(Sym *func_sym)
8401 AttributeDef ad;
8402 int v;
8403 Sym *s;
8404 CType btype, type;
8406 /* parse each declaration */
8407 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8408 if (!parse_btype(&btype, &ad))
8409 expect("declaration list");
8410 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8411 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8412 tok == ';') {
8413 /* we accept no variable after */
8414 } else {
8415 for(;;) {
8416 type = btype;
8417 type_decl(&type, &ad, &v, TYPE_DIRECT);
8418 /* find parameter in function parameter list */
8419 s = func_sym->next;
8420 while (s != NULL) {
8421 if ((s->v & ~SYM_FIELD) == v)
8422 goto found;
8423 s = s->next;
8425 error("declaration for parameter '%s' but no such parameter",
8426 get_tok_str(v, NULL));
8427 found:
8428 /* check that no storage specifier except 'register' was given */
8429 if (type.t & VT_STORAGE)
8430 error("storage class specified for '%s'", get_tok_str(v, NULL));
8431 convert_parameter_type(&type);
8432 /* we can add the type (NOTE: it could be local to the function) */
8433 s->type = type;
8434 /* accept other parameters */
8435 if (tok == ',')
8436 next();
8437 else
8438 break;
8441 skip(';');
8445 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8446 static void decl(int l)
8448 int v, has_init, r;
8449 CType type, btype;
8450 Sym *sym;
8451 AttributeDef ad;
8453 while (1) {
8454 if (!parse_btype(&btype, &ad)) {
8455 /* skip redundant ';' */
8456 /* XXX: find more elegant solution */
8457 if (tok == ';') {
8458 next();
8459 continue;
8461 /* special test for old K&R protos without explicit int
8462 type. Only accepted when defining global data */
8463 if (l == VT_LOCAL || tok < TOK_DEFINE)
8464 break;
8465 btype.t = VT_INT;
8467 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8468 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8469 tok == ';') {
8470 /* we accept no variable after */
8471 next();
8472 continue;
8474 while (1) { /* iterate thru each declaration */
8475 type = btype;
8476 type_decl(&type, &ad, &v, TYPE_DIRECT);
8477 #if 0
8479 char buf[500];
8480 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8481 printf("type = '%s'\n", buf);
8483 #endif
8484 if ((type.t & VT_BTYPE) == VT_FUNC) {
8485 /* if old style function prototype, we accept a
8486 declaration list */
8487 sym = type.ref;
8488 if (sym->c == FUNC_OLD)
8489 func_decl_list(sym);
8492 if (tok == '{') {
8493 #ifdef CONFIG_REG_VARS
8494 TokenString func_str;
8495 ParseState saved_parse_state;
8496 int block_level;
8497 #endif
8499 if (l == VT_LOCAL)
8500 error("cannot use local functions");
8501 if (!(type.t & VT_FUNC))
8502 expect("function definition");
8503 /* XXX: cannot do better now: convert extern line to static inline */
8504 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8505 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8507 #ifdef CONFIG_REG_VARS
8508 /* parse all function code and record it */
8510 tok_str_new(&func_str);
8512 block_level = 0;
8513 for(;;) {
8514 int t;
8515 if (tok == -1)
8516 error("unexpected end of file");
8517 tok_str_add_tok(&func_str);
8518 t = tok;
8519 next();
8520 if (t == '{') {
8521 block_level++;
8522 } else if (t == '}') {
8523 block_level--;
8524 if (block_level == 0)
8525 break;
8528 tok_str_add(&func_str, -1);
8529 tok_str_add(&func_str, 0);
8531 save_parse_state(&saved_parse_state);
8533 macro_ptr = func_str.str;
8534 next();
8535 analyse_function();
8536 #endif
8538 /* compute text section */
8539 cur_text_section = ad.section;
8540 if (!cur_text_section)
8541 cur_text_section = text_section;
8542 ind = cur_text_section->data_offset;
8543 funcname = get_tok_str(v, NULL);
8544 sym = sym_find(v);
8545 if (sym) {
8546 /* if symbol is already defined, then put complete type */
8547 sym->type = type;
8548 } else {
8549 /* put function symbol */
8550 sym = global_identifier_push(v, type.t, 0);
8551 sym->type.ref = type.ref;
8553 /* NOTE: we patch the symbol size later */
8554 put_extern_sym(sym, cur_text_section, ind, 0);
8555 func_ind = ind;
8556 sym->r = VT_SYM | VT_CONST;
8557 /* put debug symbol */
8558 if (do_debug)
8559 put_func_debug(sym);
8560 /* push a dummy symbol to enable local sym storage */
8561 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8562 gfunc_prolog(&type);
8563 loc = 0;
8564 rsym = 0;
8565 #ifdef CONFIG_REG_VARS
8566 macro_ptr = func_str.str;
8567 next();
8568 #endif
8569 block(NULL, NULL, NULL, NULL, 0, 0);
8570 gsym(rsym);
8571 gfunc_epilog();
8572 cur_text_section->data_offset = ind;
8573 label_pop(&global_label_stack, NULL);
8574 sym_pop(&local_stack, NULL); /* reset local stack */
8575 /* end of function */
8576 /* patch symbol size */
8577 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8578 ind - func_ind;
8579 if (do_debug) {
8580 put_stabn(N_FUN, 0, 0, ind - func_ind);
8582 funcname = ""; /* for safety */
8583 func_vt.t = VT_VOID; /* for safety */
8584 ind = 0; /* for safety */
8586 #ifdef CONFIG_REG_VARS
8587 tok_str_free(func_str.str);
8588 restore_parse_state(&saved_parse_state);
8589 #endif
8590 break;
8591 } else {
8592 if (btype.t & VT_TYPEDEF) {
8593 /* save typedefed type */
8594 /* XXX: test storage specifiers ? */
8595 sym = sym_push(v, &type, 0, 0);
8596 sym->type.t |= VT_TYPEDEF;
8597 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8598 /* external function definition */
8599 external_sym(v, &type, 0);
8600 } else {
8601 /* not lvalue if array */
8602 r = 0;
8603 if (!(type.t & VT_ARRAY))
8604 r |= lvalue_type(type.t);
8605 has_init = (tok == '=');
8606 if ((btype.t & VT_EXTERN) ||
8607 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8608 !has_init && l == VT_CONST && type.ref->c < 0)) {
8609 /* external variable */
8610 /* NOTE: as GCC, uninitialized global static
8611 arrays of null size are considered as
8612 extern */
8613 external_sym(v, &type, r);
8614 } else {
8615 if (type.t & VT_STATIC)
8616 r |= VT_CONST;
8617 else
8618 r |= l;
8619 if (has_init)
8620 next();
8621 decl_initializer_alloc(&type, &ad, r,
8622 has_init, v, l);
8625 if (tok != ',') {
8626 skip(';');
8627 break;
8629 next();
8635 /* better than nothing, but needs extension to handle '-E' option
8636 correctly too */
8637 static void preprocess_init(TCCState *s1)
8639 s1->include_stack_ptr = s1->include_stack;
8640 /* XXX: move that before to avoid having to initialize
8641 file->ifdef_stack_ptr ? */
8642 s1->ifdef_stack_ptr = s1->ifdef_stack;
8643 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8645 /* XXX: not ANSI compliant: bound checking says error */
8646 vtop = vstack - 1;
8649 /* compile the C file opened in 'file'. Return non zero if errors. */
8650 static int tcc_compile(TCCState *s1)
8652 Sym *define_start;
8653 char buf[512];
8654 volatile int section_sym;
8656 #ifdef INC_DEBUG
8657 printf("%s: **** new file\n", file->filename);
8658 #endif
8659 preprocess_init(s1);
8661 funcname = "";
8662 anon_sym = SYM_FIRST_ANOM;
8664 /* file info: full path + filename */
8665 section_sym = 0; /* avoid warning */
8666 if (do_debug) {
8667 section_sym = put_elf_sym(symtab_section, 0, 0,
8668 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8669 text_section->sh_num, NULL);
8670 getcwd(buf, sizeof(buf));
8671 pstrcat(buf, sizeof(buf), "/");
8672 put_stabs_r(buf, N_SO, 0, 0,
8673 text_section->data_offset, text_section, section_sym);
8674 put_stabs_r(file->filename, N_SO, 0, 0,
8675 text_section->data_offset, text_section, section_sym);
8677 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8678 symbols can be safely used */
8679 put_elf_sym(symtab_section, 0, 0,
8680 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8681 SHN_ABS, file->filename);
8683 /* define some often used types */
8684 int_type.t = VT_INT;
8686 char_pointer_type.t = VT_BYTE;
8687 mk_pointer(&char_pointer_type);
8689 func_old_type.t = VT_FUNC;
8690 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8692 #if 0
8693 /* define 'void *alloca(unsigned int)' builtin function */
8695 Sym *s1;
8697 p = anon_sym++;
8698 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8699 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8700 s1->next = NULL;
8701 sym->next = s1;
8702 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8704 #endif
8706 define_start = define_stack;
8708 if (setjmp(s1->error_jmp_buf) == 0) {
8709 s1->nb_errors = 0;
8710 s1->error_set_jmp_enabled = 1;
8712 ch = file->buf_ptr[0];
8713 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8714 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8715 next();
8716 decl(VT_CONST);
8717 if (tok != TOK_EOF)
8718 expect("declaration");
8720 /* end of translation unit info */
8721 if (do_debug) {
8722 put_stabs_r(NULL, N_SO, 0, 0,
8723 text_section->data_offset, text_section, section_sym);
8726 s1->error_set_jmp_enabled = 0;
8728 /* reset define stack, but leave -Dsymbols (may be incorrect if
8729 they are undefined) */
8730 free_defines(define_start);
8732 sym_pop(&global_stack, NULL);
8734 return s1->nb_errors != 0 ? -1 : 0;
8737 #ifdef LIBTCC
8738 int tcc_compile_string(TCCState *s, const char *str)
8740 BufferedFile bf1, *bf = &bf1;
8741 int ret, len;
8742 char *buf;
8744 /* init file structure */
8745 bf->fd = -1;
8746 /* XXX: avoid copying */
8747 len = strlen(str);
8748 buf = tcc_malloc(len + 1);
8749 if (!buf)
8750 return -1;
8751 memcpy(buf, str, len);
8752 buf[len] = CH_EOB;
8753 bf->buf_ptr = buf;
8754 bf->buf_end = buf + len;
8755 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8756 bf->line_num = 1;
8757 file = bf;
8759 ret = tcc_compile(s);
8761 tcc_free(buf);
8763 /* currently, no need to close */
8764 return ret;
8766 #endif
8768 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8769 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8771 BufferedFile bf1, *bf = &bf1;
8773 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8774 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8775 /* default value */
8776 if (!value)
8777 value = "1";
8778 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8780 /* init file structure */
8781 bf->fd = -1;
8782 bf->buf_ptr = bf->buffer;
8783 bf->buf_end = bf->buffer + strlen(bf->buffer);
8784 *bf->buf_end = CH_EOB;
8785 bf->filename[0] = '\0';
8786 bf->line_num = 1;
8787 file = bf;
8789 s1->include_stack_ptr = s1->include_stack;
8791 /* parse with define parser */
8792 ch = file->buf_ptr[0];
8793 next_nomacro();
8794 parse_define();
8795 file = NULL;
8798 /* undefine a preprocessor symbol */
8799 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8801 TokenSym *ts;
8802 Sym *s;
8803 ts = tok_alloc(sym, strlen(sym));
8804 s = define_find(ts->tok);
8805 /* undefine symbol by putting an invalid name */
8806 if (s)
8807 define_undef(s);
8810 #ifdef CONFIG_TCC_ASM
8812 #include "i386-asm.c"
8813 #include "tccasm.c"
8815 #else
8816 static void asm_instr(void)
8818 error("inline asm() not supported");
8820 #endif
8822 #include "tccelf.c"
8824 /* print the position in the source file of PC value 'pc' by reading
8825 the stabs debug information */
8826 static void rt_printline(unsigned long wanted_pc)
8828 Stab_Sym *sym, *sym_end;
8829 char func_name[128], last_func_name[128];
8830 unsigned long func_addr, last_pc, pc;
8831 const char *incl_files[INCLUDE_STACK_SIZE];
8832 int incl_index, len, last_line_num, i;
8833 const char *str, *p;
8835 fprintf(stderr, "0x%08lx:", wanted_pc);
8837 func_name[0] = '\0';
8838 func_addr = 0;
8839 incl_index = 0;
8840 last_func_name[0] = '\0';
8841 last_pc = 0xffffffff;
8842 last_line_num = 1;
8843 sym = (Stab_Sym *)stab_section->data + 1;
8844 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
8845 while (sym < sym_end) {
8846 switch(sym->n_type) {
8847 /* function start or end */
8848 case N_FUN:
8849 if (sym->n_strx == 0) {
8850 /* we test if between last line and end of function */
8851 pc = sym->n_value + func_addr;
8852 if (wanted_pc >= last_pc && wanted_pc < pc)
8853 goto found;
8854 func_name[0] = '\0';
8855 func_addr = 0;
8856 } else {
8857 str = stabstr_section->data + sym->n_strx;
8858 p = strchr(str, ':');
8859 if (!p) {
8860 pstrcpy(func_name, sizeof(func_name), str);
8861 } else {
8862 len = p - str;
8863 if (len > sizeof(func_name) - 1)
8864 len = sizeof(func_name) - 1;
8865 memcpy(func_name, str, len);
8866 func_name[len] = '\0';
8868 func_addr = sym->n_value;
8870 break;
8871 /* line number info */
8872 case N_SLINE:
8873 pc = sym->n_value + func_addr;
8874 if (wanted_pc >= last_pc && wanted_pc < pc)
8875 goto found;
8876 last_pc = pc;
8877 last_line_num = sym->n_desc;
8878 /* XXX: slow! */
8879 strcpy(last_func_name, func_name);
8880 break;
8881 /* include files */
8882 case N_BINCL:
8883 str = stabstr_section->data + sym->n_strx;
8884 add_incl:
8885 if (incl_index < INCLUDE_STACK_SIZE) {
8886 incl_files[incl_index++] = str;
8888 break;
8889 case N_EINCL:
8890 if (incl_index > 1)
8891 incl_index--;
8892 break;
8893 case N_SO:
8894 if (sym->n_strx == 0) {
8895 incl_index = 0; /* end of translation unit */
8896 } else {
8897 str = stabstr_section->data + sym->n_strx;
8898 /* do not add path */
8899 len = strlen(str);
8900 if (len > 0 && str[len - 1] != '/')
8901 goto add_incl;
8903 break;
8905 sym++;
8908 /* second pass: we try symtab symbols (no line number info) */
8909 incl_index = 0;
8911 Elf32_Sym *sym, *sym_end;
8912 int type;
8914 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
8915 for(sym = (Elf32_Sym *)symtab_section->data + 1;
8916 sym < sym_end;
8917 sym++) {
8918 type = ELF32_ST_TYPE(sym->st_info);
8919 if (type == STT_FUNC) {
8920 if (wanted_pc >= sym->st_value &&
8921 wanted_pc < sym->st_value + sym->st_size) {
8922 pstrcpy(last_func_name, sizeof(last_func_name),
8923 strtab_section->data + sym->st_name);
8924 goto found;
8929 /* did not find any info: */
8930 fprintf(stderr, " ???\n");
8931 return;
8932 found:
8933 if (last_func_name[0] != '\0') {
8934 fprintf(stderr, " %s()", last_func_name);
8936 if (incl_index > 0) {
8937 fprintf(stderr, " (%s:%d",
8938 incl_files[incl_index - 1], last_line_num);
8939 for(i = incl_index - 2; i >= 0; i--)
8940 fprintf(stderr, ", included from %s", incl_files[i]);
8941 fprintf(stderr, ")");
8943 fprintf(stderr, "\n");
8946 #ifndef WIN32
8948 #ifdef __i386__
8950 /* fix for glibc 2.1 */
8951 #ifndef REG_EIP
8952 #define REG_EIP EIP
8953 #define REG_EBP EBP
8954 #endif
8956 /* return the PC at frame level 'level'. Return non zero if not found */
8957 static int rt_get_caller_pc(unsigned long *paddr,
8958 ucontext_t *uc, int level)
8960 unsigned long fp;
8961 int i;
8963 if (level == 0) {
8964 #ifdef __FreeBSD__
8965 *paddr = uc->uc_mcontext.mc_eip;
8966 #else
8967 *paddr = uc->uc_mcontext.gregs[REG_EIP];
8968 #endif
8969 return 0;
8970 } else {
8971 #ifdef __FreeBSD__
8972 fp = uc->uc_mcontext.mc_ebp;
8973 #else
8974 fp = uc->uc_mcontext.gregs[REG_EBP];
8975 #endif
8976 for(i=1;i<level;i++) {
8977 /* XXX: check address validity with program info */
8978 if (fp <= 0x1000 || fp >= 0xc0000000)
8979 return -1;
8980 fp = ((unsigned long *)fp)[0];
8982 *paddr = ((unsigned long *)fp)[1];
8983 return 0;
8986 #else
8987 #error add arch specific rt_get_caller_pc()
8988 #endif
8990 /* emit a run time error at position 'pc' */
8991 void rt_error(ucontext_t *uc, const char *fmt, ...)
8993 va_list ap;
8994 unsigned long pc;
8995 int i;
8997 va_start(ap, fmt);
8998 fprintf(stderr, "Runtime error: ");
8999 vfprintf(stderr, fmt, ap);
9000 fprintf(stderr, "\n");
9001 for(i=0;i<num_callers;i++) {
9002 if (rt_get_caller_pc(&pc, uc, i) < 0)
9003 break;
9004 if (i == 0)
9005 fprintf(stderr, "at ");
9006 else
9007 fprintf(stderr, "by ");
9008 rt_printline(pc);
9010 exit(255);
9011 va_end(ap);
9014 /* signal handler for fatal errors */
9015 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9017 ucontext_t *uc = puc;
9019 switch(signum) {
9020 case SIGFPE:
9021 switch(siginf->si_code) {
9022 case FPE_INTDIV:
9023 case FPE_FLTDIV:
9024 rt_error(uc, "division by zero");
9025 break;
9026 default:
9027 rt_error(uc, "floating point exception");
9028 break;
9030 break;
9031 case SIGBUS:
9032 case SIGSEGV:
9033 if (rt_bound_error_msg && *rt_bound_error_msg)
9034 rt_error(uc, *rt_bound_error_msg);
9035 else
9036 rt_error(uc, "dereferencing invalid pointer");
9037 break;
9038 case SIGILL:
9039 rt_error(uc, "illegal instruction");
9040 break;
9041 case SIGABRT:
9042 rt_error(uc, "abort() called");
9043 break;
9044 default:
9045 rt_error(uc, "caught signal %d", signum);
9046 break;
9048 exit(255);
9050 #endif
9052 /* do all relocations (needed before using tcc_get_symbol()) */
9053 int tcc_relocate(TCCState *s1)
9055 Section *s;
9056 int i;
9058 s1->nb_errors = 0;
9060 tcc_add_runtime(s1);
9062 relocate_common_syms();
9064 /* compute relocation address : section are relocated in place. We
9065 also alloc the bss space */
9066 for(i = 1; i < s1->nb_sections; i++) {
9067 s = s1->sections[i];
9068 if (s->sh_flags & SHF_ALLOC) {
9069 if (s->sh_type == SHT_NOBITS)
9070 s->data = tcc_mallocz(s->data_offset);
9071 s->sh_addr = (unsigned long)s->data;
9075 relocate_syms(s1, 1);
9077 if (s1->nb_errors != 0)
9078 return -1;
9080 /* relocate each section */
9081 for(i = 1; i < s1->nb_sections; i++) {
9082 s = s1->sections[i];
9083 if (s->reloc)
9084 relocate_section(s1, s);
9086 return 0;
9089 /* launch the compiled program with the given arguments */
9090 int tcc_run(TCCState *s1, int argc, char **argv)
9092 int (*prog_main)(int, char **);
9094 if (tcc_relocate(s1) < 0)
9095 return -1;
9097 prog_main = tcc_get_symbol(s1, "main");
9099 if (do_debug) {
9100 #ifdef WIN32
9101 error("debug mode currently not available for Windows");
9102 #else
9103 struct sigaction sigact;
9104 /* install TCC signal handlers to print debug info on fatal
9105 runtime errors */
9106 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9107 sigact.sa_sigaction = sig_error;
9108 sigemptyset(&sigact.sa_mask);
9109 sigaction(SIGFPE, &sigact, NULL);
9110 sigaction(SIGILL, &sigact, NULL);
9111 sigaction(SIGSEGV, &sigact, NULL);
9112 sigaction(SIGBUS, &sigact, NULL);
9113 sigaction(SIGABRT, &sigact, NULL);
9114 #endif
9117 #ifdef CONFIG_TCC_BCHECK
9118 if (do_bounds_check) {
9119 void (*bound_init)(void);
9121 /* set error function */
9122 rt_bound_error_msg = (void *)tcc_get_symbol(s1, "__bound_error_msg");
9124 /* XXX: use .init section so that it also work in binary ? */
9125 bound_init = (void *)tcc_get_symbol(s1, "__bound_init");
9126 bound_init();
9128 #endif
9129 return (*prog_main)(argc, argv);
9132 TCCState *tcc_new(void)
9134 const char *p, *r;
9135 TCCState *s;
9136 TokenSym *ts;
9137 int i, c;
9139 s = tcc_mallocz(sizeof(TCCState));
9140 if (!s)
9141 return NULL;
9142 tcc_state = s;
9143 s->output_type = TCC_OUTPUT_MEMORY;
9145 /* init isid table */
9146 for(i=0;i<256;i++)
9147 isidnum_table[i] = isid(i) || isnum(i);
9149 /* add all tokens */
9150 table_ident = NULL;
9151 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9153 tok_ident = TOK_IDENT;
9154 p = tcc_keywords;
9155 while (*p) {
9156 r = p;
9157 for(;;) {
9158 c = *r++;
9159 if (c == '\0')
9160 break;
9162 ts = tok_alloc(p, r - p - 1);
9163 p = r;
9166 /* we add dummy defines for some special macros to speed up tests
9167 and to have working defined() */
9168 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9169 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9170 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9171 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9173 /* standard defines */
9174 tcc_define_symbol(s, "__STDC__", NULL);
9175 #if defined(TCC_TARGET_I386)
9176 tcc_define_symbol(s, "__i386__", NULL);
9177 #endif
9178 #if defined(linux)
9179 tcc_define_symbol(s, "__linux__", NULL);
9180 tcc_define_symbol(s, "linux", NULL);
9181 #endif
9182 /* tiny C specific defines */
9183 tcc_define_symbol(s, "__TINYC__", NULL);
9185 /* tiny C & gcc defines */
9186 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9187 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9188 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9190 /* default library paths */
9191 tcc_add_library_path(s, "/usr/local/lib");
9192 tcc_add_library_path(s, "/usr/lib");
9193 tcc_add_library_path(s, "/lib");
9195 /* no section zero */
9196 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9198 /* create standard sections */
9199 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9200 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9201 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9203 /* symbols are always generated for linking stage */
9204 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9205 ".strtab",
9206 ".hashtab", SHF_PRIVATE);
9207 strtab_section = symtab_section->link;
9209 /* private symbol table for dynamic symbols */
9210 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9211 ".dynstrtab",
9212 ".dynhashtab", SHF_PRIVATE);
9213 s->alacarte_link = 1;
9214 return s;
9217 void tcc_delete(TCCState *s1)
9219 int i, n;
9221 /* free -D defines */
9222 free_defines(NULL);
9224 /* free tokens */
9225 n = tok_ident - TOK_IDENT;
9226 for(i = 0; i < n; i++)
9227 tcc_free(table_ident[i]);
9228 tcc_free(table_ident);
9230 /* free all sections */
9232 free_section(symtab_section->hash);
9234 free_section(s1->dynsymtab_section->hash);
9235 free_section(s1->dynsymtab_section->link);
9236 free_section(s1->dynsymtab_section);
9238 for(i = 1; i < s1->nb_sections; i++)
9239 free_section(s1->sections[i]);
9240 tcc_free(s1->sections);
9242 /* free loaded dlls array */
9243 for(i = 0; i < s1->nb_loaded_dlls; i++)
9244 tcc_free(s1->loaded_dlls[i]);
9245 tcc_free(s1->loaded_dlls);
9247 /* library paths */
9248 for(i = 0; i < s1->nb_library_paths; i++)
9249 tcc_free(s1->library_paths[i]);
9250 tcc_free(s1->library_paths);
9252 /* cached includes */
9253 for(i = 0; i < s1->nb_cached_includes; i++)
9254 tcc_free(s1->cached_includes[i]);
9255 tcc_free(s1->cached_includes);
9257 for(i = 0; i < s1->nb_include_paths; i++)
9258 tcc_free(s1->include_paths[i]);
9259 tcc_free(s1->include_paths);
9261 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9262 tcc_free(s1->sysinclude_paths[i]);
9263 tcc_free(s1->sysinclude_paths);
9265 tcc_free(s1);
9268 int tcc_add_include_path(TCCState *s1, const char *pathname)
9270 char *pathname1;
9272 pathname1 = tcc_strdup(pathname);
9273 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9274 return 0;
9277 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9279 char *pathname1;
9281 pathname1 = tcc_strdup(pathname);
9282 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9283 return 0;
9286 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9288 const char *ext, *filename1;
9289 Elf32_Ehdr ehdr;
9290 int fd, ret;
9291 BufferedFile *saved_file;
9293 /* find source file type with extension */
9294 filename1 = strrchr(filename, '/');
9295 if (filename1)
9296 filename1++;
9297 else
9298 filename1 = filename;
9299 ext = strrchr(filename1, '.');
9300 if (ext)
9301 ext++;
9303 /* open the file */
9304 saved_file = file;
9305 file = tcc_open(s1, filename);
9306 if (!file) {
9307 if (flags & AFF_PRINT_ERROR) {
9308 error_noabort("file '%s' not found", filename);
9310 ret = -1;
9311 goto fail1;
9314 if (!ext || !strcmp(ext, "c")) {
9315 /* C file assumed */
9316 ret = tcc_compile(s1);
9317 } else
9318 #ifdef CONFIG_TCC_ASM
9319 if (!strcmp(ext, "S")) {
9320 /* preprocessed assembler */
9321 ret = tcc_assemble(s1, 1);
9322 } else if (!strcmp(ext, "s")) {
9323 /* non preprocessed assembler */
9324 ret = tcc_assemble(s1, 0);
9325 } else
9326 #endif
9328 fd = file->fd;
9329 /* assume executable format: auto guess file type */
9330 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
9331 error_noabort("could not read header");
9332 goto fail;
9334 lseek(fd, 0, SEEK_SET);
9336 if (ehdr.e_ident[0] == ELFMAG0 &&
9337 ehdr.e_ident[1] == ELFMAG1 &&
9338 ehdr.e_ident[2] == ELFMAG2 &&
9339 ehdr.e_ident[3] == ELFMAG3) {
9340 file->line_num = 0; /* do not display line number if error */
9341 if (ehdr.e_type == ET_REL) {
9342 ret = tcc_load_object_file(s1, fd, 0);
9343 } else if (ehdr.e_type == ET_DYN) {
9344 ret = tcc_load_dll(s1, fd, filename,
9345 (flags & AFF_REFERENCED_DLL) != 0);
9346 } else {
9347 error_noabort("unrecognized ELF file");
9348 goto fail;
9350 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9351 file->line_num = 0; /* do not display line number if error */
9352 ret = tcc_load_archive(s1, fd);
9353 } else {
9354 /* as GNU ld, consider it is an ld script if not recognized */
9355 ret = tcc_load_ldscript(s1);
9356 if (ret < 0) {
9357 error_noabort("unrecognized file type");
9358 goto fail;
9362 the_end:
9363 tcc_close(file);
9364 fail1:
9365 file = saved_file;
9366 return ret;
9367 fail:
9368 ret = -1;
9369 goto the_end;
9372 int tcc_add_file(TCCState *s, const char *filename)
9374 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9377 int tcc_add_library_path(TCCState *s, const char *pathname)
9379 char *pathname1;
9381 pathname1 = tcc_strdup(pathname);
9382 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9383 return 0;
9386 /* find and load a dll. Return non zero if not found */
9387 /* XXX: add '-rpath' option support ? */
9388 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9390 char buf[1024];
9391 int i;
9393 for(i = 0; i < s->nb_library_paths; i++) {
9394 snprintf(buf, sizeof(buf), "%s/%s",
9395 s->library_paths[i], filename);
9396 if (tcc_add_file_internal(s, buf, flags) == 0)
9397 return 0;
9399 return -1;
9402 /* the library name is the same as the argument of the '-l' option */
9403 int tcc_add_library(TCCState *s, const char *libraryname)
9405 char buf[1024];
9406 int i;
9407 void *h;
9409 /* first we look for the dynamic library if not static linking */
9410 if (!s->static_link) {
9411 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9412 /* if we output to memory, then we simply we dlopen(). */
9413 if (s->output_type == TCC_OUTPUT_MEMORY) {
9414 /* Since the libc is already loaded, we don't need to load it again */
9415 if (!strcmp(libraryname, "c"))
9416 return 0;
9417 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
9418 if (h)
9419 return 0;
9420 } else {
9421 if (tcc_add_dll(s, buf, 0) == 0)
9422 return 0;
9426 /* then we look for the static library */
9427 for(i = 0; i < s->nb_library_paths; i++) {
9428 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9429 s->library_paths[i], libraryname);
9430 if (tcc_add_file_internal(s, buf, 0) == 0)
9431 return 0;
9433 return -1;
9436 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9438 add_elf_sym(symtab_section, val, 0,
9439 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9440 SHN_ABS, name);
9441 return 0;
9444 int tcc_set_output_type(TCCState *s, int output_type)
9446 char buf[1024];
9448 s->output_type = output_type;
9450 if (!s->nostdinc) {
9451 /* default include paths */
9452 /* XXX: reverse order needed if -isystem support */
9453 tcc_add_sysinclude_path(s, "/usr/local/include");
9454 tcc_add_sysinclude_path(s, "/usr/include");
9455 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9456 tcc_add_sysinclude_path(s, buf);
9459 /* if bound checking, then add corresponding sections */
9460 #ifdef CONFIG_TCC_BCHECK
9461 if (do_bounds_check) {
9462 /* define symbol */
9463 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9464 /* create bounds sections */
9465 bounds_section = new_section(s, ".bounds",
9466 SHT_PROGBITS, SHF_ALLOC);
9467 lbounds_section = new_section(s, ".lbounds",
9468 SHT_PROGBITS, SHF_ALLOC);
9470 #endif
9472 /* add debug sections */
9473 if (do_debug) {
9474 /* stab symbols */
9475 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9476 stab_section->sh_entsize = sizeof(Stab_Sym);
9477 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9478 put_elf_str(stabstr_section, "");
9479 stab_section->link = stabstr_section;
9480 /* put first entry */
9481 put_stabs("", 0, 0, 0, 0);
9484 /* add libc crt1/crti objects */
9485 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9486 !s->nostdlib) {
9487 if (output_type != TCC_OUTPUT_DLL)
9488 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9489 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9491 return 0;
9494 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9496 typedef struct WarningDef {
9497 int offset;
9498 int flags;
9499 const char *name;
9500 } WarningDef;
9502 static const WarningDef warning_defs[] = {
9503 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9504 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9505 { offsetof(TCCState, warn_error), 0, "error" },
9508 /* set/reset a warning */
9509 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9511 int i;
9512 const WarningDef *p;
9513 if (!strcmp(warning_name, "all")) {
9514 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9515 if (p->flags & WD_ALL)
9516 *(int *)((uint8_t *)s + p->offset) = 1;
9518 } else {
9519 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9520 if (!strcmp(warning_name, p->name))
9521 goto found;
9523 return -1;
9524 found:
9525 *(int *)((uint8_t *)s + p->offset) = value;
9527 return 0;
9531 #if !defined(LIBTCC)
9533 /* extract the basename of a file */
9534 static const char *tcc_basename(const char *name)
9536 const char *p;
9537 p = strrchr(name, '/');
9538 #ifdef WIN32
9539 if (!p)
9540 p = strrchr(name, '\\');
9541 #endif
9542 if (!p)
9543 p = name;
9544 else
9545 p++;
9546 return p;
9549 static int64_t getclock_us(void)
9551 #ifdef WIN32
9552 struct _timeb tb;
9553 _ftime(&tb);
9554 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9555 #else
9556 struct timeval tv;
9557 gettimeofday(&tv, NULL);
9558 return tv.tv_sec * 1000000LL + tv.tv_usec;
9559 #endif
9562 void help(void)
9564 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2003 Fabrice Bellard\n"
9565 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9566 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9567 " [infile1 infile2...] [-run infile args...]\n"
9568 "\n"
9569 "General options:\n"
9570 " -v display current version\n"
9571 " -c compile only - generate an object file\n"
9572 " -o outfile set output filename\n"
9573 " -Bdir set tcc internal library path\n"
9574 " -bench output compilation statistics\n"
9575 " -run run compiled source\n"
9576 " -Wwarning set or reset (with 'no-' prefix) 'warning'\n"
9577 "Preprocessor options:\n"
9578 " -Idir add include path 'dir'\n"
9579 " -Dsym[=val] define 'sym' with value 'val'\n"
9580 " -Usym undefine 'sym'\n"
9581 "Linker options:\n"
9582 " -Ldir add library path 'dir'\n"
9583 " -llib link with dynamic or static library 'lib'\n"
9584 " -shared generate a shared library\n"
9585 " -static static linking\n"
9586 " -r relocatable output\n"
9587 "Debugger options:\n"
9588 " -g generate runtime debug info\n"
9589 #ifdef CONFIG_TCC_BCHECK
9590 " -b compile with built-in memory and bounds checker (implies -g)\n"
9591 #endif
9592 " -bt N show N callers in stack traces\n"
9596 #define TCC_OPTION_HAS_ARG 0x0001
9597 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9599 typedef struct TCCOption {
9600 const char *name;
9601 uint16_t index;
9602 uint16_t flags;
9603 } TCCOption;
9605 enum {
9606 TCC_OPTION_HELP,
9607 TCC_OPTION_I,
9608 TCC_OPTION_D,
9609 TCC_OPTION_U,
9610 TCC_OPTION_L,
9611 TCC_OPTION_B,
9612 TCC_OPTION_l,
9613 TCC_OPTION_bench,
9614 TCC_OPTION_bt,
9615 TCC_OPTION_b,
9616 TCC_OPTION_g,
9617 TCC_OPTION_c,
9618 TCC_OPTION_static,
9619 TCC_OPTION_shared,
9620 TCC_OPTION_o,
9621 TCC_OPTION_r,
9622 TCC_OPTION_W,
9623 TCC_OPTION_O,
9624 TCC_OPTION_m,
9625 TCC_OPTION_f,
9626 TCC_OPTION_nostdinc,
9627 TCC_OPTION_nostdlib,
9628 TCC_OPTION_print_search_dirs,
9629 TCC_OPTION_rdynamic,
9630 TCC_OPTION_run,
9631 TCC_OPTION_v,
9634 static const TCCOption tcc_options[] = {
9635 { "h", TCC_OPTION_HELP, 0 },
9636 { "?", TCC_OPTION_HELP, 0 },
9637 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9638 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9639 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9640 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9641 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9642 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9643 { "bench", TCC_OPTION_bench, 0 },
9644 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9645 #ifdef CONFIG_TCC_BCHECK
9646 { "b", TCC_OPTION_b, 0 },
9647 #endif
9648 { "g", TCC_OPTION_g, 0 },
9649 { "c", TCC_OPTION_c, 0 },
9650 { "static", TCC_OPTION_static, 0 },
9651 { "shared", TCC_OPTION_shared, 0 },
9652 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9653 { "run", TCC_OPTION_run, 0 },
9654 { "rdynamic", TCC_OPTION_rdynamic, 0 }, /* currently ignored */
9655 { "r", TCC_OPTION_r, 0 },
9656 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9657 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9658 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9659 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9660 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9661 { "nostdlib", TCC_OPTION_nostdlib, 0 },
9662 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9663 { "v", TCC_OPTION_v, 0 },
9664 { NULL },
9667 int main(int argc, char **argv)
9669 char *r;
9670 int optind, output_type, multiple_files, i, reloc_output;
9671 TCCState *s;
9672 char **files;
9673 int nb_files, nb_libraries, nb_objfiles, dminus, ret;
9674 char objfilename[1024];
9675 int64_t start_time = 0;
9676 const TCCOption *popt;
9677 const char *optarg, *p1, *r1, *outfile;
9678 int print_search_dirs;
9680 s = tcc_new();
9681 output_type = TCC_OUTPUT_EXE;
9683 optind = 1;
9684 outfile = NULL;
9685 multiple_files = 1;
9686 dminus = 0;
9687 files = NULL;
9688 nb_files = 0;
9689 nb_libraries = 0;
9690 reloc_output = 0;
9691 print_search_dirs = 0;
9692 while (1) {
9693 if (optind >= argc) {
9694 if (nb_files == 0 && !print_search_dirs)
9695 goto show_help;
9696 else
9697 break;
9699 r = argv[optind++];
9700 if (r[0] != '-') {
9701 /* add a new file */
9702 dynarray_add((void ***)&files, &nb_files, r);
9703 if (!multiple_files) {
9704 optind--;
9705 /* argv[0] will be this file */
9706 break;
9708 } else {
9709 /* find option in table (match only the first chars */
9710 popt = tcc_options;
9711 for(;;) {
9712 p1 = popt->name;
9713 if (p1 == NULL)
9714 error("invalid option -- '%s'", r);
9715 r1 = r + 1;
9716 for(;;) {
9717 if (*p1 == '\0')
9718 goto option_found;
9719 if (*r1 != *p1)
9720 break;
9721 p1++;
9722 r1++;
9724 popt++;
9726 option_found:
9727 if (popt->flags & TCC_OPTION_HAS_ARG) {
9728 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
9729 optarg = r1;
9730 } else {
9731 if (optind >= argc)
9732 error("argument to '%s' is missing", r);
9733 optarg = argv[optind++];
9735 } else {
9736 if (*r1 != '\0')
9737 goto show_help;
9738 optarg = NULL;
9741 switch(popt->index) {
9742 case TCC_OPTION_HELP:
9743 show_help:
9744 help();
9745 return 1;
9746 case TCC_OPTION_I:
9747 if (tcc_add_include_path(s, optarg) < 0)
9748 error("too many include paths");
9749 break;
9750 case TCC_OPTION_D:
9752 char *sym, *value;
9753 sym = (char *)optarg;
9754 value = strchr(sym, '=');
9755 if (value) {
9756 *value = '\0';
9757 value++;
9759 tcc_define_symbol(s, sym, value);
9761 break;
9762 case TCC_OPTION_U:
9763 tcc_undefine_symbol(s, optarg);
9764 break;
9765 case TCC_OPTION_L:
9766 tcc_add_library_path(s, optarg);
9767 break;
9768 case TCC_OPTION_B:
9769 /* set tcc utilities path (mainly for tcc development) */
9770 tcc_lib_path = optarg;
9771 break;
9772 case TCC_OPTION_l:
9773 dynarray_add((void ***)&files, &nb_files, r);
9774 nb_libraries++;
9775 break;
9776 case TCC_OPTION_bench:
9777 do_bench = 1;
9778 break;
9779 case TCC_OPTION_bt:
9780 num_callers = atoi(optarg);
9781 break;
9782 #ifdef CONFIG_TCC_BCHECK
9783 case TCC_OPTION_b:
9784 do_bounds_check = 1;
9785 do_debug = 1;
9786 break;
9787 #endif
9788 case TCC_OPTION_g:
9789 do_debug = 1;
9790 break;
9791 case TCC_OPTION_c:
9792 multiple_files = 1;
9793 output_type = TCC_OUTPUT_OBJ;
9794 break;
9795 case TCC_OPTION_static:
9796 s->static_link = 1;
9797 break;
9798 case TCC_OPTION_shared:
9799 output_type = TCC_OUTPUT_DLL;
9800 break;
9801 case TCC_OPTION_o:
9802 multiple_files = 1;
9803 outfile = optarg;
9804 break;
9805 case TCC_OPTION_r:
9806 /* generate a .o merging several output files */
9807 reloc_output = 1;
9808 output_type = TCC_OUTPUT_OBJ;
9809 break;
9810 case TCC_OPTION_nostdinc:
9811 s->nostdinc = 1;
9812 break;
9813 case TCC_OPTION_nostdlib:
9814 s->nostdlib = 1;
9815 break;
9816 case TCC_OPTION_print_search_dirs:
9817 print_search_dirs = 1;
9818 break;
9819 case TCC_OPTION_run:
9820 multiple_files = 0;
9821 output_type = TCC_OUTPUT_MEMORY;
9822 break;
9823 case TCC_OPTION_v:
9824 printf("tcc version %s\n", TCC_VERSION);
9825 return 0;
9826 case TCC_OPTION_W:
9828 const char *p = optarg;
9829 int value;
9830 value = 1;
9831 if (p[0] == 'n' && p[1] == 'o' && p[2] == '-') {
9832 p += 2;
9833 value = 0;
9835 if (tcc_set_warning(s, p, value) < 0 && s->warn_unsupported)
9836 goto unsupported_option;
9838 break;
9839 default:
9840 if (s->warn_unsupported) {
9841 unsupported_option:
9842 warning("unsupported option '%s'", r);
9844 break;
9848 if (print_search_dirs) {
9849 /* enough for Linux kernel */
9850 printf("install: %s/\n", tcc_lib_path);
9851 return 0;
9854 nb_objfiles = nb_files - nb_libraries;
9856 /* if outfile provided without other options, we output an
9857 executable */
9858 if (outfile && output_type == TCC_OUTPUT_MEMORY)
9859 output_type = TCC_OUTPUT_EXE;
9861 /* check -c consistency : only single file handled. XXX: checks file type */
9862 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9863 /* accepts only a single input file */
9864 if (nb_objfiles != 1)
9865 error("cannot specify multiple files with -c");
9866 if (nb_libraries != 0)
9867 error("cannot specify libraries with -c");
9870 /* compute default outfile name */
9871 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
9872 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9873 char *ext;
9874 /* strip path */
9875 pstrcpy(objfilename, sizeof(objfilename) - 1,
9876 tcc_basename(files[0]));
9877 /* add .o extension */
9878 ext = strrchr(objfilename, '.');
9879 if (!ext)
9880 goto default_outfile;
9881 strcpy(ext + 1, "o");
9882 } else {
9883 default_outfile:
9884 pstrcpy(objfilename, sizeof(objfilename), "a.out");
9886 outfile = objfilename;
9889 if (do_bench) {
9890 start_time = getclock_us();
9893 tcc_set_output_type(s, output_type);
9895 /* compile or add each files or library */
9896 for(i = 0;i < nb_files; i++) {
9897 const char *filename;
9899 filename = files[i];
9900 if (filename[0] == '-') {
9901 if (tcc_add_library(s, filename + 2) < 0)
9902 error("cannot find %s", filename);
9903 } else {
9904 if (tcc_add_file(s, filename) < 0) {
9905 ret = 1;
9906 goto the_end;
9911 /* free all files */
9912 tcc_free(files);
9914 if (do_bench) {
9915 double total_time;
9916 total_time = (double)(getclock_us() - start_time) / 1000000.0;
9917 if (total_time < 0.001)
9918 total_time = 0.001;
9919 if (total_bytes < 1)
9920 total_bytes = 1;
9921 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
9922 tok_ident - TOK_IDENT, total_lines, total_bytes,
9923 total_time, (int)(total_lines / total_time),
9924 total_bytes / total_time / 1000000.0);
9927 if (s->output_type != TCC_OUTPUT_MEMORY) {
9928 tcc_output_file(s, outfile);
9929 ret = 0;
9930 } else {
9931 ret = tcc_run(s, argc - optind, argv + optind);
9933 the_end:
9934 /* XXX: cannot do it with bound checking because of the malloc hooks */
9935 if (!do_bounds_check)
9936 tcc_delete(s);
9938 #ifdef MEM_DEBUG
9939 if (do_bench) {
9940 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
9942 #endif
9943 return ret;
9946 #endif