configure support
[tinycc.git] / tcc.c
blob19fad0b6bf1f6adf9863205129ed33fc4a91b137
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 "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <math.h>
29 #include <unistd.h>
30 #include <signal.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <setjmp.h>
34 #ifdef WIN32
35 #include <sys/timeb.h>
36 #endif
37 #ifndef WIN32
38 #include <sys/time.h>
39 #include <sys/ucontext.h>
40 #endif
41 #include "elf.h"
42 #include "stab.h"
43 #ifndef CONFIG_TCC_STATIC
44 #include <dlfcn.h>
45 #endif
47 #include "libtcc.h"
49 /* parser debug */
50 //#define PARSE_DEBUG
51 /* preprocessor debug */
52 //#define PP_DEBUG
53 /* include file debug */
54 //#define INC_DEBUG
56 //#define MEM_DEBUG
58 /* assembler debug */
59 //#define ASM_DEBUG
61 /* target selection */
62 //#define TCC_TARGET_I386 /* i386 code generator */
64 /* default target is I386 */
65 #if !defined(TCC_TARGET_I386)
66 #define TCC_TARGET_I386
67 #endif
69 #if !defined(WIN32) && !defined(TCC_UCLIBC)
70 #define CONFIG_TCC_BCHECK /* enable bound checking code */
71 #endif
73 /* define it to include assembler support */
74 #define CONFIG_TCC_ASM
76 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
77 executables or dlls */
78 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
80 #define INCLUDE_STACK_SIZE 32
81 #define IFDEF_STACK_SIZE 64
82 #define VSTACK_SIZE 64
83 #define STRING_MAX_SIZE 1024
85 #define TOK_HASH_SIZE 2048 /* must be a power of two */
86 #define TOK_ALLOC_INCR 512 /* must be a power of two */
87 #define TOK_STR_ALLOC_INCR_BITS 6
88 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
89 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
91 /* token symbol management */
92 typedef struct TokenSym {
93 struct TokenSym *hash_next;
94 struct Sym *sym_define; /* direct pointer to define */
95 struct Sym *sym_label; /* direct pointer to label */
96 struct Sym *sym_struct; /* direct pointer to structure */
97 struct Sym *sym_identifier; /* direct pointer to identifier */
98 int tok; /* token number */
99 int len;
100 char str[1];
101 } TokenSym;
103 typedef struct CString {
104 int size; /* size in bytes */
105 void *data; /* either 'char *' or 'int *' */
106 int size_allocated;
107 void *data_allocated; /* if non NULL, data has been malloced */
108 } CString;
110 /* type definition */
111 typedef struct CType {
112 int t;
113 struct Sym *ref;
114 } CType;
116 /* constant value */
117 typedef union CValue {
118 long double ld;
119 double d;
120 float f;
121 int i;
122 unsigned int ui;
123 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
124 long long ll;
125 unsigned long long ull;
126 struct CString *cstr;
127 void *ptr;
128 int tab[1];
129 } CValue;
131 /* value on stack */
132 typedef struct SValue {
133 CType type; /* type */
134 unsigned short r; /* register + flags */
135 unsigned short r2; /* second register, used for 'long long'
136 type. If not used, set to VT_CONST */
137 CValue c; /* constant, if VT_CONST */
138 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
139 } SValue;
141 /* symbol management */
142 typedef struct Sym {
143 int v; /* symbol token */
144 int r; /* associated register */
145 int c; /* associated number */
146 CType type; /* associated type */
147 struct Sym *next; /* next related symbol */
148 struct Sym *prev; /* prev symbol in stack */
149 struct Sym *prev_tok; /* previous symbol for this token */
150 } Sym;
152 /* section definition */
153 /* XXX: use directly ELF structure for parameters ? */
154 /* special flag to indicate that the section should not be linked to
155 the other ones */
156 #define SHF_PRIVATE 0x80000000
158 typedef struct Section {
159 unsigned long data_offset; /* current data offset */
160 unsigned char *data; /* section data */
161 unsigned long data_allocated; /* used for realloc() handling */
162 int sh_name; /* elf section name (only used during output) */
163 int sh_num; /* elf section number */
164 int sh_type; /* elf section type */
165 int sh_flags; /* elf section flags */
166 int sh_info; /* elf section info */
167 int sh_addralign; /* elf section alignment */
168 int sh_entsize; /* elf entry size */
169 unsigned long sh_size; /* section size (only used during output) */
170 unsigned long sh_addr; /* address at which the section is relocated */
171 unsigned long sh_offset; /* address at which the section is relocated */
172 int nb_hashed_syms; /* used to resize the hash table */
173 struct Section *link; /* link to another section */
174 struct Section *reloc; /* corresponding section for relocation, if any */
175 struct Section *hash; /* hash table for symbols */
176 struct Section *next;
177 char name[64]; /* section name */
178 } Section;
180 typedef struct DLLReference {
181 int level;
182 char name[1];
183 } DLLReference;
185 /* GNUC attribute definition */
186 typedef struct AttributeDef {
187 int aligned;
188 Section *section;
189 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
190 } AttributeDef;
192 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
193 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
194 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
196 /* stored in 'Sym.c' field */
197 #define FUNC_NEW 1 /* ansi function prototype */
198 #define FUNC_OLD 2 /* old function prototype */
199 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
201 /* stored in 'Sym.r' field */
202 #define FUNC_CDECL 0 /* standard c call */
203 #define FUNC_STDCALL 1 /* pascal c call */
205 /* field 'Sym.t' for macros */
206 #define MACRO_OBJ 0 /* object like macro */
207 #define MACRO_FUNC 1 /* function like macro */
209 /* field 'Sym.r' for C labels */
210 #define LABEL_DEFINED 0 /* label is defined */
211 #define LABEL_FORWARD 1 /* label is forward defined */
212 #define LABEL_DECLARED 2 /* label is declared but never used */
214 /* type_decl() types */
215 #define TYPE_ABSTRACT 1 /* type without variable */
216 #define TYPE_DIRECT 2 /* type with variable */
218 #define IO_BUF_SIZE 8192
220 typedef struct BufferedFile {
221 uint8_t *buf_ptr;
222 uint8_t *buf_end;
223 int fd;
224 int line_num; /* current line number - here to simplify code */
225 int ifndef_macro; /* #ifndef macro / #endif search */
226 int ifndef_macro_saved; /* saved ifndef_macro */
227 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
228 char inc_type; /* type of include */
229 char inc_filename[512]; /* filename specified by the user */
230 char filename[1024]; /* current filename - here to simplify code */
231 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
232 } BufferedFile;
234 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
235 #define CH_EOF (-1) /* end of file */
237 /* parsing state (used to save parser state to reparse part of the
238 source several times) */
239 typedef struct ParseState {
240 int *macro_ptr;
241 int line_num;
242 int tok;
243 CValue tokc;
244 } ParseState;
246 /* used to record tokens */
247 typedef struct TokenString {
248 int *str;
249 int len;
250 int allocated_len;
251 int last_line_num;
252 } TokenString;
254 /* include file cache, used to find files faster and also to eliminate
255 inclusion if the include file is protected by #ifndef ... #endif */
256 typedef struct CachedInclude {
257 int ifndef_macro;
258 char type; /* '"' or '>' to give include type */
259 char filename[1]; /* path specified in #include */
260 } CachedInclude;
262 /* parser */
263 static struct BufferedFile *file;
264 static int ch, tok;
265 static CValue tokc;
266 static CString tokcstr; /* current parsed string, if any */
267 /* additional informations about token */
268 static int tok_flags;
269 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
270 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
271 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
273 static int *macro_ptr, *macro_ptr_allocated;
274 static int *unget_saved_macro_ptr;
275 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
276 static int unget_buffer_enabled;
277 static int parse_flags;
278 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
279 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
280 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
281 token. line feed is also
282 returned at eof */
284 static Section *text_section, *data_section, *bss_section; /* predefined sections */
285 static Section *cur_text_section; /* current section where function code is
286 generated */
287 /* bound check related sections */
288 static Section *bounds_section; /* contains global data bound description */
289 static Section *lbounds_section; /* contains local data bound description */
290 /* symbol sections */
291 static Section *symtab_section, *strtab_section;
293 /* debug sections */
294 static Section *stab_section, *stabstr_section;
296 /* loc : local variable index
297 ind : output code index
298 rsym: return symbol
299 anon_sym: anonymous symbol index
301 static int rsym, anon_sym, ind, loc;
302 /* expression generation modifiers */
303 static int const_wanted; /* true if constant wanted */
304 static int nocode_wanted; /* true if no code generation wanted for an expression */
305 static int global_expr; /* true if compound literals must be allocated
306 globally (used during initializers parsing */
307 static CType func_vt; /* current function return type (used by return
308 instruction) */
309 static int func_vc;
310 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
311 static int tok_ident;
312 static TokenSym **table_ident;
313 static TokenSym *hash_ident[TOK_HASH_SIZE];
314 static char token_buf[STRING_MAX_SIZE + 1];
315 static char *funcname;
316 static Sym *global_stack, *local_stack;
317 static Sym *define_stack;
318 static Sym *global_label_stack, *local_label_stack;
320 static SValue vstack[VSTACK_SIZE], *vtop;
321 /* some predefined types */
322 static CType char_pointer_type, func_old_type, int_type;
323 /* true if isid(c) || isnum(c) */
324 static unsigned char isidnum_table[256];
326 /* compile with debug symbol (and use them if error during execution) */
327 static int do_debug = 0;
329 /* compile with built-in memory and bounds checker */
330 static int do_bounds_check = 0;
332 /* display benchmark infos */
333 #if !defined(LIBTCC)
334 static int do_bench = 0;
335 #endif
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_LIBDIR "/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 just the EOB case, but not stray */
1742 #define PEEKC_EOB(c, p)\
1744 p++;\
1745 c = *p;\
1746 if (c == '\\') {\
1747 file->buf_ptr = p;\
1748 c = handle_eob();\
1749 p = file->buf_ptr;\
1753 /* handle the complicated stray case */
1754 #define PEEKC(c, p)\
1756 p++;\
1757 c = *p;\
1758 if (c == '\\') {\
1759 c = handle_stray1(p);\
1760 p = file->buf_ptr;\
1764 /* input with '\[\r]\n' handling. Note that this function cannot
1765 handle other characters after '\', so you cannot call it inside
1766 strings or comments */
1767 static void minp(void)
1769 inp();
1770 if (ch == '\\')
1771 handle_stray();
1775 /* single line C++ comments */
1776 static uint8_t *parse_line_comment(uint8_t *p)
1778 int c;
1780 p++;
1781 for(;;) {
1782 c = *p;
1783 if (c == '\n' || c == CH_EOF) {
1784 break;
1785 } else if (c == '\\') {
1786 PEEKC_EOB(c, p);
1787 if (c == '\n') {
1788 file->line_num++;
1789 PEEKC_EOB(c, p);
1790 } else if (c == '\r') {
1791 PEEKC_EOB(c, p);
1792 if (c == '\n') {
1793 file->line_num++;
1794 PEEKC_EOB(c, p);
1797 } else {
1798 p++;
1801 return p;
1804 /* C comments */
1805 static uint8_t *parse_comment(uint8_t *p)
1807 int c;
1809 p++;
1810 for(;;) {
1811 /* fast skip loop */
1812 for(;;) {
1813 c = *p;
1814 if (c == '\n' || c == '*' || c == '\\')
1815 break;
1816 p++;
1817 c = *p;
1818 if (c == '\n' || c == '*' || c == '\\')
1819 break;
1820 p++;
1822 /* now we can handle all the cases */
1823 if (c == '\n') {
1824 file->line_num++;
1825 p++;
1826 } else if (c == '*') {
1827 p++;
1828 for(;;) {
1829 c = *p;
1830 if (c == '*') {
1831 p++;
1832 } else if (c == '/') {
1833 goto end_of_comment;
1834 } else if (c == '\\') {
1835 file->buf_ptr = p;
1836 c = handle_eob();
1837 p = file->buf_ptr;
1838 if (c == '\\') {
1839 /* skip '\[\r]\n', otherwise just skip the stray */
1840 while (c == '\\') {
1841 PEEKC_EOB(c, p);
1842 if (c == '\n') {
1843 file->line_num++;
1844 PEEKC_EOB(c, p);
1845 } else if (c == '\r') {
1846 PEEKC_EOB(c, p);
1847 if (c == '\n') {
1848 file->line_num++;
1849 PEEKC_EOB(c, p);
1851 } else {
1852 goto after_star;
1856 } else {
1857 break;
1860 after_star: ;
1861 } else {
1862 /* stray, eob or eof */
1863 file->buf_ptr = p;
1864 c = handle_eob();
1865 p = file->buf_ptr;
1866 if (c == CH_EOF) {
1867 error("unexpected end of file in comment");
1868 } else if (c == '\\') {
1869 p++;
1873 end_of_comment:
1874 p++;
1875 return p;
1878 #define cinp minp
1880 /* space exlcuding newline */
1881 static inline int is_space(int ch)
1883 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1886 static inline void skip_spaces(void)
1888 while (is_space(ch))
1889 cinp();
1892 /* parse a string without interpreting escapes */
1893 static uint8_t *parse_pp_string(uint8_t *p,
1894 int sep, CString *str)
1896 int c;
1897 p++;
1898 for(;;) {
1899 c = *p;
1900 if (c == sep) {
1901 break;
1902 } else if (c == '\\') {
1903 file->buf_ptr = p;
1904 c = handle_eob();
1905 p = file->buf_ptr;
1906 if (c == CH_EOF) {
1907 unterminated_string:
1908 /* XXX: indicate line number of start of string */
1909 error("missing terminating %c character", sep);
1910 } else if (c == '\\') {
1911 /* escape : just skip \[\r]\n */
1912 PEEKC_EOB(c, p);
1913 if (c == '\n') {
1914 file->line_num++;
1915 p++;
1916 } else if (c == '\r') {
1917 PEEKC_EOB(c, p);
1918 if (c != '\n')
1919 expect("'\n' after '\r'");
1920 file->line_num++;
1921 p++;
1922 } else if (c == CH_EOF) {
1923 goto unterminated_string;
1924 } else {
1925 if (str) {
1926 cstr_ccat(str, '\\');
1927 cstr_ccat(str, c);
1929 p++;
1932 } else if (c == '\n') {
1933 file->line_num++;
1934 goto add_char;
1935 } else if (c == '\r') {
1936 PEEKC_EOB(c, p);
1937 if (c != '\n') {
1938 cstr_ccat(str, '\r');
1939 } else {
1940 file->line_num++;
1941 goto add_char;
1943 } else {
1944 add_char:
1945 if (str)
1946 cstr_ccat(str, c);
1947 p++;
1950 p++;
1951 return p;
1954 /* skip block of text until #else, #elif or #endif. skip also pairs of
1955 #if/#endif */
1956 void preprocess_skip(void)
1958 int a, start_of_line, c;
1959 uint8_t *p;
1961 p = file->buf_ptr;
1962 start_of_line = 1;
1963 a = 0;
1964 for(;;) {
1965 redo_no_start:
1966 c = *p;
1967 switch(c) {
1968 case ' ':
1969 case '\t':
1970 case '\f':
1971 case '\v':
1972 case '\r':
1973 p++;
1974 goto redo_no_start;
1975 case '\n':
1976 start_of_line = 1;
1977 file->line_num++;
1978 p++;
1979 goto redo_no_start;
1980 case '\\':
1981 file->buf_ptr = p;
1982 c = handle_eob();
1983 if (c == CH_EOF) {
1984 expect("#endif");
1985 } else if (c == '\\') {
1986 /* XXX: incorrect: should not give an error */
1987 ch = file->buf_ptr[0];
1988 handle_stray();
1990 p = file->buf_ptr;
1991 goto redo_no_start;
1992 /* skip strings */
1993 case '\"':
1994 case '\'':
1995 p = parse_pp_string(p, c, NULL);
1996 break;
1997 /* skip comments */
1998 case '/':
1999 file->buf_ptr = p;
2000 ch = *p;
2001 minp();
2002 p = file->buf_ptr;
2003 if (ch == '*') {
2004 p = parse_comment(p);
2005 } else if (ch == '/') {
2006 p = parse_line_comment(p);
2008 break;
2010 case '#':
2011 p++;
2012 if (start_of_line) {
2013 file->buf_ptr = p;
2014 next_nomacro();
2015 p = file->buf_ptr;
2016 if (a == 0 &&
2017 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2018 goto the_end;
2019 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2020 a++;
2021 else if (tok == TOK_ENDIF)
2022 a--;
2024 break;
2025 default:
2026 p++;
2027 break;
2029 start_of_line = 0;
2031 the_end: ;
2032 file->buf_ptr = p;
2035 /* ParseState handling */
2037 /* XXX: currently, no include file info is stored. Thus, we cannot display
2038 accurate messages if the function or data definition spans multiple
2039 files */
2041 /* save current parse state in 's' */
2042 void save_parse_state(ParseState *s)
2044 s->line_num = file->line_num;
2045 s->macro_ptr = macro_ptr;
2046 s->tok = tok;
2047 s->tokc = tokc;
2050 /* restore parse state from 's' */
2051 void restore_parse_state(ParseState *s)
2053 file->line_num = s->line_num;
2054 macro_ptr = s->macro_ptr;
2055 tok = s->tok;
2056 tokc = s->tokc;
2059 /* return the number of additional 'ints' necessary to store the
2060 token */
2061 static inline int tok_ext_size(int t)
2063 switch(t) {
2064 /* 4 bytes */
2065 case TOK_CINT:
2066 case TOK_CUINT:
2067 case TOK_CCHAR:
2068 case TOK_LCHAR:
2069 case TOK_STR:
2070 case TOK_LSTR:
2071 case TOK_CFLOAT:
2072 case TOK_LINENUM:
2073 case TOK_PPNUM:
2074 return 1;
2075 case TOK_CDOUBLE:
2076 case TOK_CLLONG:
2077 case TOK_CULLONG:
2078 return 2;
2079 case TOK_CLDOUBLE:
2080 return LDOUBLE_SIZE / 4;
2081 default:
2082 return 0;
2086 /* token string handling */
2088 static inline void tok_str_new(TokenString *s)
2090 s->str = NULL;
2091 s->len = 0;
2092 s->allocated_len = 0;
2093 s->last_line_num = -1;
2096 static void tok_str_free(int *str)
2098 const int *p;
2099 CString *cstr;
2100 int t;
2102 p = str;
2103 for(;;) {
2104 t = *p;
2105 /* NOTE: we test zero separately so that GCC can generate a
2106 table for the following switch */
2107 if (t == 0)
2108 break;
2109 switch(t) {
2110 case TOK_CINT:
2111 case TOK_CUINT:
2112 case TOK_CCHAR:
2113 case TOK_LCHAR:
2114 case TOK_CFLOAT:
2115 case TOK_LINENUM:
2116 p += 2;
2117 break;
2118 case TOK_PPNUM:
2119 case TOK_STR:
2120 case TOK_LSTR:
2121 /* XXX: use a macro to be portable on 64 bit ? */
2122 cstr = (CString *)p[1];
2123 cstr_free(cstr);
2124 tcc_free(cstr);
2125 p += 2;
2126 break;
2127 case TOK_CDOUBLE:
2128 case TOK_CLLONG:
2129 case TOK_CULLONG:
2130 p += 3;
2131 break;
2132 case TOK_CLDOUBLE:
2133 p += 1 + (LDOUBLE_SIZE / 4);
2134 break;
2135 default:
2136 p++;
2137 break;
2140 tcc_free(str);
2143 static int *tok_str_realloc(TokenString *s)
2145 int *str, len;
2147 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2148 str = tcc_realloc(s->str, len * sizeof(int));
2149 if (!str)
2150 error("memory full");
2151 s->allocated_len = len;
2152 s->str = str;
2153 return str;
2156 static void tok_str_add(TokenString *s, int t)
2158 int len, *str;
2160 len = s->len;
2161 str = s->str;
2162 if (len >= s->allocated_len)
2163 str = tok_str_realloc(s);
2164 str[len++] = t;
2165 s->len = len;
2168 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2170 int len, *str;
2172 len = s->len;
2173 str = s->str;
2175 /* allocate space for worst case */
2176 if (len + TOK_MAX_SIZE > s->allocated_len)
2177 str = tok_str_realloc(s);
2178 str[len++] = t;
2179 switch(t) {
2180 case TOK_CINT:
2181 case TOK_CUINT:
2182 case TOK_CCHAR:
2183 case TOK_LCHAR:
2184 case TOK_CFLOAT:
2185 case TOK_LINENUM:
2186 str[len++] = cv->tab[0];
2187 break;
2188 case TOK_PPNUM:
2189 case TOK_STR:
2190 case TOK_LSTR:
2191 str[len++] = (int)cstr_dup(cv->cstr);
2192 break;
2193 case TOK_CDOUBLE:
2194 case TOK_CLLONG:
2195 case TOK_CULLONG:
2196 str[len++] = cv->tab[0];
2197 str[len++] = cv->tab[1];
2198 break;
2199 case TOK_CLDOUBLE:
2200 #if LDOUBLE_SIZE == 12
2201 str[len++] = cv->tab[0];
2202 str[len++] = cv->tab[1];
2203 str[len++] = cv->tab[2];
2204 #else
2205 #error add long double size support
2206 #endif
2207 break;
2208 default:
2209 break;
2211 s->len = len;
2214 /* add the current parse token in token string 's' */
2215 static void tok_str_add_tok(TokenString *s)
2217 CValue cval;
2219 /* save line number info */
2220 if (file->line_num != s->last_line_num) {
2221 s->last_line_num = file->line_num;
2222 cval.i = s->last_line_num;
2223 tok_str_add2(s, TOK_LINENUM, &cval);
2225 tok_str_add2(s, tok, &tokc);
2228 #if LDOUBLE_SIZE == 12
2229 #define LDOUBLE_GET(p, cv) \
2230 cv.tab[0] = p[0]; \
2231 cv.tab[1] = p[1]; \
2232 cv.tab[2] = p[2];
2233 #else
2234 #error add long double size support
2235 #endif
2238 /* get a token from an integer array and increment pointer
2239 accordingly. we code it as a macro to avoid pointer aliasing. */
2240 #define TOK_GET(t, p, cv) \
2242 t = *p++; \
2243 switch(t) { \
2244 case TOK_CINT: \
2245 case TOK_CUINT: \
2246 case TOK_CCHAR: \
2247 case TOK_LCHAR: \
2248 case TOK_CFLOAT: \
2249 case TOK_LINENUM: \
2250 case TOK_STR: \
2251 case TOK_LSTR: \
2252 case TOK_PPNUM: \
2253 cv.tab[0] = *p++; \
2254 break; \
2255 case TOK_CDOUBLE: \
2256 case TOK_CLLONG: \
2257 case TOK_CULLONG: \
2258 cv.tab[0] = p[0]; \
2259 cv.tab[1] = p[1]; \
2260 p += 2; \
2261 break; \
2262 case TOK_CLDOUBLE: \
2263 LDOUBLE_GET(p, cv); \
2264 p += LDOUBLE_SIZE / 4; \
2265 break; \
2266 default: \
2267 break; \
2271 /* defines handling */
2272 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2274 Sym *s;
2276 s = sym_push2(&define_stack, v, macro_type, (int)str);
2277 s->next = first_arg;
2278 table_ident[v - TOK_IDENT]->sym_define = s;
2281 /* undefined a define symbol. Its name is just set to zero */
2282 static void define_undef(Sym *s)
2284 int v;
2285 v = s->v;
2286 if (v >= TOK_IDENT && v < tok_ident)
2287 table_ident[v - TOK_IDENT]->sym_define = NULL;
2288 s->v = 0;
2291 static inline Sym *define_find(int v)
2293 v -= TOK_IDENT;
2294 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2295 return NULL;
2296 return table_ident[v]->sym_define;
2299 /* free define stack until top reaches 'b' */
2300 static void free_defines(Sym *b)
2302 Sym *top, *top1;
2303 int v;
2305 top = define_stack;
2306 while (top != b) {
2307 top1 = top->prev;
2308 /* do not free args or predefined defines */
2309 if (top->c)
2310 tok_str_free((int *)top->c);
2311 v = top->v;
2312 if (v >= TOK_IDENT && v < tok_ident)
2313 table_ident[v - TOK_IDENT]->sym_define = NULL;
2314 tcc_free(top);
2315 top = top1;
2317 define_stack = b;
2320 /* label lookup */
2321 static Sym *label_find(int v)
2323 v -= TOK_IDENT;
2324 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2325 return NULL;
2326 return table_ident[v]->sym_label;
2329 static Sym *label_push(Sym **ptop, int v, int flags)
2331 Sym *s, **ps;
2332 s = sym_push2(ptop, v, 0, 0);
2333 s->r = flags;
2334 ps = &table_ident[v - TOK_IDENT]->sym_label;
2335 if (ptop == &global_label_stack) {
2336 /* modify the top most local identifier, so that
2337 sym_identifier will point to 's' when popped */
2338 while (*ps != NULL)
2339 ps = &(*ps)->prev_tok;
2341 s->prev_tok = *ps;
2342 *ps = s;
2343 return s;
2346 /* pop labels until element last is reached. Look if any labels are
2347 undefined. Define symbols if '&&label' was used. */
2348 static void label_pop(Sym **ptop, Sym *slast)
2350 Sym *s, *s1;
2351 for(s = *ptop; s != slast; s = s1) {
2352 s1 = s->prev;
2353 if (s->r == LABEL_DECLARED) {
2354 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2355 } else if (s->r == LABEL_FORWARD) {
2356 error("label '%s' used but not defined",
2357 get_tok_str(s->v, NULL));
2358 } else {
2359 if (s->c) {
2360 /* define corresponding symbol. A size of
2361 1 is put. */
2362 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2365 /* remove label */
2366 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2367 tcc_free(s);
2369 *ptop = slast;
2372 /* eval an expression for #if/#elif */
2373 static int expr_preprocess(void)
2375 int c, t;
2376 TokenString str;
2378 tok_str_new(&str);
2379 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2380 next(); /* do macro subst */
2381 if (tok == TOK_DEFINED) {
2382 next_nomacro();
2383 t = tok;
2384 if (t == '(')
2385 next_nomacro();
2386 c = define_find(tok) != 0;
2387 if (t == '(')
2388 next_nomacro();
2389 tok = TOK_CINT;
2390 tokc.i = c;
2391 } else if (tok >= TOK_IDENT) {
2392 /* if undefined macro */
2393 tok = TOK_CINT;
2394 tokc.i = 0;
2396 tok_str_add_tok(&str);
2398 tok_str_add(&str, -1); /* simulate end of file */
2399 tok_str_add(&str, 0);
2400 /* now evaluate C constant expression */
2401 macro_ptr = str.str;
2402 next();
2403 c = expr_const();
2404 macro_ptr = NULL;
2405 tok_str_free(str.str);
2406 return c != 0;
2409 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2410 static void tok_print(int *str)
2412 int t;
2413 CValue cval;
2415 while (1) {
2416 TOK_GET(t, str, cval);
2417 if (!t)
2418 break;
2419 printf(" %s", get_tok_str(t, &cval));
2421 printf("\n");
2423 #endif
2425 /* parse after #define */
2426 static void parse_define(void)
2428 Sym *s, *first, **ps;
2429 int v, t, varg, is_vaargs, c;
2430 TokenString str;
2432 v = tok;
2433 if (v < TOK_IDENT)
2434 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2435 /* XXX: should check if same macro (ANSI) */
2436 first = NULL;
2437 t = MACRO_OBJ;
2438 /* '(' must be just after macro definition for MACRO_FUNC */
2439 c = file->buf_ptr[0];
2440 if (c == '\\')
2441 c = handle_stray1(file->buf_ptr);
2442 if (c == '(') {
2443 next_nomacro();
2444 next_nomacro();
2445 ps = &first;
2446 while (tok != ')') {
2447 varg = tok;
2448 next_nomacro();
2449 is_vaargs = 0;
2450 if (varg == TOK_DOTS) {
2451 varg = TOK___VA_ARGS__;
2452 is_vaargs = 1;
2453 } else if (tok == TOK_DOTS && gnu_ext) {
2454 is_vaargs = 1;
2455 next_nomacro();
2457 if (varg < TOK_IDENT)
2458 error("badly punctuated parameter list");
2459 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2460 *ps = s;
2461 ps = &s->next;
2462 if (tok != ',')
2463 break;
2464 next_nomacro();
2466 t = MACRO_FUNC;
2468 tok_str_new(&str);
2469 next_nomacro();
2470 /* EOF testing necessary for '-D' handling */
2471 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2472 tok_str_add2(&str, tok, &tokc);
2473 next_nomacro();
2475 tok_str_add(&str, 0);
2476 #ifdef PP_DEBUG
2477 printf("define %s %d: ", get_tok_str(v, NULL), t);
2478 tok_print(str.str);
2479 #endif
2480 define_push(v, t, str.str, first);
2483 /* XXX: use a token or a hash table to accelerate matching ? */
2484 static CachedInclude *search_cached_include(TCCState *s1,
2485 int type, const char *filename)
2487 CachedInclude *e;
2488 int i;
2490 for(i = 0;i < s1->nb_cached_includes; i++) {
2491 e = s1->cached_includes[i];
2492 if (e->type == type && !strcmp(e->filename, filename))
2493 return e;
2495 return NULL;
2498 static inline void add_cached_include(TCCState *s1, int type,
2499 const char *filename, int ifndef_macro)
2501 CachedInclude *e;
2503 if (search_cached_include(s1, type, filename))
2504 return;
2505 #ifdef INC_DEBUG
2506 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2507 #endif
2508 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2509 if (!e)
2510 return;
2511 e->type = type;
2512 strcpy(e->filename, filename);
2513 e->ifndef_macro = ifndef_macro;
2514 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2517 /* is_bof is true if first non space token at beginning of file */
2518 static void preprocess(int is_bof)
2520 TCCState *s1 = tcc_state;
2521 int size, i, c, n, saved_parse_flags;
2522 char buf[1024], *q, *p;
2523 char buf1[1024];
2524 BufferedFile *f;
2525 Sym *s;
2526 CachedInclude *e;
2528 saved_parse_flags = parse_flags;
2529 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2530 PARSE_FLAG_LINEFEED;
2531 next_nomacro();
2532 redo:
2533 switch(tok) {
2534 case TOK_DEFINE:
2535 next_nomacro();
2536 parse_define();
2537 break;
2538 case TOK_UNDEF:
2539 next_nomacro();
2540 s = define_find(tok);
2541 /* undefine symbol by putting an invalid name */
2542 if (s)
2543 define_undef(s);
2544 break;
2545 case TOK_INCLUDE:
2546 ch = file->buf_ptr[0];
2547 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2548 skip_spaces();
2549 if (ch == '<') {
2550 c = '>';
2551 goto read_name;
2552 } else if (ch == '\"') {
2553 c = ch;
2554 read_name:
2555 /* XXX: better stray handling */
2556 minp();
2557 q = buf;
2558 while (ch != c && ch != '\n' && ch != CH_EOF) {
2559 if ((q - buf) < sizeof(buf) - 1)
2560 *q++ = ch;
2561 minp();
2563 *q = '\0';
2564 minp();
2565 #if 0
2566 /* eat all spaces and comments after include */
2567 /* XXX: slightly incorrect */
2568 while (ch1 != '\n' && ch1 != CH_EOF)
2569 inp();
2570 #endif
2571 } else {
2572 /* computed #include : either we have only strings or
2573 we have anything enclosed in '<>' */
2574 next();
2575 buf[0] = '\0';
2576 if (tok == TOK_STR) {
2577 while (tok != TOK_LINEFEED) {
2578 if (tok != TOK_STR) {
2579 include_syntax:
2580 error("'#include' expects \"FILENAME\" or <FILENAME>");
2582 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2583 next();
2585 c = '\"';
2586 } else {
2587 int len;
2588 while (tok != TOK_LINEFEED) {
2589 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2590 next();
2592 len = strlen(buf);
2593 /* check syntax and remove '<>' */
2594 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2595 goto include_syntax;
2596 memmove(buf, buf + 1, len - 2);
2597 buf[len - 2] = '\0';
2598 c = '>';
2602 e = search_cached_include(s1, c, buf);
2603 if (e && define_find(e->ifndef_macro)) {
2604 /* no need to parse the include because the 'ifndef macro'
2605 is defined */
2606 #ifdef INC_DEBUG
2607 printf("%s: skipping %s\n", file->filename, buf);
2608 #endif
2609 } else {
2610 if (c == '\"') {
2611 /* first search in current dir if "header.h" */
2612 size = 0;
2613 p = strrchr(file->filename, '/');
2614 if (p)
2615 size = p + 1 - file->filename;
2616 if (size > sizeof(buf1) - 1)
2617 size = sizeof(buf1) - 1;
2618 memcpy(buf1, file->filename, size);
2619 buf1[size] = '\0';
2620 pstrcat(buf1, sizeof(buf1), buf);
2621 f = tcc_open(s1, buf1);
2622 if (f)
2623 goto found;
2625 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2626 error("#include recursion too deep");
2627 /* now search in all the include paths */
2628 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2629 for(i = 0; i < n; i++) {
2630 const char *path;
2631 if (i < s1->nb_include_paths)
2632 path = s1->include_paths[i];
2633 else
2634 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2635 pstrcpy(buf1, sizeof(buf1), path);
2636 pstrcat(buf1, sizeof(buf1), "/");
2637 pstrcat(buf1, sizeof(buf1), buf);
2638 f = tcc_open(s1, buf1);
2639 if (f)
2640 goto found;
2642 error("include file '%s' not found", buf);
2643 f = NULL;
2644 found:
2645 #ifdef INC_DEBUG
2646 printf("%s: including %s\n", file->filename, buf1);
2647 #endif
2648 f->inc_type = c;
2649 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2650 /* push current file in stack */
2651 /* XXX: fix current line init */
2652 *s1->include_stack_ptr++ = file;
2653 file = f;
2654 /* add include file debug info */
2655 if (do_debug) {
2656 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2658 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2659 ch = file->buf_ptr[0];
2660 goto the_end;
2662 break;
2663 case TOK_IFNDEF:
2664 c = 1;
2665 goto do_ifdef;
2666 case TOK_IF:
2667 c = expr_preprocess();
2668 goto do_if;
2669 case TOK_IFDEF:
2670 c = 0;
2671 do_ifdef:
2672 next_nomacro();
2673 if (tok < TOK_IDENT)
2674 error("invalid argument for '#if%sdef'", c ? "n" : "");
2675 if (is_bof) {
2676 if (c) {
2677 #ifdef INC_DEBUG
2678 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2679 #endif
2680 file->ifndef_macro = tok;
2683 c = (define_find(tok) != 0) ^ c;
2684 do_if:
2685 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2686 error("memory full");
2687 *s1->ifdef_stack_ptr++ = c;
2688 goto test_skip;
2689 case TOK_ELSE:
2690 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2691 error("#else without matching #if");
2692 if (s1->ifdef_stack_ptr[-1] & 2)
2693 error("#else after #else");
2694 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2695 goto test_skip;
2696 case TOK_ELIF:
2697 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2698 error("#elif without matching #if");
2699 c = s1->ifdef_stack_ptr[-1];
2700 if (c > 1)
2701 error("#elif after #else");
2702 /* last #if/#elif expression was true: we skip */
2703 if (c == 1)
2704 goto skip;
2705 c = expr_preprocess();
2706 s1->ifdef_stack_ptr[-1] = c;
2707 test_skip:
2708 if (!(c & 1)) {
2709 skip:
2710 preprocess_skip();
2711 is_bof = 0;
2712 goto redo;
2714 break;
2715 case TOK_ENDIF:
2716 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2717 error("#endif without matching #if");
2718 s1->ifdef_stack_ptr--;
2719 /* '#ifndef macro' was at the start of file. Now we check if
2720 an '#endif' is exactly at the end of file */
2721 if (file->ifndef_macro &&
2722 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2723 file->ifndef_macro_saved = file->ifndef_macro;
2724 /* need to set to zero to avoid false matches if another
2725 #ifndef at middle of file */
2726 file->ifndef_macro = 0;
2727 while (tok != TOK_LINEFEED)
2728 next_nomacro();
2729 tok_flags |= TOK_FLAG_ENDIF;
2730 goto the_end;
2732 break;
2733 case TOK_LINE:
2734 next();
2735 if (tok != TOK_CINT)
2736 error("#line");
2737 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2738 next();
2739 if (tok != TOK_LINEFEED) {
2740 if (tok != TOK_STR)
2741 error("#line");
2742 pstrcpy(file->filename, sizeof(file->filename),
2743 (char *)tokc.cstr->data);
2745 break;
2746 case TOK_ERROR:
2747 case TOK_WARNING:
2748 c = tok;
2749 ch = file->buf_ptr[0];
2750 skip_spaces();
2751 q = buf;
2752 while (ch != '\n' && ch != CH_EOF) {
2753 if ((q - buf) < sizeof(buf) - 1)
2754 *q++ = ch;
2755 minp();
2757 *q = '\0';
2758 if (c == TOK_ERROR)
2759 error("#error %s", buf);
2760 else
2761 warning("#warning %s", buf);
2762 break;
2763 case TOK_PRAGMA:
2764 /* ignored */
2765 break;
2766 default:
2767 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2768 /* '!' is ignored to allow C scripts. numbers are ignored
2769 to emulate cpp behaviour */
2770 } else {
2771 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2773 break;
2775 /* ignore other preprocess commands or #! for C scripts */
2776 while (tok != TOK_LINEFEED)
2777 next_nomacro();
2778 the_end:
2779 parse_flags = saved_parse_flags;
2782 /* evaluate escape codes in a string. */
2783 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2785 int c, n;
2786 const char *p;
2788 p = buf;
2789 for(;;) {
2790 c = *p;
2791 if (c == '\0')
2792 break;
2793 if (c == '\\') {
2794 p++;
2795 /* escape */
2796 c = *p;
2797 switch(c) {
2798 case '0': case '1': case '2': case '3':
2799 case '4': case '5': case '6': case '7':
2800 /* at most three octal digits */
2801 n = c - '0';
2802 p++;
2803 c = *p;
2804 if (isoct(c)) {
2805 n = n * 8 + c - '0';
2806 p++;
2807 c = *p;
2808 if (isoct(c)) {
2809 n = n * 8 + c - '0';
2810 p++;
2813 c = n;
2814 goto add_char_nonext;
2815 case 'x':
2816 p++;
2817 n = 0;
2818 for(;;) {
2819 c = *p;
2820 if (c >= 'a' && c <= 'f')
2821 c = c - 'a' + 10;
2822 else if (c >= 'A' && c <= 'F')
2823 c = c - 'A' + 10;
2824 else if (isnum(c))
2825 c = c - '0';
2826 else
2827 break;
2828 n = n * 16 + c;
2829 p++;
2831 c = n;
2832 goto add_char_nonext;
2833 case 'a':
2834 c = '\a';
2835 break;
2836 case 'b':
2837 c = '\b';
2838 break;
2839 case 'f':
2840 c = '\f';
2841 break;
2842 case 'n':
2843 c = '\n';
2844 break;
2845 case 'r':
2846 c = '\r';
2847 break;
2848 case 't':
2849 c = '\t';
2850 break;
2851 case 'v':
2852 c = '\v';
2853 break;
2854 case 'e':
2855 if (!gnu_ext)
2856 goto invalid_escape;
2857 c = 27;
2858 break;
2859 case '\'':
2860 case '\"':
2861 case '\\':
2862 case '?':
2863 break;
2864 default:
2865 invalid_escape:
2866 error("invalid escaped char");
2869 p++;
2870 add_char_nonext:
2871 if (!is_long)
2872 cstr_ccat(outstr, c);
2873 else
2874 cstr_wccat(outstr, c);
2876 /* add a trailing '\0' */
2877 if (!is_long)
2878 cstr_ccat(outstr, '\0');
2879 else
2880 cstr_wccat(outstr, '\0');
2883 /* we use 64 bit numbers */
2884 #define BN_SIZE 2
2886 /* bn = (bn << shift) | or_val */
2887 void bn_lshift(unsigned int *bn, int shift, int or_val)
2889 int i;
2890 unsigned int v;
2891 for(i=0;i<BN_SIZE;i++) {
2892 v = bn[i];
2893 bn[i] = (v << shift) | or_val;
2894 or_val = v >> (32 - shift);
2898 void bn_zero(unsigned int *bn)
2900 int i;
2901 for(i=0;i<BN_SIZE;i++) {
2902 bn[i] = 0;
2906 /* parse number in null terminated string 'p' and return it in the
2907 current token */
2908 void parse_number(const char *p)
2910 int b, t, shift, frac_bits, s, exp_val, ch;
2911 char *q;
2912 unsigned int bn[BN_SIZE];
2913 double d;
2915 /* number */
2916 q = token_buf;
2917 ch = *p++;
2918 t = ch;
2919 ch = *p++;
2920 *q++ = t;
2921 b = 10;
2922 if (t == '.') {
2923 goto float_frac_parse;
2924 } else if (t == '0') {
2925 if (ch == 'x' || ch == 'X') {
2926 q--;
2927 ch = *p++;
2928 b = 16;
2929 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2930 q--;
2931 ch = *p++;
2932 b = 2;
2935 /* parse all digits. cannot check octal numbers at this stage
2936 because of floating point constants */
2937 while (1) {
2938 if (ch >= 'a' && ch <= 'f')
2939 t = ch - 'a' + 10;
2940 else if (ch >= 'A' && ch <= 'F')
2941 t = ch - 'A' + 10;
2942 else if (isnum(ch))
2943 t = ch - '0';
2944 else
2945 break;
2946 if (t >= b)
2947 break;
2948 if (q >= token_buf + STRING_MAX_SIZE) {
2949 num_too_long:
2950 error("number too long");
2952 *q++ = ch;
2953 ch = *p++;
2955 if (ch == '.' ||
2956 ((ch == 'e' || ch == 'E') && b == 10) ||
2957 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
2958 if (b != 10) {
2959 /* NOTE: strtox should support that for hexa numbers, but
2960 non ISOC99 libcs do not support it, so we prefer to do
2961 it by hand */
2962 /* hexadecimal or binary floats */
2963 /* XXX: handle overflows */
2964 *q = '\0';
2965 if (b == 16)
2966 shift = 4;
2967 else
2968 shift = 2;
2969 bn_zero(bn);
2970 q = token_buf;
2971 while (1) {
2972 t = *q++;
2973 if (t == '\0') {
2974 break;
2975 } else if (t >= 'a') {
2976 t = t - 'a' + 10;
2977 } else if (t >= 'A') {
2978 t = t - 'A' + 10;
2979 } else {
2980 t = t - '0';
2982 bn_lshift(bn, shift, t);
2984 frac_bits = 0;
2985 if (ch == '.') {
2986 ch = *p++;
2987 while (1) {
2988 t = ch;
2989 if (t >= 'a' && t <= 'f') {
2990 t = t - 'a' + 10;
2991 } else if (t >= 'A' && t <= 'F') {
2992 t = t - 'A' + 10;
2993 } else if (t >= '0' && t <= '9') {
2994 t = t - '0';
2995 } else {
2996 break;
2998 if (t >= b)
2999 error("invalid digit");
3000 bn_lshift(bn, shift, t);
3001 frac_bits += shift;
3002 ch = *p++;
3005 if (ch != 'p' && ch != 'P')
3006 expect("exponent");
3007 ch = *p++;
3008 s = 1;
3009 exp_val = 0;
3010 if (ch == '+') {
3011 ch = *p++;
3012 } else if (ch == '-') {
3013 s = -1;
3014 ch = *p++;
3016 if (ch < '0' || ch > '9')
3017 expect("exponent digits");
3018 while (ch >= '0' && ch <= '9') {
3019 exp_val = exp_val * 10 + ch - '0';
3020 ch = *p++;
3022 exp_val = exp_val * s;
3024 /* now we can generate the number */
3025 /* XXX: should patch directly float number */
3026 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3027 d = ldexp(d, exp_val - frac_bits);
3028 t = toup(ch);
3029 if (t == 'F') {
3030 ch = *p++;
3031 tok = TOK_CFLOAT;
3032 /* float : should handle overflow */
3033 tokc.f = (float)d;
3034 } else if (t == 'L') {
3035 ch = *p++;
3036 tok = TOK_CLDOUBLE;
3037 /* XXX: not large enough */
3038 tokc.ld = (long double)d;
3039 } else {
3040 tok = TOK_CDOUBLE;
3041 tokc.d = d;
3043 } else {
3044 /* decimal floats */
3045 if (ch == '.') {
3046 if (q >= token_buf + STRING_MAX_SIZE)
3047 goto num_too_long;
3048 *q++ = ch;
3049 ch = *p++;
3050 float_frac_parse:
3051 while (ch >= '0' && ch <= '9') {
3052 if (q >= token_buf + STRING_MAX_SIZE)
3053 goto num_too_long;
3054 *q++ = ch;
3055 ch = *p++;
3058 if (ch == 'e' || ch == 'E') {
3059 if (q >= token_buf + STRING_MAX_SIZE)
3060 goto num_too_long;
3061 *q++ = ch;
3062 ch = *p++;
3063 if (ch == '-' || ch == '+') {
3064 if (q >= token_buf + STRING_MAX_SIZE)
3065 goto num_too_long;
3066 *q++ = ch;
3067 ch = *p++;
3069 if (ch < '0' || ch > '9')
3070 expect("exponent digits");
3071 while (ch >= '0' && ch <= '9') {
3072 if (q >= token_buf + STRING_MAX_SIZE)
3073 goto num_too_long;
3074 *q++ = ch;
3075 ch = *p++;
3078 *q = '\0';
3079 t = toup(ch);
3080 errno = 0;
3081 if (t == 'F') {
3082 ch = *p++;
3083 tok = TOK_CFLOAT;
3084 tokc.f = strtof(token_buf, NULL);
3085 } else if (t == 'L') {
3086 ch = *p++;
3087 tok = TOK_CLDOUBLE;
3088 tokc.ld = strtold(token_buf, NULL);
3089 } else {
3090 tok = TOK_CDOUBLE;
3091 tokc.d = strtod(token_buf, NULL);
3094 } else {
3095 unsigned long long n, n1;
3096 int lcount, ucount;
3098 /* integer number */
3099 *q = '\0';
3100 q = token_buf;
3101 if (b == 10 && *q == '0') {
3102 b = 8;
3103 q++;
3105 n = 0;
3106 while(1) {
3107 t = *q++;
3108 /* no need for checks except for base 10 / 8 errors */
3109 if (t == '\0') {
3110 break;
3111 } else if (t >= 'a') {
3112 t = t - 'a' + 10;
3113 } else if (t >= 'A') {
3114 t = t - 'A' + 10;
3115 } else {
3116 t = t - '0';
3117 if (t >= b)
3118 error("invalid digit");
3120 n1 = n;
3121 n = n * b + t;
3122 /* detect overflow */
3123 /* XXX: this test is not reliable */
3124 if (n < n1)
3125 error("integer constant overflow");
3128 /* XXX: not exactly ANSI compliant */
3129 if ((n & 0xffffffff00000000LL) != 0) {
3130 if ((n >> 63) != 0)
3131 tok = TOK_CULLONG;
3132 else
3133 tok = TOK_CLLONG;
3134 } else if (n > 0x7fffffff) {
3135 tok = TOK_CUINT;
3136 } else {
3137 tok = TOK_CINT;
3139 lcount = 0;
3140 ucount = 0;
3141 for(;;) {
3142 t = toup(ch);
3143 if (t == 'L') {
3144 if (lcount >= 2)
3145 error("three 'l's in integer constant");
3146 lcount++;
3147 if (lcount == 2) {
3148 if (tok == TOK_CINT)
3149 tok = TOK_CLLONG;
3150 else if (tok == TOK_CUINT)
3151 tok = TOK_CULLONG;
3153 ch = *p++;
3154 } else if (t == 'U') {
3155 if (ucount >= 1)
3156 error("two 'u's in integer constant");
3157 ucount++;
3158 if (tok == TOK_CINT)
3159 tok = TOK_CUINT;
3160 else if (tok == TOK_CLLONG)
3161 tok = TOK_CULLONG;
3162 ch = *p++;
3163 } else {
3164 break;
3167 if (tok == TOK_CINT || tok == TOK_CUINT)
3168 tokc.ui = n;
3169 else
3170 tokc.ull = n;
3175 #define PARSE2(c1, tok1, c2, tok2) \
3176 case c1: \
3177 PEEKC(c, p); \
3178 if (c == c2) { \
3179 p++; \
3180 tok = tok2; \
3181 } else { \
3182 tok = tok1; \
3184 break;
3186 /* return next token without macro substitution */
3187 static inline void next_nomacro1(void)
3189 int t, c, is_long;
3190 TokenSym *ts;
3191 uint8_t *p, *p1;
3192 unsigned int h;
3194 p = file->buf_ptr;
3195 redo_no_start:
3196 c = *p;
3197 switch(c) {
3198 case ' ':
3199 case '\t':
3200 case '\f':
3201 case '\v':
3202 case '\r':
3203 p++;
3204 goto redo_no_start;
3206 case '\\':
3207 /* first look if it is in fact an end of buffer */
3208 if (p >= file->buf_end) {
3209 file->buf_ptr = p;
3210 handle_eob();
3211 p = file->buf_ptr;
3212 if (p >= file->buf_end)
3213 goto parse_eof;
3214 else
3215 goto redo_no_start;
3216 } else {
3217 file->buf_ptr = p;
3218 ch = *p;
3219 handle_stray();
3220 p = file->buf_ptr;
3221 goto redo_no_start;
3223 parse_eof:
3225 TCCState *s1 = tcc_state;
3226 if (parse_flags & PARSE_FLAG_LINEFEED) {
3227 tok = TOK_LINEFEED;
3228 } else if (s1->include_stack_ptr == s1->include_stack ||
3229 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3230 /* no include left : end of file. */
3231 tok = TOK_EOF;
3232 } else {
3233 /* pop include file */
3235 /* test if previous '#endif' was after a #ifdef at
3236 start of file */
3237 if (tok_flags & TOK_FLAG_ENDIF) {
3238 #ifdef INC_DEBUG
3239 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3240 #endif
3241 add_cached_include(s1, file->inc_type, file->inc_filename,
3242 file->ifndef_macro_saved);
3245 /* add end of include file debug info */
3246 if (do_debug) {
3247 put_stabd(N_EINCL, 0, 0);
3249 /* pop include stack */
3250 tcc_close(file);
3251 s1->include_stack_ptr--;
3252 file = *s1->include_stack_ptr;
3253 p = file->buf_ptr;
3254 goto redo_no_start;
3257 break;
3259 case '\n':
3260 if (parse_flags & PARSE_FLAG_LINEFEED) {
3261 tok = TOK_LINEFEED;
3262 } else {
3263 file->line_num++;
3264 tok_flags |= TOK_FLAG_BOL;
3265 p++;
3266 goto redo_no_start;
3268 break;
3270 case '#':
3271 /* XXX: simplify */
3272 PEEKC(c, p);
3273 if ((tok_flags & TOK_FLAG_BOL) &&
3274 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3275 file->buf_ptr = p;
3276 preprocess(tok_flags & TOK_FLAG_BOF);
3277 p = file->buf_ptr;
3278 goto redo_no_start;
3279 } else {
3280 if (c == '#') {
3281 p++;
3282 tok = TOK_TWOSHARPS;
3283 } else {
3284 tok = '#';
3287 break;
3289 case 'a': case 'b': case 'c': case 'd':
3290 case 'e': case 'f': case 'g': case 'h':
3291 case 'i': case 'j': case 'k': case 'l':
3292 case 'm': case 'n': case 'o': case 'p':
3293 case 'q': case 'r': case 's': case 't':
3294 case 'u': case 'v': case 'w': case 'x':
3295 case 'y': case 'z':
3296 case 'A': case 'B': case 'C': case 'D':
3297 case 'E': case 'F': case 'G': case 'H':
3298 case 'I': case 'J': case 'K':
3299 case 'M': case 'N': case 'O': case 'P':
3300 case 'Q': case 'R': case 'S': case 'T':
3301 case 'U': case 'V': case 'W': case 'X':
3302 case 'Y': case 'Z':
3303 case '_':
3304 parse_ident_fast:
3305 p1 = p;
3306 h = TOK_HASH_INIT;
3307 h = TOK_HASH_FUNC(h, c);
3308 p++;
3309 for(;;) {
3310 c = *p;
3311 if (!isidnum_table[c])
3312 break;
3313 h = TOK_HASH_FUNC(h, c);
3314 p++;
3316 if (c != '\\') {
3317 TokenSym **pts;
3318 int len;
3320 /* fast case : no stray found, so we have the full token
3321 and we have already hashed it */
3322 len = p - p1;
3323 h &= (TOK_HASH_SIZE - 1);
3324 pts = &hash_ident[h];
3325 for(;;) {
3326 ts = *pts;
3327 if (!ts)
3328 break;
3329 if (ts->len == len && !memcmp(ts->str, p1, len))
3330 goto token_found;
3331 pts = &(ts->hash_next);
3333 ts = tok_alloc_new(pts, p1, len);
3334 token_found: ;
3335 } else {
3336 /* slower case */
3337 cstr_reset(&tokcstr);
3339 while (p1 < p) {
3340 cstr_ccat(&tokcstr, *p1);
3341 p1++;
3343 p--;
3344 PEEKC(c, p);
3345 parse_ident_slow:
3346 while (isidnum_table[c]) {
3347 cstr_ccat(&tokcstr, c);
3348 PEEKC(c, p);
3350 ts = tok_alloc(tokcstr.data, tokcstr.size);
3352 tok = ts->tok;
3353 break;
3354 case 'L':
3355 t = p[1];
3356 if (t != '\\' && t != '\'' && t != '\"') {
3357 /* fast case */
3358 goto parse_ident_fast;
3359 } else {
3360 PEEKC(c, p);
3361 if (c == '\'' || c == '\"') {
3362 is_long = 1;
3363 goto str_const;
3364 } else {
3365 cstr_reset(&tokcstr);
3366 cstr_ccat(&tokcstr, 'L');
3367 goto parse_ident_slow;
3370 break;
3371 case '0': case '1': case '2': case '3':
3372 case '4': case '5': case '6': case '7':
3373 case '8': case '9':
3375 cstr_reset(&tokcstr);
3376 /* after the first digit, accept digits, alpha, '.' or sign if
3377 prefixed by 'eEpP' */
3378 parse_num:
3379 for(;;) {
3380 t = c;
3381 cstr_ccat(&tokcstr, c);
3382 PEEKC(c, p);
3383 if (!(isnum(c) || isid(c) || c == '.' ||
3384 ((c == '+' || c == '-') &&
3385 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3386 break;
3388 /* We add a trailing '\0' to ease parsing */
3389 cstr_ccat(&tokcstr, '\0');
3390 tokc.cstr = &tokcstr;
3391 tok = TOK_PPNUM;
3392 break;
3393 case '.':
3394 /* special dot handling because it can also start a number */
3395 PEEKC(c, p);
3396 if (isnum(c)) {
3397 cstr_reset(&tokcstr);
3398 cstr_ccat(&tokcstr, '.');
3399 goto parse_num;
3400 } else if (c == '.') {
3401 PEEKC(c, p);
3402 if (c != '.')
3403 expect("'.'");
3404 PEEKC(c, p);
3405 tok = TOK_DOTS;
3406 } else {
3407 tok = '.';
3409 break;
3410 case '\'':
3411 case '\"':
3412 is_long = 0;
3413 str_const:
3415 CString str;
3416 int sep;
3418 sep = c;
3420 /* parse the string */
3421 cstr_new(&str);
3422 p = parse_pp_string(p, sep, &str);
3423 cstr_ccat(&str, '\0');
3425 /* eval the escape (should be done as TOK_PPNUM) */
3426 cstr_reset(&tokcstr);
3427 parse_escape_string(&tokcstr, str.data, is_long);
3428 cstr_free(&str);
3430 if (sep == '\'') {
3431 int char_size;
3432 /* XXX: make it portable */
3433 if (!is_long)
3434 char_size = 1;
3435 else
3436 char_size = sizeof(int);
3437 if (tokcstr.size <= char_size)
3438 error("empty character constant");
3439 if (tokcstr.size > 2 * char_size)
3440 warning("multi-character character constant");
3441 if (!is_long) {
3442 tokc.i = *(int8_t *)tokcstr.data;
3443 tok = TOK_CCHAR;
3444 } else {
3445 tokc.i = *(int *)tokcstr.data;
3446 tok = TOK_LCHAR;
3448 } else {
3449 tokc.cstr = &tokcstr;
3450 if (!is_long)
3451 tok = TOK_STR;
3452 else
3453 tok = TOK_LSTR;
3456 break;
3458 case '<':
3459 PEEKC(c, p);
3460 if (c == '=') {
3461 p++;
3462 tok = TOK_LE;
3463 } else if (c == '<') {
3464 PEEKC(c, p);
3465 if (c == '=') {
3466 p++;
3467 tok = TOK_A_SHL;
3468 } else {
3469 tok = TOK_SHL;
3471 } else {
3472 tok = TOK_LT;
3474 break;
3476 case '>':
3477 PEEKC(c, p);
3478 if (c == '=') {
3479 p++;
3480 tok = TOK_GE;
3481 } else if (c == '>') {
3482 PEEKC(c, p);
3483 if (c == '=') {
3484 p++;
3485 tok = TOK_A_SAR;
3486 } else {
3487 tok = TOK_SAR;
3489 } else {
3490 tok = TOK_GT;
3492 break;
3494 case '&':
3495 PEEKC(c, p);
3496 if (c == '&') {
3497 p++;
3498 tok = TOK_LAND;
3499 } else if (c == '=') {
3500 p++;
3501 tok = TOK_A_AND;
3502 } else {
3503 tok = '&';
3505 break;
3507 case '|':
3508 PEEKC(c, p);
3509 if (c == '|') {
3510 p++;
3511 tok = TOK_LOR;
3512 } else if (c == '=') {
3513 p++;
3514 tok = TOK_A_OR;
3515 } else {
3516 tok = '|';
3518 break;
3520 case '+':
3521 PEEKC(c, p);
3522 if (c == '+') {
3523 p++;
3524 tok = TOK_INC;
3525 } else if (c == '=') {
3526 p++;
3527 tok = TOK_A_ADD;
3528 } else {
3529 tok = '+';
3531 break;
3533 case '-':
3534 PEEKC(c, p);
3535 if (c == '-') {
3536 p++;
3537 tok = TOK_DEC;
3538 } else if (c == '=') {
3539 p++;
3540 tok = TOK_A_SUB;
3541 } else if (c == '>') {
3542 p++;
3543 tok = TOK_ARROW;
3544 } else {
3545 tok = '-';
3547 break;
3549 PARSE2('!', '!', '=', TOK_NE)
3550 PARSE2('=', '=', '=', TOK_EQ)
3551 PARSE2('*', '*', '=', TOK_A_MUL)
3552 PARSE2('%', '%', '=', TOK_A_MOD)
3553 PARSE2('^', '^', '=', TOK_A_XOR)
3555 /* comments or operator */
3556 case '/':
3557 PEEKC(c, p);
3558 if (c == '*') {
3559 p = parse_comment(p);
3560 goto redo_no_start;
3561 } else if (c == '/') {
3562 p = parse_line_comment(p);
3563 goto redo_no_start;
3564 } else if (c == '=') {
3565 p++;
3566 tok = TOK_A_DIV;
3567 } else {
3568 tok = '/';
3570 break;
3572 /* simple tokens */
3573 case '(':
3574 case ')':
3575 case '[':
3576 case ']':
3577 case '{':
3578 case '}':
3579 case ',':
3580 case ';':
3581 case ':':
3582 case '?':
3583 case '~':
3584 case '$': /* only used in assembler */
3585 tok = c;
3586 p++;
3587 break;
3588 default:
3589 error("unrecognized character \\x%02x", c);
3590 break;
3592 file->buf_ptr = p;
3593 tok_flags = 0;
3594 #if defined(PARSE_DEBUG)
3595 printf("token = %s\n", get_tok_str(tok, &tokc));
3596 #endif
3599 /* return next token without macro substitution. Can read input from
3600 macro_ptr buffer */
3601 static void next_nomacro(void)
3603 if (macro_ptr) {
3604 redo:
3605 tok = *macro_ptr;
3606 if (tok) {
3607 TOK_GET(tok, macro_ptr, tokc);
3608 if (tok == TOK_LINENUM) {
3609 file->line_num = tokc.i;
3610 goto redo;
3613 } else {
3614 next_nomacro1();
3618 /* substitute args in macro_str and return allocated string */
3619 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3621 int *st, last_tok, t, notfirst;
3622 Sym *s;
3623 CValue cval;
3624 TokenString str;
3625 CString cstr;
3627 tok_str_new(&str);
3628 last_tok = 0;
3629 while(1) {
3630 TOK_GET(t, macro_str, cval);
3631 if (!t)
3632 break;
3633 if (t == '#') {
3634 /* stringize */
3635 TOK_GET(t, macro_str, cval);
3636 if (!t)
3637 break;
3638 s = sym_find2(args, t);
3639 if (s) {
3640 cstr_new(&cstr);
3641 st = (int *)s->c;
3642 notfirst = 0;
3643 while (*st) {
3644 if (notfirst)
3645 cstr_ccat(&cstr, ' ');
3646 TOK_GET(t, st, cval);
3647 cstr_cat(&cstr, get_tok_str(t, &cval));
3648 notfirst = 1;
3650 cstr_ccat(&cstr, '\0');
3651 #ifdef PP_DEBUG
3652 printf("stringize: %s\n", (char *)cstr.data);
3653 #endif
3654 /* add string */
3655 cval.cstr = &cstr;
3656 tok_str_add2(&str, TOK_STR, &cval);
3657 cstr_free(&cstr);
3658 } else {
3659 tok_str_add2(&str, t, &cval);
3661 } else if (t >= TOK_IDENT) {
3662 s = sym_find2(args, t);
3663 if (s) {
3664 st = (int *)s->c;
3665 /* if '##' is present before or after, no arg substitution */
3666 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3667 /* special case for var arg macros : ## eats the
3668 ',' if empty VA_ARGS variable. */
3669 /* XXX: test of the ',' is not 100%
3670 reliable. should fix it to avoid security
3671 problems */
3672 if (gnu_ext && s->type.t &&
3673 last_tok == TOK_TWOSHARPS &&
3674 str.len >= 2 && str.str[str.len - 2] == ',') {
3675 if (*st == 0) {
3676 /* suppress ',' '##' */
3677 str.len -= 2;
3678 } else {
3679 /* suppress '##' and add variable */
3680 str.len--;
3681 goto add_var;
3683 } else {
3684 int t1;
3685 add_var:
3686 for(;;) {
3687 TOK_GET(t1, st, cval);
3688 if (!t1)
3689 break;
3690 tok_str_add2(&str, t1, &cval);
3693 } else {
3694 macro_subst(&str, nested_list, st);
3696 } else {
3697 tok_str_add(&str, t);
3699 } else {
3700 tok_str_add2(&str, t, &cval);
3702 last_tok = t;
3704 tok_str_add(&str, 0);
3705 return str.str;
3708 /* do macro substitution of current token with macro 's' and add
3709 result to (tok_str,tok_len). 'nested_list' is the list of all
3710 macros we got inside to avoid recursing. Return non zero if no
3711 substitution needs to be done */
3712 static int macro_subst_tok(TokenString *tok_str,
3713 Sym **nested_list, Sym *s)
3715 Sym *args, *sa, *sa1;
3716 int mstr_allocated, parlevel, *mstr, t;
3717 TokenString str;
3718 char *cstrval;
3719 CValue cval;
3720 CString cstr;
3722 /* if symbol is a macro, prepare substitution */
3724 /* special macros */
3725 if (tok == TOK___LINE__) {
3726 cval.i = file->line_num;
3727 tok_str_add2(tok_str, TOK_CINT, &cval);
3728 } else if (tok == TOK___FILE__) {
3729 cstrval = file->filename;
3730 goto add_cstr;
3731 tok_str_add2(tok_str, TOK_STR, &cval);
3732 } else if (tok == TOK___DATE__) {
3733 cstrval = "Jan 1 2002";
3734 goto add_cstr;
3735 } else if (tok == TOK___TIME__) {
3736 cstrval = "00:00:00";
3737 add_cstr:
3738 cstr_new(&cstr);
3739 cstr_cat(&cstr, cstrval);
3740 cstr_ccat(&cstr, '\0');
3741 cval.cstr = &cstr;
3742 tok_str_add2(tok_str, TOK_STR, &cval);
3743 cstr_free(&cstr);
3744 } else {
3745 mstr = (int *)s->c;
3746 mstr_allocated = 0;
3747 if (s->type.t == MACRO_FUNC) {
3748 /* NOTE: we do not use next_nomacro to avoid eating the
3749 next token. XXX: find better solution */
3750 if (macro_ptr) {
3751 t = *macro_ptr;
3752 if (t == 0) {
3753 /* end of macro stream: we must look at the token
3754 after in the file */
3755 macro_ptr = NULL;
3756 goto parse_stream;
3758 } else {
3759 parse_stream:
3760 /* XXX: incorrect with comments */
3761 ch = file->buf_ptr[0];
3762 while (is_space(ch) || ch == '\n')
3763 cinp();
3764 t = ch;
3766 if (t != '(') /* no macro subst */
3767 return -1;
3769 /* argument macro */
3770 next_nomacro();
3771 next_nomacro();
3772 args = NULL;
3773 sa = s->next;
3774 /* NOTE: empty args are allowed, except if no args */
3775 for(;;) {
3776 /* handle '()' case */
3777 if (!args && tok == ')')
3778 break;
3779 if (!sa)
3780 error("macro '%s' used with too many args",
3781 get_tok_str(s->v, 0));
3782 tok_str_new(&str);
3783 parlevel = 0;
3784 /* NOTE: non zero sa->t indicates VA_ARGS */
3785 while ((parlevel > 0 ||
3786 (tok != ')' &&
3787 (tok != ',' || sa->type.t))) &&
3788 tok != -1) {
3789 if (tok == '(')
3790 parlevel++;
3791 else if (tok == ')')
3792 parlevel--;
3793 tok_str_add2(&str, tok, &tokc);
3794 next_nomacro();
3796 tok_str_add(&str, 0);
3797 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3798 sa = sa->next;
3799 if (tok == ')') {
3800 /* special case for gcc var args: add an empty
3801 var arg argument if it is omitted */
3802 if (sa && sa->type.t && gnu_ext)
3803 continue;
3804 else
3805 break;
3807 if (tok != ',')
3808 expect(",");
3809 next_nomacro();
3811 if (sa) {
3812 error("macro '%s' used with too few args",
3813 get_tok_str(s->v, 0));
3816 /* now subst each arg */
3817 mstr = macro_arg_subst(nested_list, mstr, args);
3818 /* free memory */
3819 sa = args;
3820 while (sa) {
3821 sa1 = sa->prev;
3822 tok_str_free((int *)sa->c);
3823 tcc_free(sa);
3824 sa = sa1;
3826 mstr_allocated = 1;
3828 sym_push2(nested_list, s->v, 0, 0);
3829 macro_subst(tok_str, nested_list, mstr);
3830 /* pop nested defined symbol */
3831 sa1 = *nested_list;
3832 *nested_list = sa1->prev;
3833 tcc_free(sa1);
3834 if (mstr_allocated)
3835 tok_str_free(mstr);
3837 return 0;
3840 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3841 return the resulting string (which must be freed). */
3842 static inline int *macro_twosharps(const int *macro_str)
3844 TokenSym *ts;
3845 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3846 int t;
3847 const char *p1, *p2;
3848 CValue cval;
3849 TokenString macro_str1;
3850 CString cstr;
3852 start_macro_ptr = macro_str;
3853 /* we search the first '##' */
3854 for(;;) {
3855 macro_ptr1 = macro_str;
3856 TOK_GET(t, macro_str, cval);
3857 /* nothing more to do if end of string */
3858 if (t == 0)
3859 return NULL;
3860 if (*macro_str == TOK_TWOSHARPS)
3861 break;
3864 /* we saw '##', so we need more processing to handle it */
3865 cstr_new(&cstr);
3866 tok_str_new(&macro_str1);
3867 tok = t;
3868 tokc = cval;
3870 /* add all tokens seen so far */
3871 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
3872 TOK_GET(t, ptr, cval);
3873 tok_str_add2(&macro_str1, t, &cval);
3875 saved_macro_ptr = macro_ptr;
3876 /* XXX: get rid of the use of macro_ptr here */
3877 macro_ptr = (int *)macro_str;
3878 for(;;) {
3879 while (*macro_ptr == TOK_TWOSHARPS) {
3880 macro_ptr++;
3881 macro_ptr1 = macro_ptr;
3882 t = *macro_ptr;
3883 if (t) {
3884 TOK_GET(t, macro_ptr, cval);
3885 /* We concatenate the two tokens if we have an
3886 identifier or a preprocessing number */
3887 cstr_reset(&cstr);
3888 p1 = get_tok_str(tok, &tokc);
3889 cstr_cat(&cstr, p1);
3890 p2 = get_tok_str(t, &cval);
3891 cstr_cat(&cstr, p2);
3892 cstr_ccat(&cstr, '\0');
3894 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3895 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3896 if (tok == TOK_PPNUM) {
3897 /* if number, then create a number token */
3898 /* NOTE: no need to allocate because
3899 tok_str_add2() does it */
3900 tokc.cstr = &cstr;
3901 } else {
3902 /* if identifier, we must do a test to
3903 validate we have a correct identifier */
3904 if (t == TOK_PPNUM) {
3905 const char *p;
3906 int c;
3908 p = p2;
3909 for(;;) {
3910 c = *p;
3911 if (c == '\0')
3912 break;
3913 p++;
3914 if (!isnum(c) && !isid(c))
3915 goto error_pasting;
3918 ts = tok_alloc(cstr.data, strlen(cstr.data));
3919 tok = ts->tok; /* modify current token */
3921 } else {
3922 const char *str = cstr.data;
3923 const unsigned char *q;
3925 /* we look for a valid token */
3926 /* XXX: do more extensive checks */
3927 if (!strcmp(str, ">>=")) {
3928 tok = TOK_A_SAR;
3929 } else if (!strcmp(str, "<<=")) {
3930 tok = TOK_A_SHL;
3931 } else if (strlen(str) == 2) {
3932 /* search in two bytes table */
3933 q = tok_two_chars;
3934 for(;;) {
3935 if (!*q)
3936 goto error_pasting;
3937 if (q[0] == str[0] && q[1] == str[1])
3938 break;
3939 q += 3;
3941 tok = q[2];
3942 } else {
3943 error_pasting:
3944 /* NOTE: because get_tok_str use a static buffer,
3945 we must save it */
3946 cstr_reset(&cstr);
3947 p1 = get_tok_str(tok, &tokc);
3948 cstr_cat(&cstr, p1);
3949 cstr_ccat(&cstr, '\0');
3950 p2 = get_tok_str(t, &cval);
3951 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
3952 /* cannot merge tokens: just add them separately */
3953 tok_str_add2(&macro_str1, tok, &tokc);
3954 /* XXX: free associated memory ? */
3955 tok = t;
3956 tokc = cval;
3961 tok_str_add2(&macro_str1, tok, &tokc);
3962 next_nomacro();
3963 if (tok == 0)
3964 break;
3966 macro_ptr = (int *)saved_macro_ptr;
3967 cstr_free(&cstr);
3968 tok_str_add(&macro_str1, 0);
3969 return macro_str1.str;
3973 /* do macro substitution of macro_str and add result to
3974 (tok_str,tok_len). 'nested_list' is the list of all macros we got
3975 inside to avoid recursing. */
3976 static void macro_subst(TokenString *tok_str,
3977 Sym **nested_list, const int *macro_str)
3979 Sym *s;
3980 int *saved_macro_ptr, *macro_str1;
3981 const int *ptr;
3982 int t, ret;
3983 CValue cval;
3985 /* first scan for '##' operator handling */
3986 ptr = macro_str;
3987 macro_str1 = macro_twosharps(ptr);
3988 if (macro_str1)
3989 ptr = macro_str1;
3990 while (1) {
3991 /* NOTE: ptr == NULL can only happen if tokens are read from
3992 file stream due to a macro function call */
3993 if (ptr == NULL)
3994 break;
3995 TOK_GET(t, ptr, cval);
3996 if (t == 0)
3997 break;
3998 s = define_find(t);
3999 if (s != NULL) {
4000 /* if nested substitution, do nothing */
4001 if (sym_find2(*nested_list, t))
4002 goto no_subst;
4003 saved_macro_ptr = macro_ptr;
4004 macro_ptr = (int *)ptr;
4005 tok = t;
4006 ret = macro_subst_tok(tok_str, nested_list, s);
4007 ptr = (int *)macro_ptr;
4008 macro_ptr = saved_macro_ptr;
4009 if (ret != 0)
4010 goto no_subst;
4011 } else {
4012 no_subst:
4013 tok_str_add2(tok_str, t, &cval);
4016 if (macro_str1)
4017 tok_str_free(macro_str1);
4020 /* return next token with macro substitution */
4021 static void next(void)
4023 Sym *nested_list, *s;
4024 TokenString str;
4026 redo:
4027 next_nomacro();
4028 if (!macro_ptr) {
4029 /* if not reading from macro substituted string, then try
4030 to substitute macros */
4031 if (tok >= TOK_IDENT &&
4032 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4033 s = define_find(tok);
4034 if (s) {
4035 /* we have a macro: we try to substitute */
4036 tok_str_new(&str);
4037 nested_list = NULL;
4038 if (macro_subst_tok(&str, &nested_list, s) == 0) {
4039 /* substitution done, NOTE: maybe empty */
4040 tok_str_add(&str, 0);
4041 macro_ptr = str.str;
4042 macro_ptr_allocated = str.str;
4043 goto redo;
4047 } else {
4048 if (tok == 0) {
4049 /* end of macro or end of unget buffer */
4050 if (unget_buffer_enabled) {
4051 macro_ptr = unget_saved_macro_ptr;
4052 unget_buffer_enabled = 0;
4053 } else {
4054 /* end of macro string: free it */
4055 tok_str_free(macro_ptr_allocated);
4056 macro_ptr = NULL;
4058 goto redo;
4062 /* convert preprocessor tokens into C tokens */
4063 if (tok == TOK_PPNUM &&
4064 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4065 parse_number((char *)tokc.cstr->data);
4069 /* push back current token and set current token to 'last_tok'. Only
4070 identifier case handled for labels. */
4071 static inline void unget_tok(int last_tok)
4073 int i, n;
4074 int *q;
4075 unget_saved_macro_ptr = macro_ptr;
4076 unget_buffer_enabled = 1;
4077 q = unget_saved_buffer;
4078 macro_ptr = q;
4079 *q++ = tok;
4080 n = tok_ext_size(tok) - 1;
4081 for(i=0;i<n;i++)
4082 *q++ = tokc.tab[i];
4083 *q = 0; /* end of token string */
4084 tok = last_tok;
4088 void swap(int *p, int *q)
4090 int t;
4091 t = *p;
4092 *p = *q;
4093 *q = t;
4096 void vsetc(CType *type, int r, CValue *vc)
4098 int v;
4100 if (vtop >= vstack + VSTACK_SIZE)
4101 error("memory full");
4102 /* cannot let cpu flags if other instruction are generated. Also
4103 avoid leaving VT_JMP anywhere except on the top of the stack
4104 because it would complicate the code generator. */
4105 if (vtop >= vstack) {
4106 v = vtop->r & VT_VALMASK;
4107 if (v == VT_CMP || (v & ~1) == VT_JMP)
4108 gv(RC_INT);
4110 vtop++;
4111 vtop->type = *type;
4112 vtop->r = r;
4113 vtop->r2 = VT_CONST;
4114 vtop->c = *vc;
4117 /* push integer constant */
4118 void vpushi(int v)
4120 CValue cval;
4121 cval.i = v;
4122 vsetc(&int_type, VT_CONST, &cval);
4125 /* Return a static symbol pointing to a section */
4126 static Sym *get_sym_ref(CType *type, Section *sec,
4127 unsigned long offset, unsigned long size)
4129 int v;
4130 Sym *sym;
4132 v = anon_sym++;
4133 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4134 sym->type.ref = type->ref;
4135 sym->r = VT_CONST | VT_SYM;
4136 put_extern_sym(sym, sec, offset, size);
4137 return sym;
4140 /* push a reference to a section offset by adding a dummy symbol */
4141 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4143 CValue cval;
4145 cval.ul = 0;
4146 vsetc(type, VT_CONST | VT_SYM, &cval);
4147 vtop->sym = get_sym_ref(type, sec, offset, size);
4150 /* define a new external reference to a symbol 'v' of type 'u' */
4151 static Sym *external_global_sym(int v, CType *type, int r)
4153 Sym *s;
4155 s = sym_find(v);
4156 if (!s) {
4157 /* push forward reference */
4158 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4159 s->type.ref = type->ref;
4160 s->r = r | VT_CONST | VT_SYM;
4162 return s;
4165 /* define a new external reference to a symbol 'v' of type 'u' */
4166 static Sym *external_sym(int v, CType *type, int r)
4168 Sym *s;
4170 s = sym_find(v);
4171 if (!s) {
4172 /* push forward reference */
4173 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4174 s->type.t |= VT_EXTERN;
4175 } else {
4176 if (!is_compatible_types(&s->type, type))
4177 error("incompatible types for redefinition of '%s'",
4178 get_tok_str(v, NULL));
4180 return s;
4183 /* push a reference to global symbol v */
4184 static void vpush_global_sym(CType *type, int v)
4186 Sym *sym;
4187 CValue cval;
4189 sym = external_global_sym(v, type, 0);
4190 cval.ul = 0;
4191 vsetc(type, VT_CONST | VT_SYM, &cval);
4192 vtop->sym = sym;
4195 void vset(CType *type, int r, int v)
4197 CValue cval;
4199 cval.i = v;
4200 vsetc(type, r, &cval);
4203 void vseti(int r, int v)
4205 CType type;
4206 type.t = VT_INT;
4207 vset(&type, r, v);
4210 void vswap(void)
4212 SValue tmp;
4214 tmp = vtop[0];
4215 vtop[0] = vtop[-1];
4216 vtop[-1] = tmp;
4219 void vpushv(SValue *v)
4221 if (vtop >= vstack + VSTACK_SIZE)
4222 error("memory full");
4223 vtop++;
4224 *vtop = *v;
4227 void vdup(void)
4229 vpushv(vtop);
4232 /* save r to the memory stack, and mark it as being free */
4233 void save_reg(int r)
4235 int l, saved, size, align;
4236 SValue *p, sv;
4237 CType *type;
4239 /* modify all stack values */
4240 saved = 0;
4241 l = 0;
4242 for(p=vstack;p<=vtop;p++) {
4243 if ((p->r & VT_VALMASK) == r ||
4244 (p->r2 & VT_VALMASK) == r) {
4245 /* must save value on stack if not already done */
4246 if (!saved) {
4247 /* NOTE: must reload 'r' because r might be equal to r2 */
4248 r = p->r & VT_VALMASK;
4249 /* store register in the stack */
4250 type = &p->type;
4251 if ((p->r & VT_LVAL) ||
4252 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4253 type = &int_type;
4254 size = type_size(type, &align);
4255 loc = (loc - size) & -align;
4256 sv.type.t = type->t;
4257 sv.r = VT_LOCAL | VT_LVAL;
4258 sv.c.ul = loc;
4259 store(r, &sv);
4260 #ifdef TCC_TARGET_I386
4261 /* x86 specific: need to pop fp register ST0 if saved */
4262 if (r == TREG_ST0) {
4263 o(0xd9dd); /* fstp %st(1) */
4265 #endif
4266 /* special long long case */
4267 if ((type->t & VT_BTYPE) == VT_LLONG) {
4268 sv.c.ul += 4;
4269 store(p->r2, &sv);
4271 l = loc;
4272 saved = 1;
4274 /* mark that stack entry as being saved on the stack */
4275 if (p->r & VT_LVAL) {
4276 /* also clear the bounded flag because the
4277 relocation address of the function was stored in
4278 p->c.ul */
4279 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4280 } else {
4281 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4283 p->r2 = VT_CONST;
4284 p->c.ul = l;
4289 /* find a free register of class 'rc'. If none, save one register */
4290 int get_reg(int rc)
4292 int r;
4293 SValue *p;
4295 /* find a free register */
4296 for(r=0;r<NB_REGS;r++) {
4297 if (reg_classes[r] & rc) {
4298 for(p=vstack;p<=vtop;p++) {
4299 if ((p->r & VT_VALMASK) == r ||
4300 (p->r2 & VT_VALMASK) == r)
4301 goto notfound;
4303 return r;
4305 notfound: ;
4308 /* no register left : free the first one on the stack (VERY
4309 IMPORTANT to start from the bottom to ensure that we don't
4310 spill registers used in gen_opi()) */
4311 for(p=vstack;p<=vtop;p++) {
4312 r = p->r & VT_VALMASK;
4313 if (r < VT_CONST && (reg_classes[r] & rc))
4314 goto save_found;
4315 /* also look at second register (if long long) */
4316 r = p->r2 & VT_VALMASK;
4317 if (r < VT_CONST && (reg_classes[r] & rc)) {
4318 save_found:
4319 save_reg(r);
4320 return r;
4323 /* Should never comes here */
4324 return -1;
4327 /* save registers up to (vtop - n) stack entry */
4328 void save_regs(int n)
4330 int r;
4331 SValue *p, *p1;
4332 p1 = vtop - n;
4333 for(p = vstack;p <= p1; p++) {
4334 r = p->r & VT_VALMASK;
4335 if (r < VT_CONST) {
4336 save_reg(r);
4341 /* move register 's' to 'r', and flush previous value of r to memory
4342 if needed */
4343 void move_reg(int r, int s)
4345 SValue sv;
4347 if (r != s) {
4348 save_reg(r);
4349 sv.type.t = VT_INT;
4350 sv.r = s;
4351 sv.c.ul = 0;
4352 load(r, &sv);
4356 /* get address of vtop (vtop MUST BE an lvalue) */
4357 void gaddrof(void)
4359 vtop->r &= ~VT_LVAL;
4360 /* tricky: if saved lvalue, then we can go back to lvalue */
4361 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4362 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4365 #ifdef CONFIG_TCC_BCHECK
4366 /* generate lvalue bound code */
4367 void gbound(void)
4369 int lval_type;
4370 CType type1;
4372 vtop->r &= ~VT_MUSTBOUND;
4373 /* if lvalue, then use checking code before dereferencing */
4374 if (vtop->r & VT_LVAL) {
4375 /* if not VT_BOUNDED value, then make one */
4376 if (!(vtop->r & VT_BOUNDED)) {
4377 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4378 /* must save type because we must set it to int to get pointer */
4379 type1 = vtop->type;
4380 vtop->type.t = VT_INT;
4381 gaddrof();
4382 vpushi(0);
4383 gen_bounded_ptr_add();
4384 vtop->r |= lval_type;
4385 vtop->type = type1;
4387 /* then check for dereferencing */
4388 gen_bounded_ptr_deref();
4391 #endif
4393 /* store vtop a register belonging to class 'rc'. lvalues are
4394 converted to values. Cannot be used if cannot be converted to
4395 register value (such as structures). */
4396 int gv(int rc)
4398 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4399 unsigned long long ll;
4401 /* NOTE: get_reg can modify vstack[] */
4402 if (vtop->type.t & VT_BITFIELD) {
4403 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4404 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4405 /* remove bit field info to avoid loops */
4406 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4407 /* generate shifts */
4408 vpushi(32 - (bit_pos + bit_size));
4409 gen_op(TOK_SHL);
4410 vpushi(32 - bit_size);
4411 /* NOTE: transformed to SHR if unsigned */
4412 gen_op(TOK_SAR);
4413 r = gv(rc);
4414 } else {
4415 if (is_float(vtop->type.t) &&
4416 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4417 Sym *sym;
4418 int *ptr;
4419 unsigned long offset;
4421 /* XXX: unify with initializers handling ? */
4422 /* CPUs usually cannot use float constants, so we store them
4423 generically in data segment */
4424 size = type_size(&vtop->type, &align);
4425 offset = (data_section->data_offset + align - 1) & -align;
4426 data_section->data_offset = offset;
4427 /* XXX: not portable yet */
4428 ptr = section_ptr_add(data_section, size);
4429 size = size >> 2;
4430 for(i=0;i<size;i++)
4431 ptr[i] = vtop->c.tab[i];
4432 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4433 vtop->r |= VT_LVAL | VT_SYM;
4434 vtop->sym = sym;
4435 vtop->c.ul = 0;
4437 #ifdef CONFIG_TCC_BCHECK
4438 if (vtop->r & VT_MUSTBOUND)
4439 gbound();
4440 #endif
4442 r = vtop->r & VT_VALMASK;
4443 /* need to reload if:
4444 - constant
4445 - lvalue (need to dereference pointer)
4446 - already a register, but not in the right class */
4447 if (r >= VT_CONST ||
4448 (vtop->r & VT_LVAL) ||
4449 !(reg_classes[r] & rc) ||
4450 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4451 !(reg_classes[vtop->r2] & rc))) {
4452 r = get_reg(rc);
4453 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4454 /* two register type load : expand to two words
4455 temporarily */
4456 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4457 /* load constant */
4458 ll = vtop->c.ull;
4459 vtop->c.ui = ll; /* first word */
4460 load(r, vtop);
4461 vtop->r = r; /* save register value */
4462 vpushi(ll >> 32); /* second word */
4463 } else if (r >= VT_CONST ||
4464 (vtop->r & VT_LVAL)) {
4465 /* load from memory */
4466 load(r, vtop);
4467 vdup();
4468 vtop[-1].r = r; /* save register value */
4469 /* increment pointer to get second word */
4470 vtop->type.t = VT_INT;
4471 gaddrof();
4472 vpushi(4);
4473 gen_op('+');
4474 vtop->r |= VT_LVAL;
4475 } else {
4476 /* move registers */
4477 load(r, vtop);
4478 vdup();
4479 vtop[-1].r = r; /* save register value */
4480 vtop->r = vtop[-1].r2;
4482 /* allocate second register */
4483 rc2 = RC_INT;
4484 if (rc == RC_IRET)
4485 rc2 = RC_LRET;
4486 r2 = get_reg(rc2);
4487 load(r2, vtop);
4488 vpop();
4489 /* write second register */
4490 vtop->r2 = r2;
4491 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4492 int t1, t;
4493 /* lvalue of scalar type : need to use lvalue type
4494 because of possible cast */
4495 t = vtop->type.t;
4496 t1 = t;
4497 /* compute memory access type */
4498 if (vtop->r & VT_LVAL_BYTE)
4499 t = VT_BYTE;
4500 else if (vtop->r & VT_LVAL_SHORT)
4501 t = VT_SHORT;
4502 if (vtop->r & VT_LVAL_UNSIGNED)
4503 t |= VT_UNSIGNED;
4504 vtop->type.t = t;
4505 load(r, vtop);
4506 /* restore wanted type */
4507 vtop->type.t = t1;
4508 } else {
4509 /* one register type load */
4510 load(r, vtop);
4513 vtop->r = r;
4515 return r;
4518 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4519 void gv2(int rc1, int rc2)
4521 int v;
4523 /* generate more generic register first. But VT_JMP or VT_CMP
4524 values must be generated first in all cases to avoid possible
4525 reload errors */
4526 v = vtop[0].r & VT_VALMASK;
4527 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4528 vswap();
4529 gv(rc1);
4530 vswap();
4531 gv(rc2);
4532 /* test if reload is needed for first register */
4533 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4534 vswap();
4535 gv(rc1);
4536 vswap();
4538 } else {
4539 gv(rc2);
4540 vswap();
4541 gv(rc1);
4542 vswap();
4543 /* test if reload is needed for first register */
4544 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4545 gv(rc2);
4550 /* expand long long on stack in two int registers */
4551 void lexpand(void)
4553 int u;
4555 u = vtop->type.t & VT_UNSIGNED;
4556 gv(RC_INT);
4557 vdup();
4558 vtop[0].r = vtop[-1].r2;
4559 vtop[0].r2 = VT_CONST;
4560 vtop[-1].r2 = VT_CONST;
4561 vtop[0].type.t = VT_INT | u;
4562 vtop[-1].type.t = VT_INT | u;
4565 /* build a long long from two ints */
4566 void lbuild(int t)
4568 gv2(RC_INT, RC_INT);
4569 vtop[-1].r2 = vtop[0].r;
4570 vtop[-1].type.t = t;
4571 vpop();
4574 /* rotate n first stack elements to the bottom */
4575 void vrotb(int n)
4577 int i;
4578 SValue tmp;
4580 tmp = vtop[-n + 1];
4581 for(i=-n+1;i!=0;i++)
4582 vtop[i] = vtop[i+1];
4583 vtop[0] = tmp;
4586 /* pop stack value */
4587 void vpop(void)
4589 int v;
4590 v = vtop->r & VT_VALMASK;
4591 #ifdef TCC_TARGET_I386
4592 /* for x86, we need to pop the FP stack */
4593 if (v == TREG_ST0 && !nocode_wanted) {
4594 o(0xd9dd); /* fstp %st(1) */
4595 } else
4596 #endif
4597 if (v == VT_JMP || v == VT_JMPI) {
4598 /* need to put correct jump if && or || without test */
4599 gsym(vtop->c.ul);
4601 vtop--;
4604 /* convert stack entry to register and duplicate its value in another
4605 register */
4606 void gv_dup(void)
4608 int rc, t, r, r1;
4609 SValue sv;
4611 t = vtop->type.t;
4612 if ((t & VT_BTYPE) == VT_LLONG) {
4613 lexpand();
4614 gv_dup();
4615 vswap();
4616 vrotb(3);
4617 gv_dup();
4618 vrotb(4);
4619 /* stack: H L L1 H1 */
4620 lbuild(t);
4621 vrotb(3);
4622 vrotb(3);
4623 vswap();
4624 lbuild(t);
4625 vswap();
4626 } else {
4627 /* duplicate value */
4628 rc = RC_INT;
4629 sv.type.t = VT_INT;
4630 if (is_float(t)) {
4631 rc = RC_FLOAT;
4632 sv.type.t = t;
4634 r = gv(rc);
4635 r1 = get_reg(rc);
4636 sv.r = r;
4637 sv.c.ul = 0;
4638 load(r1, &sv); /* move r to r1 */
4639 vdup();
4640 /* duplicates value */
4641 vtop->r = r1;
4645 /* generate CPU independent (unsigned) long long operations */
4646 void gen_opl(int op)
4648 int t, a, b, op1, c, i;
4649 int func;
4650 GFuncContext gf;
4651 SValue tmp;
4653 switch(op) {
4654 case '/':
4655 case TOK_PDIV:
4656 func = TOK___divdi3;
4657 goto gen_func;
4658 case TOK_UDIV:
4659 func = TOK___udivdi3;
4660 goto gen_func;
4661 case '%':
4662 func = TOK___moddi3;
4663 goto gen_func;
4664 case TOK_UMOD:
4665 func = TOK___umoddi3;
4666 gen_func:
4667 /* call generic long long function */
4668 gfunc_start(&gf, FUNC_CDECL);
4669 gfunc_param(&gf);
4670 gfunc_param(&gf);
4671 vpush_global_sym(&func_old_type, func);
4672 gfunc_call(&gf);
4673 vpushi(0);
4674 vtop->r = REG_IRET;
4675 vtop->r2 = REG_LRET;
4676 break;
4677 case '^':
4678 case '&':
4679 case '|':
4680 case '*':
4681 case '+':
4682 case '-':
4683 t = vtop->type.t;
4684 vswap();
4685 lexpand();
4686 vrotb(3);
4687 lexpand();
4688 /* stack: L1 H1 L2 H2 */
4689 tmp = vtop[0];
4690 vtop[0] = vtop[-3];
4691 vtop[-3] = tmp;
4692 tmp = vtop[-2];
4693 vtop[-2] = vtop[-3];
4694 vtop[-3] = tmp;
4695 vswap();
4696 /* stack: H1 H2 L1 L2 */
4697 if (op == '*') {
4698 vpushv(vtop - 1);
4699 vpushv(vtop - 1);
4700 gen_op(TOK_UMULL);
4701 lexpand();
4702 /* stack: H1 H2 L1 L2 ML MH */
4703 for(i=0;i<4;i++)
4704 vrotb(6);
4705 /* stack: ML MH H1 H2 L1 L2 */
4706 tmp = vtop[0];
4707 vtop[0] = vtop[-2];
4708 vtop[-2] = tmp;
4709 /* stack: ML MH H1 L2 H2 L1 */
4710 gen_op('*');
4711 vrotb(3);
4712 vrotb(3);
4713 gen_op('*');
4714 /* stack: ML MH M1 M2 */
4715 gen_op('+');
4716 gen_op('+');
4717 } else if (op == '+' || op == '-') {
4718 /* XXX: add non carry method too (for MIPS or alpha) */
4719 if (op == '+')
4720 op1 = TOK_ADDC1;
4721 else
4722 op1 = TOK_SUBC1;
4723 gen_op(op1);
4724 /* stack: H1 H2 (L1 op L2) */
4725 vrotb(3);
4726 vrotb(3);
4727 gen_op(op1 + 1); /* TOK_xxxC2 */
4728 } else {
4729 gen_op(op);
4730 /* stack: H1 H2 (L1 op L2) */
4731 vrotb(3);
4732 vrotb(3);
4733 /* stack: (L1 op L2) H1 H2 */
4734 gen_op(op);
4735 /* stack: (L1 op L2) (H1 op H2) */
4737 /* stack: L H */
4738 lbuild(t);
4739 break;
4740 case TOK_SAR:
4741 case TOK_SHR:
4742 case TOK_SHL:
4743 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4744 t = vtop[-1].type.t;
4745 vswap();
4746 lexpand();
4747 vrotb(3);
4748 /* stack: L H shift */
4749 c = (int)vtop->c.i;
4750 /* constant: simpler */
4751 /* NOTE: all comments are for SHL. the other cases are
4752 done by swaping words */
4753 vpop();
4754 if (op != TOK_SHL)
4755 vswap();
4756 if (c >= 32) {
4757 /* stack: L H */
4758 vpop();
4759 if (c > 32) {
4760 vpushi(c - 32);
4761 gen_op(op);
4763 if (op != TOK_SAR) {
4764 vpushi(0);
4765 } else {
4766 gv_dup();
4767 vpushi(31);
4768 gen_op(TOK_SAR);
4770 vswap();
4771 } else {
4772 vswap();
4773 gv_dup();
4774 /* stack: H L L */
4775 vpushi(c);
4776 gen_op(op);
4777 vswap();
4778 vpushi(32 - c);
4779 if (op == TOK_SHL)
4780 gen_op(TOK_SHR);
4781 else
4782 gen_op(TOK_SHL);
4783 vrotb(3);
4784 /* stack: L L H */
4785 vpushi(c);
4786 if (op == TOK_SHL)
4787 gen_op(TOK_SHL);
4788 else
4789 gen_op(TOK_SHR);
4790 gen_op('|');
4792 if (op != TOK_SHL)
4793 vswap();
4794 lbuild(t);
4795 } else {
4796 /* XXX: should provide a faster fallback on x86 ? */
4797 switch(op) {
4798 case TOK_SAR:
4799 func = TOK___sardi3;
4800 goto gen_func;
4801 case TOK_SHR:
4802 func = TOK___shrdi3;
4803 goto gen_func;
4804 case TOK_SHL:
4805 func = TOK___shldi3;
4806 goto gen_func;
4809 break;
4810 default:
4811 /* compare operations */
4812 t = vtop->type.t;
4813 vswap();
4814 lexpand();
4815 vrotb(3);
4816 lexpand();
4817 /* stack: L1 H1 L2 H2 */
4818 tmp = vtop[-1];
4819 vtop[-1] = vtop[-2];
4820 vtop[-2] = tmp;
4821 /* stack: L1 L2 H1 H2 */
4822 /* compare high */
4823 op1 = op;
4824 /* when values are equal, we need to compare low words. since
4825 the jump is inverted, we invert the test too. */
4826 if (op1 == TOK_LT)
4827 op1 = TOK_LE;
4828 else if (op1 == TOK_GT)
4829 op1 = TOK_GE;
4830 else if (op1 == TOK_ULT)
4831 op1 = TOK_ULE;
4832 else if (op1 == TOK_UGT)
4833 op1 = TOK_UGE;
4834 a = 0;
4835 b = 0;
4836 gen_op(op1);
4837 if (op1 != TOK_NE) {
4838 a = gtst(1, 0);
4840 if (op != TOK_EQ) {
4841 /* generate non equal test */
4842 /* XXX: NOT PORTABLE yet */
4843 if (a == 0) {
4844 b = gtst(0, 0);
4845 } else {
4846 #ifdef TCC_TARGET_I386
4847 b = psym(0x850f, 0);
4848 #else
4849 error("not implemented");
4850 #endif
4853 /* compare low. Always unsigned */
4854 op1 = op;
4855 if (op1 == TOK_LT)
4856 op1 = TOK_ULT;
4857 else if (op1 == TOK_LE)
4858 op1 = TOK_ULE;
4859 else if (op1 == TOK_GT)
4860 op1 = TOK_UGT;
4861 else if (op1 == TOK_GE)
4862 op1 = TOK_UGE;
4863 gen_op(op1);
4864 a = gtst(1, a);
4865 gsym(b);
4866 vseti(VT_JMPI, a);
4867 break;
4871 /* handle integer constant optimizations and various machine
4872 independent opt */
4873 void gen_opic(int op)
4875 int fc, c1, c2, n;
4876 SValue *v1, *v2;
4878 v1 = vtop - 1;
4879 v2 = vtop;
4880 /* currently, we cannot do computations with forward symbols */
4881 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4882 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4883 if (c1 && c2) {
4884 fc = v2->c.i;
4885 switch(op) {
4886 case '+': v1->c.i += fc; break;
4887 case '-': v1->c.i -= fc; break;
4888 case '&': v1->c.i &= fc; break;
4889 case '^': v1->c.i ^= fc; break;
4890 case '|': v1->c.i |= fc; break;
4891 case '*': v1->c.i *= fc; break;
4893 case TOK_PDIV:
4894 case '/':
4895 case '%':
4896 case TOK_UDIV:
4897 case TOK_UMOD:
4898 /* if division by zero, generate explicit division */
4899 if (fc == 0) {
4900 if (const_wanted)
4901 error("division by zero in constant");
4902 goto general_case;
4904 switch(op) {
4905 default: v1->c.i /= fc; break;
4906 case '%': v1->c.i %= fc; break;
4907 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
4908 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
4910 break;
4911 case TOK_SHL: v1->c.i <<= fc; break;
4912 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
4913 case TOK_SAR: v1->c.i >>= fc; break;
4914 /* tests */
4915 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
4916 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
4917 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
4918 case TOK_NE: v1->c.i = v1->c.i != fc; break;
4919 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
4920 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
4921 case TOK_LT: v1->c.i = v1->c.i < fc; break;
4922 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
4923 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
4924 case TOK_GT: v1->c.i = v1->c.i > fc; break;
4925 /* logical */
4926 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
4927 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
4928 default:
4929 goto general_case;
4931 vtop--;
4932 } else {
4933 /* if commutative ops, put c2 as constant */
4934 if (c1 && (op == '+' || op == '&' || op == '^' ||
4935 op == '|' || op == '*')) {
4936 vswap();
4937 swap(&c1, &c2);
4939 fc = vtop->c.i;
4940 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
4941 op == TOK_PDIV) &&
4942 fc == 1) ||
4943 ((op == '+' || op == '-' || op == '|' || op == '^' ||
4944 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
4945 fc == 0) ||
4946 (op == '&' &&
4947 fc == -1))) {
4948 /* nothing to do */
4949 vtop--;
4950 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
4951 /* try to use shifts instead of muls or divs */
4952 if (fc > 0 && (fc & (fc - 1)) == 0) {
4953 n = -1;
4954 while (fc) {
4955 fc >>= 1;
4956 n++;
4958 vtop->c.i = n;
4959 if (op == '*')
4960 op = TOK_SHL;
4961 else if (op == TOK_PDIV)
4962 op = TOK_SAR;
4963 else
4964 op = TOK_SHR;
4966 goto general_case;
4967 } else if (c2 && (op == '+' || op == '-') &&
4968 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
4969 (VT_CONST | VT_SYM)) {
4970 /* symbol + constant case */
4971 if (op == '-')
4972 fc = -fc;
4973 vtop--;
4974 vtop->c.i += fc;
4975 } else {
4976 general_case:
4977 if (!nocode_wanted) {
4978 /* call low level op generator */
4979 gen_opi(op);
4980 } else {
4981 vtop--;
4987 /* generate a floating point operation with constant propagation */
4988 void gen_opif(int op)
4990 int c1, c2;
4991 SValue *v1, *v2;
4992 long double f1, f2;
4994 v1 = vtop - 1;
4995 v2 = vtop;
4996 /* currently, we cannot do computations with forward symbols */
4997 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4998 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4999 if (c1 && c2) {
5000 if (v1->type.t == VT_FLOAT) {
5001 f1 = v1->c.f;
5002 f2 = v2->c.f;
5003 } else if (v1->type.t == VT_DOUBLE) {
5004 f1 = v1->c.d;
5005 f2 = v2->c.d;
5006 } else {
5007 f1 = v1->c.ld;
5008 f2 = v2->c.ld;
5011 /* NOTE: we only do constant propagation if finite number (not
5012 NaN or infinity) (ANSI spec) */
5013 if (!ieee_finite(f1) || !ieee_finite(f2))
5014 goto general_case;
5016 switch(op) {
5017 case '+': f1 += f2; break;
5018 case '-': f1 -= f2; break;
5019 case '*': f1 *= f2; break;
5020 case '/':
5021 if (f2 == 0.0) {
5022 if (const_wanted)
5023 error("division by zero in constant");
5024 goto general_case;
5026 f1 /= f2;
5027 break;
5028 /* XXX: also handles tests ? */
5029 default:
5030 goto general_case;
5032 /* XXX: overflow test ? */
5033 if (v1->type.t == VT_FLOAT) {
5034 v1->c.f = f1;
5035 } else if (v1->type.t == VT_DOUBLE) {
5036 v1->c.d = f1;
5037 } else {
5038 v1->c.ld = f1;
5040 vtop--;
5041 } else {
5042 general_case:
5043 if (!nocode_wanted) {
5044 gen_opf(op);
5045 } else {
5046 vtop--;
5051 static int pointed_size(CType *type)
5053 int align;
5054 return type_size(pointed_type(type), &align);
5057 #if 0
5058 void check_pointer_types(SValue *p1, SValue *p2)
5060 char buf1[256], buf2[256];
5061 int t1, t2;
5062 t1 = p1->t;
5063 t2 = p2->t;
5064 if (!is_compatible_types(t1, t2)) {
5065 type_to_str(buf1, sizeof(buf1), t1, NULL);
5066 type_to_str(buf2, sizeof(buf2), t2, NULL);
5067 error("incompatible pointers '%s' and '%s'", buf1, buf2);
5070 #endif
5072 /* generic gen_op: handles types problems */
5073 void gen_op(int op)
5075 int u, t1, t2, bt1, bt2, t;
5076 CType type1;
5078 t1 = vtop[-1].type.t;
5079 t2 = vtop[0].type.t;
5080 bt1 = t1 & VT_BTYPE;
5081 bt2 = t2 & VT_BTYPE;
5083 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5084 /* at least one operand is a pointer */
5085 /* relationnal op: must be both pointers */
5086 if (op >= TOK_ULT && op <= TOK_GT) {
5087 // check_pointer_types(vtop, vtop - 1);
5088 /* pointers are handled are unsigned */
5089 t = VT_INT | VT_UNSIGNED;
5090 goto std_op;
5092 /* if both pointers, then it must be the '-' op */
5093 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5094 if (op != '-')
5095 error("cannot use pointers here");
5096 // check_pointer_types(vtop - 1, vtop);
5097 /* XXX: check that types are compatible */
5098 u = pointed_size(&vtop[-1].type);
5099 gen_opic(op);
5100 /* set to integer type */
5101 vtop->type.t = VT_INT;
5102 vpushi(u);
5103 gen_op(TOK_PDIV);
5104 } else {
5105 /* exactly one pointer : must be '+' or '-'. */
5106 if (op != '-' && op != '+')
5107 error("cannot use pointers here");
5108 /* Put pointer as first operand */
5109 if (bt2 == VT_PTR) {
5110 vswap();
5111 swap(&t1, &t2);
5113 type1 = vtop[-1].type;
5114 /* XXX: cast to int ? (long long case) */
5115 vpushi(pointed_size(&vtop[-1].type));
5116 gen_op('*');
5117 #ifdef CONFIG_TCC_BCHECK
5118 /* if evaluating constant expression, no code should be
5119 generated, so no bound check */
5120 if (do_bounds_check && !const_wanted) {
5121 /* if bounded pointers, we generate a special code to
5122 test bounds */
5123 if (op == '-') {
5124 vpushi(0);
5125 vswap();
5126 gen_op('-');
5128 gen_bounded_ptr_add();
5129 } else
5130 #endif
5132 gen_opic(op);
5134 /* put again type if gen_opic() swaped operands */
5135 vtop->type = type1;
5137 } else if (is_float(bt1) || is_float(bt2)) {
5138 /* compute bigger type and do implicit casts */
5139 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5140 t = VT_LDOUBLE;
5141 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5142 t = VT_DOUBLE;
5143 } else {
5144 t = VT_FLOAT;
5146 /* floats can only be used for a few operations */
5147 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5148 (op < TOK_ULT || op > TOK_GT))
5149 error("invalid operands for binary operation");
5150 goto std_op;
5151 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5152 /* cast to biggest op */
5153 t = VT_LLONG;
5154 /* convert to unsigned if it does not fit in a long long */
5155 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5156 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5157 t |= VT_UNSIGNED;
5158 goto std_op;
5159 } else {
5160 /* integer operations */
5161 t = VT_INT;
5162 /* convert to unsigned if it does not fit in an integer */
5163 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5164 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5165 t |= VT_UNSIGNED;
5166 std_op:
5167 /* XXX: currently, some unsigned operations are explicit, so
5168 we modify them here */
5169 if (t & VT_UNSIGNED) {
5170 if (op == TOK_SAR)
5171 op = TOK_SHR;
5172 else if (op == '/')
5173 op = TOK_UDIV;
5174 else if (op == '%')
5175 op = TOK_UMOD;
5176 else if (op == TOK_LT)
5177 op = TOK_ULT;
5178 else if (op == TOK_GT)
5179 op = TOK_UGT;
5180 else if (op == TOK_LE)
5181 op = TOK_ULE;
5182 else if (op == TOK_GE)
5183 op = TOK_UGE;
5185 vswap();
5186 type1.t = t;
5187 gen_cast(&type1);
5188 vswap();
5189 /* special case for shifts and long long: we keep the shift as
5190 an integer */
5191 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5192 type1.t = VT_INT;
5193 gen_cast(&type1);
5194 if (is_float(t))
5195 gen_opif(op);
5196 else if ((t & VT_BTYPE) == VT_LLONG)
5197 gen_opl(op);
5198 else
5199 gen_opic(op);
5200 if (op >= TOK_ULT && op <= TOK_GT) {
5201 /* relationnal op: the result is an int */
5202 vtop->type.t = VT_INT;
5203 } else {
5204 vtop->type.t = t;
5209 /* generic itof for unsigned long long case */
5210 void gen_cvt_itof1(int t)
5212 GFuncContext gf;
5214 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5215 (VT_LLONG | VT_UNSIGNED)) {
5217 gfunc_start(&gf, FUNC_CDECL);
5218 gfunc_param(&gf);
5219 if (t == VT_FLOAT)
5220 vpush_global_sym(&func_old_type, TOK___ulltof);
5221 else if (t == VT_DOUBLE)
5222 vpush_global_sym(&func_old_type, TOK___ulltod);
5223 else
5224 vpush_global_sym(&func_old_type, TOK___ulltold);
5225 gfunc_call(&gf);
5226 vpushi(0);
5227 vtop->r = REG_FRET;
5228 } else {
5229 gen_cvt_itof(t);
5233 /* generic ftoi for unsigned long long case */
5234 void gen_cvt_ftoi1(int t)
5236 GFuncContext gf;
5237 int st;
5239 if (t == (VT_LLONG | VT_UNSIGNED)) {
5240 /* not handled natively */
5241 gfunc_start(&gf, FUNC_CDECL);
5242 st = vtop->type.t & VT_BTYPE;
5243 gfunc_param(&gf);
5244 if (st == VT_FLOAT)
5245 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5246 else if (st == VT_DOUBLE)
5247 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5248 else
5249 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5250 gfunc_call(&gf);
5251 vpushi(0);
5252 vtop->r = REG_IRET;
5253 vtop->r2 = REG_LRET;
5254 } else {
5255 gen_cvt_ftoi(t);
5259 /* force char or short cast */
5260 void force_charshort_cast(int t)
5262 int bits, dbt;
5263 dbt = t & VT_BTYPE;
5264 /* XXX: add optimization if lvalue : just change type and offset */
5265 if (dbt == VT_BYTE)
5266 bits = 8;
5267 else
5268 bits = 16;
5269 if (t & VT_UNSIGNED) {
5270 vpushi((1 << bits) - 1);
5271 gen_op('&');
5272 } else {
5273 bits = 32 - bits;
5274 vpushi(bits);
5275 gen_op(TOK_SHL);
5276 vpushi(bits);
5277 gen_op(TOK_SAR);
5281 /* cast 'vtop' to 'type' */
5282 static void gen_cast(CType *type)
5284 int sbt, dbt, sf, df, c;
5286 /* special delayed cast for char/short */
5287 /* XXX: in some cases (multiple cascaded casts), it may still
5288 be incorrect */
5289 if (vtop->r & VT_MUSTCAST) {
5290 vtop->r &= ~VT_MUSTCAST;
5291 force_charshort_cast(vtop->type.t);
5294 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5295 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5297 if (sbt != dbt && !nocode_wanted) {
5298 sf = is_float(sbt);
5299 df = is_float(dbt);
5300 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5301 if (sf && df) {
5302 /* convert from fp to fp */
5303 if (c) {
5304 /* constant case: we can do it now */
5305 /* XXX: in ISOC, cannot do it if error in convert */
5306 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5307 vtop->c.f = (float)vtop->c.d;
5308 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5309 vtop->c.f = (float)vtop->c.ld;
5310 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5311 vtop->c.d = (double)vtop->c.f;
5312 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5313 vtop->c.d = (double)vtop->c.ld;
5314 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5315 vtop->c.ld = (long double)vtop->c.f;
5316 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5317 vtop->c.ld = (long double)vtop->c.d;
5318 } else {
5319 /* non constant case: generate code */
5320 gen_cvt_ftof(dbt);
5322 } else if (df) {
5323 /* convert int to fp */
5324 if (c) {
5325 switch(sbt) {
5326 case VT_LLONG | VT_UNSIGNED:
5327 case VT_LLONG:
5328 /* XXX: add const cases for long long */
5329 goto do_itof;
5330 case VT_INT | VT_UNSIGNED:
5331 switch(dbt) {
5332 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5333 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5334 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5336 break;
5337 default:
5338 switch(dbt) {
5339 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5340 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5341 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5343 break;
5345 } else {
5346 do_itof:
5347 gen_cvt_itof1(dbt);
5349 } else if (sf) {
5350 /* convert fp to int */
5351 /* we handle char/short/etc... with generic code */
5352 if (dbt != (VT_INT | VT_UNSIGNED) &&
5353 dbt != (VT_LLONG | VT_UNSIGNED) &&
5354 dbt != VT_LLONG)
5355 dbt = VT_INT;
5356 if (c) {
5357 switch(dbt) {
5358 case VT_LLONG | VT_UNSIGNED:
5359 case VT_LLONG:
5360 /* XXX: add const cases for long long */
5361 goto do_ftoi;
5362 case VT_INT | VT_UNSIGNED:
5363 switch(sbt) {
5364 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5365 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5366 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5368 break;
5369 default:
5370 /* int case */
5371 switch(sbt) {
5372 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5373 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5374 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5376 break;
5378 } else {
5379 do_ftoi:
5380 gen_cvt_ftoi1(dbt);
5382 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5383 /* additional cast for char/short/bool... */
5384 vtop->type.t = dbt;
5385 gen_cast(type);
5387 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5388 if ((sbt & VT_BTYPE) != VT_LLONG) {
5389 /* scalar to long long */
5390 if (c) {
5391 if (sbt == (VT_INT | VT_UNSIGNED))
5392 vtop->c.ll = vtop->c.ui;
5393 else
5394 vtop->c.ll = vtop->c.i;
5395 } else {
5396 /* machine independent conversion */
5397 gv(RC_INT);
5398 /* generate high word */
5399 if (sbt == (VT_INT | VT_UNSIGNED)) {
5400 vpushi(0);
5401 gv(RC_INT);
5402 } else {
5403 gv_dup();
5404 vpushi(31);
5405 gen_op(TOK_SAR);
5407 /* patch second register */
5408 vtop[-1].r2 = vtop->r;
5409 vpop();
5412 } else if (dbt == VT_BOOL) {
5413 /* scalar to bool */
5414 vpushi(0);
5415 gen_op(TOK_NE);
5416 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5417 (dbt & VT_BTYPE) == VT_SHORT) {
5418 force_charshort_cast(dbt);
5419 } else if ((dbt & VT_BTYPE) == VT_INT) {
5420 /* scalar to int */
5421 if (sbt == VT_LLONG) {
5422 /* from long long: just take low order word */
5423 lexpand();
5424 vpop();
5426 /* if lvalue and single word type, nothing to do because
5427 the lvalue already contains the real type size (see
5428 VT_LVAL_xxx constants) */
5431 vtop->type = *type;
5434 /* return type size. Put alignment at 'a' */
5435 static int type_size(CType *type, int *a)
5437 Sym *s;
5438 int bt;
5440 bt = type->t & VT_BTYPE;
5441 if (bt == VT_STRUCT) {
5442 /* struct/union */
5443 s = type->ref;
5444 *a = s->r;
5445 return s->c;
5446 } else if (bt == VT_PTR) {
5447 if (type->t & VT_ARRAY) {
5448 s = type->ref;
5449 return type_size(&s->type, a) * s->c;
5450 } else {
5451 *a = PTR_SIZE;
5452 return PTR_SIZE;
5454 } else if (bt == VT_LDOUBLE) {
5455 *a = LDOUBLE_ALIGN;
5456 return LDOUBLE_SIZE;
5457 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5458 *a = 4; /* XXX: i386 specific */
5459 return 8;
5460 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5461 *a = 4;
5462 return 4;
5463 } else if (bt == VT_SHORT) {
5464 *a = 2;
5465 return 2;
5466 } else {
5467 /* char, void, function, _Bool */
5468 *a = 1;
5469 return 1;
5473 /* return the pointed type of t */
5474 static inline CType *pointed_type(CType *type)
5476 return &type->ref->type;
5479 /* modify type so that its it is a pointer to type. */
5480 static void mk_pointer(CType *type)
5482 Sym *s;
5483 s = sym_push(SYM_FIELD, type, 0, -1);
5484 type->t = VT_PTR | (type->t & ~VT_TYPE);
5485 type->ref = s;
5488 static int is_compatible_types(CType *type1, CType *type2)
5490 Sym *s1, *s2;
5491 int bt1, bt2, t1, t2;
5493 t1 = type1->t & VT_TYPE;
5494 t2 = type2->t & VT_TYPE;
5495 bt1 = t1 & VT_BTYPE;
5496 bt2 = t2 & VT_BTYPE;
5497 if (bt1 == VT_PTR) {
5498 type1 = pointed_type(type1);
5499 /* if function, then convert implicitely to function pointer */
5500 if (bt2 != VT_FUNC) {
5501 if (bt2 != VT_PTR)
5502 return 0;
5503 type2 = pointed_type(type2);
5505 /* void matches everything */
5506 /* XXX: not fully compliant */
5507 if ((type1->t & VT_TYPE) == VT_VOID || (type2->t & VT_TYPE) == VT_VOID)
5508 return 1;
5509 return is_compatible_types(type1, type2);
5510 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
5511 return (type1->ref == type2->ref);
5512 } else if (bt1 == VT_FUNC) {
5513 if (bt2 != VT_FUNC)
5514 return 0;
5515 s1 = type1->ref;
5516 s2 = type2->ref;
5517 if (!is_compatible_types(&s1->type, &s2->type))
5518 return 0;
5519 /* XXX: not complete */
5520 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5521 return 1;
5522 if (s1->c != s2->c)
5523 return 0;
5524 while (s1 != NULL) {
5525 if (s2 == NULL)
5526 return 0;
5527 if (!is_compatible_types(&s1->type, &s2->type))
5528 return 0;
5529 s1 = s1->next;
5530 s2 = s2->next;
5532 if (s2)
5533 return 0;
5534 return 1;
5535 } else {
5536 /* XXX: not complete */
5537 return 1;
5541 /* print a type. If 'varstr' is not NULL, then the variable is also
5542 printed in the type */
5543 /* XXX: union */
5544 /* XXX: add array and function pointers */
5545 void type_to_str(char *buf, int buf_size,
5546 CType *type, const char *varstr)
5548 int bt, v, t;
5549 Sym *s, *sa;
5550 char buf1[256];
5551 const char *tstr;
5553 t = type->t & VT_TYPE;
5554 bt = t & VT_BTYPE;
5555 buf[0] = '\0';
5556 if (t & VT_UNSIGNED)
5557 pstrcat(buf, buf_size, "unsigned ");
5558 switch(bt) {
5559 case VT_VOID:
5560 tstr = "void";
5561 goto add_tstr;
5562 case VT_BOOL:
5563 tstr = "_Bool";
5564 goto add_tstr;
5565 case VT_BYTE:
5566 tstr = "char";
5567 goto add_tstr;
5568 case VT_SHORT:
5569 tstr = "short";
5570 goto add_tstr;
5571 case VT_INT:
5572 tstr = "int";
5573 goto add_tstr;
5574 case VT_LONG:
5575 tstr = "long";
5576 goto add_tstr;
5577 case VT_LLONG:
5578 tstr = "long long";
5579 goto add_tstr;
5580 case VT_FLOAT:
5581 tstr = "float";
5582 goto add_tstr;
5583 case VT_DOUBLE:
5584 tstr = "double";
5585 goto add_tstr;
5586 case VT_LDOUBLE:
5587 tstr = "long double";
5588 add_tstr:
5589 pstrcat(buf, buf_size, tstr);
5590 break;
5591 case VT_ENUM:
5592 case VT_STRUCT:
5593 if (bt == VT_STRUCT)
5594 tstr = "struct ";
5595 else
5596 tstr = "enum ";
5597 pstrcat(buf, buf_size, tstr);
5598 v = type->ref->v & ~SYM_STRUCT;
5599 if (v >= SYM_FIRST_ANOM)
5600 pstrcat(buf, buf_size, "<anonymous>");
5601 else
5602 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5603 break;
5604 case VT_FUNC:
5605 s = type->ref;
5606 type_to_str(buf, buf_size, &s->type, varstr);
5607 pstrcat(buf, buf_size, "(");
5608 sa = s->next;
5609 while (sa != NULL) {
5610 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5611 pstrcat(buf, buf_size, buf1);
5612 sa = sa->next;
5613 if (sa)
5614 pstrcat(buf, buf_size, ", ");
5616 pstrcat(buf, buf_size, ")");
5617 goto no_var;
5618 case VT_PTR:
5619 s = type->ref;
5620 pstrcpy(buf1, sizeof(buf1), "*");
5621 if (varstr)
5622 pstrcat(buf1, sizeof(buf1), varstr);
5623 type_to_str(buf, buf_size, &s->type, buf1);
5624 goto no_var;
5626 if (varstr) {
5627 pstrcat(buf, buf_size, " ");
5628 pstrcat(buf, buf_size, varstr);
5630 no_var: ;
5633 /* verify type compatibility to store vtop in 'dt' type, and generate
5634 casts if needed. */
5635 static void gen_assign_cast(CType *dt)
5637 CType *st;
5638 char buf1[256], buf2[256];
5639 int dbt, sbt;
5641 st = &vtop->type; /* source type */
5642 dbt = dt->t & VT_BTYPE;
5643 sbt = st->t & VT_BTYPE;
5644 if (dbt == VT_PTR) {
5645 /* special cases for pointers */
5646 /* a function is implicitely a function pointer */
5647 if (sbt == VT_FUNC) {
5648 if (!is_compatible_types(pointed_type(dt), st))
5649 goto error;
5650 else
5651 goto type_ok;
5653 /* '0' can also be a pointer */
5654 if (sbt == VT_INT &&
5655 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) &&
5656 vtop->c.i == 0)
5657 goto type_ok;
5658 /* accept implicit pointer to integer cast with warning */
5659 if (sbt == VT_BYTE || sbt == VT_SHORT ||
5660 sbt == VT_INT || sbt == VT_LLONG) {
5661 warning("assignment makes pointer from integer without a cast");
5662 goto type_ok;
5664 } else if (dbt == VT_BYTE || dbt == VT_SHORT ||
5665 dbt == VT_INT || dbt == VT_LLONG) {
5666 if (sbt == VT_PTR || sbt == VT_FUNC) {
5667 warning("assignment makes integer from pointer without a cast");
5668 goto type_ok;
5671 if (!is_compatible_types(dt, st)) {
5672 error:
5673 type_to_str(buf1, sizeof(buf1), st, NULL);
5674 type_to_str(buf2, sizeof(buf2), dt, NULL);
5675 error("cannot cast '%s' to '%s'", buf1, buf2);
5677 type_ok:
5678 gen_cast(dt);
5681 /* store vtop in lvalue pushed on stack */
5682 void vstore(void)
5684 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5685 GFuncContext gf;
5687 ft = vtop[-1].type.t;
5688 sbt = vtop->type.t & VT_BTYPE;
5689 dbt = ft & VT_BTYPE;
5690 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5691 (sbt == VT_INT && dbt == VT_SHORT)) {
5692 /* optimize char/short casts */
5693 delayed_cast = VT_MUSTCAST;
5694 vtop->type.t = ft & VT_TYPE;
5695 } else {
5696 delayed_cast = 0;
5697 gen_assign_cast(&vtop[-1].type);
5700 if (sbt == VT_STRUCT) {
5701 /* if structure, only generate pointer */
5702 /* structure assignment : generate memcpy */
5703 /* XXX: optimize if small size */
5704 if (!nocode_wanted) {
5705 vdup();
5706 gfunc_start(&gf, FUNC_CDECL);
5707 /* type size */
5708 size = type_size(&vtop->type, &align);
5709 vpushi(size);
5710 gfunc_param(&gf);
5711 /* source */
5712 vtop->type.t = VT_INT;
5713 gaddrof();
5714 gfunc_param(&gf);
5715 /* destination */
5716 vswap();
5717 vtop->type.t = VT_INT;
5718 gaddrof();
5719 gfunc_param(&gf);
5721 save_regs(0);
5722 vpush_global_sym(&func_old_type, TOK_memcpy);
5723 gfunc_call(&gf);
5724 } else {
5725 vswap();
5726 vpop();
5728 /* leave source on stack */
5729 } else if (ft & VT_BITFIELD) {
5730 /* bitfield store handling */
5731 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5732 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5733 /* remove bit field info to avoid loops */
5734 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5736 /* duplicate destination */
5737 vdup();
5738 vtop[-1] = vtop[-2];
5740 /* mask and shift source */
5741 vpushi((1 << bit_size) - 1);
5742 gen_op('&');
5743 vpushi(bit_pos);
5744 gen_op(TOK_SHL);
5745 /* load destination, mask and or with source */
5746 vswap();
5747 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5748 gen_op('&');
5749 gen_op('|');
5750 /* store result */
5751 vstore();
5752 } else {
5753 #ifdef CONFIG_TCC_BCHECK
5754 /* bound check case */
5755 if (vtop[-1].r & VT_MUSTBOUND) {
5756 vswap();
5757 gbound();
5758 vswap();
5760 #endif
5761 if (!nocode_wanted) {
5762 rc = RC_INT;
5763 if (is_float(ft))
5764 rc = RC_FLOAT;
5765 r = gv(rc); /* generate value */
5766 /* if lvalue was saved on stack, must read it */
5767 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5768 SValue sv;
5769 t = get_reg(RC_INT);
5770 sv.type.t = VT_INT;
5771 sv.r = VT_LOCAL | VT_LVAL;
5772 sv.c.ul = vtop[-1].c.ul;
5773 load(t, &sv);
5774 vtop[-1].r = t | VT_LVAL;
5776 store(r, vtop - 1);
5777 /* two word case handling : store second register at word + 4 */
5778 if ((ft & VT_BTYPE) == VT_LLONG) {
5779 vswap();
5780 /* convert to int to increment easily */
5781 vtop->type.t = VT_INT;
5782 gaddrof();
5783 vpushi(4);
5784 gen_op('+');
5785 vtop->r |= VT_LVAL;
5786 vswap();
5787 /* XXX: it works because r2 is spilled last ! */
5788 store(vtop->r2, vtop - 1);
5791 vswap();
5792 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5793 vtop->r |= delayed_cast;
5797 /* post defines POST/PRE add. c is the token ++ or -- */
5798 void inc(int post, int c)
5800 test_lvalue();
5801 vdup(); /* save lvalue */
5802 if (post) {
5803 gv_dup(); /* duplicate value */
5804 vrotb(3);
5805 vrotb(3);
5807 /* add constant */
5808 vpushi(c - TOK_MID);
5809 gen_op('+');
5810 vstore(); /* store value */
5811 if (post)
5812 vpop(); /* if post op, return saved value */
5815 /* Parse GNUC __attribute__ extension. Currently, the following
5816 extensions are recognized:
5817 - aligned(n) : set data/function alignment.
5818 - section(x) : generate data/code in this section.
5819 - unused : currently ignored, but may be used someday.
5821 static void parse_attribute(AttributeDef *ad)
5823 int t, n;
5825 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
5826 next();
5827 skip('(');
5828 skip('(');
5829 while (tok != ')') {
5830 if (tok < TOK_IDENT)
5831 expect("attribute name");
5832 t = tok;
5833 next();
5834 switch(t) {
5835 case TOK_SECTION1:
5836 case TOK_SECTION2:
5837 skip('(');
5838 if (tok != TOK_STR)
5839 expect("section name");
5840 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
5841 next();
5842 skip(')');
5843 break;
5844 case TOK_ALIGNED1:
5845 case TOK_ALIGNED2:
5846 if (tok == '(') {
5847 next();
5848 n = expr_const();
5849 if (n <= 0 || (n & (n - 1)) != 0)
5850 error("alignment must be a positive power of two");
5851 skip(')');
5852 } else {
5853 n = MAX_ALIGN;
5855 ad->aligned = n;
5856 break;
5857 case TOK_UNUSED1:
5858 case TOK_UNUSED2:
5859 /* currently, no need to handle it because tcc does not
5860 track unused objects */
5861 break;
5862 case TOK_NORETURN1:
5863 case TOK_NORETURN2:
5864 /* currently, no need to handle it because tcc does not
5865 track unused objects */
5866 break;
5867 case TOK_CDECL1:
5868 case TOK_CDECL2:
5869 case TOK_CDECL3:
5870 ad->func_call = FUNC_CDECL;
5871 break;
5872 case TOK_STDCALL1:
5873 case TOK_STDCALL2:
5874 case TOK_STDCALL3:
5875 ad->func_call = FUNC_STDCALL;
5876 break;
5877 default:
5878 // warning("'%s' attribute ignored", get_tok_str(t, NULL));
5879 /* skip parameters */
5880 /* XXX: skip parenthesis too */
5881 if (tok == '(') {
5882 next();
5883 while (tok != ')' && tok != -1)
5884 next();
5885 next();
5887 break;
5889 if (tok != ',')
5890 break;
5891 next();
5893 skip(')');
5894 skip(')');
5898 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
5899 static void struct_decl(CType *type, int u)
5901 int a, v, size, align, maxalign, c, offset;
5902 int bit_size, bit_pos, bsize, bt, lbit_pos;
5903 Sym *s, *ss, **ps;
5904 AttributeDef ad;
5905 CType type1, btype;
5907 a = tok; /* save decl type */
5908 next();
5909 if (tok != '{') {
5910 v = tok;
5911 next();
5912 /* struct already defined ? return it */
5913 if (v < TOK_IDENT)
5914 expect("struct/union/enum name");
5915 s = struct_find(v);
5916 if (s) {
5917 if (s->type.t != a)
5918 error("invalid type");
5919 goto do_decl;
5921 } else {
5922 v = anon_sym++;
5924 type1.t = a;
5925 s = sym_push(v | SYM_STRUCT, &type1, 0, 0);
5926 /* put struct/union/enum name in type */
5927 do_decl:
5928 type->t = u;
5929 type->ref = s;
5931 if (tok == '{') {
5932 next();
5933 if (s->c)
5934 error("struct/union/enum already defined");
5935 /* cannot be empty */
5936 c = 0;
5937 /* non empty enums are not allowed */
5938 if (a == TOK_ENUM) {
5939 for(;;) {
5940 v = tok;
5941 if (v < TOK_UIDENT)
5942 expect("identifier");
5943 next();
5944 if (tok == '=') {
5945 next();
5946 c = expr_const();
5948 /* enum symbols have static storage */
5949 ss = sym_push(v, &int_type, VT_CONST, c);
5950 ss->type.t |= VT_STATIC;
5951 if (tok != ',')
5952 break;
5953 next();
5954 c++;
5955 /* NOTE: we accept a trailing comma */
5956 if (tok == '}')
5957 break;
5959 skip('}');
5960 } else {
5961 maxalign = 1;
5962 ps = &s->next;
5963 bit_pos = 0;
5964 offset = 0;
5965 while (tok != '}') {
5966 parse_btype(&btype, &ad);
5967 while (1) {
5968 bit_size = -1;
5969 v = 0;
5970 type1 = btype;
5971 if (tok != ':') {
5972 type_decl(&type1, &ad, &v, TYPE_DIRECT);
5973 if ((type1.t & VT_BTYPE) == VT_FUNC ||
5974 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
5975 error("invalid type for '%s'",
5976 get_tok_str(v, NULL));
5978 if (tok == ':') {
5979 next();
5980 bit_size = expr_const();
5981 /* XXX: handle v = 0 case for messages */
5982 if (bit_size < 0)
5983 error("negative width in bit-field '%s'",
5984 get_tok_str(v, NULL));
5985 if (v && bit_size == 0)
5986 error("zero width for bit-field '%s'",
5987 get_tok_str(v, NULL));
5989 size = type_size(&type1, &align);
5990 lbit_pos = 0;
5991 if (bit_size >= 0) {
5992 bt = type1.t & VT_BTYPE;
5993 if (bt != VT_INT &&
5994 bt != VT_BYTE &&
5995 bt != VT_SHORT &&
5996 bt != VT_ENUM)
5997 error("bitfields must have scalar type");
5998 bsize = size * 8;
5999 if (bit_size > bsize) {
6000 error("width of '%s' exceeds its type",
6001 get_tok_str(v, NULL));
6002 } else if (bit_size == bsize) {
6003 /* no need for bit fields */
6004 bit_pos = 0;
6005 } else if (bit_size == 0) {
6006 /* XXX: what to do if only padding in a
6007 structure ? */
6008 /* zero size: means to pad */
6009 if (bit_pos > 0)
6010 bit_pos = bsize;
6011 } else {
6012 /* we do not have enough room ? */
6013 if ((bit_pos + bit_size) > bsize)
6014 bit_pos = 0;
6015 lbit_pos = bit_pos;
6016 /* XXX: handle LSB first */
6017 type1.t |= VT_BITFIELD |
6018 (bit_pos << VT_STRUCT_SHIFT) |
6019 (bit_size << (VT_STRUCT_SHIFT + 6));
6020 bit_pos += bit_size;
6022 } else {
6023 bit_pos = 0;
6025 if (v) {
6026 /* add new memory data only if starting
6027 bit field */
6028 if (lbit_pos == 0) {
6029 if (a == TOK_STRUCT) {
6030 c = (c + align - 1) & -align;
6031 offset = c;
6032 c += size;
6033 } else {
6034 offset = 0;
6035 if (size > c)
6036 c = size;
6038 if (align > maxalign)
6039 maxalign = align;
6041 #if 0
6042 printf("add field %s offset=%d",
6043 get_tok_str(v, NULL), offset);
6044 if (type1.t & VT_BITFIELD) {
6045 printf(" pos=%d size=%d",
6046 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6047 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6049 printf("\n");
6050 #endif
6051 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6052 *ps = ss;
6053 ps = &ss->next;
6055 if (tok == ';' || tok == TOK_EOF)
6056 break;
6057 skip(',');
6059 skip(';');
6061 skip('}');
6062 /* store size and alignment */
6063 s->c = (c + maxalign - 1) & -maxalign;
6064 s->r = maxalign;
6069 /* return 0 if no type declaration. otherwise, return the basic type
6070 and skip it.
6072 static int parse_btype(CType *type, AttributeDef *ad)
6074 int t, u, type_found;
6075 Sym *s;
6076 CType type1;
6078 memset(ad, 0, sizeof(AttributeDef));
6079 type_found = 0;
6080 t = 0;
6081 while(1) {
6082 switch(tok) {
6083 case TOK_EXTENSION:
6084 /* currently, we really ignore extension */
6085 next();
6086 continue;
6088 /* basic types */
6089 case TOK_CHAR:
6090 u = VT_BYTE;
6091 basic_type:
6092 next();
6093 basic_type1:
6094 if ((t & VT_BTYPE) != 0)
6095 error("too many basic types");
6096 t |= u;
6097 break;
6098 case TOK_VOID:
6099 u = VT_VOID;
6100 goto basic_type;
6101 case TOK_SHORT:
6102 u = VT_SHORT;
6103 goto basic_type;
6104 case TOK_INT:
6105 next();
6106 break;
6107 case TOK_LONG:
6108 next();
6109 if ((t & VT_BTYPE) == VT_DOUBLE) {
6110 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6111 } else if ((t & VT_BTYPE) == VT_LONG) {
6112 t = (t & ~VT_BTYPE) | VT_LLONG;
6113 } else {
6114 u = VT_LONG;
6115 goto basic_type1;
6117 break;
6118 case TOK_BOOL:
6119 u = VT_BOOL;
6120 goto basic_type;
6121 case TOK_FLOAT:
6122 u = VT_FLOAT;
6123 goto basic_type;
6124 case TOK_DOUBLE:
6125 next();
6126 if ((t & VT_BTYPE) == VT_LONG) {
6127 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6128 } else {
6129 u = VT_DOUBLE;
6130 goto basic_type1;
6132 break;
6133 case TOK_ENUM:
6134 struct_decl(&type1, VT_ENUM);
6135 basic_type2:
6136 u = type1.t;
6137 type->ref = type1.ref;
6138 goto basic_type1;
6139 case TOK_STRUCT:
6140 case TOK_UNION:
6141 struct_decl(&type1, VT_STRUCT);
6142 goto basic_type2;
6144 /* type modifiers */
6145 case TOK_CONST1:
6146 case TOK_CONST2:
6147 case TOK_CONST3:
6148 case TOK_VOLATILE1:
6149 case TOK_VOLATILE2:
6150 case TOK_VOLATILE3:
6151 case TOK_REGISTER:
6152 case TOK_SIGNED1:
6153 case TOK_SIGNED2:
6154 case TOK_SIGNED3:
6155 case TOK_AUTO:
6156 case TOK_RESTRICT1:
6157 case TOK_RESTRICT2:
6158 case TOK_RESTRICT3:
6159 next();
6160 break;
6161 case TOK_UNSIGNED:
6162 t |= VT_UNSIGNED;
6163 next();
6164 break;
6166 /* storage */
6167 case TOK_EXTERN:
6168 t |= VT_EXTERN;
6169 next();
6170 break;
6171 case TOK_STATIC:
6172 t |= VT_STATIC;
6173 next();
6174 break;
6175 case TOK_TYPEDEF:
6176 t |= VT_TYPEDEF;
6177 next();
6178 break;
6179 case TOK_INLINE1:
6180 case TOK_INLINE2:
6181 case TOK_INLINE3:
6182 t |= VT_INLINE;
6183 next();
6184 break;
6186 /* GNUC attribute */
6187 case TOK_ATTRIBUTE1:
6188 case TOK_ATTRIBUTE2:
6189 parse_attribute(ad);
6190 break;
6191 /* GNUC typeof */
6192 case TOK_TYPEOF1:
6193 case TOK_TYPEOF2:
6194 case TOK_TYPEOF3:
6195 next();
6196 parse_expr_type(&type1);
6197 goto basic_type2;
6198 default:
6199 s = sym_find(tok);
6200 if (!s || !(s->type.t & VT_TYPEDEF))
6201 goto the_end;
6202 t |= (s->type.t & ~VT_TYPEDEF);
6203 type->ref = s->type.ref;
6204 next();
6205 break;
6207 type_found = 1;
6209 the_end:
6210 /* long is never used as type */
6211 if ((t & VT_BTYPE) == VT_LONG)
6212 t = (t & ~VT_BTYPE) | VT_INT;
6213 type->t = t;
6214 return type_found;
6217 /* convert a function parameter type (array to pointer and function to
6218 function pointer) */
6219 static inline void convert_parameter_type(CType *pt)
6221 /* array must be transformed to pointer according to ANSI C */
6222 pt->t &= ~VT_ARRAY;
6223 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6224 mk_pointer(pt);
6228 static void post_type(CType *type, AttributeDef *ad)
6230 int n, l, t1;
6231 Sym **plast, *s, *first;
6232 AttributeDef ad1;
6233 CType pt;
6235 if (tok == '(') {
6236 /* function declaration */
6237 next();
6238 l = 0;
6239 first = NULL;
6240 plast = &first;
6241 while (tok != ')') {
6242 /* read param name and compute offset */
6243 if (l != FUNC_OLD) {
6244 if (!parse_btype(&pt, &ad1)) {
6245 if (l) {
6246 error("invalid type");
6247 } else {
6248 l = FUNC_OLD;
6249 goto old_proto;
6252 l = FUNC_NEW;
6253 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6254 break;
6255 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6256 if ((pt.t & VT_BTYPE) == VT_VOID)
6257 error("parameter declared as void");
6258 } else {
6259 old_proto:
6260 n = tok;
6261 pt.t = VT_INT;
6262 next();
6264 convert_parameter_type(&pt);
6265 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6266 *plast = s;
6267 plast = &s->next;
6268 if (tok == ',') {
6269 next();
6270 if (l == FUNC_NEW && tok == TOK_DOTS) {
6271 l = FUNC_ELLIPSIS;
6272 next();
6273 break;
6277 /* if no parameters, then old type prototype */
6278 if (l == 0)
6279 l = FUNC_OLD;
6280 skip(')');
6281 t1 = type->t & VT_STORAGE;
6282 type->t &= ~VT_STORAGE;
6283 post_type(type, ad);
6284 /* we push a anonymous symbol which will contain the function prototype */
6285 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6286 s->next = first;
6287 type->t = t1 | VT_FUNC;
6288 type->ref = s;
6289 } else if (tok == '[') {
6290 /* array definition */
6291 next();
6292 n = -1;
6293 if (tok != ']') {
6294 n = expr_const();
6295 if (n < 0)
6296 error("invalid array size");
6298 skip(']');
6299 /* parse next post type */
6300 t1 = type->t & VT_STORAGE;
6301 type->t &= ~VT_STORAGE;
6302 post_type(type, ad);
6304 /* we push a anonymous symbol which will contain the array
6305 element type */
6306 s = sym_push(SYM_FIELD, type, 0, n);
6307 type->t = t1 | VT_ARRAY | VT_PTR;
6308 type->ref = s;
6312 /* Parse a type declaration (except basic type), and return the type
6313 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6314 expected. 'type' should contain the basic type. 'ad' is the
6315 attribute definition of the basic type. It can be modified by
6316 type_decl().
6318 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6320 Sym *s;
6321 CType type1, *type2;
6323 while (tok == '*') {
6324 next();
6325 redo:
6326 switch(tok) {
6327 case TOK_CONST1:
6328 case TOK_CONST2:
6329 case TOK_CONST3:
6330 case TOK_VOLATILE1:
6331 case TOK_VOLATILE2:
6332 case TOK_VOLATILE3:
6333 case TOK_RESTRICT1:
6334 case TOK_RESTRICT2:
6335 case TOK_RESTRICT3:
6336 next();
6337 goto redo;
6339 mk_pointer(type);
6342 /* XXX: clarify attribute handling */
6343 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6344 parse_attribute(ad);
6346 /* recursive type */
6347 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6348 type1.t = 0; /* XXX: same as int */
6349 if (tok == '(') {
6350 next();
6351 /* XXX: this is not correct to modify 'ad' at this point, but
6352 the syntax is not clear */
6353 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6354 parse_attribute(ad);
6355 type_decl(&type1, ad, v, td);
6356 skip(')');
6357 } else {
6358 /* type identifier */
6359 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6360 *v = tok;
6361 next();
6362 } else {
6363 if (!(td & TYPE_ABSTRACT))
6364 expect("identifier");
6365 *v = 0;
6368 post_type(type, ad);
6369 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6370 parse_attribute(ad);
6371 if (!type1.t)
6372 return;
6373 /* append type at the end of type1 */
6374 type2 = &type1;
6375 for(;;) {
6376 s = type2->ref;
6377 type2 = &s->type;
6378 if (!type2->t) {
6379 *type2 = *type;
6380 break;
6383 *type = type1;
6386 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6387 static int lvalue_type(int t)
6389 int bt, r;
6390 r = VT_LVAL;
6391 bt = t & VT_BTYPE;
6392 if (bt == VT_BYTE || bt == VT_BOOL)
6393 r |= VT_LVAL_BYTE;
6394 else if (bt == VT_SHORT)
6395 r |= VT_LVAL_SHORT;
6396 else
6397 return r;
6398 if (t & VT_UNSIGNED)
6399 r |= VT_LVAL_UNSIGNED;
6400 return r;
6403 /* indirection with full error checking and bound check */
6404 static void indir(void)
6406 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6407 expect("pointer");
6408 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6409 gv(RC_INT);
6410 vtop->type = *pointed_type(&vtop->type);
6411 /* an array is never an lvalue */
6412 if (!(vtop->type.t & VT_ARRAY)) {
6413 vtop->r |= lvalue_type(vtop->type.t);
6414 /* if bound checking, the referenced pointer must be checked */
6415 if (do_bounds_check)
6416 vtop->r |= VT_MUSTBOUND;
6420 /* pass a parameter to a function and do type checking and casting */
6421 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
6423 int func_type;
6424 CType type;
6426 func_type = func->c;
6427 if (func_type == FUNC_OLD ||
6428 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6429 /* default casting : only need to convert float to double */
6430 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6431 type.t = VT_DOUBLE;
6432 gen_cast(&type);
6434 } else if (arg == NULL) {
6435 error("too many arguments to function");
6436 } else {
6437 gen_assign_cast(&arg->type);
6439 if (!nocode_wanted) {
6440 gfunc_param(gf);
6441 } else {
6442 vpop();
6446 /* parse an expression of the form '(type)' or '(expr)' and return its
6447 type */
6448 static void parse_expr_type(CType *type)
6450 int n;
6451 AttributeDef ad;
6453 skip('(');
6454 if (parse_btype(type, &ad)) {
6455 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6456 } else {
6457 expr_type(type);
6459 skip(')');
6462 static void vpush_tokc(int t)
6464 CType type;
6465 type.t = t;
6466 vsetc(&type, VT_CONST, &tokc);
6469 static void unary(void)
6471 int n, t, align, size, r;
6472 CType type;
6473 Sym *s;
6474 GFuncContext gf;
6475 AttributeDef ad;
6477 /* XXX: GCC 2.95.3 does not generate a table although it should be
6478 better here */
6479 tok_next:
6480 switch(tok) {
6481 case TOK_EXTENSION:
6482 next();
6483 goto tok_next;
6484 case TOK_CINT:
6485 case TOK_CCHAR:
6486 case TOK_LCHAR:
6487 vpushi(tokc.i);
6488 next();
6489 break;
6490 case TOK_CUINT:
6491 vpush_tokc(VT_INT | VT_UNSIGNED);
6492 next();
6493 break;
6494 case TOK_CLLONG:
6495 vpush_tokc(VT_LLONG);
6496 next();
6497 break;
6498 case TOK_CULLONG:
6499 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6500 next();
6501 break;
6502 case TOK_CFLOAT:
6503 vpush_tokc(VT_FLOAT);
6504 next();
6505 break;
6506 case TOK_CDOUBLE:
6507 vpush_tokc(VT_DOUBLE);
6508 next();
6509 break;
6510 case TOK_CLDOUBLE:
6511 vpush_tokc(VT_LDOUBLE);
6512 next();
6513 break;
6514 case TOK___FUNCTION__:
6515 if (!gnu_ext)
6516 goto tok_identifier;
6517 /* fall thru */
6518 case TOK___FUNC__:
6520 void *ptr;
6521 int len;
6522 /* special function name identifier */
6523 len = strlen(funcname) + 1;
6524 /* generate char[len] type */
6525 type.t = VT_BYTE;
6526 mk_pointer(&type);
6527 type.t |= VT_ARRAY;
6528 type.ref->c = len;
6529 vpush_ref(&type, data_section, data_section->data_offset, len);
6530 ptr = section_ptr_add(data_section, len);
6531 memcpy(ptr, funcname, len);
6532 next();
6534 break;
6535 case TOK_LSTR:
6536 t = VT_INT;
6537 goto str_init;
6538 case TOK_STR:
6539 /* string parsing */
6540 t = VT_BYTE;
6541 str_init:
6542 type.t = t;
6543 mk_pointer(&type);
6544 type.t |= VT_ARRAY;
6545 memset(&ad, 0, sizeof(AttributeDef));
6546 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6547 break;
6548 case '(':
6549 next();
6550 /* cast ? */
6551 if (parse_btype(&type, &ad)) {
6552 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6553 skip(')');
6554 /* check ISOC99 compound literal */
6555 if (tok == '{') {
6556 /* data is allocated locally by default */
6557 if (global_expr)
6558 r = VT_CONST;
6559 else
6560 r = VT_LOCAL;
6561 /* all except arrays are lvalues */
6562 if (!(type.t & VT_ARRAY))
6563 r |= lvalue_type(type.t);
6564 memset(&ad, 0, sizeof(AttributeDef));
6565 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6566 } else {
6567 unary();
6568 gen_cast(&type);
6570 } else if (tok == '{') {
6571 /* save all registers */
6572 save_regs(0);
6573 /* statement expression : we do not accept break/continue
6574 inside as GCC does */
6575 block(NULL, NULL, NULL, NULL, 0, 1);
6576 skip(')');
6577 } else {
6578 gexpr();
6579 skip(')');
6581 break;
6582 case '*':
6583 next();
6584 unary();
6585 indir();
6586 break;
6587 case '&':
6588 next();
6589 unary();
6590 /* functions names must be treated as function pointers,
6591 except for unary '&' and sizeof. Since we consider that
6592 functions are not lvalues, we only have to handle it
6593 there and in function calls. */
6594 /* arrays can also be used although they are not lvalues */
6595 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6596 !(vtop->type.t & VT_ARRAY))
6597 test_lvalue();
6598 mk_pointer(&vtop->type);
6599 gaddrof();
6600 break;
6601 case '!':
6602 next();
6603 unary();
6604 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6605 vtop->c.i = !vtop->c.i;
6606 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6607 vtop->c.i = vtop->c.i ^ 1;
6608 else
6609 vseti(VT_JMP, gtst(1, 0));
6610 break;
6611 case '~':
6612 next();
6613 unary();
6614 vpushi(-1);
6615 gen_op('^');
6616 break;
6617 case '+':
6618 next();
6619 /* in order to force cast, we add zero */
6620 unary();
6621 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6622 error("pointer not accepted for unary plus");
6623 vpushi(0);
6624 gen_op('+');
6625 break;
6626 case TOK_SIZEOF:
6627 case TOK_ALIGNOF1:
6628 case TOK_ALIGNOF2:
6629 t = tok;
6630 next();
6631 if (tok == '(') {
6632 parse_expr_type(&type);
6633 } else {
6634 unary_type(&type);
6636 size = type_size(&type, &align);
6637 if (t == TOK_SIZEOF)
6638 vpushi(size);
6639 else
6640 vpushi(align);
6641 break;
6643 case TOK_INC:
6644 case TOK_DEC:
6645 t = tok;
6646 next();
6647 unary();
6648 inc(0, t);
6649 break;
6650 case '-':
6651 next();
6652 vpushi(0);
6653 unary();
6654 gen_op('-');
6655 break;
6656 case TOK_LAND:
6657 if (!gnu_ext)
6658 goto tok_identifier;
6659 next();
6660 /* allow to take the address of a label */
6661 if (tok < TOK_UIDENT)
6662 expect("label identifier");
6663 s = label_find(tok);
6664 if (!s) {
6665 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6666 } else {
6667 if (s->r == LABEL_DECLARED)
6668 s->r = LABEL_FORWARD;
6670 if (!s->type.t) {
6671 s->type.t = VT_VOID;
6672 mk_pointer(&s->type);
6673 s->type.t |= VT_STATIC;
6675 vset(&s->type, VT_CONST | VT_SYM, 0);
6676 vtop->sym = s;
6677 next();
6678 break;
6679 default:
6680 tok_identifier:
6681 t = tok;
6682 next();
6683 if (t < TOK_UIDENT)
6684 expect("identifier");
6685 s = sym_find(t);
6686 if (!s) {
6687 if (tok != '(')
6688 error("'%s' undeclared", get_tok_str(t, NULL));
6689 /* for simple function calls, we tolerate undeclared
6690 external reference to int() function */
6691 s = external_global_sym(t, &func_old_type, 0);
6693 vset(&s->type, s->r, s->c);
6694 /* if forward reference, we must point to s */
6695 if (vtop->r & VT_SYM) {
6696 vtop->sym = s;
6697 vtop->c.ul = 0;
6699 break;
6702 /* post operations */
6703 while (1) {
6704 if (tok == TOK_INC || tok == TOK_DEC) {
6705 inc(1, tok);
6706 next();
6707 } else if (tok == '.' || tok == TOK_ARROW) {
6708 /* field */
6709 if (tok == TOK_ARROW)
6710 indir();
6711 test_lvalue();
6712 gaddrof();
6713 next();
6714 /* expect pointer on structure */
6715 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6716 expect("struct or union");
6717 s = vtop->type.ref;
6718 /* find field */
6719 tok |= SYM_FIELD;
6720 while ((s = s->next) != NULL) {
6721 if (s->v == tok)
6722 break;
6724 if (!s)
6725 error("field not found");
6726 /* add field offset to pointer */
6727 vtop->type = char_pointer_type; /* change type to 'char *' */
6728 vpushi(s->c);
6729 gen_op('+');
6730 /* change type to field type, and set to lvalue */
6731 vtop->type = s->type;
6732 /* an array is never an lvalue */
6733 if (!(vtop->type.t & VT_ARRAY)) {
6734 vtop->r |= lvalue_type(vtop->type.t);
6735 /* if bound checking, the referenced pointer must be checked */
6736 if (do_bounds_check)
6737 vtop->r |= VT_MUSTBOUND;
6739 next();
6740 } else if (tok == '[') {
6741 next();
6742 gexpr();
6743 gen_op('+');
6744 indir();
6745 skip(']');
6746 } else if (tok == '(') {
6747 SValue ret;
6748 Sym *sa;
6750 /* function call */
6751 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
6752 /* pointer test (no array accepted) */
6753 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
6754 vtop->type = *pointed_type(&vtop->type);
6755 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
6756 goto error_func;
6757 } else {
6758 error_func:
6759 expect("function pointer");
6761 } else {
6762 vtop->r &= ~VT_LVAL; /* no lvalue */
6764 /* get return type */
6765 s = vtop->type.ref;
6766 if (!nocode_wanted) {
6767 save_regs(0); /* save used temporary registers */
6768 gfunc_start(&gf, s->r);
6770 next();
6771 sa = s->next; /* first parameter */
6772 #ifdef INVERT_FUNC_PARAMS
6774 int parlevel;
6775 Sym *args, *s1;
6776 ParseState saved_parse_state;
6777 TokenString str;
6779 /* read each argument and store it on a stack */
6780 args = NULL;
6781 if (tok != ')') {
6782 for(;;) {
6783 tok_str_new(&str);
6784 parlevel = 0;
6785 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
6786 tok != TOK_EOF) {
6787 if (tok == '(')
6788 parlevel++;
6789 else if (tok == ')')
6790 parlevel--;
6791 tok_str_add_tok(&str);
6792 next();
6794 tok_str_add(&str, -1); /* end of file added */
6795 tok_str_add(&str, 0);
6796 s1 = sym_push2(&args, 0, 0, (int)str.str);
6797 s1->next = sa; /* add reference to argument */
6798 if (sa)
6799 sa = sa->next;
6800 if (tok == ')')
6801 break;
6802 skip(',');
6806 /* now generate code in reverse order by reading the stack */
6807 save_parse_state(&saved_parse_state);
6808 while (args) {
6809 macro_ptr = (int *)args->c;
6810 next();
6811 expr_eq();
6812 if (tok != -1)
6813 expect("',' or ')'");
6814 gfunc_param_typed(&gf, s, args->next);
6815 s1 = args->prev;
6816 tok_str_free((int *)args->c);
6817 tcc_free(args);
6818 args = s1;
6820 restore_parse_state(&saved_parse_state);
6822 #endif
6823 /* compute first implicit argument if a structure is returned */
6824 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
6825 /* get some space for the returned structure */
6826 size = type_size(&s->type, &align);
6827 loc = (loc - size) & -align;
6828 ret.type = s->type;
6829 ret.r = VT_LOCAL | VT_LVAL;
6830 /* pass it as 'int' to avoid structure arg passing
6831 problems */
6832 vseti(VT_LOCAL, loc);
6833 ret.c = vtop->c;
6834 if (!nocode_wanted)
6835 gfunc_param(&gf);
6836 else
6837 vtop--;
6838 } else {
6839 ret.type = s->type;
6840 ret.r2 = VT_CONST;
6841 /* return in register */
6842 if (is_float(ret.type.t)) {
6843 ret.r = REG_FRET;
6844 } else {
6845 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
6846 ret.r2 = REG_LRET;
6847 ret.r = REG_IRET;
6849 ret.c.i = 0;
6851 #ifndef INVERT_FUNC_PARAMS
6852 if (tok != ')') {
6853 for(;;) {
6854 expr_eq();
6855 gfunc_param_typed(&gf, s, sa);
6856 if (sa)
6857 sa = sa->next;
6858 if (tok == ')')
6859 break;
6860 skip(',');
6863 #endif
6864 if (sa)
6865 error("too few arguments to function");
6866 skip(')');
6867 if (!nocode_wanted)
6868 gfunc_call(&gf);
6869 else
6870 vtop--;
6871 /* return value */
6872 vsetc(&ret.type, ret.r, &ret.c);
6873 vtop->r2 = ret.r2;
6874 } else {
6875 break;
6880 static void uneq(void)
6882 int t;
6884 unary();
6885 if (tok == '=' ||
6886 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
6887 tok == TOK_A_XOR || tok == TOK_A_OR ||
6888 tok == TOK_A_SHL || tok == TOK_A_SAR) {
6889 test_lvalue();
6890 t = tok;
6891 next();
6892 if (t == '=') {
6893 expr_eq();
6894 } else {
6895 vdup();
6896 expr_eq();
6897 gen_op(t & 0x7f);
6899 vstore();
6903 static void expr_prod(void)
6905 int t;
6907 uneq();
6908 while (tok == '*' || tok == '/' || tok == '%') {
6909 t = tok;
6910 next();
6911 uneq();
6912 gen_op(t);
6916 static void expr_sum(void)
6918 int t;
6920 expr_prod();
6921 while (tok == '+' || tok == '-') {
6922 t = tok;
6923 next();
6924 expr_prod();
6925 gen_op(t);
6929 static void expr_shift(void)
6931 int t;
6933 expr_sum();
6934 while (tok == TOK_SHL || tok == TOK_SAR) {
6935 t = tok;
6936 next();
6937 expr_sum();
6938 gen_op(t);
6942 static void expr_cmp(void)
6944 int t;
6946 expr_shift();
6947 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
6948 tok == TOK_ULT || tok == TOK_UGE) {
6949 t = tok;
6950 next();
6951 expr_shift();
6952 gen_op(t);
6956 static void expr_cmpeq(void)
6958 int t;
6960 expr_cmp();
6961 while (tok == TOK_EQ || tok == TOK_NE) {
6962 t = tok;
6963 next();
6964 expr_cmp();
6965 gen_op(t);
6969 static void expr_and(void)
6971 expr_cmpeq();
6972 while (tok == '&') {
6973 next();
6974 expr_cmpeq();
6975 gen_op('&');
6979 static void expr_xor(void)
6981 expr_and();
6982 while (tok == '^') {
6983 next();
6984 expr_and();
6985 gen_op('^');
6989 static void expr_or(void)
6991 expr_xor();
6992 while (tok == '|') {
6993 next();
6994 expr_xor();
6995 gen_op('|');
6999 /* XXX: fix this mess */
7000 static void expr_land_const(void)
7002 expr_or();
7003 while (tok == TOK_LAND) {
7004 next();
7005 expr_or();
7006 gen_op(TOK_LAND);
7010 /* XXX: fix this mess */
7011 static void expr_lor_const(void)
7013 expr_land_const();
7014 while (tok == TOK_LOR) {
7015 next();
7016 expr_land_const();
7017 gen_op(TOK_LOR);
7021 /* only used if non constant */
7022 static void expr_land(void)
7024 int t;
7026 expr_or();
7027 if (tok == TOK_LAND) {
7028 t = 0;
7029 for(;;) {
7030 t = gtst(1, t);
7031 if (tok != TOK_LAND) {
7032 vseti(VT_JMPI, t);
7033 break;
7035 next();
7036 expr_or();
7041 static void expr_lor(void)
7043 int t;
7045 expr_land();
7046 if (tok == TOK_LOR) {
7047 t = 0;
7048 for(;;) {
7049 t = gtst(0, t);
7050 if (tok != TOK_LOR) {
7051 vseti(VT_JMP, t);
7052 break;
7054 next();
7055 expr_land();
7060 /* XXX: better constant handling */
7061 static void expr_eq(void)
7063 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7064 SValue sv;
7065 CType type, type1, type2;
7067 if (const_wanted) {
7068 int c1, c;
7069 expr_lor_const();
7070 if (tok == '?') {
7071 c = vtop->c.i;
7072 vpop();
7073 next();
7074 if (tok == ':' && gnu_ext) {
7075 c1 = c;
7076 } else {
7077 gexpr();
7078 c1 = vtop->c.i;
7079 vpop();
7081 skip(':');
7082 expr_eq();
7083 if (c)
7084 vtop->c.i = c1;
7086 } else {
7087 expr_lor();
7088 if (tok == '?') {
7089 next();
7090 if (vtop != vstack) {
7091 /* needed to avoid having different registers saved in
7092 each branch */
7093 if (is_float(vtop->type.t))
7094 rc = RC_FLOAT;
7095 else
7096 rc = RC_INT;
7097 gv(rc);
7098 save_regs(1);
7100 if (tok == ':' && gnu_ext) {
7101 gv_dup();
7102 tt = gtst(1, 0);
7103 } else {
7104 tt = gtst(1, 0);
7105 gexpr();
7107 type1 = vtop->type;
7108 sv = *vtop; /* save value to handle it later */
7109 vtop--; /* no vpop so that FP stack is not flushed */
7110 skip(':');
7111 u = gjmp(0);
7112 gsym(tt);
7113 expr_eq();
7114 type2 = vtop->type;
7116 t1 = type1.t;
7117 bt1 = t1 & VT_BTYPE;
7118 t2 = type2.t;
7119 bt2 = t2 & VT_BTYPE;
7120 /* cast operands to correct type according to ISOC rules */
7121 if (is_float(bt1) || is_float(bt2)) {
7122 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7123 type.t = VT_LDOUBLE;
7124 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7125 type.t = VT_DOUBLE;
7126 } else {
7127 type.t = VT_FLOAT;
7129 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7130 /* cast to biggest op */
7131 type.t = VT_LLONG;
7132 /* convert to unsigned if it does not fit in a long long */
7133 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7134 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7135 type.t |= VT_UNSIGNED;
7136 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7137 /* XXX: test pointer compatibility */
7138 type = type1;
7139 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7140 /* XXX: test structure compatibility */
7141 type = type1;
7142 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7143 /* NOTE: as an extension, we accept void on only one side */
7144 type.t = VT_VOID;
7145 } else {
7146 /* integer operations */
7147 type.t = VT_INT;
7148 /* convert to unsigned if it does not fit in an integer */
7149 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7150 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7151 type.t |= VT_UNSIGNED;
7154 /* now we convert second operand */
7155 gen_cast(&type);
7156 rc = RC_INT;
7157 if (is_float(type.t)) {
7158 rc = RC_FLOAT;
7159 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7160 /* for long longs, we use fixed registers to avoid having
7161 to handle a complicated move */
7162 rc = RC_IRET;
7165 r2 = gv(rc);
7166 /* this is horrible, but we must also convert first
7167 operand */
7168 tt = gjmp(0);
7169 gsym(u);
7170 /* put again first value and cast it */
7171 *vtop = sv;
7172 gen_cast(&type);
7173 r1 = gv(rc);
7174 move_reg(r2, r1);
7175 vtop->r = r2;
7176 gsym(tt);
7181 static void gexpr(void)
7183 while (1) {
7184 expr_eq();
7185 if (tok != ',')
7186 break;
7187 vpop();
7188 next();
7192 /* parse an expression and return its type without any side effect. */
7193 static void expr_type(CType *type)
7195 int a;
7197 a = nocode_wanted;
7198 nocode_wanted = 1;
7199 gexpr();
7200 *type = vtop->type;
7201 vpop();
7202 nocode_wanted = a;
7205 /* parse a unary expression and return its type without any side
7206 effect. */
7207 static void unary_type(CType *type)
7209 int a;
7211 a = nocode_wanted;
7212 nocode_wanted = 1;
7213 unary();
7214 *type = vtop->type;
7215 vpop();
7216 nocode_wanted = a;
7219 /* parse a constant expression and return value in vtop. */
7220 static void expr_const1(void)
7222 int a;
7223 a = const_wanted;
7224 const_wanted = 1;
7225 expr_eq();
7226 const_wanted = a;
7229 /* parse an integer constant and return its value. */
7230 static int expr_const(void)
7232 int c;
7233 expr_const1();
7234 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7235 expect("constant expression");
7236 c = vtop->c.i;
7237 vpop();
7238 return c;
7241 /* return the label token if current token is a label, otherwise
7242 return zero */
7243 static int is_label(void)
7245 int last_tok;
7247 /* fast test first */
7248 if (tok < TOK_UIDENT)
7249 return 0;
7250 /* no need to save tokc because tok is an identifier */
7251 last_tok = tok;
7252 next();
7253 if (tok == ':') {
7254 next();
7255 return last_tok;
7256 } else {
7257 unget_tok(last_tok);
7258 return 0;
7262 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7263 int case_reg, int is_expr)
7265 int a, b, c, d;
7266 Sym *s;
7268 /* generate line number info */
7269 if (do_debug &&
7270 (last_line_num != file->line_num || last_ind != ind)) {
7271 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7272 last_ind = ind;
7273 last_line_num = file->line_num;
7276 if (is_expr) {
7277 /* default return value is (void) */
7278 vpushi(0);
7279 vtop->type.t = VT_VOID;
7282 if (tok == TOK_IF) {
7283 /* if test */
7284 next();
7285 skip('(');
7286 gexpr();
7287 skip(')');
7288 a = gtst(1, 0);
7289 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7290 c = tok;
7291 if (c == TOK_ELSE) {
7292 next();
7293 d = gjmp(0);
7294 gsym(a);
7295 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7296 gsym(d); /* patch else jmp */
7297 } else
7298 gsym(a);
7299 } else if (tok == TOK_WHILE) {
7300 next();
7301 d = ind;
7302 skip('(');
7303 gexpr();
7304 skip(')');
7305 a = gtst(1, 0);
7306 b = 0;
7307 block(&a, &b, case_sym, def_sym, case_reg, 0);
7308 gjmp_addr(d);
7309 gsym(a);
7310 gsym_addr(b, d);
7311 } else if (tok == '{') {
7312 Sym *llabel;
7314 next();
7315 /* record local declaration stack position */
7316 s = local_stack;
7317 llabel = local_label_stack;
7318 /* handle local labels declarations */
7319 if (tok == TOK_LABEL) {
7320 next();
7321 for(;;) {
7322 if (tok < TOK_UIDENT)
7323 expect("label identifier");
7324 label_push(&local_label_stack, tok, LABEL_DECLARED);
7325 next();
7326 if (tok == ',') {
7327 next();
7328 } else {
7329 skip(';');
7330 break;
7334 while (tok != '}') {
7335 decl(VT_LOCAL);
7336 if (tok != '}') {
7337 if (is_expr)
7338 vpop();
7339 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7342 /* pop locally defined labels */
7343 label_pop(&local_label_stack, llabel);
7344 /* pop locally defined symbols */
7345 sym_pop(&local_stack, s);
7346 next();
7347 } else if (tok == TOK_RETURN) {
7348 next();
7349 if (tok != ';') {
7350 gexpr();
7351 gen_assign_cast(&func_vt);
7352 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7353 CType type;
7354 /* if returning structure, must copy it to implicit
7355 first pointer arg location */
7356 type = func_vt;
7357 mk_pointer(&type);
7358 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7359 indir();
7360 vswap();
7361 /* copy structure value to pointer */
7362 vstore();
7363 } else if (is_float(func_vt.t)) {
7364 gv(RC_FRET);
7365 } else {
7366 gv(RC_IRET);
7368 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7370 skip(';');
7371 rsym = gjmp(rsym); /* jmp */
7372 } else if (tok == TOK_BREAK) {
7373 /* compute jump */
7374 if (!bsym)
7375 error("cannot break");
7376 *bsym = gjmp(*bsym);
7377 next();
7378 skip(';');
7379 } else if (tok == TOK_CONTINUE) {
7380 /* compute jump */
7381 if (!csym)
7382 error("cannot continue");
7383 *csym = gjmp(*csym);
7384 next();
7385 skip(';');
7386 } else if (tok == TOK_FOR) {
7387 int e;
7388 next();
7389 skip('(');
7390 if (tok != ';') {
7391 gexpr();
7392 vpop();
7394 skip(';');
7395 d = ind;
7396 c = ind;
7397 a = 0;
7398 b = 0;
7399 if (tok != ';') {
7400 gexpr();
7401 a = gtst(1, 0);
7403 skip(';');
7404 if (tok != ')') {
7405 e = gjmp(0);
7406 c = ind;
7407 gexpr();
7408 vpop();
7409 gjmp_addr(d);
7410 gsym(e);
7412 skip(')');
7413 block(&a, &b, case_sym, def_sym, case_reg, 0);
7414 gjmp_addr(c);
7415 gsym(a);
7416 gsym_addr(b, c);
7417 } else
7418 if (tok == TOK_DO) {
7419 next();
7420 a = 0;
7421 b = 0;
7422 d = ind;
7423 block(&a, &b, case_sym, def_sym, case_reg, 0);
7424 skip(TOK_WHILE);
7425 skip('(');
7426 gsym(b);
7427 gexpr();
7428 c = gtst(0, 0);
7429 gsym_addr(c, d);
7430 skip(')');
7431 gsym(a);
7432 skip(';');
7433 } else
7434 if (tok == TOK_SWITCH) {
7435 next();
7436 skip('(');
7437 gexpr();
7438 /* XXX: other types than integer */
7439 case_reg = gv(RC_INT);
7440 vpop();
7441 skip(')');
7442 a = 0;
7443 b = gjmp(0); /* jump to first case */
7444 c = 0;
7445 block(&a, csym, &b, &c, case_reg, 0);
7446 /* if no default, jmp after switch */
7447 if (c == 0)
7448 c = ind;
7449 /* default label */
7450 gsym_addr(b, c);
7451 /* break label */
7452 gsym(a);
7453 } else
7454 if (tok == TOK_CASE) {
7455 int v1, v2;
7456 if (!case_sym)
7457 expect("switch");
7458 next();
7459 v1 = expr_const();
7460 v2 = v1;
7461 if (gnu_ext && tok == TOK_DOTS) {
7462 next();
7463 v2 = expr_const();
7464 if (v2 < v1)
7465 warning("empty case range");
7467 /* since a case is like a label, we must skip it with a jmp */
7468 b = gjmp(0);
7469 gsym(*case_sym);
7470 vseti(case_reg, 0);
7471 vpushi(v1);
7472 if (v1 == v2) {
7473 gen_op(TOK_EQ);
7474 *case_sym = gtst(1, 0);
7475 } else {
7476 gen_op(TOK_GE);
7477 *case_sym = gtst(1, 0);
7478 vseti(case_reg, 0);
7479 vpushi(v2);
7480 gen_op(TOK_LE);
7481 *case_sym = gtst(1, *case_sym);
7483 gsym(b);
7484 skip(':');
7485 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7486 } else
7487 if (tok == TOK_DEFAULT) {
7488 next();
7489 skip(':');
7490 if (!def_sym)
7491 expect("switch");
7492 if (*def_sym)
7493 error("too many 'default'");
7494 *def_sym = ind;
7495 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7496 } else
7497 if (tok == TOK_GOTO) {
7498 next();
7499 if (tok == '*' && gnu_ext) {
7500 /* computed goto */
7501 next();
7502 gexpr();
7503 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7504 expect("pointer");
7505 ggoto();
7506 } else if (tok >= TOK_UIDENT) {
7507 s = label_find(tok);
7508 /* put forward definition if needed */
7509 if (!s) {
7510 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7511 } else {
7512 if (s->r == LABEL_DECLARED)
7513 s->r = LABEL_FORWARD;
7515 /* label already defined */
7516 if (s->r & LABEL_FORWARD)
7517 s->next = (void *)gjmp((long)s->next);
7518 else
7519 gjmp_addr((long)s->next);
7520 next();
7521 } else {
7522 expect("label identifier");
7524 skip(';');
7525 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7526 asm_instr();
7527 } else {
7528 b = is_label();
7529 if (b) {
7530 /* label case */
7531 s = label_find(b);
7532 if (s) {
7533 if (s->r == LABEL_DEFINED)
7534 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7535 gsym((long)s->next);
7536 s->r = LABEL_DEFINED;
7537 } else {
7538 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7540 s->next = (void *)ind;
7541 /* we accept this, but it is a mistake */
7542 if (tok == '}') {
7543 warning("deprecated use of label at end of compound statement");
7544 } else {
7545 if (is_expr)
7546 vpop();
7547 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7549 } else {
7550 /* expression case */
7551 if (tok != ';') {
7552 if (is_expr) {
7553 vpop();
7554 gexpr();
7555 } else {
7556 gexpr();
7557 vpop();
7560 skip(';');
7565 /* t is the array or struct type. c is the array or struct
7566 address. cur_index/cur_field is the pointer to the current
7567 value. 'size_only' is true if only size info is needed (only used
7568 in arrays) */
7569 static void decl_designator(CType *type, Section *sec, unsigned long c,
7570 int *cur_index, Sym **cur_field,
7571 int size_only)
7573 Sym *s, *f;
7574 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7575 CType type1;
7577 notfirst = 0;
7578 elem_size = 0;
7579 nb_elems = 1;
7580 if (gnu_ext && (l = is_label()) != 0)
7581 goto struct_field;
7582 while (tok == '[' || tok == '.') {
7583 if (tok == '[') {
7584 if (!(type->t & VT_ARRAY))
7585 expect("array type");
7586 s = type->ref;
7587 next();
7588 index = expr_const();
7589 if (index < 0 || (s->c >= 0 && index >= s->c))
7590 expect("invalid index");
7591 if (tok == TOK_DOTS && gnu_ext) {
7592 next();
7593 index_last = expr_const();
7594 if (index_last < 0 ||
7595 (s->c >= 0 && index_last >= s->c) ||
7596 index_last < index)
7597 expect("invalid index");
7598 } else {
7599 index_last = index;
7601 skip(']');
7602 if (!notfirst)
7603 *cur_index = index_last;
7604 type = pointed_type(type);
7605 elem_size = type_size(type, &align);
7606 c += index * elem_size;
7607 /* NOTE: we only support ranges for last designator */
7608 nb_elems = index_last - index + 1;
7609 if (nb_elems != 1) {
7610 notfirst = 1;
7611 break;
7613 } else {
7614 next();
7615 l = tok;
7616 next();
7617 struct_field:
7618 if ((type->t & VT_BTYPE) != VT_STRUCT)
7619 expect("struct/union type");
7620 s = type->ref;
7621 l |= SYM_FIELD;
7622 f = s->next;
7623 while (f) {
7624 if (f->v == l)
7625 break;
7626 f = f->next;
7628 if (!f)
7629 expect("field");
7630 if (!notfirst)
7631 *cur_field = f;
7632 /* XXX: fix this mess by using explicit storage field */
7633 type1 = f->type;
7634 type1.t |= (type->t & ~VT_TYPE);
7635 type = &type1;
7636 c += f->c;
7638 notfirst = 1;
7640 if (notfirst) {
7641 if (tok == '=') {
7642 next();
7643 } else {
7644 if (!gnu_ext)
7645 expect("=");
7647 } else {
7648 if (type->t & VT_ARRAY) {
7649 index = *cur_index;
7650 type = pointed_type(type);
7651 c += index * type_size(type, &align);
7652 } else {
7653 f = *cur_field;
7654 if (!f)
7655 error("too many field init");
7656 /* XXX: fix this mess by using explicit storage field */
7657 type1 = f->type;
7658 type1.t |= (type->t & ~VT_TYPE);
7659 type = &type1;
7660 c += f->c;
7663 decl_initializer(type, sec, c, 0, size_only);
7665 /* XXX: make it more general */
7666 if (!size_only && nb_elems > 1) {
7667 unsigned long c_end;
7668 uint8_t *src, *dst;
7669 int i;
7671 if (!sec)
7672 error("range init not supported yet for dynamic storage");
7673 c_end = c + nb_elems * elem_size;
7674 if (c_end > sec->data_allocated)
7675 section_realloc(sec, c_end);
7676 src = sec->data + c;
7677 dst = src;
7678 for(i = 1; i < nb_elems; i++) {
7679 dst += elem_size;
7680 memcpy(dst, src, elem_size);
7685 #define EXPR_VAL 0
7686 #define EXPR_CONST 1
7687 #define EXPR_ANY 2
7689 /* store a value or an expression directly in global data or in local array */
7690 static void init_putv(CType *type, Section *sec, unsigned long c,
7691 int v, int expr_type)
7693 int saved_global_expr, bt, bit_pos, bit_size;
7694 void *ptr;
7695 unsigned long long bit_mask;
7697 switch(expr_type) {
7698 case EXPR_VAL:
7699 vpushi(v);
7700 break;
7701 case EXPR_CONST:
7702 /* compound literals must be allocated globally in this case */
7703 saved_global_expr = global_expr;
7704 global_expr = 1;
7705 expr_const1();
7706 global_expr = saved_global_expr;
7707 /* NOTE: symbols are accepted */
7708 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
7709 error("initializer element is not constant");
7710 break;
7711 case EXPR_ANY:
7712 expr_eq();
7713 break;
7716 if (sec) {
7717 /* XXX: not portable */
7718 /* XXX: generate error if incorrect relocation */
7719 gen_assign_cast(type);
7720 bt = type->t & VT_BTYPE;
7721 ptr = sec->data + c;
7722 /* XXX: make code faster ? */
7723 if (!(type->t & VT_BITFIELD)) {
7724 bit_pos = 0;
7725 bit_size = 32;
7726 bit_mask = -1LL;
7727 } else {
7728 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
7729 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
7730 bit_mask = (1LL << bit_size) - 1;
7732 if ((vtop->r & VT_SYM) &&
7733 (bt == VT_BYTE ||
7734 bt == VT_SHORT ||
7735 bt == VT_DOUBLE ||
7736 bt == VT_LDOUBLE ||
7737 bt == VT_LLONG ||
7738 (bt == VT_INT && bit_size != 32)))
7739 error("initializer element is not computable at load time");
7740 switch(bt) {
7741 case VT_BYTE:
7742 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7743 break;
7744 case VT_SHORT:
7745 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7746 break;
7747 case VT_DOUBLE:
7748 *(double *)ptr = vtop->c.d;
7749 break;
7750 case VT_LDOUBLE:
7751 *(long double *)ptr = vtop->c.ld;
7752 break;
7753 case VT_LLONG:
7754 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
7755 break;
7756 default:
7757 if (vtop->r & VT_SYM) {
7758 greloc(sec, vtop->sym, c, R_DATA_32);
7760 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7761 break;
7763 vtop--;
7764 } else {
7765 vset(type, VT_LOCAL, c);
7766 vswap();
7767 vstore();
7768 vpop();
7772 /* put zeros for variable based init */
7773 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
7775 GFuncContext gf;
7777 if (sec) {
7778 /* nothing to do because globals are already set to zero */
7779 } else {
7780 gfunc_start(&gf, FUNC_CDECL);
7781 vpushi(size);
7782 gfunc_param(&gf);
7783 vpushi(0);
7784 gfunc_param(&gf);
7785 vseti(VT_LOCAL, c);
7786 gfunc_param(&gf);
7787 vpush_global_sym(&func_old_type, TOK_memset);
7788 gfunc_call(&gf);
7792 /* 't' contains the type and storage info. 'c' is the offset of the
7793 object in section 'sec'. If 'sec' is NULL, it means stack based
7794 allocation. 'first' is true if array '{' must be read (multi
7795 dimension implicit array init handling). 'size_only' is true if
7796 size only evaluation is wanted (only for arrays). */
7797 static void decl_initializer(CType *type, Section *sec, unsigned long c,
7798 int first, int size_only)
7800 int index, array_length, n, no_oblock, nb, parlevel, i;
7801 int size1, align1, expr_type;
7802 Sym *s, *f;
7803 CType *t1;
7805 if (type->t & VT_ARRAY) {
7806 s = type->ref;
7807 n = s->c;
7808 array_length = 0;
7809 t1 = pointed_type(type);
7810 size1 = type_size(t1, &align1);
7812 no_oblock = 1;
7813 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
7814 tok == '{') {
7815 skip('{');
7816 no_oblock = 0;
7819 /* only parse strings here if correct type (otherwise: handle
7820 them as ((w)char *) expressions */
7821 if ((tok == TOK_LSTR &&
7822 (t1->t & VT_BTYPE) == VT_INT) ||
7823 (tok == TOK_STR &&
7824 (t1->t & VT_BTYPE) == VT_BYTE)) {
7825 while (tok == TOK_STR || tok == TOK_LSTR) {
7826 int cstr_len, ch;
7827 CString *cstr;
7829 cstr = tokc.cstr;
7830 /* compute maximum number of chars wanted */
7831 if (tok == TOK_STR)
7832 cstr_len = cstr->size;
7833 else
7834 cstr_len = cstr->size / sizeof(int);
7835 cstr_len--;
7836 nb = cstr_len;
7837 if (n >= 0 && nb > (n - array_length))
7838 nb = n - array_length;
7839 if (!size_only) {
7840 if (cstr_len > nb)
7841 warning("initializer-string for array is too long");
7842 /* in order to go faster for common case (char
7843 string in global variable, we handle it
7844 specifically */
7845 if (sec && tok == TOK_STR && size1 == 1) {
7846 memcpy(sec->data + c + array_length, cstr->data, nb);
7847 } else {
7848 for(i=0;i<nb;i++) {
7849 if (tok == TOK_STR)
7850 ch = ((unsigned char *)cstr->data)[i];
7851 else
7852 ch = ((int *)cstr->data)[i];
7853 init_putv(t1, sec, c + (array_length + i) * size1,
7854 ch, EXPR_VAL);
7858 array_length += nb;
7859 next();
7861 /* only add trailing zero if enough storage (no
7862 warning in this case since it is standard) */
7863 if (n < 0 || array_length < n) {
7864 if (!size_only) {
7865 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
7867 array_length++;
7869 } else {
7870 index = 0;
7871 while (tok != '}') {
7872 decl_designator(type, sec, c, &index, NULL, size_only);
7873 if (n >= 0 && index >= n)
7874 error("index too large");
7875 /* must put zero in holes (note that doing it that way
7876 ensures that it even works with designators) */
7877 if (!size_only && array_length < index) {
7878 init_putz(t1, sec, c + array_length * size1,
7879 (index - array_length) * size1);
7881 index++;
7882 if (index > array_length)
7883 array_length = index;
7884 /* special test for multi dimensional arrays (may not
7885 be strictly correct if designators are used at the
7886 same time) */
7887 if (index >= n && no_oblock)
7888 break;
7889 if (tok == '}')
7890 break;
7891 skip(',');
7894 if (!no_oblock)
7895 skip('}');
7896 /* put zeros at the end */
7897 if (!size_only && n >= 0 && array_length < n) {
7898 init_putz(t1, sec, c + array_length * size1,
7899 (n - array_length) * size1);
7901 /* patch type size if needed */
7902 if (n < 0)
7903 s->c = array_length;
7904 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
7905 (sec || !first || tok == '{')) {
7906 int par_count;
7908 /* NOTE: the previous test is a specific case for automatic
7909 struct/union init */
7910 /* XXX: union needs only one init */
7912 /* XXX: this test is incorrect for local initializers
7913 beginning with ( without {. It would be much more difficult
7914 to do it correctly (ideally, the expression parser should
7915 be used in all cases) */
7916 par_count = 0;
7917 if (tok == '(') {
7918 AttributeDef ad1;
7919 CType type1;
7920 next();
7921 while (tok == '(') {
7922 par_count++;
7923 next();
7925 if (!parse_btype(&type1, &ad1))
7926 expect("cast");
7927 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
7928 if (!is_compatible_types(type, &type1))
7929 error("invalid type for cast");
7930 skip(')');
7932 no_oblock = 1;
7933 if (first || tok == '{') {
7934 skip('{');
7935 no_oblock = 0;
7937 s = type->ref;
7938 f = s->next;
7939 array_length = 0;
7940 index = 0;
7941 n = s->c;
7942 while (tok != '}') {
7943 decl_designator(type, sec, c, NULL, &f, size_only);
7944 index = f->c;
7945 if (!size_only && array_length < index) {
7946 init_putz(type, sec, c + array_length,
7947 index - array_length);
7949 index = index + type_size(&f->type, &align1);
7950 if (index > array_length)
7951 array_length = index;
7952 f = f->next;
7953 if (no_oblock && f == NULL)
7954 break;
7955 if (tok == '}')
7956 break;
7957 skip(',');
7959 /* put zeros at the end */
7960 if (!size_only && array_length < n) {
7961 init_putz(type, sec, c + array_length,
7962 n - array_length);
7964 if (!no_oblock)
7965 skip('}');
7966 while (par_count) {
7967 skip(')');
7968 par_count--;
7970 } else if (tok == '{') {
7971 next();
7972 decl_initializer(type, sec, c, first, size_only);
7973 skip('}');
7974 } else if (size_only) {
7975 /* just skip expression */
7976 parlevel = 0;
7977 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
7978 tok != -1) {
7979 if (tok == '(')
7980 parlevel++;
7981 else if (tok == ')')
7982 parlevel--;
7983 next();
7985 } else {
7986 /* currently, we always use constant expression for globals
7987 (may change for scripting case) */
7988 expr_type = EXPR_CONST;
7989 if (!sec)
7990 expr_type = EXPR_ANY;
7991 init_putv(type, sec, c, 0, expr_type);
7995 /* parse an initializer for type 't' if 'has_init' is non zero, and
7996 allocate space in local or global data space ('r' is either
7997 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
7998 variable 'v' of scope 'scope' is declared before initializers are
7999 parsed. If 'v' is zero, then a reference to the new object is put
8000 in the value stack. If 'has_init' is 2, a special parsing is done
8001 to handle string constants. */
8002 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8003 int has_init, int v, int scope)
8005 int size, align, addr, data_offset;
8006 int level;
8007 ParseState saved_parse_state;
8008 TokenString init_str;
8009 Section *sec;
8011 size = type_size(type, &align);
8012 /* If unknown size, we must evaluate it before
8013 evaluating initializers because
8014 initializers can generate global data too
8015 (e.g. string pointers or ISOC99 compound
8016 literals). It also simplifies local
8017 initializers handling */
8018 tok_str_new(&init_str);
8019 if (size < 0) {
8020 if (!has_init)
8021 error("unknown type size");
8022 /* get all init string */
8023 if (has_init == 2) {
8024 /* only get strings */
8025 while (tok == TOK_STR || tok == TOK_LSTR) {
8026 tok_str_add_tok(&init_str);
8027 next();
8029 } else {
8030 level = 0;
8031 while (level > 0 || (tok != ',' && tok != ';')) {
8032 if (tok < 0)
8033 error("unexpected end of file in initializer");
8034 tok_str_add_tok(&init_str);
8035 if (tok == '{')
8036 level++;
8037 else if (tok == '}') {
8038 if (level == 0)
8039 break;
8040 level--;
8042 next();
8045 tok_str_add(&init_str, -1);
8046 tok_str_add(&init_str, 0);
8048 /* compute size */
8049 save_parse_state(&saved_parse_state);
8051 macro_ptr = init_str.str;
8052 next();
8053 decl_initializer(type, NULL, 0, 1, 1);
8054 /* prepare second initializer parsing */
8055 macro_ptr = init_str.str;
8056 next();
8058 /* if still unknown size, error */
8059 size = type_size(type, &align);
8060 if (size < 0)
8061 error("unknown type size");
8063 /* take into account specified alignment if bigger */
8064 if (ad->aligned > align)
8065 align = ad->aligned;
8066 if ((r & VT_VALMASK) == VT_LOCAL) {
8067 sec = NULL;
8068 if (do_bounds_check && (type->t & VT_ARRAY))
8069 loc--;
8070 loc = (loc - size) & -align;
8071 addr = loc;
8072 /* handles bounds */
8073 /* XXX: currently, since we do only one pass, we cannot track
8074 '&' operators, so we add only arrays */
8075 if (do_bounds_check && (type->t & VT_ARRAY)) {
8076 unsigned long *bounds_ptr;
8077 /* add padding between regions */
8078 loc--;
8079 /* then add local bound info */
8080 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8081 bounds_ptr[0] = addr;
8082 bounds_ptr[1] = size;
8084 if (v) {
8085 /* local variable */
8086 sym_push(v, type, r, addr);
8087 } else {
8088 /* push local reference */
8089 vset(type, r, addr);
8091 } else {
8092 Sym *sym;
8094 sym = NULL;
8095 if (v && scope == VT_CONST) {
8096 /* see if the symbol was already defined */
8097 sym = sym_find(v);
8098 if (sym) {
8099 if (!is_compatible_types(&sym->type, type))
8100 error("incompatible types for redefinition of '%s'",
8101 get_tok_str(v, NULL));
8102 if (sym->type.t & VT_EXTERN) {
8103 /* if the variable is extern, it was not allocated */
8104 sym->type.t &= ~VT_EXTERN;
8105 } else {
8106 /* we accept several definitions of the same
8107 global variable. this is tricky, because we
8108 must play with the SHN_COMMON type of the symbol */
8109 /* XXX: should check if the variable was already
8110 initialized. It is incorrect to initialized it
8111 twice */
8112 /* no init data, we won't add more to the symbol */
8113 if (!has_init)
8114 goto no_alloc;
8119 /* allocate symbol in corresponding section */
8120 sec = ad->section;
8121 if (!sec) {
8122 if (has_init)
8123 sec = data_section;
8125 if (sec) {
8126 data_offset = sec->data_offset;
8127 data_offset = (data_offset + align - 1) & -align;
8128 addr = data_offset;
8129 /* very important to increment global pointer at this time
8130 because initializers themselves can create new initializers */
8131 data_offset += size;
8132 /* add padding if bound check */
8133 if (do_bounds_check)
8134 data_offset++;
8135 sec->data_offset = data_offset;
8136 /* allocate section space to put the data */
8137 if (sec->sh_type != SHT_NOBITS &&
8138 data_offset > sec->data_allocated)
8139 section_realloc(sec, data_offset);
8140 } else {
8141 addr = 0; /* avoid warning */
8144 if (v) {
8145 if (scope == VT_CONST) {
8146 if (!sym)
8147 goto do_def;
8148 } else {
8149 do_def:
8150 sym = sym_push(v, type, r | VT_SYM, 0);
8152 /* update symbol definition */
8153 if (sec) {
8154 put_extern_sym(sym, sec, addr, size);
8155 } else {
8156 Elf32_Sym *esym;
8157 /* put a common area */
8158 put_extern_sym(sym, NULL, align, size);
8159 /* XXX: find a nicer way */
8160 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8161 esym->st_shndx = SHN_COMMON;
8163 } else {
8164 CValue cval;
8166 /* push global reference */
8167 sym = get_sym_ref(type, sec, addr, size);
8168 cval.ul = 0;
8169 vsetc(type, VT_CONST | VT_SYM, &cval);
8170 vtop->sym = sym;
8173 /* handles bounds now because the symbol must be defined
8174 before for the relocation */
8175 if (do_bounds_check) {
8176 unsigned long *bounds_ptr;
8178 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8179 /* then add global bound info */
8180 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8181 bounds_ptr[0] = 0; /* relocated */
8182 bounds_ptr[1] = size;
8185 if (has_init) {
8186 decl_initializer(type, sec, addr, 1, 0);
8187 /* restore parse state if needed */
8188 if (init_str.str) {
8189 tok_str_free(init_str.str);
8190 restore_parse_state(&saved_parse_state);
8193 no_alloc: ;
8196 void put_func_debug(Sym *sym)
8198 char buf[512];
8200 /* stabs info */
8201 /* XXX: we put here a dummy type */
8202 snprintf(buf, sizeof(buf), "%s:%c1",
8203 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8204 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8205 cur_text_section, sym->c);
8206 last_ind = 0;
8207 last_line_num = 0;
8210 /* not finished : try to put some local vars in registers */
8211 //#define CONFIG_REG_VARS
8213 #ifdef CONFIG_REG_VARS
8214 void add_var_ref(int t)
8216 printf("%s:%d: &%s\n",
8217 file->filename, file->line_num,
8218 get_tok_str(t, NULL));
8221 /* first pass on a function with heuristic to extract variable usage
8222 and pointer references to local variables for register allocation */
8223 void analyse_function(void)
8225 int level, t;
8227 for(;;) {
8228 if (tok == -1)
8229 break;
8230 /* any symbol coming after '&' is considered as being a
8231 variable whose reference is taken. It is highly unaccurate
8232 but it is difficult to do better without a complete parse */
8233 if (tok == '&') {
8234 next();
8235 /* if '& number', then no need to examine next tokens */
8236 if (tok == TOK_CINT ||
8237 tok == TOK_CUINT ||
8238 tok == TOK_CLLONG ||
8239 tok == TOK_CULLONG) {
8240 continue;
8241 } else if (tok >= TOK_UIDENT) {
8242 /* if '& ident [' or '& ident ->', then ident address
8243 is not needed */
8244 t = tok;
8245 next();
8246 if (tok != '[' && tok != TOK_ARROW)
8247 add_var_ref(t);
8248 } else {
8249 level = 0;
8250 while (tok != '}' && tok != ';' &&
8251 !((tok == ',' || tok == ')') && level == 0)) {
8252 if (tok >= TOK_UIDENT) {
8253 add_var_ref(tok);
8254 } else if (tok == '(') {
8255 level++;
8256 } else if (tok == ')') {
8257 level--;
8259 next();
8262 } else {
8263 next();
8267 #endif
8269 /* parse an old style function declaration list */
8270 /* XXX: check multiple parameter */
8271 static void func_decl_list(Sym *func_sym)
8273 AttributeDef ad;
8274 int v;
8275 Sym *s;
8276 CType btype, type;
8278 /* parse each declaration */
8279 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8280 if (!parse_btype(&btype, &ad))
8281 expect("declaration list");
8282 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8283 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8284 tok == ';') {
8285 /* we accept no variable after */
8286 } else {
8287 for(;;) {
8288 type = btype;
8289 type_decl(&type, &ad, &v, TYPE_DIRECT);
8290 /* find parameter in function parameter list */
8291 s = func_sym->next;
8292 while (s != NULL) {
8293 if ((s->v & ~SYM_FIELD) == v)
8294 goto found;
8295 s = s->next;
8297 error("declaration for parameter '%s' but no such parameter",
8298 get_tok_str(v, NULL));
8299 found:
8300 /* check that no storage specifier except 'register' was given */
8301 if (type.t & VT_STORAGE)
8302 error("storage class specified for '%s'", get_tok_str(v, NULL));
8303 convert_parameter_type(&type);
8304 /* we can add the type (NOTE: it could be local to the function) */
8305 s->type = type;
8306 /* accept other parameters */
8307 if (tok == ',')
8308 next();
8309 else
8310 break;
8313 skip(';');
8317 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8318 static void decl(int l)
8320 int v, has_init, r;
8321 CType type, btype;
8322 Sym *sym;
8323 AttributeDef ad;
8325 while (1) {
8326 if (!parse_btype(&btype, &ad)) {
8327 /* skip redundant ';' */
8328 /* XXX: find more elegant solution */
8329 if (tok == ';') {
8330 next();
8331 continue;
8333 /* special test for old K&R protos without explicit int
8334 type. Only accepted when defining global data */
8335 if (l == VT_LOCAL || tok < TOK_DEFINE)
8336 break;
8337 btype.t = VT_INT;
8339 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8340 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8341 tok == ';') {
8342 /* we accept no variable after */
8343 next();
8344 continue;
8346 while (1) { /* iterate thru each declaration */
8347 type = btype;
8348 type_decl(&type, &ad, &v, TYPE_DIRECT);
8349 #if 0
8351 char buf[500];
8352 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8353 printf("type = '%s'\n", buf);
8355 #endif
8356 if ((type.t & VT_BTYPE) == VT_FUNC) {
8357 /* if old style function prototype, we accept a
8358 declaration list */
8359 sym = type.ref;
8360 if (sym->c == FUNC_OLD)
8361 func_decl_list(sym);
8364 if (tok == '{') {
8365 #ifdef CONFIG_REG_VARS
8366 TokenString func_str;
8367 ParseState saved_parse_state;
8368 int block_level;
8369 #endif
8371 if (l == VT_LOCAL)
8372 error("cannot use local functions");
8373 if (!(type.t & VT_FUNC))
8374 expect("function definition");
8375 /* XXX: cannot do better now: convert extern line to static inline */
8376 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8377 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8379 #ifdef CONFIG_REG_VARS
8380 /* parse all function code and record it */
8382 tok_str_new(&func_str);
8384 block_level = 0;
8385 for(;;) {
8386 int t;
8387 if (tok == -1)
8388 error("unexpected end of file");
8389 tok_str_add_tok(&func_str);
8390 t = tok;
8391 next();
8392 if (t == '{') {
8393 block_level++;
8394 } else if (t == '}') {
8395 block_level--;
8396 if (block_level == 0)
8397 break;
8400 tok_str_add(&func_str, -1);
8401 tok_str_add(&func_str, 0);
8403 save_parse_state(&saved_parse_state);
8405 macro_ptr = func_str.str;
8406 next();
8407 analyse_function();
8408 #endif
8410 /* compute text section */
8411 cur_text_section = ad.section;
8412 if (!cur_text_section)
8413 cur_text_section = text_section;
8414 ind = cur_text_section->data_offset;
8415 funcname = get_tok_str(v, NULL);
8416 sym = sym_find(v);
8417 if (sym) {
8418 /* if symbol is already defined, then put complete type */
8419 sym->type = type;
8420 } else {
8421 /* put function symbol */
8422 sym = global_identifier_push(v, type.t, 0);
8423 sym->type.ref = type.ref;
8425 /* NOTE: we patch the symbol size later */
8426 put_extern_sym(sym, cur_text_section, ind, 0);
8427 func_ind = ind;
8428 sym->r = VT_SYM | VT_CONST;
8429 /* put debug symbol */
8430 if (do_debug)
8431 put_func_debug(sym);
8432 /* push a dummy symbol to enable local sym storage */
8433 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8434 gfunc_prolog(&type);
8435 loc = 0;
8436 rsym = 0;
8437 #ifdef CONFIG_REG_VARS
8438 macro_ptr = func_str.str;
8439 next();
8440 #endif
8441 block(NULL, NULL, NULL, NULL, 0, 0);
8442 gsym(rsym);
8443 gfunc_epilog();
8444 cur_text_section->data_offset = ind;
8445 label_pop(&global_label_stack, NULL);
8446 sym_pop(&local_stack, NULL); /* reset local stack */
8447 /* end of function */
8448 /* patch symbol size */
8449 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8450 ind - func_ind;
8451 if (do_debug) {
8452 put_stabn(N_FUN, 0, 0, ind - func_ind);
8454 funcname = ""; /* for safety */
8455 func_vt.t = VT_VOID; /* for safety */
8456 ind = 0; /* for safety */
8458 #ifdef CONFIG_REG_VARS
8459 tok_str_free(func_str.str);
8460 restore_parse_state(&saved_parse_state);
8461 #endif
8462 break;
8463 } else {
8464 if (btype.t & VT_TYPEDEF) {
8465 /* save typedefed type */
8466 /* XXX: test storage specifiers ? */
8467 sym = sym_push(v, &type, 0, 0);
8468 sym->type.t |= VT_TYPEDEF;
8469 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8470 /* external function definition */
8471 external_sym(v, &type, 0);
8472 } else {
8473 /* not lvalue if array */
8474 r = 0;
8475 if (!(type.t & VT_ARRAY))
8476 r |= lvalue_type(type.t);
8477 has_init = (tok == '=');
8478 if ((btype.t & VT_EXTERN) ||
8479 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8480 !has_init && l == VT_CONST && type.ref->c < 0)) {
8481 /* external variable */
8482 /* NOTE: as GCC, uninitialized global static
8483 arrays of null size are considered as
8484 extern */
8485 external_sym(v, &type, r);
8486 } else {
8487 if (type.t & VT_STATIC)
8488 r |= VT_CONST;
8489 else
8490 r |= l;
8491 if (has_init)
8492 next();
8493 decl_initializer_alloc(&type, &ad, r,
8494 has_init, v, l);
8497 if (tok != ',') {
8498 skip(';');
8499 break;
8501 next();
8507 /* better than nothing, but needs extension to handle '-E' option
8508 correctly too */
8509 static void preprocess_init(TCCState *s1)
8511 s1->include_stack_ptr = s1->include_stack;
8512 /* XXX: move that before to avoid having to initialize
8513 file->ifdef_stack_ptr ? */
8514 s1->ifdef_stack_ptr = s1->ifdef_stack;
8515 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8517 /* XXX: not ANSI compliant: bound checking says error */
8518 vtop = vstack - 1;
8521 /* compile the C file opened in 'file'. Return non zero if errors. */
8522 static int tcc_compile(TCCState *s1)
8524 Sym *define_start;
8525 char buf[512];
8526 volatile int section_sym;
8528 #ifdef INC_DEBUG
8529 printf("%s: **** new file\n", file->filename);
8530 #endif
8531 preprocess_init(s1);
8533 funcname = "";
8534 anon_sym = SYM_FIRST_ANOM;
8536 /* file info: full path + filename */
8537 section_sym = 0; /* avoid warning */
8538 if (do_debug) {
8539 section_sym = put_elf_sym(symtab_section, 0, 0,
8540 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8541 text_section->sh_num, NULL);
8542 getcwd(buf, sizeof(buf));
8543 pstrcat(buf, sizeof(buf), "/");
8544 put_stabs_r(buf, N_SO, 0, 0,
8545 text_section->data_offset, text_section, section_sym);
8546 put_stabs_r(file->filename, N_SO, 0, 0,
8547 text_section->data_offset, text_section, section_sym);
8549 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8550 symbols can be safely used */
8551 put_elf_sym(symtab_section, 0, 0,
8552 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8553 SHN_ABS, file->filename);
8555 /* define some often used types */
8556 int_type.t = VT_INT;
8558 char_pointer_type.t = VT_BYTE;
8559 mk_pointer(&char_pointer_type);
8561 func_old_type.t = VT_FUNC;
8562 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8564 #if 0
8565 /* define 'void *alloca(unsigned int)' builtin function */
8567 Sym *s1;
8569 p = anon_sym++;
8570 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8571 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8572 s1->next = NULL;
8573 sym->next = s1;
8574 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8576 #endif
8578 define_start = define_stack;
8580 if (setjmp(s1->error_jmp_buf) == 0) {
8581 s1->nb_errors = 0;
8582 s1->error_set_jmp_enabled = 1;
8584 ch = file->buf_ptr[0];
8585 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8586 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8587 next();
8588 decl(VT_CONST);
8589 if (tok != -1)
8590 expect("declaration");
8592 /* end of translation unit info */
8593 if (do_debug) {
8594 put_stabs_r(NULL, N_SO, 0, 0,
8595 text_section->data_offset, text_section, section_sym);
8598 s1->error_set_jmp_enabled = 0;
8600 /* reset define stack, but leave -Dsymbols (may be incorrect if
8601 they are undefined) */
8602 free_defines(define_start);
8604 sym_pop(&global_stack, NULL);
8606 return s1->nb_errors != 0 ? -1 : 0;
8609 #ifdef LIBTCC
8610 int tcc_compile_string(TCCState *s, const char *str)
8612 BufferedFile bf1, *bf = &bf1;
8613 int ret, len;
8614 char *buf;
8616 /* init file structure */
8617 bf->fd = -1;
8618 /* XXX: avoid copying */
8619 len = strlen(str);
8620 buf = tcc_malloc(len + 1);
8621 if (!buf)
8622 return -1;
8623 memcpy(buf, str, len);
8624 buf[len] = CH_EOB;
8625 bf->buf_ptr = buf;
8626 bf->buf_end = buf + len;
8627 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8628 bf->line_num = 1;
8629 file = bf;
8631 ret = tcc_compile(s);
8633 tcc_free(buf);
8635 /* currently, no need to close */
8636 return ret;
8638 #endif
8640 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8641 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8643 BufferedFile bf1, *bf = &bf1;
8645 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8646 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8647 /* default value */
8648 if (!value)
8649 value = "1";
8650 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8652 /* init file structure */
8653 bf->fd = -1;
8654 bf->buf_ptr = bf->buffer;
8655 bf->buf_end = bf->buffer + strlen(bf->buffer);
8656 *bf->buf_end = CH_EOB;
8657 bf->filename[0] = '\0';
8658 bf->line_num = 1;
8659 file = bf;
8661 s1->include_stack_ptr = s1->include_stack;
8663 /* parse with define parser */
8664 ch = file->buf_ptr[0];
8665 next_nomacro();
8666 parse_define();
8667 file = NULL;
8670 /* undefine a preprocessor symbol */
8671 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8673 TokenSym *ts;
8674 Sym *s;
8675 ts = tok_alloc(sym, strlen(sym));
8676 s = define_find(ts->tok);
8677 /* undefine symbol by putting an invalid name */
8678 if (s)
8679 define_undef(s);
8682 #ifdef CONFIG_TCC_ASM
8684 #include "i386-asm.c"
8685 #include "tccasm.c"
8687 #else
8688 static void asm_instr(void)
8690 error("inline asm() not supported");
8692 #endif
8694 #include "tccelf.c"
8696 /* print the position in the source file of PC value 'pc' by reading
8697 the stabs debug information */
8698 static void rt_printline(unsigned long wanted_pc)
8700 Stab_Sym *sym, *sym_end;
8701 char func_name[128], last_func_name[128];
8702 unsigned long func_addr, last_pc, pc;
8703 const char *incl_files[INCLUDE_STACK_SIZE];
8704 int incl_index, len, last_line_num, i;
8705 const char *str, *p;
8707 fprintf(stderr, "0x%08lx:", wanted_pc);
8709 func_name[0] = '\0';
8710 func_addr = 0;
8711 incl_index = 0;
8712 last_func_name[0] = '\0';
8713 last_pc = 0xffffffff;
8714 last_line_num = 1;
8715 sym = (Stab_Sym *)stab_section->data + 1;
8716 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
8717 while (sym < sym_end) {
8718 switch(sym->n_type) {
8719 /* function start or end */
8720 case N_FUN:
8721 if (sym->n_strx == 0) {
8722 /* we test if between last line and end of function */
8723 pc = sym->n_value + func_addr;
8724 if (wanted_pc >= last_pc && wanted_pc < pc)
8725 goto found;
8726 func_name[0] = '\0';
8727 func_addr = 0;
8728 } else {
8729 str = stabstr_section->data + sym->n_strx;
8730 p = strchr(str, ':');
8731 if (!p) {
8732 pstrcpy(func_name, sizeof(func_name), str);
8733 } else {
8734 len = p - str;
8735 if (len > sizeof(func_name) - 1)
8736 len = sizeof(func_name) - 1;
8737 memcpy(func_name, str, len);
8738 func_name[len] = '\0';
8740 func_addr = sym->n_value;
8742 break;
8743 /* line number info */
8744 case N_SLINE:
8745 pc = sym->n_value + func_addr;
8746 if (wanted_pc >= last_pc && wanted_pc < pc)
8747 goto found;
8748 last_pc = pc;
8749 last_line_num = sym->n_desc;
8750 /* XXX: slow! */
8751 strcpy(last_func_name, func_name);
8752 break;
8753 /* include files */
8754 case N_BINCL:
8755 str = stabstr_section->data + sym->n_strx;
8756 add_incl:
8757 if (incl_index < INCLUDE_STACK_SIZE) {
8758 incl_files[incl_index++] = str;
8760 break;
8761 case N_EINCL:
8762 if (incl_index > 1)
8763 incl_index--;
8764 break;
8765 case N_SO:
8766 if (sym->n_strx == 0) {
8767 incl_index = 0; /* end of translation unit */
8768 } else {
8769 str = stabstr_section->data + sym->n_strx;
8770 /* do not add path */
8771 len = strlen(str);
8772 if (len > 0 && str[len - 1] != '/')
8773 goto add_incl;
8775 break;
8777 sym++;
8780 /* second pass: we try symtab symbols (no line number info) */
8781 incl_index = 0;
8783 Elf32_Sym *sym, *sym_end;
8784 int type;
8786 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
8787 for(sym = (Elf32_Sym *)symtab_section->data + 1;
8788 sym < sym_end;
8789 sym++) {
8790 type = ELF32_ST_TYPE(sym->st_info);
8791 if (type == STT_FUNC) {
8792 if (wanted_pc >= sym->st_value &&
8793 wanted_pc < sym->st_value + sym->st_size) {
8794 pstrcpy(last_func_name, sizeof(last_func_name),
8795 strtab_section->data + sym->st_name);
8796 goto found;
8801 /* did not find any info: */
8802 fprintf(stderr, " ???\n");
8803 return;
8804 found:
8805 if (last_func_name[0] != '\0') {
8806 fprintf(stderr, " %s()", last_func_name);
8808 if (incl_index > 0) {
8809 fprintf(stderr, " (%s:%d",
8810 incl_files[incl_index - 1], last_line_num);
8811 for(i = incl_index - 2; i >= 0; i--)
8812 fprintf(stderr, ", included from %s", incl_files[i]);
8813 fprintf(stderr, ")");
8815 fprintf(stderr, "\n");
8818 #ifndef WIN32
8820 #ifdef __i386__
8822 /* fix for glibc 2.1 */
8823 #ifndef REG_EIP
8824 #define REG_EIP EIP
8825 #define REG_EBP EBP
8826 #endif
8828 /* return the PC at frame level 'level'. Return non zero if not found */
8829 static int rt_get_caller_pc(unsigned long *paddr,
8830 ucontext_t *uc, int level)
8832 unsigned long fp;
8833 int i;
8835 if (level == 0) {
8836 #ifdef __FreeBSD__
8837 *paddr = uc->uc_mcontext.mc_eip;
8838 #else
8839 *paddr = uc->uc_mcontext.gregs[REG_EIP];
8840 #endif
8841 return 0;
8842 } else {
8843 #ifdef __FreeBSD__
8844 fp = uc->uc_mcontext.mc_ebp;
8845 #else
8846 fp = uc->uc_mcontext.gregs[REG_EBP];
8847 #endif
8848 for(i=1;i<level;i++) {
8849 /* XXX: check address validity with program info */
8850 if (fp <= 0x1000 || fp >= 0xc0000000)
8851 return -1;
8852 fp = ((unsigned long *)fp)[0];
8854 *paddr = ((unsigned long *)fp)[1];
8855 return 0;
8858 #else
8859 #error add arch specific rt_get_caller_pc()
8860 #endif
8862 /* emit a run time error at position 'pc' */
8863 void rt_error(ucontext_t *uc, const char *fmt, ...)
8865 va_list ap;
8866 unsigned long pc;
8867 int i;
8869 va_start(ap, fmt);
8870 fprintf(stderr, "Runtime error: ");
8871 vfprintf(stderr, fmt, ap);
8872 fprintf(stderr, "\n");
8873 for(i=0;i<num_callers;i++) {
8874 if (rt_get_caller_pc(&pc, uc, i) < 0)
8875 break;
8876 if (i == 0)
8877 fprintf(stderr, "at ");
8878 else
8879 fprintf(stderr, "by ");
8880 rt_printline(pc);
8882 exit(255);
8883 va_end(ap);
8886 /* signal handler for fatal errors */
8887 static void sig_error(int signum, siginfo_t *siginf, void *puc)
8889 ucontext_t *uc = puc;
8891 switch(signum) {
8892 case SIGFPE:
8893 switch(siginf->si_code) {
8894 case FPE_INTDIV:
8895 case FPE_FLTDIV:
8896 rt_error(uc, "division by zero");
8897 break;
8898 default:
8899 rt_error(uc, "floating point exception");
8900 break;
8902 break;
8903 case SIGBUS:
8904 case SIGSEGV:
8905 if (rt_bound_error_msg && *rt_bound_error_msg)
8906 rt_error(uc, *rt_bound_error_msg);
8907 else
8908 rt_error(uc, "dereferencing invalid pointer");
8909 break;
8910 case SIGILL:
8911 rt_error(uc, "illegal instruction");
8912 break;
8913 case SIGABRT:
8914 rt_error(uc, "abort() called");
8915 break;
8916 default:
8917 rt_error(uc, "caught signal %d", signum);
8918 break;
8920 exit(255);
8922 #endif
8924 /* do all relocations (needed before using tcc_get_symbol()) */
8925 int tcc_relocate(TCCState *s1)
8927 Section *s;
8928 int i;
8930 s1->nb_errors = 0;
8932 tcc_add_runtime(s1);
8934 relocate_common_syms();
8936 /* compute relocation address : section are relocated in place. We
8937 also alloc the bss space */
8938 for(i = 1; i < s1->nb_sections; i++) {
8939 s = s1->sections[i];
8940 if (s->sh_flags & SHF_ALLOC) {
8941 if (s->sh_type == SHT_NOBITS)
8942 s->data = tcc_mallocz(s->data_offset);
8943 s->sh_addr = (unsigned long)s->data;
8947 relocate_syms(s1, 1);
8949 if (s1->nb_errors != 0)
8950 return -1;
8952 /* relocate each section */
8953 for(i = 1; i < s1->nb_sections; i++) {
8954 s = s1->sections[i];
8955 if (s->reloc)
8956 relocate_section(s1, s);
8958 return 0;
8961 /* launch the compiled program with the given arguments */
8962 int tcc_run(TCCState *s1, int argc, char **argv)
8964 int (*prog_main)(int, char **);
8966 if (tcc_relocate(s1) < 0)
8967 return -1;
8969 prog_main = tcc_get_symbol(s1, "main");
8971 if (do_debug) {
8972 #ifdef WIN32
8973 error("debug mode currently not available for Windows");
8974 #else
8975 struct sigaction sigact;
8976 /* install TCC signal handlers to print debug info on fatal
8977 runtime errors */
8978 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
8979 sigact.sa_sigaction = sig_error;
8980 sigemptyset(&sigact.sa_mask);
8981 sigaction(SIGFPE, &sigact, NULL);
8982 sigaction(SIGILL, &sigact, NULL);
8983 sigaction(SIGSEGV, &sigact, NULL);
8984 sigaction(SIGBUS, &sigact, NULL);
8985 sigaction(SIGABRT, &sigact, NULL);
8986 #endif
8989 #ifdef CONFIG_TCC_BCHECK
8990 if (do_bounds_check) {
8991 void (*bound_init)(void);
8993 /* set error function */
8994 rt_bound_error_msg = (void *)tcc_get_symbol(s1, "__bound_error_msg");
8996 /* XXX: use .init section so that it also work in binary ? */
8997 bound_init = (void *)tcc_get_symbol(s1, "__bound_init");
8998 bound_init();
9000 #endif
9001 return (*prog_main)(argc, argv);
9004 TCCState *tcc_new(void)
9006 const char *p, *r;
9007 TCCState *s;
9008 TokenSym *ts;
9009 int i, c;
9011 s = tcc_mallocz(sizeof(TCCState));
9012 if (!s)
9013 return NULL;
9014 tcc_state = s;
9015 s->output_type = TCC_OUTPUT_MEMORY;
9017 /* init isid table */
9018 for(i=0;i<256;i++)
9019 isidnum_table[i] = isid(i) || isnum(i);
9021 /* add all tokens */
9022 table_ident = NULL;
9023 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9025 tok_ident = TOK_IDENT;
9026 p = tcc_keywords;
9027 while (*p) {
9028 r = p;
9029 for(;;) {
9030 c = *r++;
9031 if (c == '\0')
9032 break;
9034 ts = tok_alloc(p, r - p - 1);
9035 p = r;
9038 /* we add dummy defines for some special macros to speed up tests
9039 and to have working defined() */
9040 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9041 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9042 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9043 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9045 /* standard defines */
9046 tcc_define_symbol(s, "__STDC__", NULL);
9047 #if defined(TCC_TARGET_I386)
9048 tcc_define_symbol(s, "__i386__", NULL);
9049 #endif
9050 #if defined(linux)
9051 tcc_define_symbol(s, "__linux__", NULL);
9052 tcc_define_symbol(s, "linux", NULL);
9053 #endif
9054 /* tiny C specific defines */
9055 tcc_define_symbol(s, "__TINYC__", NULL);
9057 /* tiny C & gcc defines */
9058 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9059 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9060 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9062 /* default library paths */
9063 tcc_add_library_path(s, "/usr/local/lib");
9064 tcc_add_library_path(s, "/usr/lib");
9065 tcc_add_library_path(s, "/lib");
9067 /* no section zero */
9068 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9070 /* create standard sections */
9071 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9072 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9073 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9075 /* symbols are always generated for linking stage */
9076 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9077 ".strtab",
9078 ".hashtab", SHF_PRIVATE);
9079 strtab_section = symtab_section->link;
9081 /* private symbol table for dynamic symbols */
9082 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9083 ".dynstrtab",
9084 ".dynhashtab", SHF_PRIVATE);
9085 return s;
9088 void tcc_delete(TCCState *s1)
9090 int i, n;
9092 /* free -D defines */
9093 free_defines(NULL);
9095 /* free tokens */
9096 n = tok_ident - TOK_IDENT;
9097 for(i = 0; i < n; i++)
9098 tcc_free(table_ident[i]);
9099 tcc_free(table_ident);
9101 /* free all sections */
9103 free_section(symtab_section->hash);
9105 free_section(s1->dynsymtab_section->hash);
9106 free_section(s1->dynsymtab_section->link);
9107 free_section(s1->dynsymtab_section);
9109 for(i = 1; i < s1->nb_sections; i++)
9110 free_section(s1->sections[i]);
9111 tcc_free(s1->sections);
9113 /* free loaded dlls array */
9114 for(i = 0; i < s1->nb_loaded_dlls; i++)
9115 tcc_free(s1->loaded_dlls[i]);
9116 tcc_free(s1->loaded_dlls);
9118 /* library paths */
9119 for(i = 0; i < s1->nb_library_paths; i++)
9120 tcc_free(s1->library_paths[i]);
9121 tcc_free(s1->library_paths);
9123 /* cached includes */
9124 for(i = 0; i < s1->nb_cached_includes; i++)
9125 tcc_free(s1->cached_includes[i]);
9126 tcc_free(s1->cached_includes);
9128 for(i = 0; i < s1->nb_include_paths; i++)
9129 tcc_free(s1->include_paths[i]);
9130 tcc_free(s1->include_paths);
9132 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9133 tcc_free(s1->sysinclude_paths[i]);
9134 tcc_free(s1->sysinclude_paths);
9136 tcc_free(s1);
9139 int tcc_add_include_path(TCCState *s1, const char *pathname)
9141 char *pathname1;
9143 pathname1 = tcc_strdup(pathname);
9144 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9145 return 0;
9148 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9150 char *pathname1;
9152 pathname1 = tcc_strdup(pathname);
9153 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9154 return 0;
9157 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9159 const char *ext, *filename1;
9160 Elf32_Ehdr ehdr;
9161 int fd, ret;
9162 BufferedFile *saved_file;
9164 /* find source file type with extension */
9165 filename1 = strrchr(filename, '/');
9166 if (filename1)
9167 filename1++;
9168 else
9169 filename1 = filename;
9170 ext = strrchr(filename1, '.');
9171 if (ext)
9172 ext++;
9174 /* open the file */
9175 saved_file = file;
9176 file = tcc_open(s1, filename);
9177 if (!file) {
9178 if (flags & AFF_PRINT_ERROR) {
9179 error_noabort("file '%s' not found", filename);
9181 ret = -1;
9182 goto fail1;
9185 if (!ext || !strcmp(ext, "c")) {
9186 /* C file assumed */
9187 ret = tcc_compile(s1);
9188 } else
9189 #ifdef CONFIG_TCC_ASM
9190 if (!strcmp(ext, "S")) {
9191 /* preprocessed assembler */
9192 ret = tcc_assemble(s1, 1);
9193 } else if (!strcmp(ext, "s")) {
9194 /* non preprocessed assembler */
9195 ret = tcc_assemble(s1, 0);
9196 } else
9197 #endif
9199 fd = file->fd;
9200 /* assume executable format: auto guess file type */
9201 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
9202 error_noabort("could not read header");
9203 goto fail;
9205 lseek(fd, 0, SEEK_SET);
9207 if (ehdr.e_ident[0] == ELFMAG0 &&
9208 ehdr.e_ident[1] == ELFMAG1 &&
9209 ehdr.e_ident[2] == ELFMAG2 &&
9210 ehdr.e_ident[3] == ELFMAG3) {
9211 file->line_num = 0; /* do not display line number if error */
9212 if (ehdr.e_type == ET_REL) {
9213 ret = tcc_load_object_file(s1, fd, 0);
9214 } else if (ehdr.e_type == ET_DYN) {
9215 ret = tcc_load_dll(s1, fd, filename,
9216 (flags & AFF_REFERENCED_DLL) != 0);
9217 } else {
9218 error_noabort("unrecognized ELF file");
9219 goto fail;
9221 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9222 file->line_num = 0; /* do not display line number if error */
9223 ret = tcc_load_archive(s1, fd);
9224 } else {
9225 /* as GNU ld, consider it is an ld script if not recognized */
9226 ret = tcc_load_ldscript(s1);
9227 if (ret < 0) {
9228 error_noabort("unrecognized file type");
9229 goto fail;
9233 the_end:
9234 tcc_close(file);
9235 fail1:
9236 file = saved_file;
9237 return ret;
9238 fail:
9239 ret = -1;
9240 goto the_end;
9243 int tcc_add_file(TCCState *s, const char *filename)
9245 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9248 int tcc_add_library_path(TCCState *s, const char *pathname)
9250 char *pathname1;
9252 pathname1 = tcc_strdup(pathname);
9253 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9254 return 0;
9257 /* find and load a dll. Return non zero if not found */
9258 /* XXX: add '-rpath' option support ? */
9259 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9261 char buf[1024];
9262 int i;
9264 for(i = 0; i < s->nb_library_paths; i++) {
9265 snprintf(buf, sizeof(buf), "%s/%s",
9266 s->library_paths[i], filename);
9267 if (tcc_add_file_internal(s, buf, flags) == 0)
9268 return 0;
9270 return -1;
9273 /* the library name is the same as the argument of the '-l' option */
9274 int tcc_add_library(TCCState *s, const char *libraryname)
9276 char buf[1024];
9277 int i;
9278 void *h;
9280 /* first we look for the dynamic library if not static linking */
9281 if (!s->static_link) {
9282 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9283 /* if we output to memory, then we simply we dlopen(). */
9284 if (s->output_type == TCC_OUTPUT_MEMORY) {
9285 /* Since the libc is already loaded, we don't need to load it again */
9286 if (!strcmp(libraryname, "c"))
9287 return 0;
9288 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
9289 if (h)
9290 return 0;
9291 } else {
9292 if (tcc_add_dll(s, buf, 0) == 0)
9293 return 0;
9297 /* then we look for the static library */
9298 for(i = 0; i < s->nb_library_paths; i++) {
9299 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9300 s->library_paths[i], libraryname);
9301 if (tcc_add_file_internal(s, buf, 0) == 0)
9302 return 0;
9304 return -1;
9307 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9309 add_elf_sym(symtab_section, val, 0,
9310 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9311 SHN_ABS, name);
9312 return 0;
9315 int tcc_set_output_type(TCCState *s, int output_type)
9317 char buf[1024];
9319 s->output_type = output_type;
9321 if (!s->nostdinc) {
9322 /* default include paths */
9323 /* XXX: reverse order needed if -isystem support */
9324 tcc_add_sysinclude_path(s, "/usr/local/include");
9325 tcc_add_sysinclude_path(s, "/usr/include");
9326 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9327 tcc_add_sysinclude_path(s, buf);
9330 /* if bound checking, then add corresponding sections */
9331 #ifdef CONFIG_TCC_BCHECK
9332 if (do_bounds_check) {
9333 /* define symbol */
9334 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9335 /* create bounds sections */
9336 bounds_section = new_section(s, ".bounds",
9337 SHT_PROGBITS, SHF_ALLOC);
9338 lbounds_section = new_section(s, ".lbounds",
9339 SHT_PROGBITS, SHF_ALLOC);
9341 #endif
9343 /* add debug sections */
9344 if (do_debug) {
9345 /* stab symbols */
9346 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9347 stab_section->sh_entsize = sizeof(Stab_Sym);
9348 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9349 put_elf_str(stabstr_section, "");
9350 stab_section->link = stabstr_section;
9351 /* put first entry */
9352 put_stabs("", 0, 0, 0, 0);
9355 /* add libc crt1/crti objects */
9356 if (output_type == TCC_OUTPUT_EXE ||
9357 output_type == TCC_OUTPUT_DLL) {
9358 if (output_type != TCC_OUTPUT_DLL)
9359 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9360 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9362 return 0;
9365 #if !defined(LIBTCC)
9367 static int64_t getclock_us(void)
9369 #ifdef WIN32
9370 struct _timeb tb;
9371 _ftime(&tb);
9372 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9373 #else
9374 struct timeval tv;
9375 gettimeofday(&tv, NULL);
9376 return tv.tv_sec * 1000000LL + tv.tv_usec;
9377 #endif
9380 void help(void)
9382 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
9383 "usage: tcc [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9384 " [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9385 " [--] infile1 [infile2... --] [infile_args...]\n"
9386 "\n"
9387 "General options:\n"
9388 " -c compile only - generate an object file\n"
9389 " -o outfile set output filename\n"
9390 " -- allows multiples input files if no -o option given. Also\n"
9391 " separate input files from runtime arguments\n"
9392 " -Bdir set tcc internal library path\n"
9393 " -bench output compilation statistics\n"
9394 "Preprocessor options:\n"
9395 " -Idir add include path 'dir'\n"
9396 " -Dsym[=val] define 'sym' with value 'val'\n"
9397 " -Usym undefine 'sym'\n"
9398 "Linker options:\n"
9399 " -Ldir add library path 'dir'\n"
9400 " -llib link with dynamic or static library 'lib'\n"
9401 " -shared generate a shared library\n"
9402 " -static static linking\n"
9403 " -r relocatable output\n"
9404 "Debugger options:\n"
9405 " -g generate runtime debug info\n"
9406 #ifdef CONFIG_TCC_BCHECK
9407 " -b compile with built-in memory and bounds checker (implies -g)\n"
9408 #endif
9409 " -bt N show N callers in stack traces\n"
9413 #define TCC_OPTION_HAS_ARG 0x0001
9414 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9416 typedef struct TCCOption {
9417 const char *name;
9418 uint16_t index;
9419 uint16_t flags;
9420 } TCCOption;
9422 enum {
9423 TCC_OPTION_HELP,
9424 TCC_OPTION_MARKER,
9425 TCC_OPTION_I,
9426 TCC_OPTION_D,
9427 TCC_OPTION_U,
9428 TCC_OPTION_L,
9429 TCC_OPTION_B,
9430 TCC_OPTION_l,
9431 TCC_OPTION_bench,
9432 TCC_OPTION_bt,
9433 TCC_OPTION_b,
9434 TCC_OPTION_g,
9435 TCC_OPTION_c,
9436 TCC_OPTION_static,
9437 TCC_OPTION_shared,
9438 TCC_OPTION_o,
9439 TCC_OPTION_r,
9440 TCC_OPTION_W,
9441 TCC_OPTION_O,
9442 TCC_OPTION_m,
9443 TCC_OPTION_f,
9444 TCC_OPTION_nostdinc,
9445 TCC_OPTION_print_search_dirs,
9446 TCC_OPTION_rdynamic,
9449 static const TCCOption tcc_options[] = {
9450 { "h", TCC_OPTION_HELP, 0 },
9451 { "?", TCC_OPTION_HELP, 0 },
9452 { "-", TCC_OPTION_MARKER, 0 },
9453 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9454 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9455 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9456 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9457 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9458 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9459 { "bench", TCC_OPTION_bench, 0 },
9460 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9461 #ifdef CONFIG_TCC_BCHECK
9462 { "b", TCC_OPTION_b, 0 },
9463 #endif
9464 { "g", TCC_OPTION_g, 0 },
9465 { "c", TCC_OPTION_c, 0 },
9466 { "static", TCC_OPTION_static, 0 },
9467 { "shared", TCC_OPTION_shared, 0 },
9468 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9469 { "rdynamic", TCC_OPTION_rdynamic, 0 }, /* currently ignored */
9470 { "r", TCC_OPTION_r, 0 },
9471 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9472 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9473 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9474 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9475 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9476 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9477 { NULL },
9480 int main(int argc, char **argv)
9482 char *r;
9483 int optind, output_type, multiple_files, i, reloc_output;
9484 TCCState *s;
9485 char **files;
9486 int nb_files, nb_libraries, nb_objfiles, dminus, ret;
9487 char objfilename[1024];
9488 int64_t start_time = 0;
9489 const TCCOption *popt;
9490 const char *optarg, *p1, *r1, *outfile;
9491 int print_search_dirs;
9493 s = tcc_new();
9494 output_type = TCC_OUTPUT_MEMORY;
9496 optind = 1;
9497 outfile = NULL;
9498 multiple_files = 0;
9499 dminus = 0;
9500 files = NULL;
9501 nb_files = 0;
9502 nb_libraries = 0;
9503 reloc_output = 0;
9504 print_search_dirs = 0;
9505 while (1) {
9506 if (optind >= argc) {
9507 if (nb_files == 0 && !print_search_dirs)
9508 goto show_help;
9509 else
9510 break;
9512 r = argv[optind++];
9513 if (r[0] != '-') {
9514 /* add a new file */
9515 dynarray_add((void ***)&files, &nb_files, r);
9516 if (!multiple_files) {
9517 optind--;
9518 /* argv[0] will be this file */
9519 break;
9521 } else {
9522 /* find option in table (match only the first chars */
9523 popt = tcc_options;
9524 for(;;) {
9525 p1 = popt->name;
9526 if (p1 == NULL)
9527 error("invalid option -- '%s'", r);
9528 r1 = r + 1;
9529 for(;;) {
9530 if (*p1 == '\0')
9531 goto option_found;
9532 if (*r1 != *p1)
9533 break;
9534 p1++;
9535 r1++;
9537 popt++;
9539 option_found:
9540 if (popt->flags & TCC_OPTION_HAS_ARG) {
9541 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
9542 optarg = r1;
9543 } else {
9544 if (optind >= argc)
9545 error("argument to '%s' is missing", r);
9546 optarg = argv[optind++];
9548 } else {
9549 if (*r1 != '\0')
9550 goto show_help;
9551 optarg = NULL;
9554 switch(popt->index) {
9555 case TCC_OPTION_HELP:
9556 show_help:
9557 help();
9558 return 1;
9559 case TCC_OPTION_MARKER:
9560 /* '--' enables multiple files input and also ends several
9561 file input */
9562 if (dminus && multiple_files) {
9563 optind--; /* argv[0] will be '--' */
9564 goto end_parse;
9566 dminus = 1;
9567 multiple_files = 1;
9568 case TCC_OPTION_I:
9569 if (tcc_add_include_path(s, optarg) < 0)
9570 error("too many include paths");
9571 break;
9572 case TCC_OPTION_D:
9574 char *sym, *value;
9575 sym = (char *)optarg;
9576 value = strchr(sym, '=');
9577 if (value) {
9578 *value = '\0';
9579 value++;
9581 tcc_define_symbol(s, sym, value);
9583 break;
9584 case TCC_OPTION_U:
9585 tcc_undefine_symbol(s, optarg);
9586 break;
9587 case TCC_OPTION_L:
9588 tcc_add_library_path(s, optarg);
9589 break;
9590 case TCC_OPTION_B:
9591 /* set tcc utilities path (mainly for tcc development) */
9592 tcc_lib_path = optarg;
9593 break;
9594 case TCC_OPTION_l:
9595 dynarray_add((void ***)&files, &nb_files, r);
9596 nb_libraries++;
9597 break;
9598 case TCC_OPTION_bench:
9599 do_bench = 1;
9600 break;
9601 case TCC_OPTION_bt:
9602 num_callers = atoi(optarg);
9603 break;
9604 #ifdef CONFIG_TCC_BCHECK
9605 case TCC_OPTION_b:
9606 do_bounds_check = 1;
9607 do_debug = 1;
9608 break;
9609 #endif
9610 case TCC_OPTION_g:
9611 do_debug = 1;
9612 break;
9613 case TCC_OPTION_c:
9614 multiple_files = 1;
9615 output_type = TCC_OUTPUT_OBJ;
9616 break;
9617 case TCC_OPTION_static:
9618 s->static_link = 1;
9619 break;
9620 case TCC_OPTION_shared:
9621 output_type = TCC_OUTPUT_DLL;
9622 break;
9623 case TCC_OPTION_o:
9624 multiple_files = 1;
9625 outfile = optarg;
9626 break;
9627 case TCC_OPTION_r:
9628 /* generate a .o merging several output files */
9629 reloc_output = 1;
9630 output_type = TCC_OUTPUT_OBJ;
9631 break;
9632 case TCC_OPTION_nostdinc:
9633 s->nostdinc = 1;
9634 break;
9635 case TCC_OPTION_print_search_dirs:
9636 print_search_dirs = 1;
9637 break;
9638 default:
9639 break;
9643 end_parse:
9644 if (print_search_dirs) {
9645 /* enough for Linux kernel */
9646 printf("install: %s/\n", tcc_lib_path);
9647 return 0;
9650 nb_objfiles = nb_files - nb_libraries;
9652 /* if outfile provided without other options, we output an
9653 executable */
9654 if (outfile && output_type == TCC_OUTPUT_MEMORY)
9655 output_type = TCC_OUTPUT_EXE;
9657 /* check -c consistency : only single file handled. XXX: checks file type */
9658 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9659 /* accepts only a single input file */
9660 if (nb_objfiles != 1)
9661 error("cannot specify multiple files with -c");
9662 if (nb_libraries != 0)
9663 error("cannot specify libraries with -c");
9666 /* compute default outfile name */
9667 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
9668 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
9669 char *ext;
9670 /* add .o extension */
9671 pstrcpy(objfilename, sizeof(objfilename) - 1, files[0]);
9672 ext = strrchr(objfilename, '.');
9673 if (!ext)
9674 goto default_outfile;
9675 strcpy(ext + 1, "o");
9676 } else {
9677 default_outfile:
9678 pstrcpy(objfilename, sizeof(objfilename), "a.out");
9680 outfile = objfilename;
9683 if (do_bench) {
9684 start_time = getclock_us();
9687 tcc_set_output_type(s, output_type);
9689 /* compile or add each files or library */
9690 for(i = 0;i < nb_files; i++) {
9691 const char *filename;
9693 filename = files[i];
9694 if (filename[0] == '-') {
9695 if (tcc_add_library(s, filename + 2) < 0)
9696 error("cannot find %s", filename);
9697 } else {
9698 if (tcc_add_file(s, filename) < 0) {
9699 ret = 1;
9700 goto the_end;
9705 /* free all files */
9706 tcc_free(files);
9708 if (do_bench) {
9709 double total_time;
9710 total_time = (double)(getclock_us() - start_time) / 1000000.0;
9711 if (total_time < 0.001)
9712 total_time = 0.001;
9713 if (total_bytes < 1)
9714 total_bytes = 1;
9715 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
9716 tok_ident - TOK_IDENT, total_lines, total_bytes,
9717 total_time, (int)(total_lines / total_time),
9718 total_bytes / total_time / 1000000.0);
9721 if (s->output_type != TCC_OUTPUT_MEMORY) {
9722 tcc_output_file(s, outfile);
9723 ret = 0;
9724 } else {
9725 ret = tcc_run(s, argc - optind, argv + optind);
9727 the_end:
9728 /* XXX: cannot do it with bound checking because of the malloc hooks */
9729 if (!do_bounds_check)
9730 tcc_delete(s);
9732 #ifdef MEM_DEBUG
9733 if (do_bench) {
9734 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
9736 #endif
9737 return ret;
9740 #endif