removed warnings
[tinycc/miki.git] / tcc.c
blob5a8e83279a3f9389a08f993d6819f6efb4cd778c
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define _GNU_SOURCE
21 #include "config.h"
23 #ifdef CONFIG_TCCBOOT
25 #include "tccboot.h"
26 #define CONFIG_TCC_STATIC
28 #else
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <math.h>
36 #include <unistd.h>
37 #include <signal.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 #include <setjmp.h>
41 #include <time.h>
42 #ifdef WIN32
43 #include <sys/timeb.h>
44 #define CONFIG_TCC_STATIC
45 #endif
46 #ifndef WIN32
47 #include <sys/time.h>
48 #include <sys/ucontext.h>
49 #endif
51 #endif /* !CONFIG_TCCBOOT */
53 #include "elf.h"
54 #include "stab.h"
55 #ifndef CONFIG_TCC_STATIC
56 #include <dlfcn.h>
57 #endif
58 #ifndef O_BINARY
59 #define O_BINARY 0
60 #endif
62 #include "libtcc.h"
64 /* parser debug */
65 //#define PARSE_DEBUG
66 /* preprocessor debug */
67 //#define PP_DEBUG
68 /* include file debug */
69 //#define INC_DEBUG
71 //#define MEM_DEBUG
73 /* assembler debug */
74 //#define ASM_DEBUG
76 /* target selection */
77 //#define TCC_TARGET_I386 /* i386 code generator */
78 //#define TCC_TARGET_ARM /* ARMv4 code generator */
79 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
81 /* default target is I386 */
82 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
83 !defined(TCC_TARGET_C67)
84 #define TCC_TARGET_I386
85 #endif
87 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
88 !defined(TCC_TARGET_C67)
89 #define CONFIG_TCC_BCHECK /* enable bound checking code */
90 #endif
92 /* define it to include assembler support */
93 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
94 #define CONFIG_TCC_ASM
95 #endif
97 /* object format selection */
98 #if defined(TCC_TARGET_C67)
99 #define TCC_TARGET_COFF
100 #endif
102 #define FALSE 0
103 #define false 0
104 #define TRUE 1
105 #define true 1
106 typedef int BOOL;
108 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
109 executables or dlls */
110 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
112 #define INCLUDE_STACK_SIZE 32
113 #define IFDEF_STACK_SIZE 64
114 #define VSTACK_SIZE 256
115 #define STRING_MAX_SIZE 1024
117 #define TOK_HASH_SIZE 8192 /* must be a power of two */
118 #define TOK_ALLOC_INCR 512 /* must be a power of two */
119 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
121 /* token symbol management */
122 typedef struct TokenSym {
123 struct TokenSym *hash_next;
124 struct Sym *sym_define; /* direct pointer to define */
125 struct Sym *sym_label; /* direct pointer to label */
126 struct Sym *sym_struct; /* direct pointer to structure */
127 struct Sym *sym_identifier; /* direct pointer to identifier */
128 int tok; /* token number */
129 int len;
130 char str[1];
131 } TokenSym;
133 typedef struct CString {
134 int size; /* size in bytes */
135 void *data; /* either 'char *' or 'int *' */
136 int size_allocated;
137 void *data_allocated; /* if non NULL, data has been malloced */
138 } CString;
140 /* type definition */
141 typedef struct CType {
142 int t;
143 struct Sym *ref;
144 } CType;
146 /* constant value */
147 typedef union CValue {
148 long double ld;
149 double d;
150 float f;
151 int i;
152 unsigned int ui;
153 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
154 long long ll;
155 unsigned long long ull;
156 struct CString *cstr;
157 void *ptr;
158 int tab[1];
159 } CValue;
161 /* value on stack */
162 typedef struct SValue {
163 CType type; /* type */
164 unsigned short r; /* register + flags */
165 unsigned short r2; /* second register, used for 'long long'
166 type. If not used, set to VT_CONST */
167 CValue c; /* constant, if VT_CONST */
168 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
169 } SValue;
171 /* symbol management */
172 typedef struct Sym {
173 int v; /* symbol token */
174 int r; /* associated register */
175 int c; /* associated number */
176 CType type; /* associated type */
177 struct Sym *next; /* next related symbol */
178 struct Sym *prev; /* prev symbol in stack */
179 struct Sym *prev_tok; /* previous symbol for this token */
180 } Sym;
182 /* section definition */
183 /* XXX: use directly ELF structure for parameters ? */
184 /* special flag to indicate that the section should not be linked to
185 the other ones */
186 #define SHF_PRIVATE 0x80000000
188 typedef struct Section {
189 unsigned long data_offset; /* current data offset */
190 unsigned char *data; /* section data */
191 unsigned long data_allocated; /* used for realloc() handling */
192 int sh_name; /* elf section name (only used during output) */
193 int sh_num; /* elf section number */
194 int sh_type; /* elf section type */
195 int sh_flags; /* elf section flags */
196 int sh_info; /* elf section info */
197 int sh_addralign; /* elf section alignment */
198 int sh_entsize; /* elf entry size */
199 unsigned long sh_size; /* section size (only used during output) */
200 unsigned long sh_addr; /* address at which the section is relocated */
201 unsigned long sh_offset; /* address at which the section is relocated */
202 int nb_hashed_syms; /* used to resize the hash table */
203 struct Section *link; /* link to another section */
204 struct Section *reloc; /* corresponding section for relocation, if any */
205 struct Section *hash; /* hash table for symbols */
206 struct Section *next;
207 char name[1]; /* section name */
208 } Section;
210 typedef struct DLLReference {
211 int level;
212 char name[1];
213 } DLLReference;
215 /* GNUC attribute definition */
216 typedef struct AttributeDef {
217 int aligned;
218 int packed;
219 Section *section;
220 unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
221 } AttributeDef;
223 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
224 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
225 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
227 /* stored in 'Sym.c' field */
228 #define FUNC_NEW 1 /* ansi function prototype */
229 #define FUNC_OLD 2 /* old function prototype */
230 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
232 /* stored in 'Sym.r' field */
233 #define FUNC_CDECL 0 /* standard c call */
234 #define FUNC_STDCALL 1 /* pascal c call */
235 #define FUNC_FASTCALL1 2 /* first param in %eax */
236 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
237 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
239 /* field 'Sym.t' for macros */
240 #define MACRO_OBJ 0 /* object like macro */
241 #define MACRO_FUNC 1 /* function like macro */
243 /* field 'Sym.r' for C labels */
244 #define LABEL_DEFINED 0 /* label is defined */
245 #define LABEL_FORWARD 1 /* label is forward defined */
246 #define LABEL_DECLARED 2 /* label is declared but never used */
248 /* type_decl() types */
249 #define TYPE_ABSTRACT 1 /* type without variable */
250 #define TYPE_DIRECT 2 /* type with variable */
252 #define IO_BUF_SIZE 8192
254 typedef struct BufferedFile {
255 uint8_t *buf_ptr;
256 uint8_t *buf_end;
257 int fd;
258 int line_num; /* current line number - here to simplify code */
259 int ifndef_macro; /* #ifndef macro / #endif search */
260 int ifndef_macro_saved; /* saved ifndef_macro */
261 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
262 char inc_type; /* type of include */
263 char inc_filename[512]; /* filename specified by the user */
264 char filename[1024]; /* current filename - here to simplify code */
265 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
266 } BufferedFile;
268 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
269 #define CH_EOF (-1) /* end of file */
271 /* parsing state (used to save parser state to reparse part of the
272 source several times) */
273 typedef struct ParseState {
274 int *macro_ptr;
275 int line_num;
276 int tok;
277 CValue tokc;
278 } ParseState;
280 /* used to record tokens */
281 typedef struct TokenString {
282 int *str;
283 int len;
284 int allocated_len;
285 int last_line_num;
286 } TokenString;
288 /* include file cache, used to find files faster and also to eliminate
289 inclusion if the include file is protected by #ifndef ... #endif */
290 typedef struct CachedInclude {
291 int ifndef_macro;
292 char type; /* '"' or '>' to give include type */
293 char filename[1]; /* path specified in #include */
294 } CachedInclude;
296 /* parser */
297 static struct BufferedFile *file;
298 static int ch, tok;
299 static CValue tokc;
300 static CString tokcstr; /* current parsed string, if any */
301 /* additional informations about token */
302 static int tok_flags;
303 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
304 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
305 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
307 static int *macro_ptr, *macro_ptr_allocated;
308 static int *unget_saved_macro_ptr;
309 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
310 static int unget_buffer_enabled;
311 static int parse_flags;
312 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
313 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
314 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
315 token. line feed is also
316 returned at eof */
317 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
319 static Section *text_section, *data_section, *bss_section; /* predefined sections */
320 static Section *cur_text_section; /* current section where function code is
321 generated */
322 static Section *last_text_section; /* to handle .previous asm directive */
323 /* bound check related sections */
324 static Section *bounds_section; /* contains global data bound description */
325 static Section *lbounds_section; /* contains local data bound description */
326 /* symbol sections */
327 static Section *symtab_section, *strtab_section;
329 /* debug sections */
330 static Section *stab_section, *stabstr_section;
332 /* loc : local variable index
333 ind : output code index
334 rsym: return symbol
335 anon_sym: anonymous symbol index
337 static int rsym, anon_sym, ind, loc;
338 /* expression generation modifiers */
339 static int const_wanted; /* true if constant wanted */
340 static int nocode_wanted; /* true if no code generation wanted for an expression */
341 static int global_expr; /* true if compound literals must be allocated
342 globally (used during initializers parsing */
343 static CType func_vt; /* current function return type (used by return
344 instruction) */
345 static int func_vc;
346 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
347 static int tok_ident;
348 static TokenSym **table_ident;
349 static TokenSym *hash_ident[TOK_HASH_SIZE];
350 static char token_buf[STRING_MAX_SIZE + 1];
351 static char *funcname;
352 static Sym *global_stack, *local_stack;
353 static Sym *define_stack;
354 static Sym *global_label_stack, *local_label_stack;
356 static SValue vstack[VSTACK_SIZE], *vtop;
357 /* some predefined types */
358 static CType char_pointer_type, func_old_type, int_type;
359 /* true if isid(c) || isnum(c) */
360 static unsigned char isidnum_table[256];
362 /* compile with debug symbol (and use them if error during execution) */
363 static int do_debug = 0;
365 /* compile with built-in memory and bounds checker */
366 static int do_bounds_check = 0;
368 /* display benchmark infos */
369 #if !defined(LIBTCC)
370 static int do_bench = 0;
371 #endif
372 static int total_lines;
373 static int total_bytes;
375 /* use GNU C extensions */
376 static int gnu_ext = 1;
378 /* use Tiny C extensions */
379 static int tcc_ext = 1;
381 /* max number of callers shown if error */
382 static int num_callers = 6;
383 static const char **rt_bound_error_msg;
385 /* XXX: get rid of this ASAP */
386 static struct TCCState *tcc_state;
388 /* give the path of the tcc libraries */
389 static const char *tcc_lib_path = CONFIG_TCC_LIBDIR "/tcc";
391 struct TCCState {
392 int output_type;
394 BufferedFile **include_stack_ptr;
395 int *ifdef_stack_ptr;
397 /* include file handling */
398 char **include_paths;
399 int nb_include_paths;
400 char **sysinclude_paths;
401 int nb_sysinclude_paths;
402 CachedInclude **cached_includes;
403 int nb_cached_includes;
405 char **library_paths;
406 int nb_library_paths;
408 /* array of all loaded dlls (including those referenced by loaded
409 dlls) */
410 DLLReference **loaded_dlls;
411 int nb_loaded_dlls;
413 /* sections */
414 Section **sections;
415 int nb_sections; /* number of sections, including first dummy section */
417 /* got handling */
418 Section *got;
419 Section *plt;
420 unsigned long *got_offsets;
421 int nb_got_offsets;
422 /* give the correspondance from symtab indexes to dynsym indexes */
423 int *symtab_to_dynsym;
425 /* temporary dynamic symbol sections (for dll loading) */
426 Section *dynsymtab_section;
427 /* exported dynamic symbol section */
428 Section *dynsym;
430 int nostdinc; /* if true, no standard headers are added */
431 int nostdlib; /* if true, no standard libraries are added */
433 int nocommon; /* if true, do not use common symbols for .bss data */
435 /* if true, static linking is performed */
436 int static_link;
438 /* if true, all symbols are exported */
439 int rdynamic;
441 /* if true, only link in referenced objects from archive */
442 int alacarte_link;
444 /* address of text section */
445 unsigned long text_addr;
446 int has_text_addr;
448 /* output format, see TCC_OUTPUT_FORMAT_xxx */
449 int output_format;
451 /* C language options */
452 int char_is_unsigned;
454 /* warning switches */
455 int warn_write_strings;
456 int warn_unsupported;
457 int warn_error;
458 int warn_none;
459 int warn_implicit_function_declaration;
461 /* error handling */
462 void *error_opaque;
463 void (*error_func)(void *opaque, const char *msg);
464 int error_set_jmp_enabled;
465 jmp_buf error_jmp_buf;
466 int nb_errors;
468 /* tiny assembler state */
469 Sym *asm_labels;
471 /* see include_stack_ptr */
472 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
474 /* see ifdef_stack_ptr */
475 int ifdef_stack[IFDEF_STACK_SIZE];
478 /* The current value can be: */
479 #define VT_VALMASK 0x00ff
480 #define VT_CONST 0x00f0 /* constant in vc
481 (must be first non register value) */
482 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
483 #define VT_LOCAL 0x00f2 /* offset on stack */
484 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
485 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
486 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
487 #define VT_LVAL 0x0100 /* var is an lvalue */
488 #define VT_SYM 0x0200 /* a symbol value is added */
489 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
490 char/short stored in integer registers) */
491 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
492 dereferencing value */
493 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
494 bounding function call point is in vc */
495 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
496 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
497 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
498 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
500 /* types */
501 #define VT_INT 0 /* integer type */
502 #define VT_BYTE 1 /* signed byte type */
503 #define VT_SHORT 2 /* short type */
504 #define VT_VOID 3 /* void type */
505 #define VT_PTR 4 /* pointer */
506 #define VT_ENUM 5 /* enum definition */
507 #define VT_FUNC 6 /* function type */
508 #define VT_STRUCT 7 /* struct/union definition */
509 #define VT_FLOAT 8 /* IEEE float */
510 #define VT_DOUBLE 9 /* IEEE double */
511 #define VT_LDOUBLE 10 /* IEEE long double */
512 #define VT_BOOL 11 /* ISOC99 boolean type */
513 #define VT_LLONG 12 /* 64 bit integer */
514 #define VT_LONG 13 /* long integer (NEVER USED as type, only
515 during parsing) */
516 #define VT_BTYPE 0x000f /* mask for basic type */
517 #define VT_UNSIGNED 0x0010 /* unsigned type */
518 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
519 #define VT_BITFIELD 0x0040 /* bitfield modifier */
520 #define VT_CONSTANT 0x0800 /* const modifier */
521 #define VT_VOLATILE 0x1000 /* volatile modifier */
522 #define VT_SIGNED 0x2000 /* signed type */
524 /* storage */
525 #define VT_EXTERN 0x00000080 /* extern definition */
526 #define VT_STATIC 0x00000100 /* static variable */
527 #define VT_TYPEDEF 0x00000200 /* typedef definition */
528 #define VT_INLINE 0x00000400 /* inline definition */
530 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
532 /* type mask (except storage) */
533 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
534 #define VT_TYPE (~(VT_STORAGE))
536 /* token values */
538 /* warning: the following compare tokens depend on i386 asm code */
539 #define TOK_ULT 0x92
540 #define TOK_UGE 0x93
541 #define TOK_EQ 0x94
542 #define TOK_NE 0x95
543 #define TOK_ULE 0x96
544 #define TOK_UGT 0x97
545 #define TOK_LT 0x9c
546 #define TOK_GE 0x9d
547 #define TOK_LE 0x9e
548 #define TOK_GT 0x9f
550 #define TOK_LAND 0xa0
551 #define TOK_LOR 0xa1
553 #define TOK_DEC 0xa2
554 #define TOK_MID 0xa3 /* inc/dec, to void constant */
555 #define TOK_INC 0xa4
556 #define TOK_UDIV 0xb0 /* unsigned division */
557 #define TOK_UMOD 0xb1 /* unsigned modulo */
558 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
559 #define TOK_CINT 0xb3 /* number in tokc */
560 #define TOK_CCHAR 0xb4 /* char constant in tokc */
561 #define TOK_STR 0xb5 /* pointer to string in tokc */
562 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
563 #define TOK_LCHAR 0xb7
564 #define TOK_LSTR 0xb8
565 #define TOK_CFLOAT 0xb9 /* float constant */
566 #define TOK_LINENUM 0xba /* line number info */
567 #define TOK_CDOUBLE 0xc0 /* double constant */
568 #define TOK_CLDOUBLE 0xc1 /* long double constant */
569 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
570 #define TOK_ADDC1 0xc3 /* add with carry generation */
571 #define TOK_ADDC2 0xc4 /* add with carry use */
572 #define TOK_SUBC1 0xc5 /* add with carry generation */
573 #define TOK_SUBC2 0xc6 /* add with carry use */
574 #define TOK_CUINT 0xc8 /* unsigned int constant */
575 #define TOK_CLLONG 0xc9 /* long long constant */
576 #define TOK_CULLONG 0xca /* unsigned long long constant */
577 #define TOK_ARROW 0xcb
578 #define TOK_DOTS 0xcc /* three dots */
579 #define TOK_SHR 0xcd /* unsigned shift right */
580 #define TOK_PPNUM 0xce /* preprocessor number */
582 #define TOK_SHL 0x01 /* shift left */
583 #define TOK_SAR 0x02 /* signed shift right */
585 /* assignement operators : normal operator or 0x80 */
586 #define TOK_A_MOD 0xa5
587 #define TOK_A_AND 0xa6
588 #define TOK_A_MUL 0xaa
589 #define TOK_A_ADD 0xab
590 #define TOK_A_SUB 0xad
591 #define TOK_A_DIV 0xaf
592 #define TOK_A_XOR 0xde
593 #define TOK_A_OR 0xfc
594 #define TOK_A_SHL 0x81
595 #define TOK_A_SAR 0x82
597 #ifndef offsetof
598 #define offsetof(type, field) ((size_t) &((type *)0)->field)
599 #endif
601 #ifndef countof
602 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
603 #endif
605 /* WARNING: the content of this string encodes token numbers */
606 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";
608 #define TOK_EOF (-1) /* end of file */
609 #define TOK_LINEFEED 10 /* line feed */
611 /* all identificators and strings have token above that */
612 #define TOK_IDENT 256
614 /* only used for i386 asm opcodes definitions */
615 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
617 #define DEF_BWL(x) \
618 DEF(TOK_ASM_ ## x ## b, #x "b") \
619 DEF(TOK_ASM_ ## x ## w, #x "w") \
620 DEF(TOK_ASM_ ## x ## l, #x "l") \
621 DEF(TOK_ASM_ ## x, #x)
623 #define DEF_WL(x) \
624 DEF(TOK_ASM_ ## x ## w, #x "w") \
625 DEF(TOK_ASM_ ## x ## l, #x "l") \
626 DEF(TOK_ASM_ ## x, #x)
628 #define DEF_FP1(x) \
629 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
630 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
631 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
632 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
634 #define DEF_FP(x) \
635 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
636 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
637 DEF_FP1(x)
639 #define DEF_ASMTEST(x) \
640 DEF_ASM(x ## o) \
641 DEF_ASM(x ## no) \
642 DEF_ASM(x ## b) \
643 DEF_ASM(x ## c) \
644 DEF_ASM(x ## nae) \
645 DEF_ASM(x ## nb) \
646 DEF_ASM(x ## nc) \
647 DEF_ASM(x ## ae) \
648 DEF_ASM(x ## e) \
649 DEF_ASM(x ## z) \
650 DEF_ASM(x ## ne) \
651 DEF_ASM(x ## nz) \
652 DEF_ASM(x ## be) \
653 DEF_ASM(x ## na) \
654 DEF_ASM(x ## nbe) \
655 DEF_ASM(x ## a) \
656 DEF_ASM(x ## s) \
657 DEF_ASM(x ## ns) \
658 DEF_ASM(x ## p) \
659 DEF_ASM(x ## pe) \
660 DEF_ASM(x ## np) \
661 DEF_ASM(x ## po) \
662 DEF_ASM(x ## l) \
663 DEF_ASM(x ## nge) \
664 DEF_ASM(x ## nl) \
665 DEF_ASM(x ## ge) \
666 DEF_ASM(x ## le) \
667 DEF_ASM(x ## ng) \
668 DEF_ASM(x ## nle) \
669 DEF_ASM(x ## g)
671 #define TOK_ASM_int TOK_INT
673 enum tcc_token {
674 TOK_LAST = TOK_IDENT - 1,
675 #define DEF(id, str) id,
676 #include "tcctok.h"
677 #undef DEF
680 static const char tcc_keywords[] =
681 #define DEF(id, str) str "\0"
682 #include "tcctok.h"
683 #undef DEF
686 #define TOK_UIDENT TOK_DEFINE
688 #ifdef WIN32
689 #define snprintf _snprintf
690 #define vsnprintf _vsnprintf
691 #endif
693 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
694 /* currently incorrect */
695 long double strtold(const char *nptr, char **endptr)
697 return (long double)strtod(nptr, endptr);
699 float strtof(const char *nptr, char **endptr)
701 return (float)strtod(nptr, endptr);
703 #else
704 /* XXX: need to define this to use them in non ISOC99 context */
705 extern float strtof (const char *__nptr, char **__endptr);
706 extern long double strtold (const char *__nptr, char **__endptr);
707 #endif
709 static char *pstrcpy(char *buf, int buf_size, const char *s);
710 static char *pstrcat(char *buf, int buf_size, const char *s);
712 static void next(void);
713 static void next_nomacro(void);
714 static void parse_expr_type(CType *type);
715 static void expr_type(CType *type);
716 static void unary_type(CType *type);
717 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
718 int case_reg, int is_expr);
719 static int expr_const(void);
720 static void expr_eq(void);
721 static void gexpr(void);
722 static void gen_inline_functions(void);
723 static void decl(int l);
724 static void decl_initializer(CType *type, Section *sec, unsigned long c,
725 int first, int size_only);
726 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
727 int has_init, int v, int scope);
728 int gv(int rc);
729 void gv2(int rc1, int rc2);
730 void move_reg(int r, int s);
731 void save_regs(int n);
732 void save_reg(int r);
733 void vpop(void);
734 void vswap(void);
735 void vdup(void);
736 int get_reg(int rc);
737 int get_reg_ex(int rc,int rc2);
739 static void macro_subst(TokenString *tok_str, Sym **nested_list,
740 const int *macro_str, int can_read_stream);
741 void gen_op(int op);
742 void force_charshort_cast(int t);
743 static void gen_cast(CType *type);
744 void vstore(void);
745 static Sym *sym_find(int v);
746 static Sym *sym_push(int v, CType *type, int r, int c);
748 /* type handling */
749 static int type_size(CType *type, int *a);
750 static inline CType *pointed_type(CType *type);
751 static int pointed_size(CType *type);
752 static int lvalue_type(int t);
753 static int parse_btype(CType *type, AttributeDef *ad);
754 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
755 static int is_compatible_types(CType *type1, CType *type2);
757 int ieee_finite(double d);
758 void error(const char *fmt, ...);
759 void vpushi(int v);
760 void vrott(int n);
761 void vnrott(int n);
762 void lexpand_nr(void);
763 static void vpush_global_sym(CType *type, int v);
764 void vset(CType *type, int r, int v);
765 void type_to_str(char *buf, int buf_size,
766 CType *type, const char *varstr);
767 char *get_tok_str(int v, CValue *cv);
768 static Sym *get_sym_ref(CType *type, Section *sec,
769 unsigned long offset, unsigned long size);
770 static Sym *external_global_sym(int v, CType *type, int r);
772 /* section generation */
773 static void section_realloc(Section *sec, unsigned long new_size);
774 static void *section_ptr_add(Section *sec, unsigned long size);
775 static void put_extern_sym(Sym *sym, Section *section,
776 unsigned long value, unsigned long size);
777 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
778 static int put_elf_str(Section *s, const char *sym);
779 static int put_elf_sym(Section *s,
780 unsigned long value, unsigned long size,
781 int info, int other, int shndx, const char *name);
782 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
783 int info, int sh_num, const char *name);
784 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
785 int type, int symbol);
786 static void put_stabs(const char *str, int type, int other, int desc,
787 unsigned long value);
788 static void put_stabs_r(const char *str, int type, int other, int desc,
789 unsigned long value, Section *sec, int sym_index);
790 static void put_stabn(int type, int other, int desc, int value);
791 static void put_stabd(int type, int other, int desc);
792 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
794 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
795 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
796 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
798 /* tcccoff.c */
799 int tcc_output_coff(TCCState *s1, FILE *f);
801 /* tccasm.c */
803 #ifdef CONFIG_TCC_ASM
805 typedef struct ExprValue {
806 uint32_t v;
807 Sym *sym;
808 } ExprValue;
810 #define MAX_ASM_OPERANDS 30
812 typedef struct ASMOperand {
813 int id; /* GCC 3 optionnal identifier (0 if number only supported */
814 char *constraint;
815 char asm_str[16]; /* computed asm string for operand */
816 SValue *vt; /* C value of the expression */
817 int ref_index; /* if >= 0, gives reference to a output constraint */
818 int input_index; /* if >= 0, gives reference to an input constraint */
819 int priority; /* priority, used to assign registers */
820 int reg; /* if >= 0, register number used for this operand */
821 int is_llong; /* true if double register value */
822 int is_memory; /* true if memory operand */
823 int is_rw; /* for '+' modifier */
824 } ASMOperand;
826 static void asm_expr(TCCState *s1, ExprValue *pe);
827 static int asm_int_expr(TCCState *s1);
828 static int find_constraint(ASMOperand *operands, int nb_operands,
829 const char *name, const char **pp);
831 static int tcc_assemble(TCCState *s1, int do_preprocess);
833 #endif
835 static void asm_instr(void);
836 static void asm_global_instr(void);
838 /* true if float/double/long double type */
839 static inline int is_float(int t)
841 int bt;
842 bt = t & VT_BTYPE;
843 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
846 #ifdef TCC_TARGET_I386
847 #include "i386-gen.c"
848 #endif
850 #ifdef TCC_TARGET_ARM
851 #include "arm-gen.c"
852 #endif
854 #ifdef TCC_TARGET_C67
855 #include "c67-gen.c"
856 #endif
858 #ifdef CONFIG_TCC_STATIC
860 #define RTLD_LAZY 0x001
861 #define RTLD_NOW 0x002
862 #define RTLD_GLOBAL 0x100
863 #define RTLD_DEFAULT NULL
865 /* dummy function for profiling */
866 void *dlopen(const char *filename, int flag)
868 return NULL;
871 const char *dlerror(void)
873 return "error";
876 typedef struct TCCSyms {
877 char *str;
878 void *ptr;
879 } TCCSyms;
881 #define TCCSYM(a) { #a, &a, },
883 /* add the symbol you want here if no dynamic linking is done */
884 static TCCSyms tcc_syms[] = {
885 #if !defined(CONFIG_TCCBOOT)
886 TCCSYM(printf)
887 TCCSYM(fprintf)
888 TCCSYM(fopen)
889 TCCSYM(fclose)
890 #endif
891 { NULL, NULL },
894 void *dlsym(void *handle, const char *symbol)
896 TCCSyms *p;
897 p = tcc_syms;
898 while (p->str != NULL) {
899 if (!strcmp(p->str, symbol))
900 return p->ptr;
901 p++;
903 return NULL;
906 #endif
908 /********************************************************/
910 /* we use our own 'finite' function to avoid potential problems with
911 non standard math libs */
912 /* XXX: endianness dependent */
913 int ieee_finite(double d)
915 int *p = (int *)&d;
916 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
919 /* copy a string and truncate it. */
920 static char *pstrcpy(char *buf, int buf_size, const char *s)
922 char *q, *q_end;
923 int c;
925 if (buf_size > 0) {
926 q = buf;
927 q_end = buf + buf_size - 1;
928 while (q < q_end) {
929 c = *s++;
930 if (c == '\0')
931 break;
932 *q++ = c;
934 *q = '\0';
936 return buf;
939 /* strcat and truncate. */
940 static char *pstrcat(char *buf, int buf_size, const char *s)
942 int len;
943 len = strlen(buf);
944 if (len < buf_size)
945 pstrcpy(buf + len, buf_size - len, s);
946 return buf;
949 static int strstart(const char *str, const char *val, const char **ptr)
951 const char *p, *q;
952 p = str;
953 q = val;
954 while (*q != '\0') {
955 if (*p != *q)
956 return 0;
957 p++;
958 q++;
960 if (ptr)
961 *ptr = p;
962 return 1;
965 /* memory management */
966 #ifdef MEM_DEBUG
967 int mem_cur_size;
968 int mem_max_size;
969 #endif
971 static inline void tcc_free(void *ptr)
973 #ifdef MEM_DEBUG
974 mem_cur_size -= malloc_usable_size(ptr);
975 #endif
976 free(ptr);
979 static void *tcc_malloc(unsigned long size)
981 void *ptr;
982 ptr = malloc(size);
983 if (!ptr && size)
984 error("memory full");
985 #ifdef MEM_DEBUG
986 mem_cur_size += malloc_usable_size(ptr);
987 if (mem_cur_size > mem_max_size)
988 mem_max_size = mem_cur_size;
989 #endif
990 return ptr;
993 static void *tcc_mallocz(unsigned long size)
995 void *ptr;
996 ptr = tcc_malloc(size);
997 memset(ptr, 0, size);
998 return ptr;
1001 static inline void *tcc_realloc(void *ptr, unsigned long size)
1003 void *ptr1;
1004 #ifdef MEM_DEBUG
1005 mem_cur_size -= malloc_usable_size(ptr);
1006 #endif
1007 ptr1 = realloc(ptr, size);
1008 #ifdef MEM_DEBUG
1009 /* NOTE: count not correct if alloc error, but not critical */
1010 mem_cur_size += malloc_usable_size(ptr1);
1011 if (mem_cur_size > mem_max_size)
1012 mem_max_size = mem_cur_size;
1013 #endif
1014 return ptr1;
1017 static char *tcc_strdup(const char *str)
1019 char *ptr;
1020 ptr = tcc_malloc(strlen(str) + 1);
1021 strcpy(ptr, str);
1022 return ptr;
1025 #define free(p) use_tcc_free(p)
1026 #define malloc(s) use_tcc_malloc(s)
1027 #define realloc(p, s) use_tcc_realloc(p, s)
1029 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1031 int nb, nb_alloc;
1032 void **pp;
1034 nb = *nb_ptr;
1035 pp = *ptab;
1036 /* every power of two we double array size */
1037 if ((nb & (nb - 1)) == 0) {
1038 if (!nb)
1039 nb_alloc = 1;
1040 else
1041 nb_alloc = nb * 2;
1042 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1043 if (!pp)
1044 error("memory full");
1045 *ptab = pp;
1047 pp[nb++] = data;
1048 *nb_ptr = nb;
1051 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1053 Section *sec;
1055 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1056 strcpy(sec->name, name);
1057 sec->sh_type = sh_type;
1058 sec->sh_flags = sh_flags;
1059 switch(sh_type) {
1060 case SHT_HASH:
1061 case SHT_REL:
1062 case SHT_DYNSYM:
1063 case SHT_SYMTAB:
1064 case SHT_DYNAMIC:
1065 sec->sh_addralign = 4;
1066 break;
1067 case SHT_STRTAB:
1068 sec->sh_addralign = 1;
1069 break;
1070 default:
1071 sec->sh_addralign = 32; /* default conservative alignment */
1072 break;
1075 /* only add section if not private */
1076 if (!(sh_flags & SHF_PRIVATE)) {
1077 sec->sh_num = s1->nb_sections;
1078 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1080 return sec;
1083 static void free_section(Section *s)
1085 tcc_free(s->data);
1086 tcc_free(s);
1089 /* realloc section and set its content to zero */
1090 static void section_realloc(Section *sec, unsigned long new_size)
1092 unsigned long size;
1093 unsigned char *data;
1095 size = sec->data_allocated;
1096 if (size == 0)
1097 size = 1;
1098 while (size < new_size)
1099 size = size * 2;
1100 data = tcc_realloc(sec->data, size);
1101 if (!data)
1102 error("memory full");
1103 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1104 sec->data = data;
1105 sec->data_allocated = size;
1108 /* reserve at least 'size' bytes in section 'sec' from
1109 sec->data_offset. */
1110 static void *section_ptr_add(Section *sec, unsigned long size)
1112 unsigned long offset, offset1;
1114 offset = sec->data_offset;
1115 offset1 = offset + size;
1116 if (offset1 > sec->data_allocated)
1117 section_realloc(sec, offset1);
1118 sec->data_offset = offset1;
1119 return sec->data + offset;
1122 /* return a reference to a section, and create it if it does not
1123 exists */
1124 Section *find_section(TCCState *s1, const char *name)
1126 Section *sec;
1127 int i;
1128 for(i = 1; i < s1->nb_sections; i++) {
1129 sec = s1->sections[i];
1130 if (!strcmp(name, sec->name))
1131 return sec;
1133 /* sections are created as PROGBITS */
1134 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1137 #define SECTION_ABS ((void *)1)
1139 /* update sym->c so that it points to an external symbol in section
1140 'section' with value 'value' */
1141 static void put_extern_sym(Sym *sym, Section *section,
1142 unsigned long value, unsigned long size)
1144 int sym_type, sym_bind, sh_num, info;
1145 Elf32_Sym *esym;
1146 const char *name;
1148 if (section == NULL)
1149 sh_num = SHN_UNDEF;
1150 else if (section == SECTION_ABS)
1151 sh_num = SHN_ABS;
1152 else
1153 sh_num = section->sh_num;
1154 if (!sym->c) {
1155 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1156 sym_type = STT_FUNC;
1157 else
1158 sym_type = STT_OBJECT;
1159 if (sym->type.t & VT_STATIC)
1160 sym_bind = STB_LOCAL;
1161 else
1162 sym_bind = STB_GLOBAL;
1164 name = get_tok_str(sym->v, NULL);
1165 #ifdef CONFIG_TCC_BCHECK
1166 if (do_bounds_check) {
1167 char buf[32];
1169 /* XXX: avoid doing that for statics ? */
1170 /* if bound checking is activated, we change some function
1171 names by adding the "__bound" prefix */
1172 switch(sym->v) {
1173 #if 0
1174 /* XXX: we rely only on malloc hooks */
1175 case TOK_malloc:
1176 case TOK_free:
1177 case TOK_realloc:
1178 case TOK_memalign:
1179 case TOK_calloc:
1180 #endif
1181 case TOK_memcpy:
1182 case TOK_memmove:
1183 case TOK_memset:
1184 case TOK_strlen:
1185 case TOK_strcpy:
1186 strcpy(buf, "__bound_");
1187 strcat(buf, name);
1188 name = buf;
1189 break;
1192 #endif
1193 info = ELF32_ST_INFO(sym_bind, sym_type);
1194 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1195 } else {
1196 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1197 esym->st_value = value;
1198 esym->st_size = size;
1199 esym->st_shndx = sh_num;
1203 /* add a new relocation entry to symbol 'sym' in section 's' */
1204 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1206 if (!sym->c)
1207 put_extern_sym(sym, NULL, 0, 0);
1208 /* now we can add ELF relocation info */
1209 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1212 static inline int isid(int c)
1214 return (c >= 'a' && c <= 'z') ||
1215 (c >= 'A' && c <= 'Z') ||
1216 c == '_';
1219 static inline int isnum(int c)
1221 return c >= '0' && c <= '9';
1224 static inline int isoct(int c)
1226 return c >= '0' && c <= '7';
1229 static inline int toup(int c)
1231 if (c >= 'a' && c <= 'z')
1232 return c - 'a' + 'A';
1233 else
1234 return c;
1237 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1239 int len;
1240 len = strlen(buf);
1241 vsnprintf(buf + len, buf_size - len, fmt, ap);
1244 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1246 va_list ap;
1247 va_start(ap, fmt);
1248 strcat_vprintf(buf, buf_size, fmt, ap);
1249 va_end(ap);
1252 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1254 char buf[2048];
1255 BufferedFile **f;
1257 buf[0] = '\0';
1258 if (file) {
1259 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1260 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1261 (*f)->filename, (*f)->line_num);
1262 if (file->line_num > 0) {
1263 strcat_printf(buf, sizeof(buf),
1264 "%s:%d: ", file->filename, file->line_num);
1265 } else {
1266 strcat_printf(buf, sizeof(buf),
1267 "%s: ", file->filename);
1269 } else {
1270 strcat_printf(buf, sizeof(buf),
1271 "tcc: ");
1273 if (is_warning)
1274 strcat_printf(buf, sizeof(buf), "warning: ");
1275 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1277 if (!s1->error_func) {
1278 /* default case: stderr */
1279 fprintf(stderr, "%s\n", buf);
1280 } else {
1281 s1->error_func(s1->error_opaque, buf);
1283 if (!is_warning || s1->warn_error)
1284 s1->nb_errors++;
1287 #ifdef LIBTCC
1288 void tcc_set_error_func(TCCState *s, void *error_opaque,
1289 void (*error_func)(void *opaque, const char *msg))
1291 s->error_opaque = error_opaque;
1292 s->error_func = error_func;
1294 #endif
1296 /* error without aborting current compilation */
1297 void error_noabort(const char *fmt, ...)
1299 TCCState *s1 = tcc_state;
1300 va_list ap;
1302 va_start(ap, fmt);
1303 error1(s1, 0, fmt, ap);
1304 va_end(ap);
1307 void error(const char *fmt, ...)
1309 TCCState *s1 = tcc_state;
1310 va_list ap;
1312 va_start(ap, fmt);
1313 error1(s1, 0, fmt, ap);
1314 va_end(ap);
1315 /* better than nothing: in some cases, we accept to handle errors */
1316 if (s1->error_set_jmp_enabled) {
1317 longjmp(s1->error_jmp_buf, 1);
1318 } else {
1319 /* XXX: eliminate this someday */
1320 exit(1);
1324 void expect(const char *msg)
1326 error("%s expected", msg);
1329 void warning(const char *fmt, ...)
1331 TCCState *s1 = tcc_state;
1332 va_list ap;
1334 if (s1->warn_none)
1335 return;
1337 va_start(ap, fmt);
1338 error1(s1, 1, fmt, ap);
1339 va_end(ap);
1342 void skip(int c)
1344 if (tok != c)
1345 error("'%c' expected", c);
1346 next();
1349 static void test_lvalue(void)
1351 if (!(vtop->r & VT_LVAL))
1352 expect("lvalue");
1355 /* allocate a new token */
1356 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1358 TokenSym *ts, **ptable;
1359 int i;
1361 if (tok_ident >= SYM_FIRST_ANOM)
1362 error("memory full");
1364 /* expand token table if needed */
1365 i = tok_ident - TOK_IDENT;
1366 if ((i % TOK_ALLOC_INCR) == 0) {
1367 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1368 if (!ptable)
1369 error("memory full");
1370 table_ident = ptable;
1373 ts = tcc_malloc(sizeof(TokenSym) + len);
1374 table_ident[i] = ts;
1375 ts->tok = tok_ident++;
1376 ts->sym_define = NULL;
1377 ts->sym_label = NULL;
1378 ts->sym_struct = NULL;
1379 ts->sym_identifier = NULL;
1380 ts->len = len;
1381 ts->hash_next = NULL;
1382 memcpy(ts->str, str, len);
1383 ts->str[len] = '\0';
1384 *pts = ts;
1385 return ts;
1388 #define TOK_HASH_INIT 1
1389 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1391 /* find a token and add it if not found */
1392 static TokenSym *tok_alloc(const char *str, int len)
1394 TokenSym *ts, **pts;
1395 int i;
1396 unsigned int h;
1398 h = TOK_HASH_INIT;
1399 for(i=0;i<len;i++)
1400 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1401 h &= (TOK_HASH_SIZE - 1);
1403 pts = &hash_ident[h];
1404 for(;;) {
1405 ts = *pts;
1406 if (!ts)
1407 break;
1408 if (ts->len == len && !memcmp(ts->str, str, len))
1409 return ts;
1410 pts = &(ts->hash_next);
1412 return tok_alloc_new(pts, str, len);
1415 /* CString handling */
1417 static void cstr_realloc(CString *cstr, int new_size)
1419 int size;
1420 void *data;
1422 size = cstr->size_allocated;
1423 if (size == 0)
1424 size = 8; /* no need to allocate a too small first string */
1425 while (size < new_size)
1426 size = size * 2;
1427 data = tcc_realloc(cstr->data_allocated, size);
1428 if (!data)
1429 error("memory full");
1430 cstr->data_allocated = data;
1431 cstr->size_allocated = size;
1432 cstr->data = data;
1435 /* add a byte */
1436 static void cstr_ccat(CString *cstr, int ch)
1438 int size;
1439 size = cstr->size + 1;
1440 if (size > cstr->size_allocated)
1441 cstr_realloc(cstr, size);
1442 ((unsigned char *)cstr->data)[size - 1] = ch;
1443 cstr->size = size;
1446 static void cstr_cat(CString *cstr, const char *str)
1448 int c;
1449 for(;;) {
1450 c = *str;
1451 if (c == '\0')
1452 break;
1453 cstr_ccat(cstr, c);
1454 str++;
1458 /* add a wide char */
1459 static void cstr_wccat(CString *cstr, int ch)
1461 int size;
1462 size = cstr->size + sizeof(int);
1463 if (size > cstr->size_allocated)
1464 cstr_realloc(cstr, size);
1465 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1466 cstr->size = size;
1469 static void cstr_new(CString *cstr)
1471 memset(cstr, 0, sizeof(CString));
1474 /* free string and reset it to NULL */
1475 static void cstr_free(CString *cstr)
1477 tcc_free(cstr->data_allocated);
1478 cstr_new(cstr);
1481 #define cstr_reset(cstr) cstr_free(cstr)
1483 static CString *cstr_dup(CString *cstr1)
1485 CString *cstr;
1486 int size;
1488 cstr = tcc_malloc(sizeof(CString));
1489 size = cstr1->size;
1490 cstr->size = size;
1491 cstr->size_allocated = size;
1492 cstr->data_allocated = tcc_malloc(size);
1493 cstr->data = cstr->data_allocated;
1494 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1495 return cstr;
1498 /* XXX: unicode ? */
1499 static void add_char(CString *cstr, int c)
1501 if (c == '\'' || c == '\"' || c == '\\') {
1502 /* XXX: could be more precise if char or string */
1503 cstr_ccat(cstr, '\\');
1505 if (c >= 32 && c <= 126) {
1506 cstr_ccat(cstr, c);
1507 } else {
1508 cstr_ccat(cstr, '\\');
1509 if (c == '\n') {
1510 cstr_ccat(cstr, 'n');
1511 } else {
1512 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1513 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1514 cstr_ccat(cstr, '0' + (c & 7));
1519 /* XXX: buffer overflow */
1520 /* XXX: float tokens */
1521 char *get_tok_str(int v, CValue *cv)
1523 static char buf[STRING_MAX_SIZE + 1];
1524 static CString cstr_buf;
1525 CString *cstr;
1526 unsigned char *q;
1527 char *p;
1528 int i, len;
1530 /* NOTE: to go faster, we give a fixed buffer for small strings */
1531 cstr_reset(&cstr_buf);
1532 cstr_buf.data = buf;
1533 cstr_buf.size_allocated = sizeof(buf);
1534 p = buf;
1536 switch(v) {
1537 case TOK_CINT:
1538 case TOK_CUINT:
1539 /* XXX: not quite exact, but only useful for testing */
1540 sprintf(p, "%u", cv->ui);
1541 break;
1542 case TOK_CLLONG:
1543 case TOK_CULLONG:
1544 /* XXX: not quite exact, but only useful for testing */
1545 sprintf(p, "%Lu", cv->ull);
1546 break;
1547 case TOK_CCHAR:
1548 case TOK_LCHAR:
1549 cstr_ccat(&cstr_buf, '\'');
1550 add_char(&cstr_buf, cv->i);
1551 cstr_ccat(&cstr_buf, '\'');
1552 cstr_ccat(&cstr_buf, '\0');
1553 break;
1554 case TOK_PPNUM:
1555 cstr = cv->cstr;
1556 len = cstr->size - 1;
1557 for(i=0;i<len;i++)
1558 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1559 cstr_ccat(&cstr_buf, '\0');
1560 break;
1561 case TOK_STR:
1562 case TOK_LSTR:
1563 cstr = cv->cstr;
1564 cstr_ccat(&cstr_buf, '\"');
1565 if (v == TOK_STR) {
1566 len = cstr->size - 1;
1567 for(i=0;i<len;i++)
1568 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1569 } else {
1570 len = (cstr->size / sizeof(int)) - 1;
1571 for(i=0;i<len;i++)
1572 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1574 cstr_ccat(&cstr_buf, '\"');
1575 cstr_ccat(&cstr_buf, '\0');
1576 break;
1577 case TOK_LT:
1578 v = '<';
1579 goto addv;
1580 case TOK_GT:
1581 v = '>';
1582 goto addv;
1583 case TOK_A_SHL:
1584 return strcpy(p, "<<=");
1585 case TOK_A_SAR:
1586 return strcpy(p, ">>=");
1587 default:
1588 if (v < TOK_IDENT) {
1589 /* search in two bytes table */
1590 q = tok_two_chars;
1591 while (*q) {
1592 if (q[2] == v) {
1593 *p++ = q[0];
1594 *p++ = q[1];
1595 *p = '\0';
1596 return buf;
1598 q += 3;
1600 addv:
1601 *p++ = v;
1602 *p = '\0';
1603 } else if (v < tok_ident) {
1604 return table_ident[v - TOK_IDENT]->str;
1605 } else if (v >= SYM_FIRST_ANOM) {
1606 /* special name for anonymous symbol */
1607 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1608 } else {
1609 /* should never happen */
1610 return NULL;
1612 break;
1614 return cstr_buf.data;
1617 /* push, without hashing */
1618 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1620 Sym *s;
1621 s = tcc_malloc(sizeof(Sym));
1622 s->v = v;
1623 s->type.t = t;
1624 s->c = c;
1625 s->next = NULL;
1626 /* add in stack */
1627 s->prev = *ps;
1628 *ps = s;
1629 return s;
1632 /* find a symbol and return its associated structure. 's' is the top
1633 of the symbol stack */
1634 static Sym *sym_find2(Sym *s, int v)
1636 while (s) {
1637 if (s->v == v)
1638 return s;
1639 s = s->prev;
1641 return NULL;
1644 /* structure lookup */
1645 static inline Sym *struct_find(int v)
1647 v -= TOK_IDENT;
1648 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1649 return NULL;
1650 return table_ident[v]->sym_struct;
1653 /* find an identifier */
1654 static inline Sym *sym_find(int v)
1656 v -= TOK_IDENT;
1657 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1658 return NULL;
1659 return table_ident[v]->sym_identifier;
1662 /* push a given symbol on the symbol stack */
1663 static Sym *sym_push(int v, CType *type, int r, int c)
1665 Sym *s, **ps;
1666 TokenSym *ts;
1668 if (local_stack)
1669 ps = &local_stack;
1670 else
1671 ps = &global_stack;
1672 s = sym_push2(ps, v, type->t, c);
1673 s->type.ref = type->ref;
1674 s->r = r;
1675 /* don't record fields or anonymous symbols */
1676 /* XXX: simplify */
1677 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1678 /* record symbol in token array */
1679 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1680 if (v & SYM_STRUCT)
1681 ps = &ts->sym_struct;
1682 else
1683 ps = &ts->sym_identifier;
1684 s->prev_tok = *ps;
1685 *ps = s;
1687 return s;
1690 /* push a global identifier */
1691 static Sym *global_identifier_push(int v, int t, int c)
1693 Sym *s, **ps;
1694 s = sym_push2(&global_stack, v, t, c);
1695 /* don't record anonymous symbol */
1696 if (v < SYM_FIRST_ANOM) {
1697 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1698 /* modify the top most local identifier, so that
1699 sym_identifier will point to 's' when popped */
1700 while (*ps != NULL)
1701 ps = &(*ps)->prev_tok;
1702 s->prev_tok = NULL;
1703 *ps = s;
1705 return s;
1708 /* pop symbols until top reaches 'b' */
1709 static void sym_pop(Sym **ptop, Sym *b)
1711 Sym *s, *ss, **ps;
1712 TokenSym *ts;
1713 int v;
1715 s = *ptop;
1716 while(s != b) {
1717 ss = s->prev;
1718 v = s->v;
1719 /* remove symbol in token array */
1720 /* XXX: simplify */
1721 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1722 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1723 if (v & SYM_STRUCT)
1724 ps = &ts->sym_struct;
1725 else
1726 ps = &ts->sym_identifier;
1727 *ps = s->prev_tok;
1729 tcc_free(s);
1730 s = ss;
1732 *ptop = b;
1735 /* I/O layer */
1737 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1739 int fd;
1740 BufferedFile *bf;
1742 fd = open(filename, O_RDONLY | O_BINARY);
1743 if (fd < 0)
1744 return NULL;
1745 bf = tcc_malloc(sizeof(BufferedFile));
1746 if (!bf) {
1747 close(fd);
1748 return NULL;
1750 bf->fd = fd;
1751 bf->buf_ptr = bf->buffer;
1752 bf->buf_end = bf->buffer;
1753 bf->buffer[0] = CH_EOB; /* put eob symbol */
1754 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1755 bf->line_num = 1;
1756 bf->ifndef_macro = 0;
1757 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1758 // printf("opening '%s'\n", filename);
1759 return bf;
1762 void tcc_close(BufferedFile *bf)
1764 total_lines += bf->line_num;
1765 close(bf->fd);
1766 tcc_free(bf);
1769 /* fill input buffer and peek next char */
1770 static int tcc_peekc_slow(BufferedFile *bf)
1772 int len;
1773 /* only tries to read if really end of buffer */
1774 if (bf->buf_ptr >= bf->buf_end) {
1775 if (bf->fd != -1) {
1776 #if defined(PARSE_DEBUG)
1777 len = 8;
1778 #else
1779 len = IO_BUF_SIZE;
1780 #endif
1781 len = read(bf->fd, bf->buffer, len);
1782 if (len < 0)
1783 len = 0;
1784 } else {
1785 len = 0;
1787 total_bytes += len;
1788 bf->buf_ptr = bf->buffer;
1789 bf->buf_end = bf->buffer + len;
1790 *bf->buf_end = CH_EOB;
1792 if (bf->buf_ptr < bf->buf_end) {
1793 return bf->buf_ptr[0];
1794 } else {
1795 bf->buf_ptr = bf->buf_end;
1796 return CH_EOF;
1800 /* return the current character, handling end of block if necessary
1801 (but not stray) */
1802 static int handle_eob(void)
1804 return tcc_peekc_slow(file);
1807 /* read next char from current input file and handle end of input buffer */
1808 static inline void inp(void)
1810 ch = *(++(file->buf_ptr));
1811 /* end of buffer/file handling */
1812 if (ch == CH_EOB)
1813 ch = handle_eob();
1816 /* handle '\[\r]\n' */
1817 static void handle_stray(void)
1819 while (ch == '\\') {
1820 inp();
1821 if (ch == '\n') {
1822 file->line_num++;
1823 inp();
1824 } else if (ch == '\r') {
1825 inp();
1826 if (ch != '\n')
1827 goto fail;
1828 file->line_num++;
1829 inp();
1830 } else {
1831 fail:
1832 error("stray '\\' in program");
1837 /* skip the stray and handle the \\n case. Output an error if
1838 incorrect char after the stray */
1839 static int handle_stray1(uint8_t *p)
1841 int c;
1843 if (p >= file->buf_end) {
1844 file->buf_ptr = p;
1845 c = handle_eob();
1846 p = file->buf_ptr;
1847 if (c == '\\')
1848 goto parse_stray;
1849 } else {
1850 parse_stray:
1851 file->buf_ptr = p;
1852 ch = *p;
1853 handle_stray();
1854 p = file->buf_ptr;
1855 c = *p;
1857 return c;
1860 /* handle just the EOB case, but not stray */
1861 #define PEEKC_EOB(c, p)\
1863 p++;\
1864 c = *p;\
1865 if (c == '\\') {\
1866 file->buf_ptr = p;\
1867 c = handle_eob();\
1868 p = file->buf_ptr;\
1872 /* handle the complicated stray case */
1873 #define PEEKC(c, p)\
1875 p++;\
1876 c = *p;\
1877 if (c == '\\') {\
1878 c = handle_stray1(p);\
1879 p = file->buf_ptr;\
1883 /* input with '\[\r]\n' handling. Note that this function cannot
1884 handle other characters after '\', so you cannot call it inside
1885 strings or comments */
1886 static void minp(void)
1888 inp();
1889 if (ch == '\\')
1890 handle_stray();
1894 /* single line C++ comments */
1895 static uint8_t *parse_line_comment(uint8_t *p)
1897 int c;
1899 p++;
1900 for(;;) {
1901 c = *p;
1902 redo:
1903 if (c == '\n' || c == CH_EOF) {
1904 break;
1905 } else if (c == '\\') {
1906 file->buf_ptr = p;
1907 c = handle_eob();
1908 p = file->buf_ptr;
1909 if (c == '\\') {
1910 PEEKC_EOB(c, p);
1911 if (c == '\n') {
1912 file->line_num++;
1913 PEEKC_EOB(c, p);
1914 } else if (c == '\r') {
1915 PEEKC_EOB(c, p);
1916 if (c == '\n') {
1917 file->line_num++;
1918 PEEKC_EOB(c, p);
1921 } else {
1922 goto redo;
1924 } else {
1925 p++;
1928 return p;
1931 /* C comments */
1932 static uint8_t *parse_comment(uint8_t *p)
1934 int c;
1936 p++;
1937 for(;;) {
1938 /* fast skip loop */
1939 for(;;) {
1940 c = *p;
1941 if (c == '\n' || c == '*' || c == '\\')
1942 break;
1943 p++;
1944 c = *p;
1945 if (c == '\n' || c == '*' || c == '\\')
1946 break;
1947 p++;
1949 /* now we can handle all the cases */
1950 if (c == '\n') {
1951 file->line_num++;
1952 p++;
1953 } else if (c == '*') {
1954 p++;
1955 for(;;) {
1956 c = *p;
1957 if (c == '*') {
1958 p++;
1959 } else if (c == '/') {
1960 goto end_of_comment;
1961 } else if (c == '\\') {
1962 file->buf_ptr = p;
1963 c = handle_eob();
1964 p = file->buf_ptr;
1965 if (c == '\\') {
1966 /* skip '\[\r]\n', otherwise just skip the stray */
1967 while (c == '\\') {
1968 PEEKC_EOB(c, p);
1969 if (c == '\n') {
1970 file->line_num++;
1971 PEEKC_EOB(c, p);
1972 } else if (c == '\r') {
1973 PEEKC_EOB(c, p);
1974 if (c == '\n') {
1975 file->line_num++;
1976 PEEKC_EOB(c, p);
1978 } else {
1979 goto after_star;
1983 } else {
1984 break;
1987 after_star: ;
1988 } else {
1989 /* stray, eob or eof */
1990 file->buf_ptr = p;
1991 c = handle_eob();
1992 p = file->buf_ptr;
1993 if (c == CH_EOF) {
1994 error("unexpected end of file in comment");
1995 } else if (c == '\\') {
1996 p++;
2000 end_of_comment:
2001 p++;
2002 return p;
2005 #define cinp minp
2007 /* space exlcuding newline */
2008 static inline int is_space(int ch)
2010 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2013 static inline void skip_spaces(void)
2015 while (is_space(ch))
2016 cinp();
2019 /* parse a string without interpreting escapes */
2020 static uint8_t *parse_pp_string(uint8_t *p,
2021 int sep, CString *str)
2023 int c;
2024 p++;
2025 for(;;) {
2026 c = *p;
2027 if (c == sep) {
2028 break;
2029 } else if (c == '\\') {
2030 file->buf_ptr = p;
2031 c = handle_eob();
2032 p = file->buf_ptr;
2033 if (c == CH_EOF) {
2034 unterminated_string:
2035 /* XXX: indicate line number of start of string */
2036 error("missing terminating %c character", sep);
2037 } else if (c == '\\') {
2038 /* escape : just skip \[\r]\n */
2039 PEEKC_EOB(c, p);
2040 if (c == '\n') {
2041 file->line_num++;
2042 p++;
2043 } else if (c == '\r') {
2044 PEEKC_EOB(c, p);
2045 if (c != '\n')
2046 expect("'\n' after '\r'");
2047 file->line_num++;
2048 p++;
2049 } else if (c == CH_EOF) {
2050 goto unterminated_string;
2051 } else {
2052 if (str) {
2053 cstr_ccat(str, '\\');
2054 cstr_ccat(str, c);
2056 p++;
2059 } else if (c == '\n') {
2060 file->line_num++;
2061 goto add_char;
2062 } else if (c == '\r') {
2063 PEEKC_EOB(c, p);
2064 if (c != '\n') {
2065 if (str)
2066 cstr_ccat(str, '\r');
2067 } else {
2068 file->line_num++;
2069 goto add_char;
2071 } else {
2072 add_char:
2073 if (str)
2074 cstr_ccat(str, c);
2075 p++;
2078 p++;
2079 return p;
2082 /* skip block of text until #else, #elif or #endif. skip also pairs of
2083 #if/#endif */
2084 void preprocess_skip(void)
2086 int a, start_of_line, c;
2087 uint8_t *p;
2089 p = file->buf_ptr;
2090 start_of_line = 1;
2091 a = 0;
2092 for(;;) {
2093 redo_no_start:
2094 c = *p;
2095 switch(c) {
2096 case ' ':
2097 case '\t':
2098 case '\f':
2099 case '\v':
2100 case '\r':
2101 p++;
2102 goto redo_no_start;
2103 case '\n':
2104 start_of_line = 1;
2105 file->line_num++;
2106 p++;
2107 goto redo_no_start;
2108 case '\\':
2109 file->buf_ptr = p;
2110 c = handle_eob();
2111 if (c == CH_EOF) {
2112 expect("#endif");
2113 } else if (c == '\\') {
2114 /* XXX: incorrect: should not give an error */
2115 ch = file->buf_ptr[0];
2116 handle_stray();
2118 p = file->buf_ptr;
2119 goto redo_no_start;
2120 /* skip strings */
2121 case '\"':
2122 case '\'':
2123 p = parse_pp_string(p, c, NULL);
2124 break;
2125 /* skip comments */
2126 case '/':
2127 file->buf_ptr = p;
2128 ch = *p;
2129 minp();
2130 p = file->buf_ptr;
2131 if (ch == '*') {
2132 p = parse_comment(p);
2133 } else if (ch == '/') {
2134 p = parse_line_comment(p);
2136 break;
2138 case '#':
2139 p++;
2140 if (start_of_line) {
2141 file->buf_ptr = p;
2142 next_nomacro();
2143 p = file->buf_ptr;
2144 if (a == 0 &&
2145 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2146 goto the_end;
2147 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2148 a++;
2149 else if (tok == TOK_ENDIF)
2150 a--;
2152 break;
2153 default:
2154 p++;
2155 break;
2157 start_of_line = 0;
2159 the_end: ;
2160 file->buf_ptr = p;
2163 /* ParseState handling */
2165 /* XXX: currently, no include file info is stored. Thus, we cannot display
2166 accurate messages if the function or data definition spans multiple
2167 files */
2169 /* save current parse state in 's' */
2170 void save_parse_state(ParseState *s)
2172 s->line_num = file->line_num;
2173 s->macro_ptr = macro_ptr;
2174 s->tok = tok;
2175 s->tokc = tokc;
2178 /* restore parse state from 's' */
2179 void restore_parse_state(ParseState *s)
2181 file->line_num = s->line_num;
2182 macro_ptr = s->macro_ptr;
2183 tok = s->tok;
2184 tokc = s->tokc;
2187 /* return the number of additional 'ints' necessary to store the
2188 token */
2189 static inline int tok_ext_size(int t)
2191 switch(t) {
2192 /* 4 bytes */
2193 case TOK_CINT:
2194 case TOK_CUINT:
2195 case TOK_CCHAR:
2196 case TOK_LCHAR:
2197 case TOK_STR:
2198 case TOK_LSTR:
2199 case TOK_CFLOAT:
2200 case TOK_LINENUM:
2201 case TOK_PPNUM:
2202 return 1;
2203 case TOK_CDOUBLE:
2204 case TOK_CLLONG:
2205 case TOK_CULLONG:
2206 return 2;
2207 case TOK_CLDOUBLE:
2208 return LDOUBLE_SIZE / 4;
2209 default:
2210 return 0;
2214 /* token string handling */
2216 static inline void tok_str_new(TokenString *s)
2218 s->str = NULL;
2219 s->len = 0;
2220 s->allocated_len = 0;
2221 s->last_line_num = -1;
2224 static void tok_str_free(int *str)
2226 const int *p;
2227 CString *cstr;
2228 int t;
2230 p = str;
2231 for(;;) {
2232 t = *p;
2233 /* NOTE: we test zero separately so that GCC can generate a
2234 table for the following switch */
2235 if (t == 0)
2236 break;
2237 switch(t) {
2238 case TOK_CINT:
2239 case TOK_CUINT:
2240 case TOK_CCHAR:
2241 case TOK_LCHAR:
2242 case TOK_CFLOAT:
2243 case TOK_LINENUM:
2244 p += 2;
2245 break;
2246 case TOK_PPNUM:
2247 case TOK_STR:
2248 case TOK_LSTR:
2249 /* XXX: use a macro to be portable on 64 bit ? */
2250 cstr = (CString *)p[1];
2251 cstr_free(cstr);
2252 tcc_free(cstr);
2253 p += 2;
2254 break;
2255 case TOK_CDOUBLE:
2256 case TOK_CLLONG:
2257 case TOK_CULLONG:
2258 p += 3;
2259 break;
2260 case TOK_CLDOUBLE:
2261 p += 1 + (LDOUBLE_SIZE / 4);
2262 break;
2263 default:
2264 p++;
2265 break;
2268 tcc_free(str);
2271 static int *tok_str_realloc(TokenString *s)
2273 int *str, len;
2275 if (s->allocated_len == 0) {
2276 len = 8;
2277 } else {
2278 len = s->allocated_len * 2;
2280 str = tcc_realloc(s->str, len * sizeof(int));
2281 if (!str)
2282 error("memory full");
2283 s->allocated_len = len;
2284 s->str = str;
2285 return str;
2288 static void tok_str_add(TokenString *s, int t)
2290 int len, *str;
2292 len = s->len;
2293 str = s->str;
2294 if (len >= s->allocated_len)
2295 str = tok_str_realloc(s);
2296 str[len++] = t;
2297 s->len = len;
2300 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2302 int len, *str;
2304 len = s->len;
2305 str = s->str;
2307 /* allocate space for worst case */
2308 if (len + TOK_MAX_SIZE > s->allocated_len)
2309 str = tok_str_realloc(s);
2310 str[len++] = t;
2311 switch(t) {
2312 case TOK_CINT:
2313 case TOK_CUINT:
2314 case TOK_CCHAR:
2315 case TOK_LCHAR:
2316 case TOK_CFLOAT:
2317 case TOK_LINENUM:
2318 str[len++] = cv->tab[0];
2319 break;
2320 case TOK_PPNUM:
2321 case TOK_STR:
2322 case TOK_LSTR:
2323 str[len++] = (int)cstr_dup(cv->cstr);
2324 break;
2325 case TOK_CDOUBLE:
2326 case TOK_CLLONG:
2327 case TOK_CULLONG:
2328 #if LDOUBLE_SIZE == 8
2329 case TOK_CLDOUBLE:
2330 #endif
2331 str[len++] = cv->tab[0];
2332 str[len++] = cv->tab[1];
2333 break;
2334 #if LDOUBLE_SIZE == 12
2335 case TOK_CLDOUBLE:
2336 str[len++] = cv->tab[0];
2337 str[len++] = cv->tab[1];
2338 str[len++] = cv->tab[2];
2339 #elif LDOUBLE_SIZE != 8
2340 #error add long double size support
2341 #endif
2342 break;
2343 default:
2344 break;
2346 s->len = len;
2349 /* add the current parse token in token string 's' */
2350 static void tok_str_add_tok(TokenString *s)
2352 CValue cval;
2354 /* save line number info */
2355 if (file->line_num != s->last_line_num) {
2356 s->last_line_num = file->line_num;
2357 cval.i = s->last_line_num;
2358 tok_str_add2(s, TOK_LINENUM, &cval);
2360 tok_str_add2(s, tok, &tokc);
2363 #if LDOUBLE_SIZE == 12
2364 #define LDOUBLE_GET(p, cv) \
2365 cv.tab[0] = p[0]; \
2366 cv.tab[1] = p[1]; \
2367 cv.tab[2] = p[2];
2368 #elif LDOUBLE_SIZE == 8
2369 #define LDOUBLE_GET(p, cv) \
2370 cv.tab[0] = p[0]; \
2371 cv.tab[1] = p[1];
2372 #else
2373 #error add long double size support
2374 #endif
2377 /* get a token from an integer array and increment pointer
2378 accordingly. we code it as a macro to avoid pointer aliasing. */
2379 #define TOK_GET(t, p, cv) \
2381 t = *p++; \
2382 switch(t) { \
2383 case TOK_CINT: \
2384 case TOK_CUINT: \
2385 case TOK_CCHAR: \
2386 case TOK_LCHAR: \
2387 case TOK_CFLOAT: \
2388 case TOK_LINENUM: \
2389 case TOK_STR: \
2390 case TOK_LSTR: \
2391 case TOK_PPNUM: \
2392 cv.tab[0] = *p++; \
2393 break; \
2394 case TOK_CDOUBLE: \
2395 case TOK_CLLONG: \
2396 case TOK_CULLONG: \
2397 cv.tab[0] = p[0]; \
2398 cv.tab[1] = p[1]; \
2399 p += 2; \
2400 break; \
2401 case TOK_CLDOUBLE: \
2402 LDOUBLE_GET(p, cv); \
2403 p += LDOUBLE_SIZE / 4; \
2404 break; \
2405 default: \
2406 break; \
2410 /* defines handling */
2411 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2413 Sym *s;
2415 s = sym_push2(&define_stack, v, macro_type, (int)str);
2416 s->next = first_arg;
2417 table_ident[v - TOK_IDENT]->sym_define = s;
2420 /* undefined a define symbol. Its name is just set to zero */
2421 static void define_undef(Sym *s)
2423 int v;
2424 v = s->v;
2425 if (v >= TOK_IDENT && v < tok_ident)
2426 table_ident[v - TOK_IDENT]->sym_define = NULL;
2427 s->v = 0;
2430 static inline Sym *define_find(int v)
2432 v -= TOK_IDENT;
2433 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2434 return NULL;
2435 return table_ident[v]->sym_define;
2438 /* free define stack until top reaches 'b' */
2439 static void free_defines(Sym *b)
2441 Sym *top, *top1;
2442 int v;
2444 top = define_stack;
2445 while (top != b) {
2446 top1 = top->prev;
2447 /* do not free args or predefined defines */
2448 if (top->c)
2449 tok_str_free((int *)top->c);
2450 v = top->v;
2451 if (v >= TOK_IDENT && v < tok_ident)
2452 table_ident[v - TOK_IDENT]->sym_define = NULL;
2453 tcc_free(top);
2454 top = top1;
2456 define_stack = b;
2459 /* label lookup */
2460 static Sym *label_find(int v)
2462 v -= TOK_IDENT;
2463 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2464 return NULL;
2465 return table_ident[v]->sym_label;
2468 static Sym *label_push(Sym **ptop, int v, int flags)
2470 Sym *s, **ps;
2471 s = sym_push2(ptop, v, 0, 0);
2472 s->r = flags;
2473 ps = &table_ident[v - TOK_IDENT]->sym_label;
2474 if (ptop == &global_label_stack) {
2475 /* modify the top most local identifier, so that
2476 sym_identifier will point to 's' when popped */
2477 while (*ps != NULL)
2478 ps = &(*ps)->prev_tok;
2480 s->prev_tok = *ps;
2481 *ps = s;
2482 return s;
2485 /* pop labels until element last is reached. Look if any labels are
2486 undefined. Define symbols if '&&label' was used. */
2487 static void label_pop(Sym **ptop, Sym *slast)
2489 Sym *s, *s1;
2490 for(s = *ptop; s != slast; s = s1) {
2491 s1 = s->prev;
2492 if (s->r == LABEL_DECLARED) {
2493 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2494 } else if (s->r == LABEL_FORWARD) {
2495 error("label '%s' used but not defined",
2496 get_tok_str(s->v, NULL));
2497 } else {
2498 if (s->c) {
2499 /* define corresponding symbol. A size of
2500 1 is put. */
2501 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2504 /* remove label */
2505 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2506 tcc_free(s);
2508 *ptop = slast;
2511 /* eval an expression for #if/#elif */
2512 static int expr_preprocess(void)
2514 int c, t;
2515 TokenString str;
2517 tok_str_new(&str);
2518 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2519 next(); /* do macro subst */
2520 if (tok == TOK_DEFINED) {
2521 next_nomacro();
2522 t = tok;
2523 if (t == '(')
2524 next_nomacro();
2525 c = define_find(tok) != 0;
2526 if (t == '(')
2527 next_nomacro();
2528 tok = TOK_CINT;
2529 tokc.i = c;
2530 } else if (tok >= TOK_IDENT) {
2531 /* if undefined macro */
2532 tok = TOK_CINT;
2533 tokc.i = 0;
2535 tok_str_add_tok(&str);
2537 tok_str_add(&str, -1); /* simulate end of file */
2538 tok_str_add(&str, 0);
2539 /* now evaluate C constant expression */
2540 macro_ptr = str.str;
2541 next();
2542 c = expr_const();
2543 macro_ptr = NULL;
2544 tok_str_free(str.str);
2545 return c != 0;
2548 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2549 static void tok_print(int *str)
2551 int t;
2552 CValue cval;
2554 while (1) {
2555 TOK_GET(t, str, cval);
2556 if (!t)
2557 break;
2558 printf(" %s", get_tok_str(t, &cval));
2560 printf("\n");
2562 #endif
2564 /* parse after #define */
2565 static void parse_define(void)
2567 Sym *s, *first, **ps;
2568 int v, t, varg, is_vaargs, c;
2569 TokenString str;
2571 v = tok;
2572 if (v < TOK_IDENT)
2573 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2574 /* XXX: should check if same macro (ANSI) */
2575 first = NULL;
2576 t = MACRO_OBJ;
2577 /* '(' must be just after macro definition for MACRO_FUNC */
2578 c = file->buf_ptr[0];
2579 if (c == '\\')
2580 c = handle_stray1(file->buf_ptr);
2581 if (c == '(') {
2582 next_nomacro();
2583 next_nomacro();
2584 ps = &first;
2585 while (tok != ')') {
2586 varg = tok;
2587 next_nomacro();
2588 is_vaargs = 0;
2589 if (varg == TOK_DOTS) {
2590 varg = TOK___VA_ARGS__;
2591 is_vaargs = 1;
2592 } else if (tok == TOK_DOTS && gnu_ext) {
2593 is_vaargs = 1;
2594 next_nomacro();
2596 if (varg < TOK_IDENT)
2597 error("badly punctuated parameter list");
2598 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2599 *ps = s;
2600 ps = &s->next;
2601 if (tok != ',')
2602 break;
2603 next_nomacro();
2605 t = MACRO_FUNC;
2607 tok_str_new(&str);
2608 next_nomacro();
2609 /* EOF testing necessary for '-D' handling */
2610 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2611 tok_str_add2(&str, tok, &tokc);
2612 next_nomacro();
2614 tok_str_add(&str, 0);
2615 #ifdef PP_DEBUG
2616 printf("define %s %d: ", get_tok_str(v, NULL), t);
2617 tok_print(str.str);
2618 #endif
2619 define_push(v, t, str.str, first);
2622 /* XXX: use a token or a hash table to accelerate matching ? */
2623 static CachedInclude *search_cached_include(TCCState *s1,
2624 int type, const char *filename)
2626 CachedInclude *e;
2627 int i;
2629 for(i = 0;i < s1->nb_cached_includes; i++) {
2630 e = s1->cached_includes[i];
2631 if (e->type == type && !strcmp(e->filename, filename))
2632 return e;
2634 return NULL;
2637 static inline void add_cached_include(TCCState *s1, int type,
2638 const char *filename, int ifndef_macro)
2640 CachedInclude *e;
2642 if (search_cached_include(s1, type, filename))
2643 return;
2644 #ifdef INC_DEBUG
2645 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2646 #endif
2647 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2648 if (!e)
2649 return;
2650 e->type = type;
2651 strcpy(e->filename, filename);
2652 e->ifndef_macro = ifndef_macro;
2653 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2656 /* is_bof is true if first non space token at beginning of file */
2657 static void preprocess(int is_bof)
2659 TCCState *s1 = tcc_state;
2660 int size, i, c, n, saved_parse_flags;
2661 char buf[1024], *q, *p;
2662 char buf1[1024];
2663 BufferedFile *f;
2664 Sym *s;
2665 CachedInclude *e;
2667 saved_parse_flags = parse_flags;
2668 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2669 PARSE_FLAG_LINEFEED;
2670 next_nomacro();
2671 redo:
2672 switch(tok) {
2673 case TOK_DEFINE:
2674 next_nomacro();
2675 parse_define();
2676 break;
2677 case TOK_UNDEF:
2678 next_nomacro();
2679 s = define_find(tok);
2680 /* undefine symbol by putting an invalid name */
2681 if (s)
2682 define_undef(s);
2683 break;
2684 case TOK_INCLUDE:
2685 ch = file->buf_ptr[0];
2686 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2687 skip_spaces();
2688 if (ch == '<') {
2689 c = '>';
2690 goto read_name;
2691 } else if (ch == '\"') {
2692 c = ch;
2693 read_name:
2694 /* XXX: better stray handling */
2695 minp();
2696 q = buf;
2697 while (ch != c && ch != '\n' && ch != CH_EOF) {
2698 if ((q - buf) < sizeof(buf) - 1)
2699 *q++ = ch;
2700 minp();
2702 *q = '\0';
2703 minp();
2704 #if 0
2705 /* eat all spaces and comments after include */
2706 /* XXX: slightly incorrect */
2707 while (ch1 != '\n' && ch1 != CH_EOF)
2708 inp();
2709 #endif
2710 } else {
2711 /* computed #include : either we have only strings or
2712 we have anything enclosed in '<>' */
2713 next();
2714 buf[0] = '\0';
2715 if (tok == TOK_STR) {
2716 while (tok != TOK_LINEFEED) {
2717 if (tok != TOK_STR) {
2718 include_syntax:
2719 error("'#include' expects \"FILENAME\" or <FILENAME>");
2721 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2722 next();
2724 c = '\"';
2725 } else {
2726 int len;
2727 while (tok != TOK_LINEFEED) {
2728 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2729 next();
2731 len = strlen(buf);
2732 /* check syntax and remove '<>' */
2733 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2734 goto include_syntax;
2735 memmove(buf, buf + 1, len - 2);
2736 buf[len - 2] = '\0';
2737 c = '>';
2741 e = search_cached_include(s1, c, buf);
2742 if (e && define_find(e->ifndef_macro)) {
2743 /* no need to parse the include because the 'ifndef macro'
2744 is defined */
2745 #ifdef INC_DEBUG
2746 printf("%s: skipping %s\n", file->filename, buf);
2747 #endif
2748 } else {
2749 if (c == '\"') {
2750 /* first search in current dir if "header.h" */
2751 size = 0;
2752 p = strrchr(file->filename, '/');
2753 if (p)
2754 size = p + 1 - file->filename;
2755 if (size > sizeof(buf1) - 1)
2756 size = sizeof(buf1) - 1;
2757 memcpy(buf1, file->filename, size);
2758 buf1[size] = '\0';
2759 pstrcat(buf1, sizeof(buf1), buf);
2760 f = tcc_open(s1, buf1);
2761 if (f)
2762 goto found;
2764 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2765 error("#include recursion too deep");
2766 /* now search in all the include paths */
2767 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2768 for(i = 0; i < n; i++) {
2769 const char *path;
2770 if (i < s1->nb_include_paths)
2771 path = s1->include_paths[i];
2772 else
2773 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2774 pstrcpy(buf1, sizeof(buf1), path);
2775 pstrcat(buf1, sizeof(buf1), "/");
2776 pstrcat(buf1, sizeof(buf1), buf);
2777 f = tcc_open(s1, buf1);
2778 if (f)
2779 goto found;
2781 error("include file '%s' not found", buf);
2782 f = NULL;
2783 found:
2784 #ifdef INC_DEBUG
2785 printf("%s: including %s\n", file->filename, buf1);
2786 #endif
2787 f->inc_type = c;
2788 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2789 /* push current file in stack */
2790 /* XXX: fix current line init */
2791 *s1->include_stack_ptr++ = file;
2792 file = f;
2793 /* add include file debug info */
2794 if (do_debug) {
2795 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2797 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2798 ch = file->buf_ptr[0];
2799 goto the_end;
2801 break;
2802 case TOK_IFNDEF:
2803 c = 1;
2804 goto do_ifdef;
2805 case TOK_IF:
2806 c = expr_preprocess();
2807 goto do_if;
2808 case TOK_IFDEF:
2809 c = 0;
2810 do_ifdef:
2811 next_nomacro();
2812 if (tok < TOK_IDENT)
2813 error("invalid argument for '#if%sdef'", c ? "n" : "");
2814 if (is_bof) {
2815 if (c) {
2816 #ifdef INC_DEBUG
2817 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2818 #endif
2819 file->ifndef_macro = tok;
2822 c = (define_find(tok) != 0) ^ c;
2823 do_if:
2824 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2825 error("memory full");
2826 *s1->ifdef_stack_ptr++ = c;
2827 goto test_skip;
2828 case TOK_ELSE:
2829 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2830 error("#else without matching #if");
2831 if (s1->ifdef_stack_ptr[-1] & 2)
2832 error("#else after #else");
2833 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2834 goto test_skip;
2835 case TOK_ELIF:
2836 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2837 error("#elif without matching #if");
2838 c = s1->ifdef_stack_ptr[-1];
2839 if (c > 1)
2840 error("#elif after #else");
2841 /* last #if/#elif expression was true: we skip */
2842 if (c == 1)
2843 goto skip;
2844 c = expr_preprocess();
2845 s1->ifdef_stack_ptr[-1] = c;
2846 test_skip:
2847 if (!(c & 1)) {
2848 skip:
2849 preprocess_skip();
2850 is_bof = 0;
2851 goto redo;
2853 break;
2854 case TOK_ENDIF:
2855 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2856 error("#endif without matching #if");
2857 s1->ifdef_stack_ptr--;
2858 /* '#ifndef macro' was at the start of file. Now we check if
2859 an '#endif' is exactly at the end of file */
2860 if (file->ifndef_macro &&
2861 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2862 file->ifndef_macro_saved = file->ifndef_macro;
2863 /* need to set to zero to avoid false matches if another
2864 #ifndef at middle of file */
2865 file->ifndef_macro = 0;
2866 while (tok != TOK_LINEFEED)
2867 next_nomacro();
2868 tok_flags |= TOK_FLAG_ENDIF;
2869 goto the_end;
2871 break;
2872 case TOK_LINE:
2873 next();
2874 if (tok != TOK_CINT)
2875 error("#line");
2876 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2877 next();
2878 if (tok != TOK_LINEFEED) {
2879 if (tok != TOK_STR)
2880 error("#line");
2881 pstrcpy(file->filename, sizeof(file->filename),
2882 (char *)tokc.cstr->data);
2884 break;
2885 case TOK_ERROR:
2886 case TOK_WARNING:
2887 c = tok;
2888 ch = file->buf_ptr[0];
2889 skip_spaces();
2890 q = buf;
2891 while (ch != '\n' && ch != CH_EOF) {
2892 if ((q - buf) < sizeof(buf) - 1)
2893 *q++ = ch;
2894 minp();
2896 *q = '\0';
2897 if (c == TOK_ERROR)
2898 error("#error %s", buf);
2899 else
2900 warning("#warning %s", buf);
2901 break;
2902 case TOK_PRAGMA:
2903 /* ignored */
2904 break;
2905 default:
2906 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2907 /* '!' is ignored to allow C scripts. numbers are ignored
2908 to emulate cpp behaviour */
2909 } else {
2910 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
2911 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2913 break;
2915 /* ignore other preprocess commands or #! for C scripts */
2916 while (tok != TOK_LINEFEED)
2917 next_nomacro();
2918 the_end:
2919 parse_flags = saved_parse_flags;
2922 /* evaluate escape codes in a string. */
2923 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2925 int c, n;
2926 const uint8_t *p;
2928 p = buf;
2929 for(;;) {
2930 c = *p;
2931 if (c == '\0')
2932 break;
2933 if (c == '\\') {
2934 p++;
2935 /* escape */
2936 c = *p;
2937 switch(c) {
2938 case '0': case '1': case '2': case '3':
2939 case '4': case '5': case '6': case '7':
2940 /* at most three octal digits */
2941 n = c - '0';
2942 p++;
2943 c = *p;
2944 if (isoct(c)) {
2945 n = n * 8 + c - '0';
2946 p++;
2947 c = *p;
2948 if (isoct(c)) {
2949 n = n * 8 + c - '0';
2950 p++;
2953 c = n;
2954 goto add_char_nonext;
2955 case 'x':
2956 p++;
2957 n = 0;
2958 for(;;) {
2959 c = *p;
2960 if (c >= 'a' && c <= 'f')
2961 c = c - 'a' + 10;
2962 else if (c >= 'A' && c <= 'F')
2963 c = c - 'A' + 10;
2964 else if (isnum(c))
2965 c = c - '0';
2966 else
2967 break;
2968 n = n * 16 + c;
2969 p++;
2971 c = n;
2972 goto add_char_nonext;
2973 case 'a':
2974 c = '\a';
2975 break;
2976 case 'b':
2977 c = '\b';
2978 break;
2979 case 'f':
2980 c = '\f';
2981 break;
2982 case 'n':
2983 c = '\n';
2984 break;
2985 case 'r':
2986 c = '\r';
2987 break;
2988 case 't':
2989 c = '\t';
2990 break;
2991 case 'v':
2992 c = '\v';
2993 break;
2994 case 'e':
2995 if (!gnu_ext)
2996 goto invalid_escape;
2997 c = 27;
2998 break;
2999 case '\'':
3000 case '\"':
3001 case '\\':
3002 case '?':
3003 break;
3004 default:
3005 invalid_escape:
3006 if (c >= '!' && c <= '~')
3007 warning("unknown escape sequence: \'\\%c\'", c);
3008 else
3009 warning("unknown escape sequence: \'\\x%x\'", c);
3010 break;
3013 p++;
3014 add_char_nonext:
3015 if (!is_long)
3016 cstr_ccat(outstr, c);
3017 else
3018 cstr_wccat(outstr, c);
3020 /* add a trailing '\0' */
3021 if (!is_long)
3022 cstr_ccat(outstr, '\0');
3023 else
3024 cstr_wccat(outstr, '\0');
3027 /* we use 64 bit numbers */
3028 #define BN_SIZE 2
3030 /* bn = (bn << shift) | or_val */
3031 void bn_lshift(unsigned int *bn, int shift, int or_val)
3033 int i;
3034 unsigned int v;
3035 for(i=0;i<BN_SIZE;i++) {
3036 v = bn[i];
3037 bn[i] = (v << shift) | or_val;
3038 or_val = v >> (32 - shift);
3042 void bn_zero(unsigned int *bn)
3044 int i;
3045 for(i=0;i<BN_SIZE;i++) {
3046 bn[i] = 0;
3050 /* parse number in null terminated string 'p' and return it in the
3051 current token */
3052 void parse_number(const char *p)
3054 int b, t, shift, frac_bits, s, exp_val, ch;
3055 char *q;
3056 unsigned int bn[BN_SIZE];
3057 double d;
3059 /* number */
3060 q = token_buf;
3061 ch = *p++;
3062 t = ch;
3063 ch = *p++;
3064 *q++ = t;
3065 b = 10;
3066 if (t == '.') {
3067 goto float_frac_parse;
3068 } else if (t == '0') {
3069 if (ch == 'x' || ch == 'X') {
3070 q--;
3071 ch = *p++;
3072 b = 16;
3073 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3074 q--;
3075 ch = *p++;
3076 b = 2;
3079 /* parse all digits. cannot check octal numbers at this stage
3080 because of floating point constants */
3081 while (1) {
3082 if (ch >= 'a' && ch <= 'f')
3083 t = ch - 'a' + 10;
3084 else if (ch >= 'A' && ch <= 'F')
3085 t = ch - 'A' + 10;
3086 else if (isnum(ch))
3087 t = ch - '0';
3088 else
3089 break;
3090 if (t >= b)
3091 break;
3092 if (q >= token_buf + STRING_MAX_SIZE) {
3093 num_too_long:
3094 error("number too long");
3096 *q++ = ch;
3097 ch = *p++;
3099 if (ch == '.' ||
3100 ((ch == 'e' || ch == 'E') && b == 10) ||
3101 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3102 if (b != 10) {
3103 /* NOTE: strtox should support that for hexa numbers, but
3104 non ISOC99 libcs do not support it, so we prefer to do
3105 it by hand */
3106 /* hexadecimal or binary floats */
3107 /* XXX: handle overflows */
3108 *q = '\0';
3109 if (b == 16)
3110 shift = 4;
3111 else
3112 shift = 2;
3113 bn_zero(bn);
3114 q = token_buf;
3115 while (1) {
3116 t = *q++;
3117 if (t == '\0') {
3118 break;
3119 } else if (t >= 'a') {
3120 t = t - 'a' + 10;
3121 } else if (t >= 'A') {
3122 t = t - 'A' + 10;
3123 } else {
3124 t = t - '0';
3126 bn_lshift(bn, shift, t);
3128 frac_bits = 0;
3129 if (ch == '.') {
3130 ch = *p++;
3131 while (1) {
3132 t = ch;
3133 if (t >= 'a' && t <= 'f') {
3134 t = t - 'a' + 10;
3135 } else if (t >= 'A' && t <= 'F') {
3136 t = t - 'A' + 10;
3137 } else if (t >= '0' && t <= '9') {
3138 t = t - '0';
3139 } else {
3140 break;
3142 if (t >= b)
3143 error("invalid digit");
3144 bn_lshift(bn, shift, t);
3145 frac_bits += shift;
3146 ch = *p++;
3149 if (ch != 'p' && ch != 'P')
3150 expect("exponent");
3151 ch = *p++;
3152 s = 1;
3153 exp_val = 0;
3154 if (ch == '+') {
3155 ch = *p++;
3156 } else if (ch == '-') {
3157 s = -1;
3158 ch = *p++;
3160 if (ch < '0' || ch > '9')
3161 expect("exponent digits");
3162 while (ch >= '0' && ch <= '9') {
3163 exp_val = exp_val * 10 + ch - '0';
3164 ch = *p++;
3166 exp_val = exp_val * s;
3168 /* now we can generate the number */
3169 /* XXX: should patch directly float number */
3170 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3171 d = ldexp(d, exp_val - frac_bits);
3172 t = toup(ch);
3173 if (t == 'F') {
3174 ch = *p++;
3175 tok = TOK_CFLOAT;
3176 /* float : should handle overflow */
3177 tokc.f = (float)d;
3178 } else if (t == 'L') {
3179 ch = *p++;
3180 tok = TOK_CLDOUBLE;
3181 /* XXX: not large enough */
3182 tokc.ld = (long double)d;
3183 } else {
3184 tok = TOK_CDOUBLE;
3185 tokc.d = d;
3187 } else {
3188 /* decimal floats */
3189 if (ch == '.') {
3190 if (q >= token_buf + STRING_MAX_SIZE)
3191 goto num_too_long;
3192 *q++ = ch;
3193 ch = *p++;
3194 float_frac_parse:
3195 while (ch >= '0' && ch <= '9') {
3196 if (q >= token_buf + STRING_MAX_SIZE)
3197 goto num_too_long;
3198 *q++ = ch;
3199 ch = *p++;
3202 if (ch == 'e' || ch == 'E') {
3203 if (q >= token_buf + STRING_MAX_SIZE)
3204 goto num_too_long;
3205 *q++ = ch;
3206 ch = *p++;
3207 if (ch == '-' || ch == '+') {
3208 if (q >= token_buf + STRING_MAX_SIZE)
3209 goto num_too_long;
3210 *q++ = ch;
3211 ch = *p++;
3213 if (ch < '0' || ch > '9')
3214 expect("exponent digits");
3215 while (ch >= '0' && ch <= '9') {
3216 if (q >= token_buf + STRING_MAX_SIZE)
3217 goto num_too_long;
3218 *q++ = ch;
3219 ch = *p++;
3222 *q = '\0';
3223 t = toup(ch);
3224 errno = 0;
3225 if (t == 'F') {
3226 ch = *p++;
3227 tok = TOK_CFLOAT;
3228 tokc.f = strtof(token_buf, NULL);
3229 } else if (t == 'L') {
3230 ch = *p++;
3231 tok = TOK_CLDOUBLE;
3232 tokc.ld = strtold(token_buf, NULL);
3233 } else {
3234 tok = TOK_CDOUBLE;
3235 tokc.d = strtod(token_buf, NULL);
3238 } else {
3239 unsigned long long n, n1;
3240 int lcount, ucount;
3242 /* integer number */
3243 *q = '\0';
3244 q = token_buf;
3245 if (b == 10 && *q == '0') {
3246 b = 8;
3247 q++;
3249 n = 0;
3250 while(1) {
3251 t = *q++;
3252 /* no need for checks except for base 10 / 8 errors */
3253 if (t == '\0') {
3254 break;
3255 } else if (t >= 'a') {
3256 t = t - 'a' + 10;
3257 } else if (t >= 'A') {
3258 t = t - 'A' + 10;
3259 } else {
3260 t = t - '0';
3261 if (t >= b)
3262 error("invalid digit");
3264 n1 = n;
3265 n = n * b + t;
3266 /* detect overflow */
3267 /* XXX: this test is not reliable */
3268 if (n < n1)
3269 error("integer constant overflow");
3272 /* XXX: not exactly ANSI compliant */
3273 if ((n & 0xffffffff00000000LL) != 0) {
3274 if ((n >> 63) != 0)
3275 tok = TOK_CULLONG;
3276 else
3277 tok = TOK_CLLONG;
3278 } else if (n > 0x7fffffff) {
3279 tok = TOK_CUINT;
3280 } else {
3281 tok = TOK_CINT;
3283 lcount = 0;
3284 ucount = 0;
3285 for(;;) {
3286 t = toup(ch);
3287 if (t == 'L') {
3288 if (lcount >= 2)
3289 error("three 'l's in integer constant");
3290 lcount++;
3291 if (lcount == 2) {
3292 if (tok == TOK_CINT)
3293 tok = TOK_CLLONG;
3294 else if (tok == TOK_CUINT)
3295 tok = TOK_CULLONG;
3297 ch = *p++;
3298 } else if (t == 'U') {
3299 if (ucount >= 1)
3300 error("two 'u's in integer constant");
3301 ucount++;
3302 if (tok == TOK_CINT)
3303 tok = TOK_CUINT;
3304 else if (tok == TOK_CLLONG)
3305 tok = TOK_CULLONG;
3306 ch = *p++;
3307 } else {
3308 break;
3311 if (tok == TOK_CINT || tok == TOK_CUINT)
3312 tokc.ui = n;
3313 else
3314 tokc.ull = n;
3319 #define PARSE2(c1, tok1, c2, tok2) \
3320 case c1: \
3321 PEEKC(c, p); \
3322 if (c == c2) { \
3323 p++; \
3324 tok = tok2; \
3325 } else { \
3326 tok = tok1; \
3328 break;
3330 /* return next token without macro substitution */
3331 static inline void next_nomacro1(void)
3333 int t, c, is_long;
3334 TokenSym *ts;
3335 uint8_t *p, *p1;
3336 unsigned int h;
3338 p = file->buf_ptr;
3339 redo_no_start:
3340 c = *p;
3341 switch(c) {
3342 case ' ':
3343 case '\t':
3344 case '\f':
3345 case '\v':
3346 case '\r':
3347 p++;
3348 goto redo_no_start;
3350 case '\\':
3351 /* first look if it is in fact an end of buffer */
3352 if (p >= file->buf_end) {
3353 file->buf_ptr = p;
3354 handle_eob();
3355 p = file->buf_ptr;
3356 if (p >= file->buf_end)
3357 goto parse_eof;
3358 else
3359 goto redo_no_start;
3360 } else {
3361 file->buf_ptr = p;
3362 ch = *p;
3363 handle_stray();
3364 p = file->buf_ptr;
3365 goto redo_no_start;
3367 parse_eof:
3369 TCCState *s1 = tcc_state;
3370 if (parse_flags & PARSE_FLAG_LINEFEED) {
3371 tok = TOK_LINEFEED;
3372 } else if (s1->include_stack_ptr == s1->include_stack ||
3373 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3374 /* no include left : end of file. */
3375 tok = TOK_EOF;
3376 } else {
3377 /* pop include file */
3379 /* test if previous '#endif' was after a #ifdef at
3380 start of file */
3381 if (tok_flags & TOK_FLAG_ENDIF) {
3382 #ifdef INC_DEBUG
3383 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3384 #endif
3385 add_cached_include(s1, file->inc_type, file->inc_filename,
3386 file->ifndef_macro_saved);
3389 /* add end of include file debug info */
3390 if (do_debug) {
3391 put_stabd(N_EINCL, 0, 0);
3393 /* pop include stack */
3394 tcc_close(file);
3395 s1->include_stack_ptr--;
3396 file = *s1->include_stack_ptr;
3397 p = file->buf_ptr;
3398 goto redo_no_start;
3401 break;
3403 case '\n':
3404 if (parse_flags & PARSE_FLAG_LINEFEED) {
3405 tok = TOK_LINEFEED;
3406 } else {
3407 file->line_num++;
3408 tok_flags |= TOK_FLAG_BOL;
3409 p++;
3410 goto redo_no_start;
3412 break;
3414 case '#':
3415 /* XXX: simplify */
3416 PEEKC(c, p);
3417 if ((tok_flags & TOK_FLAG_BOL) &&
3418 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3419 file->buf_ptr = p;
3420 preprocess(tok_flags & TOK_FLAG_BOF);
3421 p = file->buf_ptr;
3422 goto redo_no_start;
3423 } else {
3424 if (c == '#') {
3425 p++;
3426 tok = TOK_TWOSHARPS;
3427 } else {
3428 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3429 p = parse_line_comment(p - 1);
3430 goto redo_no_start;
3431 } else {
3432 tok = '#';
3436 break;
3438 case 'a': case 'b': case 'c': case 'd':
3439 case 'e': case 'f': case 'g': case 'h':
3440 case 'i': case 'j': case 'k': case 'l':
3441 case 'm': case 'n': case 'o': case 'p':
3442 case 'q': case 'r': case 's': case 't':
3443 case 'u': case 'v': case 'w': case 'x':
3444 case 'y': case 'z':
3445 case 'A': case 'B': case 'C': case 'D':
3446 case 'E': case 'F': case 'G': case 'H':
3447 case 'I': case 'J': case 'K':
3448 case 'M': case 'N': case 'O': case 'P':
3449 case 'Q': case 'R': case 'S': case 'T':
3450 case 'U': case 'V': case 'W': case 'X':
3451 case 'Y': case 'Z':
3452 case '_':
3453 parse_ident_fast:
3454 p1 = p;
3455 h = TOK_HASH_INIT;
3456 h = TOK_HASH_FUNC(h, c);
3457 p++;
3458 for(;;) {
3459 c = *p;
3460 if (!isidnum_table[c])
3461 break;
3462 h = TOK_HASH_FUNC(h, c);
3463 p++;
3465 if (c != '\\') {
3466 TokenSym **pts;
3467 int len;
3469 /* fast case : no stray found, so we have the full token
3470 and we have already hashed it */
3471 len = p - p1;
3472 h &= (TOK_HASH_SIZE - 1);
3473 pts = &hash_ident[h];
3474 for(;;) {
3475 ts = *pts;
3476 if (!ts)
3477 break;
3478 if (ts->len == len && !memcmp(ts->str, p1, len))
3479 goto token_found;
3480 pts = &(ts->hash_next);
3482 ts = tok_alloc_new(pts, p1, len);
3483 token_found: ;
3484 } else {
3485 /* slower case */
3486 cstr_reset(&tokcstr);
3488 while (p1 < p) {
3489 cstr_ccat(&tokcstr, *p1);
3490 p1++;
3492 p--;
3493 PEEKC(c, p);
3494 parse_ident_slow:
3495 while (isidnum_table[c]) {
3496 cstr_ccat(&tokcstr, c);
3497 PEEKC(c, p);
3499 ts = tok_alloc(tokcstr.data, tokcstr.size);
3501 tok = ts->tok;
3502 break;
3503 case 'L':
3504 t = p[1];
3505 if (t != '\\' && t != '\'' && t != '\"') {
3506 /* fast case */
3507 goto parse_ident_fast;
3508 } else {
3509 PEEKC(c, p);
3510 if (c == '\'' || c == '\"') {
3511 is_long = 1;
3512 goto str_const;
3513 } else {
3514 cstr_reset(&tokcstr);
3515 cstr_ccat(&tokcstr, 'L');
3516 goto parse_ident_slow;
3519 break;
3520 case '0': case '1': case '2': case '3':
3521 case '4': case '5': case '6': case '7':
3522 case '8': case '9':
3524 cstr_reset(&tokcstr);
3525 /* after the first digit, accept digits, alpha, '.' or sign if
3526 prefixed by 'eEpP' */
3527 parse_num:
3528 for(;;) {
3529 t = c;
3530 cstr_ccat(&tokcstr, c);
3531 PEEKC(c, p);
3532 if (!(isnum(c) || isid(c) || c == '.' ||
3533 ((c == '+' || c == '-') &&
3534 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3535 break;
3537 /* We add a trailing '\0' to ease parsing */
3538 cstr_ccat(&tokcstr, '\0');
3539 tokc.cstr = &tokcstr;
3540 tok = TOK_PPNUM;
3541 break;
3542 case '.':
3543 /* special dot handling because it can also start a number */
3544 PEEKC(c, p);
3545 if (isnum(c)) {
3546 cstr_reset(&tokcstr);
3547 cstr_ccat(&tokcstr, '.');
3548 goto parse_num;
3549 } else if (c == '.') {
3550 PEEKC(c, p);
3551 if (c != '.')
3552 expect("'.'");
3553 PEEKC(c, p);
3554 tok = TOK_DOTS;
3555 } else {
3556 tok = '.';
3558 break;
3559 case '\'':
3560 case '\"':
3561 is_long = 0;
3562 str_const:
3564 CString str;
3565 int sep;
3567 sep = c;
3569 /* parse the string */
3570 cstr_new(&str);
3571 p = parse_pp_string(p, sep, &str);
3572 cstr_ccat(&str, '\0');
3574 /* eval the escape (should be done as TOK_PPNUM) */
3575 cstr_reset(&tokcstr);
3576 parse_escape_string(&tokcstr, str.data, is_long);
3577 cstr_free(&str);
3579 if (sep == '\'') {
3580 int char_size;
3581 /* XXX: make it portable */
3582 if (!is_long)
3583 char_size = 1;
3584 else
3585 char_size = sizeof(int);
3586 if (tokcstr.size <= char_size)
3587 error("empty character constant");
3588 if (tokcstr.size > 2 * char_size)
3589 warning("multi-character character constant");
3590 if (!is_long) {
3591 tokc.i = *(int8_t *)tokcstr.data;
3592 tok = TOK_CCHAR;
3593 } else {
3594 tokc.i = *(int *)tokcstr.data;
3595 tok = TOK_LCHAR;
3597 } else {
3598 tokc.cstr = &tokcstr;
3599 if (!is_long)
3600 tok = TOK_STR;
3601 else
3602 tok = TOK_LSTR;
3605 break;
3607 case '<':
3608 PEEKC(c, p);
3609 if (c == '=') {
3610 p++;
3611 tok = TOK_LE;
3612 } else if (c == '<') {
3613 PEEKC(c, p);
3614 if (c == '=') {
3615 p++;
3616 tok = TOK_A_SHL;
3617 } else {
3618 tok = TOK_SHL;
3620 } else {
3621 tok = TOK_LT;
3623 break;
3625 case '>':
3626 PEEKC(c, p);
3627 if (c == '=') {
3628 p++;
3629 tok = TOK_GE;
3630 } else if (c == '>') {
3631 PEEKC(c, p);
3632 if (c == '=') {
3633 p++;
3634 tok = TOK_A_SAR;
3635 } else {
3636 tok = TOK_SAR;
3638 } else {
3639 tok = TOK_GT;
3641 break;
3643 case '&':
3644 PEEKC(c, p);
3645 if (c == '&') {
3646 p++;
3647 tok = TOK_LAND;
3648 } else if (c == '=') {
3649 p++;
3650 tok = TOK_A_AND;
3651 } else {
3652 tok = '&';
3654 break;
3656 case '|':
3657 PEEKC(c, p);
3658 if (c == '|') {
3659 p++;
3660 tok = TOK_LOR;
3661 } else if (c == '=') {
3662 p++;
3663 tok = TOK_A_OR;
3664 } else {
3665 tok = '|';
3667 break;
3669 case '+':
3670 PEEKC(c, p);
3671 if (c == '+') {
3672 p++;
3673 tok = TOK_INC;
3674 } else if (c == '=') {
3675 p++;
3676 tok = TOK_A_ADD;
3677 } else {
3678 tok = '+';
3680 break;
3682 case '-':
3683 PEEKC(c, p);
3684 if (c == '-') {
3685 p++;
3686 tok = TOK_DEC;
3687 } else if (c == '=') {
3688 p++;
3689 tok = TOK_A_SUB;
3690 } else if (c == '>') {
3691 p++;
3692 tok = TOK_ARROW;
3693 } else {
3694 tok = '-';
3696 break;
3698 PARSE2('!', '!', '=', TOK_NE)
3699 PARSE2('=', '=', '=', TOK_EQ)
3700 PARSE2('*', '*', '=', TOK_A_MUL)
3701 PARSE2('%', '%', '=', TOK_A_MOD)
3702 PARSE2('^', '^', '=', TOK_A_XOR)
3704 /* comments or operator */
3705 case '/':
3706 PEEKC(c, p);
3707 if (c == '*') {
3708 p = parse_comment(p);
3709 goto redo_no_start;
3710 } else if (c == '/') {
3711 p = parse_line_comment(p);
3712 goto redo_no_start;
3713 } else if (c == '=') {
3714 p++;
3715 tok = TOK_A_DIV;
3716 } else {
3717 tok = '/';
3719 break;
3721 /* simple tokens */
3722 case '(':
3723 case ')':
3724 case '[':
3725 case ']':
3726 case '{':
3727 case '}':
3728 case ',':
3729 case ';':
3730 case ':':
3731 case '?':
3732 case '~':
3733 case '$': /* only used in assembler */
3734 tok = c;
3735 p++;
3736 break;
3737 default:
3738 error("unrecognized character \\x%02x", c);
3739 break;
3741 file->buf_ptr = p;
3742 tok_flags = 0;
3743 #if defined(PARSE_DEBUG)
3744 printf("token = %s\n", get_tok_str(tok, &tokc));
3745 #endif
3748 /* return next token without macro substitution. Can read input from
3749 macro_ptr buffer */
3750 static void next_nomacro(void)
3752 if (macro_ptr) {
3753 redo:
3754 tok = *macro_ptr;
3755 if (tok) {
3756 TOK_GET(tok, macro_ptr, tokc);
3757 if (tok == TOK_LINENUM) {
3758 file->line_num = tokc.i;
3759 goto redo;
3762 } else {
3763 next_nomacro1();
3767 /* substitute args in macro_str and return allocated string */
3768 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3770 int *st, last_tok, t, notfirst;
3771 Sym *s;
3772 CValue cval;
3773 TokenString str;
3774 CString cstr;
3776 tok_str_new(&str);
3777 last_tok = 0;
3778 while(1) {
3779 TOK_GET(t, macro_str, cval);
3780 if (!t)
3781 break;
3782 if (t == '#') {
3783 /* stringize */
3784 TOK_GET(t, macro_str, cval);
3785 if (!t)
3786 break;
3787 s = sym_find2(args, t);
3788 if (s) {
3789 cstr_new(&cstr);
3790 st = (int *)s->c;
3791 notfirst = 0;
3792 while (*st) {
3793 if (notfirst)
3794 cstr_ccat(&cstr, ' ');
3795 TOK_GET(t, st, cval);
3796 cstr_cat(&cstr, get_tok_str(t, &cval));
3797 notfirst = 1;
3799 cstr_ccat(&cstr, '\0');
3800 #ifdef PP_DEBUG
3801 printf("stringize: %s\n", (char *)cstr.data);
3802 #endif
3803 /* add string */
3804 cval.cstr = &cstr;
3805 tok_str_add2(&str, TOK_STR, &cval);
3806 cstr_free(&cstr);
3807 } else {
3808 tok_str_add2(&str, t, &cval);
3810 } else if (t >= TOK_IDENT) {
3811 s = sym_find2(args, t);
3812 if (s) {
3813 st = (int *)s->c;
3814 /* if '##' is present before or after, no arg substitution */
3815 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3816 /* special case for var arg macros : ## eats the
3817 ',' if empty VA_ARGS variable. */
3818 /* XXX: test of the ',' is not 100%
3819 reliable. should fix it to avoid security
3820 problems */
3821 if (gnu_ext && s->type.t &&
3822 last_tok == TOK_TWOSHARPS &&
3823 str.len >= 2 && str.str[str.len - 2] == ',') {
3824 if (*st == 0) {
3825 /* suppress ',' '##' */
3826 str.len -= 2;
3827 } else {
3828 /* suppress '##' and add variable */
3829 str.len--;
3830 goto add_var;
3832 } else {
3833 int t1;
3834 add_var:
3835 for(;;) {
3836 TOK_GET(t1, st, cval);
3837 if (!t1)
3838 break;
3839 tok_str_add2(&str, t1, &cval);
3842 } else {
3843 /* NOTE: the stream cannot be read when macro
3844 substituing an argument */
3845 macro_subst(&str, nested_list, st, 0);
3847 } else {
3848 tok_str_add(&str, t);
3850 } else {
3851 tok_str_add2(&str, t, &cval);
3853 last_tok = t;
3855 tok_str_add(&str, 0);
3856 return str.str;
3859 static char const ab_month_name[12][4] =
3861 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3862 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3865 /* do macro substitution of current token with macro 's' and add
3866 result to (tok_str,tok_len). 'nested_list' is the list of all
3867 macros we got inside to avoid recursing. Return non zero if no
3868 substitution needs to be done */
3869 static int macro_subst_tok(TokenString *tok_str,
3870 Sym **nested_list, Sym *s, int can_read_stream)
3872 Sym *args, *sa, *sa1;
3873 int mstr_allocated, parlevel, *mstr, t, t1;
3874 TokenString str;
3875 char *cstrval;
3876 CValue cval;
3877 CString cstr;
3878 char buf[32];
3880 /* if symbol is a macro, prepare substitution */
3881 /* special macros */
3882 if (tok == TOK___LINE__) {
3883 snprintf(buf, sizeof(buf), "%d", file->line_num);
3884 cstrval = buf;
3885 t1 = TOK_PPNUM;
3886 goto add_cstr1;
3887 } else if (tok == TOK___FILE__) {
3888 cstrval = file->filename;
3889 goto add_cstr;
3890 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3891 time_t ti;
3892 struct tm *tm;
3894 time(&ti);
3895 tm = localtime(&ti);
3896 if (tok == TOK___DATE__) {
3897 snprintf(buf, sizeof(buf), "%s %2d %d",
3898 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3899 } else {
3900 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3901 tm->tm_hour, tm->tm_min, tm->tm_sec);
3903 cstrval = buf;
3904 add_cstr:
3905 t1 = TOK_STR;
3906 add_cstr1:
3907 cstr_new(&cstr);
3908 cstr_cat(&cstr, cstrval);
3909 cstr_ccat(&cstr, '\0');
3910 cval.cstr = &cstr;
3911 tok_str_add2(tok_str, t1, &cval);
3912 cstr_free(&cstr);
3913 } else {
3914 mstr = (int *)s->c;
3915 mstr_allocated = 0;
3916 if (s->type.t == MACRO_FUNC) {
3917 /* NOTE: we do not use next_nomacro to avoid eating the
3918 next token. XXX: find better solution */
3919 if (macro_ptr) {
3920 t = *macro_ptr;
3921 if (t == 0 && can_read_stream) {
3922 /* end of macro stream: we must look at the token
3923 after in the file */
3924 macro_ptr = NULL;
3925 goto parse_stream;
3927 } else {
3928 parse_stream:
3929 /* XXX: incorrect with comments */
3930 ch = file->buf_ptr[0];
3931 while (is_space(ch) || ch == '\n')
3932 cinp();
3933 t = ch;
3935 if (t != '(') /* no macro subst */
3936 return -1;
3938 /* argument macro */
3939 next_nomacro();
3940 next_nomacro();
3941 args = NULL;
3942 sa = s->next;
3943 /* NOTE: empty args are allowed, except if no args */
3944 for(;;) {
3945 /* handle '()' case */
3946 if (!args && !sa && tok == ')')
3947 break;
3948 if (!sa)
3949 error("macro '%s' used with too many args",
3950 get_tok_str(s->v, 0));
3951 tok_str_new(&str);
3952 parlevel = 0;
3953 /* NOTE: non zero sa->t indicates VA_ARGS */
3954 while ((parlevel > 0 ||
3955 (tok != ')' &&
3956 (tok != ',' || sa->type.t))) &&
3957 tok != -1) {
3958 if (tok == '(')
3959 parlevel++;
3960 else if (tok == ')')
3961 parlevel--;
3962 tok_str_add2(&str, tok, &tokc);
3963 next_nomacro();
3965 tok_str_add(&str, 0);
3966 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3967 sa = sa->next;
3968 if (tok == ')') {
3969 /* special case for gcc var args: add an empty
3970 var arg argument if it is omitted */
3971 if (sa && sa->type.t && gnu_ext)
3972 continue;
3973 else
3974 break;
3976 if (tok != ',')
3977 expect(",");
3978 next_nomacro();
3980 if (sa) {
3981 error("macro '%s' used with too few args",
3982 get_tok_str(s->v, 0));
3985 /* now subst each arg */
3986 mstr = macro_arg_subst(nested_list, mstr, args);
3987 /* free memory */
3988 sa = args;
3989 while (sa) {
3990 sa1 = sa->prev;
3991 tok_str_free((int *)sa->c);
3992 tcc_free(sa);
3993 sa = sa1;
3995 mstr_allocated = 1;
3997 sym_push2(nested_list, s->v, 0, 0);
3998 macro_subst(tok_str, nested_list, mstr, 1);
3999 /* pop nested defined symbol */
4000 sa1 = *nested_list;
4001 *nested_list = sa1->prev;
4002 tcc_free(sa1);
4003 if (mstr_allocated)
4004 tok_str_free(mstr);
4006 return 0;
4009 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4010 return the resulting string (which must be freed). */
4011 static inline int *macro_twosharps(const int *macro_str)
4013 TokenSym *ts;
4014 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4015 int t;
4016 const char *p1, *p2;
4017 CValue cval;
4018 TokenString macro_str1;
4019 CString cstr;
4021 start_macro_ptr = macro_str;
4022 /* we search the first '##' */
4023 for(;;) {
4024 macro_ptr1 = macro_str;
4025 TOK_GET(t, macro_str, cval);
4026 /* nothing more to do if end of string */
4027 if (t == 0)
4028 return NULL;
4029 if (*macro_str == TOK_TWOSHARPS)
4030 break;
4033 /* we saw '##', so we need more processing to handle it */
4034 cstr_new(&cstr);
4035 tok_str_new(&macro_str1);
4036 tok = t;
4037 tokc = cval;
4039 /* add all tokens seen so far */
4040 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4041 TOK_GET(t, ptr, cval);
4042 tok_str_add2(&macro_str1, t, &cval);
4044 saved_macro_ptr = macro_ptr;
4045 /* XXX: get rid of the use of macro_ptr here */
4046 macro_ptr = (int *)macro_str;
4047 for(;;) {
4048 while (*macro_ptr == TOK_TWOSHARPS) {
4049 macro_ptr++;
4050 macro_ptr1 = macro_ptr;
4051 t = *macro_ptr;
4052 if (t) {
4053 TOK_GET(t, macro_ptr, cval);
4054 /* We concatenate the two tokens if we have an
4055 identifier or a preprocessing number */
4056 cstr_reset(&cstr);
4057 p1 = get_tok_str(tok, &tokc);
4058 cstr_cat(&cstr, p1);
4059 p2 = get_tok_str(t, &cval);
4060 cstr_cat(&cstr, p2);
4061 cstr_ccat(&cstr, '\0');
4063 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4064 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4065 if (tok == TOK_PPNUM) {
4066 /* if number, then create a number token */
4067 /* NOTE: no need to allocate because
4068 tok_str_add2() does it */
4069 tokc.cstr = &cstr;
4070 } else {
4071 /* if identifier, we must do a test to
4072 validate we have a correct identifier */
4073 if (t == TOK_PPNUM) {
4074 const char *p;
4075 int c;
4077 p = p2;
4078 for(;;) {
4079 c = *p;
4080 if (c == '\0')
4081 break;
4082 p++;
4083 if (!isnum(c) && !isid(c))
4084 goto error_pasting;
4087 ts = tok_alloc(cstr.data, strlen(cstr.data));
4088 tok = ts->tok; /* modify current token */
4090 } else {
4091 const char *str = cstr.data;
4092 const unsigned char *q;
4094 /* we look for a valid token */
4095 /* XXX: do more extensive checks */
4096 if (!strcmp(str, ">>=")) {
4097 tok = TOK_A_SAR;
4098 } else if (!strcmp(str, "<<=")) {
4099 tok = TOK_A_SHL;
4100 } else if (strlen(str) == 2) {
4101 /* search in two bytes table */
4102 q = tok_two_chars;
4103 for(;;) {
4104 if (!*q)
4105 goto error_pasting;
4106 if (q[0] == str[0] && q[1] == str[1])
4107 break;
4108 q += 3;
4110 tok = q[2];
4111 } else {
4112 error_pasting:
4113 /* NOTE: because get_tok_str use a static buffer,
4114 we must save it */
4115 cstr_reset(&cstr);
4116 p1 = get_tok_str(tok, &tokc);
4117 cstr_cat(&cstr, p1);
4118 cstr_ccat(&cstr, '\0');
4119 p2 = get_tok_str(t, &cval);
4120 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4121 /* cannot merge tokens: just add them separately */
4122 tok_str_add2(&macro_str1, tok, &tokc);
4123 /* XXX: free associated memory ? */
4124 tok = t;
4125 tokc = cval;
4130 tok_str_add2(&macro_str1, tok, &tokc);
4131 next_nomacro();
4132 if (tok == 0)
4133 break;
4135 macro_ptr = (int *)saved_macro_ptr;
4136 cstr_free(&cstr);
4137 tok_str_add(&macro_str1, 0);
4138 return macro_str1.str;
4142 /* do macro substitution of macro_str and add result to
4143 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4144 inside to avoid recursing. */
4145 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4146 const int *macro_str, int can_read_stream)
4148 Sym *s;
4149 int *saved_macro_ptr, *macro_str1;
4150 const int *ptr;
4151 int t, ret;
4152 CValue cval;
4154 /* first scan for '##' operator handling */
4155 ptr = macro_str;
4156 macro_str1 = macro_twosharps(ptr);
4157 if (macro_str1)
4158 ptr = macro_str1;
4159 while (1) {
4160 /* NOTE: ptr == NULL can only happen if tokens are read from
4161 file stream due to a macro function call */
4162 if (ptr == NULL)
4163 break;
4164 TOK_GET(t, ptr, cval);
4165 if (t == 0)
4166 break;
4167 s = define_find(t);
4168 if (s != NULL) {
4169 /* if nested substitution, do nothing */
4170 if (sym_find2(*nested_list, t))
4171 goto no_subst;
4172 saved_macro_ptr = macro_ptr;
4173 macro_ptr = (int *)ptr;
4174 tok = t;
4175 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4176 ptr = (int *)macro_ptr;
4177 macro_ptr = saved_macro_ptr;
4178 if (ret != 0)
4179 goto no_subst;
4180 } else {
4181 no_subst:
4182 tok_str_add2(tok_str, t, &cval);
4185 if (macro_str1)
4186 tok_str_free(macro_str1);
4189 /* return next token with macro substitution */
4190 static void next(void)
4192 Sym *nested_list, *s;
4193 TokenString str;
4195 redo:
4196 next_nomacro();
4197 if (!macro_ptr) {
4198 /* if not reading from macro substituted string, then try
4199 to substitute macros */
4200 if (tok >= TOK_IDENT &&
4201 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4202 s = define_find(tok);
4203 if (s) {
4204 /* we have a macro: we try to substitute */
4205 tok_str_new(&str);
4206 nested_list = NULL;
4207 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4208 /* substitution done, NOTE: maybe empty */
4209 tok_str_add(&str, 0);
4210 macro_ptr = str.str;
4211 macro_ptr_allocated = str.str;
4212 goto redo;
4216 } else {
4217 if (tok == 0) {
4218 /* end of macro or end of unget buffer */
4219 if (unget_buffer_enabled) {
4220 macro_ptr = unget_saved_macro_ptr;
4221 unget_buffer_enabled = 0;
4222 } else {
4223 /* end of macro string: free it */
4224 tok_str_free(macro_ptr_allocated);
4225 macro_ptr = NULL;
4227 goto redo;
4231 /* convert preprocessor tokens into C tokens */
4232 if (tok == TOK_PPNUM &&
4233 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4234 parse_number((char *)tokc.cstr->data);
4238 /* push back current token and set current token to 'last_tok'. Only
4239 identifier case handled for labels. */
4240 static inline void unget_tok(int last_tok)
4242 int i, n;
4243 int *q;
4244 unget_saved_macro_ptr = macro_ptr;
4245 unget_buffer_enabled = 1;
4246 q = unget_saved_buffer;
4247 macro_ptr = q;
4248 *q++ = tok;
4249 n = tok_ext_size(tok) - 1;
4250 for(i=0;i<n;i++)
4251 *q++ = tokc.tab[i];
4252 *q = 0; /* end of token string */
4253 tok = last_tok;
4257 void swap(int *p, int *q)
4259 int t;
4260 t = *p;
4261 *p = *q;
4262 *q = t;
4265 void vsetc(CType *type, int r, CValue *vc)
4267 int v;
4269 if (vtop >= vstack + (VSTACK_SIZE - 1))
4270 error("memory full");
4271 /* cannot let cpu flags if other instruction are generated. Also
4272 avoid leaving VT_JMP anywhere except on the top of the stack
4273 because it would complicate the code generator. */
4274 if (vtop >= vstack) {
4275 v = vtop->r & VT_VALMASK;
4276 if (v == VT_CMP || (v & ~1) == VT_JMP)
4277 gv(RC_INT);
4279 vtop++;
4280 vtop->type = *type;
4281 vtop->r = r;
4282 vtop->r2 = VT_CONST;
4283 vtop->c = *vc;
4286 /* push integer constant */
4287 void vpushi(int v)
4289 CValue cval;
4290 cval.i = v;
4291 vsetc(&int_type, VT_CONST, &cval);
4294 /* Return a static symbol pointing to a section */
4295 static Sym *get_sym_ref(CType *type, Section *sec,
4296 unsigned long offset, unsigned long size)
4298 int v;
4299 Sym *sym;
4301 v = anon_sym++;
4302 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4303 sym->type.ref = type->ref;
4304 sym->r = VT_CONST | VT_SYM;
4305 put_extern_sym(sym, sec, offset, size);
4306 return sym;
4309 /* push a reference to a section offset by adding a dummy symbol */
4310 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4312 CValue cval;
4314 cval.ul = 0;
4315 vsetc(type, VT_CONST | VT_SYM, &cval);
4316 vtop->sym = get_sym_ref(type, sec, offset, size);
4319 /* define a new external reference to a symbol 'v' of type 'u' */
4320 static Sym *external_global_sym(int v, CType *type, int r)
4322 Sym *s;
4324 s = sym_find(v);
4325 if (!s) {
4326 /* push forward reference */
4327 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4328 s->type.ref = type->ref;
4329 s->r = r | VT_CONST | VT_SYM;
4331 return s;
4334 /* define a new external reference to a symbol 'v' of type 'u' */
4335 static Sym *external_sym(int v, CType *type, int r)
4337 Sym *s;
4339 s = sym_find(v);
4340 if (!s) {
4341 /* push forward reference */
4342 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4343 s->type.t |= VT_EXTERN;
4344 } else {
4345 if (!is_compatible_types(&s->type, type))
4346 error("incompatible types for redefinition of '%s'",
4347 get_tok_str(v, NULL));
4349 return s;
4352 /* push a reference to global symbol v */
4353 static void vpush_global_sym(CType *type, int v)
4355 Sym *sym;
4356 CValue cval;
4358 sym = external_global_sym(v, type, 0);
4359 cval.ul = 0;
4360 vsetc(type, VT_CONST | VT_SYM, &cval);
4361 vtop->sym = sym;
4364 void vset(CType *type, int r, int v)
4366 CValue cval;
4368 cval.i = v;
4369 vsetc(type, r, &cval);
4372 void vseti(int r, int v)
4374 CType type;
4375 type.t = VT_INT;
4376 vset(&type, r, v);
4379 void vswap(void)
4381 SValue tmp;
4383 tmp = vtop[0];
4384 vtop[0] = vtop[-1];
4385 vtop[-1] = tmp;
4388 void vpushv(SValue *v)
4390 if (vtop >= vstack + (VSTACK_SIZE - 1))
4391 error("memory full");
4392 vtop++;
4393 *vtop = *v;
4396 void vdup(void)
4398 vpushv(vtop);
4401 /* save r to the memory stack, and mark it as being free */
4402 void save_reg(int r)
4404 int l, saved, size, align;
4405 SValue *p, sv;
4406 CType *type;
4408 /* modify all stack values */
4409 saved = 0;
4410 l = 0;
4411 for(p=vstack;p<=vtop;p++) {
4412 if ((p->r & VT_VALMASK) == r ||
4413 (p->r2 & VT_VALMASK) == r) {
4414 /* must save value on stack if not already done */
4415 if (!saved) {
4416 /* NOTE: must reload 'r' because r might be equal to r2 */
4417 r = p->r & VT_VALMASK;
4418 /* store register in the stack */
4419 type = &p->type;
4420 if ((p->r & VT_LVAL) ||
4421 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4422 type = &int_type;
4423 size = type_size(type, &align);
4424 loc = (loc - size) & -align;
4425 sv.type.t = type->t;
4426 sv.r = VT_LOCAL | VT_LVAL;
4427 sv.c.ul = loc;
4428 store(r, &sv);
4429 #ifdef TCC_TARGET_I386
4430 /* x86 specific: need to pop fp register ST0 if saved */
4431 if (r == TREG_ST0) {
4432 o(0xd9dd); /* fstp %st(1) */
4434 #endif
4435 /* special long long case */
4436 if ((type->t & VT_BTYPE) == VT_LLONG) {
4437 sv.c.ul += 4;
4438 store(p->r2, &sv);
4440 l = loc;
4441 saved = 1;
4443 /* mark that stack entry as being saved on the stack */
4444 if (p->r & VT_LVAL) {
4445 /* also clear the bounded flag because the
4446 relocation address of the function was stored in
4447 p->c.ul */
4448 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4449 } else {
4450 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4452 p->r2 = VT_CONST;
4453 p->c.ul = l;
4458 /* find a register of class 'rc2' with at most one reference on stack.
4459 * If none, call get_reg(rc) */
4460 int get_reg_ex(int rc, int rc2)
4462 int r;
4463 SValue *p;
4465 for(r=0;r<NB_REGS;r++) {
4466 if (reg_classes[r] & rc2) {
4467 int n;
4468 n=0;
4469 for(p = vstack; p <= vtop; p++) {
4470 if ((p->r & VT_VALMASK) == r ||
4471 (p->r2 & VT_VALMASK) == r)
4472 n++;
4474 if (n <= 1)
4475 return r;
4478 return get_reg(rc);
4481 /* find a free register of class 'rc'. If none, save one register */
4482 int get_reg(int rc)
4484 int r;
4485 SValue *p;
4487 /* find a free register */
4488 for(r=0;r<NB_REGS;r++) {
4489 if (reg_classes[r] & rc) {
4490 for(p=vstack;p<=vtop;p++) {
4491 if ((p->r & VT_VALMASK) == r ||
4492 (p->r2 & VT_VALMASK) == r)
4493 goto notfound;
4495 return r;
4497 notfound: ;
4500 /* no register left : free the first one on the stack (VERY
4501 IMPORTANT to start from the bottom to ensure that we don't
4502 spill registers used in gen_opi()) */
4503 for(p=vstack;p<=vtop;p++) {
4504 r = p->r & VT_VALMASK;
4505 if (r < VT_CONST && (reg_classes[r] & rc))
4506 goto save_found;
4507 /* also look at second register (if long long) */
4508 r = p->r2 & VT_VALMASK;
4509 if (r < VT_CONST && (reg_classes[r] & rc)) {
4510 save_found:
4511 save_reg(r);
4512 return r;
4515 /* Should never comes here */
4516 return -1;
4519 /* save registers up to (vtop - n) stack entry */
4520 void save_regs(int n)
4522 int r;
4523 SValue *p, *p1;
4524 p1 = vtop - n;
4525 for(p = vstack;p <= p1; p++) {
4526 r = p->r & VT_VALMASK;
4527 if (r < VT_CONST) {
4528 save_reg(r);
4533 /* move register 's' to 'r', and flush previous value of r to memory
4534 if needed */
4535 void move_reg(int r, int s)
4537 SValue sv;
4539 if (r != s) {
4540 save_reg(r);
4541 sv.type.t = VT_INT;
4542 sv.r = s;
4543 sv.c.ul = 0;
4544 load(r, &sv);
4548 /* get address of vtop (vtop MUST BE an lvalue) */
4549 void gaddrof(void)
4551 vtop->r &= ~VT_LVAL;
4552 /* tricky: if saved lvalue, then we can go back to lvalue */
4553 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4554 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4557 #ifdef CONFIG_TCC_BCHECK
4558 /* generate lvalue bound code */
4559 void gbound(void)
4561 int lval_type;
4562 CType type1;
4564 vtop->r &= ~VT_MUSTBOUND;
4565 /* if lvalue, then use checking code before dereferencing */
4566 if (vtop->r & VT_LVAL) {
4567 /* if not VT_BOUNDED value, then make one */
4568 if (!(vtop->r & VT_BOUNDED)) {
4569 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4570 /* must save type because we must set it to int to get pointer */
4571 type1 = vtop->type;
4572 vtop->type.t = VT_INT;
4573 gaddrof();
4574 vpushi(0);
4575 gen_bounded_ptr_add();
4576 vtop->r |= lval_type;
4577 vtop->type = type1;
4579 /* then check for dereferencing */
4580 gen_bounded_ptr_deref();
4583 #endif
4585 /* store vtop a register belonging to class 'rc'. lvalues are
4586 converted to values. Cannot be used if cannot be converted to
4587 register value (such as structures). */
4588 int gv(int rc)
4590 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4591 unsigned long long ll;
4593 /* NOTE: get_reg can modify vstack[] */
4594 if (vtop->type.t & VT_BITFIELD) {
4595 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4596 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4597 /* remove bit field info to avoid loops */
4598 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4599 /* generate shifts */
4600 vpushi(32 - (bit_pos + bit_size));
4601 gen_op(TOK_SHL);
4602 vpushi(32 - bit_size);
4603 /* NOTE: transformed to SHR if unsigned */
4604 gen_op(TOK_SAR);
4605 r = gv(rc);
4606 } else {
4607 if (is_float(vtop->type.t) &&
4608 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4609 Sym *sym;
4610 int *ptr;
4611 unsigned long offset;
4613 /* XXX: unify with initializers handling ? */
4614 /* CPUs usually cannot use float constants, so we store them
4615 generically in data segment */
4616 size = type_size(&vtop->type, &align);
4617 offset = (data_section->data_offset + align - 1) & -align;
4618 data_section->data_offset = offset;
4619 /* XXX: not portable yet */
4620 ptr = section_ptr_add(data_section, size);
4621 size = size >> 2;
4622 for(i=0;i<size;i++)
4623 ptr[i] = vtop->c.tab[i];
4624 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4625 vtop->r |= VT_LVAL | VT_SYM;
4626 vtop->sym = sym;
4627 vtop->c.ul = 0;
4629 #ifdef CONFIG_TCC_BCHECK
4630 if (vtop->r & VT_MUSTBOUND)
4631 gbound();
4632 #endif
4634 r = vtop->r & VT_VALMASK;
4635 /* need to reload if:
4636 - constant
4637 - lvalue (need to dereference pointer)
4638 - already a register, but not in the right class */
4639 if (r >= VT_CONST ||
4640 (vtop->r & VT_LVAL) ||
4641 !(reg_classes[r] & rc) ||
4642 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4643 !(reg_classes[vtop->r2] & rc))) {
4644 r = get_reg(rc);
4645 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4646 /* two register type load : expand to two words
4647 temporarily */
4648 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4649 /* load constant */
4650 ll = vtop->c.ull;
4651 vtop->c.ui = ll; /* first word */
4652 load(r, vtop);
4653 vtop->r = r; /* save register value */
4654 vpushi(ll >> 32); /* second word */
4655 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4656 (vtop->r & VT_LVAL)) {
4657 /* We do not want to modifier the long long
4658 pointer here, so the safest (and less
4659 efficient) is to save all the other registers
4660 in the stack. XXX: totally inefficient. */
4661 save_regs(1);
4662 /* load from memory */
4663 load(r, vtop);
4664 vdup();
4665 vtop[-1].r = r; /* save register value */
4666 /* increment pointer to get second word */
4667 vtop->type.t = VT_INT;
4668 gaddrof();
4669 vpushi(4);
4670 gen_op('+');
4671 vtop->r |= VT_LVAL;
4672 } else {
4673 /* move registers */
4674 load(r, vtop);
4675 vdup();
4676 vtop[-1].r = r; /* save register value */
4677 vtop->r = vtop[-1].r2;
4679 /* allocate second register */
4680 rc2 = RC_INT;
4681 if (rc == RC_IRET)
4682 rc2 = RC_LRET;
4683 r2 = get_reg(rc2);
4684 load(r2, vtop);
4685 vpop();
4686 /* write second register */
4687 vtop->r2 = r2;
4688 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4689 int t1, t;
4690 /* lvalue of scalar type : need to use lvalue type
4691 because of possible cast */
4692 t = vtop->type.t;
4693 t1 = t;
4694 /* compute memory access type */
4695 if (vtop->r & VT_LVAL_BYTE)
4696 t = VT_BYTE;
4697 else if (vtop->r & VT_LVAL_SHORT)
4698 t = VT_SHORT;
4699 if (vtop->r & VT_LVAL_UNSIGNED)
4700 t |= VT_UNSIGNED;
4701 vtop->type.t = t;
4702 load(r, vtop);
4703 /* restore wanted type */
4704 vtop->type.t = t1;
4705 } else {
4706 /* one register type load */
4707 load(r, vtop);
4710 vtop->r = r;
4711 #ifdef TCC_TARGET_C67
4712 /* uses register pairs for doubles */
4713 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4714 vtop->r2 = r+1;
4715 #endif
4717 return r;
4720 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4721 void gv2(int rc1, int rc2)
4723 int v;
4725 /* generate more generic register first. But VT_JMP or VT_CMP
4726 values must be generated first in all cases to avoid possible
4727 reload errors */
4728 v = vtop[0].r & VT_VALMASK;
4729 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4730 vswap();
4731 gv(rc1);
4732 vswap();
4733 gv(rc2);
4734 /* test if reload is needed for first register */
4735 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4736 vswap();
4737 gv(rc1);
4738 vswap();
4740 } else {
4741 gv(rc2);
4742 vswap();
4743 gv(rc1);
4744 vswap();
4745 /* test if reload is needed for first register */
4746 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4747 gv(rc2);
4752 /* expand long long on stack in two int registers */
4753 void lexpand(void)
4755 int u;
4757 u = vtop->type.t & VT_UNSIGNED;
4758 gv(RC_INT);
4759 vdup();
4760 vtop[0].r = vtop[-1].r2;
4761 vtop[0].r2 = VT_CONST;
4762 vtop[-1].r2 = VT_CONST;
4763 vtop[0].type.t = VT_INT | u;
4764 vtop[-1].type.t = VT_INT | u;
4767 #ifdef TCC_TARGET_ARM
4768 /* expand long long on stack */
4769 void lexpand_nr(void)
4771 int u,v;
4773 u = vtop->type.t & VT_UNSIGNED;
4774 vdup();
4775 vtop->r2 = VT_CONST;
4776 vtop->type.t = VT_INT | u;
4777 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4778 if (v == VT_CONST) {
4779 vtop[-1].c.ui = vtop->c.ull;
4780 vtop->c.ui = vtop->c.ull >> 32;
4781 vtop->r = VT_CONST;
4782 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4783 vtop->c.ui += 4;
4784 vtop->r = vtop[-1].r;
4785 } else if (v > VT_CONST) {
4786 vtop--;
4787 lexpand();
4788 } else
4789 vtop->r = vtop[-1].r2;
4790 vtop[-1].r2 = VT_CONST;
4791 vtop[-1].type.t = VT_INT | u;
4793 #endif
4795 /* build a long long from two ints */
4796 void lbuild(int t)
4798 gv2(RC_INT, RC_INT);
4799 vtop[-1].r2 = vtop[0].r;
4800 vtop[-1].type.t = t;
4801 vpop();
4804 /* rotate n first stack elements to the bottom
4805 I1 ... In -> I2 ... In I1 [top is right]
4807 void vrotb(int n)
4809 int i;
4810 SValue tmp;
4812 tmp = vtop[-n + 1];
4813 for(i=-n+1;i!=0;i++)
4814 vtop[i] = vtop[i+1];
4815 vtop[0] = tmp;
4818 /* rotate n first stack elements to the top
4819 I1 ... In -> In I1 ... I(n-1) [top is right]
4821 void vrott(int n)
4823 int i;
4824 SValue tmp;
4826 tmp = vtop[0];
4827 for(i = 0;i < n - 1; i++)
4828 vtop[-i] = vtop[-i - 1];
4829 vtop[-n + 1] = tmp;
4832 #ifdef TCC_TARGET_ARM
4833 /* like vrott but in other direction
4834 In ... I1 -> I(n-1) ... I1 In [top is right]
4836 void vnrott(int n)
4838 int i;
4839 SValue tmp;
4841 tmp = vtop[-n + 1];
4842 for(i = n - 1; i > 0; i--)
4843 vtop[-i] = vtop[-i + 1];
4844 vtop[0] = tmp;
4846 #endif
4848 /* pop stack value */
4849 void vpop(void)
4851 int v;
4852 v = vtop->r & VT_VALMASK;
4853 #ifdef TCC_TARGET_I386
4854 /* for x86, we need to pop the FP stack */
4855 if (v == TREG_ST0 && !nocode_wanted) {
4856 o(0xd9dd); /* fstp %st(1) */
4857 } else
4858 #endif
4859 if (v == VT_JMP || v == VT_JMPI) {
4860 /* need to put correct jump if && or || without test */
4861 gsym(vtop->c.ul);
4863 vtop--;
4866 /* convert stack entry to register and duplicate its value in another
4867 register */
4868 void gv_dup(void)
4870 int rc, t, r, r1;
4871 SValue sv;
4873 t = vtop->type.t;
4874 if ((t & VT_BTYPE) == VT_LLONG) {
4875 lexpand();
4876 gv_dup();
4877 vswap();
4878 vrotb(3);
4879 gv_dup();
4880 vrotb(4);
4881 /* stack: H L L1 H1 */
4882 lbuild(t);
4883 vrotb(3);
4884 vrotb(3);
4885 vswap();
4886 lbuild(t);
4887 vswap();
4888 } else {
4889 /* duplicate value */
4890 rc = RC_INT;
4891 sv.type.t = VT_INT;
4892 if (is_float(t)) {
4893 rc = RC_FLOAT;
4894 sv.type.t = t;
4896 r = gv(rc);
4897 r1 = get_reg(rc);
4898 sv.r = r;
4899 sv.c.ul = 0;
4900 load(r1, &sv); /* move r to r1 */
4901 vdup();
4902 /* duplicates value */
4903 vtop->r = r1;
4907 /* generate CPU independent (unsigned) long long operations */
4908 void gen_opl(int op)
4910 int t, a, b, op1, c, i;
4911 int func;
4912 SValue tmp;
4914 switch(op) {
4915 case '/':
4916 case TOK_PDIV:
4917 func = TOK___divdi3;
4918 goto gen_func;
4919 case TOK_UDIV:
4920 func = TOK___udivdi3;
4921 goto gen_func;
4922 case '%':
4923 func = TOK___moddi3;
4924 goto gen_func;
4925 case TOK_UMOD:
4926 func = TOK___umoddi3;
4927 gen_func:
4928 /* call generic long long function */
4929 vpush_global_sym(&func_old_type, func);
4930 vrott(3);
4931 gfunc_call(2);
4932 vpushi(0);
4933 vtop->r = REG_IRET;
4934 vtop->r2 = REG_LRET;
4935 break;
4936 case '^':
4937 case '&':
4938 case '|':
4939 case '*':
4940 case '+':
4941 case '-':
4942 t = vtop->type.t;
4943 vswap();
4944 lexpand();
4945 vrotb(3);
4946 lexpand();
4947 /* stack: L1 H1 L2 H2 */
4948 tmp = vtop[0];
4949 vtop[0] = vtop[-3];
4950 vtop[-3] = tmp;
4951 tmp = vtop[-2];
4952 vtop[-2] = vtop[-3];
4953 vtop[-3] = tmp;
4954 vswap();
4955 /* stack: H1 H2 L1 L2 */
4956 if (op == '*') {
4957 vpushv(vtop - 1);
4958 vpushv(vtop - 1);
4959 gen_op(TOK_UMULL);
4960 lexpand();
4961 /* stack: H1 H2 L1 L2 ML MH */
4962 for(i=0;i<4;i++)
4963 vrotb(6);
4964 /* stack: ML MH H1 H2 L1 L2 */
4965 tmp = vtop[0];
4966 vtop[0] = vtop[-2];
4967 vtop[-2] = tmp;
4968 /* stack: ML MH H1 L2 H2 L1 */
4969 gen_op('*');
4970 vrotb(3);
4971 vrotb(3);
4972 gen_op('*');
4973 /* stack: ML MH M1 M2 */
4974 gen_op('+');
4975 gen_op('+');
4976 } else if (op == '+' || op == '-') {
4977 /* XXX: add non carry method too (for MIPS or alpha) */
4978 if (op == '+')
4979 op1 = TOK_ADDC1;
4980 else
4981 op1 = TOK_SUBC1;
4982 gen_op(op1);
4983 /* stack: H1 H2 (L1 op L2) */
4984 vrotb(3);
4985 vrotb(3);
4986 gen_op(op1 + 1); /* TOK_xxxC2 */
4987 } else {
4988 gen_op(op);
4989 /* stack: H1 H2 (L1 op L2) */
4990 vrotb(3);
4991 vrotb(3);
4992 /* stack: (L1 op L2) H1 H2 */
4993 gen_op(op);
4994 /* stack: (L1 op L2) (H1 op H2) */
4996 /* stack: L H */
4997 lbuild(t);
4998 break;
4999 case TOK_SAR:
5000 case TOK_SHR:
5001 case TOK_SHL:
5002 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5003 t = vtop[-1].type.t;
5004 vswap();
5005 lexpand();
5006 vrotb(3);
5007 /* stack: L H shift */
5008 c = (int)vtop->c.i;
5009 /* constant: simpler */
5010 /* NOTE: all comments are for SHL. the other cases are
5011 done by swaping words */
5012 vpop();
5013 if (op != TOK_SHL)
5014 vswap();
5015 if (c >= 32) {
5016 /* stack: L H */
5017 vpop();
5018 if (c > 32) {
5019 vpushi(c - 32);
5020 gen_op(op);
5022 if (op != TOK_SAR) {
5023 vpushi(0);
5024 } else {
5025 gv_dup();
5026 vpushi(31);
5027 gen_op(TOK_SAR);
5029 vswap();
5030 } else {
5031 vswap();
5032 gv_dup();
5033 /* stack: H L L */
5034 vpushi(c);
5035 gen_op(op);
5036 vswap();
5037 vpushi(32 - c);
5038 if (op == TOK_SHL)
5039 gen_op(TOK_SHR);
5040 else
5041 gen_op(TOK_SHL);
5042 vrotb(3);
5043 /* stack: L L H */
5044 vpushi(c);
5045 if (op == TOK_SHL)
5046 gen_op(TOK_SHL);
5047 else
5048 gen_op(TOK_SHR);
5049 gen_op('|');
5051 if (op != TOK_SHL)
5052 vswap();
5053 lbuild(t);
5054 } else {
5055 /* XXX: should provide a faster fallback on x86 ? */
5056 switch(op) {
5057 case TOK_SAR:
5058 func = TOK___sardi3;
5059 goto gen_func;
5060 case TOK_SHR:
5061 func = TOK___shrdi3;
5062 goto gen_func;
5063 case TOK_SHL:
5064 func = TOK___shldi3;
5065 goto gen_func;
5068 break;
5069 default:
5070 /* compare operations */
5071 t = vtop->type.t;
5072 vswap();
5073 lexpand();
5074 vrotb(3);
5075 lexpand();
5076 /* stack: L1 H1 L2 H2 */
5077 tmp = vtop[-1];
5078 vtop[-1] = vtop[-2];
5079 vtop[-2] = tmp;
5080 /* stack: L1 L2 H1 H2 */
5081 /* compare high */
5082 op1 = op;
5083 /* when values are equal, we need to compare low words. since
5084 the jump is inverted, we invert the test too. */
5085 if (op1 == TOK_LT)
5086 op1 = TOK_LE;
5087 else if (op1 == TOK_GT)
5088 op1 = TOK_GE;
5089 else if (op1 == TOK_ULT)
5090 op1 = TOK_ULE;
5091 else if (op1 == TOK_UGT)
5092 op1 = TOK_UGE;
5093 a = 0;
5094 b = 0;
5095 gen_op(op1);
5096 if (op1 != TOK_NE) {
5097 a = gtst(1, 0);
5099 if (op != TOK_EQ) {
5100 /* generate non equal test */
5101 /* XXX: NOT PORTABLE yet */
5102 if (a == 0) {
5103 b = gtst(0, 0);
5104 } else {
5105 #if defined(TCC_TARGET_I386)
5106 b = psym(0x850f, 0);
5107 #elif defined(TCC_TARGET_ARM)
5108 b = ind;
5109 o(0x1A000000 | encbranch(ind, 0, 1));
5110 #elif defined(TCC_TARGET_C67)
5111 error("not implemented");
5112 #else
5113 #error not supported
5114 #endif
5117 /* compare low. Always unsigned */
5118 op1 = op;
5119 if (op1 == TOK_LT)
5120 op1 = TOK_ULT;
5121 else if (op1 == TOK_LE)
5122 op1 = TOK_ULE;
5123 else if (op1 == TOK_GT)
5124 op1 = TOK_UGT;
5125 else if (op1 == TOK_GE)
5126 op1 = TOK_UGE;
5127 gen_op(op1);
5128 a = gtst(1, a);
5129 gsym(b);
5130 vseti(VT_JMPI, a);
5131 break;
5135 /* handle integer constant optimizations and various machine
5136 independent opt */
5137 void gen_opic(int op)
5139 int fc, c1, c2, n;
5140 SValue *v1, *v2;
5142 v1 = vtop - 1;
5143 v2 = vtop;
5144 /* currently, we cannot do computations with forward symbols */
5145 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5146 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5147 if (c1 && c2) {
5148 fc = v2->c.i;
5149 switch(op) {
5150 case '+': v1->c.i += fc; break;
5151 case '-': v1->c.i -= fc; break;
5152 case '&': v1->c.i &= fc; break;
5153 case '^': v1->c.i ^= fc; break;
5154 case '|': v1->c.i |= fc; break;
5155 case '*': v1->c.i *= fc; break;
5157 case TOK_PDIV:
5158 case '/':
5159 case '%':
5160 case TOK_UDIV:
5161 case TOK_UMOD:
5162 /* if division by zero, generate explicit division */
5163 if (fc == 0) {
5164 if (const_wanted)
5165 error("division by zero in constant");
5166 goto general_case;
5168 switch(op) {
5169 default: v1->c.i /= fc; break;
5170 case '%': v1->c.i %= fc; break;
5171 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5172 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5174 break;
5175 case TOK_SHL: v1->c.i <<= fc; break;
5176 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5177 case TOK_SAR: v1->c.i >>= fc; break;
5178 /* tests */
5179 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5180 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5181 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5182 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5183 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5184 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5185 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5186 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5187 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5188 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5189 /* logical */
5190 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5191 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5192 default:
5193 goto general_case;
5195 vtop--;
5196 } else {
5197 /* if commutative ops, put c2 as constant */
5198 if (c1 && (op == '+' || op == '&' || op == '^' ||
5199 op == '|' || op == '*')) {
5200 vswap();
5201 swap(&c1, &c2);
5203 fc = vtop->c.i;
5204 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5205 op == TOK_PDIV) &&
5206 fc == 1) ||
5207 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5208 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5209 fc == 0) ||
5210 (op == '&' &&
5211 fc == -1))) {
5212 /* nothing to do */
5213 vtop--;
5214 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5215 /* try to use shifts instead of muls or divs */
5216 if (fc > 0 && (fc & (fc - 1)) == 0) {
5217 n = -1;
5218 while (fc) {
5219 fc >>= 1;
5220 n++;
5222 vtop->c.i = n;
5223 if (op == '*')
5224 op = TOK_SHL;
5225 else if (op == TOK_PDIV)
5226 op = TOK_SAR;
5227 else
5228 op = TOK_SHR;
5230 goto general_case;
5231 } else if (c2 && (op == '+' || op == '-') &&
5232 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5233 (VT_CONST | VT_SYM)) {
5234 /* symbol + constant case */
5235 if (op == '-')
5236 fc = -fc;
5237 vtop--;
5238 vtop->c.i += fc;
5239 } else {
5240 general_case:
5241 if (!nocode_wanted) {
5242 /* call low level op generator */
5243 gen_opi(op);
5244 } else {
5245 vtop--;
5251 /* generate a floating point operation with constant propagation */
5252 void gen_opif(int op)
5254 int c1, c2;
5255 SValue *v1, *v2;
5256 long double f1, f2;
5258 v1 = vtop - 1;
5259 v2 = vtop;
5260 /* currently, we cannot do computations with forward symbols */
5261 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5262 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5263 if (c1 && c2) {
5264 if (v1->type.t == VT_FLOAT) {
5265 f1 = v1->c.f;
5266 f2 = v2->c.f;
5267 } else if (v1->type.t == VT_DOUBLE) {
5268 f1 = v1->c.d;
5269 f2 = v2->c.d;
5270 } else {
5271 f1 = v1->c.ld;
5272 f2 = v2->c.ld;
5275 /* NOTE: we only do constant propagation if finite number (not
5276 NaN or infinity) (ANSI spec) */
5277 if (!ieee_finite(f1) || !ieee_finite(f2))
5278 goto general_case;
5280 switch(op) {
5281 case '+': f1 += f2; break;
5282 case '-': f1 -= f2; break;
5283 case '*': f1 *= f2; break;
5284 case '/':
5285 if (f2 == 0.0) {
5286 if (const_wanted)
5287 error("division by zero in constant");
5288 goto general_case;
5290 f1 /= f2;
5291 break;
5292 /* XXX: also handles tests ? */
5293 default:
5294 goto general_case;
5296 /* XXX: overflow test ? */
5297 if (v1->type.t == VT_FLOAT) {
5298 v1->c.f = f1;
5299 } else if (v1->type.t == VT_DOUBLE) {
5300 v1->c.d = f1;
5301 } else {
5302 v1->c.ld = f1;
5304 vtop--;
5305 } else {
5306 general_case:
5307 if (!nocode_wanted) {
5308 gen_opf(op);
5309 } else {
5310 vtop--;
5315 static int pointed_size(CType *type)
5317 int align;
5318 return type_size(pointed_type(type), &align);
5321 static inline int is_null_pointer(SValue *p)
5323 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5324 return 0;
5325 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5326 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5329 static inline int is_integer_btype(int bt)
5331 return (bt == VT_BYTE || bt == VT_SHORT ||
5332 bt == VT_INT || bt == VT_LLONG);
5335 /* check types for comparison or substraction of pointers */
5336 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5338 CType *type1, *type2, tmp_type1, tmp_type2;
5339 int bt1, bt2;
5341 /* null pointers are accepted for all comparisons as gcc */
5342 if (is_null_pointer(p1) || is_null_pointer(p2))
5343 return;
5344 type1 = &p1->type;
5345 type2 = &p2->type;
5346 bt1 = type1->t & VT_BTYPE;
5347 bt2 = type2->t & VT_BTYPE;
5348 /* accept comparison between pointer and integer with a warning */
5349 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5350 warning("comparison between pointer and integer");
5351 return;
5354 /* both must be pointers or implicit function pointers */
5355 if (bt1 == VT_PTR) {
5356 type1 = pointed_type(type1);
5357 } else if (bt1 != VT_FUNC)
5358 goto invalid_operands;
5360 if (bt2 == VT_PTR) {
5361 type2 = pointed_type(type2);
5362 } else if (bt2 != VT_FUNC) {
5363 invalid_operands:
5364 error("invalid operands to binary %s", get_tok_str(op, NULL));
5366 if ((type1->t & VT_BTYPE) == VT_VOID ||
5367 (type2->t & VT_BTYPE) == VT_VOID)
5368 return;
5369 tmp_type1 = *type1;
5370 tmp_type2 = *type2;
5371 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5372 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5373 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5374 /* gcc-like error if '-' is used */
5375 if (op == '-')
5376 goto invalid_operands;
5377 else
5378 warning("comparison of distinct pointer types lacks a cast");
5382 /* generic gen_op: handles types problems */
5383 void gen_op(int op)
5385 int u, t1, t2, bt1, bt2, t;
5386 CType type1;
5388 t1 = vtop[-1].type.t;
5389 t2 = vtop[0].type.t;
5390 bt1 = t1 & VT_BTYPE;
5391 bt2 = t2 & VT_BTYPE;
5393 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5394 /* at least one operand is a pointer */
5395 /* relationnal op: must be both pointers */
5396 if (op >= TOK_ULT && op <= TOK_GT) {
5397 check_comparison_pointer_types(vtop - 1, vtop, op);
5398 /* pointers are handled are unsigned */
5399 t = VT_INT | VT_UNSIGNED;
5400 goto std_op;
5402 /* if both pointers, then it must be the '-' op */
5403 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5404 if (op != '-')
5405 error("cannot use pointers here");
5406 check_comparison_pointer_types(vtop - 1, vtop, op);
5407 /* XXX: check that types are compatible */
5408 u = pointed_size(&vtop[-1].type);
5409 gen_opic(op);
5410 /* set to integer type */
5411 vtop->type.t = VT_INT;
5412 vpushi(u);
5413 gen_op(TOK_PDIV);
5414 } else {
5415 /* exactly one pointer : must be '+' or '-'. */
5416 if (op != '-' && op != '+')
5417 error("cannot use pointers here");
5418 /* Put pointer as first operand */
5419 if (bt2 == VT_PTR) {
5420 vswap();
5421 swap(&t1, &t2);
5423 type1 = vtop[-1].type;
5424 /* XXX: cast to int ? (long long case) */
5425 vpushi(pointed_size(&vtop[-1].type));
5426 gen_op('*');
5427 #ifdef CONFIG_TCC_BCHECK
5428 /* if evaluating constant expression, no code should be
5429 generated, so no bound check */
5430 if (do_bounds_check && !const_wanted) {
5431 /* if bounded pointers, we generate a special code to
5432 test bounds */
5433 if (op == '-') {
5434 vpushi(0);
5435 vswap();
5436 gen_op('-');
5438 gen_bounded_ptr_add();
5439 } else
5440 #endif
5442 gen_opic(op);
5444 /* put again type if gen_opic() swaped operands */
5445 vtop->type = type1;
5447 } else if (is_float(bt1) || is_float(bt2)) {
5448 /* compute bigger type and do implicit casts */
5449 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5450 t = VT_LDOUBLE;
5451 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5452 t = VT_DOUBLE;
5453 } else {
5454 t = VT_FLOAT;
5456 /* floats can only be used for a few operations */
5457 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5458 (op < TOK_ULT || op > TOK_GT))
5459 error("invalid operands for binary operation");
5460 goto std_op;
5461 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5462 /* cast to biggest op */
5463 t = VT_LLONG;
5464 /* convert to unsigned if it does not fit in a long long */
5465 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5466 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5467 t |= VT_UNSIGNED;
5468 goto std_op;
5469 } else {
5470 /* integer operations */
5471 t = VT_INT;
5472 /* convert to unsigned if it does not fit in an integer */
5473 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5474 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5475 t |= VT_UNSIGNED;
5476 std_op:
5477 /* XXX: currently, some unsigned operations are explicit, so
5478 we modify them here */
5479 if (t & VT_UNSIGNED) {
5480 if (op == TOK_SAR)
5481 op = TOK_SHR;
5482 else if (op == '/')
5483 op = TOK_UDIV;
5484 else if (op == '%')
5485 op = TOK_UMOD;
5486 else if (op == TOK_LT)
5487 op = TOK_ULT;
5488 else if (op == TOK_GT)
5489 op = TOK_UGT;
5490 else if (op == TOK_LE)
5491 op = TOK_ULE;
5492 else if (op == TOK_GE)
5493 op = TOK_UGE;
5495 vswap();
5496 type1.t = t;
5497 gen_cast(&type1);
5498 vswap();
5499 /* special case for shifts and long long: we keep the shift as
5500 an integer */
5501 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5502 type1.t = VT_INT;
5503 gen_cast(&type1);
5504 if (is_float(t))
5505 gen_opif(op);
5506 else if ((t & VT_BTYPE) == VT_LLONG)
5507 gen_opl(op);
5508 else
5509 gen_opic(op);
5510 if (op >= TOK_ULT && op <= TOK_GT) {
5511 /* relationnal op: the result is an int */
5512 vtop->type.t = VT_INT;
5513 } else {
5514 vtop->type.t = t;
5519 /* generic itof for unsigned long long case */
5520 void gen_cvt_itof1(int t)
5522 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5523 (VT_LLONG | VT_UNSIGNED)) {
5525 if (t == VT_FLOAT)
5526 vpush_global_sym(&func_old_type, TOK___ulltof);
5527 else if (t == VT_DOUBLE)
5528 vpush_global_sym(&func_old_type, TOK___ulltod);
5529 else
5530 vpush_global_sym(&func_old_type, TOK___ulltold);
5531 vrott(2);
5532 gfunc_call(1);
5533 vpushi(0);
5534 vtop->r = REG_FRET;
5535 } else {
5536 gen_cvt_itof(t);
5540 /* generic ftoi for unsigned long long case */
5541 void gen_cvt_ftoi1(int t)
5543 int st;
5545 if (t == (VT_LLONG | VT_UNSIGNED)) {
5546 /* not handled natively */
5547 st = vtop->type.t & VT_BTYPE;
5548 if (st == VT_FLOAT)
5549 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5550 else if (st == VT_DOUBLE)
5551 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5552 else
5553 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5554 vrott(2);
5555 gfunc_call(1);
5556 vpushi(0);
5557 vtop->r = REG_IRET;
5558 vtop->r2 = REG_LRET;
5559 } else {
5560 gen_cvt_ftoi(t);
5564 /* force char or short cast */
5565 void force_charshort_cast(int t)
5567 int bits, dbt;
5568 dbt = t & VT_BTYPE;
5569 /* XXX: add optimization if lvalue : just change type and offset */
5570 if (dbt == VT_BYTE)
5571 bits = 8;
5572 else
5573 bits = 16;
5574 if (t & VT_UNSIGNED) {
5575 vpushi((1 << bits) - 1);
5576 gen_op('&');
5577 } else {
5578 bits = 32 - bits;
5579 vpushi(bits);
5580 gen_op(TOK_SHL);
5581 vpushi(bits);
5582 gen_op(TOK_SAR);
5586 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5587 static void gen_cast(CType *type)
5589 int sbt, dbt, sf, df, c;
5591 /* special delayed cast for char/short */
5592 /* XXX: in some cases (multiple cascaded casts), it may still
5593 be incorrect */
5594 if (vtop->r & VT_MUSTCAST) {
5595 vtop->r &= ~VT_MUSTCAST;
5596 force_charshort_cast(vtop->type.t);
5599 /* bitfields first get cast to ints */
5600 if (vtop->type.t & VT_BITFIELD) {
5601 gv(RC_INT);
5604 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5605 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5607 if (sbt != dbt && !nocode_wanted) {
5608 sf = is_float(sbt);
5609 df = is_float(dbt);
5610 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5611 if (sf && df) {
5612 /* convert from fp to fp */
5613 if (c) {
5614 /* constant case: we can do it now */
5615 /* XXX: in ISOC, cannot do it if error in convert */
5616 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5617 vtop->c.f = (float)vtop->c.d;
5618 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5619 vtop->c.f = (float)vtop->c.ld;
5620 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5621 vtop->c.d = (double)vtop->c.f;
5622 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5623 vtop->c.d = (double)vtop->c.ld;
5624 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5625 vtop->c.ld = (long double)vtop->c.f;
5626 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5627 vtop->c.ld = (long double)vtop->c.d;
5628 } else {
5629 /* non constant case: generate code */
5630 gen_cvt_ftof(dbt);
5632 } else if (df) {
5633 /* convert int to fp */
5634 if (c) {
5635 switch(sbt) {
5636 case VT_LLONG | VT_UNSIGNED:
5637 case VT_LLONG:
5638 /* XXX: add const cases for long long */
5639 goto do_itof;
5640 case VT_INT | VT_UNSIGNED:
5641 switch(dbt) {
5642 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5643 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5644 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5646 break;
5647 default:
5648 switch(dbt) {
5649 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5650 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5651 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5653 break;
5655 } else {
5656 do_itof:
5657 #if !defined(TCC_TARGET_ARM)
5658 gen_cvt_itof1(dbt);
5659 #else
5660 gen_cvt_itof(dbt);
5661 #endif
5663 } else if (sf) {
5664 /* convert fp to int */
5665 /* we handle char/short/etc... with generic code */
5666 if (dbt != (VT_INT | VT_UNSIGNED) &&
5667 dbt != (VT_LLONG | VT_UNSIGNED) &&
5668 dbt != VT_LLONG)
5669 dbt = VT_INT;
5670 if (c) {
5671 switch(dbt) {
5672 case VT_LLONG | VT_UNSIGNED:
5673 case VT_LLONG:
5674 /* XXX: add const cases for long long */
5675 goto do_ftoi;
5676 case VT_INT | VT_UNSIGNED:
5677 switch(sbt) {
5678 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5679 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5680 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5682 break;
5683 default:
5684 /* int case */
5685 switch(sbt) {
5686 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5687 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5688 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5690 break;
5692 } else {
5693 do_ftoi:
5694 gen_cvt_ftoi1(dbt);
5696 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5697 /* additional cast for char/short/bool... */
5698 vtop->type.t = dbt;
5699 gen_cast(type);
5701 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5702 if ((sbt & VT_BTYPE) != VT_LLONG) {
5703 /* scalar to long long */
5704 if (c) {
5705 if (sbt == (VT_INT | VT_UNSIGNED))
5706 vtop->c.ll = vtop->c.ui;
5707 else
5708 vtop->c.ll = vtop->c.i;
5709 } else {
5710 /* machine independent conversion */
5711 gv(RC_INT);
5712 /* generate high word */
5713 if (sbt == (VT_INT | VT_UNSIGNED)) {
5714 vpushi(0);
5715 gv(RC_INT);
5716 } else {
5717 gv_dup();
5718 vpushi(31);
5719 gen_op(TOK_SAR);
5721 /* patch second register */
5722 vtop[-1].r2 = vtop->r;
5723 vpop();
5726 } else if (dbt == VT_BOOL) {
5727 /* scalar to bool */
5728 vpushi(0);
5729 gen_op(TOK_NE);
5730 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5731 (dbt & VT_BTYPE) == VT_SHORT) {
5732 force_charshort_cast(dbt);
5733 } else if ((dbt & VT_BTYPE) == VT_INT) {
5734 /* scalar to int */
5735 if (sbt == VT_LLONG) {
5736 /* from long long: just take low order word */
5737 lexpand();
5738 vpop();
5740 /* if lvalue and single word type, nothing to do because
5741 the lvalue already contains the real type size (see
5742 VT_LVAL_xxx constants) */
5745 vtop->type = *type;
5748 /* return type size. Put alignment at 'a' */
5749 static int type_size(CType *type, int *a)
5751 Sym *s;
5752 int bt;
5754 bt = type->t & VT_BTYPE;
5755 if (bt == VT_STRUCT) {
5756 /* struct/union */
5757 s = type->ref;
5758 *a = s->r;
5759 return s->c;
5760 } else if (bt == VT_PTR) {
5761 if (type->t & VT_ARRAY) {
5762 s = type->ref;
5763 return type_size(&s->type, a) * s->c;
5764 } else {
5765 *a = PTR_SIZE;
5766 return PTR_SIZE;
5768 } else if (bt == VT_LDOUBLE) {
5769 *a = LDOUBLE_ALIGN;
5770 return LDOUBLE_SIZE;
5771 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5772 #ifdef TCC_TARGET_I386
5773 *a = 4;
5774 #else
5775 *a = 8;
5776 #endif
5777 return 8;
5778 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5779 *a = 4;
5780 return 4;
5781 } else if (bt == VT_SHORT) {
5782 *a = 2;
5783 return 2;
5784 } else {
5785 /* char, void, function, _Bool */
5786 *a = 1;
5787 return 1;
5791 /* return the pointed type of t */
5792 static inline CType *pointed_type(CType *type)
5794 return &type->ref->type;
5797 /* modify type so that its it is a pointer to type. */
5798 static void mk_pointer(CType *type)
5800 Sym *s;
5801 s = sym_push(SYM_FIELD, type, 0, -1);
5802 type->t = VT_PTR | (type->t & ~VT_TYPE);
5803 type->ref = s;
5806 /* compare function types. OLD functions match any new functions */
5807 static int is_compatible_func(CType *type1, CType *type2)
5809 Sym *s1, *s2;
5811 s1 = type1->ref;
5812 s2 = type2->ref;
5813 if (!is_compatible_types(&s1->type, &s2->type))
5814 return 0;
5815 /* check func_call */
5816 if (s1->r != s2->r)
5817 return 0;
5818 /* XXX: not complete */
5819 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5820 return 1;
5821 if (s1->c != s2->c)
5822 return 0;
5823 while (s1 != NULL) {
5824 if (s2 == NULL)
5825 return 0;
5826 if (!is_compatible_types(&s1->type, &s2->type))
5827 return 0;
5828 s1 = s1->next;
5829 s2 = s2->next;
5831 if (s2)
5832 return 0;
5833 return 1;
5836 /* return true if type1 and type2 are exactly the same (including
5837 qualifiers).
5839 - enums are not checked as gcc __builtin_types_compatible_p ()
5841 static int is_compatible_types(CType *type1, CType *type2)
5843 int bt1, t1, t2;
5845 t1 = type1->t & VT_TYPE;
5846 t2 = type2->t & VT_TYPE;
5847 /* XXX: bitfields ? */
5848 if (t1 != t2)
5849 return 0;
5850 /* test more complicated cases */
5851 bt1 = t1 & VT_BTYPE;
5852 if (bt1 == VT_PTR) {
5853 type1 = pointed_type(type1);
5854 type2 = pointed_type(type2);
5855 return is_compatible_types(type1, type2);
5856 } else if (bt1 == VT_STRUCT) {
5857 return (type1->ref == type2->ref);
5858 } else if (bt1 == VT_FUNC) {
5859 return is_compatible_func(type1, type2);
5860 } else {
5861 return 1;
5865 /* print a type. If 'varstr' is not NULL, then the variable is also
5866 printed in the type */
5867 /* XXX: union */
5868 /* XXX: add array and function pointers */
5869 void type_to_str(char *buf, int buf_size,
5870 CType *type, const char *varstr)
5872 int bt, v, t;
5873 Sym *s, *sa;
5874 char buf1[256];
5875 const char *tstr;
5877 t = type->t & VT_TYPE;
5878 bt = t & VT_BTYPE;
5879 buf[0] = '\0';
5880 if (t & VT_CONSTANT)
5881 pstrcat(buf, buf_size, "const ");
5882 if (t & VT_VOLATILE)
5883 pstrcat(buf, buf_size, "volatile ");
5884 if (t & VT_UNSIGNED)
5885 pstrcat(buf, buf_size, "unsigned ");
5886 switch(bt) {
5887 case VT_VOID:
5888 tstr = "void";
5889 goto add_tstr;
5890 case VT_BOOL:
5891 tstr = "_Bool";
5892 goto add_tstr;
5893 case VT_BYTE:
5894 tstr = "char";
5895 goto add_tstr;
5896 case VT_SHORT:
5897 tstr = "short";
5898 goto add_tstr;
5899 case VT_INT:
5900 tstr = "int";
5901 goto add_tstr;
5902 case VT_LONG:
5903 tstr = "long";
5904 goto add_tstr;
5905 case VT_LLONG:
5906 tstr = "long long";
5907 goto add_tstr;
5908 case VT_FLOAT:
5909 tstr = "float";
5910 goto add_tstr;
5911 case VT_DOUBLE:
5912 tstr = "double";
5913 goto add_tstr;
5914 case VT_LDOUBLE:
5915 tstr = "long double";
5916 add_tstr:
5917 pstrcat(buf, buf_size, tstr);
5918 break;
5919 case VT_ENUM:
5920 case VT_STRUCT:
5921 if (bt == VT_STRUCT)
5922 tstr = "struct ";
5923 else
5924 tstr = "enum ";
5925 pstrcat(buf, buf_size, tstr);
5926 v = type->ref->v & ~SYM_STRUCT;
5927 if (v >= SYM_FIRST_ANOM)
5928 pstrcat(buf, buf_size, "<anonymous>");
5929 else
5930 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5931 break;
5932 case VT_FUNC:
5933 s = type->ref;
5934 type_to_str(buf, buf_size, &s->type, varstr);
5935 pstrcat(buf, buf_size, "(");
5936 sa = s->next;
5937 while (sa != NULL) {
5938 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5939 pstrcat(buf, buf_size, buf1);
5940 sa = sa->next;
5941 if (sa)
5942 pstrcat(buf, buf_size, ", ");
5944 pstrcat(buf, buf_size, ")");
5945 goto no_var;
5946 case VT_PTR:
5947 s = type->ref;
5948 pstrcpy(buf1, sizeof(buf1), "*");
5949 if (varstr)
5950 pstrcat(buf1, sizeof(buf1), varstr);
5951 type_to_str(buf, buf_size, &s->type, buf1);
5952 goto no_var;
5954 if (varstr) {
5955 pstrcat(buf, buf_size, " ");
5956 pstrcat(buf, buf_size, varstr);
5958 no_var: ;
5961 /* verify type compatibility to store vtop in 'dt' type, and generate
5962 casts if needed. */
5963 static void gen_assign_cast(CType *dt)
5965 CType *st, *type1, *type2, tmp_type1, tmp_type2;
5966 char buf1[256], buf2[256];
5967 int dbt, sbt;
5969 st = &vtop->type; /* source type */
5970 dbt = dt->t & VT_BTYPE;
5971 sbt = st->t & VT_BTYPE;
5972 if (dt->t & VT_CONSTANT)
5973 warning("assignment of read-only location");
5974 switch(dbt) {
5975 case VT_PTR:
5976 /* special cases for pointers */
5977 /* '0' can also be a pointer */
5978 if (is_null_pointer(vtop))
5979 goto type_ok;
5980 /* accept implicit pointer to integer cast with warning */
5981 if (is_integer_btype(sbt)) {
5982 warning("assignment makes pointer from integer without a cast");
5983 goto type_ok;
5985 type1 = pointed_type(dt);
5986 /* a function is implicitely a function pointer */
5987 if (sbt == VT_FUNC) {
5988 if ((type1->t & VT_BTYPE) != VT_VOID &&
5989 !is_compatible_types(pointed_type(dt), st))
5990 goto error;
5991 else
5992 goto type_ok;
5994 if (sbt != VT_PTR)
5995 goto error;
5996 type2 = pointed_type(st);
5997 if ((type1->t & VT_BTYPE) == VT_VOID ||
5998 (type2->t & VT_BTYPE) == VT_VOID) {
5999 /* void * can match anything */
6000 } else {
6001 /* exact type match, except for unsigned */
6002 tmp_type1 = *type1;
6003 tmp_type2 = *type2;
6004 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6005 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6006 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6007 goto error;
6009 /* check const and volatile */
6010 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6011 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6012 warning("assignment discards qualifiers from pointer target type");
6013 break;
6014 case VT_BYTE:
6015 case VT_SHORT:
6016 case VT_INT:
6017 case VT_LLONG:
6018 if (sbt == VT_PTR || sbt == VT_FUNC) {
6019 warning("assignment makes integer from pointer without a cast");
6021 /* XXX: more tests */
6022 break;
6023 case VT_STRUCT:
6024 tmp_type1 = *dt;
6025 tmp_type2 = *st;
6026 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6027 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6028 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6029 error:
6030 type_to_str(buf1, sizeof(buf1), st, NULL);
6031 type_to_str(buf2, sizeof(buf2), dt, NULL);
6032 error("cannot cast '%s' to '%s'", buf1, buf2);
6034 break;
6036 type_ok:
6037 gen_cast(dt);
6040 /* store vtop in lvalue pushed on stack */
6041 void vstore(void)
6043 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6045 ft = vtop[-1].type.t;
6046 sbt = vtop->type.t & VT_BTYPE;
6047 dbt = ft & VT_BTYPE;
6048 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6049 (sbt == VT_INT && dbt == VT_SHORT)) {
6050 /* optimize char/short casts */
6051 delayed_cast = VT_MUSTCAST;
6052 vtop->type.t = ft & VT_TYPE;
6053 /* XXX: factorize */
6054 if (ft & VT_CONSTANT)
6055 warning("assignment of read-only location");
6056 } else {
6057 delayed_cast = 0;
6058 if (!(ft & VT_BITFIELD))
6059 gen_assign_cast(&vtop[-1].type);
6062 if (sbt == VT_STRUCT) {
6063 /* if structure, only generate pointer */
6064 /* structure assignment : generate memcpy */
6065 /* XXX: optimize if small size */
6066 if (!nocode_wanted) {
6067 size = type_size(&vtop->type, &align);
6069 vpush_global_sym(&func_old_type, TOK_memcpy);
6071 /* destination */
6072 vpushv(vtop - 2);
6073 vtop->type.t = VT_INT;
6074 gaddrof();
6075 /* source */
6076 vpushv(vtop - 2);
6077 vtop->type.t = VT_INT;
6078 gaddrof();
6079 /* type size */
6080 vpushi(size);
6081 gfunc_call(3);
6083 vswap();
6084 vpop();
6085 } else {
6086 vswap();
6087 vpop();
6089 /* leave source on stack */
6090 } else if (ft & VT_BITFIELD) {
6091 /* bitfield store handling */
6092 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6093 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6094 /* remove bit field info to avoid loops */
6095 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6097 /* duplicate destination */
6098 vdup();
6099 vtop[-1] = vtop[-2];
6101 /* mask and shift source */
6102 vpushi((1 << bit_size) - 1);
6103 gen_op('&');
6104 vpushi(bit_pos);
6105 gen_op(TOK_SHL);
6106 /* load destination, mask and or with source */
6107 vswap();
6108 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6109 gen_op('&');
6110 gen_op('|');
6111 /* store result */
6112 vstore();
6113 } else {
6114 #ifdef CONFIG_TCC_BCHECK
6115 /* bound check case */
6116 if (vtop[-1].r & VT_MUSTBOUND) {
6117 vswap();
6118 gbound();
6119 vswap();
6121 #endif
6122 if (!nocode_wanted) {
6123 rc = RC_INT;
6124 if (is_float(ft))
6125 rc = RC_FLOAT;
6126 r = gv(rc); /* generate value */
6127 /* if lvalue was saved on stack, must read it */
6128 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6129 SValue sv;
6130 t = get_reg(RC_INT);
6131 sv.type.t = VT_INT;
6132 sv.r = VT_LOCAL | VT_LVAL;
6133 sv.c.ul = vtop[-1].c.ul;
6134 load(t, &sv);
6135 vtop[-1].r = t | VT_LVAL;
6137 store(r, vtop - 1);
6138 /* two word case handling : store second register at word + 4 */
6139 if ((ft & VT_BTYPE) == VT_LLONG) {
6140 vswap();
6141 /* convert to int to increment easily */
6142 vtop->type.t = VT_INT;
6143 gaddrof();
6144 vpushi(4);
6145 gen_op('+');
6146 vtop->r |= VT_LVAL;
6147 vswap();
6148 /* XXX: it works because r2 is spilled last ! */
6149 store(vtop->r2, vtop - 1);
6152 vswap();
6153 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6154 vtop->r |= delayed_cast;
6158 /* post defines POST/PRE add. c is the token ++ or -- */
6159 void inc(int post, int c)
6161 test_lvalue();
6162 vdup(); /* save lvalue */
6163 if (post) {
6164 gv_dup(); /* duplicate value */
6165 vrotb(3);
6166 vrotb(3);
6168 /* add constant */
6169 vpushi(c - TOK_MID);
6170 gen_op('+');
6171 vstore(); /* store value */
6172 if (post)
6173 vpop(); /* if post op, return saved value */
6176 /* Parse GNUC __attribute__ extension. Currently, the following
6177 extensions are recognized:
6178 - aligned(n) : set data/function alignment.
6179 - packed : force data alignment to 1
6180 - section(x) : generate data/code in this section.
6181 - unused : currently ignored, but may be used someday.
6182 - regparm(n) : pass function parameters in registers (i386 only)
6184 static void parse_attribute(AttributeDef *ad)
6186 int t, n;
6188 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6189 next();
6190 skip('(');
6191 skip('(');
6192 while (tok != ')') {
6193 if (tok < TOK_IDENT)
6194 expect("attribute name");
6195 t = tok;
6196 next();
6197 switch(t) {
6198 case TOK_SECTION1:
6199 case TOK_SECTION2:
6200 skip('(');
6201 if (tok != TOK_STR)
6202 expect("section name");
6203 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6204 next();
6205 skip(')');
6206 break;
6207 case TOK_ALIGNED1:
6208 case TOK_ALIGNED2:
6209 if (tok == '(') {
6210 next();
6211 n = expr_const();
6212 if (n <= 0 || (n & (n - 1)) != 0)
6213 error("alignment must be a positive power of two");
6214 skip(')');
6215 } else {
6216 n = MAX_ALIGN;
6218 ad->aligned = n;
6219 break;
6220 case TOK_PACKED1:
6221 case TOK_PACKED2:
6222 ad->packed = 1;
6223 break;
6224 case TOK_UNUSED1:
6225 case TOK_UNUSED2:
6226 /* currently, no need to handle it because tcc does not
6227 track unused objects */
6228 break;
6229 case TOK_NORETURN1:
6230 case TOK_NORETURN2:
6231 /* currently, no need to handle it because tcc does not
6232 track unused objects */
6233 break;
6234 case TOK_CDECL1:
6235 case TOK_CDECL2:
6236 case TOK_CDECL3:
6237 ad->func_call = FUNC_CDECL;
6238 break;
6239 case TOK_STDCALL1:
6240 case TOK_STDCALL2:
6241 case TOK_STDCALL3:
6242 ad->func_call = FUNC_STDCALL;
6243 break;
6244 #ifdef TCC_TARGET_I386
6245 case TOK_REGPARM1:
6246 case TOK_REGPARM2:
6247 skip('(');
6248 n = expr_const();
6249 if (n > 3)
6250 n = 3;
6251 else if (n < 0)
6252 n = 0;
6253 if (n > 0)
6254 ad->func_call = FUNC_FASTCALL1 + n - 1;
6255 skip(')');
6256 break;
6257 #endif
6258 default:
6259 if (tcc_state->warn_unsupported)
6260 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6261 /* skip parameters */
6262 /* XXX: skip parenthesis too */
6263 if (tok == '(') {
6264 next();
6265 while (tok != ')' && tok != -1)
6266 next();
6267 next();
6269 break;
6271 if (tok != ',')
6272 break;
6273 next();
6275 skip(')');
6276 skip(')');
6280 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6281 static void struct_decl(CType *type, int u)
6283 int a, v, size, align, maxalign, c, offset;
6284 int bit_size, bit_pos, bsize, bt, lbit_pos;
6285 Sym *s, *ss, **ps;
6286 AttributeDef ad;
6287 CType type1, btype;
6289 a = tok; /* save decl type */
6290 next();
6291 if (tok != '{') {
6292 v = tok;
6293 next();
6294 /* struct already defined ? return it */
6295 if (v < TOK_IDENT)
6296 expect("struct/union/enum name");
6297 s = struct_find(v);
6298 if (s) {
6299 if (s->type.t != a)
6300 error("invalid type");
6301 goto do_decl;
6303 } else {
6304 v = anon_sym++;
6306 type1.t = a;
6307 /* we put an undefined size for struct/union */
6308 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6309 s->r = 0; /* default alignment is zero as gcc */
6310 /* put struct/union/enum name in type */
6311 do_decl:
6312 type->t = u;
6313 type->ref = s;
6315 if (tok == '{') {
6316 next();
6317 if (s->c != -1)
6318 error("struct/union/enum already defined");
6319 /* cannot be empty */
6320 c = 0;
6321 /* non empty enums are not allowed */
6322 if (a == TOK_ENUM) {
6323 for(;;) {
6324 v = tok;
6325 if (v < TOK_UIDENT)
6326 expect("identifier");
6327 next();
6328 if (tok == '=') {
6329 next();
6330 c = expr_const();
6332 /* enum symbols have static storage */
6333 ss = sym_push(v, &int_type, VT_CONST, c);
6334 ss->type.t |= VT_STATIC;
6335 if (tok != ',')
6336 break;
6337 next();
6338 c++;
6339 /* NOTE: we accept a trailing comma */
6340 if (tok == '}')
6341 break;
6343 skip('}');
6344 } else {
6345 maxalign = 1;
6346 ps = &s->next;
6347 bit_pos = 0;
6348 offset = 0;
6349 while (tok != '}') {
6350 parse_btype(&btype, &ad);
6351 while (1) {
6352 bit_size = -1;
6353 v = 0;
6354 type1 = btype;
6355 if (tok != ':') {
6356 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6357 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6358 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6359 error("invalid type for '%s'",
6360 get_tok_str(v, NULL));
6362 if (tok == ':') {
6363 next();
6364 bit_size = expr_const();
6365 /* XXX: handle v = 0 case for messages */
6366 if (bit_size < 0)
6367 error("negative width in bit-field '%s'",
6368 get_tok_str(v, NULL));
6369 if (v && bit_size == 0)
6370 error("zero width for bit-field '%s'",
6371 get_tok_str(v, NULL));
6373 size = type_size(&type1, &align);
6374 if (ad.aligned) {
6375 if (align < ad.aligned)
6376 align = ad.aligned;
6377 } else if (ad.packed) {
6378 align = 1;
6380 lbit_pos = 0;
6381 if (bit_size >= 0) {
6382 bt = type1.t & VT_BTYPE;
6383 if (bt != VT_INT &&
6384 bt != VT_BYTE &&
6385 bt != VT_SHORT &&
6386 bt != VT_BOOL &&
6387 bt != VT_ENUM)
6388 error("bitfields must have scalar type");
6389 bsize = size * 8;
6390 if (bit_size > bsize) {
6391 error("width of '%s' exceeds its type",
6392 get_tok_str(v, NULL));
6393 } else if (bit_size == bsize) {
6394 /* no need for bit fields */
6395 bit_pos = 0;
6396 } else if (bit_size == 0) {
6397 /* XXX: what to do if only padding in a
6398 structure ? */
6399 /* zero size: means to pad */
6400 if (bit_pos > 0)
6401 bit_pos = bsize;
6402 } else {
6403 /* we do not have enough room ? */
6404 if ((bit_pos + bit_size) > bsize)
6405 bit_pos = 0;
6406 lbit_pos = bit_pos;
6407 /* XXX: handle LSB first */
6408 type1.t |= VT_BITFIELD |
6409 (bit_pos << VT_STRUCT_SHIFT) |
6410 (bit_size << (VT_STRUCT_SHIFT + 6));
6411 bit_pos += bit_size;
6413 } else {
6414 bit_pos = 0;
6416 if (v) {
6417 /* add new memory data only if starting
6418 bit field */
6419 if (lbit_pos == 0) {
6420 if (a == TOK_STRUCT) {
6421 c = (c + align - 1) & -align;
6422 offset = c;
6423 c += size;
6424 } else {
6425 offset = 0;
6426 if (size > c)
6427 c = size;
6429 if (align > maxalign)
6430 maxalign = align;
6432 #if 0
6433 printf("add field %s offset=%d",
6434 get_tok_str(v, NULL), offset);
6435 if (type1.t & VT_BITFIELD) {
6436 printf(" pos=%d size=%d",
6437 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6438 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6440 printf("\n");
6441 #endif
6442 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6443 *ps = ss;
6444 ps = &ss->next;
6446 if (tok == ';' || tok == TOK_EOF)
6447 break;
6448 skip(',');
6450 skip(';');
6452 skip('}');
6453 /* store size and alignment */
6454 s->c = (c + maxalign - 1) & -maxalign;
6455 s->r = maxalign;
6460 /* return 0 if no type declaration. otherwise, return the basic type
6461 and skip it.
6463 static int parse_btype(CType *type, AttributeDef *ad)
6465 int t, u, type_found, typespec_found;
6466 Sym *s;
6467 CType type1;
6469 memset(ad, 0, sizeof(AttributeDef));
6470 type_found = 0;
6471 typespec_found = 0;
6472 t = 0;
6473 while(1) {
6474 switch(tok) {
6475 case TOK_EXTENSION:
6476 /* currently, we really ignore extension */
6477 next();
6478 continue;
6480 /* basic types */
6481 case TOK_CHAR:
6482 u = VT_BYTE;
6483 basic_type:
6484 next();
6485 basic_type1:
6486 if ((t & VT_BTYPE) != 0)
6487 error("too many basic types");
6488 t |= u;
6489 typespec_found = 1;
6490 break;
6491 case TOK_VOID:
6492 u = VT_VOID;
6493 goto basic_type;
6494 case TOK_SHORT:
6495 u = VT_SHORT;
6496 goto basic_type;
6497 case TOK_INT:
6498 next();
6499 typespec_found = 1;
6500 break;
6501 case TOK_LONG:
6502 next();
6503 if ((t & VT_BTYPE) == VT_DOUBLE) {
6504 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6505 } else if ((t & VT_BTYPE) == VT_LONG) {
6506 t = (t & ~VT_BTYPE) | VT_LLONG;
6507 } else {
6508 u = VT_LONG;
6509 goto basic_type1;
6511 break;
6512 case TOK_BOOL:
6513 u = VT_BOOL;
6514 goto basic_type;
6515 case TOK_FLOAT:
6516 u = VT_FLOAT;
6517 goto basic_type;
6518 case TOK_DOUBLE:
6519 next();
6520 if ((t & VT_BTYPE) == VT_LONG) {
6521 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6522 } else {
6523 u = VT_DOUBLE;
6524 goto basic_type1;
6526 break;
6527 case TOK_ENUM:
6528 struct_decl(&type1, VT_ENUM);
6529 basic_type2:
6530 u = type1.t;
6531 type->ref = type1.ref;
6532 goto basic_type1;
6533 case TOK_STRUCT:
6534 case TOK_UNION:
6535 struct_decl(&type1, VT_STRUCT);
6536 goto basic_type2;
6538 /* type modifiers */
6539 case TOK_CONST1:
6540 case TOK_CONST2:
6541 case TOK_CONST3:
6542 t |= VT_CONSTANT;
6543 next();
6544 break;
6545 case TOK_VOLATILE1:
6546 case TOK_VOLATILE2:
6547 case TOK_VOLATILE3:
6548 t |= VT_VOLATILE;
6549 next();
6550 break;
6551 case TOK_SIGNED1:
6552 case TOK_SIGNED2:
6553 case TOK_SIGNED3:
6554 typespec_found = 1;
6555 t |= VT_SIGNED;
6556 next();
6557 break;
6558 case TOK_REGISTER:
6559 case TOK_AUTO:
6560 case TOK_RESTRICT1:
6561 case TOK_RESTRICT2:
6562 case TOK_RESTRICT3:
6563 next();
6564 break;
6565 case TOK_UNSIGNED:
6566 t |= VT_UNSIGNED;
6567 next();
6568 typespec_found = 1;
6569 break;
6571 /* storage */
6572 case TOK_EXTERN:
6573 t |= VT_EXTERN;
6574 next();
6575 break;
6576 case TOK_STATIC:
6577 t |= VT_STATIC;
6578 next();
6579 break;
6580 case TOK_TYPEDEF:
6581 t |= VT_TYPEDEF;
6582 next();
6583 break;
6584 case TOK_INLINE1:
6585 case TOK_INLINE2:
6586 case TOK_INLINE3:
6587 t |= VT_INLINE;
6588 next();
6589 break;
6591 /* GNUC attribute */
6592 case TOK_ATTRIBUTE1:
6593 case TOK_ATTRIBUTE2:
6594 parse_attribute(ad);
6595 break;
6596 /* GNUC typeof */
6597 case TOK_TYPEOF1:
6598 case TOK_TYPEOF2:
6599 case TOK_TYPEOF3:
6600 next();
6601 parse_expr_type(&type1);
6602 goto basic_type2;
6603 default:
6604 if (typespec_found)
6605 goto the_end;
6606 s = sym_find(tok);
6607 if (!s || !(s->type.t & VT_TYPEDEF))
6608 goto the_end;
6609 t |= (s->type.t & ~VT_TYPEDEF);
6610 type->ref = s->type.ref;
6611 next();
6612 break;
6614 type_found = 1;
6616 the_end:
6617 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6618 error("signed and unsigned modifier");
6619 if (tcc_state->char_is_unsigned) {
6620 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6621 t |= VT_UNSIGNED;
6623 t &= ~VT_SIGNED;
6625 /* long is never used as type */
6626 if ((t & VT_BTYPE) == VT_LONG)
6627 t = (t & ~VT_BTYPE) | VT_INT;
6628 type->t = t;
6629 return type_found;
6632 /* convert a function parameter type (array to pointer and function to
6633 function pointer) */
6634 static inline void convert_parameter_type(CType *pt)
6636 /* remove const and volatile qualifiers (XXX: const could be used
6637 to indicate a const function parameter */
6638 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6639 /* array must be transformed to pointer according to ANSI C */
6640 pt->t &= ~VT_ARRAY;
6641 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6642 mk_pointer(pt);
6646 static void post_type(CType *type, AttributeDef *ad)
6648 int n, l, t1;
6649 Sym **plast, *s, *first;
6650 AttributeDef ad1;
6651 CType pt;
6653 if (tok == '(') {
6654 /* function declaration */
6655 next();
6656 l = 0;
6657 first = NULL;
6658 plast = &first;
6659 while (tok != ')') {
6660 /* read param name and compute offset */
6661 if (l != FUNC_OLD) {
6662 if (!parse_btype(&pt, &ad1)) {
6663 if (l) {
6664 error("invalid type");
6665 } else {
6666 l = FUNC_OLD;
6667 goto old_proto;
6670 l = FUNC_NEW;
6671 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6672 break;
6673 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6674 if ((pt.t & VT_BTYPE) == VT_VOID)
6675 error("parameter declared as void");
6676 } else {
6677 old_proto:
6678 n = tok;
6679 pt.t = VT_INT;
6680 next();
6682 convert_parameter_type(&pt);
6683 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6684 *plast = s;
6685 plast = &s->next;
6686 if (tok == ',') {
6687 next();
6688 if (l == FUNC_NEW && tok == TOK_DOTS) {
6689 l = FUNC_ELLIPSIS;
6690 next();
6691 break;
6695 /* if no parameters, then old type prototype */
6696 if (l == 0)
6697 l = FUNC_OLD;
6698 skip(')');
6699 t1 = type->t & VT_STORAGE;
6700 /* NOTE: const is ignored in returned type as it has a special
6701 meaning in gcc / C++ */
6702 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6703 post_type(type, ad);
6704 /* we push a anonymous symbol which will contain the function prototype */
6705 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6706 s->next = first;
6707 type->t = t1 | VT_FUNC;
6708 type->ref = s;
6709 } else if (tok == '[') {
6710 /* array definition */
6711 next();
6712 n = -1;
6713 if (tok != ']') {
6714 n = expr_const();
6715 if (n < 0)
6716 error("invalid array size");
6718 skip(']');
6719 /* parse next post type */
6720 t1 = type->t & VT_STORAGE;
6721 type->t &= ~VT_STORAGE;
6722 post_type(type, ad);
6724 /* we push a anonymous symbol which will contain the array
6725 element type */
6726 s = sym_push(SYM_FIELD, type, 0, n);
6727 type->t = t1 | VT_ARRAY | VT_PTR;
6728 type->ref = s;
6732 /* Parse a type declaration (except basic type), and return the type
6733 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6734 expected. 'type' should contain the basic type. 'ad' is the
6735 attribute definition of the basic type. It can be modified by
6736 type_decl().
6738 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6740 Sym *s;
6741 CType type1, *type2;
6742 int qualifiers;
6744 while (tok == '*') {
6745 qualifiers = 0;
6746 redo:
6747 next();
6748 switch(tok) {
6749 case TOK_CONST1:
6750 case TOK_CONST2:
6751 case TOK_CONST3:
6752 qualifiers |= VT_CONSTANT;
6753 goto redo;
6754 case TOK_VOLATILE1:
6755 case TOK_VOLATILE2:
6756 case TOK_VOLATILE3:
6757 qualifiers |= VT_VOLATILE;
6758 goto redo;
6759 case TOK_RESTRICT1:
6760 case TOK_RESTRICT2:
6761 case TOK_RESTRICT3:
6762 goto redo;
6764 mk_pointer(type);
6765 type->t |= qualifiers;
6768 /* XXX: clarify attribute handling */
6769 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6770 parse_attribute(ad);
6772 /* recursive type */
6773 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6774 type1.t = 0; /* XXX: same as int */
6775 if (tok == '(') {
6776 next();
6777 /* XXX: this is not correct to modify 'ad' at this point, but
6778 the syntax is not clear */
6779 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6780 parse_attribute(ad);
6781 type_decl(&type1, ad, v, td);
6782 skip(')');
6783 } else {
6784 /* type identifier */
6785 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6786 *v = tok;
6787 next();
6788 } else {
6789 if (!(td & TYPE_ABSTRACT))
6790 expect("identifier");
6791 *v = 0;
6794 post_type(type, ad);
6795 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6796 parse_attribute(ad);
6797 if (!type1.t)
6798 return;
6799 /* append type at the end of type1 */
6800 type2 = &type1;
6801 for(;;) {
6802 s = type2->ref;
6803 type2 = &s->type;
6804 if (!type2->t) {
6805 *type2 = *type;
6806 break;
6809 *type = type1;
6812 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6813 static int lvalue_type(int t)
6815 int bt, r;
6816 r = VT_LVAL;
6817 bt = t & VT_BTYPE;
6818 if (bt == VT_BYTE || bt == VT_BOOL)
6819 r |= VT_LVAL_BYTE;
6820 else if (bt == VT_SHORT)
6821 r |= VT_LVAL_SHORT;
6822 else
6823 return r;
6824 if (t & VT_UNSIGNED)
6825 r |= VT_LVAL_UNSIGNED;
6826 return r;
6829 /* indirection with full error checking and bound check */
6830 static void indir(void)
6832 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6833 expect("pointer");
6834 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6835 gv(RC_INT);
6836 vtop->type = *pointed_type(&vtop->type);
6837 /* an array is never an lvalue */
6838 if (!(vtop->type.t & VT_ARRAY)) {
6839 vtop->r |= lvalue_type(vtop->type.t);
6840 /* if bound checking, the referenced pointer must be checked */
6841 if (do_bounds_check)
6842 vtop->r |= VT_MUSTBOUND;
6846 /* pass a parameter to a function and do type checking and casting */
6847 static void gfunc_param_typed(Sym *func, Sym *arg)
6849 int func_type;
6850 CType type;
6852 func_type = func->c;
6853 if (func_type == FUNC_OLD ||
6854 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6855 /* default casting : only need to convert float to double */
6856 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6857 type.t = VT_DOUBLE;
6858 gen_cast(&type);
6860 } else if (arg == NULL) {
6861 error("too many arguments to function");
6862 } else {
6863 type = arg->type;
6864 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6865 gen_assign_cast(&type);
6869 /* parse an expression of the form '(type)' or '(expr)' and return its
6870 type */
6871 static void parse_expr_type(CType *type)
6873 int n;
6874 AttributeDef ad;
6876 skip('(');
6877 if (parse_btype(type, &ad)) {
6878 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6879 } else {
6880 expr_type(type);
6882 skip(')');
6885 static void parse_type(CType *type)
6887 AttributeDef ad;
6888 int n;
6890 if (!parse_btype(type, &ad)) {
6891 expect("type");
6893 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6896 static void vpush_tokc(int t)
6898 CType type;
6899 type.t = t;
6900 vsetc(&type, VT_CONST, &tokc);
6903 static void unary(void)
6905 int n, t, align, size, r;
6906 CType type;
6907 Sym *s;
6908 AttributeDef ad;
6910 /* XXX: GCC 2.95.3 does not generate a table although it should be
6911 better here */
6912 tok_next:
6913 switch(tok) {
6914 case TOK_EXTENSION:
6915 next();
6916 goto tok_next;
6917 case TOK_CINT:
6918 case TOK_CCHAR:
6919 case TOK_LCHAR:
6920 vpushi(tokc.i);
6921 next();
6922 break;
6923 case TOK_CUINT:
6924 vpush_tokc(VT_INT | VT_UNSIGNED);
6925 next();
6926 break;
6927 case TOK_CLLONG:
6928 vpush_tokc(VT_LLONG);
6929 next();
6930 break;
6931 case TOK_CULLONG:
6932 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6933 next();
6934 break;
6935 case TOK_CFLOAT:
6936 vpush_tokc(VT_FLOAT);
6937 next();
6938 break;
6939 case TOK_CDOUBLE:
6940 vpush_tokc(VT_DOUBLE);
6941 next();
6942 break;
6943 case TOK_CLDOUBLE:
6944 vpush_tokc(VT_LDOUBLE);
6945 next();
6946 break;
6947 case TOK___FUNCTION__:
6948 if (!gnu_ext)
6949 goto tok_identifier;
6950 /* fall thru */
6951 case TOK___FUNC__:
6953 void *ptr;
6954 int len;
6955 /* special function name identifier */
6956 len = strlen(funcname) + 1;
6957 /* generate char[len] type */
6958 type.t = VT_BYTE;
6959 mk_pointer(&type);
6960 type.t |= VT_ARRAY;
6961 type.ref->c = len;
6962 vpush_ref(&type, data_section, data_section->data_offset, len);
6963 ptr = section_ptr_add(data_section, len);
6964 memcpy(ptr, funcname, len);
6965 next();
6967 break;
6968 case TOK_LSTR:
6969 t = VT_INT;
6970 goto str_init;
6971 case TOK_STR:
6972 /* string parsing */
6973 t = VT_BYTE;
6974 str_init:
6975 if (tcc_state->warn_write_strings)
6976 t |= VT_CONSTANT;
6977 type.t = t;
6978 mk_pointer(&type);
6979 type.t |= VT_ARRAY;
6980 memset(&ad, 0, sizeof(AttributeDef));
6981 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6982 break;
6983 case '(':
6984 next();
6985 /* cast ? */
6986 if (parse_btype(&type, &ad)) {
6987 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6988 skip(')');
6989 /* check ISOC99 compound literal */
6990 if (tok == '{') {
6991 /* data is allocated locally by default */
6992 if (global_expr)
6993 r = VT_CONST;
6994 else
6995 r = VT_LOCAL;
6996 /* all except arrays are lvalues */
6997 if (!(type.t & VT_ARRAY))
6998 r |= lvalue_type(type.t);
6999 memset(&ad, 0, sizeof(AttributeDef));
7000 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7001 } else {
7002 unary();
7003 gen_cast(&type);
7005 } else if (tok == '{') {
7006 /* save all registers */
7007 save_regs(0);
7008 /* statement expression : we do not accept break/continue
7009 inside as GCC does */
7010 block(NULL, NULL, NULL, NULL, 0, 1);
7011 skip(')');
7012 } else {
7013 gexpr();
7014 skip(')');
7016 break;
7017 case '*':
7018 next();
7019 unary();
7020 indir();
7021 break;
7022 case '&':
7023 next();
7024 unary();
7025 /* functions names must be treated as function pointers,
7026 except for unary '&' and sizeof. Since we consider that
7027 functions are not lvalues, we only have to handle it
7028 there and in function calls. */
7029 /* arrays can also be used although they are not lvalues */
7030 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7031 !(vtop->type.t & VT_ARRAY))
7032 test_lvalue();
7033 mk_pointer(&vtop->type);
7034 gaddrof();
7035 break;
7036 case '!':
7037 next();
7038 unary();
7039 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7040 vtop->c.i = !vtop->c.i;
7041 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7042 vtop->c.i = vtop->c.i ^ 1;
7043 else
7044 vseti(VT_JMP, gtst(1, 0));
7045 break;
7046 case '~':
7047 next();
7048 unary();
7049 vpushi(-1);
7050 gen_op('^');
7051 break;
7052 case '+':
7053 next();
7054 /* in order to force cast, we add zero */
7055 unary();
7056 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7057 error("pointer not accepted for unary plus");
7058 vpushi(0);
7059 gen_op('+');
7060 break;
7061 case TOK_SIZEOF:
7062 case TOK_ALIGNOF1:
7063 case TOK_ALIGNOF2:
7064 t = tok;
7065 next();
7066 if (tok == '(') {
7067 parse_expr_type(&type);
7068 } else {
7069 unary_type(&type);
7071 size = type_size(&type, &align);
7072 if (t == TOK_SIZEOF) {
7073 if (size < 0)
7074 error("sizeof applied to an incomplete type");
7075 vpushi(size);
7076 } else {
7077 vpushi(align);
7079 break;
7081 case TOK_builtin_types_compatible_p:
7083 CType type1, type2;
7084 next();
7085 skip('(');
7086 parse_type(&type1);
7087 skip(',');
7088 parse_type(&type2);
7089 skip(')');
7090 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7091 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7092 vpushi(is_compatible_types(&type1, &type2));
7094 break;
7095 case TOK_builtin_constant_p:
7097 int saved_nocode_wanted, res;
7098 next();
7099 skip('(');
7100 saved_nocode_wanted = nocode_wanted;
7101 nocode_wanted = 1;
7102 gexpr();
7103 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7104 vpop();
7105 nocode_wanted = saved_nocode_wanted;
7106 skip(')');
7107 vpushi(res);
7109 break;
7110 case TOK_INC:
7111 case TOK_DEC:
7112 t = tok;
7113 next();
7114 unary();
7115 inc(0, t);
7116 break;
7117 case '-':
7118 next();
7119 vpushi(0);
7120 unary();
7121 gen_op('-');
7122 break;
7123 case TOK_LAND:
7124 if (!gnu_ext)
7125 goto tok_identifier;
7126 next();
7127 /* allow to take the address of a label */
7128 if (tok < TOK_UIDENT)
7129 expect("label identifier");
7130 s = label_find(tok);
7131 if (!s) {
7132 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7133 } else {
7134 if (s->r == LABEL_DECLARED)
7135 s->r = LABEL_FORWARD;
7137 if (!s->type.t) {
7138 s->type.t = VT_VOID;
7139 mk_pointer(&s->type);
7140 s->type.t |= VT_STATIC;
7142 vset(&s->type, VT_CONST | VT_SYM, 0);
7143 vtop->sym = s;
7144 next();
7145 break;
7146 default:
7147 tok_identifier:
7148 t = tok;
7149 next();
7150 if (t < TOK_UIDENT)
7151 expect("identifier");
7152 s = sym_find(t);
7153 if (!s) {
7154 if (tok != '(')
7155 error("'%s' undeclared", get_tok_str(t, NULL));
7156 /* for simple function calls, we tolerate undeclared
7157 external reference to int() function */
7158 if (tcc_state->warn_implicit_function_declaration)
7159 warning("implicit declaration of function '%s'",
7160 get_tok_str(t, NULL));
7161 s = external_global_sym(t, &func_old_type, 0);
7163 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7164 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7165 /* if referencing an inline function, then we generate a
7166 symbol to it if not already done. It will have the
7167 effect to generate code for it at the end of the
7168 compilation unit. Inline function as always
7169 generated in the text section. */
7170 if (!s->c)
7171 put_extern_sym(s, text_section, 0, 0);
7172 r = VT_SYM | VT_CONST;
7173 } else {
7174 r = s->r;
7176 vset(&s->type, r, s->c);
7177 /* if forward reference, we must point to s */
7178 if (vtop->r & VT_SYM) {
7179 vtop->sym = s;
7180 vtop->c.ul = 0;
7182 break;
7185 /* post operations */
7186 while (1) {
7187 if (tok == TOK_INC || tok == TOK_DEC) {
7188 inc(1, tok);
7189 next();
7190 } else if (tok == '.' || tok == TOK_ARROW) {
7191 /* field */
7192 if (tok == TOK_ARROW)
7193 indir();
7194 test_lvalue();
7195 gaddrof();
7196 next();
7197 /* expect pointer on structure */
7198 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7199 expect("struct or union");
7200 s = vtop->type.ref;
7201 /* find field */
7202 tok |= SYM_FIELD;
7203 while ((s = s->next) != NULL) {
7204 if (s->v == tok)
7205 break;
7207 if (!s)
7208 error("field not found");
7209 /* add field offset to pointer */
7210 vtop->type = char_pointer_type; /* change type to 'char *' */
7211 vpushi(s->c);
7212 gen_op('+');
7213 /* change type to field type, and set to lvalue */
7214 vtop->type = s->type;
7215 /* an array is never an lvalue */
7216 if (!(vtop->type.t & VT_ARRAY)) {
7217 vtop->r |= lvalue_type(vtop->type.t);
7218 /* if bound checking, the referenced pointer must be checked */
7219 if (do_bounds_check)
7220 vtop->r |= VT_MUSTBOUND;
7222 next();
7223 } else if (tok == '[') {
7224 next();
7225 gexpr();
7226 gen_op('+');
7227 indir();
7228 skip(']');
7229 } else if (tok == '(') {
7230 SValue ret;
7231 Sym *sa;
7232 int nb_args;
7234 /* function call */
7235 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7236 /* pointer test (no array accepted) */
7237 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7238 vtop->type = *pointed_type(&vtop->type);
7239 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7240 goto error_func;
7241 } else {
7242 error_func:
7243 expect("function pointer");
7245 } else {
7246 vtop->r &= ~VT_LVAL; /* no lvalue */
7248 /* get return type */
7249 s = vtop->type.ref;
7250 next();
7251 sa = s->next; /* first parameter */
7252 nb_args = 0;
7253 /* compute first implicit argument if a structure is returned */
7254 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7255 /* get some space for the returned structure */
7256 size = type_size(&s->type, &align);
7257 loc = (loc - size) & -align;
7258 ret.type = s->type;
7259 ret.r = VT_LOCAL | VT_LVAL;
7260 /* pass it as 'int' to avoid structure arg passing
7261 problems */
7262 vseti(VT_LOCAL, loc);
7263 ret.c = vtop->c;
7264 nb_args++;
7265 } else {
7266 ret.type = s->type;
7267 ret.r2 = VT_CONST;
7268 /* return in register */
7269 if (is_float(ret.type.t)) {
7270 ret.r = REG_FRET;
7271 } else {
7272 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7273 ret.r2 = REG_LRET;
7274 ret.r = REG_IRET;
7276 ret.c.i = 0;
7278 if (tok != ')') {
7279 for(;;) {
7280 expr_eq();
7281 gfunc_param_typed(s, sa);
7282 nb_args++;
7283 if (sa)
7284 sa = sa->next;
7285 if (tok == ')')
7286 break;
7287 skip(',');
7290 if (sa)
7291 error("too few arguments to function");
7292 skip(')');
7293 if (!nocode_wanted) {
7294 gfunc_call(nb_args);
7295 } else {
7296 vtop -= (nb_args + 1);
7298 /* return value */
7299 vsetc(&ret.type, ret.r, &ret.c);
7300 vtop->r2 = ret.r2;
7301 } else {
7302 break;
7307 static void uneq(void)
7309 int t;
7311 unary();
7312 if (tok == '=' ||
7313 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7314 tok == TOK_A_XOR || tok == TOK_A_OR ||
7315 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7316 test_lvalue();
7317 t = tok;
7318 next();
7319 if (t == '=') {
7320 expr_eq();
7321 } else {
7322 vdup();
7323 expr_eq();
7324 gen_op(t & 0x7f);
7326 vstore();
7330 static void expr_prod(void)
7332 int t;
7334 uneq();
7335 while (tok == '*' || tok == '/' || tok == '%') {
7336 t = tok;
7337 next();
7338 uneq();
7339 gen_op(t);
7343 static void expr_sum(void)
7345 int t;
7347 expr_prod();
7348 while (tok == '+' || tok == '-') {
7349 t = tok;
7350 next();
7351 expr_prod();
7352 gen_op(t);
7356 static void expr_shift(void)
7358 int t;
7360 expr_sum();
7361 while (tok == TOK_SHL || tok == TOK_SAR) {
7362 t = tok;
7363 next();
7364 expr_sum();
7365 gen_op(t);
7369 static void expr_cmp(void)
7371 int t;
7373 expr_shift();
7374 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7375 tok == TOK_ULT || tok == TOK_UGE) {
7376 t = tok;
7377 next();
7378 expr_shift();
7379 gen_op(t);
7383 static void expr_cmpeq(void)
7385 int t;
7387 expr_cmp();
7388 while (tok == TOK_EQ || tok == TOK_NE) {
7389 t = tok;
7390 next();
7391 expr_cmp();
7392 gen_op(t);
7396 static void expr_and(void)
7398 expr_cmpeq();
7399 while (tok == '&') {
7400 next();
7401 expr_cmpeq();
7402 gen_op('&');
7406 static void expr_xor(void)
7408 expr_and();
7409 while (tok == '^') {
7410 next();
7411 expr_and();
7412 gen_op('^');
7416 static void expr_or(void)
7418 expr_xor();
7419 while (tok == '|') {
7420 next();
7421 expr_xor();
7422 gen_op('|');
7426 /* XXX: fix this mess */
7427 static void expr_land_const(void)
7429 expr_or();
7430 while (tok == TOK_LAND) {
7431 next();
7432 expr_or();
7433 gen_op(TOK_LAND);
7437 /* XXX: fix this mess */
7438 static void expr_lor_const(void)
7440 expr_land_const();
7441 while (tok == TOK_LOR) {
7442 next();
7443 expr_land_const();
7444 gen_op(TOK_LOR);
7448 /* only used if non constant */
7449 static void expr_land(void)
7451 int t;
7453 expr_or();
7454 if (tok == TOK_LAND) {
7455 t = 0;
7456 for(;;) {
7457 t = gtst(1, t);
7458 if (tok != TOK_LAND) {
7459 vseti(VT_JMPI, t);
7460 break;
7462 next();
7463 expr_or();
7468 static void expr_lor(void)
7470 int t;
7472 expr_land();
7473 if (tok == TOK_LOR) {
7474 t = 0;
7475 for(;;) {
7476 t = gtst(0, t);
7477 if (tok != TOK_LOR) {
7478 vseti(VT_JMP, t);
7479 break;
7481 next();
7482 expr_land();
7487 /* XXX: better constant handling */
7488 static void expr_eq(void)
7490 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7491 SValue sv;
7492 CType type, type1, type2;
7494 if (const_wanted) {
7495 int c1, c;
7496 expr_lor_const();
7497 if (tok == '?') {
7498 c = vtop->c.i;
7499 vpop();
7500 next();
7501 if (tok == ':' && gnu_ext) {
7502 c1 = c;
7503 } else {
7504 gexpr();
7505 c1 = vtop->c.i;
7506 vpop();
7508 skip(':');
7509 expr_eq();
7510 if (c)
7511 vtop->c.i = c1;
7513 } else {
7514 expr_lor();
7515 if (tok == '?') {
7516 next();
7517 if (vtop != vstack) {
7518 /* needed to avoid having different registers saved in
7519 each branch */
7520 if (is_float(vtop->type.t))
7521 rc = RC_FLOAT;
7522 else
7523 rc = RC_INT;
7524 gv(rc);
7525 save_regs(1);
7527 if (tok == ':' && gnu_ext) {
7528 gv_dup();
7529 tt = gtst(1, 0);
7530 } else {
7531 tt = gtst(1, 0);
7532 gexpr();
7534 type1 = vtop->type;
7535 sv = *vtop; /* save value to handle it later */
7536 vtop--; /* no vpop so that FP stack is not flushed */
7537 skip(':');
7538 u = gjmp(0);
7539 gsym(tt);
7540 expr_eq();
7541 type2 = vtop->type;
7543 t1 = type1.t;
7544 bt1 = t1 & VT_BTYPE;
7545 t2 = type2.t;
7546 bt2 = t2 & VT_BTYPE;
7547 /* cast operands to correct type according to ISOC rules */
7548 if (is_float(bt1) || is_float(bt2)) {
7549 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7550 type.t = VT_LDOUBLE;
7551 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7552 type.t = VT_DOUBLE;
7553 } else {
7554 type.t = VT_FLOAT;
7556 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7557 /* cast to biggest op */
7558 type.t = VT_LLONG;
7559 /* convert to unsigned if it does not fit in a long long */
7560 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7561 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7562 type.t |= VT_UNSIGNED;
7563 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7564 /* XXX: test pointer compatibility */
7565 type = type1;
7566 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7567 /* XXX: test structure compatibility */
7568 type = type1;
7569 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7570 /* NOTE: as an extension, we accept void on only one side */
7571 type.t = VT_VOID;
7572 } else {
7573 /* integer operations */
7574 type.t = VT_INT;
7575 /* convert to unsigned if it does not fit in an integer */
7576 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7577 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7578 type.t |= VT_UNSIGNED;
7581 /* now we convert second operand */
7582 gen_cast(&type);
7583 rc = RC_INT;
7584 if (is_float(type.t)) {
7585 rc = RC_FLOAT;
7586 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7587 /* for long longs, we use fixed registers to avoid having
7588 to handle a complicated move */
7589 rc = RC_IRET;
7592 r2 = gv(rc);
7593 /* this is horrible, but we must also convert first
7594 operand */
7595 tt = gjmp(0);
7596 gsym(u);
7597 /* put again first value and cast it */
7598 *vtop = sv;
7599 gen_cast(&type);
7600 r1 = gv(rc);
7601 move_reg(r2, r1);
7602 vtop->r = r2;
7603 gsym(tt);
7608 static void gexpr(void)
7610 while (1) {
7611 expr_eq();
7612 if (tok != ',')
7613 break;
7614 vpop();
7615 next();
7619 /* parse an expression and return its type without any side effect. */
7620 static void expr_type(CType *type)
7622 int saved_nocode_wanted;
7624 saved_nocode_wanted = nocode_wanted;
7625 nocode_wanted = 1;
7626 gexpr();
7627 *type = vtop->type;
7628 vpop();
7629 nocode_wanted = saved_nocode_wanted;
7632 /* parse a unary expression and return its type without any side
7633 effect. */
7634 static void unary_type(CType *type)
7636 int a;
7638 a = nocode_wanted;
7639 nocode_wanted = 1;
7640 unary();
7641 *type = vtop->type;
7642 vpop();
7643 nocode_wanted = a;
7646 /* parse a constant expression and return value in vtop. */
7647 static void expr_const1(void)
7649 int a;
7650 a = const_wanted;
7651 const_wanted = 1;
7652 expr_eq();
7653 const_wanted = a;
7656 /* parse an integer constant and return its value. */
7657 static int expr_const(void)
7659 int c;
7660 expr_const1();
7661 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7662 expect("constant expression");
7663 c = vtop->c.i;
7664 vpop();
7665 return c;
7668 /* return the label token if current token is a label, otherwise
7669 return zero */
7670 static int is_label(void)
7672 int last_tok;
7674 /* fast test first */
7675 if (tok < TOK_UIDENT)
7676 return 0;
7677 /* no need to save tokc because tok is an identifier */
7678 last_tok = tok;
7679 next();
7680 if (tok == ':') {
7681 next();
7682 return last_tok;
7683 } else {
7684 unget_tok(last_tok);
7685 return 0;
7689 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7690 int case_reg, int is_expr)
7692 int a, b, c, d;
7693 Sym *s;
7695 /* generate line number info */
7696 if (do_debug &&
7697 (last_line_num != file->line_num || last_ind != ind)) {
7698 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7699 last_ind = ind;
7700 last_line_num = file->line_num;
7703 if (is_expr) {
7704 /* default return value is (void) */
7705 vpushi(0);
7706 vtop->type.t = VT_VOID;
7709 if (tok == TOK_IF) {
7710 /* if test */
7711 next();
7712 skip('(');
7713 gexpr();
7714 skip(')');
7715 a = gtst(1, 0);
7716 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7717 c = tok;
7718 if (c == TOK_ELSE) {
7719 next();
7720 d = gjmp(0);
7721 gsym(a);
7722 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7723 gsym(d); /* patch else jmp */
7724 } else
7725 gsym(a);
7726 } else if (tok == TOK_WHILE) {
7727 next();
7728 d = ind;
7729 skip('(');
7730 gexpr();
7731 skip(')');
7732 a = gtst(1, 0);
7733 b = 0;
7734 block(&a, &b, case_sym, def_sym, case_reg, 0);
7735 gjmp_addr(d);
7736 gsym(a);
7737 gsym_addr(b, d);
7738 } else if (tok == '{') {
7739 Sym *llabel;
7741 next();
7742 /* record local declaration stack position */
7743 s = local_stack;
7744 llabel = local_label_stack;
7745 /* handle local labels declarations */
7746 if (tok == TOK_LABEL) {
7747 next();
7748 for(;;) {
7749 if (tok < TOK_UIDENT)
7750 expect("label identifier");
7751 label_push(&local_label_stack, tok, LABEL_DECLARED);
7752 next();
7753 if (tok == ',') {
7754 next();
7755 } else {
7756 skip(';');
7757 break;
7761 while (tok != '}') {
7762 decl(VT_LOCAL);
7763 if (tok != '}') {
7764 if (is_expr)
7765 vpop();
7766 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7769 /* pop locally defined labels */
7770 label_pop(&local_label_stack, llabel);
7771 /* pop locally defined symbols */
7772 sym_pop(&local_stack, s);
7773 next();
7774 } else if (tok == TOK_RETURN) {
7775 next();
7776 if (tok != ';') {
7777 gexpr();
7778 gen_assign_cast(&func_vt);
7779 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7780 CType type;
7781 /* if returning structure, must copy it to implicit
7782 first pointer arg location */
7783 type = func_vt;
7784 mk_pointer(&type);
7785 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7786 indir();
7787 vswap();
7788 /* copy structure value to pointer */
7789 vstore();
7790 } else if (is_float(func_vt.t)) {
7791 gv(RC_FRET);
7792 } else {
7793 gv(RC_IRET);
7795 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7797 skip(';');
7798 rsym = gjmp(rsym); /* jmp */
7799 } else if (tok == TOK_BREAK) {
7800 /* compute jump */
7801 if (!bsym)
7802 error("cannot break");
7803 *bsym = gjmp(*bsym);
7804 next();
7805 skip(';');
7806 } else if (tok == TOK_CONTINUE) {
7807 /* compute jump */
7808 if (!csym)
7809 error("cannot continue");
7810 *csym = gjmp(*csym);
7811 next();
7812 skip(';');
7813 } else if (tok == TOK_FOR) {
7814 int e;
7815 next();
7816 skip('(');
7817 if (tok != ';') {
7818 gexpr();
7819 vpop();
7821 skip(';');
7822 d = ind;
7823 c = ind;
7824 a = 0;
7825 b = 0;
7826 if (tok != ';') {
7827 gexpr();
7828 a = gtst(1, 0);
7830 skip(';');
7831 if (tok != ')') {
7832 e = gjmp(0);
7833 c = ind;
7834 gexpr();
7835 vpop();
7836 gjmp_addr(d);
7837 gsym(e);
7839 skip(')');
7840 block(&a, &b, case_sym, def_sym, case_reg, 0);
7841 gjmp_addr(c);
7842 gsym(a);
7843 gsym_addr(b, c);
7844 } else
7845 if (tok == TOK_DO) {
7846 next();
7847 a = 0;
7848 b = 0;
7849 d = ind;
7850 block(&a, &b, case_sym, def_sym, case_reg, 0);
7851 skip(TOK_WHILE);
7852 skip('(');
7853 gsym(b);
7854 gexpr();
7855 c = gtst(0, 0);
7856 gsym_addr(c, d);
7857 skip(')');
7858 gsym(a);
7859 skip(';');
7860 } else
7861 if (tok == TOK_SWITCH) {
7862 next();
7863 skip('(');
7864 gexpr();
7865 /* XXX: other types than integer */
7866 case_reg = gv(RC_INT);
7867 vpop();
7868 skip(')');
7869 a = 0;
7870 b = gjmp(0); /* jump to first case */
7871 c = 0;
7872 block(&a, csym, &b, &c, case_reg, 0);
7873 /* if no default, jmp after switch */
7874 if (c == 0)
7875 c = ind;
7876 /* default label */
7877 gsym_addr(b, c);
7878 /* break label */
7879 gsym(a);
7880 } else
7881 if (tok == TOK_CASE) {
7882 int v1, v2;
7883 if (!case_sym)
7884 expect("switch");
7885 next();
7886 v1 = expr_const();
7887 v2 = v1;
7888 if (gnu_ext && tok == TOK_DOTS) {
7889 next();
7890 v2 = expr_const();
7891 if (v2 < v1)
7892 warning("empty case range");
7894 /* since a case is like a label, we must skip it with a jmp */
7895 b = gjmp(0);
7896 gsym(*case_sym);
7897 vseti(case_reg, 0);
7898 vpushi(v1);
7899 if (v1 == v2) {
7900 gen_op(TOK_EQ);
7901 *case_sym = gtst(1, 0);
7902 } else {
7903 gen_op(TOK_GE);
7904 *case_sym = gtst(1, 0);
7905 vseti(case_reg, 0);
7906 vpushi(v2);
7907 gen_op(TOK_LE);
7908 *case_sym = gtst(1, *case_sym);
7910 gsym(b);
7911 skip(':');
7912 is_expr = 0;
7913 goto block_after_label;
7914 } else
7915 if (tok == TOK_DEFAULT) {
7916 next();
7917 skip(':');
7918 if (!def_sym)
7919 expect("switch");
7920 if (*def_sym)
7921 error("too many 'default'");
7922 *def_sym = ind;
7923 is_expr = 0;
7924 goto block_after_label;
7925 } else
7926 if (tok == TOK_GOTO) {
7927 next();
7928 if (tok == '*' && gnu_ext) {
7929 /* computed goto */
7930 next();
7931 gexpr();
7932 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7933 expect("pointer");
7934 ggoto();
7935 } else if (tok >= TOK_UIDENT) {
7936 s = label_find(tok);
7937 /* put forward definition if needed */
7938 if (!s) {
7939 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7940 } else {
7941 if (s->r == LABEL_DECLARED)
7942 s->r = LABEL_FORWARD;
7944 /* label already defined */
7945 if (s->r & LABEL_FORWARD)
7946 s->next = (void *)gjmp((long)s->next);
7947 else
7948 gjmp_addr((long)s->next);
7949 next();
7950 } else {
7951 expect("label identifier");
7953 skip(';');
7954 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7955 asm_instr();
7956 } else {
7957 b = is_label();
7958 if (b) {
7959 /* label case */
7960 s = label_find(b);
7961 if (s) {
7962 if (s->r == LABEL_DEFINED)
7963 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7964 gsym((long)s->next);
7965 s->r = LABEL_DEFINED;
7966 } else {
7967 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7969 s->next = (void *)ind;
7970 /* we accept this, but it is a mistake */
7971 block_after_label:
7972 if (tok == '}') {
7973 warning("deprecated use of label at end of compound statement");
7974 } else {
7975 if (is_expr)
7976 vpop();
7977 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7979 } else {
7980 /* expression case */
7981 if (tok != ';') {
7982 if (is_expr) {
7983 vpop();
7984 gexpr();
7985 } else {
7986 gexpr();
7987 vpop();
7990 skip(';');
7995 /* t is the array or struct type. c is the array or struct
7996 address. cur_index/cur_field is the pointer to the current
7997 value. 'size_only' is true if only size info is needed (only used
7998 in arrays) */
7999 static void decl_designator(CType *type, Section *sec, unsigned long c,
8000 int *cur_index, Sym **cur_field,
8001 int size_only)
8003 Sym *s, *f;
8004 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8005 CType type1;
8007 notfirst = 0;
8008 elem_size = 0;
8009 nb_elems = 1;
8010 if (gnu_ext && (l = is_label()) != 0)
8011 goto struct_field;
8012 while (tok == '[' || tok == '.') {
8013 if (tok == '[') {
8014 if (!(type->t & VT_ARRAY))
8015 expect("array type");
8016 s = type->ref;
8017 next();
8018 index = expr_const();
8019 if (index < 0 || (s->c >= 0 && index >= s->c))
8020 expect("invalid index");
8021 if (tok == TOK_DOTS && gnu_ext) {
8022 next();
8023 index_last = expr_const();
8024 if (index_last < 0 ||
8025 (s->c >= 0 && index_last >= s->c) ||
8026 index_last < index)
8027 expect("invalid index");
8028 } else {
8029 index_last = index;
8031 skip(']');
8032 if (!notfirst)
8033 *cur_index = index_last;
8034 type = pointed_type(type);
8035 elem_size = type_size(type, &align);
8036 c += index * elem_size;
8037 /* NOTE: we only support ranges for last designator */
8038 nb_elems = index_last - index + 1;
8039 if (nb_elems != 1) {
8040 notfirst = 1;
8041 break;
8043 } else {
8044 next();
8045 l = tok;
8046 next();
8047 struct_field:
8048 if ((type->t & VT_BTYPE) != VT_STRUCT)
8049 expect("struct/union type");
8050 s = type->ref;
8051 l |= SYM_FIELD;
8052 f = s->next;
8053 while (f) {
8054 if (f->v == l)
8055 break;
8056 f = f->next;
8058 if (!f)
8059 expect("field");
8060 if (!notfirst)
8061 *cur_field = f;
8062 /* XXX: fix this mess by using explicit storage field */
8063 type1 = f->type;
8064 type1.t |= (type->t & ~VT_TYPE);
8065 type = &type1;
8066 c += f->c;
8068 notfirst = 1;
8070 if (notfirst) {
8071 if (tok == '=') {
8072 next();
8073 } else {
8074 if (!gnu_ext)
8075 expect("=");
8077 } else {
8078 if (type->t & VT_ARRAY) {
8079 index = *cur_index;
8080 type = pointed_type(type);
8081 c += index * type_size(type, &align);
8082 } else {
8083 f = *cur_field;
8084 if (!f)
8085 error("too many field init");
8086 /* XXX: fix this mess by using explicit storage field */
8087 type1 = f->type;
8088 type1.t |= (type->t & ~VT_TYPE);
8089 type = &type1;
8090 c += f->c;
8093 decl_initializer(type, sec, c, 0, size_only);
8095 /* XXX: make it more general */
8096 if (!size_only && nb_elems > 1) {
8097 unsigned long c_end;
8098 uint8_t *src, *dst;
8099 int i;
8101 if (!sec)
8102 error("range init not supported yet for dynamic storage");
8103 c_end = c + nb_elems * elem_size;
8104 if (c_end > sec->data_allocated)
8105 section_realloc(sec, c_end);
8106 src = sec->data + c;
8107 dst = src;
8108 for(i = 1; i < nb_elems; i++) {
8109 dst += elem_size;
8110 memcpy(dst, src, elem_size);
8115 #define EXPR_VAL 0
8116 #define EXPR_CONST 1
8117 #define EXPR_ANY 2
8119 /* store a value or an expression directly in global data or in local array */
8120 static void init_putv(CType *type, Section *sec, unsigned long c,
8121 int v, int expr_type)
8123 int saved_global_expr, bt, bit_pos, bit_size;
8124 void *ptr;
8125 unsigned long long bit_mask;
8126 CType dtype;
8128 switch(expr_type) {
8129 case EXPR_VAL:
8130 vpushi(v);
8131 break;
8132 case EXPR_CONST:
8133 /* compound literals must be allocated globally in this case */
8134 saved_global_expr = global_expr;
8135 global_expr = 1;
8136 expr_const1();
8137 global_expr = saved_global_expr;
8138 /* NOTE: symbols are accepted */
8139 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8140 error("initializer element is not constant");
8141 break;
8142 case EXPR_ANY:
8143 expr_eq();
8144 break;
8147 dtype = *type;
8148 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8150 if (sec) {
8151 /* XXX: not portable */
8152 /* XXX: generate error if incorrect relocation */
8153 gen_assign_cast(&dtype);
8154 bt = type->t & VT_BTYPE;
8155 ptr = sec->data + c;
8156 /* XXX: make code faster ? */
8157 if (!(type->t & VT_BITFIELD)) {
8158 bit_pos = 0;
8159 bit_size = 32;
8160 bit_mask = -1LL;
8161 } else {
8162 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8163 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8164 bit_mask = (1LL << bit_size) - 1;
8166 if ((vtop->r & VT_SYM) &&
8167 (bt == VT_BYTE ||
8168 bt == VT_SHORT ||
8169 bt == VT_DOUBLE ||
8170 bt == VT_LDOUBLE ||
8171 bt == VT_LLONG ||
8172 (bt == VT_INT && bit_size != 32)))
8173 error("initializer element is not computable at load time");
8174 switch(bt) {
8175 case VT_BYTE:
8176 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8177 break;
8178 case VT_SHORT:
8179 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8180 break;
8181 case VT_DOUBLE:
8182 *(double *)ptr = vtop->c.d;
8183 break;
8184 case VT_LDOUBLE:
8185 *(long double *)ptr = vtop->c.ld;
8186 break;
8187 case VT_LLONG:
8188 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8189 break;
8190 default:
8191 if (vtop->r & VT_SYM) {
8192 greloc(sec, vtop->sym, c, R_DATA_32);
8194 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8195 break;
8197 vtop--;
8198 } else {
8199 vset(&dtype, VT_LOCAL, c);
8200 vswap();
8201 vstore();
8202 vpop();
8206 /* put zeros for variable based init */
8207 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8209 if (sec) {
8210 /* nothing to do because globals are already set to zero */
8211 } else {
8212 vpush_global_sym(&func_old_type, TOK_memset);
8213 vseti(VT_LOCAL, c);
8214 vpushi(0);
8215 vpushi(size);
8216 gfunc_call(3);
8220 /* 't' contains the type and storage info. 'c' is the offset of the
8221 object in section 'sec'. If 'sec' is NULL, it means stack based
8222 allocation. 'first' is true if array '{' must be read (multi
8223 dimension implicit array init handling). 'size_only' is true if
8224 size only evaluation is wanted (only for arrays). */
8225 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8226 int first, int size_only)
8228 int index, array_length, n, no_oblock, nb, parlevel, i;
8229 int size1, align1, expr_type;
8230 Sym *s, *f;
8231 CType *t1;
8233 if (type->t & VT_ARRAY) {
8234 s = type->ref;
8235 n = s->c;
8236 array_length = 0;
8237 t1 = pointed_type(type);
8238 size1 = type_size(t1, &align1);
8240 no_oblock = 1;
8241 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8242 tok == '{') {
8243 skip('{');
8244 no_oblock = 0;
8247 /* only parse strings here if correct type (otherwise: handle
8248 them as ((w)char *) expressions */
8249 if ((tok == TOK_LSTR &&
8250 (t1->t & VT_BTYPE) == VT_INT) ||
8251 (tok == TOK_STR &&
8252 (t1->t & VT_BTYPE) == VT_BYTE)) {
8253 while (tok == TOK_STR || tok == TOK_LSTR) {
8254 int cstr_len, ch;
8255 CString *cstr;
8257 cstr = tokc.cstr;
8258 /* compute maximum number of chars wanted */
8259 if (tok == TOK_STR)
8260 cstr_len = cstr->size;
8261 else
8262 cstr_len = cstr->size / sizeof(int);
8263 cstr_len--;
8264 nb = cstr_len;
8265 if (n >= 0 && nb > (n - array_length))
8266 nb = n - array_length;
8267 if (!size_only) {
8268 if (cstr_len > nb)
8269 warning("initializer-string for array is too long");
8270 /* in order to go faster for common case (char
8271 string in global variable, we handle it
8272 specifically */
8273 if (sec && tok == TOK_STR && size1 == 1) {
8274 memcpy(sec->data + c + array_length, cstr->data, nb);
8275 } else {
8276 for(i=0;i<nb;i++) {
8277 if (tok == TOK_STR)
8278 ch = ((unsigned char *)cstr->data)[i];
8279 else
8280 ch = ((int *)cstr->data)[i];
8281 init_putv(t1, sec, c + (array_length + i) * size1,
8282 ch, EXPR_VAL);
8286 array_length += nb;
8287 next();
8289 /* only add trailing zero if enough storage (no
8290 warning in this case since it is standard) */
8291 if (n < 0 || array_length < n) {
8292 if (!size_only) {
8293 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8295 array_length++;
8297 } else {
8298 index = 0;
8299 while (tok != '}') {
8300 decl_designator(type, sec, c, &index, NULL, size_only);
8301 if (n >= 0 && index >= n)
8302 error("index too large");
8303 /* must put zero in holes (note that doing it that way
8304 ensures that it even works with designators) */
8305 if (!size_only && array_length < index) {
8306 init_putz(t1, sec, c + array_length * size1,
8307 (index - array_length) * size1);
8309 index++;
8310 if (index > array_length)
8311 array_length = index;
8312 /* special test for multi dimensional arrays (may not
8313 be strictly correct if designators are used at the
8314 same time) */
8315 if (index >= n && no_oblock)
8316 break;
8317 if (tok == '}')
8318 break;
8319 skip(',');
8322 if (!no_oblock)
8323 skip('}');
8324 /* put zeros at the end */
8325 if (!size_only && n >= 0 && array_length < n) {
8326 init_putz(t1, sec, c + array_length * size1,
8327 (n - array_length) * size1);
8329 /* patch type size if needed */
8330 if (n < 0)
8331 s->c = array_length;
8332 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8333 (sec || !first || tok == '{')) {
8334 int par_count;
8336 /* NOTE: the previous test is a specific case for automatic
8337 struct/union init */
8338 /* XXX: union needs only one init */
8340 /* XXX: this test is incorrect for local initializers
8341 beginning with ( without {. It would be much more difficult
8342 to do it correctly (ideally, the expression parser should
8343 be used in all cases) */
8344 par_count = 0;
8345 if (tok == '(') {
8346 AttributeDef ad1;
8347 CType type1;
8348 next();
8349 while (tok == '(') {
8350 par_count++;
8351 next();
8353 if (!parse_btype(&type1, &ad1))
8354 expect("cast");
8355 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8356 #if 0
8357 if (!is_assignable_types(type, &type1))
8358 error("invalid type for cast");
8359 #endif
8360 skip(')');
8362 no_oblock = 1;
8363 if (first || tok == '{') {
8364 skip('{');
8365 no_oblock = 0;
8367 s = type->ref;
8368 f = s->next;
8369 array_length = 0;
8370 index = 0;
8371 n = s->c;
8372 while (tok != '}') {
8373 decl_designator(type, sec, c, NULL, &f, size_only);
8374 index = f->c;
8375 if (!size_only && array_length < index) {
8376 init_putz(type, sec, c + array_length,
8377 index - array_length);
8379 index = index + type_size(&f->type, &align1);
8380 if (index > array_length)
8381 array_length = index;
8382 f = f->next;
8383 if (no_oblock && f == NULL)
8384 break;
8385 if (tok == '}')
8386 break;
8387 skip(',');
8389 /* put zeros at the end */
8390 if (!size_only && array_length < n) {
8391 init_putz(type, sec, c + array_length,
8392 n - array_length);
8394 if (!no_oblock)
8395 skip('}');
8396 while (par_count) {
8397 skip(')');
8398 par_count--;
8400 } else if (tok == '{') {
8401 next();
8402 decl_initializer(type, sec, c, first, size_only);
8403 skip('}');
8404 } else if (size_only) {
8405 /* just skip expression */
8406 parlevel = 0;
8407 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8408 tok != -1) {
8409 if (tok == '(')
8410 parlevel++;
8411 else if (tok == ')')
8412 parlevel--;
8413 next();
8415 } else {
8416 /* currently, we always use constant expression for globals
8417 (may change for scripting case) */
8418 expr_type = EXPR_CONST;
8419 if (!sec)
8420 expr_type = EXPR_ANY;
8421 init_putv(type, sec, c, 0, expr_type);
8425 /* parse an initializer for type 't' if 'has_init' is non zero, and
8426 allocate space in local or global data space ('r' is either
8427 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8428 variable 'v' of scope 'scope' is declared before initializers are
8429 parsed. If 'v' is zero, then a reference to the new object is put
8430 in the value stack. If 'has_init' is 2, a special parsing is done
8431 to handle string constants. */
8432 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8433 int has_init, int v, int scope)
8435 int size, align, addr, data_offset;
8436 int level;
8437 ParseState saved_parse_state;
8438 TokenString init_str;
8439 Section *sec;
8441 size = type_size(type, &align);
8442 /* If unknown size, we must evaluate it before
8443 evaluating initializers because
8444 initializers can generate global data too
8445 (e.g. string pointers or ISOC99 compound
8446 literals). It also simplifies local
8447 initializers handling */
8448 tok_str_new(&init_str);
8449 if (size < 0) {
8450 if (!has_init)
8451 error("unknown type size");
8452 /* get all init string */
8453 if (has_init == 2) {
8454 /* only get strings */
8455 while (tok == TOK_STR || tok == TOK_LSTR) {
8456 tok_str_add_tok(&init_str);
8457 next();
8459 } else {
8460 level = 0;
8461 while (level > 0 || (tok != ',' && tok != ';')) {
8462 if (tok < 0)
8463 error("unexpected end of file in initializer");
8464 tok_str_add_tok(&init_str);
8465 if (tok == '{')
8466 level++;
8467 else if (tok == '}') {
8468 if (level == 0)
8469 break;
8470 level--;
8472 next();
8475 tok_str_add(&init_str, -1);
8476 tok_str_add(&init_str, 0);
8478 /* compute size */
8479 save_parse_state(&saved_parse_state);
8481 macro_ptr = init_str.str;
8482 next();
8483 decl_initializer(type, NULL, 0, 1, 1);
8484 /* prepare second initializer parsing */
8485 macro_ptr = init_str.str;
8486 next();
8488 /* if still unknown size, error */
8489 size = type_size(type, &align);
8490 if (size < 0)
8491 error("unknown type size");
8493 /* take into account specified alignment if bigger */
8494 if (ad->aligned) {
8495 if (ad->aligned > align)
8496 align = ad->aligned;
8497 } else if (ad->packed) {
8498 align = 1;
8500 if ((r & VT_VALMASK) == VT_LOCAL) {
8501 sec = NULL;
8502 if (do_bounds_check && (type->t & VT_ARRAY))
8503 loc--;
8504 loc = (loc - size) & -align;
8505 addr = loc;
8506 /* handles bounds */
8507 /* XXX: currently, since we do only one pass, we cannot track
8508 '&' operators, so we add only arrays */
8509 if (do_bounds_check && (type->t & VT_ARRAY)) {
8510 unsigned long *bounds_ptr;
8511 /* add padding between regions */
8512 loc--;
8513 /* then add local bound info */
8514 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8515 bounds_ptr[0] = addr;
8516 bounds_ptr[1] = size;
8518 if (v) {
8519 /* local variable */
8520 sym_push(v, type, r, addr);
8521 } else {
8522 /* push local reference */
8523 vset(type, r, addr);
8525 } else {
8526 Sym *sym;
8528 sym = NULL;
8529 if (v && scope == VT_CONST) {
8530 /* see if the symbol was already defined */
8531 sym = sym_find(v);
8532 if (sym) {
8533 if (!is_compatible_types(&sym->type, type))
8534 error("incompatible types for redefinition of '%s'",
8535 get_tok_str(v, NULL));
8536 if (sym->type.t & VT_EXTERN) {
8537 /* if the variable is extern, it was not allocated */
8538 sym->type.t &= ~VT_EXTERN;
8539 /* set array size if it was ommited in extern
8540 declaration */
8541 if ((sym->type.t & VT_ARRAY) &&
8542 sym->type.ref->c < 0 &&
8543 type->ref->c >= 0)
8544 sym->type.ref->c = type->ref->c;
8545 } else {
8546 /* we accept several definitions of the same
8547 global variable. this is tricky, because we
8548 must play with the SHN_COMMON type of the symbol */
8549 /* XXX: should check if the variable was already
8550 initialized. It is incorrect to initialized it
8551 twice */
8552 /* no init data, we won't add more to the symbol */
8553 if (!has_init)
8554 goto no_alloc;
8559 /* allocate symbol in corresponding section */
8560 sec = ad->section;
8561 if (!sec) {
8562 if (has_init)
8563 sec = data_section;
8564 else if (tcc_state->nocommon)
8565 sec = bss_section;
8567 if (sec) {
8568 data_offset = sec->data_offset;
8569 data_offset = (data_offset + align - 1) & -align;
8570 addr = data_offset;
8571 /* very important to increment global pointer at this time
8572 because initializers themselves can create new initializers */
8573 data_offset += size;
8574 /* add padding if bound check */
8575 if (do_bounds_check)
8576 data_offset++;
8577 sec->data_offset = data_offset;
8578 /* allocate section space to put the data */
8579 if (sec->sh_type != SHT_NOBITS &&
8580 data_offset > sec->data_allocated)
8581 section_realloc(sec, data_offset);
8582 /* align section if needed */
8583 if (align > sec->sh_addralign)
8584 sec->sh_addralign = align;
8585 } else {
8586 addr = 0; /* avoid warning */
8589 if (v) {
8590 if (scope == VT_CONST) {
8591 if (!sym)
8592 goto do_def;
8593 } else {
8594 do_def:
8595 sym = sym_push(v, type, r | VT_SYM, 0);
8597 /* update symbol definition */
8598 if (sec) {
8599 put_extern_sym(sym, sec, addr, size);
8600 } else {
8601 Elf32_Sym *esym;
8602 /* put a common area */
8603 put_extern_sym(sym, NULL, align, size);
8604 /* XXX: find a nicer way */
8605 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8606 esym->st_shndx = SHN_COMMON;
8608 } else {
8609 CValue cval;
8611 /* push global reference */
8612 sym = get_sym_ref(type, sec, addr, size);
8613 cval.ul = 0;
8614 vsetc(type, VT_CONST | VT_SYM, &cval);
8615 vtop->sym = sym;
8618 /* handles bounds now because the symbol must be defined
8619 before for the relocation */
8620 if (do_bounds_check) {
8621 unsigned long *bounds_ptr;
8623 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8624 /* then add global bound info */
8625 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8626 bounds_ptr[0] = 0; /* relocated */
8627 bounds_ptr[1] = size;
8630 if (has_init) {
8631 decl_initializer(type, sec, addr, 1, 0);
8632 /* restore parse state if needed */
8633 if (init_str.str) {
8634 tok_str_free(init_str.str);
8635 restore_parse_state(&saved_parse_state);
8638 no_alloc: ;
8641 void put_func_debug(Sym *sym)
8643 char buf[512];
8645 /* stabs info */
8646 /* XXX: we put here a dummy type */
8647 snprintf(buf, sizeof(buf), "%s:%c1",
8648 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8649 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8650 cur_text_section, sym->c);
8651 last_ind = 0;
8652 last_line_num = 0;
8655 /* parse an old style function declaration list */
8656 /* XXX: check multiple parameter */
8657 static void func_decl_list(Sym *func_sym)
8659 AttributeDef ad;
8660 int v;
8661 Sym *s;
8662 CType btype, type;
8664 /* parse each declaration */
8665 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8666 if (!parse_btype(&btype, &ad))
8667 expect("declaration list");
8668 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8669 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8670 tok == ';') {
8671 /* we accept no variable after */
8672 } else {
8673 for(;;) {
8674 type = btype;
8675 type_decl(&type, &ad, &v, TYPE_DIRECT);
8676 /* find parameter in function parameter list */
8677 s = func_sym->next;
8678 while (s != NULL) {
8679 if ((s->v & ~SYM_FIELD) == v)
8680 goto found;
8681 s = s->next;
8683 error("declaration for parameter '%s' but no such parameter",
8684 get_tok_str(v, NULL));
8685 found:
8686 /* check that no storage specifier except 'register' was given */
8687 if (type.t & VT_STORAGE)
8688 error("storage class specified for '%s'", get_tok_str(v, NULL));
8689 convert_parameter_type(&type);
8690 /* we can add the type (NOTE: it could be local to the function) */
8691 s->type = type;
8692 /* accept other parameters */
8693 if (tok == ',')
8694 next();
8695 else
8696 break;
8699 skip(';');
8703 /* parse a function defined by symbol 'sym' and generate its code in
8704 'cur_text_section' */
8705 static void gen_function(Sym *sym)
8707 ind = cur_text_section->data_offset;
8708 /* NOTE: we patch the symbol size later */
8709 put_extern_sym(sym, cur_text_section, ind, 0);
8710 funcname = get_tok_str(sym->v, NULL);
8711 func_ind = ind;
8712 /* put debug symbol */
8713 if (do_debug)
8714 put_func_debug(sym);
8715 /* push a dummy symbol to enable local sym storage */
8716 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8717 gfunc_prolog(&sym->type);
8718 rsym = 0;
8719 block(NULL, NULL, NULL, NULL, 0, 0);
8720 gsym(rsym);
8721 gfunc_epilog();
8722 cur_text_section->data_offset = ind;
8723 label_pop(&global_label_stack, NULL);
8724 sym_pop(&local_stack, NULL); /* reset local stack */
8725 /* end of function */
8726 /* patch symbol size */
8727 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8728 ind - func_ind;
8729 if (do_debug) {
8730 put_stabn(N_FUN, 0, 0, ind - func_ind);
8732 funcname = ""; /* for safety */
8733 func_vt.t = VT_VOID; /* for safety */
8734 ind = 0; /* for safety */
8737 static void gen_inline_functions(void)
8739 Sym *sym;
8740 CType *type;
8741 int *str, inline_generated;
8743 /* iterate while inline function are referenced */
8744 for(;;) {
8745 inline_generated = 0;
8746 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8747 type = &sym->type;
8748 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8749 (type->t & (VT_STATIC | VT_INLINE)) ==
8750 (VT_STATIC | VT_INLINE) &&
8751 sym->c != 0) {
8752 /* the function was used: generate its code and
8753 convert it to a normal function */
8754 str = (int *)sym->r;
8755 sym->r = VT_SYM | VT_CONST;
8756 type->t &= ~VT_INLINE;
8758 macro_ptr = str;
8759 next();
8760 cur_text_section = text_section;
8761 gen_function(sym);
8762 macro_ptr = NULL; /* fail safe */
8764 tok_str_free(str);
8765 inline_generated = 1;
8768 if (!inline_generated)
8769 break;
8772 /* free all remaining inline function tokens */
8773 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8774 type = &sym->type;
8775 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8776 (type->t & (VT_STATIC | VT_INLINE)) ==
8777 (VT_STATIC | VT_INLINE)) {
8778 str = (int *)sym->r;
8779 tok_str_free(str);
8780 sym->r = 0; /* fail safe */
8785 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8786 static void decl(int l)
8788 int v, has_init, r;
8789 CType type, btype;
8790 Sym *sym;
8791 AttributeDef ad;
8793 while (1) {
8794 if (!parse_btype(&btype, &ad)) {
8795 /* skip redundant ';' */
8796 /* XXX: find more elegant solution */
8797 if (tok == ';') {
8798 next();
8799 continue;
8801 if (l == VT_CONST &&
8802 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
8803 /* global asm block */
8804 asm_global_instr();
8805 continue;
8807 /* special test for old K&R protos without explicit int
8808 type. Only accepted when defining global data */
8809 if (l == VT_LOCAL || tok < TOK_DEFINE)
8810 break;
8811 btype.t = VT_INT;
8813 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8814 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8815 tok == ';') {
8816 /* we accept no variable after */
8817 next();
8818 continue;
8820 while (1) { /* iterate thru each declaration */
8821 type = btype;
8822 type_decl(&type, &ad, &v, TYPE_DIRECT);
8823 #if 0
8825 char buf[500];
8826 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8827 printf("type = '%s'\n", buf);
8829 #endif
8830 if ((type.t & VT_BTYPE) == VT_FUNC) {
8831 /* if old style function prototype, we accept a
8832 declaration list */
8833 sym = type.ref;
8834 if (sym->c == FUNC_OLD)
8835 func_decl_list(sym);
8838 if (tok == '{') {
8839 if (l == VT_LOCAL)
8840 error("cannot use local functions");
8841 if (!(type.t & VT_FUNC))
8842 expect("function definition");
8844 /* reject abstract declarators in function definition */
8845 sym = type.ref;
8846 while ((sym = sym->next) != NULL)
8847 if (!(sym->v & ~SYM_FIELD))
8848 expect("identifier");
8850 /* XXX: cannot do better now: convert extern line to static inline */
8851 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8852 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8854 sym = sym_find(v);
8855 if (sym) {
8856 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
8857 goto func_error1;
8858 /* specific case: if not func_call defined, we put
8859 the one of the prototype */
8860 /* XXX: should have default value */
8861 if (sym->type.ref->r != FUNC_CDECL &&
8862 type.ref->r == FUNC_CDECL)
8863 type.ref->r = sym->type.ref->r;
8864 if (!is_compatible_types(&sym->type, &type)) {
8865 func_error1:
8866 error("incompatible types for redefinition of '%s'",
8867 get_tok_str(v, NULL));
8869 /* if symbol is already defined, then put complete type */
8870 sym->type = type;
8871 } else {
8872 /* put function symbol */
8873 sym = global_identifier_push(v, type.t, 0);
8874 sym->type.ref = type.ref;
8877 /* static inline functions are just recorded as a kind
8878 of macro. Their code will be emitted at the end of
8879 the compilation unit only if they are used */
8880 if ((type.t & (VT_INLINE | VT_STATIC)) ==
8881 (VT_INLINE | VT_STATIC)) {
8882 TokenString func_str;
8883 int block_level;
8885 tok_str_new(&func_str);
8887 block_level = 0;
8888 for(;;) {
8889 int t;
8890 if (tok == TOK_EOF)
8891 error("unexpected end of file");
8892 tok_str_add_tok(&func_str);
8893 t = tok;
8894 next();
8895 if (t == '{') {
8896 block_level++;
8897 } else if (t == '}') {
8898 block_level--;
8899 if (block_level == 0)
8900 break;
8903 tok_str_add(&func_str, -1);
8904 tok_str_add(&func_str, 0);
8905 sym->r = (int)func_str.str;
8906 } else {
8907 /* compute text section */
8908 cur_text_section = ad.section;
8909 if (!cur_text_section)
8910 cur_text_section = text_section;
8911 sym->r = VT_SYM | VT_CONST;
8912 gen_function(sym);
8914 break;
8915 } else {
8916 if (btype.t & VT_TYPEDEF) {
8917 /* save typedefed type */
8918 /* XXX: test storage specifiers ? */
8919 sym = sym_push(v, &type, 0, 0);
8920 sym->type.t |= VT_TYPEDEF;
8921 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8922 /* external function definition */
8923 /* specific case for func_call attribute */
8924 if (ad.func_call)
8925 type.ref->r = ad.func_call;
8926 external_sym(v, &type, 0);
8927 } else {
8928 /* not lvalue if array */
8929 r = 0;
8930 if (!(type.t & VT_ARRAY))
8931 r |= lvalue_type(type.t);
8932 has_init = (tok == '=');
8933 if ((btype.t & VT_EXTERN) ||
8934 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8935 !has_init && l == VT_CONST && type.ref->c < 0)) {
8936 /* external variable */
8937 /* NOTE: as GCC, uninitialized global static
8938 arrays of null size are considered as
8939 extern */
8940 external_sym(v, &type, r);
8941 } else {
8942 if (type.t & VT_STATIC)
8943 r |= VT_CONST;
8944 else
8945 r |= l;
8946 if (has_init)
8947 next();
8948 decl_initializer_alloc(&type, &ad, r,
8949 has_init, v, l);
8952 if (tok != ',') {
8953 skip(';');
8954 break;
8956 next();
8962 /* better than nothing, but needs extension to handle '-E' option
8963 correctly too */
8964 static void preprocess_init(TCCState *s1)
8966 s1->include_stack_ptr = s1->include_stack;
8967 /* XXX: move that before to avoid having to initialize
8968 file->ifdef_stack_ptr ? */
8969 s1->ifdef_stack_ptr = s1->ifdef_stack;
8970 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8972 /* XXX: not ANSI compliant: bound checking says error */
8973 vtop = vstack - 1;
8976 /* compile the C file opened in 'file'. Return non zero if errors. */
8977 static int tcc_compile(TCCState *s1)
8979 Sym *define_start;
8980 char buf[512];
8981 volatile int section_sym;
8983 #ifdef INC_DEBUG
8984 printf("%s: **** new file\n", file->filename);
8985 #endif
8986 preprocess_init(s1);
8988 funcname = "";
8989 anon_sym = SYM_FIRST_ANOM;
8991 /* file info: full path + filename */
8992 section_sym = 0; /* avoid warning */
8993 if (do_debug) {
8994 section_sym = put_elf_sym(symtab_section, 0, 0,
8995 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8996 text_section->sh_num, NULL);
8997 getcwd(buf, sizeof(buf));
8998 pstrcat(buf, sizeof(buf), "/");
8999 put_stabs_r(buf, N_SO, 0, 0,
9000 text_section->data_offset, text_section, section_sym);
9001 put_stabs_r(file->filename, N_SO, 0, 0,
9002 text_section->data_offset, text_section, section_sym);
9004 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9005 symbols can be safely used */
9006 put_elf_sym(symtab_section, 0, 0,
9007 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9008 SHN_ABS, file->filename);
9010 /* define some often used types */
9011 int_type.t = VT_INT;
9013 char_pointer_type.t = VT_BYTE;
9014 mk_pointer(&char_pointer_type);
9016 func_old_type.t = VT_FUNC;
9017 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9019 #if 0
9020 /* define 'void *alloca(unsigned int)' builtin function */
9022 Sym *s1;
9024 p = anon_sym++;
9025 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9026 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9027 s1->next = NULL;
9028 sym->next = s1;
9029 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9031 #endif
9033 define_start = define_stack;
9035 if (setjmp(s1->error_jmp_buf) == 0) {
9036 s1->nb_errors = 0;
9037 s1->error_set_jmp_enabled = 1;
9039 ch = file->buf_ptr[0];
9040 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9041 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9042 next();
9043 decl(VT_CONST);
9044 if (tok != TOK_EOF)
9045 expect("declaration");
9047 /* end of translation unit info */
9048 if (do_debug) {
9049 put_stabs_r(NULL, N_SO, 0, 0,
9050 text_section->data_offset, text_section, section_sym);
9053 s1->error_set_jmp_enabled = 0;
9055 /* reset define stack, but leave -Dsymbols (may be incorrect if
9056 they are undefined) */
9057 free_defines(define_start);
9059 gen_inline_functions();
9061 sym_pop(&global_stack, NULL);
9063 return s1->nb_errors != 0 ? -1 : 0;
9066 #ifdef LIBTCC
9067 int tcc_compile_string(TCCState *s, const char *str)
9069 BufferedFile bf1, *bf = &bf1;
9070 int ret, len;
9071 char *buf;
9073 /* init file structure */
9074 bf->fd = -1;
9075 /* XXX: avoid copying */
9076 len = strlen(str);
9077 buf = tcc_malloc(len + 1);
9078 if (!buf)
9079 return -1;
9080 memcpy(buf, str, len);
9081 buf[len] = CH_EOB;
9082 bf->buf_ptr = buf;
9083 bf->buf_end = buf + len;
9084 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9085 bf->line_num = 1;
9086 file = bf;
9088 ret = tcc_compile(s);
9090 tcc_free(buf);
9092 /* currently, no need to close */
9093 return ret;
9095 #endif
9097 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9098 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9100 BufferedFile bf1, *bf = &bf1;
9102 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9103 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9104 /* default value */
9105 if (!value)
9106 value = "1";
9107 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9109 /* init file structure */
9110 bf->fd = -1;
9111 bf->buf_ptr = bf->buffer;
9112 bf->buf_end = bf->buffer + strlen(bf->buffer);
9113 *bf->buf_end = CH_EOB;
9114 bf->filename[0] = '\0';
9115 bf->line_num = 1;
9116 file = bf;
9118 s1->include_stack_ptr = s1->include_stack;
9120 /* parse with define parser */
9121 ch = file->buf_ptr[0];
9122 next_nomacro();
9123 parse_define();
9124 file = NULL;
9127 /* undefine a preprocessor symbol */
9128 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9130 TokenSym *ts;
9131 Sym *s;
9132 ts = tok_alloc(sym, strlen(sym));
9133 s = define_find(ts->tok);
9134 /* undefine symbol by putting an invalid name */
9135 if (s)
9136 define_undef(s);
9139 #ifdef CONFIG_TCC_ASM
9141 #ifdef TCC_TARGET_I386
9142 #include "i386-asm.c"
9143 #endif
9144 #include "tccasm.c"
9146 #else
9147 static void asm_instr(void)
9149 error("inline asm() not supported");
9151 static void asm_global_instr(void)
9153 error("inline asm() not supported");
9155 #endif
9157 #include "tccelf.c"
9159 #ifdef TCC_TARGET_COFF
9160 #include "tcccoff.c"
9161 #endif
9163 /* print the position in the source file of PC value 'pc' by reading
9164 the stabs debug information */
9165 static void rt_printline(unsigned long wanted_pc)
9167 Stab_Sym *sym, *sym_end;
9168 char func_name[128], last_func_name[128];
9169 unsigned long func_addr, last_pc, pc;
9170 const char *incl_files[INCLUDE_STACK_SIZE];
9171 int incl_index, len, last_line_num, i;
9172 const char *str, *p;
9174 fprintf(stderr, "0x%08lx:", wanted_pc);
9176 func_name[0] = '\0';
9177 func_addr = 0;
9178 incl_index = 0;
9179 last_func_name[0] = '\0';
9180 last_pc = 0xffffffff;
9181 last_line_num = 1;
9182 sym = (Stab_Sym *)stab_section->data + 1;
9183 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9184 while (sym < sym_end) {
9185 switch(sym->n_type) {
9186 /* function start or end */
9187 case N_FUN:
9188 if (sym->n_strx == 0) {
9189 /* we test if between last line and end of function */
9190 pc = sym->n_value + func_addr;
9191 if (wanted_pc >= last_pc && wanted_pc < pc)
9192 goto found;
9193 func_name[0] = '\0';
9194 func_addr = 0;
9195 } else {
9196 str = stabstr_section->data + sym->n_strx;
9197 p = strchr(str, ':');
9198 if (!p) {
9199 pstrcpy(func_name, sizeof(func_name), str);
9200 } else {
9201 len = p - str;
9202 if (len > sizeof(func_name) - 1)
9203 len = sizeof(func_name) - 1;
9204 memcpy(func_name, str, len);
9205 func_name[len] = '\0';
9207 func_addr = sym->n_value;
9209 break;
9210 /* line number info */
9211 case N_SLINE:
9212 pc = sym->n_value + func_addr;
9213 if (wanted_pc >= last_pc && wanted_pc < pc)
9214 goto found;
9215 last_pc = pc;
9216 last_line_num = sym->n_desc;
9217 /* XXX: slow! */
9218 strcpy(last_func_name, func_name);
9219 break;
9220 /* include files */
9221 case N_BINCL:
9222 str = stabstr_section->data + sym->n_strx;
9223 add_incl:
9224 if (incl_index < INCLUDE_STACK_SIZE) {
9225 incl_files[incl_index++] = str;
9227 break;
9228 case N_EINCL:
9229 if (incl_index > 1)
9230 incl_index--;
9231 break;
9232 case N_SO:
9233 if (sym->n_strx == 0) {
9234 incl_index = 0; /* end of translation unit */
9235 } else {
9236 str = stabstr_section->data + sym->n_strx;
9237 /* do not add path */
9238 len = strlen(str);
9239 if (len > 0 && str[len - 1] != '/')
9240 goto add_incl;
9242 break;
9244 sym++;
9247 /* second pass: we try symtab symbols (no line number info) */
9248 incl_index = 0;
9250 Elf32_Sym *sym, *sym_end;
9251 int type;
9253 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9254 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9255 sym < sym_end;
9256 sym++) {
9257 type = ELF32_ST_TYPE(sym->st_info);
9258 if (type == STT_FUNC) {
9259 if (wanted_pc >= sym->st_value &&
9260 wanted_pc < sym->st_value + sym->st_size) {
9261 pstrcpy(last_func_name, sizeof(last_func_name),
9262 strtab_section->data + sym->st_name);
9263 goto found;
9268 /* did not find any info: */
9269 fprintf(stderr, " ???\n");
9270 return;
9271 found:
9272 if (last_func_name[0] != '\0') {
9273 fprintf(stderr, " %s()", last_func_name);
9275 if (incl_index > 0) {
9276 fprintf(stderr, " (%s:%d",
9277 incl_files[incl_index - 1], last_line_num);
9278 for(i = incl_index - 2; i >= 0; i--)
9279 fprintf(stderr, ", included from %s", incl_files[i]);
9280 fprintf(stderr, ")");
9282 fprintf(stderr, "\n");
9285 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9287 #ifdef __i386__
9289 /* fix for glibc 2.1 */
9290 #ifndef REG_EIP
9291 #define REG_EIP EIP
9292 #define REG_EBP EBP
9293 #endif
9295 /* return the PC at frame level 'level'. Return non zero if not found */
9296 static int rt_get_caller_pc(unsigned long *paddr,
9297 ucontext_t *uc, int level)
9299 unsigned long fp;
9300 int i;
9302 if (level == 0) {
9303 #if defined(__FreeBSD__)
9304 *paddr = uc->uc_mcontext.mc_eip;
9305 #elif defined(__dietlibc__)
9306 *paddr = uc->uc_mcontext.eip;
9307 #else
9308 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9309 #endif
9310 return 0;
9311 } else {
9312 #if defined(__FreeBSD__)
9313 fp = uc->uc_mcontext.mc_ebp;
9314 #elif defined(__dietlibc__)
9315 fp = uc->uc_mcontext.ebp;
9316 #else
9317 fp = uc->uc_mcontext.gregs[REG_EBP];
9318 #endif
9319 for(i=1;i<level;i++) {
9320 /* XXX: check address validity with program info */
9321 if (fp <= 0x1000 || fp >= 0xc0000000)
9322 return -1;
9323 fp = ((unsigned long *)fp)[0];
9325 *paddr = ((unsigned long *)fp)[1];
9326 return 0;
9329 #else
9331 #warning add arch specific rt_get_caller_pc()
9333 static int rt_get_caller_pc(unsigned long *paddr,
9334 ucontext_t *uc, int level)
9336 return -1;
9338 #endif
9340 /* emit a run time error at position 'pc' */
9341 void rt_error(ucontext_t *uc, const char *fmt, ...)
9343 va_list ap;
9344 unsigned long pc;
9345 int i;
9347 va_start(ap, fmt);
9348 fprintf(stderr, "Runtime error: ");
9349 vfprintf(stderr, fmt, ap);
9350 fprintf(stderr, "\n");
9351 for(i=0;i<num_callers;i++) {
9352 if (rt_get_caller_pc(&pc, uc, i) < 0)
9353 break;
9354 if (i == 0)
9355 fprintf(stderr, "at ");
9356 else
9357 fprintf(stderr, "by ");
9358 rt_printline(pc);
9360 exit(255);
9361 va_end(ap);
9364 /* signal handler for fatal errors */
9365 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9367 ucontext_t *uc = puc;
9369 switch(signum) {
9370 case SIGFPE:
9371 switch(siginf->si_code) {
9372 case FPE_INTDIV:
9373 case FPE_FLTDIV:
9374 rt_error(uc, "division by zero");
9375 break;
9376 default:
9377 rt_error(uc, "floating point exception");
9378 break;
9380 break;
9381 case SIGBUS:
9382 case SIGSEGV:
9383 if (rt_bound_error_msg && *rt_bound_error_msg)
9384 rt_error(uc, *rt_bound_error_msg);
9385 else
9386 rt_error(uc, "dereferencing invalid pointer");
9387 break;
9388 case SIGILL:
9389 rt_error(uc, "illegal instruction");
9390 break;
9391 case SIGABRT:
9392 rt_error(uc, "abort() called");
9393 break;
9394 default:
9395 rt_error(uc, "caught signal %d", signum);
9396 break;
9398 exit(255);
9400 #endif
9402 /* do all relocations (needed before using tcc_get_symbol()) */
9403 int tcc_relocate(TCCState *s1)
9405 Section *s;
9406 int i;
9408 s1->nb_errors = 0;
9410 tcc_add_runtime(s1);
9412 build_got_entries(s1);
9414 relocate_common_syms();
9416 /* compute relocation address : section are relocated in place. We
9417 also alloc the bss space */
9418 for(i = 1; i < s1->nb_sections; i++) {
9419 s = s1->sections[i];
9420 if (s->sh_flags & SHF_ALLOC) {
9421 if (s->sh_type == SHT_NOBITS)
9422 s->data = tcc_mallocz(s->data_offset);
9423 s->sh_addr = (unsigned long)s->data;
9427 relocate_syms(s1, 1);
9429 if (s1->nb_errors != 0)
9430 return -1;
9432 /* relocate each section */
9433 for(i = 1; i < s1->nb_sections; i++) {
9434 s = s1->sections[i];
9435 if (s->reloc)
9436 relocate_section(s1, s);
9438 return 0;
9441 /* launch the compiled program with the given arguments */
9442 int tcc_run(TCCState *s1, int argc, char **argv)
9444 int (*prog_main)(int, char **);
9446 if (tcc_relocate(s1) < 0)
9447 return -1;
9449 prog_main = tcc_get_symbol_err(s1, "main");
9451 if (do_debug) {
9452 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9453 error("debug mode currently not available for Windows");
9454 #else
9455 struct sigaction sigact;
9456 /* install TCC signal handlers to print debug info on fatal
9457 runtime errors */
9458 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9459 sigact.sa_sigaction = sig_error;
9460 sigemptyset(&sigact.sa_mask);
9461 sigaction(SIGFPE, &sigact, NULL);
9462 sigaction(SIGILL, &sigact, NULL);
9463 sigaction(SIGSEGV, &sigact, NULL);
9464 sigaction(SIGBUS, &sigact, NULL);
9465 sigaction(SIGABRT, &sigact, NULL);
9466 #endif
9469 #ifdef CONFIG_TCC_BCHECK
9470 if (do_bounds_check) {
9471 void (*bound_init)(void);
9473 /* set error function */
9474 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9475 "__bound_error_msg");
9477 /* XXX: use .init section so that it also work in binary ? */
9478 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9479 bound_init();
9481 #endif
9482 return (*prog_main)(argc, argv);
9485 TCCState *tcc_new(void)
9487 const char *p, *r;
9488 TCCState *s;
9489 TokenSym *ts;
9490 int i, c;
9492 s = tcc_mallocz(sizeof(TCCState));
9493 if (!s)
9494 return NULL;
9495 tcc_state = s;
9496 s->output_type = TCC_OUTPUT_MEMORY;
9498 /* init isid table */
9499 for(i=0;i<256;i++)
9500 isidnum_table[i] = isid(i) || isnum(i);
9502 /* add all tokens */
9503 table_ident = NULL;
9504 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9506 tok_ident = TOK_IDENT;
9507 p = tcc_keywords;
9508 while (*p) {
9509 r = p;
9510 for(;;) {
9511 c = *r++;
9512 if (c == '\0')
9513 break;
9515 ts = tok_alloc(p, r - p - 1);
9516 p = r;
9519 /* we add dummy defines for some special macros to speed up tests
9520 and to have working defined() */
9521 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9522 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9523 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9524 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9526 /* standard defines */
9527 tcc_define_symbol(s, "__STDC__", NULL);
9528 #if defined(TCC_TARGET_I386)
9529 tcc_define_symbol(s, "__i386__", NULL);
9530 #endif
9531 #if defined(TCC_TARGET_ARM)
9532 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9533 tcc_define_symbol(s, "__arm_elf__", NULL);
9534 tcc_define_symbol(s, "__arm_elf", NULL);
9535 tcc_define_symbol(s, "arm_elf", NULL);
9536 tcc_define_symbol(s, "__arm__", NULL);
9537 tcc_define_symbol(s, "__arm", NULL);
9538 tcc_define_symbol(s, "arm", NULL);
9539 tcc_define_symbol(s, "__APCS_32__", NULL);
9540 #endif
9541 #if defined(linux)
9542 tcc_define_symbol(s, "__linux__", NULL);
9543 tcc_define_symbol(s, "linux", NULL);
9544 #endif
9545 /* tiny C specific defines */
9546 tcc_define_symbol(s, "__TINYC__", NULL);
9548 /* tiny C & gcc defines */
9549 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9550 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9551 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9553 /* default library paths */
9554 tcc_add_library_path(s, "/usr/local/lib");
9555 tcc_add_library_path(s, "/usr/lib");
9556 tcc_add_library_path(s, "/lib");
9558 /* no section zero */
9559 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9561 /* create standard sections */
9562 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9563 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9564 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9566 /* symbols are always generated for linking stage */
9567 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9568 ".strtab",
9569 ".hashtab", SHF_PRIVATE);
9570 strtab_section = symtab_section->link;
9572 /* private symbol table for dynamic symbols */
9573 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9574 ".dynstrtab",
9575 ".dynhashtab", SHF_PRIVATE);
9576 s->alacarte_link = 1;
9578 #ifdef CHAR_IS_UNSIGNED
9579 s->char_is_unsigned = 1;
9580 #endif
9581 return s;
9584 void tcc_delete(TCCState *s1)
9586 int i, n;
9588 /* free -D defines */
9589 free_defines(NULL);
9591 /* free tokens */
9592 n = tok_ident - TOK_IDENT;
9593 for(i = 0; i < n; i++)
9594 tcc_free(table_ident[i]);
9595 tcc_free(table_ident);
9597 /* free all sections */
9599 free_section(symtab_section->hash);
9601 free_section(s1->dynsymtab_section->hash);
9602 free_section(s1->dynsymtab_section->link);
9603 free_section(s1->dynsymtab_section);
9605 for(i = 1; i < s1->nb_sections; i++)
9606 free_section(s1->sections[i]);
9607 tcc_free(s1->sections);
9609 /* free loaded dlls array */
9610 for(i = 0; i < s1->nb_loaded_dlls; i++)
9611 tcc_free(s1->loaded_dlls[i]);
9612 tcc_free(s1->loaded_dlls);
9614 /* library paths */
9615 for(i = 0; i < s1->nb_library_paths; i++)
9616 tcc_free(s1->library_paths[i]);
9617 tcc_free(s1->library_paths);
9619 /* cached includes */
9620 for(i = 0; i < s1->nb_cached_includes; i++)
9621 tcc_free(s1->cached_includes[i]);
9622 tcc_free(s1->cached_includes);
9624 for(i = 0; i < s1->nb_include_paths; i++)
9625 tcc_free(s1->include_paths[i]);
9626 tcc_free(s1->include_paths);
9628 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9629 tcc_free(s1->sysinclude_paths[i]);
9630 tcc_free(s1->sysinclude_paths);
9632 tcc_free(s1);
9635 int tcc_add_include_path(TCCState *s1, const char *pathname)
9637 char *pathname1;
9639 pathname1 = tcc_strdup(pathname);
9640 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9641 return 0;
9644 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9646 char *pathname1;
9648 pathname1 = tcc_strdup(pathname);
9649 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9650 return 0;
9653 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9655 const char *ext, *filename1;
9656 Elf32_Ehdr ehdr;
9657 int fd, ret;
9658 BufferedFile *saved_file;
9660 /* find source file type with extension */
9661 filename1 = strrchr(filename, '/');
9662 if (filename1)
9663 filename1++;
9664 else
9665 filename1 = filename;
9666 ext = strrchr(filename1, '.');
9667 if (ext)
9668 ext++;
9670 /* open the file */
9671 saved_file = file;
9672 file = tcc_open(s1, filename);
9673 if (!file) {
9674 if (flags & AFF_PRINT_ERROR) {
9675 error_noabort("file '%s' not found", filename);
9677 ret = -1;
9678 goto fail1;
9681 if (!ext || !strcmp(ext, "c")) {
9682 /* C file assumed */
9683 ret = tcc_compile(s1);
9684 } else
9685 #ifdef CONFIG_TCC_ASM
9686 if (!strcmp(ext, "S")) {
9687 /* preprocessed assembler */
9688 ret = tcc_assemble(s1, 1);
9689 } else if (!strcmp(ext, "s")) {
9690 /* non preprocessed assembler */
9691 ret = tcc_assemble(s1, 0);
9692 } else
9693 #endif
9695 fd = file->fd;
9696 /* assume executable format: auto guess file type */
9697 ret = read(fd, &ehdr, sizeof(ehdr));
9698 lseek(fd, 0, SEEK_SET);
9699 if (ret <= 0) {
9700 error_noabort("could not read header");
9701 goto fail;
9702 } else if (ret != sizeof(ehdr)) {
9703 goto try_load_script;
9706 if (ehdr.e_ident[0] == ELFMAG0 &&
9707 ehdr.e_ident[1] == ELFMAG1 &&
9708 ehdr.e_ident[2] == ELFMAG2 &&
9709 ehdr.e_ident[3] == ELFMAG3) {
9710 file->line_num = 0; /* do not display line number if error */
9711 if (ehdr.e_type == ET_REL) {
9712 ret = tcc_load_object_file(s1, fd, 0);
9713 } else if (ehdr.e_type == ET_DYN) {
9714 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9715 void *h;
9716 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9717 if (h)
9718 ret = 0;
9719 else
9720 ret = -1;
9721 } else {
9722 ret = tcc_load_dll(s1, fd, filename,
9723 (flags & AFF_REFERENCED_DLL) != 0);
9725 } else {
9726 error_noabort("unrecognized ELF file");
9727 goto fail;
9729 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9730 file->line_num = 0; /* do not display line number if error */
9731 ret = tcc_load_archive(s1, fd);
9732 } else
9733 #ifdef TCC_TARGET_COFF
9734 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
9735 ret = tcc_load_coff(s1, fd);
9736 } else
9737 #endif
9739 /* as GNU ld, consider it is an ld script if not recognized */
9740 try_load_script:
9741 ret = tcc_load_ldscript(s1);
9742 if (ret < 0) {
9743 error_noabort("unrecognized file type");
9744 goto fail;
9748 the_end:
9749 tcc_close(file);
9750 fail1:
9751 file = saved_file;
9752 return ret;
9753 fail:
9754 ret = -1;
9755 goto the_end;
9758 int tcc_add_file(TCCState *s, const char *filename)
9760 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9763 int tcc_add_library_path(TCCState *s, const char *pathname)
9765 char *pathname1;
9767 pathname1 = tcc_strdup(pathname);
9768 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9769 return 0;
9772 /* find and load a dll. Return non zero if not found */
9773 /* XXX: add '-rpath' option support ? */
9774 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9776 char buf[1024];
9777 int i;
9779 for(i = 0; i < s->nb_library_paths; i++) {
9780 snprintf(buf, sizeof(buf), "%s/%s",
9781 s->library_paths[i], filename);
9782 if (tcc_add_file_internal(s, buf, flags) == 0)
9783 return 0;
9785 return -1;
9788 /* the library name is the same as the argument of the '-l' option */
9789 int tcc_add_library(TCCState *s, const char *libraryname)
9791 char buf[1024];
9792 int i;
9794 /* first we look for the dynamic library if not static linking */
9795 if (!s->static_link) {
9796 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9797 if (tcc_add_dll(s, buf, 0) == 0)
9798 return 0;
9801 /* then we look for the static library */
9802 for(i = 0; i < s->nb_library_paths; i++) {
9803 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9804 s->library_paths[i], libraryname);
9805 if (tcc_add_file_internal(s, buf, 0) == 0)
9806 return 0;
9808 return -1;
9811 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9813 add_elf_sym(symtab_section, val, 0,
9814 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9815 SHN_ABS, name);
9816 return 0;
9819 int tcc_set_output_type(TCCState *s, int output_type)
9821 char buf[1024];
9823 s->output_type = output_type;
9825 if (!s->nostdinc) {
9826 /* default include paths */
9827 /* XXX: reverse order needed if -isystem support */
9828 tcc_add_sysinclude_path(s, "/usr/local/include");
9829 tcc_add_sysinclude_path(s, "/usr/include");
9830 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9831 tcc_add_sysinclude_path(s, buf);
9834 /* if bound checking, then add corresponding sections */
9835 #ifdef CONFIG_TCC_BCHECK
9836 if (do_bounds_check) {
9837 /* define symbol */
9838 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9839 /* create bounds sections */
9840 bounds_section = new_section(s, ".bounds",
9841 SHT_PROGBITS, SHF_ALLOC);
9842 lbounds_section = new_section(s, ".lbounds",
9843 SHT_PROGBITS, SHF_ALLOC);
9845 #endif
9847 if (s->char_is_unsigned) {
9848 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
9851 /* add debug sections */
9852 if (do_debug) {
9853 /* stab symbols */
9854 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9855 stab_section->sh_entsize = sizeof(Stab_Sym);
9856 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9857 put_elf_str(stabstr_section, "");
9858 stab_section->link = stabstr_section;
9859 /* put first entry */
9860 put_stabs("", 0, 0, 0, 0);
9863 /* add libc crt1/crti objects */
9864 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9865 !s->nostdlib) {
9866 if (output_type != TCC_OUTPUT_DLL)
9867 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9868 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9870 return 0;
9873 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9874 #define FD_INVERT 0x0002 /* invert value before storing */
9876 typedef struct FlagDef {
9877 uint16_t offset;
9878 uint16_t flags;
9879 const char *name;
9880 } FlagDef;
9882 static const FlagDef warning_defs[] = {
9883 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9884 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9885 { offsetof(TCCState, warn_error), 0, "error" },
9886 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
9887 "implicit-function-declaration" },
9890 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
9891 const char *name, int value)
9893 int i;
9894 const FlagDef *p;
9895 const char *r;
9897 r = name;
9898 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
9899 r += 3;
9900 value = !value;
9902 for(i = 0, p = flags; i < nb_flags; i++, p++) {
9903 if (!strcmp(r, p->name))
9904 goto found;
9906 return -1;
9907 found:
9908 if (p->flags & FD_INVERT)
9909 value = !value;
9910 *(int *)((uint8_t *)s + p->offset) = value;
9911 return 0;
9915 /* set/reset a warning */
9916 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9918 int i;
9919 const FlagDef *p;
9921 if (!strcmp(warning_name, "all")) {
9922 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9923 if (p->flags & WD_ALL)
9924 *(int *)((uint8_t *)s + p->offset) = 1;
9926 return 0;
9927 } else {
9928 return set_flag(s, warning_defs, countof(warning_defs),
9929 warning_name, value);
9933 static const FlagDef flag_defs[] = {
9934 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
9935 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
9936 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
9939 /* set/reset a flag */
9940 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
9942 return set_flag(s, flag_defs, countof(flag_defs),
9943 flag_name, value);
9946 #if !defined(LIBTCC)
9948 /* extract the basename of a file */
9949 static const char *tcc_basename(const char *name)
9951 const char *p;
9952 p = strrchr(name, '/');
9953 #ifdef WIN32
9954 if (!p)
9955 p = strrchr(name, '\\');
9956 #endif
9957 if (!p)
9958 p = name;
9959 else
9960 p++;
9961 return p;
9964 static int64_t getclock_us(void)
9966 #ifdef WIN32
9967 struct _timeb tb;
9968 _ftime(&tb);
9969 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9970 #else
9971 struct timeval tv;
9972 gettimeofday(&tv, NULL);
9973 return tv.tv_sec * 1000000LL + tv.tv_usec;
9974 #endif
9977 void help(void)
9979 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2004 Fabrice Bellard\n"
9980 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9981 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9982 " [infile1 infile2...] [-run infile args...]\n"
9983 "\n"
9984 "General options:\n"
9985 " -v display current version\n"
9986 " -c compile only - generate an object file\n"
9987 " -o outfile set output filename\n"
9988 " -Bdir set tcc internal library path\n"
9989 " -bench output compilation statistics\n"
9990 " -run run compiled source\n"
9991 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
9992 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
9993 " -w disable all warnings\n"
9994 "Preprocessor options:\n"
9995 " -Idir add include path 'dir'\n"
9996 " -Dsym[=val] define 'sym' with value 'val'\n"
9997 " -Usym undefine 'sym'\n"
9998 "Linker options:\n"
9999 " -Ldir add library path 'dir'\n"
10000 " -llib link with dynamic or static library 'lib'\n"
10001 " -shared generate a shared library\n"
10002 " -static static linking\n"
10003 " -rdynamic export all global symbols to dynamic linker\n"
10004 " -r relocatable output\n"
10005 "Debugger options:\n"
10006 " -g generate runtime debug info\n"
10007 #ifdef CONFIG_TCC_BCHECK
10008 " -b compile with built-in memory and bounds checker (implies -g)\n"
10009 #endif
10010 " -bt N show N callers in stack traces\n"
10014 #define TCC_OPTION_HAS_ARG 0x0001
10015 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10017 typedef struct TCCOption {
10018 const char *name;
10019 uint16_t index;
10020 uint16_t flags;
10021 } TCCOption;
10023 enum {
10024 TCC_OPTION_HELP,
10025 TCC_OPTION_I,
10026 TCC_OPTION_D,
10027 TCC_OPTION_U,
10028 TCC_OPTION_L,
10029 TCC_OPTION_B,
10030 TCC_OPTION_l,
10031 TCC_OPTION_bench,
10032 TCC_OPTION_bt,
10033 TCC_OPTION_b,
10034 TCC_OPTION_g,
10035 TCC_OPTION_c,
10036 TCC_OPTION_static,
10037 TCC_OPTION_shared,
10038 TCC_OPTION_o,
10039 TCC_OPTION_r,
10040 TCC_OPTION_Wl,
10041 TCC_OPTION_W,
10042 TCC_OPTION_O,
10043 TCC_OPTION_m,
10044 TCC_OPTION_f,
10045 TCC_OPTION_nostdinc,
10046 TCC_OPTION_nostdlib,
10047 TCC_OPTION_print_search_dirs,
10048 TCC_OPTION_rdynamic,
10049 TCC_OPTION_run,
10050 TCC_OPTION_v,
10051 TCC_OPTION_w,
10054 static const TCCOption tcc_options[] = {
10055 { "h", TCC_OPTION_HELP, 0 },
10056 { "?", TCC_OPTION_HELP, 0 },
10057 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10058 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10059 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10060 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10061 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10062 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10063 { "bench", TCC_OPTION_bench, 0 },
10064 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10065 #ifdef CONFIG_TCC_BCHECK
10066 { "b", TCC_OPTION_b, 0 },
10067 #endif
10068 { "g", TCC_OPTION_g, 0 },
10069 { "c", TCC_OPTION_c, 0 },
10070 { "static", TCC_OPTION_static, 0 },
10071 { "shared", TCC_OPTION_shared, 0 },
10072 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10073 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10074 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10075 { "r", TCC_OPTION_r, 0 },
10076 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10077 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10078 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10079 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10080 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10081 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10082 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10083 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10084 { "v", TCC_OPTION_v, 0 },
10085 { "w", TCC_OPTION_w, 0 },
10086 { NULL },
10089 /* convert 'str' into an array of space separated strings */
10090 static int expand_args(char ***pargv, const char *str)
10092 const char *s1;
10093 char **argv, *arg;
10094 int argc, len;
10096 argc = 0;
10097 argv = NULL;
10098 for(;;) {
10099 while (is_space(*str))
10100 str++;
10101 if (*str == '\0')
10102 break;
10103 s1 = str;
10104 while (*str != '\0' && !is_space(*str))
10105 str++;
10106 len = str - s1;
10107 arg = tcc_malloc(len + 1);
10108 memcpy(arg, s1, len);
10109 arg[len] = '\0';
10110 dynarray_add((void ***)&argv, &argc, arg);
10112 *pargv = argv;
10113 return argc;
10116 static char **files;
10117 static int nb_files, nb_libraries;
10118 static int multiple_files;
10119 static int print_search_dirs;
10120 static int output_type;
10121 static int reloc_output;
10122 static const char *outfile;
10124 int parse_args(TCCState *s, int argc, char **argv)
10126 int optind;
10127 const TCCOption *popt;
10128 const char *optarg, *p1, *r1;
10129 char *r;
10131 optind = 0;
10132 while (1) {
10133 if (optind >= argc) {
10134 if (nb_files == 0 && !print_search_dirs)
10135 goto show_help;
10136 else
10137 break;
10139 r = argv[optind++];
10140 if (r[0] != '-') {
10141 /* add a new file */
10142 dynarray_add((void ***)&files, &nb_files, r);
10143 if (!multiple_files) {
10144 optind--;
10145 /* argv[0] will be this file */
10146 break;
10148 } else {
10149 /* find option in table (match only the first chars */
10150 popt = tcc_options;
10151 for(;;) {
10152 p1 = popt->name;
10153 if (p1 == NULL)
10154 error("invalid option -- '%s'", r);
10155 r1 = r + 1;
10156 for(;;) {
10157 if (*p1 == '\0')
10158 goto option_found;
10159 if (*r1 != *p1)
10160 break;
10161 p1++;
10162 r1++;
10164 popt++;
10166 option_found:
10167 if (popt->flags & TCC_OPTION_HAS_ARG) {
10168 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10169 optarg = r1;
10170 } else {
10171 if (optind >= argc)
10172 error("argument to '%s' is missing", r);
10173 optarg = argv[optind++];
10175 } else {
10176 if (*r1 != '\0')
10177 goto show_help;
10178 optarg = NULL;
10181 switch(popt->index) {
10182 case TCC_OPTION_HELP:
10183 show_help:
10184 help();
10185 exit(1);
10186 case TCC_OPTION_I:
10187 if (tcc_add_include_path(s, optarg) < 0)
10188 error("too many include paths");
10189 break;
10190 case TCC_OPTION_D:
10192 char *sym, *value;
10193 sym = (char *)optarg;
10194 value = strchr(sym, '=');
10195 if (value) {
10196 *value = '\0';
10197 value++;
10199 tcc_define_symbol(s, sym, value);
10201 break;
10202 case TCC_OPTION_U:
10203 tcc_undefine_symbol(s, optarg);
10204 break;
10205 case TCC_OPTION_L:
10206 tcc_add_library_path(s, optarg);
10207 break;
10208 case TCC_OPTION_B:
10209 /* set tcc utilities path (mainly for tcc development) */
10210 tcc_lib_path = optarg;
10211 break;
10212 case TCC_OPTION_l:
10213 dynarray_add((void ***)&files, &nb_files, r);
10214 nb_libraries++;
10215 break;
10216 case TCC_OPTION_bench:
10217 do_bench = 1;
10218 break;
10219 case TCC_OPTION_bt:
10220 num_callers = atoi(optarg);
10221 break;
10222 #ifdef CONFIG_TCC_BCHECK
10223 case TCC_OPTION_b:
10224 do_bounds_check = 1;
10225 do_debug = 1;
10226 break;
10227 #endif
10228 case TCC_OPTION_g:
10229 do_debug = 1;
10230 break;
10231 case TCC_OPTION_c:
10232 multiple_files = 1;
10233 output_type = TCC_OUTPUT_OBJ;
10234 break;
10235 case TCC_OPTION_static:
10236 s->static_link = 1;
10237 break;
10238 case TCC_OPTION_shared:
10239 output_type = TCC_OUTPUT_DLL;
10240 break;
10241 case TCC_OPTION_o:
10242 multiple_files = 1;
10243 outfile = optarg;
10244 break;
10245 case TCC_OPTION_r:
10246 /* generate a .o merging several output files */
10247 reloc_output = 1;
10248 output_type = TCC_OUTPUT_OBJ;
10249 break;
10250 case TCC_OPTION_nostdinc:
10251 s->nostdinc = 1;
10252 break;
10253 case TCC_OPTION_nostdlib:
10254 s->nostdlib = 1;
10255 break;
10256 case TCC_OPTION_print_search_dirs:
10257 print_search_dirs = 1;
10258 break;
10259 case TCC_OPTION_run:
10261 int argc1;
10262 char **argv1;
10263 argc1 = expand_args(&argv1, optarg);
10264 if (argc1 > 0) {
10265 parse_args(s, argc1, argv1);
10267 multiple_files = 0;
10268 output_type = TCC_OUTPUT_MEMORY;
10270 break;
10271 case TCC_OPTION_v:
10272 printf("tcc version %s\n", TCC_VERSION);
10273 exit(0);
10274 case TCC_OPTION_f:
10275 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10276 goto unsupported_option;
10277 break;
10278 case TCC_OPTION_W:
10279 if (tcc_set_warning(s, optarg, 1) < 0 &&
10280 s->warn_unsupported)
10281 goto unsupported_option;
10282 break;
10283 case TCC_OPTION_w:
10284 s->warn_none = 1;
10285 break;
10286 case TCC_OPTION_rdynamic:
10287 s->rdynamic = 1;
10288 break;
10289 case TCC_OPTION_Wl:
10291 const char *p;
10292 if (strstart(optarg, "-Ttext,", &p)) {
10293 s->text_addr = strtoul(p, NULL, 16);
10294 s->has_text_addr = 1;
10295 } else if (strstart(optarg, "--oformat,", &p)) {
10296 if (strstart(p, "elf32-", NULL)) {
10297 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10298 } else if (!strcmp(p, "binary")) {
10299 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10300 } else
10301 #ifdef TCC_TARGET_COFF
10302 if (!strcmp(p, "coff")) {
10303 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10304 } else
10305 #endif
10307 error("target %s not found", p);
10309 } else {
10310 error("unsupported linker option '%s'", optarg);
10313 break;
10314 default:
10315 if (s->warn_unsupported) {
10316 unsupported_option:
10317 warning("unsupported option '%s'", r);
10319 break;
10323 return optind;
10326 int main(int argc, char **argv)
10328 int i;
10329 TCCState *s;
10330 int nb_objfiles, ret, optind;
10331 char objfilename[1024];
10332 int64_t start_time = 0;
10334 s = tcc_new();
10335 output_type = TCC_OUTPUT_EXE;
10336 outfile = NULL;
10337 multiple_files = 1;
10338 files = NULL;
10339 nb_files = 0;
10340 nb_libraries = 0;
10341 reloc_output = 0;
10342 print_search_dirs = 0;
10344 optind = parse_args(s, argc - 1, argv + 1) + 1;
10346 if (print_search_dirs) {
10347 /* enough for Linux kernel */
10348 printf("install: %s/\n", tcc_lib_path);
10349 return 0;
10352 nb_objfiles = nb_files - nb_libraries;
10354 /* if outfile provided without other options, we output an
10355 executable */
10356 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10357 output_type = TCC_OUTPUT_EXE;
10359 /* check -c consistency : only single file handled. XXX: checks file type */
10360 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10361 /* accepts only a single input file */
10362 if (nb_objfiles != 1)
10363 error("cannot specify multiple files with -c");
10364 if (nb_libraries != 0)
10365 error("cannot specify libraries with -c");
10368 /* compute default outfile name */
10369 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
10370 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10371 char *ext;
10372 /* strip path */
10373 pstrcpy(objfilename, sizeof(objfilename) - 1,
10374 tcc_basename(files[0]));
10375 /* add .o extension */
10376 ext = strrchr(objfilename, '.');
10377 if (!ext)
10378 goto default_outfile;
10379 strcpy(ext + 1, "o");
10380 } else {
10381 default_outfile:
10382 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10384 outfile = objfilename;
10387 if (do_bench) {
10388 start_time = getclock_us();
10391 tcc_set_output_type(s, output_type);
10393 /* compile or add each files or library */
10394 for(i = 0;i < nb_files; i++) {
10395 const char *filename;
10397 filename = files[i];
10398 if (filename[0] == '-') {
10399 if (tcc_add_library(s, filename + 2) < 0)
10400 error("cannot find %s", filename);
10401 } else {
10402 if (tcc_add_file(s, filename) < 0) {
10403 ret = 1;
10404 goto the_end;
10409 /* free all files */
10410 tcc_free(files);
10412 if (do_bench) {
10413 double total_time;
10414 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10415 if (total_time < 0.001)
10416 total_time = 0.001;
10417 if (total_bytes < 1)
10418 total_bytes = 1;
10419 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10420 tok_ident - TOK_IDENT, total_lines, total_bytes,
10421 total_time, (int)(total_lines / total_time),
10422 total_bytes / total_time / 1000000.0);
10425 if (s->output_type != TCC_OUTPUT_MEMORY) {
10426 tcc_output_file(s, outfile);
10427 ret = 0;
10428 } else {
10429 ret = tcc_run(s, argc - optind, argv + optind);
10431 the_end:
10432 /* XXX: cannot do it with bound checking because of the malloc hooks */
10433 if (!do_bounds_check)
10434 tcc_delete(s);
10436 #ifdef MEM_DEBUG
10437 if (do_bench) {
10438 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10440 #endif
10441 return ret;
10444 #endif