PLT generation fix
[tinycc/miki.git] / tcc.c
blob9834fb35ef31c93d8c488ab4b2a3164e81b55245
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002 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 <stdlib.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <math.h>
27 #include <unistd.h>
28 #include <signal.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <setjmp.h>
32 #ifdef WIN32
33 #include <sys/timeb.h>
34 #endif
35 #ifndef WIN32
36 #include <sys/time.h>
37 #include <sys/ucontext.h>
38 #endif
39 #include "elf.h"
40 #include "stab.h"
41 #ifndef CONFIG_TCC_STATIC
42 #include <dlfcn.h>
43 #endif
45 #include "libtcc.h"
47 /* parser debug */
48 //#define PARSE_DEBUG
49 /* preprocessor debug */
50 //#define PP_DEBUG
51 /* include file debug */
52 //#define INC_DEBUG
54 //#define MEM_DEBUG
56 /* assembler debug */
57 //#define ASM_DEBUG
59 /* target selection */
60 //#define TCC_TARGET_I386 /* i386 code generator */
62 /* default target is I386 */
63 #if !defined(TCC_TARGET_I386)
64 #define TCC_TARGET_I386
65 #endif
67 #if !defined(WIN32) && !defined(TCC_UCLIBC)
68 #define CONFIG_TCC_BCHECK /* enable bound checking code */
69 #endif
71 /* define it to include assembler support */
72 #define CONFIG_TCC_ASM
74 #ifndef CONFIG_TCC_PREFIX
75 #define CONFIG_TCC_PREFIX "/usr/local"
76 #endif
78 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
79 executables or dlls */
80 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
82 #define INCLUDE_STACK_SIZE 32
83 #define IFDEF_STACK_SIZE 64
84 #define VSTACK_SIZE 64
85 #define STRING_MAX_SIZE 1024
87 #define TOK_HASH_SIZE 2048 /* must be a power of two */
88 #define TOK_ALLOC_INCR 512 /* must be a power of two */
89 #define TOK_STR_ALLOC_INCR_BITS 6
90 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
91 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
93 /* token symbol management */
94 typedef struct TokenSym {
95 struct TokenSym *hash_next;
96 struct Sym *sym_define; /* direct pointer to define */
97 struct Sym *sym_label; /* direct pointer to label */
98 struct Sym *sym_struct; /* direct pointer to structure */
99 struct Sym *sym_identifier; /* direct pointer to identifier */
100 int tok; /* token number */
101 int len;
102 char str[1];
103 } TokenSym;
105 typedef struct CString {
106 int size; /* size in bytes */
107 void *data; /* either 'char *' or 'int *' */
108 int size_allocated;
109 void *data_allocated; /* if non NULL, data has been malloced */
110 } CString;
112 /* type definition */
113 typedef struct CType {
114 int t;
115 struct Sym *ref;
116 } CType;
118 /* constant value */
119 typedef union CValue {
120 long double ld;
121 double d;
122 float f;
123 int i;
124 unsigned int ui;
125 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
126 long long ll;
127 unsigned long long ull;
128 struct CString *cstr;
129 void *ptr;
130 int tab[1];
131 } CValue;
133 /* value on stack */
134 typedef struct SValue {
135 CType type; /* type */
136 unsigned short r; /* register + flags */
137 unsigned short r2; /* second register, used for 'long long'
138 type. If not used, set to VT_CONST */
139 CValue c; /* constant, if VT_CONST */
140 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
141 } SValue;
143 /* symbol management */
144 typedef struct Sym {
145 int v; /* symbol token */
146 int r; /* associated register */
147 int c; /* associated number */
148 CType type; /* associated type */
149 struct Sym *next; /* next related symbol */
150 struct Sym *prev; /* prev symbol in stack */
151 struct Sym *prev_tok; /* previous symbol for this token */
152 } Sym;
154 /* section definition */
155 /* XXX: use directly ELF structure for parameters ? */
156 /* special flag to indicate that the section should not be linked to
157 the other ones */
158 #define SHF_PRIVATE 0x80000000
160 typedef struct Section {
161 unsigned long data_offset; /* current data offset */
162 unsigned char *data; /* section data */
163 unsigned long data_allocated; /* used for realloc() handling */
164 int sh_name; /* elf section name (only used during output) */
165 int sh_num; /* elf section number */
166 int sh_type; /* elf section type */
167 int sh_flags; /* elf section flags */
168 int sh_info; /* elf section info */
169 int sh_addralign; /* elf section alignment */
170 int sh_entsize; /* elf entry size */
171 unsigned long sh_size; /* section size (only used during output) */
172 unsigned long sh_addr; /* address at which the section is relocated */
173 unsigned long sh_offset; /* address at which the section is relocated */
174 int nb_hashed_syms; /* used to resize the hash table */
175 struct Section *link; /* link to another section */
176 struct Section *reloc; /* corresponding section for relocation, if any */
177 struct Section *hash; /* hash table for symbols */
178 struct Section *next;
179 char name[64]; /* section name */
180 } Section;
182 typedef struct DLLReference {
183 int level;
184 char name[1];
185 } DLLReference;
187 /* GNUC attribute definition */
188 typedef struct AttributeDef {
189 int aligned;
190 Section *section;
191 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
192 } AttributeDef;
194 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
195 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
196 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
198 /* stored in 'Sym.c' field */
199 #define FUNC_NEW 1 /* ansi function prototype */
200 #define FUNC_OLD 2 /* old function prototype */
201 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
203 /* stored in 'Sym.r' field */
204 #define FUNC_CDECL 0 /* standard c call */
205 #define FUNC_STDCALL 1 /* pascal c call */
207 /* field 'Sym.t' for macros */
208 #define MACRO_OBJ 0 /* object like macro */
209 #define MACRO_FUNC 1 /* function like macro */
211 /* field 'Sym.r' for C labels */
212 #define LABEL_DEFINED 0 /* label is defined */
213 #define LABEL_FORWARD 1 /* label is forward defined */
214 #define LABEL_DECLARED 2 /* label is declared but never used */
216 /* type_decl() types */
217 #define TYPE_ABSTRACT 1 /* type without variable */
218 #define TYPE_DIRECT 2 /* type with variable */
220 #define IO_BUF_SIZE 8192
222 typedef struct BufferedFile {
223 uint8_t *buf_ptr;
224 uint8_t *buf_end;
225 int fd;
226 int line_num; /* current line number - here to simply code */
227 int ifndef_macro; /* #ifndef macro / #endif search */
228 int ifndef_macro_saved; /* saved ifndef_macro */
229 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
230 char inc_type; /* type of include */
231 char inc_filename[512]; /* filename specified by the user */
232 char filename[1024]; /* current filename - here to simplify code */
233 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
234 } BufferedFile;
236 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
237 #define CH_EOF (-1) /* end of file */
239 /* parsing state (used to save parser state to reparse part of the
240 source several times) */
241 typedef struct ParseState {
242 int *macro_ptr;
243 int line_num;
244 int tok;
245 CValue tokc;
246 } ParseState;
248 /* used to record tokens */
249 typedef struct TokenString {
250 int *str;
251 int len;
252 int allocated_len;
253 int last_line_num;
254 } TokenString;
256 /* include file cache, used to find files faster and also to eliminate
257 inclusion if the include file is protected by #ifndef ... #endif */
258 typedef struct CachedInclude {
259 int ifndef_macro;
260 char type; /* '"' or '>' to give include type */
261 char filename[1]; /* path specified in #include */
262 } CachedInclude;
264 /* parser */
265 static struct BufferedFile *file;
266 static int ch, tok;
267 static CValue tokc;
268 static CString tokcstr; /* current parsed string, if any */
269 /* additional informations about token */
270 static int tok_flags;
271 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
272 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
273 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
275 static int *macro_ptr, *macro_ptr_allocated;
276 static int *unget_saved_macro_ptr;
277 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
278 static int unget_buffer_enabled;
279 static int parse_flags;
280 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
281 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
282 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
283 token. line feed is also
284 returned at eof */
286 static Section *text_section, *data_section, *bss_section; /* predefined sections */
287 static Section *cur_text_section; /* current section where function code is
288 generated */
289 /* bound check related sections */
290 static Section *bounds_section; /* contains global data bound description */
291 static Section *lbounds_section; /* contains local data bound description */
292 /* symbol sections */
293 static Section *symtab_section, *strtab_section;
295 /* debug sections */
296 static Section *stab_section, *stabstr_section;
298 /* loc : local variable index
299 ind : output code index
300 rsym: return symbol
301 anon_sym: anonymous symbol index
303 static int rsym, anon_sym, ind, loc;
304 /* expression generation modifiers */
305 static int const_wanted; /* true if constant wanted */
306 static int nocode_wanted; /* true if no code generation wanted for an expression */
307 static int global_expr; /* true if compound literals must be allocated
308 globally (used during initializers parsing */
309 static CType func_vt; /* current function return type (used by return
310 instruction) */
311 static int func_vc;
312 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
313 static int tok_ident;
314 static TokenSym **table_ident;
315 static TokenSym *hash_ident[TOK_HASH_SIZE];
316 static char token_buf[STRING_MAX_SIZE + 1];
317 static char *funcname;
318 static Sym *global_stack, *local_stack;
319 static Sym *define_stack;
320 static Sym *global_label_stack, *local_label_stack;
322 static SValue vstack[VSTACK_SIZE], *vtop;
323 /* some predefined types */
324 static CType char_pointer_type, func_old_type, int_type;
325 /* true if isid(c) || isnum(c) */
326 static unsigned char isidnum_table[256];
328 /* compile with debug symbol (and use them if error during execution) */
329 static int do_debug = 0;
331 /* compile with built-in memory and bounds checker */
332 static int do_bounds_check = 0;
334 /* display benchmark infos */
335 static int do_bench = 0;
336 static int total_lines;
337 static int total_bytes;
339 /* use GNU C extensions */
340 static int gnu_ext = 1;
342 /* use Tiny C extensions */
343 static int tcc_ext = 1;
345 /* max number of callers shown if error */
346 static int num_callers = 6;
347 static const char **rt_bound_error_msg;
349 /* XXX: get rid of this ASAP */
350 static struct TCCState *tcc_state;
352 /* give the path of the tcc libraries */
353 static const char *tcc_lib_path = CONFIG_TCC_PREFIX "/lib/tcc";
355 struct TCCState {
356 int output_type;
358 BufferedFile **include_stack_ptr;
359 int *ifdef_stack_ptr;
361 /* include file handling */
362 char **include_paths;
363 int nb_include_paths;
364 char **sysinclude_paths;
365 int nb_sysinclude_paths;
366 CachedInclude **cached_includes;
367 int nb_cached_includes;
369 char **library_paths;
370 int nb_library_paths;
372 /* array of all loaded dlls (including those referenced by loaded
373 dlls) */
374 DLLReference **loaded_dlls;
375 int nb_loaded_dlls;
377 /* sections */
378 Section **sections;
379 int nb_sections; /* number of sections, including first dummy section */
381 /* got handling */
382 Section *got;
383 Section *plt;
384 unsigned long *got_offsets;
385 int nb_got_offsets;
386 /* give the correspondance from symtab indexes to dynsym indexes */
387 int *symtab_to_dynsym;
389 /* temporary dynamic symbol sections (for dll loading) */
390 Section *dynsymtab_section;
391 /* exported dynamic symbol section */
392 Section *dynsym;
394 /* if true, no standard headers are added */
395 int nostdinc;
397 /* if true, static linking is performed */
398 int static_link;
400 /* error handling */
401 void *error_opaque;
402 void (*error_func)(void *opaque, const char *msg);
403 int error_set_jmp_enabled;
404 jmp_buf error_jmp_buf;
405 int nb_errors;
407 /* tiny assembler state */
408 Sym *asm_labels;
410 /* see include_stack_ptr */
411 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
413 /* see ifdef_stack_ptr */
414 int ifdef_stack[IFDEF_STACK_SIZE];
417 /* The current value can be: */
418 #define VT_VALMASK 0x00ff
419 #define VT_CONST 0x00f0 /* constant in vc
420 (must be first non register value) */
421 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
422 #define VT_LOCAL 0x00f2 /* offset on stack */
423 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
424 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
425 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
426 #define VT_LVAL 0x0100 /* var is an lvalue */
427 #define VT_SYM 0x0200 /* a symbol value is added */
428 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
429 char/short stored in integer registers) */
430 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
431 dereferencing value */
432 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
433 bounding function call point is in vc */
434 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
435 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
436 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
437 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
439 /* types */
440 #define VT_STRUCT_SHIFT 12 /* structure/enum name shift (20 bits left) */
442 #define VT_INT 0 /* integer type */
443 #define VT_BYTE 1 /* signed byte type */
444 #define VT_SHORT 2 /* short type */
445 #define VT_VOID 3 /* void type */
446 #define VT_PTR 4 /* pointer */
447 #define VT_ENUM 5 /* enum definition */
448 #define VT_FUNC 6 /* function type */
449 #define VT_STRUCT 7 /* struct/union definition */
450 #define VT_FLOAT 8 /* IEEE float */
451 #define VT_DOUBLE 9 /* IEEE double */
452 #define VT_LDOUBLE 10 /* IEEE long double */
453 #define VT_BOOL 11 /* ISOC99 boolean type */
454 #define VT_LLONG 12 /* 64 bit integer */
455 #define VT_LONG 13 /* long integer (NEVER USED as type, only
456 during parsing) */
457 #define VT_BTYPE 0x000f /* mask for basic type */
458 #define VT_UNSIGNED 0x0010 /* unsigned type */
459 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
460 #define VT_BITFIELD 0x0040 /* bitfield modifier */
462 /* storage */
463 #define VT_EXTERN 0x00000080 /* extern definition */
464 #define VT_STATIC 0x00000100 /* static variable */
465 #define VT_TYPEDEF 0x00000200 /* typedef definition */
466 #define VT_INLINE 0x00000400 /* inline definition */
468 /* type mask (except storage) */
469 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
470 #define VT_TYPE (~(VT_STORAGE))
472 /* token values */
474 /* warning: the following compare tokens depend on i386 asm code */
475 #define TOK_ULT 0x92
476 #define TOK_UGE 0x93
477 #define TOK_EQ 0x94
478 #define TOK_NE 0x95
479 #define TOK_ULE 0x96
480 #define TOK_UGT 0x97
481 #define TOK_LT 0x9c
482 #define TOK_GE 0x9d
483 #define TOK_LE 0x9e
484 #define TOK_GT 0x9f
486 #define TOK_LAND 0xa0
487 #define TOK_LOR 0xa1
489 #define TOK_DEC 0xa2
490 #define TOK_MID 0xa3 /* inc/dec, to void constant */
491 #define TOK_INC 0xa4
492 #define TOK_UDIV 0xb0 /* unsigned division */
493 #define TOK_UMOD 0xb1 /* unsigned modulo */
494 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
495 #define TOK_CINT 0xb3 /* number in tokc */
496 #define TOK_CCHAR 0xb4 /* char constant in tokc */
497 #define TOK_STR 0xb5 /* pointer to string in tokc */
498 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
499 #define TOK_LCHAR 0xb7
500 #define TOK_LSTR 0xb8
501 #define TOK_CFLOAT 0xb9 /* float constant */
502 #define TOK_LINENUM 0xba /* line number info */
503 #define TOK_CDOUBLE 0xc0 /* double constant */
504 #define TOK_CLDOUBLE 0xc1 /* long double constant */
505 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
506 #define TOK_ADDC1 0xc3 /* add with carry generation */
507 #define TOK_ADDC2 0xc4 /* add with carry use */
508 #define TOK_SUBC1 0xc5 /* add with carry generation */
509 #define TOK_SUBC2 0xc6 /* add with carry use */
510 #define TOK_CUINT 0xc8 /* unsigned int constant */
511 #define TOK_CLLONG 0xc9 /* long long constant */
512 #define TOK_CULLONG 0xca /* unsigned long long constant */
513 #define TOK_ARROW 0xcb
514 #define TOK_DOTS 0xcc /* three dots */
515 #define TOK_SHR 0xcd /* unsigned shift right */
516 #define TOK_PPNUM 0xce /* preprocessor number */
518 #define TOK_SHL 0x01 /* shift left */
519 #define TOK_SAR 0x02 /* signed shift right */
521 /* assignement operators : normal operator or 0x80 */
522 #define TOK_A_MOD 0xa5
523 #define TOK_A_AND 0xa6
524 #define TOK_A_MUL 0xaa
525 #define TOK_A_ADD 0xab
526 #define TOK_A_SUB 0xad
527 #define TOK_A_DIV 0xaf
528 #define TOK_A_XOR 0xde
529 #define TOK_A_OR 0xfc
530 #define TOK_A_SHL 0x81
531 #define TOK_A_SAR 0x82
533 /* WARNING: the content of this string encodes token numbers */
534 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";
536 #define TOK_EOF (-1) /* end of file */
537 #define TOK_LINEFEED 10 /* line feed */
539 /* all identificators and strings have token above that */
540 #define TOK_IDENT 256
542 /* only used for i386 asm opcodes definitions */
543 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
545 #define DEF_BWL(x) \
546 DEF(TOK_ASM_ ## x ## b, #x "b") \
547 DEF(TOK_ASM_ ## x ## w, #x "w") \
548 DEF(TOK_ASM_ ## x ## l, #x "l") \
549 DEF(TOK_ASM_ ## x, #x)
551 #define DEF_WL(x) \
552 DEF(TOK_ASM_ ## x ## w, #x "w") \
553 DEF(TOK_ASM_ ## x ## l, #x "l") \
554 DEF(TOK_ASM_ ## x, #x)
556 #define DEF_FP1(x) \
557 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
558 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
559 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
560 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
562 #define DEF_FP(x) \
563 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
564 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
565 DEF_FP1(x)
567 #define DEF_ASMTEST(x) \
568 DEF_ASM(x ## o) \
569 DEF_ASM(x ## no) \
570 DEF_ASM(x ## b) \
571 DEF_ASM(x ## c) \
572 DEF_ASM(x ## nae) \
573 DEF_ASM(x ## nb) \
574 DEF_ASM(x ## nc) \
575 DEF_ASM(x ## ae) \
576 DEF_ASM(x ## e) \
577 DEF_ASM(x ## z) \
578 DEF_ASM(x ## ne) \
579 DEF_ASM(x ## nz) \
580 DEF_ASM(x ## be) \
581 DEF_ASM(x ## na) \
582 DEF_ASM(x ## nbe) \
583 DEF_ASM(x ## a) \
584 DEF_ASM(x ## s) \
585 DEF_ASM(x ## ns) \
586 DEF_ASM(x ## p) \
587 DEF_ASM(x ## pe) \
588 DEF_ASM(x ## np) \
589 DEF_ASM(x ## po) \
590 DEF_ASM(x ## l) \
591 DEF_ASM(x ## nge) \
592 DEF_ASM(x ## nl) \
593 DEF_ASM(x ## ge) \
594 DEF_ASM(x ## le) \
595 DEF_ASM(x ## ng) \
596 DEF_ASM(x ## nle) \
597 DEF_ASM(x ## g)
599 #define TOK_ASM_int TOK_INT
601 enum {
602 TOK_LAST = TOK_IDENT - 1,
603 #define DEF(id, str) id,
604 #include "tcctok.h"
605 #undef DEF
608 static const char tcc_keywords[] =
609 #define DEF(id, str) str "\0"
610 #include "tcctok.h"
611 #undef DEF
614 #define TOK_UIDENT TOK_DEFINE
616 #ifdef WIN32
617 #define snprintf _snprintf
618 #define vsnprintf _vsnprintf
619 #endif
621 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
622 /* currently incorrect */
623 long double strtold(const char *nptr, char **endptr)
625 return (long double)strtod(nptr, endptr);
627 float strtof(const char *nptr, char **endptr)
629 return (float)strtod(nptr, endptr);
631 #else
632 /* XXX: need to define this to use them in non ISOC99 context */
633 extern float strtof (const char *__nptr, char **__endptr);
634 extern long double strtold (const char *__nptr, char **__endptr);
635 #endif
637 static char *pstrcpy(char *buf, int buf_size, const char *s);
638 static char *pstrcat(char *buf, int buf_size, const char *s);
640 static void next(void);
641 static void next_nomacro(void);
642 static void parse_expr_type(CType *type);
643 static void expr_type(CType *type);
644 static void unary_type(CType *type);
645 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
646 int case_reg, int is_expr);
647 static int expr_const(void);
648 static void expr_eq(void);
649 static void gexpr(void);
650 static void decl(int l);
651 static void decl_initializer(CType *type, Section *sec, unsigned long c,
652 int first, int size_only);
653 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
654 int has_init, int v, int scope);
655 int gv(int rc);
656 void gv2(int rc1, int rc2);
657 void move_reg(int r, int s);
658 void save_regs(int n);
659 void save_reg(int r);
660 void vpop(void);
661 void vswap(void);
662 void vdup(void);
663 int get_reg(int rc);
665 static void macro_subst(TokenString *tok_str,
666 Sym **nested_list, const int *macro_str);
667 int save_reg_forced(int r);
668 void gen_op(int op);
669 void force_charshort_cast(int t);
670 static void gen_cast(CType *type);
671 void vstore(void);
672 static Sym *sym_find(int v);
673 static Sym *sym_push(int v, CType *type, int r, int c);
675 /* type handling */
676 static int type_size(CType *type, int *a);
677 static inline CType *pointed_type(CType *type);
678 static int pointed_size(CType *type);
679 static int lvalue_type(int t);
680 static int is_compatible_types(CType *type1, CType *type2);
681 static int parse_btype(CType *type, AttributeDef *ad);
682 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
684 void error(const char *fmt, ...);
685 void vpushi(int v);
686 void vset(CType *type, int r, int v);
687 void type_to_str(char *buf, int buf_size,
688 CType *type, const char *varstr);
689 char *get_tok_str(int v, CValue *cv);
690 static Sym *get_sym_ref(CType *type, Section *sec,
691 unsigned long offset, unsigned long size);
692 static Sym *external_global_sym(int v, CType *type, int r);
694 /* section generation */
695 static void section_realloc(Section *sec, unsigned long new_size);
696 static void *section_ptr_add(Section *sec, unsigned long size);
697 static void put_extern_sym(Sym *sym, Section *section,
698 unsigned long value, unsigned long size);
699 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
700 static int put_elf_str(Section *s, const char *sym);
701 static int put_elf_sym(Section *s,
702 unsigned long value, unsigned long size,
703 int info, int other, int shndx, const char *name);
704 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
705 int info, int sh_num, const char *name);
706 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
707 int type, int symbol);
708 static void put_stabs(const char *str, int type, int other, int desc,
709 unsigned long value);
710 static void put_stabs_r(const char *str, int type, int other, int desc,
711 unsigned long value, Section *sec, int sym_index);
712 static void put_stabn(int type, int other, int desc, int value);
713 static void put_stabd(int type, int other, int desc);
714 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
716 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
717 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
718 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
720 /* tccasm.c */
722 #ifdef CONFIG_TCC_ASM
724 typedef struct ExprValue {
725 uint32_t v;
726 Sym *sym;
727 } ExprValue;
729 #define MAX_ASM_OPERANDS 30
731 typedef struct ASMOperand {
732 int id; /* GCC 3 optionnal identifier (0 if number only supported */
733 char *constraint;
734 char asm_str[16]; /* computed asm string for operand */
735 SValue *vt; /* C value of the expression */
736 int ref_index; /* if >= 0, gives reference to a output constraint */
737 int priority; /* priority, used to assign registers */
738 int reg; /* if >= 0, register number used for this operand */
739 } ASMOperand;
741 static void asm_expr(TCCState *s1, ExprValue *pe);
742 static int asm_int_expr(TCCState *s1);
743 static int find_constraint(ASMOperand *operands, int nb_operands,
744 const char *name, const char **pp);
746 static int tcc_assemble(TCCState *s1, int do_preprocess);
748 #endif
750 static void asm_instr(void);
752 /* true if float/double/long double type */
753 static inline int is_float(int t)
755 int bt;
756 bt = t & VT_BTYPE;
757 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
760 #ifdef TCC_TARGET_I386
761 #include "i386-gen.c"
762 #endif
764 #ifdef CONFIG_TCC_STATIC
766 #define RTLD_LAZY 0x001
767 #define RTLD_NOW 0x002
768 #define RTLD_GLOBAL 0x100
769 #define RTLD_DEFAULT NULL
771 /* dummy function for profiling */
772 void *dlopen(const char *filename, int flag)
774 return NULL;
777 const char *dlerror(void)
779 return "error";
782 typedef struct TCCSyms {
783 char *str;
784 void *ptr;
785 } TCCSyms;
787 #define TCCSYM(a) { #a, &a, },
789 /* add the symbol you want here if no dynamic linking is done */
790 static TCCSyms tcc_syms[] = {
791 TCCSYM(printf)
792 TCCSYM(fprintf)
793 TCCSYM(fopen)
794 TCCSYM(fclose)
795 { NULL, NULL },
798 void *dlsym(void *handle, const char *symbol)
800 TCCSyms *p;
801 p = tcc_syms;
802 while (p->str != NULL) {
803 if (!strcmp(p->str, symbol))
804 return p->ptr;
805 p++;
807 return NULL;
810 #endif
812 /********************************************************/
814 /* we use our own 'finite' function to avoid potential problems with
815 non standard math libs */
816 /* XXX: endianness dependent */
817 int ieee_finite(double d)
819 int *p = (int *)&d;
820 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
823 /* copy a string and truncate it. */
824 static char *pstrcpy(char *buf, int buf_size, const char *s)
826 char *q, *q_end;
827 int c;
829 if (buf_size > 0) {
830 q = buf;
831 q_end = buf + buf_size - 1;
832 while (q < q_end) {
833 c = *s++;
834 if (c == '\0')
835 break;
836 *q++ = c;
838 *q = '\0';
840 return buf;
843 /* strcat and truncate. */
844 static char *pstrcat(char *buf, int buf_size, const char *s)
846 int len;
847 len = strlen(buf);
848 if (len < buf_size)
849 pstrcpy(buf + len, buf_size - len, s);
850 return buf;
853 /* memory management */
854 #ifdef MEM_DEBUG
855 int mem_cur_size;
856 int mem_max_size;
857 #endif
859 static inline void tcc_free(void *ptr)
861 #ifdef MEM_DEBUG
862 mem_cur_size -= malloc_usable_size(ptr);
863 #endif
864 free(ptr);
867 static void *tcc_malloc(unsigned long size)
869 void *ptr;
870 ptr = malloc(size);
871 if (!ptr && size)
872 error("memory full");
873 #ifdef MEM_DEBUG
874 mem_cur_size += malloc_usable_size(ptr);
875 if (mem_cur_size > mem_max_size)
876 mem_max_size = mem_cur_size;
877 #endif
878 return ptr;
881 static void *tcc_mallocz(unsigned long size)
883 void *ptr;
884 ptr = tcc_malloc(size);
885 memset(ptr, 0, size);
886 return ptr;
889 static inline void *tcc_realloc(void *ptr, unsigned long size)
891 void *ptr1;
892 #ifdef MEM_DEBUG
893 mem_cur_size -= malloc_usable_size(ptr);
894 #endif
895 ptr1 = realloc(ptr, size);
896 #ifdef MEM_DEBUG
897 /* NOTE: count not correct if alloc error, but not critical */
898 mem_cur_size += malloc_usable_size(ptr1);
899 if (mem_cur_size > mem_max_size)
900 mem_max_size = mem_cur_size;
901 #endif
902 return ptr1;
905 static char *tcc_strdup(const char *str)
907 char *ptr;
908 ptr = tcc_malloc(strlen(str) + 1);
909 strcpy(ptr, str);
910 return ptr;
913 #define free(p) use_tcc_free(p)
914 #define malloc(s) use_tcc_malloc(s)
915 #define realloc(p, s) use_tcc_realloc(p, s)
917 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
919 int nb, nb_alloc;
920 void **pp;
922 nb = *nb_ptr;
923 pp = *ptab;
924 /* every power of two we double array size */
925 if ((nb & (nb - 1)) == 0) {
926 if (!nb)
927 nb_alloc = 1;
928 else
929 nb_alloc = nb * 2;
930 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
931 if (!pp)
932 error("memory full");
933 *ptab = pp;
935 pp[nb++] = data;
936 *nb_ptr = nb;
939 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
941 Section *sec;
943 sec = tcc_mallocz(sizeof(Section));
944 pstrcpy(sec->name, sizeof(sec->name), name);
945 sec->sh_type = sh_type;
946 sec->sh_flags = sh_flags;
947 switch(sh_type) {
948 case SHT_HASH:
949 case SHT_REL:
950 case SHT_DYNSYM:
951 case SHT_SYMTAB:
952 case SHT_DYNAMIC:
953 sec->sh_addralign = 4;
954 break;
955 case SHT_STRTAB:
956 sec->sh_addralign = 1;
957 break;
958 default:
959 sec->sh_addralign = 32; /* default conservative alignment */
960 break;
963 /* only add section if not private */
964 if (!(sh_flags & SHF_PRIVATE)) {
965 sec->sh_num = s1->nb_sections;
966 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
968 return sec;
971 static void free_section(Section *s)
973 tcc_free(s->data);
974 tcc_free(s);
977 /* realloc section and set its content to zero */
978 static void section_realloc(Section *sec, unsigned long new_size)
980 unsigned long size;
981 unsigned char *data;
983 size = sec->data_allocated;
984 if (size == 0)
985 size = 1;
986 while (size < new_size)
987 size = size * 2;
988 data = tcc_realloc(sec->data, size);
989 if (!data)
990 error("memory full");
991 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
992 sec->data = data;
993 sec->data_allocated = size;
996 /* reserve at least 'size' bytes in section 'sec' from
997 sec->data_offset. */
998 static void *section_ptr_add(Section *sec, unsigned long size)
1000 unsigned long offset, offset1;
1002 offset = sec->data_offset;
1003 offset1 = offset + size;
1004 if (offset1 > sec->data_allocated)
1005 section_realloc(sec, offset1);
1006 sec->data_offset = offset1;
1007 return sec->data + offset;
1010 /* return a reference to a section, and create it if it does not
1011 exists */
1012 Section *find_section(TCCState *s1, const char *name)
1014 Section *sec;
1015 int i;
1016 for(i = 1; i < s1->nb_sections; i++) {
1017 sec = s1->sections[i];
1018 if (!strcmp(name, sec->name))
1019 return sec;
1021 /* sections are created as PROGBITS */
1022 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1025 /* update sym->c so that it points to an external symbol in section
1026 'section' with value 'value' */
1027 static void put_extern_sym(Sym *sym, Section *section,
1028 unsigned long value, unsigned long size)
1030 int sym_type, sym_bind, sh_num, info;
1031 Elf32_Sym *esym;
1032 const char *name;
1034 if (section)
1035 sh_num = section->sh_num;
1036 else
1037 sh_num = SHN_UNDEF;
1038 if (!sym->c) {
1039 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1040 sym_type = STT_FUNC;
1041 else
1042 sym_type = STT_OBJECT;
1043 if (sym->type.t & VT_STATIC)
1044 sym_bind = STB_LOCAL;
1045 else
1046 sym_bind = STB_GLOBAL;
1048 name = get_tok_str(sym->v, NULL);
1049 #ifdef CONFIG_TCC_BCHECK
1050 if (do_bounds_check) {
1051 char buf[32];
1053 /* XXX: avoid doing that for statics ? */
1054 /* if bound checking is activated, we change some function
1055 names by adding the "__bound" prefix */
1056 switch(sym->v) {
1057 #if 0
1058 /* XXX: we rely only on malloc hooks */
1059 case TOK_malloc:
1060 case TOK_free:
1061 case TOK_realloc:
1062 case TOK_memalign:
1063 case TOK_calloc:
1064 #endif
1065 case TOK_memcpy:
1066 case TOK_memmove:
1067 case TOK_memset:
1068 case TOK_strlen:
1069 case TOK_strcpy:
1070 strcpy(buf, "__bound_");
1071 strcat(buf, name);
1072 name = buf;
1073 break;
1076 #endif
1077 info = ELF32_ST_INFO(sym_bind, sym_type);
1078 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1079 } else {
1080 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1081 esym->st_value = value;
1082 esym->st_size = size;
1083 esym->st_shndx = sh_num;
1087 /* add a new relocation entry to symbol 'sym' in section 's' */
1088 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1090 if (!sym->c)
1091 put_extern_sym(sym, NULL, 0, 0);
1092 /* now we can add ELF relocation info */
1093 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1096 static inline int isid(int c)
1098 return (c >= 'a' && c <= 'z') ||
1099 (c >= 'A' && c <= 'Z') ||
1100 c == '_';
1103 static inline int isnum(int c)
1105 return c >= '0' && c <= '9';
1108 static inline int isoct(int c)
1110 return c >= '0' && c <= '7';
1113 static inline int toup(int c)
1115 if (c >= 'a' && c <= 'z')
1116 return c - 'a' + 'A';
1117 else
1118 return c;
1121 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1123 int len;
1124 len = strlen(buf);
1125 vsnprintf(buf + len, buf_size - len, fmt, ap);
1128 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1130 va_list ap;
1131 va_start(ap, fmt);
1132 strcat_vprintf(buf, buf_size, fmt, ap);
1133 va_end(ap);
1136 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1138 char buf[2048];
1139 BufferedFile **f;
1141 buf[0] = '\0';
1142 if (file) {
1143 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1144 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1145 (*f)->filename, (*f)->line_num);
1146 if (file->line_num > 0) {
1147 strcat_printf(buf, sizeof(buf),
1148 "%s:%d: ", file->filename, file->line_num);
1149 } else {
1150 strcat_printf(buf, sizeof(buf),
1151 "%s: ", file->filename);
1153 } else {
1154 strcat_printf(buf, sizeof(buf),
1155 "tcc: ");
1157 if (is_warning)
1158 strcat_printf(buf, sizeof(buf), "warning: ");
1159 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1161 if (!s1->error_func) {
1162 /* default case: stderr */
1163 fprintf(stderr, "%s\n", buf);
1164 } else {
1165 s1->error_func(s1->error_opaque, buf);
1167 if (!is_warning)
1168 s1->nb_errors++;
1171 #ifdef LIBTCC
1172 void tcc_set_error_func(TCCState *s, void *error_opaque,
1173 void (*error_func)(void *opaque, const char *msg))
1175 s->error_opaque = error_opaque;
1176 s->error_func = error_func;
1178 #endif
1180 /* error without aborting current compilation */
1181 void error_noabort(const char *fmt, ...)
1183 TCCState *s1 = tcc_state;
1184 va_list ap;
1186 va_start(ap, fmt);
1187 error1(s1, 0, fmt, ap);
1188 va_end(ap);
1191 void error(const char *fmt, ...)
1193 TCCState *s1 = tcc_state;
1194 va_list ap;
1196 va_start(ap, fmt);
1197 error1(s1, 0, fmt, ap);
1198 va_end(ap);
1199 /* better than nothing: in some cases, we accept to handle errors */
1200 if (s1->error_set_jmp_enabled) {
1201 longjmp(s1->error_jmp_buf, 1);
1202 } else {
1203 /* XXX: eliminate this someday */
1204 exit(1);
1208 void expect(const char *msg)
1210 error("%s expected", msg);
1213 void warning(const char *fmt, ...)
1215 TCCState *s1 = tcc_state;
1216 va_list ap;
1218 va_start(ap, fmt);
1219 error1(s1, 1, fmt, ap);
1220 va_end(ap);
1223 void skip(int c)
1225 if (tok != c)
1226 error("'%c' expected", c);
1227 next();
1230 static void test_lvalue(void)
1232 if (!(vtop->r & VT_LVAL))
1233 expect("lvalue");
1236 /* allocate a new token */
1237 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1239 TokenSym *ts, **ptable;
1240 int i;
1242 if (tok_ident >= SYM_FIRST_ANOM)
1243 error("memory full");
1245 /* expand token table if needed */
1246 i = tok_ident - TOK_IDENT;
1247 if ((i % TOK_ALLOC_INCR) == 0) {
1248 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1249 if (!ptable)
1250 error("memory full");
1251 table_ident = ptable;
1254 ts = tcc_malloc(sizeof(TokenSym) + len);
1255 table_ident[i] = ts;
1256 ts->tok = tok_ident++;
1257 ts->sym_define = NULL;
1258 ts->sym_label = NULL;
1259 ts->sym_struct = NULL;
1260 ts->sym_identifier = NULL;
1261 ts->len = len;
1262 ts->hash_next = NULL;
1263 memcpy(ts->str, str, len);
1264 ts->str[len] = '\0';
1265 *pts = ts;
1266 return ts;
1269 #define TOK_HASH_INIT 1
1270 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1272 /* find a token and add it if not found */
1273 static TokenSym *tok_alloc(const char *str, int len)
1275 TokenSym *ts, **pts;
1276 int i;
1277 unsigned int h;
1279 h = TOK_HASH_INIT;
1280 for(i=0;i<len;i++)
1281 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1282 h &= (TOK_HASH_SIZE - 1);
1284 pts = &hash_ident[h];
1285 for(;;) {
1286 ts = *pts;
1287 if (!ts)
1288 break;
1289 if (ts->len == len && !memcmp(ts->str, str, len))
1290 return ts;
1291 pts = &(ts->hash_next);
1293 return tok_alloc_new(pts, str, len);
1296 /* CString handling */
1298 static void cstr_realloc(CString *cstr, int new_size)
1300 int size;
1301 void *data;
1303 size = cstr->size_allocated;
1304 if (size == 0)
1305 size = 8; /* no need to allocate a too small first string */
1306 while (size < new_size)
1307 size = size * 2;
1308 data = tcc_realloc(cstr->data_allocated, size);
1309 if (!data)
1310 error("memory full");
1311 cstr->data_allocated = data;
1312 cstr->size_allocated = size;
1313 cstr->data = data;
1316 /* add a byte */
1317 static void cstr_ccat(CString *cstr, int ch)
1319 int size;
1320 size = cstr->size + 1;
1321 if (size > cstr->size_allocated)
1322 cstr_realloc(cstr, size);
1323 ((unsigned char *)cstr->data)[size - 1] = ch;
1324 cstr->size = size;
1327 static void cstr_cat(CString *cstr, const char *str)
1329 int c;
1330 for(;;) {
1331 c = *str;
1332 if (c == '\0')
1333 break;
1334 cstr_ccat(cstr, c);
1335 str++;
1339 /* add a wide char */
1340 static void cstr_wccat(CString *cstr, int ch)
1342 int size;
1343 size = cstr->size + sizeof(int);
1344 if (size > cstr->size_allocated)
1345 cstr_realloc(cstr, size);
1346 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1347 cstr->size = size;
1350 static void cstr_new(CString *cstr)
1352 memset(cstr, 0, sizeof(CString));
1355 /* free string and reset it to NULL */
1356 static void cstr_free(CString *cstr)
1358 tcc_free(cstr->data_allocated);
1359 cstr_new(cstr);
1362 #define cstr_reset(cstr) cstr_free(cstr)
1364 static CString *cstr_dup(CString *cstr1)
1366 CString *cstr;
1367 int size;
1369 cstr = tcc_malloc(sizeof(CString));
1370 size = cstr1->size;
1371 cstr->size = size;
1372 cstr->size_allocated = size;
1373 cstr->data_allocated = tcc_malloc(size);
1374 cstr->data = cstr->data_allocated;
1375 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1376 return cstr;
1379 /* XXX: unicode ? */
1380 static void add_char(CString *cstr, int c)
1382 if (c == '\'' || c == '\"' || c == '\\') {
1383 /* XXX: could be more precise if char or string */
1384 cstr_ccat(cstr, '\\');
1386 if (c >= 32 && c <= 126) {
1387 cstr_ccat(cstr, c);
1388 } else {
1389 cstr_ccat(cstr, '\\');
1390 if (c == '\n') {
1391 cstr_ccat(cstr, 'n');
1392 } else {
1393 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1394 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1395 cstr_ccat(cstr, '0' + (c & 7));
1400 /* XXX: buffer overflow */
1401 /* XXX: float tokens */
1402 char *get_tok_str(int v, CValue *cv)
1404 static char buf[STRING_MAX_SIZE + 1];
1405 static CString cstr_buf;
1406 CString *cstr;
1407 unsigned char *q;
1408 char *p;
1409 int i, len;
1411 /* NOTE: to go faster, we give a fixed buffer for small strings */
1412 cstr_reset(&cstr_buf);
1413 cstr_buf.data = buf;
1414 cstr_buf.size_allocated = sizeof(buf);
1415 p = buf;
1417 switch(v) {
1418 case TOK_CINT:
1419 case TOK_CUINT:
1420 /* XXX: not quite exact, but only useful for testing */
1421 sprintf(p, "%u", cv->ui);
1422 break;
1423 case TOK_CLLONG:
1424 case TOK_CULLONG:
1425 /* XXX: not quite exact, but only useful for testing */
1426 sprintf(p, "%Lu", cv->ull);
1427 break;
1428 case TOK_CCHAR:
1429 case TOK_LCHAR:
1430 cstr_ccat(&cstr_buf, '\'');
1431 add_char(&cstr_buf, cv->i);
1432 cstr_ccat(&cstr_buf, '\'');
1433 cstr_ccat(&cstr_buf, '\0');
1434 break;
1435 case TOK_PPNUM:
1436 cstr = cv->cstr;
1437 len = cstr->size - 1;
1438 for(i=0;i<len;i++)
1439 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1440 cstr_ccat(&cstr_buf, '\0');
1441 break;
1442 case TOK_STR:
1443 case TOK_LSTR:
1444 cstr = cv->cstr;
1445 cstr_ccat(&cstr_buf, '\"');
1446 if (v == TOK_STR) {
1447 len = cstr->size - 1;
1448 for(i=0;i<len;i++)
1449 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1450 } else {
1451 len = (cstr->size / sizeof(int)) - 1;
1452 for(i=0;i<len;i++)
1453 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1455 cstr_ccat(&cstr_buf, '\"');
1456 cstr_ccat(&cstr_buf, '\0');
1457 break;
1458 case TOK_LT:
1459 v = '<';
1460 goto addv;
1461 case TOK_GT:
1462 v = '>';
1463 goto addv;
1464 case TOK_A_SHL:
1465 return strcpy(p, "<<=");
1466 case TOK_A_SAR:
1467 return strcpy(p, ">>=");
1468 default:
1469 if (v < TOK_IDENT) {
1470 /* search in two bytes table */
1471 q = tok_two_chars;
1472 while (*q) {
1473 if (q[2] == v) {
1474 *p++ = q[0];
1475 *p++ = q[1];
1476 *p = '\0';
1477 return buf;
1479 q += 3;
1481 addv:
1482 *p++ = v;
1483 *p = '\0';
1484 } else if (v < tok_ident) {
1485 return table_ident[v - TOK_IDENT]->str;
1486 } else if (v >= SYM_FIRST_ANOM) {
1487 /* special name for anonymous symbol */
1488 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1489 } else {
1490 /* should never happen */
1491 return NULL;
1493 break;
1495 return cstr_buf.data;
1498 /* push, without hashing */
1499 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1501 Sym *s;
1502 s = tcc_malloc(sizeof(Sym));
1503 s->v = v;
1504 s->type.t = t;
1505 s->c = c;
1506 s->next = NULL;
1507 /* add in stack */
1508 s->prev = *ps;
1509 *ps = s;
1510 return s;
1513 /* find a symbol and return its associated structure. 's' is the top
1514 of the symbol stack */
1515 static Sym *sym_find2(Sym *s, int v)
1517 while (s) {
1518 if (s->v == v)
1519 return s;
1520 s = s->prev;
1522 return NULL;
1525 /* structure lookup */
1526 static inline Sym *struct_find(int v)
1528 v -= TOK_IDENT;
1529 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1530 return NULL;
1531 return table_ident[v]->sym_struct;
1534 /* find an identifier */
1535 static inline Sym *sym_find(int v)
1537 v -= TOK_IDENT;
1538 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1539 return NULL;
1540 return table_ident[v]->sym_identifier;
1543 /* push a given symbol on the symbol stack */
1544 static Sym *sym_push(int v, CType *type, int r, int c)
1546 Sym *s, **ps;
1547 TokenSym *ts;
1549 if (local_stack)
1550 ps = &local_stack;
1551 else
1552 ps = &global_stack;
1553 s = sym_push2(ps, v, type->t, c);
1554 s->type.ref = type->ref;
1555 s->r = r;
1556 /* don't record fields or anonymous symbols */
1557 /* XXX: simplify */
1558 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1559 /* record symbol in token array */
1560 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1561 if (v & SYM_STRUCT)
1562 ps = &ts->sym_struct;
1563 else
1564 ps = &ts->sym_identifier;
1565 s->prev_tok = *ps;
1566 *ps = s;
1568 return s;
1571 /* push a global identifier */
1572 static Sym *global_identifier_push(int v, int t, int c)
1574 Sym *s, **ps;
1575 s = sym_push2(&global_stack, v, t, c);
1576 /* don't record anonymous symbol */
1577 if (v < SYM_FIRST_ANOM) {
1578 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1579 /* modify the top most local identifier, so that
1580 sym_identifier will point to 's' when popped */
1581 while (*ps != NULL)
1582 ps = &(*ps)->prev_tok;
1583 s->prev_tok = NULL;
1584 *ps = s;
1586 return s;
1589 /* pop symbols until top reaches 'b' */
1590 static void sym_pop(Sym **ptop, Sym *b)
1592 Sym *s, *ss, **ps;
1593 TokenSym *ts;
1594 int v;
1596 s = *ptop;
1597 while(s != b) {
1598 ss = s->prev;
1599 v = s->v;
1600 /* remove symbol in token array */
1601 /* XXX: simplify */
1602 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1603 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1604 if (v & SYM_STRUCT)
1605 ps = &ts->sym_struct;
1606 else
1607 ps = &ts->sym_identifier;
1608 *ps = s->prev_tok;
1610 tcc_free(s);
1611 s = ss;
1613 *ptop = b;
1616 /* I/O layer */
1618 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1620 int fd;
1621 BufferedFile *bf;
1623 fd = open(filename, O_RDONLY);
1624 if (fd < 0)
1625 return NULL;
1626 bf = tcc_malloc(sizeof(BufferedFile));
1627 if (!bf) {
1628 close(fd);
1629 return NULL;
1631 bf->fd = fd;
1632 bf->buf_ptr = bf->buffer;
1633 bf->buf_end = bf->buffer;
1634 bf->buffer[0] = CH_EOB; /* put eob symbol */
1635 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1636 bf->line_num = 1;
1637 bf->ifndef_macro = 0;
1638 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1639 // printf("opening '%s'\n", filename);
1640 return bf;
1643 void tcc_close(BufferedFile *bf)
1645 total_lines += bf->line_num;
1646 close(bf->fd);
1647 tcc_free(bf);
1650 /* fill input buffer and peek next char */
1651 static int tcc_peekc_slow(BufferedFile *bf)
1653 int len;
1654 /* only tries to read if really end of buffer */
1655 if (bf->buf_ptr >= bf->buf_end) {
1656 if (bf->fd != -1) {
1657 #if defined(PARSE_DEBUG)
1658 len = 8;
1659 #else
1660 len = IO_BUF_SIZE;
1661 #endif
1662 len = read(bf->fd, bf->buffer, len);
1663 if (len < 0)
1664 len = 0;
1665 } else {
1666 len = 0;
1668 total_bytes += len;
1669 bf->buf_ptr = bf->buffer;
1670 bf->buf_end = bf->buffer + len;
1671 *bf->buf_end = CH_EOB;
1673 if (bf->buf_ptr < bf->buf_end) {
1674 return bf->buf_ptr[0];
1675 } else {
1676 bf->buf_ptr = bf->buf_end;
1677 return CH_EOF;
1681 /* return the current character, handling end of block if necessary
1682 (but not stray) */
1683 static int handle_eob(void)
1685 return tcc_peekc_slow(file);
1688 /* read next char from current input file and handle end of input buffer */
1689 static inline void inp(void)
1691 ch = *(++(file->buf_ptr));
1692 /* end of buffer/file handling */
1693 if (ch == CH_EOB)
1694 ch = handle_eob();
1697 /* handle '\[\r]\n' */
1698 static void handle_stray(void)
1700 while (ch == '\\') {
1701 inp();
1702 if (ch == '\n') {
1703 file->line_num++;
1704 inp();
1705 } else if (ch == '\r') {
1706 inp();
1707 if (ch != '\n')
1708 goto fail;
1709 file->line_num++;
1710 inp();
1711 } else {
1712 fail:
1713 error("stray '\\' in program");
1718 /* skip the stray and handle the \\n case. Output an error if
1719 incorrect char after the stray */
1720 static int handle_stray1(uint8_t *p)
1722 int c;
1724 if (p >= file->buf_end) {
1725 file->buf_ptr = p;
1726 c = handle_eob();
1727 p = file->buf_ptr;
1728 if (c == '\\')
1729 goto parse_stray;
1730 } else {
1731 parse_stray:
1732 file->buf_ptr = p;
1733 ch = *p;
1734 handle_stray();
1735 p = file->buf_ptr;
1736 c = *p;
1738 return c;
1741 /* handle the complicated stray case */
1742 #define PEEKC(c, p)\
1744 p++;\
1745 c = *p;\
1746 if (c == '\\') {\
1747 c = handle_stray1(p);\
1748 p = file->buf_ptr;\
1752 /* input with '\[\r]\n' handling. Note that this function cannot
1753 handle other characters after '\', so you cannot call it inside
1754 strings or comments */
1755 static void minp(void)
1757 inp();
1758 if (ch == '\\')
1759 handle_stray();
1763 static void parse_line_comment(void)
1765 /* single line C++ comments */
1766 /* XXX: accept '\\\n' ? */
1767 inp();
1768 while (ch != '\n' && ch != CH_EOF)
1769 inp();
1772 static void parse_comment(void)
1774 uint8_t *p;
1775 int c;
1777 /* C comments */
1778 p = file->buf_ptr;
1779 p++;
1780 for(;;) {
1781 /* fast skip loop */
1782 for(;;) {
1783 c = *p;
1784 if (c == '\n' || c == '*' || c == '\\')
1785 break;
1786 p++;
1787 c = *p;
1788 if (c == '\n' || c == '*' || c == '\\')
1789 break;
1790 p++;
1792 /* now we can handle all the cases */
1793 if (c == '\n') {
1794 file->line_num++;
1795 p++;
1796 } else if (c == '*') {
1797 p++;
1798 for(;;) {
1799 c = *p;
1800 if (c == '*') {
1801 p++;
1802 } else if (c == '/') {
1803 goto end_of_comment;
1804 } else if (c == '\\') {
1805 file->buf_ptr = p;
1806 c = handle_eob();
1807 if (c == '\\') {
1808 /* skip '\\n', but if '\' followed but another
1809 char, behave asif a stray was parsed */
1810 ch = file->buf_ptr[0];
1811 while (ch == '\\') {
1812 inp();
1813 if (ch == '\n') {
1814 file->line_num++;
1815 inp();
1816 } else if (ch == '\r') {
1817 inp();
1818 if (ch == '\n') {
1819 file->line_num++;
1820 inp();
1822 } else {
1823 p = file->buf_ptr;
1824 break;
1828 p = file->buf_ptr;
1829 } else {
1830 break;
1833 } else {
1834 /* stray, eob or eof */
1835 file->buf_ptr = p;
1836 c = handle_eob();
1837 p = file->buf_ptr;
1838 if (c == CH_EOF) {
1839 error("unexpected end of file in comment");
1840 } else if (c == '\\') {
1841 p++;
1845 end_of_comment:
1846 p++;
1847 file->buf_ptr = p;
1848 ch = *p;
1851 #define cinp minp
1853 /* space exlcuding newline */
1854 static inline int is_space(int ch)
1856 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1859 static inline void skip_spaces(void)
1861 while (is_space(ch))
1862 cinp();
1865 /* skip block of text until #else, #elif or #endif. skip also pairs of
1866 #if/#endif */
1867 void preprocess_skip(void)
1869 int a, start_of_line, sep, c;
1870 uint8_t *p;
1872 p = file->buf_ptr;
1873 start_of_line = 1;
1874 a = 0;
1875 for(;;) {
1876 redo_no_start:
1877 c = *p;
1878 switch(c) {
1879 case ' ':
1880 case '\t':
1881 case '\f':
1882 case '\v':
1883 case '\r':
1884 p++;
1885 goto redo_no_start;
1886 case '\n':
1887 start_of_line = 1;
1888 file->line_num++;
1889 p++;
1890 goto redo_no_start;
1891 case '\\':
1892 file->buf_ptr = p;
1893 c = handle_eob();
1894 if (c == CH_EOF) {
1895 expect("#endif");
1896 } else if (c == '\\') {
1897 /* XXX: incorrect: should not give an error */
1898 ch = file->buf_ptr[0];
1899 handle_stray();
1901 p = file->buf_ptr;
1902 goto redo_no_start;
1903 /* skip strings */
1904 case '\"':
1905 case '\'':
1906 sep = c;
1907 p++;
1908 for(;;) {
1909 c = *p;
1910 if (c == sep) {
1911 break;
1912 } else if (c == '\\') {
1913 file->buf_ptr = p;
1914 c = handle_eob();
1915 p = file->buf_ptr;
1916 if (c == CH_EOF) {
1917 /* XXX: better error message */
1918 error("unterminated string");
1919 } else if (c == '\\') {
1920 /* ignore next char */
1921 p++;
1922 c = *p;
1923 if (c == '\\') {
1924 file->buf_ptr = p;
1925 c = handle_eob();
1926 p = file->buf_ptr;
1928 if (c == '\n')
1929 file->line_num++;
1930 else if (c != CH_EOF)
1931 p++;
1933 } else if (c == '\n') {
1934 file->line_num++;
1935 p++;
1936 } else {
1937 p++;
1940 p++;
1941 break;
1942 /* skip comments */
1943 case '/':
1944 file->buf_ptr = p;
1945 ch = *p;
1946 minp();
1947 if (ch == '*') {
1948 parse_comment();
1949 } else if (ch == '/') {
1950 parse_line_comment();
1952 p = file->buf_ptr;
1953 break;
1955 case '#':
1956 p++;
1957 if (start_of_line) {
1958 file->buf_ptr = p;
1959 next_nomacro();
1960 p = file->buf_ptr;
1961 if (a == 0 &&
1962 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1963 goto the_end;
1964 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1965 a++;
1966 else if (tok == TOK_ENDIF)
1967 a--;
1969 break;
1970 default:
1971 p++;
1972 break;
1974 start_of_line = 0;
1976 the_end: ;
1977 file->buf_ptr = p;
1980 /* ParseState handling */
1982 /* XXX: currently, no include file info is stored. Thus, we cannot display
1983 accurate messages if the function or data definition spans multiple
1984 files */
1986 /* save current parse state in 's' */
1987 void save_parse_state(ParseState *s)
1989 s->line_num = file->line_num;
1990 s->macro_ptr = macro_ptr;
1991 s->tok = tok;
1992 s->tokc = tokc;
1995 /* restore parse state from 's' */
1996 void restore_parse_state(ParseState *s)
1998 file->line_num = s->line_num;
1999 macro_ptr = s->macro_ptr;
2000 tok = s->tok;
2001 tokc = s->tokc;
2004 /* return the number of additional 'ints' necessary to store the
2005 token */
2006 static inline int tok_ext_size(int t)
2008 switch(t) {
2009 /* 4 bytes */
2010 case TOK_CINT:
2011 case TOK_CUINT:
2012 case TOK_CCHAR:
2013 case TOK_LCHAR:
2014 case TOK_STR:
2015 case TOK_LSTR:
2016 case TOK_CFLOAT:
2017 case TOK_LINENUM:
2018 case TOK_PPNUM:
2019 return 1;
2020 case TOK_CDOUBLE:
2021 case TOK_CLLONG:
2022 case TOK_CULLONG:
2023 return 2;
2024 case TOK_CLDOUBLE:
2025 return LDOUBLE_SIZE / 4;
2026 default:
2027 return 0;
2031 /* token string handling */
2033 static inline void tok_str_new(TokenString *s)
2035 s->str = NULL;
2036 s->len = 0;
2037 s->allocated_len = 0;
2038 s->last_line_num = -1;
2041 static void tok_str_free(int *str)
2043 const int *p;
2044 CString *cstr;
2045 int t;
2047 p = str;
2048 for(;;) {
2049 t = *p;
2050 /* NOTE: we test zero separately so that GCC can generate a
2051 table for the following switch */
2052 if (t == 0)
2053 break;
2054 switch(t) {
2055 case TOK_CINT:
2056 case TOK_CUINT:
2057 case TOK_CCHAR:
2058 case TOK_LCHAR:
2059 case TOK_CFLOAT:
2060 case TOK_LINENUM:
2061 p += 2;
2062 break;
2063 case TOK_PPNUM:
2064 case TOK_STR:
2065 case TOK_LSTR:
2066 /* XXX: use a macro to be portable on 64 bit ? */
2067 cstr = (CString *)p[1];
2068 cstr_free(cstr);
2069 tcc_free(cstr);
2070 p += 2;
2071 break;
2072 case TOK_CDOUBLE:
2073 case TOK_CLLONG:
2074 case TOK_CULLONG:
2075 p += 3;
2076 break;
2077 case TOK_CLDOUBLE:
2078 p += 1 + (LDOUBLE_SIZE / 4);
2079 break;
2080 default:
2081 p++;
2082 break;
2085 tcc_free(str);
2088 static int *tok_str_realloc(TokenString *s)
2090 int *str, len;
2092 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2093 str = tcc_realloc(s->str, len * sizeof(int));
2094 if (!str)
2095 error("memory full");
2096 s->allocated_len = len;
2097 s->str = str;
2098 return str;
2101 static void tok_str_add(TokenString *s, int t)
2103 int len, *str;
2105 len = s->len;
2106 str = s->str;
2107 if (len >= s->allocated_len)
2108 str = tok_str_realloc(s);
2109 str[len++] = t;
2110 s->len = len;
2113 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2115 int len, *str;
2117 len = s->len;
2118 str = s->str;
2120 /* allocate space for worst case */
2121 if (len + TOK_MAX_SIZE > s->allocated_len)
2122 str = tok_str_realloc(s);
2123 str[len++] = t;
2124 switch(t) {
2125 case TOK_CINT:
2126 case TOK_CUINT:
2127 case TOK_CCHAR:
2128 case TOK_LCHAR:
2129 case TOK_CFLOAT:
2130 case TOK_LINENUM:
2131 str[len++] = cv->tab[0];
2132 break;
2133 case TOK_PPNUM:
2134 case TOK_STR:
2135 case TOK_LSTR:
2136 str[len++] = (int)cstr_dup(cv->cstr);
2137 break;
2138 case TOK_CDOUBLE:
2139 case TOK_CLLONG:
2140 case TOK_CULLONG:
2141 str[len++] = cv->tab[0];
2142 str[len++] = cv->tab[1];
2143 break;
2144 case TOK_CLDOUBLE:
2145 #if LDOUBLE_SIZE == 12
2146 str[len++] = cv->tab[0];
2147 str[len++] = cv->tab[1];
2148 str[len++] = cv->tab[2];
2149 #else
2150 #error add long double size support
2151 #endif
2152 break;
2153 default:
2154 break;
2156 s->len = len;
2159 /* add the current parse token in token string 's' */
2160 static void tok_str_add_tok(TokenString *s)
2162 CValue cval;
2164 /* save line number info */
2165 if (file->line_num != s->last_line_num) {
2166 s->last_line_num = file->line_num;
2167 cval.i = s->last_line_num;
2168 tok_str_add2(s, TOK_LINENUM, &cval);
2170 tok_str_add2(s, tok, &tokc);
2173 #if LDOUBLE_SIZE == 12
2174 #define LDOUBLE_GET(p, cv) \
2175 cv.tab[0] = p[0]; \
2176 cv.tab[1] = p[1]; \
2177 cv.tab[2] = p[2];
2178 #else
2179 #error add long double size support
2180 #endif
2183 /* get a token from an integer array and increment pointer
2184 accordingly. we code it as a macro to avoid pointer aliasing. */
2185 #define TOK_GET(t, p, cv) \
2187 t = *p++; \
2188 switch(t) { \
2189 case TOK_CINT: \
2190 case TOK_CUINT: \
2191 case TOK_CCHAR: \
2192 case TOK_LCHAR: \
2193 case TOK_CFLOAT: \
2194 case TOK_LINENUM: \
2195 case TOK_STR: \
2196 case TOK_LSTR: \
2197 case TOK_PPNUM: \
2198 cv.tab[0] = *p++; \
2199 break; \
2200 case TOK_CDOUBLE: \
2201 case TOK_CLLONG: \
2202 case TOK_CULLONG: \
2203 cv.tab[0] = p[0]; \
2204 cv.tab[1] = p[1]; \
2205 p += 2; \
2206 break; \
2207 case TOK_CLDOUBLE: \
2208 LDOUBLE_GET(p, cv); \
2209 p += LDOUBLE_SIZE / 4; \
2210 break; \
2211 default: \
2212 break; \
2216 /* defines handling */
2217 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2219 Sym *s;
2221 s = sym_push2(&define_stack, v, macro_type, (int)str);
2222 s->next = first_arg;
2223 table_ident[v - TOK_IDENT]->sym_define = s;
2226 /* undefined a define symbol. Its name is just set to zero */
2227 static void define_undef(Sym *s)
2229 int v;
2230 v = s->v;
2231 if (v >= TOK_IDENT && v < tok_ident)
2232 table_ident[v - TOK_IDENT]->sym_define = NULL;
2233 s->v = 0;
2236 static inline Sym *define_find(int v)
2238 v -= TOK_IDENT;
2239 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2240 return NULL;
2241 return table_ident[v]->sym_define;
2244 /* free define stack until top reaches 'b' */
2245 static void free_defines(Sym *b)
2247 Sym *top, *top1;
2248 int v;
2250 top = define_stack;
2251 while (top != b) {
2252 top1 = top->prev;
2253 /* do not free args or predefined defines */
2254 if (top->c)
2255 tok_str_free((int *)top->c);
2256 v = top->v;
2257 if (v >= TOK_IDENT && v < tok_ident)
2258 table_ident[v - TOK_IDENT]->sym_define = NULL;
2259 tcc_free(top);
2260 top = top1;
2262 define_stack = b;
2265 /* label lookup */
2266 static Sym *label_find(int v)
2268 v -= TOK_IDENT;
2269 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2270 return NULL;
2271 return table_ident[v]->sym_label;
2274 static Sym *label_push(Sym **ptop, int v, int flags)
2276 Sym *s, **ps;
2277 s = sym_push2(ptop, v, 0, 0);
2278 s->r = flags;
2279 ps = &table_ident[v - TOK_IDENT]->sym_label;
2280 if (ptop == &global_label_stack) {
2281 /* modify the top most local identifier, so that
2282 sym_identifier will point to 's' when popped */
2283 while (*ps != NULL)
2284 ps = &(*ps)->prev_tok;
2286 s->prev_tok = *ps;
2287 *ps = s;
2288 return s;
2291 /* pop labels until element last is reached. Look if any labels are
2292 undefined. Define symbols if '&&label' was used. */
2293 static void label_pop(Sym **ptop, Sym *slast)
2295 Sym *s, *s1;
2296 for(s = *ptop; s != slast; s = s1) {
2297 s1 = s->prev;
2298 if (s->r == LABEL_DECLARED) {
2299 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2300 } else if (s->r == LABEL_FORWARD) {
2301 error("label '%s' used but not defined",
2302 get_tok_str(s->v, NULL));
2303 } else {
2304 if (s->c) {
2305 /* define corresponding symbol. A size of
2306 1 is put. */
2307 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2310 /* remove label */
2311 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2312 tcc_free(s);
2314 *ptop = slast;
2317 /* eval an expression for #if/#elif */
2318 static int expr_preprocess(void)
2320 int c, t;
2321 TokenString str;
2323 tok_str_new(&str);
2324 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2325 next(); /* do macro subst */
2326 if (tok == TOK_DEFINED) {
2327 next_nomacro();
2328 t = tok;
2329 if (t == '(')
2330 next_nomacro();
2331 c = define_find(tok) != 0;
2332 if (t == '(')
2333 next_nomacro();
2334 tok = TOK_CINT;
2335 tokc.i = c;
2336 } else if (tok >= TOK_IDENT) {
2337 /* if undefined macro */
2338 tok = TOK_CINT;
2339 tokc.i = 0;
2341 tok_str_add_tok(&str);
2343 tok_str_add(&str, -1); /* simulate end of file */
2344 tok_str_add(&str, 0);
2345 /* now evaluate C constant expression */
2346 macro_ptr = str.str;
2347 next();
2348 c = expr_const();
2349 macro_ptr = NULL;
2350 tok_str_free(str.str);
2351 return c != 0;
2354 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2355 static void tok_print(int *str)
2357 int t;
2358 CValue cval;
2360 while (1) {
2361 TOK_GET(t, str, cval);
2362 if (!t)
2363 break;
2364 printf(" %s", get_tok_str(t, &cval));
2366 printf("\n");
2368 #endif
2370 /* parse after #define */
2371 static void parse_define(void)
2373 Sym *s, *first, **ps;
2374 int v, t, varg, is_vaargs, c;
2375 TokenString str;
2377 v = tok;
2378 if (v < TOK_IDENT)
2379 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2380 /* XXX: should check if same macro (ANSI) */
2381 first = NULL;
2382 t = MACRO_OBJ;
2383 /* '(' must be just after macro definition for MACRO_FUNC */
2384 c = file->buf_ptr[0];
2385 if (c == '\\')
2386 c = handle_stray1(file->buf_ptr);
2387 if (c == '(') {
2388 next_nomacro();
2389 next_nomacro();
2390 ps = &first;
2391 while (tok != ')') {
2392 varg = tok;
2393 next_nomacro();
2394 is_vaargs = 0;
2395 if (varg == TOK_DOTS) {
2396 varg = TOK___VA_ARGS__;
2397 is_vaargs = 1;
2398 } else if (tok == TOK_DOTS && gnu_ext) {
2399 is_vaargs = 1;
2400 next_nomacro();
2402 if (varg < TOK_IDENT)
2403 error("badly punctuated parameter list");
2404 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2405 *ps = s;
2406 ps = &s->next;
2407 if (tok != ',')
2408 break;
2409 next_nomacro();
2411 t = MACRO_FUNC;
2413 tok_str_new(&str);
2414 next_nomacro();
2415 /* EOF testing necessary for '-D' handling */
2416 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2417 tok_str_add2(&str, tok, &tokc);
2418 next_nomacro();
2420 tok_str_add(&str, 0);
2421 #ifdef PP_DEBUG
2422 printf("define %s %d: ", get_tok_str(v, NULL), t);
2423 tok_print(str.str);
2424 #endif
2425 define_push(v, t, str.str, first);
2428 /* XXX: use a token or a hash table to accelerate matching ? */
2429 static CachedInclude *search_cached_include(TCCState *s1,
2430 int type, const char *filename)
2432 CachedInclude *e;
2433 int i;
2435 for(i = 0;i < s1->nb_cached_includes; i++) {
2436 e = s1->cached_includes[i];
2437 if (e->type == type && !strcmp(e->filename, filename))
2438 return e;
2440 return NULL;
2443 static inline void add_cached_include(TCCState *s1, int type,
2444 const char *filename, int ifndef_macro)
2446 CachedInclude *e;
2448 if (search_cached_include(s1, type, filename))
2449 return;
2450 #ifdef INC_DEBUG
2451 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2452 #endif
2453 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2454 if (!e)
2455 return;
2456 e->type = type;
2457 strcpy(e->filename, filename);
2458 e->ifndef_macro = ifndef_macro;
2459 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2462 /* is_bof is true if first non space token at beginning of file */
2463 static void preprocess(int is_bof)
2465 TCCState *s1 = tcc_state;
2466 int size, i, c, n, saved_parse_flags;
2467 char buf[1024], *q, *p;
2468 char buf1[1024];
2469 BufferedFile *f;
2470 Sym *s;
2471 CachedInclude *e;
2473 saved_parse_flags = parse_flags;
2474 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2475 PARSE_FLAG_LINEFEED;
2476 next_nomacro();
2477 redo:
2478 switch(tok) {
2479 case TOK_DEFINE:
2480 next_nomacro();
2481 parse_define();
2482 break;
2483 case TOK_UNDEF:
2484 next_nomacro();
2485 s = define_find(tok);
2486 /* undefine symbol by putting an invalid name */
2487 if (s)
2488 define_undef(s);
2489 break;
2490 case TOK_INCLUDE:
2491 ch = file->buf_ptr[0];
2492 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2493 skip_spaces();
2494 if (ch == '<') {
2495 c = '>';
2496 goto read_name;
2497 } else if (ch == '\"') {
2498 c = ch;
2499 read_name:
2500 /* XXX: better stray handling */
2501 minp();
2502 q = buf;
2503 while (ch != c && ch != '\n' && ch != CH_EOF) {
2504 if ((q - buf) < sizeof(buf) - 1)
2505 *q++ = ch;
2506 minp();
2508 *q = '\0';
2509 minp();
2510 #if 0
2511 /* eat all spaces and comments after include */
2512 /* XXX: slightly incorrect */
2513 while (ch1 != '\n' && ch1 != CH_EOF)
2514 inp();
2515 #endif
2516 } else {
2517 /* computed #include : either we have only strings or
2518 we have anything enclosed in '<>' */
2519 next();
2520 buf[0] = '\0';
2521 if (tok == TOK_STR) {
2522 while (tok != TOK_LINEFEED) {
2523 if (tok != TOK_STR) {
2524 include_syntax:
2525 error("'#include' expects \"FILENAME\" or <FILENAME>");
2527 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2528 next();
2530 c = '\"';
2531 } else {
2532 int len;
2533 while (tok != TOK_LINEFEED) {
2534 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2535 next();
2537 len = strlen(buf);
2538 /* check syntax and remove '<>' */
2539 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2540 goto include_syntax;
2541 memmove(buf, buf + 1, len - 2);
2542 buf[len - 2] = '\0';
2543 c = '>';
2547 e = search_cached_include(s1, c, buf);
2548 if (e && define_find(e->ifndef_macro)) {
2549 /* no need to parse the include because the 'ifndef macro'
2550 is defined */
2551 #ifdef INC_DEBUG
2552 printf("%s: skipping %s\n", file->filename, buf);
2553 #endif
2554 } else {
2555 if (c == '\"') {
2556 /* first search in current dir if "header.h" */
2557 size = 0;
2558 p = strrchr(file->filename, '/');
2559 if (p)
2560 size = p + 1 - file->filename;
2561 if (size > sizeof(buf1) - 1)
2562 size = sizeof(buf1) - 1;
2563 memcpy(buf1, file->filename, size);
2564 buf1[size] = '\0';
2565 pstrcat(buf1, sizeof(buf1), buf);
2566 f = tcc_open(s1, buf1);
2567 if (f)
2568 goto found;
2570 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2571 error("#include recursion too deep");
2572 /* now search in all the include paths */
2573 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2574 for(i = 0; i < n; i++) {
2575 const char *path;
2576 if (i < s1->nb_include_paths)
2577 path = s1->include_paths[i];
2578 else
2579 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2580 pstrcpy(buf1, sizeof(buf1), path);
2581 pstrcat(buf1, sizeof(buf1), "/");
2582 pstrcat(buf1, sizeof(buf1), buf);
2583 f = tcc_open(s1, buf1);
2584 if (f)
2585 goto found;
2587 error("include file '%s' not found", buf);
2588 f = NULL;
2589 found:
2590 #ifdef INC_DEBUG
2591 printf("%s: including %s\n", file->filename, buf1);
2592 #endif
2593 f->inc_type = c;
2594 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2595 /* push current file in stack */
2596 /* XXX: fix current line init */
2597 *s1->include_stack_ptr++ = file;
2598 file = f;
2599 /* add include file debug info */
2600 if (do_debug) {
2601 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2603 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2604 ch = file->buf_ptr[0];
2605 goto the_end;
2607 break;
2608 case TOK_IFNDEF:
2609 c = 1;
2610 goto do_ifdef;
2611 case TOK_IF:
2612 c = expr_preprocess();
2613 goto do_if;
2614 case TOK_IFDEF:
2615 c = 0;
2616 do_ifdef:
2617 next_nomacro();
2618 if (tok < TOK_IDENT)
2619 error("invalid argument for '#if%sdef'", c ? "n" : "");
2620 if (is_bof) {
2621 if (c) {
2622 #ifdef INC_DEBUG
2623 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2624 #endif
2625 file->ifndef_macro = tok;
2628 c = (define_find(tok) != 0) ^ c;
2629 do_if:
2630 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2631 error("memory full");
2632 *s1->ifdef_stack_ptr++ = c;
2633 goto test_skip;
2634 case TOK_ELSE:
2635 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2636 error("#else without matching #if");
2637 if (s1->ifdef_stack_ptr[-1] & 2)
2638 error("#else after #else");
2639 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2640 goto test_skip;
2641 case TOK_ELIF:
2642 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2643 error("#elif without matching #if");
2644 c = s1->ifdef_stack_ptr[-1];
2645 if (c > 1)
2646 error("#elif after #else");
2647 /* last #if/#elif expression was true: we skip */
2648 if (c == 1)
2649 goto skip;
2650 c = expr_preprocess();
2651 s1->ifdef_stack_ptr[-1] = c;
2652 test_skip:
2653 if (!(c & 1)) {
2654 skip:
2655 preprocess_skip();
2656 is_bof = 0;
2657 goto redo;
2659 break;
2660 case TOK_ENDIF:
2661 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2662 error("#endif without matching #if");
2663 s1->ifdef_stack_ptr--;
2664 /* '#ifndef macro' was at the start of file. Now we check if
2665 an '#endif' is exactly at the end of file */
2666 if (file->ifndef_macro &&
2667 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2668 file->ifndef_macro_saved = file->ifndef_macro;
2669 /* need to set to zero to avoid false matches if another
2670 #ifndef at middle of file */
2671 file->ifndef_macro = 0;
2672 while (tok != TOK_LINEFEED)
2673 next_nomacro();
2674 tok_flags |= TOK_FLAG_ENDIF;
2675 goto the_end;
2677 break;
2678 case TOK_LINE:
2679 next();
2680 if (tok != TOK_CINT)
2681 error("#line");
2682 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2683 next();
2684 if (tok != TOK_LINEFEED) {
2685 if (tok != TOK_STR)
2686 error("#line");
2687 pstrcpy(file->filename, sizeof(file->filename),
2688 (char *)tokc.cstr->data);
2690 break;
2691 case TOK_ERROR:
2692 case TOK_WARNING:
2693 c = tok;
2694 ch = file->buf_ptr[0];
2695 skip_spaces();
2696 q = buf;
2697 while (ch != '\n' && ch != CH_EOF) {
2698 if ((q - buf) < sizeof(buf) - 1)
2699 *q++ = ch;
2700 minp();
2702 *q = '\0';
2703 if (c == TOK_ERROR)
2704 error("#error %s", buf);
2705 else
2706 warning("#warning %s", buf);
2707 break;
2708 case TOK_PRAGMA:
2709 /* ignored */
2710 break;
2711 default:
2712 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2713 /* '!' is ignored to allow C scripts. numbers are ignored
2714 to emulate cpp behaviour */
2715 } else {
2716 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2718 break;
2720 /* ignore other preprocess commands or #! for C scripts */
2721 while (tok != TOK_LINEFEED)
2722 next_nomacro();
2723 the_end:
2724 parse_flags = saved_parse_flags;
2727 /* read a number in base b */
2728 static int getn(int b)
2730 int n, t;
2731 n = 0;
2732 while (1) {
2733 if (ch >= 'a' && ch <= 'f')
2734 t = ch - 'a' + 10;
2735 else if (ch >= 'A' && ch <= 'F')
2736 t = ch - 'A' + 10;
2737 else if (isnum(ch))
2738 t = ch - '0';
2739 else
2740 break;
2741 if (t < 0 || t >= b)
2742 break;
2743 n = n * b + t;
2744 inp();
2746 return n;
2749 /* read a character for string or char constant and eval escape codes */
2750 static int getq(void)
2752 int c;
2754 redo:
2755 c = ch;
2756 inp();
2757 if (c == '\\') {
2758 switch(ch) {
2759 case '0': case '1': case '2': case '3':
2760 case '4': case '5': case '6': case '7':
2761 /* at most three octal digits */
2762 c = ch - '0';
2763 inp();
2764 if (isoct(ch)) {
2765 c = c * 8 + ch - '0';
2766 inp();
2767 if (isoct(ch)) {
2768 c = c * 8 + ch - '0';
2769 inp();
2772 return c;
2773 case 'x':
2774 inp();
2775 return getn(16);
2776 case 'a':
2777 c = '\a';
2778 break;
2779 case 'b':
2780 c = '\b';
2781 break;
2782 case 'f':
2783 c = '\f';
2784 break;
2785 case 'n':
2786 c = '\n';
2787 break;
2788 case 'r':
2789 c = '\r';
2790 break;
2791 case 't':
2792 c = '\t';
2793 break;
2794 case 'v':
2795 c = '\v';
2796 break;
2797 case 'e':
2798 if (!gnu_ext)
2799 goto invalid_escape;
2800 c = 27;
2801 break;
2802 case '\'':
2803 case '\"':
2804 case '\\':
2805 case '?':
2806 c = ch;
2807 break;
2808 case '\n':
2809 inp();
2810 goto redo;
2811 case '\r':
2812 inp();
2813 if (ch != '\n')
2814 goto invalid_escape;
2815 inp();
2816 goto redo;
2817 default:
2818 invalid_escape:
2819 error("invalid escaped char");
2821 inp();
2822 } else if (c == '\r' && ch == '\n') {
2823 inp();
2824 c = '\n';
2826 return c;
2829 /* we use 64 bit numbers */
2830 #define BN_SIZE 2
2832 /* bn = (bn << shift) | or_val */
2833 void bn_lshift(unsigned int *bn, int shift, int or_val)
2835 int i;
2836 unsigned int v;
2837 for(i=0;i<BN_SIZE;i++) {
2838 v = bn[i];
2839 bn[i] = (v << shift) | or_val;
2840 or_val = v >> (32 - shift);
2844 void bn_zero(unsigned int *bn)
2846 int i;
2847 for(i=0;i<BN_SIZE;i++) {
2848 bn[i] = 0;
2852 /* parse number in null terminated string 'p' and return it in the
2853 current token */
2854 void parse_number(const char *p)
2856 int b, t, shift, frac_bits, s, exp_val, ch;
2857 char *q;
2858 unsigned int bn[BN_SIZE];
2859 double d;
2861 /* number */
2862 q = token_buf;
2863 ch = *p++;
2864 t = ch;
2865 ch = *p++;
2866 *q++ = t;
2867 b = 10;
2868 if (t == '.') {
2869 goto float_frac_parse;
2870 } else if (t == '0') {
2871 if (ch == 'x' || ch == 'X') {
2872 q--;
2873 ch = *p++;
2874 b = 16;
2875 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2876 q--;
2877 ch = *p++;
2878 b = 2;
2881 /* parse all digits. cannot check octal numbers at this stage
2882 because of floating point constants */
2883 while (1) {
2884 if (ch >= 'a' && ch <= 'f')
2885 t = ch - 'a' + 10;
2886 else if (ch >= 'A' && ch <= 'F')
2887 t = ch - 'A' + 10;
2888 else if (isnum(ch))
2889 t = ch - '0';
2890 else
2891 break;
2892 if (t >= b)
2893 break;
2894 if (q >= token_buf + STRING_MAX_SIZE) {
2895 num_too_long:
2896 error("number too long");
2898 *q++ = ch;
2899 ch = *p++;
2901 if (ch == '.' ||
2902 ((ch == 'e' || ch == 'E') && b == 10) ||
2903 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
2904 if (b != 10) {
2905 /* NOTE: strtox should support that for hexa numbers, but
2906 non ISOC99 libcs do not support it, so we prefer to do
2907 it by hand */
2908 /* hexadecimal or binary floats */
2909 /* XXX: handle overflows */
2910 *q = '\0';
2911 if (b == 16)
2912 shift = 4;
2913 else
2914 shift = 2;
2915 bn_zero(bn);
2916 q = token_buf;
2917 while (1) {
2918 t = *q++;
2919 if (t == '\0') {
2920 break;
2921 } else if (t >= 'a') {
2922 t = t - 'a' + 10;
2923 } else if (t >= 'A') {
2924 t = t - 'A' + 10;
2925 } else {
2926 t = t - '0';
2928 bn_lshift(bn, shift, t);
2930 frac_bits = 0;
2931 if (ch == '.') {
2932 ch = *p++;
2933 while (1) {
2934 t = ch;
2935 if (t >= 'a' && t <= 'f') {
2936 t = t - 'a' + 10;
2937 } else if (t >= 'A' && t <= 'F') {
2938 t = t - 'A' + 10;
2939 } else if (t >= '0' && t <= '9') {
2940 t = t - '0';
2941 } else {
2942 break;
2944 if (t >= b)
2945 error("invalid digit");
2946 bn_lshift(bn, shift, t);
2947 frac_bits += shift;
2948 ch = *p++;
2951 if (ch != 'p' && ch != 'P')
2952 expect("exponent");
2953 ch = *p++;
2954 s = 1;
2955 exp_val = 0;
2956 if (ch == '+') {
2957 ch = *p++;
2958 } else if (ch == '-') {
2959 s = -1;
2960 ch = *p++;
2962 if (ch < '0' || ch > '9')
2963 expect("exponent digits");
2964 while (ch >= '0' && ch <= '9') {
2965 exp_val = exp_val * 10 + ch - '0';
2966 ch = *p++;
2968 exp_val = exp_val * s;
2970 /* now we can generate the number */
2971 /* XXX: should patch directly float number */
2972 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
2973 d = ldexp(d, exp_val - frac_bits);
2974 t = toup(ch);
2975 if (t == 'F') {
2976 ch = *p++;
2977 tok = TOK_CFLOAT;
2978 /* float : should handle overflow */
2979 tokc.f = (float)d;
2980 } else if (t == 'L') {
2981 ch = *p++;
2982 tok = TOK_CLDOUBLE;
2983 /* XXX: not large enough */
2984 tokc.ld = (long double)d;
2985 } else {
2986 tok = TOK_CDOUBLE;
2987 tokc.d = d;
2989 } else {
2990 /* decimal floats */
2991 if (ch == '.') {
2992 if (q >= token_buf + STRING_MAX_SIZE)
2993 goto num_too_long;
2994 *q++ = ch;
2995 ch = *p++;
2996 float_frac_parse:
2997 while (ch >= '0' && ch <= '9') {
2998 if (q >= token_buf + STRING_MAX_SIZE)
2999 goto num_too_long;
3000 *q++ = ch;
3001 ch = *p++;
3004 if (ch == 'e' || ch == 'E') {
3005 if (q >= token_buf + STRING_MAX_SIZE)
3006 goto num_too_long;
3007 *q++ = ch;
3008 ch = *p++;
3009 if (ch == '-' || ch == '+') {
3010 if (q >= token_buf + STRING_MAX_SIZE)
3011 goto num_too_long;
3012 *q++ = ch;
3013 ch = *p++;
3015 if (ch < '0' || ch > '9')
3016 expect("exponent digits");
3017 while (ch >= '0' && ch <= '9') {
3018 if (q >= token_buf + STRING_MAX_SIZE)
3019 goto num_too_long;
3020 *q++ = ch;
3021 ch = *p++;
3024 *q = '\0';
3025 t = toup(ch);
3026 errno = 0;
3027 if (t == 'F') {
3028 ch = *p++;
3029 tok = TOK_CFLOAT;
3030 tokc.f = strtof(token_buf, NULL);
3031 } else if (t == 'L') {
3032 ch = *p++;
3033 tok = TOK_CLDOUBLE;
3034 tokc.ld = strtold(token_buf, NULL);
3035 } else {
3036 tok = TOK_CDOUBLE;
3037 tokc.d = strtod(token_buf, NULL);
3040 } else {
3041 unsigned long long n, n1;
3042 int lcount, ucount;
3044 /* integer number */
3045 *q = '\0';
3046 q = token_buf;
3047 if (b == 10 && *q == '0') {
3048 b = 8;
3049 q++;
3051 n = 0;
3052 while(1) {
3053 t = *q++;
3054 /* no need for checks except for base 10 / 8 errors */
3055 if (t == '\0') {
3056 break;
3057 } else if (t >= 'a') {
3058 t = t - 'a' + 10;
3059 } else if (t >= 'A') {
3060 t = t - 'A' + 10;
3061 } else {
3062 t = t - '0';
3063 if (t >= b)
3064 error("invalid digit");
3066 n1 = n;
3067 n = n * b + t;
3068 /* detect overflow */
3069 /* XXX: this test is not reliable */
3070 if (n < n1)
3071 error("integer constant overflow");
3074 /* XXX: not exactly ANSI compliant */
3075 if ((n & 0xffffffff00000000LL) != 0) {
3076 if ((n >> 63) != 0)
3077 tok = TOK_CULLONG;
3078 else
3079 tok = TOK_CLLONG;
3080 } else if (n > 0x7fffffff) {
3081 tok = TOK_CUINT;
3082 } else {
3083 tok = TOK_CINT;
3085 lcount = 0;
3086 ucount = 0;
3087 for(;;) {
3088 t = toup(ch);
3089 if (t == 'L') {
3090 if (lcount >= 2)
3091 error("three 'l's in integer constant");
3092 lcount++;
3093 if (lcount == 2) {
3094 if (tok == TOK_CINT)
3095 tok = TOK_CLLONG;
3096 else if (tok == TOK_CUINT)
3097 tok = TOK_CULLONG;
3099 ch = *p++;
3100 } else if (t == 'U') {
3101 if (ucount >= 1)
3102 error("two 'u's in integer constant");
3103 ucount++;
3104 if (tok == TOK_CINT)
3105 tok = TOK_CUINT;
3106 else if (tok == TOK_CLLONG)
3107 tok = TOK_CULLONG;
3108 ch = *p++;
3109 } else {
3110 break;
3113 if (tok == TOK_CINT || tok == TOK_CUINT)
3114 tokc.ui = n;
3115 else
3116 tokc.ull = n;
3121 #define PARSE2(c1, tok1, c2, tok2) \
3122 case c1: \
3123 PEEKC(c, p); \
3124 if (c == c2) { \
3125 p++; \
3126 tok = tok2; \
3127 } else { \
3128 tok = tok1; \
3130 break;
3132 /* return next token without macro substitution */
3133 static inline void next_nomacro1(void)
3135 int b, t, c;
3136 TokenSym *ts;
3137 uint8_t *p, *p1;
3138 unsigned int h;
3140 p = file->buf_ptr;
3141 redo_no_start:
3142 c = *p;
3143 switch(c) {
3144 case ' ':
3145 case '\t':
3146 case '\f':
3147 case '\v':
3148 case '\r':
3149 p++;
3150 goto redo_no_start;
3152 case '\\':
3153 /* first look if it is in fact an end of buffer */
3154 if (p >= file->buf_end) {
3155 file->buf_ptr = p;
3156 handle_eob();
3157 p = file->buf_ptr;
3158 if (p >= file->buf_end)
3159 goto parse_eof;
3160 else
3161 goto redo_no_start;
3162 } else {
3163 file->buf_ptr = p;
3164 ch = *p;
3165 handle_stray();
3166 p = file->buf_ptr;
3167 goto redo_no_start;
3169 parse_eof:
3171 TCCState *s1 = tcc_state;
3172 if (parse_flags & PARSE_FLAG_LINEFEED) {
3173 tok = TOK_LINEFEED;
3174 } else if (s1->include_stack_ptr == s1->include_stack ||
3175 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3176 /* no include left : end of file. */
3177 tok = TOK_EOF;
3178 } else {
3179 /* pop include file */
3181 /* test if previous '#endif' was after a #ifdef at
3182 start of file */
3183 if (tok_flags & TOK_FLAG_ENDIF) {
3184 #ifdef INC_DEBUG
3185 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3186 #endif
3187 add_cached_include(s1, file->inc_type, file->inc_filename,
3188 file->ifndef_macro_saved);
3191 /* add end of include file debug info */
3192 if (do_debug) {
3193 put_stabd(N_EINCL, 0, 0);
3195 /* pop include stack */
3196 tcc_close(file);
3197 s1->include_stack_ptr--;
3198 file = *s1->include_stack_ptr;
3199 p = file->buf_ptr;
3200 goto redo_no_start;
3203 break;
3205 case '\n':
3206 if (parse_flags & PARSE_FLAG_LINEFEED) {
3207 tok = TOK_LINEFEED;
3208 } else {
3209 file->line_num++;
3210 tok_flags |= TOK_FLAG_BOL;
3211 p++;
3212 goto redo_no_start;
3214 break;
3216 case '#':
3217 /* XXX: simplify */
3218 PEEKC(c, p);
3219 if ((tok_flags & TOK_FLAG_BOL) &&
3220 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3221 file->buf_ptr = p;
3222 preprocess(tok_flags & TOK_FLAG_BOF);
3223 p = file->buf_ptr;
3224 goto redo_no_start;
3225 } else {
3226 if (c == '#') {
3227 p++;
3228 tok = TOK_TWOSHARPS;
3229 } else {
3230 tok = '#';
3233 break;
3235 case 'a': case 'b': case 'c': case 'd':
3236 case 'e': case 'f': case 'g': case 'h':
3237 case 'i': case 'j': case 'k': case 'l':
3238 case 'm': case 'n': case 'o': case 'p':
3239 case 'q': case 'r': case 's': case 't':
3240 case 'u': case 'v': case 'w': case 'x':
3241 case 'y': case 'z':
3242 case 'A': case 'B': case 'C': case 'D':
3243 case 'E': case 'F': case 'G': case 'H':
3244 case 'I': case 'J': case 'K':
3245 case 'M': case 'N': case 'O': case 'P':
3246 case 'Q': case 'R': case 'S': case 'T':
3247 case 'U': case 'V': case 'W': case 'X':
3248 case 'Y': case 'Z':
3249 case '_':
3250 parse_ident_fast:
3251 p1 = p;
3252 h = TOK_HASH_INIT;
3253 h = TOK_HASH_FUNC(h, c);
3254 p++;
3255 for(;;) {
3256 c = *p;
3257 if (!isidnum_table[c])
3258 break;
3259 h = TOK_HASH_FUNC(h, c);
3260 p++;
3262 if (c != '\\') {
3263 TokenSym **pts;
3264 int len;
3266 /* fast case : no stray found, so we have the full token
3267 and we have already hashed it */
3268 len = p - p1;
3269 h &= (TOK_HASH_SIZE - 1);
3270 pts = &hash_ident[h];
3271 for(;;) {
3272 ts = *pts;
3273 if (!ts)
3274 break;
3275 if (ts->len == len && !memcmp(ts->str, p1, len))
3276 goto token_found;
3277 pts = &(ts->hash_next);
3279 ts = tok_alloc_new(pts, p1, len);
3280 token_found: ;
3281 } else {
3282 /* slower case */
3283 cstr_reset(&tokcstr);
3285 while (p1 < p) {
3286 cstr_ccat(&tokcstr, *p1);
3287 p1++;
3289 p--;
3290 PEEKC(c, p);
3291 parse_ident_slow:
3292 while (isidnum_table[c]) {
3293 cstr_ccat(&tokcstr, c);
3294 PEEKC(c, p);
3296 ts = tok_alloc(tokcstr.data, tokcstr.size);
3298 tok = ts->tok;
3299 break;
3300 case 'L':
3301 t = p[1];
3302 if (t != '\\' && t != '\'' && t != '\"') {
3303 /* fast case */
3304 goto parse_ident_fast;
3305 } else {
3306 PEEKC(c, p);
3307 if (c == '\'') {
3308 tok = TOK_LCHAR;
3309 goto char_const;
3310 } else if (c == '\"') {
3311 tok = TOK_LSTR;
3312 goto str_const;
3313 } else {
3314 cstr_reset(&tokcstr);
3315 cstr_ccat(&tokcstr, 'L');
3316 goto parse_ident_slow;
3319 break;
3320 case '0': case '1': case '2': case '3':
3321 case '4': case '5': case '6': case '7':
3322 case '8': case '9':
3324 cstr_reset(&tokcstr);
3325 /* after the first digit, accept digits, alpha, '.' or sign if
3326 prefixed by 'eEpP' */
3327 parse_num:
3328 for(;;) {
3329 t = c;
3330 cstr_ccat(&tokcstr, c);
3331 PEEKC(c, p);
3332 if (!(isnum(c) || isid(c) || c == '.' ||
3333 ((c == '+' || c == '-') &&
3334 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3335 break;
3337 /* We add a trailing '\0' to ease parsing */
3338 cstr_ccat(&tokcstr, '\0');
3339 tokc.cstr = &tokcstr;
3340 tok = TOK_PPNUM;
3341 break;
3342 case '.':
3343 /* special dot handling because it can also start a number */
3344 PEEKC(c, p);
3345 if (isnum(c)) {
3346 cstr_reset(&tokcstr);
3347 cstr_ccat(&tokcstr, '.');
3348 goto parse_num;
3349 } else if (c == '.') {
3350 PEEKC(c, p);
3351 if (c != '.')
3352 expect("'.'");
3353 PEEKC(c, p);
3354 tok = TOK_DOTS;
3355 } else {
3356 tok = '.';
3358 break;
3359 case '\'':
3360 tok = TOK_CCHAR;
3361 char_const:
3362 file->buf_ptr = p;
3363 inp();
3364 b = getq();
3365 /* this cast is needed if >= 128 */
3366 if (tok == TOK_CCHAR)
3367 b = (char)b;
3368 tokc.i = b;
3369 if (ch != '\'')
3370 error("unterminated character constant");
3371 p = file->buf_ptr;
3372 p++;
3373 break;
3374 case '\"':
3375 tok = TOK_STR;
3376 str_const:
3377 file->buf_ptr = p;
3378 inp();
3379 cstr_reset(&tokcstr);
3380 while (ch != '\"') {
3381 b = getq();
3382 if (ch == CH_EOF)
3383 error("unterminated string");
3384 if (tok == TOK_STR)
3385 cstr_ccat(&tokcstr, b);
3386 else
3387 cstr_wccat(&tokcstr, b);
3389 if (tok == TOK_STR)
3390 cstr_ccat(&tokcstr, '\0');
3391 else
3392 cstr_wccat(&tokcstr, '\0');
3393 tokc.cstr = &tokcstr;
3394 p = file->buf_ptr;
3395 p++;
3396 break;
3398 case '<':
3399 PEEKC(c, p);
3400 if (c == '=') {
3401 p++;
3402 tok = TOK_LE;
3403 } else if (c == '<') {
3404 PEEKC(c, p);
3405 if (c == '=') {
3406 p++;
3407 tok = TOK_A_SHL;
3408 } else {
3409 tok = TOK_SHL;
3411 } else {
3412 tok = TOK_LT;
3414 break;
3416 case '>':
3417 PEEKC(c, p);
3418 if (c == '=') {
3419 p++;
3420 tok = TOK_GE;
3421 } else if (c == '>') {
3422 PEEKC(c, p);
3423 if (c == '=') {
3424 p++;
3425 tok = TOK_A_SAR;
3426 } else {
3427 tok = TOK_SAR;
3429 } else {
3430 tok = TOK_GT;
3432 break;
3434 case '&':
3435 PEEKC(c, p);
3436 if (c == '&') {
3437 p++;
3438 tok = TOK_LAND;
3439 } else if (c == '=') {
3440 p++;
3441 tok = TOK_A_AND;
3442 } else {
3443 tok = '&';
3445 break;
3447 case '|':
3448 PEEKC(c, p);
3449 if (c == '|') {
3450 p++;
3451 tok = TOK_LOR;
3452 } else if (c == '=') {
3453 p++;
3454 tok = TOK_A_OR;
3455 } else {
3456 tok = '|';
3458 break;
3460 case '+':
3461 PEEKC(c, p);
3462 if (c == '+') {
3463 p++;
3464 tok = TOK_INC;
3465 } else if (c == '=') {
3466 p++;
3467 tok = TOK_A_ADD;
3468 } else {
3469 tok = '+';
3471 break;
3473 case '-':
3474 PEEKC(c, p);
3475 if (c == '-') {
3476 p++;
3477 tok = TOK_DEC;
3478 } else if (c == '=') {
3479 p++;
3480 tok = TOK_A_SUB;
3481 } else if (c == '>') {
3482 p++;
3483 tok = TOK_ARROW;
3484 } else {
3485 tok = '-';
3487 break;
3489 PARSE2('!', '!', '=', TOK_NE)
3490 PARSE2('=', '=', '=', TOK_EQ)
3491 PARSE2('*', '*', '=', TOK_A_MUL)
3492 PARSE2('%', '%', '=', TOK_A_MOD)
3493 PARSE2('^', '^', '=', TOK_A_XOR)
3495 /* comments or operator */
3496 case '/':
3497 PEEKC(c, p);
3498 if (c == '*') {
3499 file->buf_ptr = p;
3500 parse_comment();
3501 p = file->buf_ptr;
3502 goto redo_no_start;
3503 } else if (c == '/') {
3504 file->buf_ptr = p;
3505 parse_line_comment();
3506 p = file->buf_ptr;
3507 goto redo_no_start;
3508 } else if (c == '=') {
3509 p++;
3510 tok = TOK_A_DIV;
3511 } else {
3512 tok = '/';
3514 break;
3516 /* simple tokens */
3517 case '(':
3518 case ')':
3519 case '[':
3520 case ']':
3521 case '{':
3522 case '}':
3523 case ',':
3524 case ';':
3525 case ':':
3526 case '?':
3527 case '~':
3528 case '$': /* only used in assembler */
3529 tok = c;
3530 p++;
3531 break;
3532 default:
3533 error("unrecognized character \\x%02x", c);
3534 break;
3536 file->buf_ptr = p;
3537 tok_flags = 0;
3538 #if defined(PARSE_DEBUG)
3539 printf("token = %s\n", get_tok_str(tok, &tokc));
3540 #endif
3543 /* return next token without macro substitution. Can read input from
3544 macro_ptr buffer */
3545 static void next_nomacro(void)
3547 if (macro_ptr) {
3548 redo:
3549 tok = *macro_ptr;
3550 if (tok) {
3551 TOK_GET(tok, macro_ptr, tokc);
3552 if (tok == TOK_LINENUM) {
3553 file->line_num = tokc.i;
3554 goto redo;
3557 } else {
3558 next_nomacro1();
3562 /* substitute args in macro_str and return allocated string */
3563 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3565 int *st, last_tok, t, notfirst;
3566 Sym *s;
3567 CValue cval;
3568 TokenString str;
3569 CString cstr;
3571 tok_str_new(&str);
3572 last_tok = 0;
3573 while(1) {
3574 TOK_GET(t, macro_str, cval);
3575 if (!t)
3576 break;
3577 if (t == '#') {
3578 /* stringize */
3579 TOK_GET(t, macro_str, cval);
3580 if (!t)
3581 break;
3582 s = sym_find2(args, t);
3583 if (s) {
3584 cstr_new(&cstr);
3585 st = (int *)s->c;
3586 notfirst = 0;
3587 while (*st) {
3588 if (notfirst)
3589 cstr_ccat(&cstr, ' ');
3590 TOK_GET(t, st, cval);
3591 cstr_cat(&cstr, get_tok_str(t, &cval));
3592 notfirst = 1;
3594 cstr_ccat(&cstr, '\0');
3595 #ifdef PP_DEBUG
3596 printf("stringize: %s\n", (char *)cstr.data);
3597 #endif
3598 /* add string */
3599 cval.cstr = &cstr;
3600 tok_str_add2(&str, TOK_STR, &cval);
3601 cstr_free(&cstr);
3602 } else {
3603 tok_str_add2(&str, t, &cval);
3605 } else if (t >= TOK_IDENT) {
3606 s = sym_find2(args, t);
3607 if (s) {
3608 st = (int *)s->c;
3609 /* if '##' is present before or after, no arg substitution */
3610 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3611 /* special case for var arg macros : ## eats the
3612 ',' if empty VA_ARGS variable. */
3613 /* XXX: test of the ',' is not 100%
3614 reliable. should fix it to avoid security
3615 problems */
3616 if (gnu_ext && s->type.t &&
3617 last_tok == TOK_TWOSHARPS &&
3618 str.len >= 2 && str.str[str.len - 2] == ',') {
3619 if (*st == 0) {
3620 /* suppress ',' '##' */
3621 str.len -= 2;
3622 } else {
3623 /* suppress '##' and add variable */
3624 str.len--;
3625 goto add_var;
3627 } else {
3628 int t1;
3629 add_var:
3630 for(;;) {
3631 TOK_GET(t1, st, cval);
3632 if (!t1)
3633 break;
3634 tok_str_add2(&str, t1, &cval);
3637 } else {
3638 macro_subst(&str, nested_list, st);
3640 } else {
3641 tok_str_add(&str, t);
3643 } else {
3644 tok_str_add2(&str, t, &cval);
3646 last_tok = t;
3648 tok_str_add(&str, 0);
3649 return str.str;
3652 /* do macro substitution of current token with macro 's' and add
3653 result to (tok_str,tok_len). 'nested_list' is the list of all
3654 macros we got inside to avoid recursing. Return non zero if no
3655 substitution needs to be done */
3656 static int macro_subst_tok(TokenString *tok_str,
3657 Sym **nested_list, Sym *s)
3659 Sym *args, *sa, *sa1;
3660 int mstr_allocated, parlevel, *mstr, t;
3661 TokenString str;
3662 char *cstrval;
3663 CValue cval;
3664 CString cstr;
3666 /* if symbol is a macro, prepare substitution */
3668 /* special macros */
3669 if (tok == TOK___LINE__) {
3670 cval.i = file->line_num;
3671 tok_str_add2(tok_str, TOK_CINT, &cval);
3672 } else if (tok == TOK___FILE__) {
3673 cstrval = file->filename;
3674 goto add_cstr;
3675 tok_str_add2(tok_str, TOK_STR, &cval);
3676 } else if (tok == TOK___DATE__) {
3677 cstrval = "Jan 1 2002";
3678 goto add_cstr;
3679 } else if (tok == TOK___TIME__) {
3680 cstrval = "00:00:00";
3681 add_cstr:
3682 cstr_new(&cstr);
3683 cstr_cat(&cstr, cstrval);
3684 cstr_ccat(&cstr, '\0');
3685 cval.cstr = &cstr;
3686 tok_str_add2(tok_str, TOK_STR, &cval);
3687 cstr_free(&cstr);
3688 } else {
3689 mstr = (int *)s->c;
3690 mstr_allocated = 0;
3691 if (s->type.t == MACRO_FUNC) {
3692 /* NOTE: we do not use next_nomacro to avoid eating the
3693 next token. XXX: find better solution */
3694 if (macro_ptr) {
3695 t = *macro_ptr;
3696 } else {
3697 /* XXX: incorrect with comments */
3698 ch = file->buf_ptr[0];
3699 while (is_space(ch) || ch == '\n')
3700 cinp();
3701 t = ch;
3703 if (t != '(') /* no macro subst */
3704 return -1;
3706 /* argument macro */
3707 next_nomacro();
3708 next_nomacro();
3709 args = NULL;
3710 sa = s->next;
3711 /* NOTE: empty args are allowed, except if no args */
3712 for(;;) {
3713 /* handle '()' case */
3714 if (!args && tok == ')')
3715 break;
3716 if (!sa)
3717 error("macro '%s' used with too many args",
3718 get_tok_str(s->v, 0));
3719 tok_str_new(&str);
3720 parlevel = 0;
3721 /* NOTE: non zero sa->t indicates VA_ARGS */
3722 while ((parlevel > 0 ||
3723 (tok != ')' &&
3724 (tok != ',' || sa->type.t))) &&
3725 tok != -1) {
3726 if (tok == '(')
3727 parlevel++;
3728 else if (tok == ')')
3729 parlevel--;
3730 tok_str_add2(&str, tok, &tokc);
3731 next_nomacro();
3733 tok_str_add(&str, 0);
3734 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3735 sa = sa->next;
3736 if (tok == ')') {
3737 /* special case for gcc var args: add an empty
3738 var arg argument if it is omitted */
3739 if (sa && sa->type.t && gnu_ext)
3740 continue;
3741 else
3742 break;
3744 if (tok != ',')
3745 expect(",");
3746 next_nomacro();
3748 if (sa) {
3749 error("macro '%s' used with too few args",
3750 get_tok_str(s->v, 0));
3753 /* now subst each arg */
3754 mstr = macro_arg_subst(nested_list, mstr, args);
3755 /* free memory */
3756 sa = args;
3757 while (sa) {
3758 sa1 = sa->prev;
3759 tok_str_free((int *)sa->c);
3760 tcc_free(sa);
3761 sa = sa1;
3763 mstr_allocated = 1;
3765 sym_push2(nested_list, s->v, 0, 0);
3766 macro_subst(tok_str, nested_list, mstr);
3767 /* pop nested defined symbol */
3768 sa1 = *nested_list;
3769 *nested_list = sa1->prev;
3770 tcc_free(sa1);
3771 if (mstr_allocated)
3772 tok_str_free(mstr);
3774 return 0;
3777 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3778 return the resulting string (which must be freed). */
3779 static inline int *macro_twosharps(const int *macro_str)
3781 TokenSym *ts;
3782 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3783 int t;
3784 const char *p1, *p2;
3785 CValue cval;
3786 TokenString macro_str1;
3787 CString cstr;
3789 start_macro_ptr = macro_str;
3790 /* we search the first '##' */
3791 for(;;) {
3792 macro_ptr1 = macro_str;
3793 TOK_GET(t, macro_str, cval);
3794 /* nothing more to do if end of string */
3795 if (t == 0)
3796 return NULL;
3797 if (*macro_str == TOK_TWOSHARPS)
3798 break;
3801 /* we saw '##', so we need more processing to handle it */
3802 cstr_new(&cstr);
3803 tok_str_new(&macro_str1);
3804 tok = t;
3805 tokc = cval;
3807 /* add all tokens seen so far */
3808 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
3809 TOK_GET(t, ptr, cval);
3810 tok_str_add2(&macro_str1, t, &cval);
3812 saved_macro_ptr = macro_ptr;
3813 /* XXX: get rid of the use of macro_ptr here */
3814 macro_ptr = (int *)macro_str;
3815 for(;;) {
3816 while (*macro_ptr == TOK_TWOSHARPS) {
3817 macro_ptr++;
3818 macro_ptr1 = macro_ptr;
3819 t = *macro_ptr;
3820 if (t) {
3821 TOK_GET(t, macro_ptr, cval);
3822 /* We concatenate the two tokens if we have an
3823 identifier or a preprocessing number */
3824 cstr_reset(&cstr);
3825 p1 = get_tok_str(tok, &tokc);
3826 cstr_cat(&cstr, p1);
3827 p2 = get_tok_str(t, &cval);
3828 cstr_cat(&cstr, p2);
3829 cstr_ccat(&cstr, '\0');
3831 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3832 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3833 if (tok == TOK_PPNUM) {
3834 /* if number, then create a number token */
3835 /* NOTE: no need to allocate because
3836 tok_str_add2() does it */
3837 tokc.cstr = &cstr;
3838 } else {
3839 /* if identifier, we must do a test to
3840 validate we have a correct identifier */
3841 if (t == TOK_PPNUM) {
3842 const char *p;
3843 int c;
3845 p = p2;
3846 for(;;) {
3847 c = *p;
3848 if (c == '\0')
3849 break;
3850 p++;
3851 if (!isnum(c) && !isid(c))
3852 goto error_pasting;
3855 ts = tok_alloc(cstr.data, strlen(cstr.data));
3856 tok = ts->tok; /* modify current token */
3858 } else {
3859 const char *str = cstr.data;
3860 const unsigned char *q;
3862 /* we look for a valid token */
3863 /* XXX: do more extensive checks */
3864 if (!strcmp(str, ">>=")) {
3865 tok = TOK_A_SAR;
3866 } else if (!strcmp(str, "<<=")) {
3867 tok = TOK_A_SHL;
3868 } else if (strlen(str) == 2) {
3869 /* search in two bytes table */
3870 q = tok_two_chars;
3871 for(;;) {
3872 if (!*q)
3873 goto error_pasting;
3874 if (q[0] == str[0] && q[1] == str[1])
3875 break;
3876 q += 3;
3878 tok = q[2];
3879 } else {
3880 error_pasting:
3881 /* NOTE: because get_tok_str use a static buffer,
3882 we must save it */
3883 cstr_reset(&cstr);
3884 p1 = get_tok_str(tok, &tokc);
3885 cstr_cat(&cstr, p1);
3886 cstr_ccat(&cstr, '\0');
3887 p2 = get_tok_str(t, &cval);
3888 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
3889 /* cannot merge tokens: just add them separately */
3890 tok_str_add2(&macro_str1, tok, &tokc);
3891 /* XXX: free associated memory ? */
3892 tok = t;
3893 tokc = cval;
3898 tok_str_add2(&macro_str1, tok, &tokc);
3899 next_nomacro();
3900 if (tok == 0)
3901 break;
3903 macro_ptr = (int *)saved_macro_ptr;
3904 cstr_free(&cstr);
3905 tok_str_add(&macro_str1, 0);
3906 return macro_str1.str;
3910 /* do macro substitution of macro_str and add result to
3911 (tok_str,tok_len). 'nested_list' is the list of all macros we got
3912 inside to avoid recursing. */
3913 static void macro_subst(TokenString *tok_str,
3914 Sym **nested_list, const int *macro_str)
3916 Sym *s;
3917 int *saved_macro_ptr, *macro_str1;
3918 const int *ptr;
3919 int t, ret;
3920 CValue cval;
3922 /* first scan for '##' operator handling */
3923 ptr = macro_str;
3924 macro_str1 = macro_twosharps(ptr);
3925 if (macro_str1)
3926 ptr = macro_str1;
3927 while (1) {
3928 TOK_GET(t, ptr, cval);
3929 if (t == 0)
3930 break;
3931 s = define_find(t);
3932 if (s != NULL) {
3933 /* if nested substitution, do nothing */
3934 if (sym_find2(*nested_list, t))
3935 goto no_subst;
3936 saved_macro_ptr = macro_ptr;
3937 macro_ptr = (int *)ptr;
3938 tok = t;
3939 ret = macro_subst_tok(tok_str, nested_list, s);
3940 ptr = (int *)macro_ptr;
3941 macro_ptr = saved_macro_ptr;
3942 if (ret != 0)
3943 goto no_subst;
3944 } else {
3945 no_subst:
3946 tok_str_add2(tok_str, t, &cval);
3949 if (macro_str1)
3950 tok_str_free(macro_str1);
3953 /* return next token with macro substitution */
3954 static void next(void)
3956 Sym *nested_list, *s;
3957 TokenString str;
3959 redo:
3960 next_nomacro();
3961 if (!macro_ptr) {
3962 /* if not reading from macro substituted string, then try
3963 to substitute macros */
3964 if (tok >= TOK_IDENT &&
3965 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3966 s = define_find(tok);
3967 if (s) {
3968 /* we have a macro: we try to substitute */
3969 tok_str_new(&str);
3970 nested_list = NULL;
3971 if (macro_subst_tok(&str, &nested_list, s) == 0) {
3972 /* substitution done, NOTE: maybe empty */
3973 tok_str_add(&str, 0);
3974 macro_ptr = str.str;
3975 macro_ptr_allocated = str.str;
3976 goto redo;
3980 } else {
3981 if (tok == 0) {
3982 /* end of macro or end of unget buffer */
3983 if (unget_buffer_enabled) {
3984 macro_ptr = unget_saved_macro_ptr;
3985 unget_buffer_enabled = 0;
3986 } else {
3987 /* end of macro string: free it */
3988 tok_str_free(macro_ptr_allocated);
3989 macro_ptr = NULL;
3991 goto redo;
3995 /* convert preprocessor tokens into C tokens */
3996 if (tok == TOK_PPNUM &&
3997 (parse_flags & PARSE_FLAG_TOK_NUM)) {
3998 parse_number((char *)tokc.cstr->data);
4002 /* push back current token and set current token to 'last_tok'. Only
4003 identifier case handled for labels. */
4004 static inline void unget_tok(int last_tok)
4006 int i, n;
4007 int *q;
4008 unget_saved_macro_ptr = macro_ptr;
4009 unget_buffer_enabled = 1;
4010 q = unget_saved_buffer;
4011 macro_ptr = q;
4012 *q++ = tok;
4013 n = tok_ext_size(tok) - 1;
4014 for(i=0;i<n;i++)
4015 *q++ = tokc.tab[i];
4016 *q = 0; /* end of token string */
4017 tok = last_tok;
4021 void swap(int *p, int *q)
4023 int t;
4024 t = *p;
4025 *p = *q;
4026 *q = t;
4029 void vsetc(CType *type, int r, CValue *vc)
4031 int v;
4033 if (vtop >= vstack + VSTACK_SIZE)
4034 error("memory full");
4035 /* cannot let cpu flags if other instruction are generated. Also
4036 avoid leaving VT_JMP anywhere except on the top of the stack
4037 because it would complicate the code generator. */
4038 if (vtop >= vstack) {
4039 v = vtop->r & VT_VALMASK;
4040 if (v == VT_CMP || (v & ~1) == VT_JMP)
4041 gv(RC_INT);
4043 vtop++;
4044 vtop->type = *type;
4045 vtop->r = r;
4046 vtop->r2 = VT_CONST;
4047 vtop->c = *vc;
4050 /* push integer constant */
4051 void vpushi(int v)
4053 CValue cval;
4054 cval.i = v;
4055 vsetc(&int_type, VT_CONST, &cval);
4058 /* Return a static symbol pointing to a section */
4059 static Sym *get_sym_ref(CType *type, Section *sec,
4060 unsigned long offset, unsigned long size)
4062 int v;
4063 Sym *sym;
4065 v = anon_sym++;
4066 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4067 sym->type.ref = type->ref;
4068 sym->r = VT_CONST | VT_SYM;
4069 put_extern_sym(sym, sec, offset, size);
4070 return sym;
4073 /* push a reference to a section offset by adding a dummy symbol */
4074 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4076 CValue cval;
4078 cval.ul = 0;
4079 vsetc(type, VT_CONST | VT_SYM, &cval);
4080 vtop->sym = get_sym_ref(type, sec, offset, size);
4083 /* define a new external reference to a symbol 'v' of type 'u' */
4084 static Sym *external_global_sym(int v, CType *type, int r)
4086 Sym *s;
4088 s = sym_find(v);
4089 if (!s) {
4090 /* push forward reference */
4091 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4092 s->type.ref = type->ref;
4093 s->r = r | VT_CONST | VT_SYM;
4095 return s;
4098 /* define a new external reference to a symbol 'v' of type 'u' */
4099 static Sym *external_sym(int v, CType *type, int r)
4101 Sym *s;
4103 s = sym_find(v);
4104 if (!s) {
4105 /* push forward reference */
4106 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4107 s->type.t |= VT_EXTERN;
4108 } else {
4109 if (!is_compatible_types(&s->type, type))
4110 error("incompatible types for redefinition of '%s'",
4111 get_tok_str(v, NULL));
4113 return s;
4116 /* push a reference to global symbol v */
4117 static void vpush_global_sym(CType *type, int v)
4119 Sym *sym;
4120 CValue cval;
4122 sym = external_global_sym(v, type, 0);
4123 cval.ul = 0;
4124 vsetc(type, VT_CONST | VT_SYM, &cval);
4125 vtop->sym = sym;
4128 void vset(CType *type, int r, int v)
4130 CValue cval;
4132 cval.i = v;
4133 vsetc(type, r, &cval);
4136 void vseti(int r, int v)
4138 CType type;
4139 type.t = VT_INT;
4140 vset(&type, r, v);
4143 void vswap(void)
4145 SValue tmp;
4147 tmp = vtop[0];
4148 vtop[0] = vtop[-1];
4149 vtop[-1] = tmp;
4152 void vpushv(SValue *v)
4154 if (vtop >= vstack + VSTACK_SIZE)
4155 error("memory full");
4156 vtop++;
4157 *vtop = *v;
4160 void vdup(void)
4162 vpushv(vtop);
4165 /* save r to the memory stack, and mark it as being free */
4166 void save_reg(int r)
4168 int l, saved, size, align;
4169 SValue *p, sv;
4170 CType *type;
4172 /* modify all stack values */
4173 saved = 0;
4174 l = 0;
4175 for(p=vstack;p<=vtop;p++) {
4176 if ((p->r & VT_VALMASK) == r ||
4177 (p->r2 & VT_VALMASK) == r) {
4178 /* must save value on stack if not already done */
4179 if (!saved) {
4180 /* NOTE: must reload 'r' because r might be equal to r2 */
4181 r = p->r & VT_VALMASK;
4182 /* store register in the stack */
4183 type = &p->type;
4184 if ((p->r & VT_LVAL) ||
4185 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4186 type = &int_type;
4187 size = type_size(type, &align);
4188 loc = (loc - size) & -align;
4189 sv.type.t = type->t;
4190 sv.r = VT_LOCAL | VT_LVAL;
4191 sv.c.ul = loc;
4192 store(r, &sv);
4193 #ifdef TCC_TARGET_I386
4194 /* x86 specific: need to pop fp register ST0 if saved */
4195 if (r == TREG_ST0) {
4196 o(0xd9dd); /* fstp %st(1) */
4198 #endif
4199 /* special long long case */
4200 if ((type->t & VT_BTYPE) == VT_LLONG) {
4201 sv.c.ul += 4;
4202 store(p->r2, &sv);
4204 l = loc;
4205 saved = 1;
4207 /* mark that stack entry as being saved on the stack */
4208 if (p->r & VT_LVAL) {
4209 /* also clear the bounded flag because the
4210 relocation address of the function was stored in
4211 p->c.ul */
4212 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4213 } else {
4214 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4216 p->r2 = VT_CONST;
4217 p->c.ul = l;
4222 /* find a free register of class 'rc'. If none, save one register */
4223 int get_reg(int rc)
4225 int r;
4226 SValue *p;
4228 /* find a free register */
4229 for(r=0;r<NB_REGS;r++) {
4230 if (reg_classes[r] & rc) {
4231 for(p=vstack;p<=vtop;p++) {
4232 if ((p->r & VT_VALMASK) == r ||
4233 (p->r2 & VT_VALMASK) == r)
4234 goto notfound;
4236 return r;
4238 notfound: ;
4241 /* no register left : free the first one on the stack (VERY
4242 IMPORTANT to start from the bottom to ensure that we don't
4243 spill registers used in gen_opi()) */
4244 for(p=vstack;p<=vtop;p++) {
4245 r = p->r & VT_VALMASK;
4246 if (r < VT_CONST && (reg_classes[r] & rc))
4247 goto save_found;
4248 /* also look at second register (if long long) */
4249 r = p->r2 & VT_VALMASK;
4250 if (r < VT_CONST && (reg_classes[r] & rc)) {
4251 save_found:
4252 save_reg(r);
4253 return r;
4256 /* Should never comes here */
4257 return -1;
4260 /* save registers up to (vtop - n) stack entry */
4261 void save_regs(int n)
4263 int r;
4264 SValue *p, *p1;
4265 p1 = vtop - n;
4266 for(p = vstack;p <= p1; p++) {
4267 r = p->r & VT_VALMASK;
4268 if (r < VT_CONST) {
4269 save_reg(r);
4274 /* move register 's' to 'r', and flush previous value of r to memory
4275 if needed */
4276 void move_reg(int r, int s)
4278 SValue sv;
4280 if (r != s) {
4281 save_reg(r);
4282 sv.type.t = VT_INT;
4283 sv.r = s;
4284 sv.c.ul = 0;
4285 load(r, &sv);
4289 /* get address of vtop (vtop MUST BE an lvalue) */
4290 void gaddrof(void)
4292 vtop->r &= ~VT_LVAL;
4293 /* tricky: if saved lvalue, then we can go back to lvalue */
4294 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4295 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4298 #ifdef CONFIG_TCC_BCHECK
4299 /* generate lvalue bound code */
4300 void gbound(void)
4302 int lval_type;
4303 CType type1;
4305 vtop->r &= ~VT_MUSTBOUND;
4306 /* if lvalue, then use checking code before dereferencing */
4307 if (vtop->r & VT_LVAL) {
4308 /* if not VT_BOUNDED value, then make one */
4309 if (!(vtop->r & VT_BOUNDED)) {
4310 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4311 /* must save type because we must set it to int to get pointer */
4312 type1 = vtop->type;
4313 vtop->type.t = VT_INT;
4314 gaddrof();
4315 vpushi(0);
4316 gen_bounded_ptr_add();
4317 vtop->r |= lval_type;
4318 vtop->type = type1;
4320 /* then check for dereferencing */
4321 gen_bounded_ptr_deref();
4324 #endif
4326 /* store vtop a register belonging to class 'rc'. lvalues are
4327 converted to values. Cannot be used if cannot be converted to
4328 register value (such as structures). */
4329 int gv(int rc)
4331 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4332 unsigned long long ll;
4334 /* NOTE: get_reg can modify vstack[] */
4335 if (vtop->type.t & VT_BITFIELD) {
4336 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4337 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4338 /* remove bit field info to avoid loops */
4339 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4340 /* generate shifts */
4341 vpushi(32 - (bit_pos + bit_size));
4342 gen_op(TOK_SHL);
4343 vpushi(32 - bit_size);
4344 /* NOTE: transformed to SHR if unsigned */
4345 gen_op(TOK_SAR);
4346 r = gv(rc);
4347 } else {
4348 if (is_float(vtop->type.t) &&
4349 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4350 Sym *sym;
4351 int *ptr;
4352 unsigned long offset;
4354 /* XXX: unify with initializers handling ? */
4355 /* CPUs usually cannot use float constants, so we store them
4356 generically in data segment */
4357 size = type_size(&vtop->type, &align);
4358 offset = (data_section->data_offset + align - 1) & -align;
4359 data_section->data_offset = offset;
4360 /* XXX: not portable yet */
4361 ptr = section_ptr_add(data_section, size);
4362 size = size >> 2;
4363 for(i=0;i<size;i++)
4364 ptr[i] = vtop->c.tab[i];
4365 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4366 vtop->r |= VT_LVAL | VT_SYM;
4367 vtop->sym = sym;
4368 vtop->c.ul = 0;
4370 #ifdef CONFIG_TCC_BCHECK
4371 if (vtop->r & VT_MUSTBOUND)
4372 gbound();
4373 #endif
4375 r = vtop->r & VT_VALMASK;
4376 /* need to reload if:
4377 - constant
4378 - lvalue (need to dereference pointer)
4379 - already a register, but not in the right class */
4380 if (r >= VT_CONST ||
4381 (vtop->r & VT_LVAL) ||
4382 !(reg_classes[r] & rc) ||
4383 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4384 !(reg_classes[vtop->r2] & rc))) {
4385 r = get_reg(rc);
4386 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4387 /* two register type load : expand to two words
4388 temporarily */
4389 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4390 /* load constant */
4391 ll = vtop->c.ull;
4392 vtop->c.ui = ll; /* first word */
4393 load(r, vtop);
4394 vtop->r = r; /* save register value */
4395 vpushi(ll >> 32); /* second word */
4396 } else if (r >= VT_CONST ||
4397 (vtop->r & VT_LVAL)) {
4398 /* load from memory */
4399 load(r, vtop);
4400 vdup();
4401 vtop[-1].r = r; /* save register value */
4402 /* increment pointer to get second word */
4403 vtop->type.t = VT_INT;
4404 gaddrof();
4405 vpushi(4);
4406 gen_op('+');
4407 vtop->r |= VT_LVAL;
4408 } else {
4409 /* move registers */
4410 load(r, vtop);
4411 vdup();
4412 vtop[-1].r = r; /* save register value */
4413 vtop->r = vtop[-1].r2;
4415 /* allocate second register */
4416 rc2 = RC_INT;
4417 if (rc == RC_IRET)
4418 rc2 = RC_LRET;
4419 r2 = get_reg(rc2);
4420 load(r2, vtop);
4421 vpop();
4422 /* write second register */
4423 vtop->r2 = r2;
4424 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4425 int t1, t;
4426 /* lvalue of scalar type : need to use lvalue type
4427 because of possible cast */
4428 t = vtop->type.t;
4429 t1 = t;
4430 /* compute memory access type */
4431 if (vtop->r & VT_LVAL_BYTE)
4432 t = VT_BYTE;
4433 else if (vtop->r & VT_LVAL_SHORT)
4434 t = VT_SHORT;
4435 if (vtop->r & VT_LVAL_UNSIGNED)
4436 t |= VT_UNSIGNED;
4437 vtop->type.t = t;
4438 load(r, vtop);
4439 /* restore wanted type */
4440 vtop->type.t = t1;
4441 } else {
4442 /* one register type load */
4443 load(r, vtop);
4446 vtop->r = r;
4448 return r;
4451 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4452 void gv2(int rc1, int rc2)
4454 int v;
4456 /* generate more generic register first. But VT_JMP or VT_CMP
4457 values must be generated first in all cases to avoid possible
4458 reload errors */
4459 v = vtop[0].r & VT_VALMASK;
4460 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4461 vswap();
4462 gv(rc1);
4463 vswap();
4464 gv(rc2);
4465 /* test if reload is needed for first register */
4466 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4467 vswap();
4468 gv(rc1);
4469 vswap();
4471 } else {
4472 gv(rc2);
4473 vswap();
4474 gv(rc1);
4475 vswap();
4476 /* test if reload is needed for first register */
4477 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4478 gv(rc2);
4483 /* expand long long on stack in two int registers */
4484 void lexpand(void)
4486 int u;
4488 u = vtop->type.t & VT_UNSIGNED;
4489 gv(RC_INT);
4490 vdup();
4491 vtop[0].r = vtop[-1].r2;
4492 vtop[0].r2 = VT_CONST;
4493 vtop[-1].r2 = VT_CONST;
4494 vtop[0].type.t = VT_INT | u;
4495 vtop[-1].type.t = VT_INT | u;
4498 /* build a long long from two ints */
4499 void lbuild(int t)
4501 gv2(RC_INT, RC_INT);
4502 vtop[-1].r2 = vtop[0].r;
4503 vtop[-1].type.t = t;
4504 vpop();
4507 /* rotate n first stack elements to the bottom */
4508 void vrotb(int n)
4510 int i;
4511 SValue tmp;
4513 tmp = vtop[-n + 1];
4514 for(i=-n+1;i!=0;i++)
4515 vtop[i] = vtop[i+1];
4516 vtop[0] = tmp;
4519 /* pop stack value */
4520 void vpop(void)
4522 int v;
4523 v = vtop->r & VT_VALMASK;
4524 #ifdef TCC_TARGET_I386
4525 /* for x86, we need to pop the FP stack */
4526 if (v == TREG_ST0 && !nocode_wanted) {
4527 o(0xd9dd); /* fstp %st(1) */
4528 } else
4529 #endif
4530 if (v == VT_JMP || v == VT_JMPI) {
4531 /* need to put correct jump if && or || without test */
4532 gsym(vtop->c.ul);
4534 vtop--;
4537 /* convert stack entry to register and duplicate its value in another
4538 register */
4539 void gv_dup(void)
4541 int rc, t, r, r1;
4542 SValue sv;
4544 t = vtop->type.t;
4545 if ((t & VT_BTYPE) == VT_LLONG) {
4546 lexpand();
4547 gv_dup();
4548 vswap();
4549 vrotb(3);
4550 gv_dup();
4551 vrotb(4);
4552 /* stack: H L L1 H1 */
4553 lbuild(t);
4554 vrotb(3);
4555 vrotb(3);
4556 vswap();
4557 lbuild(t);
4558 vswap();
4559 } else {
4560 /* duplicate value */
4561 rc = RC_INT;
4562 sv.type.t = VT_INT;
4563 if (is_float(t)) {
4564 rc = RC_FLOAT;
4565 sv.type.t = t;
4567 r = gv(rc);
4568 r1 = get_reg(rc);
4569 sv.r = r;
4570 sv.c.ul = 0;
4571 load(r1, &sv); /* move r to r1 */
4572 vdup();
4573 /* duplicates value */
4574 vtop->r = r1;
4578 /* generate CPU independent (unsigned) long long operations */
4579 void gen_opl(int op)
4581 int t, a, b, op1, c, i;
4582 int func;
4583 GFuncContext gf;
4584 SValue tmp;
4586 switch(op) {
4587 case '/':
4588 case TOK_PDIV:
4589 func = TOK___divdi3;
4590 goto gen_func;
4591 case TOK_UDIV:
4592 func = TOK___udivdi3;
4593 goto gen_func;
4594 case '%':
4595 func = TOK___moddi3;
4596 goto gen_func;
4597 case TOK_UMOD:
4598 func = TOK___umoddi3;
4599 gen_func:
4600 /* call generic long long function */
4601 gfunc_start(&gf, FUNC_CDECL);
4602 gfunc_param(&gf);
4603 gfunc_param(&gf);
4604 vpush_global_sym(&func_old_type, func);
4605 gfunc_call(&gf);
4606 vpushi(0);
4607 vtop->r = REG_IRET;
4608 vtop->r2 = REG_LRET;
4609 break;
4610 case '^':
4611 case '&':
4612 case '|':
4613 case '*':
4614 case '+':
4615 case '-':
4616 t = vtop->type.t;
4617 vswap();
4618 lexpand();
4619 vrotb(3);
4620 lexpand();
4621 /* stack: L1 H1 L2 H2 */
4622 tmp = vtop[0];
4623 vtop[0] = vtop[-3];
4624 vtop[-3] = tmp;
4625 tmp = vtop[-2];
4626 vtop[-2] = vtop[-3];
4627 vtop[-3] = tmp;
4628 vswap();
4629 /* stack: H1 H2 L1 L2 */
4630 if (op == '*') {
4631 vpushv(vtop - 1);
4632 vpushv(vtop - 1);
4633 gen_op(TOK_UMULL);
4634 lexpand();
4635 /* stack: H1 H2 L1 L2 ML MH */
4636 for(i=0;i<4;i++)
4637 vrotb(6);
4638 /* stack: ML MH H1 H2 L1 L2 */
4639 tmp = vtop[0];
4640 vtop[0] = vtop[-2];
4641 vtop[-2] = tmp;
4642 /* stack: ML MH H1 L2 H2 L1 */
4643 gen_op('*');
4644 vrotb(3);
4645 vrotb(3);
4646 gen_op('*');
4647 /* stack: ML MH M1 M2 */
4648 gen_op('+');
4649 gen_op('+');
4650 } else if (op == '+' || op == '-') {
4651 /* XXX: add non carry method too (for MIPS or alpha) */
4652 if (op == '+')
4653 op1 = TOK_ADDC1;
4654 else
4655 op1 = TOK_SUBC1;
4656 gen_op(op1);
4657 /* stack: H1 H2 (L1 op L2) */
4658 vrotb(3);
4659 vrotb(3);
4660 gen_op(op1 + 1); /* TOK_xxxC2 */
4661 } else {
4662 gen_op(op);
4663 /* stack: H1 H2 (L1 op L2) */
4664 vrotb(3);
4665 vrotb(3);
4666 /* stack: (L1 op L2) H1 H2 */
4667 gen_op(op);
4668 /* stack: (L1 op L2) (H1 op H2) */
4670 /* stack: L H */
4671 lbuild(t);
4672 break;
4673 case TOK_SAR:
4674 case TOK_SHR:
4675 case TOK_SHL:
4676 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4677 t = vtop[-1].type.t;
4678 vswap();
4679 lexpand();
4680 vrotb(3);
4681 /* stack: L H shift */
4682 c = (int)vtop->c.i;
4683 /* constant: simpler */
4684 /* NOTE: all comments are for SHL. the other cases are
4685 done by swaping words */
4686 vpop();
4687 if (op != TOK_SHL)
4688 vswap();
4689 if (c >= 32) {
4690 /* stack: L H */
4691 vpop();
4692 if (c > 32) {
4693 vpushi(c - 32);
4694 gen_op(op);
4696 if (op != TOK_SAR) {
4697 vpushi(0);
4698 } else {
4699 gv_dup();
4700 vpushi(31);
4701 gen_op(TOK_SAR);
4703 vswap();
4704 } else {
4705 vswap();
4706 gv_dup();
4707 /* stack: H L L */
4708 vpushi(c);
4709 gen_op(op);
4710 vswap();
4711 vpushi(32 - c);
4712 if (op == TOK_SHL)
4713 gen_op(TOK_SHR);
4714 else
4715 gen_op(TOK_SHL);
4716 vrotb(3);
4717 /* stack: L L H */
4718 vpushi(c);
4719 if (op == TOK_SHL)
4720 gen_op(TOK_SHL);
4721 else
4722 gen_op(TOK_SHR);
4723 gen_op('|');
4725 if (op != TOK_SHL)
4726 vswap();
4727 lbuild(t);
4728 } else {
4729 /* XXX: should provide a faster fallback on x86 ? */
4730 switch(op) {
4731 case TOK_SAR:
4732 func = TOK___sardi3;
4733 goto gen_func;
4734 case TOK_SHR:
4735 func = TOK___shrdi3;
4736 goto gen_func;
4737 case TOK_SHL:
4738 func = TOK___shldi3;
4739 goto gen_func;
4742 break;
4743 default:
4744 /* compare operations */
4745 t = vtop->type.t;
4746 vswap();
4747 lexpand();
4748 vrotb(3);
4749 lexpand();
4750 /* stack: L1 H1 L2 H2 */
4751 tmp = vtop[-1];
4752 vtop[-1] = vtop[-2];
4753 vtop[-2] = tmp;
4754 /* stack: L1 L2 H1 H2 */
4755 /* compare high */
4756 op1 = op;
4757 /* when values are equal, we need to compare low words. since
4758 the jump is inverted, we invert the test too. */
4759 if (op1 == TOK_LT)
4760 op1 = TOK_LE;
4761 else if (op1 == TOK_GT)
4762 op1 = TOK_GE;
4763 else if (op1 == TOK_ULT)
4764 op1 = TOK_ULE;
4765 else if (op1 == TOK_UGT)
4766 op1 = TOK_UGE;
4767 a = 0;
4768 b = 0;
4769 gen_op(op1);
4770 if (op1 != TOK_NE) {
4771 a = gtst(1, 0);
4773 if (op != TOK_EQ) {
4774 /* generate non equal test */
4775 /* XXX: NOT PORTABLE yet */
4776 if (a == 0) {
4777 b = gtst(0, 0);
4778 } else {
4779 #ifdef TCC_TARGET_I386
4780 b = psym(0x850f, 0);
4781 #else
4782 error("not implemented");
4783 #endif
4786 /* compare low. Always unsigned */
4787 op1 = op;
4788 if (op1 == TOK_LT)
4789 op1 = TOK_ULT;
4790 else if (op1 == TOK_LE)
4791 op1 = TOK_ULE;
4792 else if (op1 == TOK_GT)
4793 op1 = TOK_UGT;
4794 else if (op1 == TOK_GE)
4795 op1 = TOK_UGE;
4796 gen_op(op1);
4797 a = gtst(1, a);
4798 gsym(b);
4799 vseti(VT_JMPI, a);
4800 break;
4804 /* handle integer constant optimizations and various machine
4805 independent opt */
4806 void gen_opic(int op)
4808 int fc, c1, c2, n;
4809 SValue *v1, *v2;
4811 v1 = vtop - 1;
4812 v2 = vtop;
4813 /* currently, we cannot do computations with forward symbols */
4814 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4815 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4816 if (c1 && c2) {
4817 fc = v2->c.i;
4818 switch(op) {
4819 case '+': v1->c.i += fc; break;
4820 case '-': v1->c.i -= fc; break;
4821 case '&': v1->c.i &= fc; break;
4822 case '^': v1->c.i ^= fc; break;
4823 case '|': v1->c.i |= fc; break;
4824 case '*': v1->c.i *= fc; break;
4826 case TOK_PDIV:
4827 case '/':
4828 case '%':
4829 case TOK_UDIV:
4830 case TOK_UMOD:
4831 /* if division by zero, generate explicit division */
4832 if (fc == 0) {
4833 if (const_wanted)
4834 error("division by zero in constant");
4835 goto general_case;
4837 switch(op) {
4838 default: v1->c.i /= fc; break;
4839 case '%': v1->c.i %= fc; break;
4840 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
4841 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
4843 break;
4844 case TOK_SHL: v1->c.i <<= fc; break;
4845 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
4846 case TOK_SAR: v1->c.i >>= fc; break;
4847 /* tests */
4848 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
4849 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
4850 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
4851 case TOK_NE: v1->c.i = v1->c.i != fc; break;
4852 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
4853 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
4854 case TOK_LT: v1->c.i = v1->c.i < fc; break;
4855 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
4856 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
4857 case TOK_GT: v1->c.i = v1->c.i > fc; break;
4858 /* logical */
4859 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
4860 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
4861 default:
4862 goto general_case;
4864 vtop--;
4865 } else {
4866 /* if commutative ops, put c2 as constant */
4867 if (c1 && (op == '+' || op == '&' || op == '^' ||
4868 op == '|' || op == '*')) {
4869 vswap();
4870 swap(&c1, &c2);
4872 fc = vtop->c.i;
4873 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
4874 op == TOK_PDIV) &&
4875 fc == 1) ||
4876 ((op == '+' || op == '-' || op == '|' || op == '^' ||
4877 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
4878 fc == 0) ||
4879 (op == '&' &&
4880 fc == -1))) {
4881 /* nothing to do */
4882 vtop--;
4883 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
4884 /* try to use shifts instead of muls or divs */
4885 if (fc > 0 && (fc & (fc - 1)) == 0) {
4886 n = -1;
4887 while (fc) {
4888 fc >>= 1;
4889 n++;
4891 vtop->c.i = n;
4892 if (op == '*')
4893 op = TOK_SHL;
4894 else if (op == TOK_PDIV)
4895 op = TOK_SAR;
4896 else
4897 op = TOK_SHR;
4899 goto general_case;
4900 } else if (c2 && (op == '+' || op == '-') &&
4901 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
4902 (VT_CONST | VT_SYM)) {
4903 /* symbol + constant case */
4904 if (op == '-')
4905 fc = -fc;
4906 vtop--;
4907 vtop->c.i += fc;
4908 } else {
4909 general_case:
4910 if (!nocode_wanted) {
4911 /* call low level op generator */
4912 gen_opi(op);
4913 } else {
4914 vtop--;
4920 /* generate a floating point operation with constant propagation */
4921 void gen_opif(int op)
4923 int c1, c2;
4924 SValue *v1, *v2;
4925 long double f1, f2;
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 if (v1->type.t == VT_FLOAT) {
4934 f1 = v1->c.f;
4935 f2 = v2->c.f;
4936 } else if (v1->type.t == VT_DOUBLE) {
4937 f1 = v1->c.d;
4938 f2 = v2->c.d;
4939 } else {
4940 f1 = v1->c.ld;
4941 f2 = v2->c.ld;
4944 /* NOTE: we only do constant propagation if finite number (not
4945 NaN or infinity) (ANSI spec) */
4946 if (!ieee_finite(f1) || !ieee_finite(f2))
4947 goto general_case;
4949 switch(op) {
4950 case '+': f1 += f2; break;
4951 case '-': f1 -= f2; break;
4952 case '*': f1 *= f2; break;
4953 case '/':
4954 if (f2 == 0.0) {
4955 if (const_wanted)
4956 error("division by zero in constant");
4957 goto general_case;
4959 f1 /= f2;
4960 break;
4961 /* XXX: also handles tests ? */
4962 default:
4963 goto general_case;
4965 /* XXX: overflow test ? */
4966 if (v1->type.t == VT_FLOAT) {
4967 v1->c.f = f1;
4968 } else if (v1->type.t == VT_DOUBLE) {
4969 v1->c.d = f1;
4970 } else {
4971 v1->c.ld = f1;
4973 vtop--;
4974 } else {
4975 general_case:
4976 if (!nocode_wanted) {
4977 gen_opf(op);
4978 } else {
4979 vtop--;
4984 static int pointed_size(CType *type)
4986 int align;
4987 return type_size(pointed_type(type), &align);
4990 #if 0
4991 void check_pointer_types(SValue *p1, SValue *p2)
4993 char buf1[256], buf2[256];
4994 int t1, t2;
4995 t1 = p1->t;
4996 t2 = p2->t;
4997 if (!is_compatible_types(t1, t2)) {
4998 type_to_str(buf1, sizeof(buf1), t1, NULL);
4999 type_to_str(buf2, sizeof(buf2), t2, NULL);
5000 error("incompatible pointers '%s' and '%s'", buf1, buf2);
5003 #endif
5005 /* generic gen_op: handles types problems */
5006 void gen_op(int op)
5008 int u, t1, t2, bt1, bt2, t;
5009 CType type1;
5011 t1 = vtop[-1].type.t;
5012 t2 = vtop[0].type.t;
5013 bt1 = t1 & VT_BTYPE;
5014 bt2 = t2 & VT_BTYPE;
5016 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5017 /* at least one operand is a pointer */
5018 /* relationnal op: must be both pointers */
5019 if (op >= TOK_ULT && op <= TOK_GT) {
5020 // check_pointer_types(vtop, vtop - 1);
5021 /* pointers are handled are unsigned */
5022 t = VT_INT | VT_UNSIGNED;
5023 goto std_op;
5025 /* if both pointers, then it must be the '-' op */
5026 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5027 if (op != '-')
5028 error("cannot use pointers here");
5029 // check_pointer_types(vtop - 1, vtop);
5030 /* XXX: check that types are compatible */
5031 u = pointed_size(&vtop[-1].type);
5032 gen_opic(op);
5033 /* set to integer type */
5034 vtop->type.t = VT_INT;
5035 vpushi(u);
5036 gen_op(TOK_PDIV);
5037 } else {
5038 /* exactly one pointer : must be '+' or '-'. */
5039 if (op != '-' && op != '+')
5040 error("cannot use pointers here");
5041 /* Put pointer as first operand */
5042 if (bt2 == VT_PTR) {
5043 vswap();
5044 swap(&t1, &t2);
5046 type1 = vtop[-1].type;
5047 /* XXX: cast to int ? (long long case) */
5048 vpushi(pointed_size(&vtop[-1].type));
5049 gen_op('*');
5050 #ifdef CONFIG_TCC_BCHECK
5051 /* if evaluating constant expression, no code should be
5052 generated, so no bound check */
5053 if (do_bounds_check && !const_wanted) {
5054 /* if bounded pointers, we generate a special code to
5055 test bounds */
5056 if (op == '-') {
5057 vpushi(0);
5058 vswap();
5059 gen_op('-');
5061 gen_bounded_ptr_add();
5062 } else
5063 #endif
5065 gen_opic(op);
5067 /* put again type if gen_opic() swaped operands */
5068 vtop->type = type1;
5070 } else if (is_float(bt1) || is_float(bt2)) {
5071 /* compute bigger type and do implicit casts */
5072 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5073 t = VT_LDOUBLE;
5074 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5075 t = VT_DOUBLE;
5076 } else {
5077 t = VT_FLOAT;
5079 /* floats can only be used for a few operations */
5080 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5081 (op < TOK_ULT || op > TOK_GT))
5082 error("invalid operands for binary operation");
5083 goto std_op;
5084 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5085 /* cast to biggest op */
5086 t = VT_LLONG;
5087 /* convert to unsigned if it does not fit in a long long */
5088 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5089 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5090 t |= VT_UNSIGNED;
5091 goto std_op;
5092 } else {
5093 /* integer operations */
5094 t = VT_INT;
5095 /* convert to unsigned if it does not fit in an integer */
5096 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5097 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5098 t |= VT_UNSIGNED;
5099 std_op:
5100 /* XXX: currently, some unsigned operations are explicit, so
5101 we modify them here */
5102 if (t & VT_UNSIGNED) {
5103 if (op == TOK_SAR)
5104 op = TOK_SHR;
5105 else if (op == '/')
5106 op = TOK_UDIV;
5107 else if (op == '%')
5108 op = TOK_UMOD;
5109 else if (op == TOK_LT)
5110 op = TOK_ULT;
5111 else if (op == TOK_GT)
5112 op = TOK_UGT;
5113 else if (op == TOK_LE)
5114 op = TOK_ULE;
5115 else if (op == TOK_GE)
5116 op = TOK_UGE;
5118 vswap();
5119 type1.t = t;
5120 gen_cast(&type1);
5121 vswap();
5122 /* special case for shifts and long long: we keep the shift as
5123 an integer */
5124 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5125 type1.t = VT_INT;
5126 gen_cast(&type1);
5127 if (is_float(t))
5128 gen_opif(op);
5129 else if ((t & VT_BTYPE) == VT_LLONG)
5130 gen_opl(op);
5131 else
5132 gen_opic(op);
5133 if (op >= TOK_ULT && op <= TOK_GT) {
5134 /* relationnal op: the result is an int */
5135 vtop->type.t = VT_INT;
5136 } else {
5137 vtop->type.t = t;
5142 /* generic itof for unsigned long long case */
5143 void gen_cvt_itof1(int t)
5145 GFuncContext gf;
5147 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5148 (VT_LLONG | VT_UNSIGNED)) {
5150 gfunc_start(&gf, FUNC_CDECL);
5151 gfunc_param(&gf);
5152 if (t == VT_FLOAT)
5153 vpush_global_sym(&func_old_type, TOK___ulltof);
5154 else if (t == VT_DOUBLE)
5155 vpush_global_sym(&func_old_type, TOK___ulltod);
5156 else
5157 vpush_global_sym(&func_old_type, TOK___ulltold);
5158 gfunc_call(&gf);
5159 vpushi(0);
5160 vtop->r = REG_FRET;
5161 } else {
5162 gen_cvt_itof(t);
5166 /* generic ftoi for unsigned long long case */
5167 void gen_cvt_ftoi1(int t)
5169 GFuncContext gf;
5170 int st;
5172 if (t == (VT_LLONG | VT_UNSIGNED)) {
5173 /* not handled natively */
5174 gfunc_start(&gf, FUNC_CDECL);
5175 st = vtop->type.t & VT_BTYPE;
5176 gfunc_param(&gf);
5177 if (st == VT_FLOAT)
5178 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5179 else if (st == VT_DOUBLE)
5180 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5181 else
5182 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5183 gfunc_call(&gf);
5184 vpushi(0);
5185 vtop->r = REG_IRET;
5186 vtop->r2 = REG_LRET;
5187 } else {
5188 gen_cvt_ftoi(t);
5192 /* force char or short cast */
5193 void force_charshort_cast(int t)
5195 int bits, dbt;
5196 dbt = t & VT_BTYPE;
5197 /* XXX: add optimization if lvalue : just change type and offset */
5198 if (dbt == VT_BYTE)
5199 bits = 8;
5200 else
5201 bits = 16;
5202 if (t & VT_UNSIGNED) {
5203 vpushi((1 << bits) - 1);
5204 gen_op('&');
5205 } else {
5206 bits = 32 - bits;
5207 vpushi(bits);
5208 gen_op(TOK_SHL);
5209 vpushi(bits);
5210 gen_op(TOK_SAR);
5214 /* cast 'vtop' to 'type' */
5215 static void gen_cast(CType *type)
5217 int sbt, dbt, sf, df, c;
5219 /* special delayed cast for char/short */
5220 /* XXX: in some cases (multiple cascaded casts), it may still
5221 be incorrect */
5222 if (vtop->r & VT_MUSTCAST) {
5223 vtop->r &= ~VT_MUSTCAST;
5224 force_charshort_cast(vtop->type.t);
5227 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5228 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5230 if (sbt != dbt && !nocode_wanted) {
5231 sf = is_float(sbt);
5232 df = is_float(dbt);
5233 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5234 if (sf && df) {
5235 /* convert from fp to fp */
5236 if (c) {
5237 /* constant case: we can do it now */
5238 /* XXX: in ISOC, cannot do it if error in convert */
5239 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5240 vtop->c.f = (float)vtop->c.d;
5241 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5242 vtop->c.f = (float)vtop->c.ld;
5243 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5244 vtop->c.d = (double)vtop->c.f;
5245 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5246 vtop->c.d = (double)vtop->c.ld;
5247 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5248 vtop->c.ld = (long double)vtop->c.f;
5249 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5250 vtop->c.ld = (long double)vtop->c.d;
5251 } else {
5252 /* non constant case: generate code */
5253 gen_cvt_ftof(dbt);
5255 } else if (df) {
5256 /* convert int to fp */
5257 if (c) {
5258 switch(sbt) {
5259 case VT_LLONG | VT_UNSIGNED:
5260 case VT_LLONG:
5261 /* XXX: add const cases for long long */
5262 goto do_itof;
5263 case VT_INT | VT_UNSIGNED:
5264 switch(dbt) {
5265 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5266 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5267 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5269 break;
5270 default:
5271 switch(dbt) {
5272 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5273 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5274 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5276 break;
5278 } else {
5279 do_itof:
5280 gen_cvt_itof1(dbt);
5282 } else if (sf) {
5283 /* convert fp to int */
5284 /* we handle char/short/etc... with generic code */
5285 if (dbt != (VT_INT | VT_UNSIGNED) &&
5286 dbt != (VT_LLONG | VT_UNSIGNED) &&
5287 dbt != VT_LLONG)
5288 dbt = VT_INT;
5289 if (c) {
5290 switch(dbt) {
5291 case VT_LLONG | VT_UNSIGNED:
5292 case VT_LLONG:
5293 /* XXX: add const cases for long long */
5294 goto do_ftoi;
5295 case VT_INT | VT_UNSIGNED:
5296 switch(sbt) {
5297 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5298 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5299 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5301 break;
5302 default:
5303 /* int case */
5304 switch(sbt) {
5305 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5306 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5307 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5309 break;
5311 } else {
5312 do_ftoi:
5313 gen_cvt_ftoi1(dbt);
5315 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5316 /* additional cast for char/short/bool... */
5317 vtop->type.t = dbt;
5318 gen_cast(type);
5320 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5321 if ((sbt & VT_BTYPE) != VT_LLONG) {
5322 /* scalar to long long */
5323 if (c) {
5324 if (sbt == (VT_INT | VT_UNSIGNED))
5325 vtop->c.ll = vtop->c.ui;
5326 else
5327 vtop->c.ll = vtop->c.i;
5328 } else {
5329 /* machine independent conversion */
5330 gv(RC_INT);
5331 /* generate high word */
5332 if (sbt == (VT_INT | VT_UNSIGNED)) {
5333 vpushi(0);
5334 gv(RC_INT);
5335 } else {
5336 gv_dup();
5337 vpushi(31);
5338 gen_op(TOK_SAR);
5340 /* patch second register */
5341 vtop[-1].r2 = vtop->r;
5342 vpop();
5345 } else if (dbt == VT_BOOL) {
5346 /* scalar to bool */
5347 vpushi(0);
5348 gen_op(TOK_NE);
5349 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5350 (dbt & VT_BTYPE) == VT_SHORT) {
5351 force_charshort_cast(dbt);
5352 } else if ((dbt & VT_BTYPE) == VT_INT) {
5353 /* scalar to int */
5354 if (sbt == VT_LLONG) {
5355 /* from long long: just take low order word */
5356 lexpand();
5357 vpop();
5359 /* if lvalue and single word type, nothing to do because
5360 the lvalue already contains the real type size (see
5361 VT_LVAL_xxx constants) */
5364 vtop->type = *type;
5367 /* return type size. Put alignment at 'a' */
5368 static int type_size(CType *type, int *a)
5370 Sym *s;
5371 int bt;
5373 bt = type->t & VT_BTYPE;
5374 if (bt == VT_STRUCT) {
5375 /* struct/union */
5376 s = type->ref;
5377 *a = s->r;
5378 return s->c;
5379 } else if (bt == VT_PTR) {
5380 if (type->t & VT_ARRAY) {
5381 s = type->ref;
5382 return type_size(&s->type, a) * s->c;
5383 } else {
5384 *a = PTR_SIZE;
5385 return PTR_SIZE;
5387 } else if (bt == VT_LDOUBLE) {
5388 *a = LDOUBLE_ALIGN;
5389 return LDOUBLE_SIZE;
5390 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5391 *a = 4; /* XXX: i386 specific */
5392 return 8;
5393 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5394 *a = 4;
5395 return 4;
5396 } else if (bt == VT_SHORT) {
5397 *a = 2;
5398 return 2;
5399 } else {
5400 /* char, void, function, _Bool */
5401 *a = 1;
5402 return 1;
5406 /* return the pointed type of t */
5407 static inline CType *pointed_type(CType *type)
5409 return &type->ref->type;
5412 /* modify type so that its it is a pointer to type. */
5413 static void mk_pointer(CType *type)
5415 Sym *s;
5416 s = sym_push(SYM_FIELD, type, 0, -1);
5417 type->t = VT_PTR | (type->t & ~VT_TYPE);
5418 type->ref = s;
5421 static int is_compatible_types(CType *type1, CType *type2)
5423 Sym *s1, *s2;
5424 int bt1, bt2, t1, t2;
5426 t1 = type1->t & VT_TYPE;
5427 t2 = type2->t & VT_TYPE;
5428 bt1 = t1 & VT_BTYPE;
5429 bt2 = t2 & VT_BTYPE;
5430 if (bt1 == VT_PTR) {
5431 type1 = pointed_type(type1);
5432 /* if function, then convert implicitely to function pointer */
5433 if (bt2 != VT_FUNC) {
5434 if (bt2 != VT_PTR)
5435 return 0;
5436 type2 = pointed_type(type2);
5438 /* void matches everything */
5439 /* XXX: not fully compliant */
5440 if ((type1->t & VT_TYPE) == VT_VOID || (type2->t & VT_TYPE) == VT_VOID)
5441 return 1;
5442 return is_compatible_types(type1, type2);
5443 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
5444 return (type1->ref == type2->ref);
5445 } else if (bt1 == VT_FUNC) {
5446 if (bt2 != VT_FUNC)
5447 return 0;
5448 s1 = type1->ref;
5449 s2 = type2->ref;
5450 if (!is_compatible_types(&s1->type, &s2->type))
5451 return 0;
5452 /* XXX: not complete */
5453 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5454 return 1;
5455 if (s1->c != s2->c)
5456 return 0;
5457 while (s1 != NULL) {
5458 if (s2 == NULL)
5459 return 0;
5460 if (!is_compatible_types(&s1->type, &s2->type))
5461 return 0;
5462 s1 = s1->next;
5463 s2 = s2->next;
5465 if (s2)
5466 return 0;
5467 return 1;
5468 } else {
5469 /* XXX: not complete */
5470 return 1;
5474 /* print a type. If 'varstr' is not NULL, then the variable is also
5475 printed in the type */
5476 /* XXX: union */
5477 /* XXX: add array and function pointers */
5478 void type_to_str(char *buf, int buf_size,
5479 CType *type, const char *varstr)
5481 int bt, v, t;
5482 Sym *s, *sa;
5483 char buf1[256];
5484 const char *tstr;
5486 t = type->t & VT_TYPE;
5487 bt = t & VT_BTYPE;
5488 buf[0] = '\0';
5489 if (t & VT_UNSIGNED)
5490 pstrcat(buf, buf_size, "unsigned ");
5491 switch(bt) {
5492 case VT_VOID:
5493 tstr = "void";
5494 goto add_tstr;
5495 case VT_BOOL:
5496 tstr = "_Bool";
5497 goto add_tstr;
5498 case VT_BYTE:
5499 tstr = "char";
5500 goto add_tstr;
5501 case VT_SHORT:
5502 tstr = "short";
5503 goto add_tstr;
5504 case VT_INT:
5505 tstr = "int";
5506 goto add_tstr;
5507 case VT_LONG:
5508 tstr = "long";
5509 goto add_tstr;
5510 case VT_LLONG:
5511 tstr = "long long";
5512 goto add_tstr;
5513 case VT_FLOAT:
5514 tstr = "float";
5515 goto add_tstr;
5516 case VT_DOUBLE:
5517 tstr = "double";
5518 goto add_tstr;
5519 case VT_LDOUBLE:
5520 tstr = "long double";
5521 add_tstr:
5522 pstrcat(buf, buf_size, tstr);
5523 break;
5524 case VT_ENUM:
5525 case VT_STRUCT:
5526 if (bt == VT_STRUCT)
5527 tstr = "struct ";
5528 else
5529 tstr = "enum ";
5530 pstrcat(buf, buf_size, tstr);
5531 v = type->ref->v & ~SYM_STRUCT;
5532 if (v >= SYM_FIRST_ANOM)
5533 pstrcat(buf, buf_size, "<anonymous>");
5534 else
5535 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5536 break;
5537 case VT_FUNC:
5538 s = type->ref;
5539 type_to_str(buf, buf_size, &s->type, varstr);
5540 pstrcat(buf, buf_size, "(");
5541 sa = s->next;
5542 while (sa != NULL) {
5543 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5544 pstrcat(buf, buf_size, buf1);
5545 sa = sa->next;
5546 if (sa)
5547 pstrcat(buf, buf_size, ", ");
5549 pstrcat(buf, buf_size, ")");
5550 goto no_var;
5551 case VT_PTR:
5552 s = type->ref;
5553 pstrcpy(buf1, sizeof(buf1), "*");
5554 if (varstr)
5555 pstrcat(buf1, sizeof(buf1), varstr);
5556 type_to_str(buf, buf_size, &s->type, buf1);
5557 goto no_var;
5559 if (varstr) {
5560 pstrcat(buf, buf_size, " ");
5561 pstrcat(buf, buf_size, varstr);
5563 no_var: ;
5566 /* verify type compatibility to store vtop in 'dt' type, and generate
5567 casts if needed. */
5568 static void gen_assign_cast(CType *dt)
5570 CType *st;
5571 char buf1[256], buf2[256];
5572 int dbt, sbt;
5574 st = &vtop->type; /* source type */
5575 dbt = dt->t & VT_BTYPE;
5576 sbt = st->t & VT_BTYPE;
5577 if (dbt == VT_PTR) {
5578 /* special cases for pointers */
5579 /* a function is implicitely a function pointer */
5580 if (sbt == VT_FUNC) {
5581 if (!is_compatible_types(pointed_type(dt), st))
5582 goto error;
5583 else
5584 goto type_ok;
5586 /* '0' can also be a pointer */
5587 if (sbt == VT_INT &&
5588 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) &&
5589 vtop->c.i == 0)
5590 goto type_ok;
5591 /* accept implicit pointer to integer cast with warning */
5592 if (sbt == VT_BYTE || sbt == VT_SHORT ||
5593 sbt == VT_INT || sbt == VT_LLONG) {
5594 warning("assignment makes pointer from integer without a cast");
5595 goto type_ok;
5597 } else if (dbt == VT_BYTE || dbt == VT_SHORT ||
5598 dbt == VT_INT || dbt == VT_LLONG) {
5599 if (sbt == VT_PTR || sbt == VT_FUNC) {
5600 warning("assignment makes integer from pointer without a cast");
5601 goto type_ok;
5604 if (!is_compatible_types(dt, st)) {
5605 error:
5606 type_to_str(buf1, sizeof(buf1), st, NULL);
5607 type_to_str(buf2, sizeof(buf2), dt, NULL);
5608 error("cannot cast '%s' to '%s'", buf1, buf2);
5610 type_ok:
5611 gen_cast(dt);
5614 /* store vtop in lvalue pushed on stack */
5615 void vstore(void)
5617 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5618 GFuncContext gf;
5620 ft = vtop[-1].type.t;
5621 sbt = vtop->type.t & VT_BTYPE;
5622 dbt = ft & VT_BTYPE;
5623 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5624 (sbt == VT_INT && dbt == VT_SHORT)) {
5625 /* optimize char/short casts */
5626 delayed_cast = VT_MUSTCAST;
5627 vtop->type.t = ft & VT_TYPE;
5628 } else {
5629 delayed_cast = 0;
5630 gen_assign_cast(&vtop[-1].type);
5633 if (sbt == VT_STRUCT) {
5634 /* if structure, only generate pointer */
5635 /* structure assignment : generate memcpy */
5636 /* XXX: optimize if small size */
5637 if (!nocode_wanted) {
5638 vdup();
5639 gfunc_start(&gf, FUNC_CDECL);
5640 /* type size */
5641 size = type_size(&vtop->type, &align);
5642 vpushi(size);
5643 gfunc_param(&gf);
5644 /* source */
5645 vtop->type.t = VT_INT;
5646 gaddrof();
5647 gfunc_param(&gf);
5648 /* destination */
5649 vswap();
5650 vtop->type.t = VT_INT;
5651 gaddrof();
5652 gfunc_param(&gf);
5654 save_regs(0);
5655 vpush_global_sym(&func_old_type, TOK_memcpy);
5656 gfunc_call(&gf);
5657 } else {
5658 vswap();
5659 vpop();
5661 /* leave source on stack */
5662 } else if (ft & VT_BITFIELD) {
5663 /* bitfield store handling */
5664 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5665 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5666 /* remove bit field info to avoid loops */
5667 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5669 /* duplicate destination */
5670 vdup();
5671 vtop[-1] = vtop[-2];
5673 /* mask and shift source */
5674 vpushi((1 << bit_size) - 1);
5675 gen_op('&');
5676 vpushi(bit_pos);
5677 gen_op(TOK_SHL);
5678 /* load destination, mask and or with source */
5679 vswap();
5680 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5681 gen_op('&');
5682 gen_op('|');
5683 /* store result */
5684 vstore();
5685 } else {
5686 #ifdef CONFIG_TCC_BCHECK
5687 /* bound check case */
5688 if (vtop[-1].r & VT_MUSTBOUND) {
5689 vswap();
5690 gbound();
5691 vswap();
5693 #endif
5694 if (!nocode_wanted) {
5695 rc = RC_INT;
5696 if (is_float(ft))
5697 rc = RC_FLOAT;
5698 r = gv(rc); /* generate value */
5699 /* if lvalue was saved on stack, must read it */
5700 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5701 SValue sv;
5702 t = get_reg(RC_INT);
5703 sv.type.t = VT_INT;
5704 sv.r = VT_LOCAL | VT_LVAL;
5705 sv.c.ul = vtop[-1].c.ul;
5706 load(t, &sv);
5707 vtop[-1].r = t | VT_LVAL;
5709 store(r, vtop - 1);
5710 /* two word case handling : store second register at word + 4 */
5711 if ((ft & VT_BTYPE) == VT_LLONG) {
5712 vswap();
5713 /* convert to int to increment easily */
5714 vtop->type.t = VT_INT;
5715 gaddrof();
5716 vpushi(4);
5717 gen_op('+');
5718 vtop->r |= VT_LVAL;
5719 vswap();
5720 /* XXX: it works because r2 is spilled last ! */
5721 store(vtop->r2, vtop - 1);
5724 vswap();
5725 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5726 vtop->r |= delayed_cast;
5730 /* post defines POST/PRE add. c is the token ++ or -- */
5731 void inc(int post, int c)
5733 test_lvalue();
5734 vdup(); /* save lvalue */
5735 if (post) {
5736 gv_dup(); /* duplicate value */
5737 vrotb(3);
5738 vrotb(3);
5740 /* add constant */
5741 vpushi(c - TOK_MID);
5742 gen_op('+');
5743 vstore(); /* store value */
5744 if (post)
5745 vpop(); /* if post op, return saved value */
5748 /* Parse GNUC __attribute__ extension. Currently, the following
5749 extensions are recognized:
5750 - aligned(n) : set data/function alignment.
5751 - section(x) : generate data/code in this section.
5752 - unused : currently ignored, but may be used someday.
5754 static void parse_attribute(AttributeDef *ad)
5756 int t, n;
5758 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
5759 next();
5760 skip('(');
5761 skip('(');
5762 while (tok != ')') {
5763 if (tok < TOK_IDENT)
5764 expect("attribute name");
5765 t = tok;
5766 next();
5767 switch(t) {
5768 case TOK_SECTION1:
5769 case TOK_SECTION2:
5770 skip('(');
5771 if (tok != TOK_STR)
5772 expect("section name");
5773 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
5774 next();
5775 skip(')');
5776 break;
5777 case TOK_ALIGNED1:
5778 case TOK_ALIGNED2:
5779 if (tok == '(') {
5780 next();
5781 n = expr_const();
5782 if (n <= 0 || (n & (n - 1)) != 0)
5783 error("alignment must be a positive power of two");
5784 skip(')');
5785 } else {
5786 n = MAX_ALIGN;
5788 ad->aligned = n;
5789 break;
5790 case TOK_UNUSED1:
5791 case TOK_UNUSED2:
5792 /* currently, no need to handle it because tcc does not
5793 track unused objects */
5794 break;
5795 case TOK_NORETURN1:
5796 case TOK_NORETURN2:
5797 /* currently, no need to handle it because tcc does not
5798 track unused objects */
5799 break;
5800 case TOK_CDECL1:
5801 case TOK_CDECL2:
5802 case TOK_CDECL3:
5803 ad->func_call = FUNC_CDECL;
5804 break;
5805 case TOK_STDCALL1:
5806 case TOK_STDCALL2:
5807 case TOK_STDCALL3:
5808 ad->func_call = FUNC_STDCALL;
5809 break;
5810 default:
5811 // warning("'%s' attribute ignored", get_tok_str(t, NULL));
5812 /* skip parameters */
5813 /* XXX: skip parenthesis too */
5814 if (tok == '(') {
5815 next();
5816 while (tok != ')' && tok != -1)
5817 next();
5818 next();
5820 break;
5822 if (tok != ',')
5823 break;
5824 next();
5826 skip(')');
5827 skip(')');
5831 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
5832 static void struct_decl(CType *type, int u)
5834 int a, v, size, align, maxalign, c, offset;
5835 int bit_size, bit_pos, bsize, bt, lbit_pos;
5836 Sym *s, *ss, **ps;
5837 AttributeDef ad;
5838 CType type1, btype;
5840 a = tok; /* save decl type */
5841 next();
5842 if (tok != '{') {
5843 v = tok;
5844 next();
5845 /* struct already defined ? return it */
5846 if (v < TOK_IDENT)
5847 expect("struct/union/enum name");
5848 s = struct_find(v);
5849 if (s) {
5850 if (s->type.t != a)
5851 error("invalid type");
5852 goto do_decl;
5854 } else {
5855 v = anon_sym++;
5857 type1.t = a;
5858 s = sym_push(v | SYM_STRUCT, &type1, 0, 0);
5859 /* put struct/union/enum name in type */
5860 do_decl:
5861 type->t = u;
5862 type->ref = s;
5864 if (tok == '{') {
5865 next();
5866 if (s->c)
5867 error("struct/union/enum already defined");
5868 /* cannot be empty */
5869 c = 0;
5870 /* non empty enums are not allowed */
5871 if (a == TOK_ENUM) {
5872 for(;;) {
5873 v = tok;
5874 if (v < TOK_UIDENT)
5875 expect("identifier");
5876 next();
5877 if (tok == '=') {
5878 next();
5879 c = expr_const();
5881 /* enum symbols have static storage */
5882 ss = sym_push(v, &int_type, VT_CONST, c);
5883 ss->type.t |= VT_STATIC;
5884 if (tok != ',')
5885 break;
5886 next();
5887 c++;
5888 /* NOTE: we accept a trailing comma */
5889 if (tok == '}')
5890 break;
5892 skip('}');
5893 } else {
5894 maxalign = 1;
5895 ps = &s->next;
5896 bit_pos = 0;
5897 offset = 0;
5898 while (tok != '}') {
5899 parse_btype(&btype, &ad);
5900 while (1) {
5901 bit_size = -1;
5902 v = 0;
5903 type1 = btype;
5904 if (tok != ':') {
5905 type_decl(&type1, &ad, &v, TYPE_DIRECT);
5906 if ((type1.t & VT_BTYPE) == VT_FUNC ||
5907 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
5908 error("invalid type for '%s'",
5909 get_tok_str(v, NULL));
5911 if (tok == ':') {
5912 next();
5913 bit_size = expr_const();
5914 /* XXX: handle v = 0 case for messages */
5915 if (bit_size < 0)
5916 error("negative width in bit-field '%s'",
5917 get_tok_str(v, NULL));
5918 if (v && bit_size == 0)
5919 error("zero width for bit-field '%s'",
5920 get_tok_str(v, NULL));
5922 size = type_size(&type1, &align);
5923 lbit_pos = 0;
5924 if (bit_size >= 0) {
5925 bt = type1.t & VT_BTYPE;
5926 if (bt != VT_INT &&
5927 bt != VT_BYTE &&
5928 bt != VT_SHORT &&
5929 bt != VT_ENUM)
5930 error("bitfields must have scalar type");
5931 bsize = size * 8;
5932 if (bit_size > bsize) {
5933 error("width of '%s' exceeds its type",
5934 get_tok_str(v, NULL));
5935 } else if (bit_size == bsize) {
5936 /* no need for bit fields */
5937 bit_pos = 0;
5938 } else if (bit_size == 0) {
5939 /* XXX: what to do if only padding in a
5940 structure ? */
5941 /* zero size: means to pad */
5942 if (bit_pos > 0)
5943 bit_pos = bsize;
5944 } else {
5945 /* we do not have enough room ? */
5946 if ((bit_pos + bit_size) > bsize)
5947 bit_pos = 0;
5948 lbit_pos = bit_pos;
5949 /* XXX: handle LSB first */
5950 type1.t |= VT_BITFIELD |
5951 (bit_pos << VT_STRUCT_SHIFT) |
5952 (bit_size << (VT_STRUCT_SHIFT + 6));
5953 bit_pos += bit_size;
5955 } else {
5956 bit_pos = 0;
5958 if (v) {
5959 /* add new memory data only if starting
5960 bit field */
5961 if (lbit_pos == 0) {
5962 if (a == TOK_STRUCT) {
5963 c = (c + align - 1) & -align;
5964 offset = c;
5965 c += size;
5966 } else {
5967 offset = 0;
5968 if (size > c)
5969 c = size;
5971 if (align > maxalign)
5972 maxalign = align;
5974 #if 0
5975 printf("add field %s offset=%d",
5976 get_tok_str(v, NULL), offset);
5977 if (type1.t & VT_BITFIELD) {
5978 printf(" pos=%d size=%d",
5979 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
5980 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
5982 printf("\n");
5983 #endif
5984 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
5985 *ps = ss;
5986 ps = &ss->next;
5988 if (tok == ';' || tok == TOK_EOF)
5989 break;
5990 skip(',');
5992 skip(';');
5994 skip('}');
5995 /* store size and alignment */
5996 s->c = (c + maxalign - 1) & -maxalign;
5997 s->r = maxalign;
6002 /* return 0 if no type declaration. otherwise, return the basic type
6003 and skip it.
6005 static int parse_btype(CType *type, AttributeDef *ad)
6007 int t, u, type_found;
6008 Sym *s;
6009 CType type1;
6011 memset(ad, 0, sizeof(AttributeDef));
6012 type_found = 0;
6013 t = 0;
6014 while(1) {
6015 switch(tok) {
6016 case TOK_EXTENSION:
6017 /* currently, we really ignore extension */
6018 next();
6019 continue;
6021 /* basic types */
6022 case TOK_CHAR:
6023 u = VT_BYTE;
6024 basic_type:
6025 next();
6026 basic_type1:
6027 if ((t & VT_BTYPE) != 0)
6028 error("too many basic types");
6029 t |= u;
6030 break;
6031 case TOK_VOID:
6032 u = VT_VOID;
6033 goto basic_type;
6034 case TOK_SHORT:
6035 u = VT_SHORT;
6036 goto basic_type;
6037 case TOK_INT:
6038 next();
6039 break;
6040 case TOK_LONG:
6041 next();
6042 if ((t & VT_BTYPE) == VT_DOUBLE) {
6043 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6044 } else if ((t & VT_BTYPE) == VT_LONG) {
6045 t = (t & ~VT_BTYPE) | VT_LLONG;
6046 } else {
6047 u = VT_LONG;
6048 goto basic_type1;
6050 break;
6051 case TOK_BOOL:
6052 u = VT_BOOL;
6053 goto basic_type;
6054 case TOK_FLOAT:
6055 u = VT_FLOAT;
6056 goto basic_type;
6057 case TOK_DOUBLE:
6058 next();
6059 if ((t & VT_BTYPE) == VT_LONG) {
6060 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6061 } else {
6062 u = VT_DOUBLE;
6063 goto basic_type1;
6065 break;
6066 case TOK_ENUM:
6067 struct_decl(&type1, VT_ENUM);
6068 basic_type2:
6069 u = type1.t;
6070 type->ref = type1.ref;
6071 goto basic_type1;
6072 case TOK_STRUCT:
6073 case TOK_UNION:
6074 struct_decl(&type1, VT_STRUCT);
6075 goto basic_type2;
6077 /* type modifiers */
6078 case TOK_CONST1:
6079 case TOK_CONST2:
6080 case TOK_CONST3:
6081 case TOK_VOLATILE1:
6082 case TOK_VOLATILE2:
6083 case TOK_VOLATILE3:
6084 case TOK_REGISTER:
6085 case TOK_SIGNED1:
6086 case TOK_SIGNED2:
6087 case TOK_SIGNED3:
6088 case TOK_AUTO:
6089 case TOK_RESTRICT1:
6090 case TOK_RESTRICT2:
6091 case TOK_RESTRICT3:
6092 next();
6093 break;
6094 case TOK_UNSIGNED:
6095 t |= VT_UNSIGNED;
6096 next();
6097 break;
6099 /* storage */
6100 case TOK_EXTERN:
6101 t |= VT_EXTERN;
6102 next();
6103 break;
6104 case TOK_STATIC:
6105 t |= VT_STATIC;
6106 next();
6107 break;
6108 case TOK_TYPEDEF:
6109 t |= VT_TYPEDEF;
6110 next();
6111 break;
6112 case TOK_INLINE1:
6113 case TOK_INLINE2:
6114 case TOK_INLINE3:
6115 t |= VT_INLINE;
6116 next();
6117 break;
6119 /* GNUC attribute */
6120 case TOK_ATTRIBUTE1:
6121 case TOK_ATTRIBUTE2:
6122 parse_attribute(ad);
6123 break;
6124 /* GNUC typeof */
6125 case TOK_TYPEOF1:
6126 case TOK_TYPEOF2:
6127 case TOK_TYPEOF3:
6128 next();
6129 parse_expr_type(&type1);
6130 goto basic_type2;
6131 default:
6132 s = sym_find(tok);
6133 if (!s || !(s->type.t & VT_TYPEDEF))
6134 goto the_end;
6135 t |= (s->type.t & ~VT_TYPEDEF);
6136 type->ref = s->type.ref;
6137 next();
6138 break;
6140 type_found = 1;
6142 the_end:
6143 /* long is never used as type */
6144 if ((t & VT_BTYPE) == VT_LONG)
6145 t = (t & ~VT_BTYPE) | VT_INT;
6146 type->t = t;
6147 return type_found;
6150 /* convert a function parameter type (array to pointer and function to
6151 function pointer) */
6152 static inline void convert_parameter_type(CType *pt)
6154 /* array must be transformed to pointer according to ANSI C */
6155 pt->t &= ~VT_ARRAY;
6156 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6157 mk_pointer(pt);
6161 static void post_type(CType *type, AttributeDef *ad)
6163 int n, l, t1;
6164 Sym **plast, *s, *first;
6165 AttributeDef ad1;
6166 CType pt;
6168 if (tok == '(') {
6169 /* function declaration */
6170 next();
6171 l = 0;
6172 first = NULL;
6173 plast = &first;
6174 while (tok != ')') {
6175 /* read param name and compute offset */
6176 if (l != FUNC_OLD) {
6177 if (!parse_btype(&pt, &ad1)) {
6178 if (l) {
6179 error("invalid type");
6180 } else {
6181 l = FUNC_OLD;
6182 goto old_proto;
6185 l = FUNC_NEW;
6186 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6187 break;
6188 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6189 if ((pt.t & VT_BTYPE) == VT_VOID)
6190 error("parameter declared as void");
6191 } else {
6192 old_proto:
6193 n = tok;
6194 pt.t = VT_INT;
6195 next();
6197 convert_parameter_type(&pt);
6198 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6199 *plast = s;
6200 plast = &s->next;
6201 if (tok == ',') {
6202 next();
6203 if (l == FUNC_NEW && tok == TOK_DOTS) {
6204 l = FUNC_ELLIPSIS;
6205 next();
6206 break;
6210 /* if no parameters, then old type prototype */
6211 if (l == 0)
6212 l = FUNC_OLD;
6213 skip(')');
6214 t1 = type->t & VT_STORAGE;
6215 type->t &= ~VT_STORAGE;
6216 post_type(type, ad);
6217 /* we push a anonymous symbol which will contain the function prototype */
6218 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6219 s->next = first;
6220 type->t = t1 | VT_FUNC;
6221 type->ref = s;
6222 } else if (tok == '[') {
6223 /* array definition */
6224 next();
6225 n = -1;
6226 if (tok != ']') {
6227 n = expr_const();
6228 if (n < 0)
6229 error("invalid array size");
6231 skip(']');
6232 /* parse next post type */
6233 t1 = type->t & VT_STORAGE;
6234 type->t &= ~VT_STORAGE;
6235 post_type(type, ad);
6237 /* we push a anonymous symbol which will contain the array
6238 element type */
6239 s = sym_push(SYM_FIELD, type, 0, n);
6240 type->t = t1 | VT_ARRAY | VT_PTR;
6241 type->ref = s;
6245 /* Parse a type declaration (except basic type), and return the type
6246 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6247 expected. 'type' should contain the basic type. 'ad' is the
6248 attribute definition of the basic type. It can be modified by
6249 type_decl().
6251 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6253 Sym *s;
6254 CType type1, *type2;
6256 while (tok == '*') {
6257 next();
6258 redo:
6259 switch(tok) {
6260 case TOK_CONST1:
6261 case TOK_CONST2:
6262 case TOK_CONST3:
6263 case TOK_VOLATILE1:
6264 case TOK_VOLATILE2:
6265 case TOK_VOLATILE3:
6266 case TOK_RESTRICT1:
6267 case TOK_RESTRICT2:
6268 case TOK_RESTRICT3:
6269 next();
6270 goto redo;
6272 mk_pointer(type);
6275 /* XXX: clarify attribute handling */
6276 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6277 parse_attribute(ad);
6279 /* recursive type */
6280 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6281 type1.t = 0; /* XXX: same as int */
6282 if (tok == '(') {
6283 next();
6284 /* XXX: this is not correct to modify 'ad' at this point, but
6285 the syntax is not clear */
6286 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6287 parse_attribute(ad);
6288 type_decl(&type1, ad, v, td);
6289 skip(')');
6290 } else {
6291 /* type identifier */
6292 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6293 *v = tok;
6294 next();
6295 } else {
6296 if (!(td & TYPE_ABSTRACT))
6297 expect("identifier");
6298 *v = 0;
6301 post_type(type, ad);
6302 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6303 parse_attribute(ad);
6304 if (!type1.t)
6305 return;
6306 /* append type at the end of type1 */
6307 type2 = &type1;
6308 for(;;) {
6309 s = type2->ref;
6310 type2 = &s->type;
6311 if (!type2->t) {
6312 *type2 = *type;
6313 break;
6316 *type = type1;
6319 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6320 static int lvalue_type(int t)
6322 int bt, r;
6323 r = VT_LVAL;
6324 bt = t & VT_BTYPE;
6325 if (bt == VT_BYTE || bt == VT_BOOL)
6326 r |= VT_LVAL_BYTE;
6327 else if (bt == VT_SHORT)
6328 r |= VT_LVAL_SHORT;
6329 else
6330 return r;
6331 if (t & VT_UNSIGNED)
6332 r |= VT_LVAL_UNSIGNED;
6333 return r;
6336 /* indirection with full error checking and bound check */
6337 static void indir(void)
6339 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6340 expect("pointer");
6341 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6342 gv(RC_INT);
6343 vtop->type = *pointed_type(&vtop->type);
6344 /* an array is never an lvalue */
6345 if (!(vtop->type.t & VT_ARRAY)) {
6346 vtop->r |= lvalue_type(vtop->type.t);
6347 /* if bound checking, the referenced pointer must be checked */
6348 if (do_bounds_check)
6349 vtop->r |= VT_MUSTBOUND;
6353 /* pass a parameter to a function and do type checking and casting */
6354 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
6356 int func_type;
6357 CType type;
6359 func_type = func->c;
6360 if (func_type == FUNC_OLD ||
6361 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6362 /* default casting : only need to convert float to double */
6363 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6364 type.t = VT_DOUBLE;
6365 gen_cast(&type);
6367 } else if (arg == NULL) {
6368 error("too many arguments to function");
6369 } else {
6370 gen_assign_cast(&arg->type);
6372 if (!nocode_wanted) {
6373 gfunc_param(gf);
6374 } else {
6375 vpop();
6379 /* parse an expression of the form '(type)' or '(expr)' and return its
6380 type */
6381 static void parse_expr_type(CType *type)
6383 int n;
6384 AttributeDef ad;
6386 skip('(');
6387 if (parse_btype(type, &ad)) {
6388 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6389 } else {
6390 expr_type(type);
6392 skip(')');
6395 static void vpush_tokc(int t)
6397 CType type;
6398 type.t = t;
6399 vsetc(&type, VT_CONST, &tokc);
6402 static void unary(void)
6404 int n, t, align, size, r;
6405 CType type;
6406 Sym *s;
6407 GFuncContext gf;
6408 AttributeDef ad;
6410 /* XXX: GCC 2.95.3 does not generate a table although it should be
6411 better here */
6412 tok_next:
6413 switch(tok) {
6414 case TOK_EXTENSION:
6415 next();
6416 goto tok_next;
6417 case TOK_CINT:
6418 case TOK_CCHAR:
6419 case TOK_LCHAR:
6420 vpushi(tokc.i);
6421 next();
6422 break;
6423 case TOK_CUINT:
6424 vpush_tokc(VT_INT | VT_UNSIGNED);
6425 next();
6426 break;
6427 case TOK_CLLONG:
6428 vpush_tokc(VT_LLONG);
6429 next();
6430 break;
6431 case TOK_CULLONG:
6432 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6433 next();
6434 break;
6435 case TOK_CFLOAT:
6436 vpush_tokc(VT_FLOAT);
6437 next();
6438 break;
6439 case TOK_CDOUBLE:
6440 vpush_tokc(VT_DOUBLE);
6441 next();
6442 break;
6443 case TOK_CLDOUBLE:
6444 vpush_tokc(VT_LDOUBLE);
6445 next();
6446 break;
6447 case TOK___FUNCTION__:
6448 if (!gnu_ext)
6449 goto tok_identifier;
6450 /* fall thru */
6451 case TOK___FUNC__:
6453 void *ptr;
6454 int len;
6455 /* special function name identifier */
6456 len = strlen(funcname) + 1;
6457 /* generate char[len] type */
6458 type.t = VT_BYTE;
6459 mk_pointer(&type);
6460 type.t |= VT_ARRAY;
6461 type.ref->c = len;
6462 vpush_ref(&type, data_section, data_section->data_offset, len);
6463 ptr = section_ptr_add(data_section, len);
6464 memcpy(ptr, funcname, len);
6465 next();
6467 break;
6468 case TOK_LSTR:
6469 t = VT_INT;
6470 goto str_init;
6471 case TOK_STR:
6472 /* string parsing */
6473 t = VT_BYTE;
6474 str_init:
6475 type.t = t;
6476 mk_pointer(&type);
6477 type.t |= VT_ARRAY;
6478 memset(&ad, 0, sizeof(AttributeDef));
6479 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6480 break;
6481 case '(':
6482 next();
6483 /* cast ? */
6484 if (parse_btype(&type, &ad)) {
6485 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6486 skip(')');
6487 /* check ISOC99 compound literal */
6488 if (tok == '{') {
6489 /* data is allocated locally by default */
6490 if (global_expr)
6491 r = VT_CONST;
6492 else
6493 r = VT_LOCAL;
6494 /* all except arrays are lvalues */
6495 if (!(type.t & VT_ARRAY))
6496 r |= lvalue_type(type.t);
6497 memset(&ad, 0, sizeof(AttributeDef));
6498 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6499 } else {
6500 unary();
6501 gen_cast(&type);
6503 } else if (tok == '{') {
6504 /* save all registers */
6505 save_regs(0);
6506 /* statement expression : we do not accept break/continue
6507 inside as GCC does */
6508 block(NULL, NULL, NULL, NULL, 0, 1);
6509 skip(')');
6510 } else {
6511 gexpr();
6512 skip(')');
6514 break;
6515 case '*':
6516 next();
6517 unary();
6518 indir();
6519 break;
6520 case '&':
6521 next();
6522 unary();
6523 /* functions names must be treated as function pointers,
6524 except for unary '&' and sizeof. Since we consider that
6525 functions are not lvalues, we only have to handle it
6526 there and in function calls. */
6527 /* arrays can also be used although they are not lvalues */
6528 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6529 !(vtop->type.t & VT_ARRAY))
6530 test_lvalue();
6531 mk_pointer(&vtop->type);
6532 gaddrof();
6533 break;
6534 case '!':
6535 next();
6536 unary();
6537 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6538 vtop->c.i = !vtop->c.i;
6539 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6540 vtop->c.i = vtop->c.i ^ 1;
6541 else
6542 vseti(VT_JMP, gtst(1, 0));
6543 break;
6544 case '~':
6545 next();
6546 unary();
6547 vpushi(-1);
6548 gen_op('^');
6549 break;
6550 case '+':
6551 next();
6552 /* in order to force cast, we add zero */
6553 unary();
6554 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6555 error("pointer not accepted for unary plus");
6556 vpushi(0);
6557 gen_op('+');
6558 break;
6559 case TOK_SIZEOF:
6560 case TOK_ALIGNOF1:
6561 case TOK_ALIGNOF2:
6562 t = tok;
6563 next();
6564 if (tok == '(') {
6565 parse_expr_type(&type);
6566 } else {
6567 unary_type(&type);
6569 size = type_size(&type, &align);
6570 if (t == TOK_SIZEOF)
6571 vpushi(size);
6572 else
6573 vpushi(align);
6574 break;
6576 case TOK_INC:
6577 case TOK_DEC:
6578 t = tok;
6579 next();
6580 unary();
6581 inc(0, t);
6582 break;
6583 case '-':
6584 next();
6585 vpushi(0);
6586 unary();
6587 gen_op('-');
6588 break;
6589 case TOK_LAND:
6590 if (!gnu_ext)
6591 goto tok_identifier;
6592 next();
6593 /* allow to take the address of a label */
6594 if (tok < TOK_UIDENT)
6595 expect("label identifier");
6596 s = label_find(tok);
6597 if (!s) {
6598 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6599 } else {
6600 if (s->r == LABEL_DECLARED)
6601 s->r = LABEL_FORWARD;
6603 if (!s->type.t) {
6604 s->type.t = VT_VOID;
6605 mk_pointer(&s->type);
6606 s->type.t |= VT_STATIC;
6608 vset(&s->type, VT_CONST | VT_SYM, 0);
6609 vtop->sym = s;
6610 next();
6611 break;
6612 default:
6613 tok_identifier:
6614 t = tok;
6615 next();
6616 if (t < TOK_UIDENT)
6617 expect("identifier");
6618 s = sym_find(t);
6619 if (!s) {
6620 if (tok != '(')
6621 error("'%s' undeclared", get_tok_str(t, NULL));
6622 /* for simple function calls, we tolerate undeclared
6623 external reference to int() function */
6624 s = external_global_sym(t, &func_old_type, 0);
6626 vset(&s->type, s->r, s->c);
6627 /* if forward reference, we must point to s */
6628 if (vtop->r & VT_SYM) {
6629 vtop->sym = s;
6630 vtop->c.ul = 0;
6632 break;
6635 /* post operations */
6636 while (1) {
6637 if (tok == TOK_INC || tok == TOK_DEC) {
6638 inc(1, tok);
6639 next();
6640 } else if (tok == '.' || tok == TOK_ARROW) {
6641 /* field */
6642 if (tok == TOK_ARROW)
6643 indir();
6644 test_lvalue();
6645 gaddrof();
6646 next();
6647 /* expect pointer on structure */
6648 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6649 expect("struct or union");
6650 s = vtop->type.ref;
6651 /* find field */
6652 tok |= SYM_FIELD;
6653 while ((s = s->next) != NULL) {
6654 if (s->v == tok)
6655 break;
6657 if (!s)
6658 error("field not found");
6659 /* add field offset to pointer */
6660 vtop->type = char_pointer_type; /* change type to 'char *' */
6661 vpushi(s->c);
6662 gen_op('+');
6663 /* change type to field type, and set to lvalue */
6664 vtop->type = s->type;
6665 /* an array is never an lvalue */
6666 if (!(vtop->type.t & VT_ARRAY)) {
6667 vtop->r |= lvalue_type(vtop->type.t);
6668 /* if bound checking, the referenced pointer must be checked */
6669 if (do_bounds_check)
6670 vtop->r |= VT_MUSTBOUND;
6672 next();
6673 } else if (tok == '[') {
6674 next();
6675 gexpr();
6676 gen_op('+');
6677 indir();
6678 skip(']');
6679 } else if (tok == '(') {
6680 SValue ret;
6681 Sym *sa;
6683 /* function call */
6684 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
6685 /* pointer test (no array accepted) */
6686 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
6687 vtop->type = *pointed_type(&vtop->type);
6688 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
6689 goto error_func;
6690 } else {
6691 error_func:
6692 expect("function pointer");
6694 } else {
6695 vtop->r &= ~VT_LVAL; /* no lvalue */
6697 /* get return type */
6698 s = vtop->type.ref;
6699 if (!nocode_wanted) {
6700 save_regs(0); /* save used temporary registers */
6701 gfunc_start(&gf, s->r);
6703 next();
6704 sa = s->next; /* first parameter */
6705 #ifdef INVERT_FUNC_PARAMS
6707 int parlevel;
6708 Sym *args, *s1;
6709 ParseState saved_parse_state;
6710 TokenString str;
6712 /* read each argument and store it on a stack */
6713 args = NULL;
6714 if (tok != ')') {
6715 for(;;) {
6716 tok_str_new(&str);
6717 parlevel = 0;
6718 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
6719 tok != TOK_EOF) {
6720 if (tok == '(')
6721 parlevel++;
6722 else if (tok == ')')
6723 parlevel--;
6724 tok_str_add_tok(&str);
6725 next();
6727 tok_str_add(&str, -1); /* end of file added */
6728 tok_str_add(&str, 0);
6729 s1 = sym_push2(&args, 0, 0, (int)str.str);
6730 s1->next = sa; /* add reference to argument */
6731 if (sa)
6732 sa = sa->next;
6733 if (tok == ')')
6734 break;
6735 skip(',');
6739 /* now generate code in reverse order by reading the stack */
6740 save_parse_state(&saved_parse_state);
6741 while (args) {
6742 macro_ptr = (int *)args->c;
6743 next();
6744 expr_eq();
6745 if (tok != -1)
6746 expect("',' or ')'");
6747 gfunc_param_typed(&gf, s, args->next);
6748 s1 = args->prev;
6749 tok_str_free((int *)args->c);
6750 tcc_free(args);
6751 args = s1;
6753 restore_parse_state(&saved_parse_state);
6755 #endif
6756 /* compute first implicit argument if a structure is returned */
6757 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
6758 /* get some space for the returned structure */
6759 size = type_size(&s->type, &align);
6760 loc = (loc - size) & -align;
6761 ret.type = s->type;
6762 ret.r = VT_LOCAL | VT_LVAL;
6763 /* pass it as 'int' to avoid structure arg passing
6764 problems */
6765 vseti(VT_LOCAL, loc);
6766 ret.c = vtop->c;
6767 if (!nocode_wanted)
6768 gfunc_param(&gf);
6769 else
6770 vtop--;
6771 } else {
6772 ret.type = s->type;
6773 ret.r2 = VT_CONST;
6774 /* return in register */
6775 if (is_float(ret.type.t)) {
6776 ret.r = REG_FRET;
6777 } else {
6778 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
6779 ret.r2 = REG_LRET;
6780 ret.r = REG_IRET;
6782 ret.c.i = 0;
6784 #ifndef INVERT_FUNC_PARAMS
6785 if (tok != ')') {
6786 for(;;) {
6787 expr_eq();
6788 gfunc_param_typed(&gf, s, sa);
6789 if (sa)
6790 sa = sa->next;
6791 if (tok == ')')
6792 break;
6793 skip(',');
6796 #endif
6797 if (sa)
6798 error("too few arguments to function");
6799 skip(')');
6800 if (!nocode_wanted)
6801 gfunc_call(&gf);
6802 else
6803 vtop--;
6804 /* return value */
6805 vsetc(&ret.type, ret.r, &ret.c);
6806 vtop->r2 = ret.r2;
6807 } else {
6808 break;
6813 static void uneq(void)
6815 int t;
6817 unary();
6818 if (tok == '=' ||
6819 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
6820 tok == TOK_A_XOR || tok == TOK_A_OR ||
6821 tok == TOK_A_SHL || tok == TOK_A_SAR) {
6822 test_lvalue();
6823 t = tok;
6824 next();
6825 if (t == '=') {
6826 expr_eq();
6827 } else {
6828 vdup();
6829 expr_eq();
6830 gen_op(t & 0x7f);
6832 vstore();
6836 static void expr_prod(void)
6838 int t;
6840 uneq();
6841 while (tok == '*' || tok == '/' || tok == '%') {
6842 t = tok;
6843 next();
6844 uneq();
6845 gen_op(t);
6849 static void expr_sum(void)
6851 int t;
6853 expr_prod();
6854 while (tok == '+' || tok == '-') {
6855 t = tok;
6856 next();
6857 expr_prod();
6858 gen_op(t);
6862 static void expr_shift(void)
6864 int t;
6866 expr_sum();
6867 while (tok == TOK_SHL || tok == TOK_SAR) {
6868 t = tok;
6869 next();
6870 expr_sum();
6871 gen_op(t);
6875 static void expr_cmp(void)
6877 int t;
6879 expr_shift();
6880 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
6881 tok == TOK_ULT || tok == TOK_UGE) {
6882 t = tok;
6883 next();
6884 expr_shift();
6885 gen_op(t);
6889 static void expr_cmpeq(void)
6891 int t;
6893 expr_cmp();
6894 while (tok == TOK_EQ || tok == TOK_NE) {
6895 t = tok;
6896 next();
6897 expr_cmp();
6898 gen_op(t);
6902 static void expr_and(void)
6904 expr_cmpeq();
6905 while (tok == '&') {
6906 next();
6907 expr_cmpeq();
6908 gen_op('&');
6912 static void expr_xor(void)
6914 expr_and();
6915 while (tok == '^') {
6916 next();
6917 expr_and();
6918 gen_op('^');
6922 static void expr_or(void)
6924 expr_xor();
6925 while (tok == '|') {
6926 next();
6927 expr_xor();
6928 gen_op('|');
6932 /* XXX: fix this mess */
6933 static void expr_land_const(void)
6935 expr_or();
6936 while (tok == TOK_LAND) {
6937 next();
6938 expr_or();
6939 gen_op(TOK_LAND);
6943 /* XXX: fix this mess */
6944 static void expr_lor_const(void)
6946 expr_land_const();
6947 while (tok == TOK_LOR) {
6948 next();
6949 expr_land_const();
6950 gen_op(TOK_LOR);
6954 /* only used if non constant */
6955 static void expr_land(void)
6957 int t;
6959 expr_or();
6960 if (tok == TOK_LAND) {
6961 t = 0;
6962 for(;;) {
6963 t = gtst(1, t);
6964 if (tok != TOK_LAND) {
6965 vseti(VT_JMPI, t);
6966 break;
6968 next();
6969 expr_or();
6974 static void expr_lor(void)
6976 int t;
6978 expr_land();
6979 if (tok == TOK_LOR) {
6980 t = 0;
6981 for(;;) {
6982 t = gtst(0, t);
6983 if (tok != TOK_LOR) {
6984 vseti(VT_JMP, t);
6985 break;
6987 next();
6988 expr_land();
6993 /* XXX: better constant handling */
6994 static void expr_eq(void)
6996 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
6997 SValue sv;
6998 CType type, type1, type2;
7000 if (const_wanted) {
7001 int c1, c;
7002 expr_lor_const();
7003 if (tok == '?') {
7004 c = vtop->c.i;
7005 vpop();
7006 next();
7007 if (tok == ':' && gnu_ext) {
7008 c1 = c;
7009 } else {
7010 gexpr();
7011 c1 = vtop->c.i;
7012 vpop();
7014 skip(':');
7015 expr_eq();
7016 if (c)
7017 vtop->c.i = c1;
7019 } else {
7020 expr_lor();
7021 if (tok == '?') {
7022 next();
7023 if (vtop != vstack) {
7024 /* needed to avoid having different registers saved in
7025 each branch */
7026 if (is_float(vtop->type.t))
7027 rc = RC_FLOAT;
7028 else
7029 rc = RC_INT;
7030 gv(rc);
7031 save_regs(1);
7033 if (tok == ':' && gnu_ext) {
7034 gv_dup();
7035 tt = gtst(1, 0);
7036 } else {
7037 tt = gtst(1, 0);
7038 gexpr();
7040 type1 = vtop->type;
7041 sv = *vtop; /* save value to handle it later */
7042 vtop--; /* no vpop so that FP stack is not flushed */
7043 skip(':');
7044 u = gjmp(0);
7045 gsym(tt);
7046 expr_eq();
7047 type2 = vtop->type;
7049 t1 = type1.t;
7050 bt1 = t1 & VT_BTYPE;
7051 t2 = type2.t;
7052 bt2 = t2 & VT_BTYPE;
7053 /* cast operands to correct type according to ISOC rules */
7054 if (is_float(bt1) || is_float(bt2)) {
7055 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7056 type.t = VT_LDOUBLE;
7057 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7058 type.t = VT_DOUBLE;
7059 } else {
7060 type.t = VT_FLOAT;
7062 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7063 /* cast to biggest op */
7064 type.t = VT_LLONG;
7065 /* convert to unsigned if it does not fit in a long long */
7066 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7067 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7068 type.t |= VT_UNSIGNED;
7069 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7070 /* XXX: test pointer compatibility */
7071 type = type1;
7072 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7073 /* XXX: test structure compatibility */
7074 type = type1;
7075 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7076 /* NOTE: as an extension, we accept void on only one side */
7077 type.t = VT_VOID;
7078 } else {
7079 /* integer operations */
7080 type.t = VT_INT;
7081 /* convert to unsigned if it does not fit in an integer */
7082 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7083 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7084 type.t |= VT_UNSIGNED;
7087 /* now we convert second operand */
7088 gen_cast(&type);
7089 rc = RC_INT;
7090 if (is_float(type.t)) {
7091 rc = RC_FLOAT;
7092 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7093 /* for long longs, we use fixed registers to avoid having
7094 to handle a complicated move */
7095 rc = RC_IRET;
7098 r2 = gv(rc);
7099 /* this is horrible, but we must also convert first
7100 operand */
7101 tt = gjmp(0);
7102 gsym(u);
7103 /* put again first value and cast it */
7104 *vtop = sv;
7105 gen_cast(&type);
7106 r1 = gv(rc);
7107 move_reg(r2, r1);
7108 vtop->r = r2;
7109 gsym(tt);
7114 static void gexpr(void)
7116 while (1) {
7117 expr_eq();
7118 if (tok != ',')
7119 break;
7120 vpop();
7121 next();
7125 /* parse an expression and return its type without any side effect. */
7126 static void expr_type(CType *type)
7128 int a;
7130 a = nocode_wanted;
7131 nocode_wanted = 1;
7132 gexpr();
7133 *type = vtop->type;
7134 vpop();
7135 nocode_wanted = a;
7138 /* parse a unary expression and return its type without any side
7139 effect. */
7140 static void unary_type(CType *type)
7142 int a;
7144 a = nocode_wanted;
7145 nocode_wanted = 1;
7146 unary();
7147 *type = vtop->type;
7148 vpop();
7149 nocode_wanted = a;
7152 /* parse a constant expression and return value in vtop. */
7153 static void expr_const1(void)
7155 int a;
7156 a = const_wanted;
7157 const_wanted = 1;
7158 expr_eq();
7159 const_wanted = a;
7162 /* parse an integer constant and return its value. */
7163 static int expr_const(void)
7165 int c;
7166 expr_const1();
7167 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7168 expect("constant expression");
7169 c = vtop->c.i;
7170 vpop();
7171 return c;
7174 /* return the label token if current token is a label, otherwise
7175 return zero */
7176 static int is_label(void)
7178 int last_tok;
7180 /* fast test first */
7181 if (tok < TOK_UIDENT)
7182 return 0;
7183 /* no need to save tokc because tok is an identifier */
7184 last_tok = tok;
7185 next();
7186 if (tok == ':') {
7187 next();
7188 return last_tok;
7189 } else {
7190 unget_tok(last_tok);
7191 return 0;
7195 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7196 int case_reg, int is_expr)
7198 int a, b, c, d;
7199 Sym *s;
7201 /* generate line number info */
7202 if (do_debug &&
7203 (last_line_num != file->line_num || last_ind != ind)) {
7204 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7205 last_ind = ind;
7206 last_line_num = file->line_num;
7209 if (is_expr) {
7210 /* default return value is (void) */
7211 vpushi(0);
7212 vtop->type.t = VT_VOID;
7215 if (tok == TOK_IF) {
7216 /* if test */
7217 next();
7218 skip('(');
7219 gexpr();
7220 skip(')');
7221 a = gtst(1, 0);
7222 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7223 c = tok;
7224 if (c == TOK_ELSE) {
7225 next();
7226 d = gjmp(0);
7227 gsym(a);
7228 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7229 gsym(d); /* patch else jmp */
7230 } else
7231 gsym(a);
7232 } else if (tok == TOK_WHILE) {
7233 next();
7234 d = ind;
7235 skip('(');
7236 gexpr();
7237 skip(')');
7238 a = gtst(1, 0);
7239 b = 0;
7240 block(&a, &b, case_sym, def_sym, case_reg, 0);
7241 gjmp_addr(d);
7242 gsym(a);
7243 gsym_addr(b, d);
7244 } else if (tok == '{') {
7245 Sym *llabel;
7247 next();
7248 /* record local declaration stack position */
7249 s = local_stack;
7250 llabel = local_label_stack;
7251 /* handle local labels declarations */
7252 if (tok == TOK_LABEL) {
7253 next();
7254 for(;;) {
7255 if (tok < TOK_UIDENT)
7256 expect("label identifier");
7257 label_push(&local_label_stack, tok, LABEL_DECLARED);
7258 next();
7259 if (tok == ',') {
7260 next();
7261 } else {
7262 skip(';');
7263 break;
7267 while (tok != '}') {
7268 decl(VT_LOCAL);
7269 if (tok != '}') {
7270 if (is_expr)
7271 vpop();
7272 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7275 /* pop locally defined labels */
7276 label_pop(&local_label_stack, llabel);
7277 /* pop locally defined symbols */
7278 sym_pop(&local_stack, s);
7279 next();
7280 } else if (tok == TOK_RETURN) {
7281 next();
7282 if (tok != ';') {
7283 gexpr();
7284 gen_assign_cast(&func_vt);
7285 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7286 CType type;
7287 /* if returning structure, must copy it to implicit
7288 first pointer arg location */
7289 type = func_vt;
7290 mk_pointer(&type);
7291 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7292 indir();
7293 vswap();
7294 /* copy structure value to pointer */
7295 vstore();
7296 } else if (is_float(func_vt.t)) {
7297 gv(RC_FRET);
7298 } else {
7299 gv(RC_IRET);
7301 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7303 skip(';');
7304 rsym = gjmp(rsym); /* jmp */
7305 } else if (tok == TOK_BREAK) {
7306 /* compute jump */
7307 if (!bsym)
7308 error("cannot break");
7309 *bsym = gjmp(*bsym);
7310 next();
7311 skip(';');
7312 } else if (tok == TOK_CONTINUE) {
7313 /* compute jump */
7314 if (!csym)
7315 error("cannot continue");
7316 *csym = gjmp(*csym);
7317 next();
7318 skip(';');
7319 } else if (tok == TOK_FOR) {
7320 int e;
7321 next();
7322 skip('(');
7323 if (tok != ';') {
7324 gexpr();
7325 vpop();
7327 skip(';');
7328 d = ind;
7329 c = ind;
7330 a = 0;
7331 b = 0;
7332 if (tok != ';') {
7333 gexpr();
7334 a = gtst(1, 0);
7336 skip(';');
7337 if (tok != ')') {
7338 e = gjmp(0);
7339 c = ind;
7340 gexpr();
7341 vpop();
7342 gjmp_addr(d);
7343 gsym(e);
7345 skip(')');
7346 block(&a, &b, case_sym, def_sym, case_reg, 0);
7347 gjmp_addr(c);
7348 gsym(a);
7349 gsym_addr(b, c);
7350 } else
7351 if (tok == TOK_DO) {
7352 next();
7353 a = 0;
7354 b = 0;
7355 d = ind;
7356 block(&a, &b, case_sym, def_sym, case_reg, 0);
7357 skip(TOK_WHILE);
7358 skip('(');
7359 gsym(b);
7360 gexpr();
7361 c = gtst(0, 0);
7362 gsym_addr(c, d);
7363 skip(')');
7364 gsym(a);
7365 skip(';');
7366 } else
7367 if (tok == TOK_SWITCH) {
7368 next();
7369 skip('(');
7370 gexpr();
7371 /* XXX: other types than integer */
7372 case_reg = gv(RC_INT);
7373 vpop();
7374 skip(')');
7375 a = 0;
7376 b = gjmp(0); /* jump to first case */
7377 c = 0;
7378 block(&a, csym, &b, &c, case_reg, 0);
7379 /* if no default, jmp after switch */
7380 if (c == 0)
7381 c = ind;
7382 /* default label */
7383 gsym_addr(b, c);
7384 /* break label */
7385 gsym(a);
7386 } else
7387 if (tok == TOK_CASE) {
7388 int v1, v2;
7389 if (!case_sym)
7390 expect("switch");
7391 next();
7392 v1 = expr_const();
7393 v2 = v1;
7394 if (gnu_ext && tok == TOK_DOTS) {
7395 next();
7396 v2 = expr_const();
7397 if (v2 < v1)
7398 warning("empty case range");
7400 /* since a case is like a label, we must skip it with a jmp */
7401 b = gjmp(0);
7402 gsym(*case_sym);
7403 vseti(case_reg, 0);
7404 vpushi(v1);
7405 if (v1 == v2) {
7406 gen_op(TOK_EQ);
7407 *case_sym = gtst(1, 0);
7408 } else {
7409 gen_op(TOK_GE);
7410 *case_sym = gtst(1, 0);
7411 vseti(case_reg, 0);
7412 vpushi(v2);
7413 gen_op(TOK_LE);
7414 *case_sym = gtst(1, *case_sym);
7416 gsym(b);
7417 skip(':');
7418 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7419 } else
7420 if (tok == TOK_DEFAULT) {
7421 next();
7422 skip(':');
7423 if (!def_sym)
7424 expect("switch");
7425 if (*def_sym)
7426 error("too many 'default'");
7427 *def_sym = ind;
7428 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7429 } else
7430 if (tok == TOK_GOTO) {
7431 next();
7432 if (tok == '*' && gnu_ext) {
7433 /* computed goto */
7434 next();
7435 gexpr();
7436 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7437 expect("pointer");
7438 ggoto();
7439 } else if (tok >= TOK_UIDENT) {
7440 s = label_find(tok);
7441 /* put forward definition if needed */
7442 if (!s) {
7443 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7444 } else {
7445 if (s->r == LABEL_DECLARED)
7446 s->r = LABEL_FORWARD;
7448 /* label already defined */
7449 if (s->r & LABEL_FORWARD)
7450 s->next = (void *)gjmp((long)s->next);
7451 else
7452 gjmp_addr((long)s->next);
7453 next();
7454 } else {
7455 expect("label identifier");
7457 skip(';');
7458 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7459 asm_instr();
7460 } else {
7461 b = is_label();
7462 if (b) {
7463 /* label case */
7464 s = label_find(b);
7465 if (s) {
7466 if (s->r == LABEL_DEFINED)
7467 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7468 gsym((long)s->next);
7469 s->r = LABEL_DEFINED;
7470 } else {
7471 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7473 s->next = (void *)ind;
7474 /* we accept this, but it is a mistake */
7475 if (tok == '}') {
7476 warning("deprecated use of label at end of compound statement");
7477 } else {
7478 if (is_expr)
7479 vpop();
7480 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7482 } else {
7483 /* expression case */
7484 if (tok != ';') {
7485 if (is_expr) {
7486 vpop();
7487 gexpr();
7488 } else {
7489 gexpr();
7490 vpop();
7493 skip(';');
7498 /* t is the array or struct type. c is the array or struct
7499 address. cur_index/cur_field is the pointer to the current
7500 value. 'size_only' is true if only size info is needed (only used
7501 in arrays) */
7502 static void decl_designator(CType *type, Section *sec, unsigned long c,
7503 int *cur_index, Sym **cur_field,
7504 int size_only)
7506 Sym *s, *f;
7507 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7508 CType type1;
7510 notfirst = 0;
7511 elem_size = 0;
7512 nb_elems = 1;
7513 if (gnu_ext && (l = is_label()) != 0)
7514 goto struct_field;
7515 while (tok == '[' || tok == '.') {
7516 if (tok == '[') {
7517 if (!(type->t & VT_ARRAY))
7518 expect("array type");
7519 s = type->ref;
7520 next();
7521 index = expr_const();
7522 if (index < 0 || (s->c >= 0 && index >= s->c))
7523 expect("invalid index");
7524 if (tok == TOK_DOTS && gnu_ext) {
7525 next();
7526 index_last = expr_const();
7527 if (index_last < 0 ||
7528 (s->c >= 0 && index_last >= s->c) ||
7529 index_last < index)
7530 expect("invalid index");
7531 } else {
7532 index_last = index;
7534 skip(']');
7535 if (!notfirst)
7536 *cur_index = index_last;
7537 type = pointed_type(type);
7538 elem_size = type_size(type, &align);
7539 c += index * elem_size;
7540 /* NOTE: we only support ranges for last designator */
7541 nb_elems = index_last - index + 1;
7542 if (nb_elems != 1) {
7543 notfirst = 1;
7544 break;
7546 } else {
7547 next();
7548 l = tok;
7549 next();
7550 struct_field:
7551 if ((type->t & VT_BTYPE) != VT_STRUCT)
7552 expect("struct/union type");
7553 s = type->ref;
7554 l |= SYM_FIELD;
7555 f = s->next;
7556 while (f) {
7557 if (f->v == l)
7558 break;
7559 f = f->next;
7561 if (!f)
7562 expect("field");
7563 if (!notfirst)
7564 *cur_field = f;
7565 /* XXX: fix this mess by using explicit storage field */
7566 type1 = f->type;
7567 type1.t |= (type->t & ~VT_TYPE);
7568 type = &type1;
7569 c += f->c;
7571 notfirst = 1;
7573 if (notfirst) {
7574 if (tok == '=') {
7575 next();
7576 } else {
7577 if (!gnu_ext)
7578 expect("=");
7580 } else {
7581 if (type->t & VT_ARRAY) {
7582 index = *cur_index;
7583 type = pointed_type(type);
7584 c += index * type_size(type, &align);
7585 } else {
7586 f = *cur_field;
7587 if (!f)
7588 error("too many field init");
7589 /* XXX: fix this mess by using explicit storage field */
7590 type1 = f->type;
7591 type1.t |= (type->t & ~VT_TYPE);
7592 type = &type1;
7593 c += f->c;
7596 decl_initializer(type, sec, c, 0, size_only);
7598 /* XXX: make it more general */
7599 if (!size_only && nb_elems > 1) {
7600 unsigned long c_end;
7601 uint8_t *src, *dst;
7602 int i;
7604 if (!sec)
7605 error("range init not supported yet for dynamic storage");
7606 c_end = c + nb_elems * elem_size;
7607 if (c_end > sec->data_allocated)
7608 section_realloc(sec, c_end);
7609 src = sec->data + c;
7610 dst = src;
7611 for(i = 1; i < nb_elems; i++) {
7612 dst += elem_size;
7613 memcpy(dst, src, elem_size);
7618 #define EXPR_VAL 0
7619 #define EXPR_CONST 1
7620 #define EXPR_ANY 2
7622 /* store a value or an expression directly in global data or in local array */
7623 static void init_putv(CType *type, Section *sec, unsigned long c,
7624 int v, int expr_type)
7626 int saved_global_expr, bt, bit_pos, bit_size;
7627 void *ptr;
7628 unsigned long long bit_mask;
7630 switch(expr_type) {
7631 case EXPR_VAL:
7632 vpushi(v);
7633 break;
7634 case EXPR_CONST:
7635 /* compound literals must be allocated globally in this case */
7636 saved_global_expr = global_expr;
7637 global_expr = 1;
7638 expr_const1();
7639 global_expr = saved_global_expr;
7640 /* NOTE: symbols are accepted */
7641 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
7642 error("initializer element is not constant");
7643 break;
7644 case EXPR_ANY:
7645 expr_eq();
7646 break;
7649 if (sec) {
7650 /* XXX: not portable */
7651 /* XXX: generate error if incorrect relocation */
7652 gen_assign_cast(type);
7653 bt = type->t & VT_BTYPE;
7654 ptr = sec->data + c;
7655 /* XXX: make code faster ? */
7656 if (!(type->t & VT_BITFIELD)) {
7657 bit_pos = 0;
7658 bit_size = 32;
7659 bit_mask = -1LL;
7660 } else {
7661 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
7662 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
7663 bit_mask = (1LL << bit_size) - 1;
7665 if ((vtop->r & VT_SYM) &&
7666 (bt == VT_BYTE ||
7667 bt == VT_SHORT ||
7668 bt == VT_DOUBLE ||
7669 bt == VT_LDOUBLE ||
7670 bt == VT_LLONG ||
7671 (bt == VT_INT && bit_size != 32)))
7672 error("initializer element is not computable at load time");
7673 switch(bt) {
7674 case VT_BYTE:
7675 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7676 break;
7677 case VT_SHORT:
7678 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7679 break;
7680 case VT_DOUBLE:
7681 *(double *)ptr = vtop->c.d;
7682 break;
7683 case VT_LDOUBLE:
7684 *(long double *)ptr = vtop->c.ld;
7685 break;
7686 case VT_LLONG:
7687 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
7688 break;
7689 default:
7690 if (vtop->r & VT_SYM) {
7691 greloc(sec, vtop->sym, c, R_DATA_32);
7693 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7694 break;
7696 vtop--;
7697 } else {
7698 vset(type, VT_LOCAL, c);
7699 vswap();
7700 vstore();
7701 vpop();
7705 /* put zeros for variable based init */
7706 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
7708 GFuncContext gf;
7710 if (sec) {
7711 /* nothing to do because globals are already set to zero */
7712 } else {
7713 gfunc_start(&gf, FUNC_CDECL);
7714 vpushi(size);
7715 gfunc_param(&gf);
7716 vpushi(0);
7717 gfunc_param(&gf);
7718 vseti(VT_LOCAL, c);
7719 gfunc_param(&gf);
7720 vpush_global_sym(&func_old_type, TOK_memset);
7721 gfunc_call(&gf);
7725 /* 't' contains the type and storage info. 'c' is the offset of the
7726 object in section 'sec'. If 'sec' is NULL, it means stack based
7727 allocation. 'first' is true if array '{' must be read (multi
7728 dimension implicit array init handling). 'size_only' is true if
7729 size only evaluation is wanted (only for arrays). */
7730 static void decl_initializer(CType *type, Section *sec, unsigned long c,
7731 int first, int size_only)
7733 int index, array_length, n, no_oblock, nb, parlevel, i;
7734 int size1, align1, expr_type;
7735 Sym *s, *f;
7736 CType *t1;
7738 if (type->t & VT_ARRAY) {
7739 s = type->ref;
7740 n = s->c;
7741 array_length = 0;
7742 t1 = pointed_type(type);
7743 size1 = type_size(t1, &align1);
7745 no_oblock = 1;
7746 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
7747 tok == '{') {
7748 skip('{');
7749 no_oblock = 0;
7752 /* only parse strings here if correct type (otherwise: handle
7753 them as ((w)char *) expressions */
7754 if ((tok == TOK_LSTR &&
7755 (t1->t & VT_BTYPE) == VT_INT) ||
7756 (tok == TOK_STR &&
7757 (t1->t & VT_BTYPE) == VT_BYTE)) {
7758 while (tok == TOK_STR || tok == TOK_LSTR) {
7759 int cstr_len, ch;
7760 CString *cstr;
7762 cstr = tokc.cstr;
7763 /* compute maximum number of chars wanted */
7764 if (tok == TOK_STR)
7765 cstr_len = cstr->size;
7766 else
7767 cstr_len = cstr->size / sizeof(int);
7768 cstr_len--;
7769 nb = cstr_len;
7770 if (n >= 0 && nb > (n - array_length))
7771 nb = n - array_length;
7772 if (!size_only) {
7773 if (cstr_len > nb)
7774 warning("initializer-string for array is too long");
7775 /* in order to go faster for common case (char
7776 string in global variable, we handle it
7777 specifically */
7778 if (sec && tok == TOK_STR && size1 == 1) {
7779 memcpy(sec->data + c + array_length, cstr->data, nb);
7780 } else {
7781 for(i=0;i<nb;i++) {
7782 if (tok == TOK_STR)
7783 ch = ((unsigned char *)cstr->data)[i];
7784 else
7785 ch = ((int *)cstr->data)[i];
7786 init_putv(t1, sec, c + (array_length + i) * size1,
7787 ch, EXPR_VAL);
7791 array_length += nb;
7792 next();
7794 /* only add trailing zero if enough storage (no
7795 warning in this case since it is standard) */
7796 if (n < 0 || array_length < n) {
7797 if (!size_only) {
7798 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
7800 array_length++;
7802 } else {
7803 index = 0;
7804 while (tok != '}') {
7805 decl_designator(type, sec, c, &index, NULL, size_only);
7806 if (n >= 0 && index >= n)
7807 error("index too large");
7808 /* must put zero in holes (note that doing it that way
7809 ensures that it even works with designators) */
7810 if (!size_only && array_length < index) {
7811 init_putz(t1, sec, c + array_length * size1,
7812 (index - array_length) * size1);
7814 index++;
7815 if (index > array_length)
7816 array_length = index;
7817 /* special test for multi dimensional arrays (may not
7818 be strictly correct if designators are used at the
7819 same time) */
7820 if (index >= n && no_oblock)
7821 break;
7822 if (tok == '}')
7823 break;
7824 skip(',');
7827 if (!no_oblock)
7828 skip('}');
7829 /* put zeros at the end */
7830 if (!size_only && n >= 0 && array_length < n) {
7831 init_putz(t1, sec, c + array_length * size1,
7832 (n - array_length) * size1);
7834 /* patch type size if needed */
7835 if (n < 0)
7836 s->c = array_length;
7837 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
7838 (sec || !first || tok == '{')) {
7839 int par_count;
7841 /* NOTE: the previous test is a specific case for automatic
7842 struct/union init */
7843 /* XXX: union needs only one init */
7845 /* XXX: this test is incorrect for local initializers
7846 beginning with ( without {. It would be much more difficult
7847 to do it correctly (ideally, the expression parser should
7848 be used in all cases) */
7849 par_count = 0;
7850 if (tok == '(') {
7851 AttributeDef ad1;
7852 CType type1;
7853 next();
7854 while (tok == '(') {
7855 par_count++;
7856 next();
7858 if (!parse_btype(&type1, &ad1))
7859 expect("cast");
7860 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
7861 if (!is_compatible_types(type, &type1))
7862 error("invalid type for cast");
7863 skip(')');
7865 no_oblock = 1;
7866 if (first || tok == '{') {
7867 skip('{');
7868 no_oblock = 0;
7870 s = type->ref;
7871 f = s->next;
7872 array_length = 0;
7873 index = 0;
7874 n = s->c;
7875 while (tok != '}') {
7876 decl_designator(type, sec, c, NULL, &f, size_only);
7877 index = f->c;
7878 if (!size_only && array_length < index) {
7879 init_putz(type, sec, c + array_length,
7880 index - array_length);
7882 index = index + type_size(&f->type, &align1);
7883 if (index > array_length)
7884 array_length = index;
7885 f = f->next;
7886 if (no_oblock && f == NULL)
7887 break;
7888 if (tok == '}')
7889 break;
7890 skip(',');
7892 /* put zeros at the end */
7893 if (!size_only && array_length < n) {
7894 init_putz(type, sec, c + array_length,
7895 n - array_length);
7897 if (!no_oblock)
7898 skip('}');
7899 while (par_count) {
7900 skip(')');
7901 par_count--;
7903 } else if (tok == '{') {
7904 next();
7905 decl_initializer(type, sec, c, first, size_only);
7906 skip('}');
7907 } else if (size_only) {
7908 /* just skip expression */
7909 parlevel = 0;
7910 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
7911 tok != -1) {
7912 if (tok == '(')
7913 parlevel++;
7914 else if (tok == ')')
7915 parlevel--;
7916 next();
7918 } else {
7919 /* currently, we always use constant expression for globals
7920 (may change for scripting case) */
7921 expr_type = EXPR_CONST;
7922 if (!sec)
7923 expr_type = EXPR_ANY;
7924 init_putv(type, sec, c, 0, expr_type);
7928 /* parse an initializer for type 't' if 'has_init' is non zero, and
7929 allocate space in local or global data space ('r' is either
7930 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
7931 variable 'v' of scope 'scope' is declared before initializers are
7932 parsed. If 'v' is zero, then a reference to the new object is put
7933 in the value stack. If 'has_init' is 2, a special parsing is done
7934 to handle string constants. */
7935 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
7936 int has_init, int v, int scope)
7938 int size, align, addr, data_offset;
7939 int level;
7940 ParseState saved_parse_state;
7941 TokenString init_str;
7942 Section *sec;
7944 size = type_size(type, &align);
7945 /* If unknown size, we must evaluate it before
7946 evaluating initializers because
7947 initializers can generate global data too
7948 (e.g. string pointers or ISOC99 compound
7949 literals). It also simplifies local
7950 initializers handling */
7951 tok_str_new(&init_str);
7952 if (size < 0) {
7953 if (!has_init)
7954 error("unknown type size");
7955 /* get all init string */
7956 if (has_init == 2) {
7957 /* only get strings */
7958 while (tok == TOK_STR || tok == TOK_LSTR) {
7959 tok_str_add_tok(&init_str);
7960 next();
7962 } else {
7963 level = 0;
7964 while (level > 0 || (tok != ',' && tok != ';')) {
7965 if (tok < 0)
7966 error("unexpected end of file in initializer");
7967 tok_str_add_tok(&init_str);
7968 if (tok == '{')
7969 level++;
7970 else if (tok == '}') {
7971 if (level == 0)
7972 break;
7973 level--;
7975 next();
7978 tok_str_add(&init_str, -1);
7979 tok_str_add(&init_str, 0);
7981 /* compute size */
7982 save_parse_state(&saved_parse_state);
7984 macro_ptr = init_str.str;
7985 next();
7986 decl_initializer(type, NULL, 0, 1, 1);
7987 /* prepare second initializer parsing */
7988 macro_ptr = init_str.str;
7989 next();
7991 /* if still unknown size, error */
7992 size = type_size(type, &align);
7993 if (size < 0)
7994 error("unknown type size");
7996 /* take into account specified alignment if bigger */
7997 if (ad->aligned > align)
7998 align = ad->aligned;
7999 if ((r & VT_VALMASK) == VT_LOCAL) {
8000 sec = NULL;
8001 if (do_bounds_check && (type->t & VT_ARRAY))
8002 loc--;
8003 loc = (loc - size) & -align;
8004 addr = loc;
8005 /* handles bounds */
8006 /* XXX: currently, since we do only one pass, we cannot track
8007 '&' operators, so we add only arrays */
8008 if (do_bounds_check && (type->t & VT_ARRAY)) {
8009 unsigned long *bounds_ptr;
8010 /* add padding between regions */
8011 loc--;
8012 /* then add local bound info */
8013 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8014 bounds_ptr[0] = addr;
8015 bounds_ptr[1] = size;
8017 if (v) {
8018 /* local variable */
8019 sym_push(v, type, r, addr);
8020 } else {
8021 /* push local reference */
8022 vset(type, r, addr);
8024 } else {
8025 Sym *sym;
8027 sym = NULL;
8028 if (v && scope == VT_CONST) {
8029 /* see if the symbol was already defined */
8030 sym = sym_find(v);
8031 if (sym) {
8032 if (!is_compatible_types(&sym->type, type))
8033 error("incompatible types for redefinition of '%s'",
8034 get_tok_str(v, NULL));
8035 if (sym->type.t & VT_EXTERN) {
8036 /* if the variable is extern, it was not allocated */
8037 sym->type.t &= ~VT_EXTERN;
8038 } else {
8039 /* we accept several definitions of the same
8040 global variable. this is tricky, because we
8041 must play with the SHN_COMMON type of the symbol */
8042 /* XXX: should check if the variable was already
8043 initialized. It is incorrect to initialized it
8044 twice */
8045 /* no init data, we won't add more to the symbol */
8046 if (!has_init)
8047 goto no_alloc;
8052 /* allocate symbol in corresponding section */
8053 sec = ad->section;
8054 if (!sec) {
8055 if (has_init)
8056 sec = data_section;
8058 if (sec) {
8059 data_offset = sec->data_offset;
8060 data_offset = (data_offset + align - 1) & -align;
8061 addr = data_offset;
8062 /* very important to increment global pointer at this time
8063 because initializers themselves can create new initializers */
8064 data_offset += size;
8065 /* add padding if bound check */
8066 if (do_bounds_check)
8067 data_offset++;
8068 sec->data_offset = data_offset;
8069 /* allocate section space to put the data */
8070 if (sec->sh_type != SHT_NOBITS &&
8071 data_offset > sec->data_allocated)
8072 section_realloc(sec, data_offset);
8073 } else {
8074 addr = 0; /* avoid warning */
8077 if (v) {
8078 if (scope == VT_CONST) {
8079 if (!sym)
8080 goto do_def;
8081 } else {
8082 do_def:
8083 sym = sym_push(v, type, r | VT_SYM, 0);
8085 /* update symbol definition */
8086 if (sec) {
8087 put_extern_sym(sym, sec, addr, size);
8088 } else {
8089 Elf32_Sym *esym;
8090 /* put a common area */
8091 put_extern_sym(sym, NULL, align, size);
8092 /* XXX: find a nicer way */
8093 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8094 esym->st_shndx = SHN_COMMON;
8096 } else {
8097 CValue cval;
8099 /* push global reference */
8100 sym = get_sym_ref(type, sec, addr, size);
8101 cval.ul = 0;
8102 vsetc(type, VT_CONST | VT_SYM, &cval);
8103 vtop->sym = sym;
8106 /* handles bounds now because the symbol must be defined
8107 before for the relocation */
8108 if (do_bounds_check) {
8109 unsigned long *bounds_ptr;
8111 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8112 /* then add global bound info */
8113 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8114 bounds_ptr[0] = 0; /* relocated */
8115 bounds_ptr[1] = size;
8118 if (has_init) {
8119 decl_initializer(type, sec, addr, 1, 0);
8120 /* restore parse state if needed */
8121 if (init_str.str) {
8122 tok_str_free(init_str.str);
8123 restore_parse_state(&saved_parse_state);
8126 no_alloc: ;
8129 void put_func_debug(Sym *sym)
8131 char buf[512];
8133 /* stabs info */
8134 /* XXX: we put here a dummy type */
8135 snprintf(buf, sizeof(buf), "%s:%c1",
8136 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8137 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8138 cur_text_section, sym->c);
8139 last_ind = 0;
8140 last_line_num = 0;
8143 /* not finished : try to put some local vars in registers */
8144 //#define CONFIG_REG_VARS
8146 #ifdef CONFIG_REG_VARS
8147 void add_var_ref(int t)
8149 printf("%s:%d: &%s\n",
8150 file->filename, file->line_num,
8151 get_tok_str(t, NULL));
8154 /* first pass on a function with heuristic to extract variable usage
8155 and pointer references to local variables for register allocation */
8156 void analyse_function(void)
8158 int level, t;
8160 for(;;) {
8161 if (tok == -1)
8162 break;
8163 /* any symbol coming after '&' is considered as being a
8164 variable whose reference is taken. It is highly unaccurate
8165 but it is difficult to do better without a complete parse */
8166 if (tok == '&') {
8167 next();
8168 /* if '& number', then no need to examine next tokens */
8169 if (tok == TOK_CINT ||
8170 tok == TOK_CUINT ||
8171 tok == TOK_CLLONG ||
8172 tok == TOK_CULLONG) {
8173 continue;
8174 } else if (tok >= TOK_UIDENT) {
8175 /* if '& ident [' or '& ident ->', then ident address
8176 is not needed */
8177 t = tok;
8178 next();
8179 if (tok != '[' && tok != TOK_ARROW)
8180 add_var_ref(t);
8181 } else {
8182 level = 0;
8183 while (tok != '}' && tok != ';' &&
8184 !((tok == ',' || tok == ')') && level == 0)) {
8185 if (tok >= TOK_UIDENT) {
8186 add_var_ref(tok);
8187 } else if (tok == '(') {
8188 level++;
8189 } else if (tok == ')') {
8190 level--;
8192 next();
8195 } else {
8196 next();
8200 #endif
8202 /* parse an old style function declaration list */
8203 /* XXX: check multiple parameter */
8204 static void func_decl_list(Sym *func_sym)
8206 AttributeDef ad;
8207 int v;
8208 Sym *s;
8209 CType btype, type;
8211 /* parse each declaration */
8212 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8213 if (!parse_btype(&btype, &ad))
8214 expect("declaration list");
8215 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8216 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8217 tok == ';') {
8218 /* we accept no variable after */
8219 } else {
8220 for(;;) {
8221 type = btype;
8222 type_decl(&type, &ad, &v, TYPE_DIRECT);
8223 /* find parameter in function parameter list */
8224 s = func_sym->next;
8225 while (s != NULL) {
8226 if ((s->v & ~SYM_FIELD) == v)
8227 goto found;
8228 s = s->next;
8230 error("declaration for parameter '%s' but no such parameter",
8231 get_tok_str(v, NULL));
8232 found:
8233 /* check that no storage specifier except 'register' was given */
8234 if (type.t & VT_STORAGE)
8235 error("storage class specified for '%s'", get_tok_str(v, NULL));
8236 convert_parameter_type(&type);
8237 /* we can add the type (NOTE: it could be local to the function) */
8238 s->type = type;
8239 /* accept other parameters */
8240 if (tok == ',')
8241 next();
8242 else
8243 break;
8246 skip(';');
8250 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8251 static void decl(int l)
8253 int v, has_init, r;
8254 CType type, btype;
8255 Sym *sym;
8256 AttributeDef ad;
8258 while (1) {
8259 if (!parse_btype(&btype, &ad)) {
8260 /* skip redundant ';' */
8261 /* XXX: find more elegant solution */
8262 if (tok == ';') {
8263 next();
8264 continue;
8266 /* special test for old K&R protos without explicit int
8267 type. Only accepted when defining global data */
8268 if (l == VT_LOCAL || tok < TOK_DEFINE)
8269 break;
8270 btype.t = VT_INT;
8272 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8273 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8274 tok == ';') {
8275 /* we accept no variable after */
8276 next();
8277 continue;
8279 while (1) { /* iterate thru each declaration */
8280 type = btype;
8281 type_decl(&type, &ad, &v, TYPE_DIRECT);
8282 #if 0
8284 char buf[500];
8285 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8286 printf("type = '%s'\n", buf);
8288 #endif
8289 if ((type.t & VT_BTYPE) == VT_FUNC) {
8290 /* if old style function prototype, we accept a
8291 declaration list */
8292 sym = type.ref;
8293 if (sym->c == FUNC_OLD)
8294 func_decl_list(sym);
8297 if (tok == '{') {
8298 #ifdef CONFIG_REG_VARS
8299 TokenString func_str;
8300 ParseState saved_parse_state;
8301 int block_level;
8302 #endif
8304 if (l == VT_LOCAL)
8305 error("cannot use local functions");
8306 if (!(type.t & VT_FUNC))
8307 expect("function definition");
8308 /* XXX: cannot do better now: convert extern line to static inline */
8309 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8310 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8312 #ifdef CONFIG_REG_VARS
8313 /* parse all function code and record it */
8315 tok_str_new(&func_str);
8317 block_level = 0;
8318 for(;;) {
8319 int t;
8320 if (tok == -1)
8321 error("unexpected end of file");
8322 tok_str_add_tok(&func_str);
8323 t = tok;
8324 next();
8325 if (t == '{') {
8326 block_level++;
8327 } else if (t == '}') {
8328 block_level--;
8329 if (block_level == 0)
8330 break;
8333 tok_str_add(&func_str, -1);
8334 tok_str_add(&func_str, 0);
8336 save_parse_state(&saved_parse_state);
8338 macro_ptr = func_str.str;
8339 next();
8340 analyse_function();
8341 #endif
8343 /* compute text section */
8344 cur_text_section = ad.section;
8345 if (!cur_text_section)
8346 cur_text_section = text_section;
8347 ind = cur_text_section->data_offset;
8348 funcname = get_tok_str(v, NULL);
8349 sym = sym_find(v);
8350 if (sym) {
8351 /* if symbol is already defined, then put complete type */
8352 sym->type = type;
8353 } else {
8354 /* put function symbol */
8355 sym = global_identifier_push(v, type.t, 0);
8356 sym->type.ref = type.ref;
8358 /* NOTE: we patch the symbol size later */
8359 put_extern_sym(sym, cur_text_section, ind, 0);
8360 func_ind = ind;
8361 sym->r = VT_SYM | VT_CONST;
8362 /* put debug symbol */
8363 if (do_debug)
8364 put_func_debug(sym);
8365 /* push a dummy symbol to enable local sym storage */
8366 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8367 gfunc_prolog(&type);
8368 loc = 0;
8369 rsym = 0;
8370 #ifdef CONFIG_REG_VARS
8371 macro_ptr = func_str.str;
8372 next();
8373 #endif
8374 block(NULL, NULL, NULL, NULL, 0, 0);
8375 gsym(rsym);
8376 gfunc_epilog();
8377 cur_text_section->data_offset = ind;
8378 label_pop(&global_label_stack, NULL);
8379 sym_pop(&local_stack, NULL); /* reset local stack */
8380 /* end of function */
8381 /* patch symbol size */
8382 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8383 ind - func_ind;
8384 if (do_debug) {
8385 put_stabn(N_FUN, 0, 0, ind - func_ind);
8387 funcname = ""; /* for safety */
8388 func_vt.t = VT_VOID; /* for safety */
8389 ind = 0; /* for safety */
8391 #ifdef CONFIG_REG_VARS
8392 tok_str_free(func_str.str);
8393 restore_parse_state(&saved_parse_state);
8394 #endif
8395 break;
8396 } else {
8397 if (btype.t & VT_TYPEDEF) {
8398 /* save typedefed type */
8399 /* XXX: test storage specifiers ? */
8400 sym = sym_push(v, &type, 0, 0);
8401 sym->type.t |= VT_TYPEDEF;
8402 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8403 /* external function definition */
8404 external_sym(v, &type, 0);
8405 } else {
8406 /* not lvalue if array */
8407 r = 0;
8408 if (!(type.t & VT_ARRAY))
8409 r |= lvalue_type(type.t);
8410 has_init = (tok == '=');
8411 if ((btype.t & VT_EXTERN) ||
8412 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8413 !has_init && l == VT_CONST && type.ref->c < 0)) {
8414 /* external variable */
8415 /* NOTE: as GCC, uninitialized global static
8416 arrays of null size are considered as
8417 extern */
8418 external_sym(v, &type, r);
8419 } else {
8420 if (type.t & VT_STATIC)
8421 r |= VT_CONST;
8422 else
8423 r |= l;
8424 if (has_init)
8425 next();
8426 decl_initializer_alloc(&type, &ad, r,
8427 has_init, v, l);
8430 if (tok != ',') {
8431 skip(';');
8432 break;
8434 next();
8440 /* better than nothing, but needs extension to handle '-E' option
8441 correctly too */
8442 static void preprocess_init(TCCState *s1)
8444 s1->include_stack_ptr = s1->include_stack;
8445 /* XXX: move that before to avoid having to initialize
8446 file->ifdef_stack_ptr ? */
8447 s1->ifdef_stack_ptr = s1->ifdef_stack;
8448 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8450 /* XXX: not ANSI compliant: bound checking says error */
8451 vtop = vstack - 1;
8454 /* compile the C file opened in 'file'. Return non zero if errors. */
8455 static int tcc_compile(TCCState *s1)
8457 Sym *define_start;
8458 char buf[512];
8459 volatile int section_sym;
8461 #ifdef INC_DEBUG
8462 printf("%s: **** new file\n", file->filename);
8463 #endif
8464 preprocess_init(s1);
8466 funcname = "";
8467 anon_sym = SYM_FIRST_ANOM;
8469 /* file info: full path + filename */
8470 section_sym = 0; /* avoid warning */
8471 if (do_debug) {
8472 section_sym = put_elf_sym(symtab_section, 0, 0,
8473 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8474 text_section->sh_num, NULL);
8475 getcwd(buf, sizeof(buf));
8476 pstrcat(buf, sizeof(buf), "/");
8477 put_stabs_r(buf, N_SO, 0, 0,
8478 text_section->data_offset, text_section, section_sym);
8479 put_stabs_r(file->filename, N_SO, 0, 0,
8480 text_section->data_offset, text_section, section_sym);
8482 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8483 symbols can be safely used */
8484 put_elf_sym(symtab_section, 0, 0,
8485 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8486 SHN_ABS, file->filename);
8488 /* define some often used types */
8489 int_type.t = VT_INT;
8491 char_pointer_type.t = VT_BYTE;
8492 mk_pointer(&char_pointer_type);
8494 func_old_type.t = VT_FUNC;
8495 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8497 #if 0
8498 /* define 'void *alloca(unsigned int)' builtin function */
8500 Sym *s1;
8502 p = anon_sym++;
8503 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8504 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8505 s1->next = NULL;
8506 sym->next = s1;
8507 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8509 #endif
8511 define_start = define_stack;
8513 if (setjmp(s1->error_jmp_buf) == 0) {
8514 s1->nb_errors = 0;
8515 s1->error_set_jmp_enabled = 1;
8517 ch = file->buf_ptr[0];
8518 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8519 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8520 next();
8521 decl(VT_CONST);
8522 if (tok != -1)
8523 expect("declaration");
8525 /* end of translation unit info */
8526 if (do_debug) {
8527 put_stabs_r(NULL, N_SO, 0, 0,
8528 text_section->data_offset, text_section, section_sym);
8531 s1->error_set_jmp_enabled = 0;
8533 /* reset define stack, but leave -Dsymbols (may be incorrect if
8534 they are undefined) */
8535 free_defines(define_start);
8537 sym_pop(&global_stack, NULL);
8539 return s1->nb_errors != 0 ? -1 : 0;
8542 #ifdef LIBTCC
8543 int tcc_compile_string(TCCState *s, const char *str)
8545 BufferedFile bf1, *bf = &bf1;
8546 int ret, len;
8547 char *buf;
8549 /* init file structure */
8550 bf->fd = -1;
8551 /* XXX: avoid copying */
8552 len = strlen(str);
8553 buf = tcc_malloc(len + 1);
8554 if (!buf)
8555 return -1;
8556 memcpy(buf, str, len);
8557 buf[len] = CH_EOB;
8558 bf->buf_ptr = buf;
8559 bf->buf_end = buf + len;
8560 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8561 bf->line_num = 1;
8562 file = bf;
8564 ret = tcc_compile(s);
8566 tcc_free(buf);
8568 /* currently, no need to close */
8569 return ret;
8571 #endif
8573 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8574 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8576 BufferedFile bf1, *bf = &bf1;
8578 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8579 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8580 /* default value */
8581 if (!value)
8582 value = "1";
8583 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8585 /* init file structure */
8586 bf->fd = -1;
8587 bf->buf_ptr = bf->buffer;
8588 bf->buf_end = bf->buffer + strlen(bf->buffer);
8589 *bf->buf_end = CH_EOB;
8590 bf->filename[0] = '\0';
8591 bf->line_num = 1;
8592 file = bf;
8594 s1->include_stack_ptr = s1->include_stack;
8596 /* parse with define parser */
8597 ch = file->buf_ptr[0];
8598 next_nomacro();
8599 parse_define();
8600 file = NULL;
8603 /* undefine a preprocessor symbol */
8604 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8606 TokenSym *ts;
8607 Sym *s;
8608 ts = tok_alloc(sym, strlen(sym));
8609 s = define_find(ts->tok);
8610 /* undefine symbol by putting an invalid name */
8611 if (s)
8612 define_undef(s);
8615 #ifdef CONFIG_TCC_ASM
8617 #include "i386-asm.c"
8618 #include "tccasm.c"
8620 #else
8621 static void asm_instr(void)
8623 error("inline asm() not supported");
8625 #endif
8627 #include "tccelf.c"
8629 /* print the position in the source file of PC value 'pc' by reading
8630 the stabs debug information */
8631 static void rt_printline(unsigned long wanted_pc)
8633 Stab_Sym *sym, *sym_end;
8634 char func_name[128], last_func_name[128];
8635 unsigned long func_addr, last_pc, pc;
8636 const char *incl_files[INCLUDE_STACK_SIZE];
8637 int incl_index, len, last_line_num, i;
8638 const char *str, *p;
8640 fprintf(stderr, "0x%08lx:", wanted_pc);
8642 func_name[0] = '\0';
8643 func_addr = 0;
8644 incl_index = 0;
8645 last_func_name[0] = '\0';
8646 last_pc = 0xffffffff;
8647 last_line_num = 1;
8648 sym = (Stab_Sym *)stab_section->data + 1;
8649 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
8650 while (sym < sym_end) {
8651 switch(sym->n_type) {
8652 /* function start or end */
8653 case N_FUN:
8654 if (sym->n_strx == 0) {
8655 /* we test if between last line and end of function */
8656 pc = sym->n_value + func_addr;
8657 if (wanted_pc >= last_pc && wanted_pc < pc)
8658 goto found;
8659 func_name[0] = '\0';
8660 func_addr = 0;
8661 } else {
8662 str = stabstr_section->data + sym->n_strx;
8663 p = strchr(str, ':');
8664 if (!p) {
8665 pstrcpy(func_name, sizeof(func_name), str);
8666 } else {
8667 len = p - str;
8668 if (len > sizeof(func_name) - 1)
8669 len = sizeof(func_name) - 1;
8670 memcpy(func_name, str, len);
8671 func_name[len] = '\0';
8673 func_addr = sym->n_value;
8675 break;
8676 /* line number info */
8677 case N_SLINE:
8678 pc = sym->n_value + func_addr;
8679 if (wanted_pc >= last_pc && wanted_pc < pc)
8680 goto found;
8681 last_pc = pc;
8682 last_line_num = sym->n_desc;
8683 /* XXX: slow! */
8684 strcpy(last_func_name, func_name);
8685 break;
8686 /* include files */
8687 case N_BINCL:
8688 str = stabstr_section->data + sym->n_strx;
8689 add_incl:
8690 if (incl_index < INCLUDE_STACK_SIZE) {
8691 incl_files[incl_index++] = str;
8693 break;
8694 case N_EINCL:
8695 if (incl_index > 1)
8696 incl_index--;
8697 break;
8698 case N_SO:
8699 if (sym->n_strx == 0) {
8700 incl_index = 0; /* end of translation unit */
8701 } else {
8702 str = stabstr_section->data + sym->n_strx;
8703 /* do not add path */
8704 len = strlen(str);
8705 if (len > 0 && str[len - 1] != '/')
8706 goto add_incl;
8708 break;
8710 sym++;
8713 /* second pass: we try symtab symbols (no line number info) */
8714 incl_index = 0;
8716 Elf32_Sym *sym, *sym_end;
8717 int type;
8719 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
8720 for(sym = (Elf32_Sym *)symtab_section->data + 1;
8721 sym < sym_end;
8722 sym++) {
8723 type = ELF32_ST_TYPE(sym->st_info);
8724 if (type == STT_FUNC) {
8725 if (wanted_pc >= sym->st_value &&
8726 wanted_pc < sym->st_value + sym->st_size) {
8727 pstrcpy(last_func_name, sizeof(last_func_name),
8728 strtab_section->data + sym->st_name);
8729 goto found;
8734 /* did not find any info: */
8735 fprintf(stderr, " ???\n");
8736 return;
8737 found:
8738 if (last_func_name[0] != '\0') {
8739 fprintf(stderr, " %s()", last_func_name);
8741 if (incl_index > 0) {
8742 fprintf(stderr, " (%s:%d",
8743 incl_files[incl_index - 1], last_line_num);
8744 for(i = incl_index - 2; i >= 0; i--)
8745 fprintf(stderr, ", included from %s", incl_files[i]);
8746 fprintf(stderr, ")");
8748 fprintf(stderr, "\n");
8751 #ifndef WIN32
8753 #ifdef __i386__
8755 /* fix for glibc 2.1 */
8756 #ifndef REG_EIP
8757 #define REG_EIP EIP
8758 #define REG_EBP EBP
8759 #endif
8761 /* return the PC at frame level 'level'. Return non zero if not found */
8762 static int rt_get_caller_pc(unsigned long *paddr,
8763 ucontext_t *uc, int level)
8765 unsigned long fp;
8766 int i;
8768 if (level == 0) {
8769 #ifdef __FreeBSD__
8770 *paddr = uc->uc_mcontext.mc_eip;
8771 #else
8772 *paddr = uc->uc_mcontext.gregs[REG_EIP];
8773 #endif
8774 return 0;
8775 } else {
8776 #ifdef __FreeBSD__
8777 fp = uc->uc_mcontext.mc_ebp;
8778 #else
8779 fp = uc->uc_mcontext.gregs[REG_EBP];
8780 #endif
8781 for(i=1;i<level;i++) {
8782 /* XXX: check address validity with program info */
8783 if (fp <= 0x1000 || fp >= 0xc0000000)
8784 return -1;
8785 fp = ((unsigned long *)fp)[0];
8787 *paddr = ((unsigned long *)fp)[1];
8788 return 0;
8791 #else
8792 #error add arch specific rt_get_caller_pc()
8793 #endif
8795 /* emit a run time error at position 'pc' */
8796 void rt_error(ucontext_t *uc, const char *fmt, ...)
8798 va_list ap;
8799 unsigned long pc;
8800 int i;
8802 va_start(ap, fmt);
8803 fprintf(stderr, "Runtime error: ");
8804 vfprintf(stderr, fmt, ap);
8805 fprintf(stderr, "\n");
8806 for(i=0;i<num_callers;i++) {
8807 if (rt_get_caller_pc(&pc, uc, i) < 0)
8808 break;
8809 if (i == 0)
8810 fprintf(stderr, "at ");
8811 else
8812 fprintf(stderr, "by ");
8813 rt_printline(pc);
8815 exit(255);
8816 va_end(ap);
8819 /* signal handler for fatal errors */
8820 static void sig_error(int signum, siginfo_t *siginf, void *puc)
8822 ucontext_t *uc = puc;
8824 switch(signum) {
8825 case SIGFPE:
8826 switch(siginf->si_code) {
8827 case FPE_INTDIV:
8828 case FPE_FLTDIV:
8829 rt_error(uc, "division by zero");
8830 break;
8831 default:
8832 rt_error(uc, "floating point exception");
8833 break;
8835 break;
8836 case SIGBUS:
8837 case SIGSEGV:
8838 if (rt_bound_error_msg && *rt_bound_error_msg)
8839 rt_error(uc, *rt_bound_error_msg);
8840 else
8841 rt_error(uc, "dereferencing invalid pointer");
8842 break;
8843 case SIGILL:
8844 rt_error(uc, "illegal instruction");
8845 break;
8846 case SIGABRT:
8847 rt_error(uc, "abort() called");
8848 break;
8849 default:
8850 rt_error(uc, "caught signal %d", signum);
8851 break;
8853 exit(255);
8855 #endif
8857 /* do all relocations (needed before using tcc_get_symbol()) */
8858 int tcc_relocate(TCCState *s1)
8860 Section *s;
8861 int i;
8863 s1->nb_errors = 0;
8865 tcc_add_runtime(s1);
8867 relocate_common_syms();
8869 /* compute relocation address : section are relocated in place. We
8870 also alloc the bss space */
8871 for(i = 1; i < s1->nb_sections; i++) {
8872 s = s1->sections[i];
8873 if (s->sh_flags & SHF_ALLOC) {
8874 if (s->sh_type == SHT_NOBITS)
8875 s->data = tcc_mallocz(s->data_offset);
8876 s->sh_addr = (unsigned long)s->data;
8880 relocate_syms(s1, 1);
8882 if (s1->nb_errors != 0)
8883 return -1;
8885 /* relocate each section */
8886 for(i = 1; i < s1->nb_sections; i++) {
8887 s = s1->sections[i];
8888 if (s->reloc)
8889 relocate_section(s1, s);
8891 return 0;
8894 /* launch the compiled program with the given arguments */
8895 int tcc_run(TCCState *s1, int argc, char **argv)
8897 int (*prog_main)(int, char **);
8899 if (tcc_relocate(s1) < 0)
8900 return -1;
8902 prog_main = tcc_get_symbol(s1, "main");
8904 if (do_debug) {
8905 #ifdef WIN32
8906 error("debug mode currently not available for Windows");
8907 #else
8908 struct sigaction sigact;
8909 /* install TCC signal handlers to print debug info on fatal
8910 runtime errors */
8911 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
8912 sigact.sa_sigaction = sig_error;
8913 sigemptyset(&sigact.sa_mask);
8914 sigaction(SIGFPE, &sigact, NULL);
8915 sigaction(SIGILL, &sigact, NULL);
8916 sigaction(SIGSEGV, &sigact, NULL);
8917 sigaction(SIGBUS, &sigact, NULL);
8918 sigaction(SIGABRT, &sigact, NULL);
8919 #endif
8922 #ifdef CONFIG_TCC_BCHECK
8923 if (do_bounds_check) {
8924 void (*bound_init)(void);
8926 /* set error function */
8927 rt_bound_error_msg = (void *)tcc_get_symbol(s1, "__bound_error_msg");
8929 /* XXX: use .init section so that it also work in binary ? */
8930 bound_init = (void *)tcc_get_symbol(s1, "__bound_init");
8931 bound_init();
8933 #endif
8934 return (*prog_main)(argc, argv);
8937 TCCState *tcc_new(void)
8939 const char *p, *r;
8940 TCCState *s;
8941 TokenSym *ts;
8942 int i, c;
8944 s = tcc_mallocz(sizeof(TCCState));
8945 if (!s)
8946 return NULL;
8947 tcc_state = s;
8948 s->output_type = TCC_OUTPUT_MEMORY;
8950 /* init isid table */
8951 for(i=0;i<256;i++)
8952 isidnum_table[i] = isid(i) || isnum(i);
8954 /* add all tokens */
8955 table_ident = NULL;
8956 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
8958 tok_ident = TOK_IDENT;
8959 p = tcc_keywords;
8960 while (*p) {
8961 r = p;
8962 for(;;) {
8963 c = *r++;
8964 if (c == '\0')
8965 break;
8967 ts = tok_alloc(p, r - p - 1);
8968 p = r;
8971 /* we add dummy defines for some special macros to speed up tests
8972 and to have working defined() */
8973 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
8974 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
8975 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
8976 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
8978 /* standard defines */
8979 tcc_define_symbol(s, "__STDC__", NULL);
8980 #if defined(TCC_TARGET_I386)
8981 tcc_define_symbol(s, "__i386__", NULL);
8982 #endif
8983 #if defined(linux)
8984 tcc_define_symbol(s, "__linux__", NULL);
8985 tcc_define_symbol(s, "linux", NULL);
8986 #endif
8987 /* tiny C specific defines */
8988 tcc_define_symbol(s, "__TINYC__", NULL);
8990 /* tiny C & gcc defines */
8991 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
8992 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
8993 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
8995 /* default library paths */
8996 tcc_add_library_path(s, "/usr/local/lib");
8997 tcc_add_library_path(s, "/usr/lib");
8998 tcc_add_library_path(s, "/lib");
9000 /* no section zero */
9001 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9003 /* create standard sections */
9004 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9005 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9006 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9008 /* symbols are always generated for linking stage */
9009 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9010 ".strtab",
9011 ".hashtab", SHF_PRIVATE);
9012 strtab_section = symtab_section->link;
9014 /* private symbol table for dynamic symbols */
9015 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9016 ".dynstrtab",
9017 ".dynhashtab", SHF_PRIVATE);
9018 return s;
9021 void tcc_delete(TCCState *s1)
9023 int i, n;
9025 /* free -D defines */
9026 free_defines(NULL);
9028 /* free tokens */
9029 n = tok_ident - TOK_IDENT;
9030 for(i = 0; i < n; i++)
9031 tcc_free(table_ident[i]);
9032 tcc_free(table_ident);
9034 /* free all sections */
9036 free_section(symtab_section->hash);
9038 free_section(s1->dynsymtab_section->hash);
9039 free_section(s1->dynsymtab_section->link);
9040 free_section(s1->dynsymtab_section);
9042 for(i = 1; i < s1->nb_sections; i++)
9043 free_section(s1->sections[i]);
9044 tcc_free(s1->sections);
9046 /* free loaded dlls array */
9047 for(i = 0; i < s1->nb_loaded_dlls; i++)
9048 tcc_free(s1->loaded_dlls[i]);
9049 tcc_free(s1->loaded_dlls);
9051 /* library paths */
9052 for(i = 0; i < s1->nb_library_paths; i++)
9053 tcc_free(s1->library_paths[i]);
9054 tcc_free(s1->library_paths);
9056 /* cached includes */
9057 for(i = 0; i < s1->nb_cached_includes; i++)
9058 tcc_free(s1->cached_includes[i]);
9059 tcc_free(s1->cached_includes);
9061 for(i = 0; i < s1->nb_include_paths; i++)
9062 tcc_free(s1->include_paths[i]);
9063 tcc_free(s1->include_paths);
9065 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9066 tcc_free(s1->sysinclude_paths[i]);
9067 tcc_free(s1->sysinclude_paths);
9069 tcc_free(s1);
9072 int tcc_add_include_path(TCCState *s1, const char *pathname)
9074 char *pathname1;
9076 pathname1 = tcc_strdup(pathname);
9077 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9078 return 0;
9081 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9083 char *pathname1;
9085 pathname1 = tcc_strdup(pathname);
9086 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9087 return 0;
9090 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9092 const char *ext, *filename1;
9093 Elf32_Ehdr ehdr;
9094 int fd, ret;
9095 BufferedFile *saved_file;
9097 /* find source file type with extension */
9098 filename1 = strrchr(filename, '/');
9099 if (filename1)
9100 filename1++;
9101 else
9102 filename1 = filename;
9103 ext = strrchr(filename1, '.');
9104 if (ext)
9105 ext++;
9107 /* open the file */
9108 saved_file = file;
9109 file = tcc_open(s1, filename);
9110 if (!file) {
9111 if (flags & AFF_PRINT_ERROR) {
9112 error_noabort("file '%s' not found", filename);
9114 ret = -1;
9115 goto fail1;
9118 if (!ext || !strcmp(ext, "c")) {
9119 /* C file assumed */
9120 ret = tcc_compile(s1);
9121 } else
9122 #ifdef CONFIG_TCC_ASM
9123 if (!strcmp(ext, "S")) {
9124 /* preprocessed assembler */
9125 ret = tcc_assemble(s1, 1);
9126 } else if (!strcmp(ext, "s")) {
9127 /* non preprocessed assembler */
9128 ret = tcc_assemble(s1, 0);
9129 } else
9130 #endif
9132 fd = file->fd;
9133 /* assume executable format: auto guess file type */
9134 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
9135 error_noabort("could not read header");
9136 goto fail;
9138 lseek(fd, 0, SEEK_SET);
9140 if (ehdr.e_ident[0] == ELFMAG0 &&
9141 ehdr.e_ident[1] == ELFMAG1 &&
9142 ehdr.e_ident[2] == ELFMAG2 &&
9143 ehdr.e_ident[3] == ELFMAG3) {
9144 file->line_num = 0; /* do not display line number if error */
9145 if (ehdr.e_type == ET_REL) {
9146 ret = tcc_load_object_file(s1, fd, 0);
9147 } else if (ehdr.e_type == ET_DYN) {
9148 ret = tcc_load_dll(s1, fd, filename,
9149 (flags & AFF_REFERENCED_DLL) != 0);
9150 } else {
9151 error_noabort("unrecognized ELF file");
9152 goto fail;
9154 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9155 file->line_num = 0; /* do not display line number if error */
9156 ret = tcc_load_archive(s1, fd);
9157 } else {
9158 /* as GNU ld, consider it is an ld script if not recognized */
9159 ret = tcc_load_ldscript(s1);
9160 if (ret < 0) {
9161 error_noabort("unrecognized file type");
9162 goto fail;
9166 the_end:
9167 tcc_close(file);
9168 fail1:
9169 file = saved_file;
9170 return ret;
9171 fail:
9172 ret = -1;
9173 goto the_end;
9176 int tcc_add_file(TCCState *s, const char *filename)
9178 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9181 int tcc_add_library_path(TCCState *s, const char *pathname)
9183 char *pathname1;
9185 pathname1 = tcc_strdup(pathname);
9186 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9187 return 0;
9190 /* find and load a dll. Return non zero if not found */
9191 /* XXX: add '-rpath' option support ? */
9192 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9194 char buf[1024];
9195 int i;
9197 for(i = 0; i < s->nb_library_paths; i++) {
9198 snprintf(buf, sizeof(buf), "%s/%s",
9199 s->library_paths[i], filename);
9200 if (tcc_add_file_internal(s, buf, flags) == 0)
9201 return 0;
9203 return -1;
9206 /* the library name is the same as the argument of the '-l' option */
9207 int tcc_add_library(TCCState *s, const char *libraryname)
9209 char buf[1024];
9210 int i;
9211 void *h;
9213 /* first we look for the dynamic library if not static linking */
9214 if (!s->static_link) {
9215 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9216 /* if we output to memory, then we simply we dlopen(). */
9217 if (s->output_type == TCC_OUTPUT_MEMORY) {
9218 /* Since the libc is already loaded, we don't need to load it again */
9219 if (!strcmp(libraryname, "c"))
9220 return 0;
9221 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
9222 if (h)
9223 return 0;
9224 } else {
9225 if (tcc_add_dll(s, buf, 0) == 0)
9226 return 0;
9230 /* then we look for the static library */
9231 for(i = 0; i < s->nb_library_paths; i++) {
9232 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9233 s->library_paths[i], libraryname);
9234 if (tcc_add_file_internal(s, buf, 0) == 0)
9235 return 0;
9237 return -1;
9240 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9242 add_elf_sym(symtab_section, val, 0,
9243 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9244 SHN_ABS, name);
9245 return 0;
9248 int tcc_set_output_type(TCCState *s, int output_type)
9250 char buf[1024];
9252 s->output_type = output_type;
9254 if (!s->nostdinc) {
9255 /* default include paths */
9256 /* XXX: reverse order needed if -isystem support */
9257 tcc_add_sysinclude_path(s, "/usr/local/include");
9258 tcc_add_sysinclude_path(s, "/usr/include");
9259 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9260 tcc_add_sysinclude_path(s, buf);
9263 /* if bound checking, then add corresponding sections */
9264 #ifdef CONFIG_TCC_BCHECK
9265 if (do_bounds_check) {
9266 /* define symbol */
9267 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9268 /* create bounds sections */
9269 bounds_section = new_section(s, ".bounds",
9270 SHT_PROGBITS, SHF_ALLOC);
9271 lbounds_section = new_section(s, ".lbounds",
9272 SHT_PROGBITS, SHF_ALLOC);
9274 #endif
9276 /* add debug sections */
9277 if (do_debug) {
9278 /* stab symbols */
9279 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9280 stab_section->sh_entsize = sizeof(Stab_Sym);
9281 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9282 put_elf_str(stabstr_section, "");
9283 stab_section->link = stabstr_section;
9284 /* put first entry */
9285 put_stabs("", 0, 0, 0, 0);
9288 /* add libc crt1/crti objects */
9289 if (output_type == TCC_OUTPUT_EXE ||
9290 output_type == TCC_OUTPUT_DLL) {
9291 if (output_type != TCC_OUTPUT_DLL)
9292 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9293 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9295 return 0;
9298 #if !defined(LIBTCC)
9300 static int64_t getclock_us(void)
9302 #ifdef WIN32
9303 struct _timeb tb;
9304 _ftime(&tb);
9305 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9306 #else
9307 struct timeval tv;
9308 gettimeofday(&tv, NULL);
9309 return tv.tv_sec * 1000000LL + tv.tv_usec;
9310 #endif
9313 void help(void)
9315 printf("tcc version 0.9.16 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
9316 "usage: tcc [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9317 " [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9318 " [--] infile1 [infile2... --] [infile_args...]\n"
9319 "\n"
9320 "General options:\n"
9321 " -c compile only - generate an object file\n"
9322 " -o outfile set output filename\n"
9323 " -- allows multiples input files if no -o option given. Also\n"
9324 " separate input files from runtime arguments\n"
9325 " -Bdir set tcc internal library path\n"
9326 " -bench output compilation statistics\n"
9327 "Preprocessor options:\n"
9328 " -Idir add include path 'dir'\n"
9329 " -Dsym[=val] define 'sym' with value 'val'\n"
9330 " -Usym undefine 'sym'\n"
9331 "Linker options:\n"
9332 " -Ldir add library path 'dir'\n"
9333 " -llib link with dynamic or static library 'lib'\n"
9334 " -shared generate a shared library\n"
9335 " -static static linking\n"
9336 " -r relocatable output\n"
9337 "Debugger options:\n"
9338 " -g generate runtime debug info\n"
9339 #ifdef CONFIG_TCC_BCHECK
9340 " -b compile with built-in memory and bounds checker (implies -g)\n"
9341 #endif
9342 " -bt N show N callers in stack traces\n"
9346 #define TCC_OPTION_HAS_ARG 0x0001
9347 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9349 typedef struct TCCOption {
9350 const char *name;
9351 uint16_t index;
9352 uint16_t flags;
9353 } TCCOption;
9355 enum {
9356 TCC_OPTION_HELP,
9357 TCC_OPTION_MARKER,
9358 TCC_OPTION_I,
9359 TCC_OPTION_D,
9360 TCC_OPTION_U,
9361 TCC_OPTION_L,
9362 TCC_OPTION_B,
9363 TCC_OPTION_l,
9364 TCC_OPTION_bench,
9365 TCC_OPTION_bt,
9366 TCC_OPTION_b,
9367 TCC_OPTION_g,
9368 TCC_OPTION_c,
9369 TCC_OPTION_static,
9370 TCC_OPTION_shared,
9371 TCC_OPTION_o,
9372 TCC_OPTION_r,
9373 TCC_OPTION_W,
9374 TCC_OPTION_O,
9375 TCC_OPTION_m,
9376 TCC_OPTION_f,
9377 TCC_OPTION_nostdinc,
9378 TCC_OPTION_print_search_dirs,
9379 TCC_OPTION_rdynamic,
9382 static const TCCOption tcc_options[] = {
9383 { "h", TCC_OPTION_HELP, 0 },
9384 { "?", TCC_OPTION_HELP, 0 },
9385 { "-", TCC_OPTION_MARKER, 0 },
9386 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9387 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9388 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9389 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9390 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9391 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9392 { "bench", TCC_OPTION_bench, 0 },
9393 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9394 #ifdef CONFIG_TCC_BCHECK
9395 { "b", TCC_OPTION_b, 0 },
9396 #endif
9397 { "g", TCC_OPTION_g, 0 },
9398 { "c", TCC_OPTION_c, 0 },
9399 { "static", TCC_OPTION_static, 0 },
9400 { "shared", TCC_OPTION_shared, 0 },
9401 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9402 { "rdynamic", TCC_OPTION_rdynamic, 0 }, /* currently ignored */
9403 { "r", TCC_OPTION_r, 0 },
9404 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9405 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9406 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9407 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9408 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9409 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9410 { NULL },
9413 int main(int argc, char **argv)
9415 char *r;
9416 int optind, output_type, multiple_files, i, reloc_output;
9417 TCCState *s;
9418 char **files;
9419 int nb_files, nb_libraries, nb_objfiles, dminus, ret;
9420 char objfilename[1024];
9421 int64_t start_time = 0;
9422 const TCCOption *popt;
9423 const char *optarg, *p1, *r1, *outfile;
9424 int print_search_dirs;
9426 s = tcc_new();
9427 output_type = TCC_OUTPUT_MEMORY;
9429 optind = 1;
9430 outfile = NULL;
9431 multiple_files = 0;
9432 dminus = 0;
9433 files = NULL;
9434 nb_files = 0;
9435 nb_libraries = 0;
9436 reloc_output = 0;
9437 print_search_dirs = 0;
9438 while (1) {
9439 if (optind >= argc) {
9440 if (nb_files == 0 && !print_search_dirs)
9441 goto show_help;
9442 else
9443 break;
9445 r = argv[optind++];
9446 if (r[0] != '-') {
9447 /* add a new file */
9448 dynarray_add((void ***)&files, &nb_files, r);
9449 if (!multiple_files) {
9450 optind--;
9451 /* argv[0] will be this file */
9452 break;
9454 } else {
9455 /* find option in table (match only the first chars */
9456 popt = tcc_options;
9457 for(;;) {
9458 p1 = popt->name;
9459 if (p1 == NULL)
9460 error("invalid option -- '%s'", r);
9461 r1 = r + 1;
9462 for(;;) {
9463 if (*p1 == '\0')
9464 goto option_found;
9465 if (*r1 != *p1)
9466 break;
9467 p1++;
9468 r1++;
9470 popt++;
9472 option_found:
9473 if (popt->flags & TCC_OPTION_HAS_ARG) {
9474 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
9475 optarg = r1;
9476 } else {
9477 if (optind >= argc)
9478 error("argument to '%s' is missing", r);
9479 optarg = argv[optind++];
9481 } else {
9482 if (*r1 != '\0')
9483 goto show_help;
9484 optarg = NULL;
9487 switch(popt->index) {
9488 case TCC_OPTION_HELP:
9489 show_help:
9490 help();
9491 return 1;
9492 case TCC_OPTION_MARKER:
9493 /* '--' enables multiple files input and also ends several
9494 file input */
9495 if (dminus && multiple_files) {
9496 optind--; /* argv[0] will be '--' */
9497 goto end_parse;
9499 dminus = 1;
9500 multiple_files = 1;
9501 case TCC_OPTION_I:
9502 if (tcc_add_include_path(s, optarg) < 0)
9503 error("too many include paths");
9504 break;
9505 case TCC_OPTION_D:
9507 char *sym, *value;
9508 sym = (char *)optarg;
9509 value = strchr(sym, '=');
9510 if (value) {
9511 *value = '\0';
9512 value++;
9514 tcc_define_symbol(s, sym, value);
9516 break;
9517 case TCC_OPTION_U:
9518 tcc_undefine_symbol(s, optarg);
9519 break;
9520 case TCC_OPTION_L:
9521 tcc_add_library_path(s, optarg);
9522 break;
9523 case TCC_OPTION_B:
9524 /* set tcc utilities path (mainly for tcc development) */
9525 tcc_lib_path = optarg;
9526 break;
9527 case TCC_OPTION_l:
9528 dynarray_add((void ***)&files, &nb_files, r);
9529 nb_libraries++;
9530 break;
9531 case TCC_OPTION_bench:
9532 do_bench = 1;
9533 break;
9534 case TCC_OPTION_bt:
9535 num_callers = atoi(optarg);
9536 break;
9537 #ifdef CONFIG_TCC_BCHECK
9538 case TCC_OPTION_b:
9539 do_bounds_check = 1;
9540 do_debug = 1;
9541 break;
9542 #endif
9543 case TCC_OPTION_g:
9544 do_debug = 1;
9545 break;
9546 case TCC_OPTION_c:
9547 multiple_files = 1;
9548 output_type = TCC_OUTPUT_OBJ;
9549 break;
9550 case TCC_OPTION_static:
9551 s->static_link = 1;
9552 break;
9553 case TCC_OPTION_shared:
9554 output_type = TCC_OUTPUT_DLL;
9555 break;
9556 case TCC_OPTION_o:
9557 multiple_files = 1;
9558 outfile = optarg;
9559 break;
9560 case TCC_OPTION_r:
9561 /* generate a .o merging several output files */
9562 reloc_output = 1;
9563 output_type = TCC_OUTPUT_OBJ;
9564 break;
9565 case TCC_OPTION_nostdinc:
9566 s->nostdinc = 1;
9567 break;
9568 case TCC_OPTION_print_search_dirs:
9569 print_search_dirs = 1;
9570 break;
9571 default:
9572 break;
9576 end_parse:
9577 if (print_search_dirs) {
9578 /* enough for Linux kernel */
9579 printf("install: %s/\n", tcc_lib_path);
9580 return 0;
9583 nb_objfiles = nb_files - nb_libraries;
9585 /* if outfile provided without other options, we output an
9586 executable */
9587 if (outfile && output_type == TCC_OUTPUT_MEMORY)
9588 output_type = TCC_OUTPUT_EXE;
9590 /* check -c consistency : only single file handled. XXX: checks file type */
9591 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9592 /* accepts only a single input file */
9593 if (nb_objfiles != 1)
9594 error("cannot specify multiple files with -c");
9595 if (nb_libraries != 0)
9596 error("cannot specify libraries with -c");
9599 /* compute default outfile name */
9600 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
9601 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9602 char *ext;
9603 /* add .o extension */
9604 pstrcpy(objfilename, sizeof(objfilename) - 1, files[0]);
9605 ext = strrchr(objfilename, '.');
9606 if (!ext)
9607 goto default_outfile;
9608 strcpy(ext + 1, "o");
9609 } else {
9610 default_outfile:
9611 pstrcpy(objfilename, sizeof(objfilename), "a.out");
9613 outfile = objfilename;
9616 if (do_bench) {
9617 start_time = getclock_us();
9620 tcc_set_output_type(s, output_type);
9622 /* compile or add each files or library */
9623 for(i = 0;i < nb_files; i++) {
9624 const char *filename;
9626 filename = files[i];
9627 if (filename[0] == '-') {
9628 if (tcc_add_library(s, filename + 2) < 0)
9629 error("cannot find %s", filename);
9630 } else {
9631 if (tcc_add_file(s, filename) < 0) {
9632 ret = 1;
9633 goto the_end;
9638 /* free all files */
9639 tcc_free(files);
9641 if (do_bench) {
9642 double total_time;
9643 total_time = (double)(getclock_us() - start_time) / 1000000.0;
9644 if (total_time < 0.001)
9645 total_time = 0.001;
9646 if (total_bytes < 1)
9647 total_bytes = 1;
9648 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
9649 tok_ident - TOK_IDENT, total_lines, total_bytes,
9650 total_time, (int)(total_lines / total_time),
9651 total_bytes / total_time / 1000000.0);
9654 if (s->output_type != TCC_OUTPUT_MEMORY) {
9655 tcc_output_file(s, outfile);
9656 ret = 0;
9657 } else {
9658 ret = tcc_run(s, argc - optind, argv + optind);
9660 the_end:
9661 /* XXX: cannot do it with bound checking because of the malloc hooks */
9662 if (!do_bounds_check)
9663 tcc_delete(s);
9665 #ifdef MEM_DEBUG
9666 if (do_bench) {
9667 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
9669 #endif
9670 return ret;
9673 #endif