#include_next support (Bernhard Fischer)
[tinycc.git] / tcc.c
bloba0b6db1197bd20751917cfb0628d20b889eb42f4
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 <fcntl.h>
39 #include <setjmp.h>
40 #include <time.h>
41 #ifdef WIN32
42 #include <sys/timeb.h>
43 #endif
44 #ifndef WIN32
45 #include <sys/time.h>
46 #include <sys/ucontext.h>
47 #endif
49 #endif /* !CONFIG_TCCBOOT */
51 #include "elf.h"
52 #include "stab.h"
54 #ifndef O_BINARY
55 #define O_BINARY 0
56 #endif
58 #include "libtcc.h"
60 /* parser debug */
61 //#define PARSE_DEBUG
62 /* preprocessor debug */
63 //#define PP_DEBUG
64 /* include file debug */
65 //#define INC_DEBUG
67 //#define MEM_DEBUG
69 /* assembler debug */
70 //#define ASM_DEBUG
72 /* target selection */
73 //#define TCC_TARGET_I386 /* i386 code generator */
74 //#define TCC_TARGET_ARM /* ARMv4 code generator */
75 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
77 /* default target is I386 */
78 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
79 !defined(TCC_TARGET_C67)
80 #define TCC_TARGET_I386
81 #endif
83 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
84 !defined(TCC_TARGET_C67)
85 #define CONFIG_TCC_BCHECK /* enable bound checking code */
86 #endif
88 /* define it to include assembler support */
89 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
90 #define CONFIG_TCC_ASM
91 #endif
93 /* object format selection */
94 #if defined(TCC_TARGET_C67)
95 #define TCC_TARGET_COFF
96 #endif
98 #define FALSE 0
99 #define false 0
100 #define TRUE 1
101 #define true 1
102 typedef int BOOL;
104 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
105 executables or dlls */
106 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
108 #define INCLUDE_STACK_SIZE 32
109 #define IFDEF_STACK_SIZE 64
110 #define VSTACK_SIZE 256
111 #define STRING_MAX_SIZE 1024
113 #define TOK_HASH_SIZE 8192 /* must be a power of two */
114 #define TOK_ALLOC_INCR 512 /* must be a power of two */
115 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
117 /* token symbol management */
118 typedef struct TokenSym {
119 struct TokenSym *hash_next;
120 struct Sym *sym_define; /* direct pointer to define */
121 struct Sym *sym_label; /* direct pointer to label */
122 struct Sym *sym_struct; /* direct pointer to structure */
123 struct Sym *sym_identifier; /* direct pointer to identifier */
124 int tok; /* token number */
125 int len;
126 char str[1];
127 } TokenSym;
129 typedef struct CString {
130 int size; /* size in bytes */
131 void *data; /* either 'char *' or 'int *' */
132 int size_allocated;
133 void *data_allocated; /* if non NULL, data has been malloced */
134 } CString;
136 /* type definition */
137 typedef struct CType {
138 int t;
139 struct Sym *ref;
140 } CType;
142 /* constant value */
143 typedef union CValue {
144 long double ld;
145 double d;
146 float f;
147 int i;
148 unsigned int ui;
149 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
150 long long ll;
151 unsigned long long ull;
152 struct CString *cstr;
153 void *ptr;
154 int tab[1];
155 } CValue;
157 /* value on stack */
158 typedef struct SValue {
159 CType type; /* type */
160 unsigned short r; /* register + flags */
161 unsigned short r2; /* second register, used for 'long long'
162 type. If not used, set to VT_CONST */
163 CValue c; /* constant, if VT_CONST */
164 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
165 } SValue;
167 /* symbol management */
168 typedef struct Sym {
169 int v; /* symbol token */
170 int r; /* associated register */
171 int c; /* associated number */
172 CType type; /* associated type */
173 struct Sym *next; /* next related symbol */
174 struct Sym *prev; /* prev symbol in stack */
175 struct Sym *prev_tok; /* previous symbol for this token */
176 } Sym;
178 /* section definition */
179 /* XXX: use directly ELF structure for parameters ? */
180 /* special flag to indicate that the section should not be linked to
181 the other ones */
182 #define SHF_PRIVATE 0x80000000
184 typedef struct Section {
185 unsigned long data_offset; /* current data offset */
186 unsigned char *data; /* section data */
187 unsigned long data_allocated; /* used for realloc() handling */
188 int sh_name; /* elf section name (only used during output) */
189 int sh_num; /* elf section number */
190 int sh_type; /* elf section type */
191 int sh_flags; /* elf section flags */
192 int sh_info; /* elf section info */
193 int sh_addralign; /* elf section alignment */
194 int sh_entsize; /* elf entry size */
195 unsigned long sh_size; /* section size (only used during output) */
196 unsigned long sh_addr; /* address at which the section is relocated */
197 unsigned long sh_offset; /* address at which the section is relocated */
198 int nb_hashed_syms; /* used to resize the hash table */
199 struct Section *link; /* link to another section */
200 struct Section *reloc; /* corresponding section for relocation, if any */
201 struct Section *hash; /* hash table for symbols */
202 struct Section *next;
203 char name[1]; /* section name */
204 } Section;
206 typedef struct DLLReference {
207 int level;
208 char name[1];
209 } DLLReference;
211 /* GNUC attribute definition */
212 typedef struct AttributeDef {
213 int aligned;
214 int packed;
215 Section *section;
216 unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
217 unsigned char dllexport;
218 } AttributeDef;
220 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
221 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
222 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
224 /* stored in 'Sym.c' field */
225 #define FUNC_NEW 1 /* ansi function prototype */
226 #define FUNC_OLD 2 /* old function prototype */
227 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
229 /* stored in 'Sym.r' field */
230 #define FUNC_CDECL 0 /* standard c call */
231 #define FUNC_STDCALL 1 /* pascal c call */
232 #define FUNC_FASTCALL1 2 /* first param in %eax */
233 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
234 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
236 /* field 'Sym.t' for macros */
237 #define MACRO_OBJ 0 /* object like macro */
238 #define MACRO_FUNC 1 /* function like macro */
240 /* field 'Sym.r' for C labels */
241 #define LABEL_DEFINED 0 /* label is defined */
242 #define LABEL_FORWARD 1 /* label is forward defined */
243 #define LABEL_DECLARED 2 /* label is declared but never used */
245 /* type_decl() types */
246 #define TYPE_ABSTRACT 1 /* type without variable */
247 #define TYPE_DIRECT 2 /* type with variable */
249 #define IO_BUF_SIZE 8192
251 typedef struct BufferedFile {
252 uint8_t *buf_ptr;
253 uint8_t *buf_end;
254 int fd;
255 int line_num; /* current line number - here to simplify code */
256 int ifndef_macro; /* #ifndef macro / #endif search */
257 int ifndef_macro_saved; /* saved ifndef_macro */
258 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
259 char inc_type; /* type of include */
260 char inc_filename[512]; /* filename specified by the user */
261 char filename[1024]; /* current filename - here to simplify code */
262 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
263 } BufferedFile;
265 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
266 #define CH_EOF (-1) /* end of file */
268 /* parsing state (used to save parser state to reparse part of the
269 source several times) */
270 typedef struct ParseState {
271 int *macro_ptr;
272 int line_num;
273 int tok;
274 CValue tokc;
275 } ParseState;
277 /* used to record tokens */
278 typedef struct TokenString {
279 int *str;
280 int len;
281 int allocated_len;
282 int last_line_num;
283 } TokenString;
285 /* include file cache, used to find files faster and also to eliminate
286 inclusion if the include file is protected by #ifndef ... #endif */
287 typedef struct CachedInclude {
288 int ifndef_macro;
289 int hash_next; /* -1 if none */
290 char type; /* '"' or '>' to give include type */
291 char filename[1]; /* path specified in #include */
292 } CachedInclude;
294 #define CACHED_INCLUDES_HASH_SIZE 512
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 #ifdef CONFIG_TCC_ASM
323 static Section *last_text_section; /* to handle .previous asm directive */
324 #endif
325 /* bound check related sections */
326 static Section *bounds_section; /* contains global data bound description */
327 static Section *lbounds_section; /* contains local data bound description */
328 /* symbol sections */
329 static Section *symtab_section, *strtab_section;
331 /* debug sections */
332 static Section *stab_section, *stabstr_section;
334 /* loc : local variable index
335 ind : output code index
336 rsym: return symbol
337 anon_sym: anonymous symbol index
339 static int rsym, anon_sym, ind, loc;
340 /* expression generation modifiers */
341 static int const_wanted; /* true if constant wanted */
342 static int nocode_wanted; /* true if no code generation wanted for an expression */
343 static int global_expr; /* true if compound literals must be allocated
344 globally (used during initializers parsing */
345 static CType func_vt; /* current function return type (used by return
346 instruction) */
347 static int func_vc;
348 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
349 static int tok_ident;
350 static TokenSym **table_ident;
351 static TokenSym *hash_ident[TOK_HASH_SIZE];
352 static char token_buf[STRING_MAX_SIZE + 1];
353 static char *funcname;
354 static Sym *global_stack, *local_stack;
355 static Sym *define_stack;
356 static Sym *global_label_stack, *local_label_stack;
357 /* symbol allocator */
358 #define SYM_POOL_NB (8192 / sizeof(Sym))
359 static Sym *sym_free_first;
361 static SValue vstack[VSTACK_SIZE], *vtop;
362 /* some predefined types */
363 static CType char_pointer_type, func_old_type, int_type;
364 /* true if isid(c) || isnum(c) */
365 static unsigned char isidnum_table[256];
367 /* compile with debug symbol (and use them if error during execution) */
368 static int do_debug = 0;
370 /* compile with built-in memory and bounds checker */
371 static int do_bounds_check = 0;
373 /* display benchmark infos */
374 #if !defined(LIBTCC)
375 static int do_bench = 0;
376 #endif
377 static int total_lines;
378 static int total_bytes;
380 /* use GNU C extensions */
381 static int gnu_ext = 1;
383 /* use Tiny C extensions */
384 static int tcc_ext = 1;
386 /* max number of callers shown if error */
387 static int num_callers = 6;
388 static const char **rt_bound_error_msg;
390 /* XXX: get rid of this ASAP */
391 static struct TCCState *tcc_state;
393 /* give the path of the tcc libraries */
394 static const char *tcc_lib_path = CONFIG_TCC_LIBDIR "/tcc";
396 struct TCCState {
397 int output_type;
399 BufferedFile **include_stack_ptr;
400 int *ifdef_stack_ptr;
402 /* include file handling */
403 char **include_paths;
404 int nb_include_paths;
405 char **sysinclude_paths;
406 int nb_sysinclude_paths;
407 CachedInclude **cached_includes;
408 int nb_cached_includes;
410 char **library_paths;
411 int nb_library_paths;
413 /* array of all loaded dlls (including those referenced by loaded
414 dlls) */
415 DLLReference **loaded_dlls;
416 int nb_loaded_dlls;
418 /* sections */
419 Section **sections;
420 int nb_sections; /* number of sections, including first dummy section */
422 /* got handling */
423 Section *got;
424 Section *plt;
425 unsigned long *got_offsets;
426 int nb_got_offsets;
427 /* give the correspondance from symtab indexes to dynsym indexes */
428 int *symtab_to_dynsym;
430 /* temporary dynamic symbol sections (for dll loading) */
431 Section *dynsymtab_section;
432 /* exported dynamic symbol section */
433 Section *dynsym;
435 int nostdinc; /* if true, no standard headers are added */
436 int nostdlib; /* if true, no standard libraries are added */
438 int nocommon; /* if true, do not use common symbols for .bss data */
440 /* if true, static linking is performed */
441 int static_link;
443 /* if true, all symbols are exported */
444 int rdynamic;
446 /* if true, only link in referenced objects from archive */
447 int alacarte_link;
449 /* address of text section */
450 unsigned long text_addr;
451 int has_text_addr;
453 /* output format, see TCC_OUTPUT_FORMAT_xxx */
454 int output_format;
456 /* C language options */
457 int char_is_unsigned;
459 /* warning switches */
460 int warn_write_strings;
461 int warn_unsupported;
462 int warn_error;
463 int warn_none;
464 int warn_implicit_function_declaration;
466 /* error handling */
467 void *error_opaque;
468 void (*error_func)(void *opaque, const char *msg);
469 int error_set_jmp_enabled;
470 jmp_buf error_jmp_buf;
471 int nb_errors;
473 /* tiny assembler state */
474 Sym *asm_labels;
476 /* see include_stack_ptr */
477 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
479 /* see ifdef_stack_ptr */
480 int ifdef_stack[IFDEF_STACK_SIZE];
482 /* see cached_includes */
483 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
486 /* The current value can be: */
487 #define VT_VALMASK 0x00ff
488 #define VT_CONST 0x00f0 /* constant in vc
489 (must be first non register value) */
490 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
491 #define VT_LOCAL 0x00f2 /* offset on stack */
492 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
493 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
494 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
495 #define VT_LVAL 0x0100 /* var is an lvalue */
496 #define VT_SYM 0x0200 /* a symbol value is added */
497 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
498 char/short stored in integer registers) */
499 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
500 dereferencing value */
501 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
502 bounding function call point is in vc */
503 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
504 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
505 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
506 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
508 /* types */
509 #define VT_INT 0 /* integer type */
510 #define VT_BYTE 1 /* signed byte type */
511 #define VT_SHORT 2 /* short type */
512 #define VT_VOID 3 /* void type */
513 #define VT_PTR 4 /* pointer */
514 #define VT_ENUM 5 /* enum definition */
515 #define VT_FUNC 6 /* function type */
516 #define VT_STRUCT 7 /* struct/union definition */
517 #define VT_FLOAT 8 /* IEEE float */
518 #define VT_DOUBLE 9 /* IEEE double */
519 #define VT_LDOUBLE 10 /* IEEE long double */
520 #define VT_BOOL 11 /* ISOC99 boolean type */
521 #define VT_LLONG 12 /* 64 bit integer */
522 #define VT_LONG 13 /* long integer (NEVER USED as type, only
523 during parsing) */
524 #define VT_BTYPE 0x000f /* mask for basic type */
525 #define VT_UNSIGNED 0x0010 /* unsigned type */
526 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
527 #define VT_BITFIELD 0x0040 /* bitfield modifier */
528 #define VT_CONSTANT 0x0800 /* const modifier */
529 #define VT_VOLATILE 0x1000 /* volatile modifier */
530 #define VT_SIGNED 0x2000 /* signed type */
532 /* storage */
533 #define VT_EXTERN 0x00000080 /* extern definition */
534 #define VT_STATIC 0x00000100 /* static variable */
535 #define VT_TYPEDEF 0x00000200 /* typedef definition */
536 #define VT_INLINE 0x00000400 /* inline definition */
538 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
540 /* type mask (except storage) */
541 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
542 #define VT_TYPE (~(VT_STORAGE))
544 /* token values */
546 /* warning: the following compare tokens depend on i386 asm code */
547 #define TOK_ULT 0x92
548 #define TOK_UGE 0x93
549 #define TOK_EQ 0x94
550 #define TOK_NE 0x95
551 #define TOK_ULE 0x96
552 #define TOK_UGT 0x97
553 #define TOK_LT 0x9c
554 #define TOK_GE 0x9d
555 #define TOK_LE 0x9e
556 #define TOK_GT 0x9f
558 #define TOK_LAND 0xa0
559 #define TOK_LOR 0xa1
561 #define TOK_DEC 0xa2
562 #define TOK_MID 0xa3 /* inc/dec, to void constant */
563 #define TOK_INC 0xa4
564 #define TOK_UDIV 0xb0 /* unsigned division */
565 #define TOK_UMOD 0xb1 /* unsigned modulo */
566 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
567 #define TOK_CINT 0xb3 /* number in tokc */
568 #define TOK_CCHAR 0xb4 /* char constant in tokc */
569 #define TOK_STR 0xb5 /* pointer to string in tokc */
570 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
571 #define TOK_LCHAR 0xb7
572 #define TOK_LSTR 0xb8
573 #define TOK_CFLOAT 0xb9 /* float constant */
574 #define TOK_LINENUM 0xba /* line number info */
575 #define TOK_CDOUBLE 0xc0 /* double constant */
576 #define TOK_CLDOUBLE 0xc1 /* long double constant */
577 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
578 #define TOK_ADDC1 0xc3 /* add with carry generation */
579 #define TOK_ADDC2 0xc4 /* add with carry use */
580 #define TOK_SUBC1 0xc5 /* add with carry generation */
581 #define TOK_SUBC2 0xc6 /* add with carry use */
582 #define TOK_CUINT 0xc8 /* unsigned int constant */
583 #define TOK_CLLONG 0xc9 /* long long constant */
584 #define TOK_CULLONG 0xca /* unsigned long long constant */
585 #define TOK_ARROW 0xcb
586 #define TOK_DOTS 0xcc /* three dots */
587 #define TOK_SHR 0xcd /* unsigned shift right */
588 #define TOK_PPNUM 0xce /* preprocessor number */
590 #define TOK_SHL 0x01 /* shift left */
591 #define TOK_SAR 0x02 /* signed shift right */
593 /* assignement operators : normal operator or 0x80 */
594 #define TOK_A_MOD 0xa5
595 #define TOK_A_AND 0xa6
596 #define TOK_A_MUL 0xaa
597 #define TOK_A_ADD 0xab
598 #define TOK_A_SUB 0xad
599 #define TOK_A_DIV 0xaf
600 #define TOK_A_XOR 0xde
601 #define TOK_A_OR 0xfc
602 #define TOK_A_SHL 0x81
603 #define TOK_A_SAR 0x82
605 #ifndef offsetof
606 #define offsetof(type, field) ((size_t) &((type *)0)->field)
607 #endif
609 #ifndef countof
610 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
611 #endif
613 /* WARNING: the content of this string encodes token numbers */
614 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";
616 #define TOK_EOF (-1) /* end of file */
617 #define TOK_LINEFEED 10 /* line feed */
619 /* all identificators and strings have token above that */
620 #define TOK_IDENT 256
622 /* only used for i386 asm opcodes definitions */
623 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
625 #define DEF_BWL(x) \
626 DEF(TOK_ASM_ ## x ## b, #x "b") \
627 DEF(TOK_ASM_ ## x ## w, #x "w") \
628 DEF(TOK_ASM_ ## x ## l, #x "l") \
629 DEF(TOK_ASM_ ## x, #x)
631 #define DEF_WL(x) \
632 DEF(TOK_ASM_ ## x ## w, #x "w") \
633 DEF(TOK_ASM_ ## x ## l, #x "l") \
634 DEF(TOK_ASM_ ## x, #x)
636 #define DEF_FP1(x) \
637 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
638 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
639 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
640 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
642 #define DEF_FP(x) \
643 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
644 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
645 DEF_FP1(x)
647 #define DEF_ASMTEST(x) \
648 DEF_ASM(x ## o) \
649 DEF_ASM(x ## no) \
650 DEF_ASM(x ## b) \
651 DEF_ASM(x ## c) \
652 DEF_ASM(x ## nae) \
653 DEF_ASM(x ## nb) \
654 DEF_ASM(x ## nc) \
655 DEF_ASM(x ## ae) \
656 DEF_ASM(x ## e) \
657 DEF_ASM(x ## z) \
658 DEF_ASM(x ## ne) \
659 DEF_ASM(x ## nz) \
660 DEF_ASM(x ## be) \
661 DEF_ASM(x ## na) \
662 DEF_ASM(x ## nbe) \
663 DEF_ASM(x ## a) \
664 DEF_ASM(x ## s) \
665 DEF_ASM(x ## ns) \
666 DEF_ASM(x ## p) \
667 DEF_ASM(x ## pe) \
668 DEF_ASM(x ## np) \
669 DEF_ASM(x ## po) \
670 DEF_ASM(x ## l) \
671 DEF_ASM(x ## nge) \
672 DEF_ASM(x ## nl) \
673 DEF_ASM(x ## ge) \
674 DEF_ASM(x ## le) \
675 DEF_ASM(x ## ng) \
676 DEF_ASM(x ## nle) \
677 DEF_ASM(x ## g)
679 #define TOK_ASM_int TOK_INT
681 enum tcc_token {
682 TOK_LAST = TOK_IDENT - 1,
683 #define DEF(id, str) id,
684 #include "tcctok.h"
685 #undef DEF
688 static const char tcc_keywords[] =
689 #define DEF(id, str) str "\0"
690 #include "tcctok.h"
691 #undef DEF
694 #define TOK_UIDENT TOK_DEFINE
696 #ifdef WIN32
697 #define snprintf _snprintf
698 #define vsnprintf _vsnprintf
699 #endif
701 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
702 /* currently incorrect */
703 long double strtold(const char *nptr, char **endptr)
705 return (long double)strtod(nptr, endptr);
707 float strtof(const char *nptr, char **endptr)
709 return (float)strtod(nptr, endptr);
711 #else
712 /* XXX: need to define this to use them in non ISOC99 context */
713 extern float strtof (const char *__nptr, char **__endptr);
714 extern long double strtold (const char *__nptr, char **__endptr);
715 #endif
717 static char *pstrcpy(char *buf, int buf_size, const char *s);
718 static char *pstrcat(char *buf, int buf_size, const char *s);
719 static const char *tcc_basename(const char *name);
721 static void next(void);
722 static void next_nomacro(void);
723 static void parse_expr_type(CType *type);
724 static void expr_type(CType *type);
725 static void unary_type(CType *type);
726 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
727 int case_reg, int is_expr);
728 static int expr_const(void);
729 static void expr_eq(void);
730 static void gexpr(void);
731 static void gen_inline_functions(void);
732 static void decl(int l);
733 static void decl_initializer(CType *type, Section *sec, unsigned long c,
734 int first, int size_only);
735 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
736 int has_init, int v, int scope);
737 int gv(int rc);
738 void gv2(int rc1, int rc2);
739 void move_reg(int r, int s);
740 void save_regs(int n);
741 void save_reg(int r);
742 void vpop(void);
743 void vswap(void);
744 void vdup(void);
745 int get_reg(int rc);
746 int get_reg_ex(int rc,int rc2);
748 static void macro_subst(TokenString *tok_str, Sym **nested_list,
749 const int *macro_str, int can_read_stream);
750 void gen_op(int op);
751 void force_charshort_cast(int t);
752 static void gen_cast(CType *type);
753 void vstore(void);
754 static Sym *sym_find(int v);
755 static Sym *sym_push(int v, CType *type, int r, int c);
757 /* type handling */
758 static int type_size(CType *type, int *a);
759 static inline CType *pointed_type(CType *type);
760 static int pointed_size(CType *type);
761 static int lvalue_type(int t);
762 static int parse_btype(CType *type, AttributeDef *ad);
763 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
764 static int is_compatible_types(CType *type1, CType *type2);
766 int ieee_finite(double d);
767 void error(const char *fmt, ...);
768 void vpushi(int v);
769 void vrott(int n);
770 void vnrott(int n);
771 void lexpand_nr(void);
772 static void vpush_global_sym(CType *type, int v);
773 void vset(CType *type, int r, int v);
774 void type_to_str(char *buf, int buf_size,
775 CType *type, const char *varstr);
776 char *get_tok_str(int v, CValue *cv);
777 static Sym *get_sym_ref(CType *type, Section *sec,
778 unsigned long offset, unsigned long size);
779 static Sym *external_global_sym(int v, CType *type, int r);
781 /* section generation */
782 static void section_realloc(Section *sec, unsigned long new_size);
783 static void *section_ptr_add(Section *sec, unsigned long size);
784 static void put_extern_sym(Sym *sym, Section *section,
785 unsigned long value, unsigned long size);
786 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
787 static int put_elf_str(Section *s, const char *sym);
788 static int put_elf_sym(Section *s,
789 unsigned long value, unsigned long size,
790 int info, int other, int shndx, const char *name);
791 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
792 int info, int sh_num, const char *name);
793 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
794 int type, int symbol);
795 static void put_stabs(const char *str, int type, int other, int desc,
796 unsigned long value);
797 static void put_stabs_r(const char *str, int type, int other, int desc,
798 unsigned long value, Section *sec, int sym_index);
799 static void put_stabn(int type, int other, int desc, int value);
800 static void put_stabd(int type, int other, int desc);
801 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
803 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
804 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
805 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
807 /* tcccoff.c */
808 int tcc_output_coff(TCCState *s1, FILE *f);
810 /* tccpe.c */
811 void *resolve_sym(TCCState *s1, const char *sym, int type);
812 int pe_load_def_file(struct TCCState *s1, FILE *fp);
813 void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
814 unsigned long pe_add_runtime(struct TCCState *s1);
815 int tcc_output_pe(struct TCCState *s1, const char *filename);
817 /* tccasm.c */
819 #ifdef CONFIG_TCC_ASM
821 typedef struct ExprValue {
822 uint32_t v;
823 Sym *sym;
824 } ExprValue;
826 #define MAX_ASM_OPERANDS 30
828 typedef struct ASMOperand {
829 int id; /* GCC 3 optionnal identifier (0 if number only supported */
830 char *constraint;
831 char asm_str[16]; /* computed asm string for operand */
832 SValue *vt; /* C value of the expression */
833 int ref_index; /* if >= 0, gives reference to a output constraint */
834 int input_index; /* if >= 0, gives reference to an input constraint */
835 int priority; /* priority, used to assign registers */
836 int reg; /* if >= 0, register number used for this operand */
837 int is_llong; /* true if double register value */
838 int is_memory; /* true if memory operand */
839 int is_rw; /* for '+' modifier */
840 } ASMOperand;
842 static void asm_expr(TCCState *s1, ExprValue *pe);
843 static int asm_int_expr(TCCState *s1);
844 static int find_constraint(ASMOperand *operands, int nb_operands,
845 const char *name, const char **pp);
847 static int tcc_assemble(TCCState *s1, int do_preprocess);
849 #endif
851 static void asm_instr(void);
852 static void asm_global_instr(void);
854 /* true if float/double/long double type */
855 static inline int is_float(int t)
857 int bt;
858 bt = t & VT_BTYPE;
859 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
862 #ifdef TCC_TARGET_I386
863 #include "i386-gen.c"
864 #endif
866 #ifdef TCC_TARGET_ARM
867 #include "arm-gen.c"
868 #endif
870 #ifdef TCC_TARGET_C67
871 #include "c67-gen.c"
872 #endif
874 #ifdef CONFIG_TCC_STATIC
876 #define RTLD_LAZY 0x001
877 #define RTLD_NOW 0x002
878 #define RTLD_GLOBAL 0x100
879 #define RTLD_DEFAULT NULL
881 /* dummy function for profiling */
882 void *dlopen(const char *filename, int flag)
884 return NULL;
887 const char *dlerror(void)
889 return "error";
892 typedef struct TCCSyms {
893 char *str;
894 void *ptr;
895 } TCCSyms;
897 #define TCCSYM(a) { #a, &a, },
899 /* add the symbol you want here if no dynamic linking is done */
900 static TCCSyms tcc_syms[] = {
901 #if !defined(CONFIG_TCCBOOT)
902 TCCSYM(printf)
903 TCCSYM(fprintf)
904 TCCSYM(fopen)
905 TCCSYM(fclose)
906 #endif
907 { NULL, NULL },
910 void *resolve_sym(TCCState *s1, const char *symbol, int type)
912 TCCSyms *p;
913 p = tcc_syms;
914 while (p->str != NULL) {
915 if (!strcmp(p->str, symbol))
916 return p->ptr;
917 p++;
919 return NULL;
922 #elif !defined(WIN32)
924 #include <dlfcn.h>
926 void *resolve_sym(TCCState *s1, const char *sym, int type)
928 return dlsym(RTLD_DEFAULT, sym);
931 #endif
933 /********************************************************/
935 /* we use our own 'finite' function to avoid potential problems with
936 non standard math libs */
937 /* XXX: endianness dependent */
938 int ieee_finite(double d)
940 int *p = (int *)&d;
941 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
944 /* copy a string and truncate it. */
945 static char *pstrcpy(char *buf, int buf_size, const char *s)
947 char *q, *q_end;
948 int c;
950 if (buf_size > 0) {
951 q = buf;
952 q_end = buf + buf_size - 1;
953 while (q < q_end) {
954 c = *s++;
955 if (c == '\0')
956 break;
957 *q++ = c;
959 *q = '\0';
961 return buf;
964 /* strcat and truncate. */
965 static char *pstrcat(char *buf, int buf_size, const char *s)
967 int len;
968 len = strlen(buf);
969 if (len < buf_size)
970 pstrcpy(buf + len, buf_size - len, s);
971 return buf;
974 static int strstart(const char *str, const char *val, const char **ptr)
976 const char *p, *q;
977 p = str;
978 q = val;
979 while (*q != '\0') {
980 if (*p != *q)
981 return 0;
982 p++;
983 q++;
985 if (ptr)
986 *ptr = p;
987 return 1;
990 /* memory management */
991 #ifdef MEM_DEBUG
992 int mem_cur_size;
993 int mem_max_size;
994 #endif
996 static inline void tcc_free(void *ptr)
998 #ifdef MEM_DEBUG
999 mem_cur_size -= malloc_usable_size(ptr);
1000 #endif
1001 free(ptr);
1004 static void *tcc_malloc(unsigned long size)
1006 void *ptr;
1007 ptr = malloc(size);
1008 if (!ptr && size)
1009 error("memory full");
1010 #ifdef MEM_DEBUG
1011 mem_cur_size += malloc_usable_size(ptr);
1012 if (mem_cur_size > mem_max_size)
1013 mem_max_size = mem_cur_size;
1014 #endif
1015 return ptr;
1018 static void *tcc_mallocz(unsigned long size)
1020 void *ptr;
1021 ptr = tcc_malloc(size);
1022 memset(ptr, 0, size);
1023 return ptr;
1026 static inline void *tcc_realloc(void *ptr, unsigned long size)
1028 void *ptr1;
1029 #ifdef MEM_DEBUG
1030 mem_cur_size -= malloc_usable_size(ptr);
1031 #endif
1032 ptr1 = realloc(ptr, size);
1033 #ifdef MEM_DEBUG
1034 /* NOTE: count not correct if alloc error, but not critical */
1035 mem_cur_size += malloc_usable_size(ptr1);
1036 if (mem_cur_size > mem_max_size)
1037 mem_max_size = mem_cur_size;
1038 #endif
1039 return ptr1;
1042 static char *tcc_strdup(const char *str)
1044 char *ptr;
1045 ptr = tcc_malloc(strlen(str) + 1);
1046 strcpy(ptr, str);
1047 return ptr;
1050 #define free(p) use_tcc_free(p)
1051 #define malloc(s) use_tcc_malloc(s)
1052 #define realloc(p, s) use_tcc_realloc(p, s)
1054 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1056 int nb, nb_alloc;
1057 void **pp;
1059 nb = *nb_ptr;
1060 pp = *ptab;
1061 /* every power of two we double array size */
1062 if ((nb & (nb - 1)) == 0) {
1063 if (!nb)
1064 nb_alloc = 1;
1065 else
1066 nb_alloc = nb * 2;
1067 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1068 if (!pp)
1069 error("memory full");
1070 *ptab = pp;
1072 pp[nb++] = data;
1073 *nb_ptr = nb;
1076 /* symbol allocator */
1077 static Sym *__sym_malloc(void)
1079 Sym *sym_pool, *sym, *last_sym;
1080 int i;
1082 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1084 last_sym = sym_free_first;
1085 sym = sym_pool;
1086 for(i = 0; i < SYM_POOL_NB; i++) {
1087 sym->next = last_sym;
1088 last_sym = sym;
1089 sym++;
1091 sym_free_first = last_sym;
1092 return last_sym;
1095 static inline Sym *sym_malloc(void)
1097 Sym *sym;
1098 sym = sym_free_first;
1099 if (!sym)
1100 sym = __sym_malloc();
1101 sym_free_first = sym->next;
1102 return sym;
1105 static inline void sym_free(Sym *sym)
1107 sym->next = sym_free_first;
1108 sym_free_first = sym;
1111 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1113 Section *sec;
1115 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1116 strcpy(sec->name, name);
1117 sec->sh_type = sh_type;
1118 sec->sh_flags = sh_flags;
1119 switch(sh_type) {
1120 case SHT_HASH:
1121 case SHT_REL:
1122 case SHT_DYNSYM:
1123 case SHT_SYMTAB:
1124 case SHT_DYNAMIC:
1125 sec->sh_addralign = 4;
1126 break;
1127 case SHT_STRTAB:
1128 sec->sh_addralign = 1;
1129 break;
1130 default:
1131 sec->sh_addralign = 32; /* default conservative alignment */
1132 break;
1135 /* only add section if not private */
1136 if (!(sh_flags & SHF_PRIVATE)) {
1137 sec->sh_num = s1->nb_sections;
1138 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1140 return sec;
1143 static void free_section(Section *s)
1145 tcc_free(s->data);
1146 tcc_free(s);
1149 /* realloc section and set its content to zero */
1150 static void section_realloc(Section *sec, unsigned long new_size)
1152 unsigned long size;
1153 unsigned char *data;
1155 size = sec->data_allocated;
1156 if (size == 0)
1157 size = 1;
1158 while (size < new_size)
1159 size = size * 2;
1160 data = tcc_realloc(sec->data, size);
1161 if (!data)
1162 error("memory full");
1163 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1164 sec->data = data;
1165 sec->data_allocated = size;
1168 /* reserve at least 'size' bytes in section 'sec' from
1169 sec->data_offset. */
1170 static void *section_ptr_add(Section *sec, unsigned long size)
1172 unsigned long offset, offset1;
1174 offset = sec->data_offset;
1175 offset1 = offset + size;
1176 if (offset1 > sec->data_allocated)
1177 section_realloc(sec, offset1);
1178 sec->data_offset = offset1;
1179 return sec->data + offset;
1182 /* return a reference to a section, and create it if it does not
1183 exists */
1184 Section *find_section(TCCState *s1, const char *name)
1186 Section *sec;
1187 int i;
1188 for(i = 1; i < s1->nb_sections; i++) {
1189 sec = s1->sections[i];
1190 if (!strcmp(name, sec->name))
1191 return sec;
1193 /* sections are created as PROGBITS */
1194 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1197 #define SECTION_ABS ((void *)1)
1199 /* update sym->c so that it points to an external symbol in section
1200 'section' with value 'value' */
1201 static void put_extern_sym(Sym *sym, Section *section,
1202 unsigned long value, unsigned long size)
1204 int sym_type, sym_bind, sh_num, info;
1205 Elf32_Sym *esym;
1206 const char *name;
1208 if (section == NULL)
1209 sh_num = SHN_UNDEF;
1210 else if (section == SECTION_ABS)
1211 sh_num = SHN_ABS;
1212 else
1213 sh_num = section->sh_num;
1214 if (!sym->c) {
1215 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1216 sym_type = STT_FUNC;
1217 else
1218 sym_type = STT_OBJECT;
1219 if (sym->type.t & VT_STATIC)
1220 sym_bind = STB_LOCAL;
1221 else
1222 sym_bind = STB_GLOBAL;
1224 name = get_tok_str(sym->v, NULL);
1225 #ifdef CONFIG_TCC_BCHECK
1226 if (do_bounds_check) {
1227 char buf[32];
1229 /* XXX: avoid doing that for statics ? */
1230 /* if bound checking is activated, we change some function
1231 names by adding the "__bound" prefix */
1232 switch(sym->v) {
1233 #if 0
1234 /* XXX: we rely only on malloc hooks */
1235 case TOK_malloc:
1236 case TOK_free:
1237 case TOK_realloc:
1238 case TOK_memalign:
1239 case TOK_calloc:
1240 #endif
1241 case TOK_memcpy:
1242 case TOK_memmove:
1243 case TOK_memset:
1244 case TOK_strlen:
1245 case TOK_strcpy:
1246 strcpy(buf, "__bound_");
1247 strcat(buf, name);
1248 name = buf;
1249 break;
1252 #endif
1253 info = ELF32_ST_INFO(sym_bind, sym_type);
1254 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1255 } else {
1256 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1257 esym->st_value = value;
1258 esym->st_size = size;
1259 esym->st_shndx = sh_num;
1263 /* add a new relocation entry to symbol 'sym' in section 's' */
1264 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1266 if (!sym->c)
1267 put_extern_sym(sym, NULL, 0, 0);
1268 /* now we can add ELF relocation info */
1269 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1272 static inline int isid(int c)
1274 return (c >= 'a' && c <= 'z') ||
1275 (c >= 'A' && c <= 'Z') ||
1276 c == '_';
1279 static inline int isnum(int c)
1281 return c >= '0' && c <= '9';
1284 static inline int isoct(int c)
1286 return c >= '0' && c <= '7';
1289 static inline int toup(int c)
1291 if (c >= 'a' && c <= 'z')
1292 return c - 'a' + 'A';
1293 else
1294 return c;
1297 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1299 int len;
1300 len = strlen(buf);
1301 vsnprintf(buf + len, buf_size - len, fmt, ap);
1304 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1306 va_list ap;
1307 va_start(ap, fmt);
1308 strcat_vprintf(buf, buf_size, fmt, ap);
1309 va_end(ap);
1312 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1314 char buf[2048];
1315 BufferedFile **f;
1317 buf[0] = '\0';
1318 if (file) {
1319 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1320 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1321 (*f)->filename, (*f)->line_num);
1322 if (file->line_num > 0) {
1323 strcat_printf(buf, sizeof(buf),
1324 "%s:%d: ", file->filename, file->line_num);
1325 } else {
1326 strcat_printf(buf, sizeof(buf),
1327 "%s: ", file->filename);
1329 } else {
1330 strcat_printf(buf, sizeof(buf),
1331 "tcc: ");
1333 if (is_warning)
1334 strcat_printf(buf, sizeof(buf), "warning: ");
1335 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1337 if (!s1->error_func) {
1338 /* default case: stderr */
1339 fprintf(stderr, "%s\n", buf);
1340 } else {
1341 s1->error_func(s1->error_opaque, buf);
1343 if (!is_warning || s1->warn_error)
1344 s1->nb_errors++;
1347 #ifdef LIBTCC
1348 void tcc_set_error_func(TCCState *s, void *error_opaque,
1349 void (*error_func)(void *opaque, const char *msg))
1351 s->error_opaque = error_opaque;
1352 s->error_func = error_func;
1354 #endif
1356 /* error without aborting current compilation */
1357 void error_noabort(const char *fmt, ...)
1359 TCCState *s1 = tcc_state;
1360 va_list ap;
1362 va_start(ap, fmt);
1363 error1(s1, 0, fmt, ap);
1364 va_end(ap);
1367 void error(const char *fmt, ...)
1369 TCCState *s1 = tcc_state;
1370 va_list ap;
1372 va_start(ap, fmt);
1373 error1(s1, 0, fmt, ap);
1374 va_end(ap);
1375 /* better than nothing: in some cases, we accept to handle errors */
1376 if (s1->error_set_jmp_enabled) {
1377 longjmp(s1->error_jmp_buf, 1);
1378 } else {
1379 /* XXX: eliminate this someday */
1380 exit(1);
1384 void expect(const char *msg)
1386 error("%s expected", msg);
1389 void warning(const char *fmt, ...)
1391 TCCState *s1 = tcc_state;
1392 va_list ap;
1394 if (s1->warn_none)
1395 return;
1397 va_start(ap, fmt);
1398 error1(s1, 1, fmt, ap);
1399 va_end(ap);
1402 void skip(int c)
1404 if (tok != c)
1405 error("'%c' expected", c);
1406 next();
1409 static void test_lvalue(void)
1411 if (!(vtop->r & VT_LVAL))
1412 expect("lvalue");
1415 /* allocate a new token */
1416 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1418 TokenSym *ts, **ptable;
1419 int i;
1421 if (tok_ident >= SYM_FIRST_ANOM)
1422 error("memory full");
1424 /* expand token table if needed */
1425 i = tok_ident - TOK_IDENT;
1426 if ((i % TOK_ALLOC_INCR) == 0) {
1427 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1428 if (!ptable)
1429 error("memory full");
1430 table_ident = ptable;
1433 ts = tcc_malloc(sizeof(TokenSym) + len);
1434 table_ident[i] = ts;
1435 ts->tok = tok_ident++;
1436 ts->sym_define = NULL;
1437 ts->sym_label = NULL;
1438 ts->sym_struct = NULL;
1439 ts->sym_identifier = NULL;
1440 ts->len = len;
1441 ts->hash_next = NULL;
1442 memcpy(ts->str, str, len);
1443 ts->str[len] = '\0';
1444 *pts = ts;
1445 return ts;
1448 #define TOK_HASH_INIT 1
1449 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1451 /* find a token and add it if not found */
1452 static TokenSym *tok_alloc(const char *str, int len)
1454 TokenSym *ts, **pts;
1455 int i;
1456 unsigned int h;
1458 h = TOK_HASH_INIT;
1459 for(i=0;i<len;i++)
1460 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1461 h &= (TOK_HASH_SIZE - 1);
1463 pts = &hash_ident[h];
1464 for(;;) {
1465 ts = *pts;
1466 if (!ts)
1467 break;
1468 if (ts->len == len && !memcmp(ts->str, str, len))
1469 return ts;
1470 pts = &(ts->hash_next);
1472 return tok_alloc_new(pts, str, len);
1475 /* CString handling */
1477 static void cstr_realloc(CString *cstr, int new_size)
1479 int size;
1480 void *data;
1482 size = cstr->size_allocated;
1483 if (size == 0)
1484 size = 8; /* no need to allocate a too small first string */
1485 while (size < new_size)
1486 size = size * 2;
1487 data = tcc_realloc(cstr->data_allocated, size);
1488 if (!data)
1489 error("memory full");
1490 cstr->data_allocated = data;
1491 cstr->size_allocated = size;
1492 cstr->data = data;
1495 /* add a byte */
1496 static inline void cstr_ccat(CString *cstr, int ch)
1498 int size;
1499 size = cstr->size + 1;
1500 if (size > cstr->size_allocated)
1501 cstr_realloc(cstr, size);
1502 ((unsigned char *)cstr->data)[size - 1] = ch;
1503 cstr->size = size;
1506 static void cstr_cat(CString *cstr, const char *str)
1508 int c;
1509 for(;;) {
1510 c = *str;
1511 if (c == '\0')
1512 break;
1513 cstr_ccat(cstr, c);
1514 str++;
1518 /* add a wide char */
1519 static void cstr_wccat(CString *cstr, int ch)
1521 int size;
1522 size = cstr->size + sizeof(int);
1523 if (size > cstr->size_allocated)
1524 cstr_realloc(cstr, size);
1525 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1526 cstr->size = size;
1529 static void cstr_new(CString *cstr)
1531 memset(cstr, 0, sizeof(CString));
1534 /* free string and reset it to NULL */
1535 static void cstr_free(CString *cstr)
1537 tcc_free(cstr->data_allocated);
1538 cstr_new(cstr);
1541 #define cstr_reset(cstr) cstr_free(cstr)
1543 /* XXX: unicode ? */
1544 static void add_char(CString *cstr, int c)
1546 if (c == '\'' || c == '\"' || c == '\\') {
1547 /* XXX: could be more precise if char or string */
1548 cstr_ccat(cstr, '\\');
1550 if (c >= 32 && c <= 126) {
1551 cstr_ccat(cstr, c);
1552 } else {
1553 cstr_ccat(cstr, '\\');
1554 if (c == '\n') {
1555 cstr_ccat(cstr, 'n');
1556 } else {
1557 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1558 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1559 cstr_ccat(cstr, '0' + (c & 7));
1564 /* XXX: buffer overflow */
1565 /* XXX: float tokens */
1566 char *get_tok_str(int v, CValue *cv)
1568 static char buf[STRING_MAX_SIZE + 1];
1569 static CString cstr_buf;
1570 CString *cstr;
1571 unsigned char *q;
1572 char *p;
1573 int i, len;
1575 /* NOTE: to go faster, we give a fixed buffer for small strings */
1576 cstr_reset(&cstr_buf);
1577 cstr_buf.data = buf;
1578 cstr_buf.size_allocated = sizeof(buf);
1579 p = buf;
1581 switch(v) {
1582 case TOK_CINT:
1583 case TOK_CUINT:
1584 /* XXX: not quite exact, but only useful for testing */
1585 sprintf(p, "%u", cv->ui);
1586 break;
1587 case TOK_CLLONG:
1588 case TOK_CULLONG:
1589 /* XXX: not quite exact, but only useful for testing */
1590 sprintf(p, "%Lu", cv->ull);
1591 break;
1592 case TOK_CCHAR:
1593 case TOK_LCHAR:
1594 cstr_ccat(&cstr_buf, '\'');
1595 add_char(&cstr_buf, cv->i);
1596 cstr_ccat(&cstr_buf, '\'');
1597 cstr_ccat(&cstr_buf, '\0');
1598 break;
1599 case TOK_PPNUM:
1600 cstr = cv->cstr;
1601 len = cstr->size - 1;
1602 for(i=0;i<len;i++)
1603 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1604 cstr_ccat(&cstr_buf, '\0');
1605 break;
1606 case TOK_STR:
1607 case TOK_LSTR:
1608 cstr = cv->cstr;
1609 cstr_ccat(&cstr_buf, '\"');
1610 if (v == TOK_STR) {
1611 len = cstr->size - 1;
1612 for(i=0;i<len;i++)
1613 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1614 } else {
1615 len = (cstr->size / sizeof(int)) - 1;
1616 for(i=0;i<len;i++)
1617 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1619 cstr_ccat(&cstr_buf, '\"');
1620 cstr_ccat(&cstr_buf, '\0');
1621 break;
1622 case TOK_LT:
1623 v = '<';
1624 goto addv;
1625 case TOK_GT:
1626 v = '>';
1627 goto addv;
1628 case TOK_A_SHL:
1629 return strcpy(p, "<<=");
1630 case TOK_A_SAR:
1631 return strcpy(p, ">>=");
1632 default:
1633 if (v < TOK_IDENT) {
1634 /* search in two bytes table */
1635 q = tok_two_chars;
1636 while (*q) {
1637 if (q[2] == v) {
1638 *p++ = q[0];
1639 *p++ = q[1];
1640 *p = '\0';
1641 return buf;
1643 q += 3;
1645 addv:
1646 *p++ = v;
1647 *p = '\0';
1648 } else if (v < tok_ident) {
1649 return table_ident[v - TOK_IDENT]->str;
1650 } else if (v >= SYM_FIRST_ANOM) {
1651 /* special name for anonymous symbol */
1652 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1653 } else {
1654 /* should never happen */
1655 return NULL;
1657 break;
1659 return cstr_buf.data;
1662 /* push, without hashing */
1663 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1665 Sym *s;
1666 s = sym_malloc();
1667 s->v = v;
1668 s->type.t = t;
1669 s->c = c;
1670 s->next = NULL;
1671 /* add in stack */
1672 s->prev = *ps;
1673 *ps = s;
1674 return s;
1677 /* find a symbol and return its associated structure. 's' is the top
1678 of the symbol stack */
1679 static Sym *sym_find2(Sym *s, int v)
1681 while (s) {
1682 if (s->v == v)
1683 return s;
1684 s = s->prev;
1686 return NULL;
1689 /* structure lookup */
1690 static inline Sym *struct_find(int v)
1692 v -= TOK_IDENT;
1693 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1694 return NULL;
1695 return table_ident[v]->sym_struct;
1698 /* find an identifier */
1699 static inline Sym *sym_find(int v)
1701 v -= TOK_IDENT;
1702 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1703 return NULL;
1704 return table_ident[v]->sym_identifier;
1707 /* push a given symbol on the symbol stack */
1708 static Sym *sym_push(int v, CType *type, int r, int c)
1710 Sym *s, **ps;
1711 TokenSym *ts;
1713 if (local_stack)
1714 ps = &local_stack;
1715 else
1716 ps = &global_stack;
1717 s = sym_push2(ps, v, type->t, c);
1718 s->type.ref = type->ref;
1719 s->r = r;
1720 /* don't record fields or anonymous symbols */
1721 /* XXX: simplify */
1722 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1723 /* record symbol in token array */
1724 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1725 if (v & SYM_STRUCT)
1726 ps = &ts->sym_struct;
1727 else
1728 ps = &ts->sym_identifier;
1729 s->prev_tok = *ps;
1730 *ps = s;
1732 return s;
1735 /* push a global identifier */
1736 static Sym *global_identifier_push(int v, int t, int c)
1738 Sym *s, **ps;
1739 s = sym_push2(&global_stack, v, t, c);
1740 /* don't record anonymous symbol */
1741 if (v < SYM_FIRST_ANOM) {
1742 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1743 /* modify the top most local identifier, so that
1744 sym_identifier will point to 's' when popped */
1745 while (*ps != NULL)
1746 ps = &(*ps)->prev_tok;
1747 s->prev_tok = NULL;
1748 *ps = s;
1750 return s;
1753 /* pop symbols until top reaches 'b' */
1754 static void sym_pop(Sym **ptop, Sym *b)
1756 Sym *s, *ss, **ps;
1757 TokenSym *ts;
1758 int v;
1760 s = *ptop;
1761 while(s != b) {
1762 ss = s->prev;
1763 v = s->v;
1764 /* remove symbol in token array */
1765 /* XXX: simplify */
1766 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1767 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1768 if (v & SYM_STRUCT)
1769 ps = &ts->sym_struct;
1770 else
1771 ps = &ts->sym_identifier;
1772 *ps = s->prev_tok;
1774 sym_free(s);
1775 s = ss;
1777 *ptop = b;
1780 /* I/O layer */
1782 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1784 int fd;
1785 BufferedFile *bf;
1787 fd = open(filename, O_RDONLY | O_BINARY);
1788 if (fd < 0)
1789 return NULL;
1790 bf = tcc_malloc(sizeof(BufferedFile));
1791 if (!bf) {
1792 close(fd);
1793 return NULL;
1795 bf->fd = fd;
1796 bf->buf_ptr = bf->buffer;
1797 bf->buf_end = bf->buffer;
1798 bf->buffer[0] = CH_EOB; /* put eob symbol */
1799 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1800 bf->line_num = 1;
1801 bf->ifndef_macro = 0;
1802 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1803 // printf("opening '%s'\n", filename);
1804 return bf;
1807 void tcc_close(BufferedFile *bf)
1809 total_lines += bf->line_num;
1810 close(bf->fd);
1811 tcc_free(bf);
1814 /* fill input buffer and peek next char */
1815 static int tcc_peekc_slow(BufferedFile *bf)
1817 int len;
1818 /* only tries to read if really end of buffer */
1819 if (bf->buf_ptr >= bf->buf_end) {
1820 if (bf->fd != -1) {
1821 #if defined(PARSE_DEBUG)
1822 len = 8;
1823 #else
1824 len = IO_BUF_SIZE;
1825 #endif
1826 len = read(bf->fd, bf->buffer, len);
1827 if (len < 0)
1828 len = 0;
1829 } else {
1830 len = 0;
1832 total_bytes += len;
1833 bf->buf_ptr = bf->buffer;
1834 bf->buf_end = bf->buffer + len;
1835 *bf->buf_end = CH_EOB;
1837 if (bf->buf_ptr < bf->buf_end) {
1838 return bf->buf_ptr[0];
1839 } else {
1840 bf->buf_ptr = bf->buf_end;
1841 return CH_EOF;
1845 /* return the current character, handling end of block if necessary
1846 (but not stray) */
1847 static int handle_eob(void)
1849 return tcc_peekc_slow(file);
1852 /* read next char from current input file and handle end of input buffer */
1853 static inline void inp(void)
1855 ch = *(++(file->buf_ptr));
1856 /* end of buffer/file handling */
1857 if (ch == CH_EOB)
1858 ch = handle_eob();
1861 /* handle '\[\r]\n' */
1862 static void handle_stray(void)
1864 while (ch == '\\') {
1865 inp();
1866 if (ch == '\n') {
1867 file->line_num++;
1868 inp();
1869 } else if (ch == '\r') {
1870 inp();
1871 if (ch != '\n')
1872 goto fail;
1873 file->line_num++;
1874 inp();
1875 } else {
1876 fail:
1877 error("stray '\\' in program");
1882 /* skip the stray and handle the \\n case. Output an error if
1883 incorrect char after the stray */
1884 static int handle_stray1(uint8_t *p)
1886 int c;
1888 if (p >= file->buf_end) {
1889 file->buf_ptr = p;
1890 c = handle_eob();
1891 p = file->buf_ptr;
1892 if (c == '\\')
1893 goto parse_stray;
1894 } else {
1895 parse_stray:
1896 file->buf_ptr = p;
1897 ch = *p;
1898 handle_stray();
1899 p = file->buf_ptr;
1900 c = *p;
1902 return c;
1905 /* handle just the EOB case, but not stray */
1906 #define PEEKC_EOB(c, p)\
1908 p++;\
1909 c = *p;\
1910 if (c == '\\') {\
1911 file->buf_ptr = p;\
1912 c = handle_eob();\
1913 p = file->buf_ptr;\
1917 /* handle the complicated stray case */
1918 #define PEEKC(c, p)\
1920 p++;\
1921 c = *p;\
1922 if (c == '\\') {\
1923 c = handle_stray1(p);\
1924 p = file->buf_ptr;\
1928 /* input with '\[\r]\n' handling. Note that this function cannot
1929 handle other characters after '\', so you cannot call it inside
1930 strings or comments */
1931 static void minp(void)
1933 inp();
1934 if (ch == '\\')
1935 handle_stray();
1939 /* single line C++ comments */
1940 static uint8_t *parse_line_comment(uint8_t *p)
1942 int c;
1944 p++;
1945 for(;;) {
1946 c = *p;
1947 redo:
1948 if (c == '\n' || c == CH_EOF) {
1949 break;
1950 } else if (c == '\\') {
1951 file->buf_ptr = p;
1952 c = handle_eob();
1953 p = file->buf_ptr;
1954 if (c == '\\') {
1955 PEEKC_EOB(c, p);
1956 if (c == '\n') {
1957 file->line_num++;
1958 PEEKC_EOB(c, p);
1959 } else if (c == '\r') {
1960 PEEKC_EOB(c, p);
1961 if (c == '\n') {
1962 file->line_num++;
1963 PEEKC_EOB(c, p);
1966 } else {
1967 goto redo;
1969 } else {
1970 p++;
1973 return p;
1976 /* C comments */
1977 static uint8_t *parse_comment(uint8_t *p)
1979 int c;
1981 p++;
1982 for(;;) {
1983 /* fast skip loop */
1984 for(;;) {
1985 c = *p;
1986 if (c == '\n' || c == '*' || c == '\\')
1987 break;
1988 p++;
1989 c = *p;
1990 if (c == '\n' || c == '*' || c == '\\')
1991 break;
1992 p++;
1994 /* now we can handle all the cases */
1995 if (c == '\n') {
1996 file->line_num++;
1997 p++;
1998 } else if (c == '*') {
1999 p++;
2000 for(;;) {
2001 c = *p;
2002 if (c == '*') {
2003 p++;
2004 } else if (c == '/') {
2005 goto end_of_comment;
2006 } else if (c == '\\') {
2007 file->buf_ptr = p;
2008 c = handle_eob();
2009 p = file->buf_ptr;
2010 if (c == '\\') {
2011 /* skip '\[\r]\n', otherwise just skip the stray */
2012 while (c == '\\') {
2013 PEEKC_EOB(c, p);
2014 if (c == '\n') {
2015 file->line_num++;
2016 PEEKC_EOB(c, p);
2017 } else if (c == '\r') {
2018 PEEKC_EOB(c, p);
2019 if (c == '\n') {
2020 file->line_num++;
2021 PEEKC_EOB(c, p);
2023 } else {
2024 goto after_star;
2028 } else {
2029 break;
2032 after_star: ;
2033 } else {
2034 /* stray, eob or eof */
2035 file->buf_ptr = p;
2036 c = handle_eob();
2037 p = file->buf_ptr;
2038 if (c == CH_EOF) {
2039 error("unexpected end of file in comment");
2040 } else if (c == '\\') {
2041 p++;
2045 end_of_comment:
2046 p++;
2047 return p;
2050 #define cinp minp
2052 /* space exlcuding newline */
2053 static inline int is_space(int ch)
2055 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2058 static inline void skip_spaces(void)
2060 while (is_space(ch))
2061 cinp();
2064 /* parse a string without interpreting escapes */
2065 static uint8_t *parse_pp_string(uint8_t *p,
2066 int sep, CString *str)
2068 int c;
2069 p++;
2070 for(;;) {
2071 c = *p;
2072 if (c == sep) {
2073 break;
2074 } else if (c == '\\') {
2075 file->buf_ptr = p;
2076 c = handle_eob();
2077 p = file->buf_ptr;
2078 if (c == CH_EOF) {
2079 unterminated_string:
2080 /* XXX: indicate line number of start of string */
2081 error("missing terminating %c character", sep);
2082 } else if (c == '\\') {
2083 /* escape : just skip \[\r]\n */
2084 PEEKC_EOB(c, p);
2085 if (c == '\n') {
2086 file->line_num++;
2087 p++;
2088 } else if (c == '\r') {
2089 PEEKC_EOB(c, p);
2090 if (c != '\n')
2091 expect("'\n' after '\r'");
2092 file->line_num++;
2093 p++;
2094 } else if (c == CH_EOF) {
2095 goto unterminated_string;
2096 } else {
2097 if (str) {
2098 cstr_ccat(str, '\\');
2099 cstr_ccat(str, c);
2101 p++;
2104 } else if (c == '\n') {
2105 file->line_num++;
2106 goto add_char;
2107 } else if (c == '\r') {
2108 PEEKC_EOB(c, p);
2109 if (c != '\n') {
2110 if (str)
2111 cstr_ccat(str, '\r');
2112 } else {
2113 file->line_num++;
2114 goto add_char;
2116 } else {
2117 add_char:
2118 if (str)
2119 cstr_ccat(str, c);
2120 p++;
2123 p++;
2124 return p;
2127 /* skip block of text until #else, #elif or #endif. skip also pairs of
2128 #if/#endif */
2129 void preprocess_skip(void)
2131 int a, start_of_line, c;
2132 uint8_t *p;
2134 p = file->buf_ptr;
2135 start_of_line = 1;
2136 a = 0;
2137 for(;;) {
2138 redo_no_start:
2139 c = *p;
2140 switch(c) {
2141 case ' ':
2142 case '\t':
2143 case '\f':
2144 case '\v':
2145 case '\r':
2146 p++;
2147 goto redo_no_start;
2148 case '\n':
2149 start_of_line = 1;
2150 file->line_num++;
2151 p++;
2152 goto redo_no_start;
2153 case '\\':
2154 file->buf_ptr = p;
2155 c = handle_eob();
2156 if (c == CH_EOF) {
2157 expect("#endif");
2158 } else if (c == '\\') {
2159 /* XXX: incorrect: should not give an error */
2160 ch = file->buf_ptr[0];
2161 handle_stray();
2163 p = file->buf_ptr;
2164 goto redo_no_start;
2165 /* skip strings */
2166 case '\"':
2167 case '\'':
2168 p = parse_pp_string(p, c, NULL);
2169 break;
2170 /* skip comments */
2171 case '/':
2172 file->buf_ptr = p;
2173 ch = *p;
2174 minp();
2175 p = file->buf_ptr;
2176 if (ch == '*') {
2177 p = parse_comment(p);
2178 } else if (ch == '/') {
2179 p = parse_line_comment(p);
2181 break;
2183 case '#':
2184 p++;
2185 if (start_of_line) {
2186 file->buf_ptr = p;
2187 next_nomacro();
2188 p = file->buf_ptr;
2189 if (a == 0 &&
2190 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2191 goto the_end;
2192 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2193 a++;
2194 else if (tok == TOK_ENDIF)
2195 a--;
2197 break;
2198 default:
2199 p++;
2200 break;
2202 start_of_line = 0;
2204 the_end: ;
2205 file->buf_ptr = p;
2208 /* ParseState handling */
2210 /* XXX: currently, no include file info is stored. Thus, we cannot display
2211 accurate messages if the function or data definition spans multiple
2212 files */
2214 /* save current parse state in 's' */
2215 void save_parse_state(ParseState *s)
2217 s->line_num = file->line_num;
2218 s->macro_ptr = macro_ptr;
2219 s->tok = tok;
2220 s->tokc = tokc;
2223 /* restore parse state from 's' */
2224 void restore_parse_state(ParseState *s)
2226 file->line_num = s->line_num;
2227 macro_ptr = s->macro_ptr;
2228 tok = s->tok;
2229 tokc = s->tokc;
2232 /* return the number of additional 'ints' necessary to store the
2233 token */
2234 static inline int tok_ext_size(int t)
2236 switch(t) {
2237 /* 4 bytes */
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 return 1;
2245 case TOK_STR:
2246 case TOK_LSTR:
2247 case TOK_PPNUM:
2248 error("unsupported token");
2249 return 1;
2250 case TOK_CDOUBLE:
2251 case TOK_CLLONG:
2252 case TOK_CULLONG:
2253 return 2;
2254 case TOK_CLDOUBLE:
2255 return LDOUBLE_SIZE / 4;
2256 default:
2257 return 0;
2261 /* token string handling */
2263 static inline void tok_str_new(TokenString *s)
2265 s->str = NULL;
2266 s->len = 0;
2267 s->allocated_len = 0;
2268 s->last_line_num = -1;
2271 static void tok_str_free(int *str)
2273 tcc_free(str);
2276 static int *tok_str_realloc(TokenString *s)
2278 int *str, len;
2280 if (s->allocated_len == 0) {
2281 len = 8;
2282 } else {
2283 len = s->allocated_len * 2;
2285 str = tcc_realloc(s->str, len * sizeof(int));
2286 if (!str)
2287 error("memory full");
2288 s->allocated_len = len;
2289 s->str = str;
2290 return str;
2293 static void tok_str_add(TokenString *s, int t)
2295 int len, *str;
2297 len = s->len;
2298 str = s->str;
2299 if (len >= s->allocated_len)
2300 str = tok_str_realloc(s);
2301 str[len++] = t;
2302 s->len = len;
2305 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2307 int len, *str;
2309 len = s->len;
2310 str = s->str;
2312 /* allocate space for worst case */
2313 if (len + TOK_MAX_SIZE > s->allocated_len)
2314 str = tok_str_realloc(s);
2315 str[len++] = t;
2316 switch(t) {
2317 case TOK_CINT:
2318 case TOK_CUINT:
2319 case TOK_CCHAR:
2320 case TOK_LCHAR:
2321 case TOK_CFLOAT:
2322 case TOK_LINENUM:
2323 str[len++] = cv->tab[0];
2324 break;
2325 case TOK_PPNUM:
2326 case TOK_STR:
2327 case TOK_LSTR:
2329 int nb_words;
2330 CString *cstr;
2332 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2333 while ((len + nb_words) > s->allocated_len)
2334 str = tok_str_realloc(s);
2335 cstr = (CString *)(str + len);
2336 cstr->data = NULL;
2337 cstr->size = cv->cstr->size;
2338 cstr->data_allocated = NULL;
2339 cstr->size_allocated = cstr->size;
2340 memcpy((char *)cstr + sizeof(CString),
2341 cv->cstr->data, cstr->size);
2342 len += nb_words;
2344 break;
2345 case TOK_CDOUBLE:
2346 case TOK_CLLONG:
2347 case TOK_CULLONG:
2348 #if LDOUBLE_SIZE == 8
2349 case TOK_CLDOUBLE:
2350 #endif
2351 str[len++] = cv->tab[0];
2352 str[len++] = cv->tab[1];
2353 break;
2354 #if LDOUBLE_SIZE == 12
2355 case TOK_CLDOUBLE:
2356 str[len++] = cv->tab[0];
2357 str[len++] = cv->tab[1];
2358 str[len++] = cv->tab[2];
2359 #elif LDOUBLE_SIZE != 8
2360 #error add long double size support
2361 #endif
2362 break;
2363 default:
2364 break;
2366 s->len = len;
2369 /* add the current parse token in token string 's' */
2370 static void tok_str_add_tok(TokenString *s)
2372 CValue cval;
2374 /* save line number info */
2375 if (file->line_num != s->last_line_num) {
2376 s->last_line_num = file->line_num;
2377 cval.i = s->last_line_num;
2378 tok_str_add2(s, TOK_LINENUM, &cval);
2380 tok_str_add2(s, tok, &tokc);
2383 #if LDOUBLE_SIZE == 12
2384 #define LDOUBLE_GET(p, cv) \
2385 cv.tab[0] = p[0]; \
2386 cv.tab[1] = p[1]; \
2387 cv.tab[2] = p[2];
2388 #elif LDOUBLE_SIZE == 8
2389 #define LDOUBLE_GET(p, cv) \
2390 cv.tab[0] = p[0]; \
2391 cv.tab[1] = p[1];
2392 #else
2393 #error add long double size support
2394 #endif
2397 /* get a token from an integer array and increment pointer
2398 accordingly. we code it as a macro to avoid pointer aliasing. */
2399 #define TOK_GET(t, p, cv) \
2401 t = *p++; \
2402 switch(t) { \
2403 case TOK_CINT: \
2404 case TOK_CUINT: \
2405 case TOK_CCHAR: \
2406 case TOK_LCHAR: \
2407 case TOK_CFLOAT: \
2408 case TOK_LINENUM: \
2409 cv.tab[0] = *p++; \
2410 break; \
2411 case TOK_STR: \
2412 case TOK_LSTR: \
2413 case TOK_PPNUM: \
2414 cv.cstr = (CString *)p; \
2415 cv.cstr->data = (char *)p + sizeof(CString);\
2416 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2417 break; \
2418 case TOK_CDOUBLE: \
2419 case TOK_CLLONG: \
2420 case TOK_CULLONG: \
2421 cv.tab[0] = p[0]; \
2422 cv.tab[1] = p[1]; \
2423 p += 2; \
2424 break; \
2425 case TOK_CLDOUBLE: \
2426 LDOUBLE_GET(p, cv); \
2427 p += LDOUBLE_SIZE / 4; \
2428 break; \
2429 default: \
2430 break; \
2434 /* defines handling */
2435 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2437 Sym *s;
2439 s = sym_push2(&define_stack, v, macro_type, (int)str);
2440 s->next = first_arg;
2441 table_ident[v - TOK_IDENT]->sym_define = s;
2444 /* undefined a define symbol. Its name is just set to zero */
2445 static void define_undef(Sym *s)
2447 int v;
2448 v = s->v;
2449 if (v >= TOK_IDENT && v < tok_ident)
2450 table_ident[v - TOK_IDENT]->sym_define = NULL;
2451 s->v = 0;
2454 static inline Sym *define_find(int v)
2456 v -= TOK_IDENT;
2457 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2458 return NULL;
2459 return table_ident[v]->sym_define;
2462 /* free define stack until top reaches 'b' */
2463 static void free_defines(Sym *b)
2465 Sym *top, *top1;
2466 int v;
2468 top = define_stack;
2469 while (top != b) {
2470 top1 = top->prev;
2471 /* do not free args or predefined defines */
2472 if (top->c)
2473 tok_str_free((int *)top->c);
2474 v = top->v;
2475 if (v >= TOK_IDENT && v < tok_ident)
2476 table_ident[v - TOK_IDENT]->sym_define = NULL;
2477 sym_free(top);
2478 top = top1;
2480 define_stack = b;
2483 /* label lookup */
2484 static Sym *label_find(int v)
2486 v -= TOK_IDENT;
2487 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2488 return NULL;
2489 return table_ident[v]->sym_label;
2492 static Sym *label_push(Sym **ptop, int v, int flags)
2494 Sym *s, **ps;
2495 s = sym_push2(ptop, v, 0, 0);
2496 s->r = flags;
2497 ps = &table_ident[v - TOK_IDENT]->sym_label;
2498 if (ptop == &global_label_stack) {
2499 /* modify the top most local identifier, so that
2500 sym_identifier will point to 's' when popped */
2501 while (*ps != NULL)
2502 ps = &(*ps)->prev_tok;
2504 s->prev_tok = *ps;
2505 *ps = s;
2506 return s;
2509 /* pop labels until element last is reached. Look if any labels are
2510 undefined. Define symbols if '&&label' was used. */
2511 static void label_pop(Sym **ptop, Sym *slast)
2513 Sym *s, *s1;
2514 for(s = *ptop; s != slast; s = s1) {
2515 s1 = s->prev;
2516 if (s->r == LABEL_DECLARED) {
2517 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2518 } else if (s->r == LABEL_FORWARD) {
2519 error("label '%s' used but not defined",
2520 get_tok_str(s->v, NULL));
2521 } else {
2522 if (s->c) {
2523 /* define corresponding symbol. A size of
2524 1 is put. */
2525 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2528 /* remove label */
2529 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2530 sym_free(s);
2532 *ptop = slast;
2535 /* eval an expression for #if/#elif */
2536 static int expr_preprocess(void)
2538 int c, t;
2539 TokenString str;
2541 tok_str_new(&str);
2542 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2543 next(); /* do macro subst */
2544 if (tok == TOK_DEFINED) {
2545 next_nomacro();
2546 t = tok;
2547 if (t == '(')
2548 next_nomacro();
2549 c = define_find(tok) != 0;
2550 if (t == '(')
2551 next_nomacro();
2552 tok = TOK_CINT;
2553 tokc.i = c;
2554 } else if (tok >= TOK_IDENT) {
2555 /* if undefined macro */
2556 tok = TOK_CINT;
2557 tokc.i = 0;
2559 tok_str_add_tok(&str);
2561 tok_str_add(&str, -1); /* simulate end of file */
2562 tok_str_add(&str, 0);
2563 /* now evaluate C constant expression */
2564 macro_ptr = str.str;
2565 next();
2566 c = expr_const();
2567 macro_ptr = NULL;
2568 tok_str_free(str.str);
2569 return c != 0;
2572 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2573 static void tok_print(int *str)
2575 int t;
2576 CValue cval;
2578 while (1) {
2579 TOK_GET(t, str, cval);
2580 if (!t)
2581 break;
2582 printf(" %s", get_tok_str(t, &cval));
2584 printf("\n");
2586 #endif
2588 /* parse after #define */
2589 static void parse_define(void)
2591 Sym *s, *first, **ps;
2592 int v, t, varg, is_vaargs, c;
2593 TokenString str;
2595 v = tok;
2596 if (v < TOK_IDENT)
2597 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2598 /* XXX: should check if same macro (ANSI) */
2599 first = NULL;
2600 t = MACRO_OBJ;
2601 /* '(' must be just after macro definition for MACRO_FUNC */
2602 c = file->buf_ptr[0];
2603 if (c == '\\')
2604 c = handle_stray1(file->buf_ptr);
2605 if (c == '(') {
2606 next_nomacro();
2607 next_nomacro();
2608 ps = &first;
2609 while (tok != ')') {
2610 varg = tok;
2611 next_nomacro();
2612 is_vaargs = 0;
2613 if (varg == TOK_DOTS) {
2614 varg = TOK___VA_ARGS__;
2615 is_vaargs = 1;
2616 } else if (tok == TOK_DOTS && gnu_ext) {
2617 is_vaargs = 1;
2618 next_nomacro();
2620 if (varg < TOK_IDENT)
2621 error("badly punctuated parameter list");
2622 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2623 *ps = s;
2624 ps = &s->next;
2625 if (tok != ',')
2626 break;
2627 next_nomacro();
2629 t = MACRO_FUNC;
2631 tok_str_new(&str);
2632 next_nomacro();
2633 /* EOF testing necessary for '-D' handling */
2634 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2635 tok_str_add2(&str, tok, &tokc);
2636 next_nomacro();
2638 tok_str_add(&str, 0);
2639 #ifdef PP_DEBUG
2640 printf("define %s %d: ", get_tok_str(v, NULL), t);
2641 tok_print(str.str);
2642 #endif
2643 define_push(v, t, str.str, first);
2646 static inline int hash_cached_include(int type, const char *filename)
2648 const unsigned char *s;
2649 unsigned int h;
2651 h = TOK_HASH_INIT;
2652 h = TOK_HASH_FUNC(h, type);
2653 s = filename;
2654 while (*s) {
2655 h = TOK_HASH_FUNC(h, *s);
2656 s++;
2658 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2659 return h;
2662 /* XXX: use a token or a hash table to accelerate matching ? */
2663 static CachedInclude *search_cached_include(TCCState *s1,
2664 int type, const char *filename)
2666 CachedInclude *e;
2667 int i, h;
2668 h = hash_cached_include(type, filename);
2669 i = s1->cached_includes_hash[h];
2670 for(;;) {
2671 if (i == 0)
2672 break;
2673 e = s1->cached_includes[i - 1];
2674 if (e->type == type && !strcmp(e->filename, filename))
2675 return e;
2676 i = e->hash_next;
2678 return NULL;
2681 static inline void add_cached_include(TCCState *s1, int type,
2682 const char *filename, int ifndef_macro)
2684 CachedInclude *e;
2685 int h;
2687 if (search_cached_include(s1, type, filename))
2688 return;
2689 #ifdef INC_DEBUG
2690 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2691 #endif
2692 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2693 if (!e)
2694 return;
2695 e->type = type;
2696 strcpy(e->filename, filename);
2697 e->ifndef_macro = ifndef_macro;
2698 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2699 /* add in hash table */
2700 h = hash_cached_include(type, filename);
2701 e->hash_next = s1->cached_includes_hash[h];
2702 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2705 /* is_bof is true if first non space token at beginning of file */
2706 static void preprocess(int is_bof)
2708 TCCState *s1 = tcc_state;
2709 int size, i, c, n, saved_parse_flags;
2710 char buf[1024], *q, *p;
2711 char buf1[1024];
2712 BufferedFile *f;
2713 Sym *s;
2714 CachedInclude *e;
2716 saved_parse_flags = parse_flags;
2717 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2718 PARSE_FLAG_LINEFEED;
2719 next_nomacro();
2720 redo:
2721 switch(tok) {
2722 case TOK_DEFINE:
2723 next_nomacro();
2724 parse_define();
2725 break;
2726 case TOK_UNDEF:
2727 next_nomacro();
2728 s = define_find(tok);
2729 /* undefine symbol by putting an invalid name */
2730 if (s)
2731 define_undef(s);
2732 break;
2733 case TOK_INCLUDE:
2734 case TOK_INCLUDE_NEXT:
2735 ch = file->buf_ptr[0];
2736 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2737 skip_spaces();
2738 if (ch == '<') {
2739 c = '>';
2740 goto read_name;
2741 } else if (ch == '\"') {
2742 c = ch;
2743 read_name:
2744 /* XXX: better stray handling */
2745 minp();
2746 q = buf;
2747 while (ch != c && ch != '\n' && ch != CH_EOF) {
2748 if ((q - buf) < sizeof(buf) - 1)
2749 *q++ = ch;
2750 minp();
2752 *q = '\0';
2753 minp();
2754 #if 0
2755 /* eat all spaces and comments after include */
2756 /* XXX: slightly incorrect */
2757 while (ch1 != '\n' && ch1 != CH_EOF)
2758 inp();
2759 #endif
2760 } else {
2761 /* computed #include : either we have only strings or
2762 we have anything enclosed in '<>' */
2763 next();
2764 buf[0] = '\0';
2765 if (tok == TOK_STR) {
2766 while (tok != TOK_LINEFEED) {
2767 if (tok != TOK_STR) {
2768 include_syntax:
2769 error("'#include' expects \"FILENAME\" or <FILENAME>");
2771 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2772 next();
2774 c = '\"';
2775 } else {
2776 int len;
2777 while (tok != TOK_LINEFEED) {
2778 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2779 next();
2781 len = strlen(buf);
2782 /* check syntax and remove '<>' */
2783 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2784 goto include_syntax;
2785 memmove(buf, buf + 1, len - 2);
2786 buf[len - 2] = '\0';
2787 c = '>';
2791 e = search_cached_include(s1, c, buf);
2792 if (e && define_find(e->ifndef_macro)) {
2793 /* no need to parse the include because the 'ifndef macro'
2794 is defined */
2795 #ifdef INC_DEBUG
2796 printf("%s: skipping %s\n", file->filename, buf);
2797 #endif
2798 } else {
2799 if (c == '\"') {
2800 /* first search in current dir if "header.h" */
2801 size = 0;
2802 p = strrchr(file->filename, '/');
2803 if (p)
2804 size = p + 1 - file->filename;
2805 if (size > sizeof(buf1) - 1)
2806 size = sizeof(buf1) - 1;
2807 memcpy(buf1, file->filename, size);
2808 buf1[size] = '\0';
2809 pstrcat(buf1, sizeof(buf1), buf);
2810 f = tcc_open(s1, buf1);
2811 if (f) {
2812 if (tok == TOK_INCLUDE_NEXT)
2813 tok = TOK_INCLUDE;
2814 else
2815 goto found;
2818 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2819 error("#include recursion too deep");
2820 /* now search in all the include paths */
2821 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2822 for(i = 0; i < n; i++) {
2823 const char *path;
2824 if (i < s1->nb_include_paths)
2825 path = s1->include_paths[i];
2826 else
2827 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2828 pstrcpy(buf1, sizeof(buf1), path);
2829 pstrcat(buf1, sizeof(buf1), "/");
2830 pstrcat(buf1, sizeof(buf1), buf);
2831 f = tcc_open(s1, buf1);
2832 if (f) {
2833 if (tok == TOK_INCLUDE_NEXT)
2834 tok = TOK_INCLUDE;
2835 else
2836 goto found;
2839 error("include file '%s' not found", buf);
2840 f = NULL;
2841 found:
2842 #ifdef INC_DEBUG
2843 printf("%s: including %s\n", file->filename, buf1);
2844 #endif
2845 f->inc_type = c;
2846 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2847 /* push current file in stack */
2848 /* XXX: fix current line init */
2849 *s1->include_stack_ptr++ = file;
2850 file = f;
2851 /* add include file debug info */
2852 if (do_debug) {
2853 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2855 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2856 ch = file->buf_ptr[0];
2857 goto the_end;
2859 break;
2860 case TOK_IFNDEF:
2861 c = 1;
2862 goto do_ifdef;
2863 case TOK_IF:
2864 c = expr_preprocess();
2865 goto do_if;
2866 case TOK_IFDEF:
2867 c = 0;
2868 do_ifdef:
2869 next_nomacro();
2870 if (tok < TOK_IDENT)
2871 error("invalid argument for '#if%sdef'", c ? "n" : "");
2872 if (is_bof) {
2873 if (c) {
2874 #ifdef INC_DEBUG
2875 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2876 #endif
2877 file->ifndef_macro = tok;
2880 c = (define_find(tok) != 0) ^ c;
2881 do_if:
2882 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2883 error("memory full");
2884 *s1->ifdef_stack_ptr++ = c;
2885 goto test_skip;
2886 case TOK_ELSE:
2887 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2888 error("#else without matching #if");
2889 if (s1->ifdef_stack_ptr[-1] & 2)
2890 error("#else after #else");
2891 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2892 goto test_skip;
2893 case TOK_ELIF:
2894 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2895 error("#elif without matching #if");
2896 c = s1->ifdef_stack_ptr[-1];
2897 if (c > 1)
2898 error("#elif after #else");
2899 /* last #if/#elif expression was true: we skip */
2900 if (c == 1)
2901 goto skip;
2902 c = expr_preprocess();
2903 s1->ifdef_stack_ptr[-1] = c;
2904 test_skip:
2905 if (!(c & 1)) {
2906 skip:
2907 preprocess_skip();
2908 is_bof = 0;
2909 goto redo;
2911 break;
2912 case TOK_ENDIF:
2913 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2914 error("#endif without matching #if");
2915 s1->ifdef_stack_ptr--;
2916 /* '#ifndef macro' was at the start of file. Now we check if
2917 an '#endif' is exactly at the end of file */
2918 if (file->ifndef_macro &&
2919 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2920 file->ifndef_macro_saved = file->ifndef_macro;
2921 /* need to set to zero to avoid false matches if another
2922 #ifndef at middle of file */
2923 file->ifndef_macro = 0;
2924 while (tok != TOK_LINEFEED)
2925 next_nomacro();
2926 tok_flags |= TOK_FLAG_ENDIF;
2927 goto the_end;
2929 break;
2930 case TOK_LINE:
2931 next();
2932 if (tok != TOK_CINT)
2933 error("#line");
2934 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2935 next();
2936 if (tok != TOK_LINEFEED) {
2937 if (tok != TOK_STR)
2938 error("#line");
2939 pstrcpy(file->filename, sizeof(file->filename),
2940 (char *)tokc.cstr->data);
2942 break;
2943 case TOK_ERROR:
2944 case TOK_WARNING:
2945 c = tok;
2946 ch = file->buf_ptr[0];
2947 skip_spaces();
2948 q = buf;
2949 while (ch != '\n' && ch != CH_EOF) {
2950 if ((q - buf) < sizeof(buf) - 1)
2951 *q++ = ch;
2952 minp();
2954 *q = '\0';
2955 if (c == TOK_ERROR)
2956 error("#error %s", buf);
2957 else
2958 warning("#warning %s", buf);
2959 break;
2960 case TOK_PRAGMA:
2961 /* ignored */
2962 break;
2963 default:
2964 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2965 /* '!' is ignored to allow C scripts. numbers are ignored
2966 to emulate cpp behaviour */
2967 } else {
2968 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
2969 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2971 break;
2973 /* ignore other preprocess commands or #! for C scripts */
2974 while (tok != TOK_LINEFEED)
2975 next_nomacro();
2976 the_end:
2977 parse_flags = saved_parse_flags;
2980 /* evaluate escape codes in a string. */
2981 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2983 int c, n;
2984 const uint8_t *p;
2986 p = buf;
2987 for(;;) {
2988 c = *p;
2989 if (c == '\0')
2990 break;
2991 if (c == '\\') {
2992 p++;
2993 /* escape */
2994 c = *p;
2995 switch(c) {
2996 case '0': case '1': case '2': case '3':
2997 case '4': case '5': case '6': case '7':
2998 /* at most three octal digits */
2999 n = c - '0';
3000 p++;
3001 c = *p;
3002 if (isoct(c)) {
3003 n = n * 8 + c - '0';
3004 p++;
3005 c = *p;
3006 if (isoct(c)) {
3007 n = n * 8 + c - '0';
3008 p++;
3011 c = n;
3012 goto add_char_nonext;
3013 case 'x':
3014 p++;
3015 n = 0;
3016 for(;;) {
3017 c = *p;
3018 if (c >= 'a' && c <= 'f')
3019 c = c - 'a' + 10;
3020 else if (c >= 'A' && c <= 'F')
3021 c = c - 'A' + 10;
3022 else if (isnum(c))
3023 c = c - '0';
3024 else
3025 break;
3026 n = n * 16 + c;
3027 p++;
3029 c = n;
3030 goto add_char_nonext;
3031 case 'a':
3032 c = '\a';
3033 break;
3034 case 'b':
3035 c = '\b';
3036 break;
3037 case 'f':
3038 c = '\f';
3039 break;
3040 case 'n':
3041 c = '\n';
3042 break;
3043 case 'r':
3044 c = '\r';
3045 break;
3046 case 't':
3047 c = '\t';
3048 break;
3049 case 'v':
3050 c = '\v';
3051 break;
3052 case 'e':
3053 if (!gnu_ext)
3054 goto invalid_escape;
3055 c = 27;
3056 break;
3057 case '\'':
3058 case '\"':
3059 case '\\':
3060 case '?':
3061 break;
3062 default:
3063 invalid_escape:
3064 if (c >= '!' && c <= '~')
3065 warning("unknown escape sequence: \'\\%c\'", c);
3066 else
3067 warning("unknown escape sequence: \'\\x%x\'", c);
3068 break;
3071 p++;
3072 add_char_nonext:
3073 if (!is_long)
3074 cstr_ccat(outstr, c);
3075 else
3076 cstr_wccat(outstr, c);
3078 /* add a trailing '\0' */
3079 if (!is_long)
3080 cstr_ccat(outstr, '\0');
3081 else
3082 cstr_wccat(outstr, '\0');
3085 /* we use 64 bit numbers */
3086 #define BN_SIZE 2
3088 /* bn = (bn << shift) | or_val */
3089 void bn_lshift(unsigned int *bn, int shift, int or_val)
3091 int i;
3092 unsigned int v;
3093 for(i=0;i<BN_SIZE;i++) {
3094 v = bn[i];
3095 bn[i] = (v << shift) | or_val;
3096 or_val = v >> (32 - shift);
3100 void bn_zero(unsigned int *bn)
3102 int i;
3103 for(i=0;i<BN_SIZE;i++) {
3104 bn[i] = 0;
3108 /* parse number in null terminated string 'p' and return it in the
3109 current token */
3110 void parse_number(const char *p)
3112 int b, t, shift, frac_bits, s, exp_val, ch;
3113 char *q;
3114 unsigned int bn[BN_SIZE];
3115 double d;
3117 /* number */
3118 q = token_buf;
3119 ch = *p++;
3120 t = ch;
3121 ch = *p++;
3122 *q++ = t;
3123 b = 10;
3124 if (t == '.') {
3125 goto float_frac_parse;
3126 } else if (t == '0') {
3127 if (ch == 'x' || ch == 'X') {
3128 q--;
3129 ch = *p++;
3130 b = 16;
3131 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3132 q--;
3133 ch = *p++;
3134 b = 2;
3137 /* parse all digits. cannot check octal numbers at this stage
3138 because of floating point constants */
3139 while (1) {
3140 if (ch >= 'a' && ch <= 'f')
3141 t = ch - 'a' + 10;
3142 else if (ch >= 'A' && ch <= 'F')
3143 t = ch - 'A' + 10;
3144 else if (isnum(ch))
3145 t = ch - '0';
3146 else
3147 break;
3148 if (t >= b)
3149 break;
3150 if (q >= token_buf + STRING_MAX_SIZE) {
3151 num_too_long:
3152 error("number too long");
3154 *q++ = ch;
3155 ch = *p++;
3157 if (ch == '.' ||
3158 ((ch == 'e' || ch == 'E') && b == 10) ||
3159 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3160 if (b != 10) {
3161 /* NOTE: strtox should support that for hexa numbers, but
3162 non ISOC99 libcs do not support it, so we prefer to do
3163 it by hand */
3164 /* hexadecimal or binary floats */
3165 /* XXX: handle overflows */
3166 *q = '\0';
3167 if (b == 16)
3168 shift = 4;
3169 else
3170 shift = 2;
3171 bn_zero(bn);
3172 q = token_buf;
3173 while (1) {
3174 t = *q++;
3175 if (t == '\0') {
3176 break;
3177 } else if (t >= 'a') {
3178 t = t - 'a' + 10;
3179 } else if (t >= 'A') {
3180 t = t - 'A' + 10;
3181 } else {
3182 t = t - '0';
3184 bn_lshift(bn, shift, t);
3186 frac_bits = 0;
3187 if (ch == '.') {
3188 ch = *p++;
3189 while (1) {
3190 t = ch;
3191 if (t >= 'a' && t <= 'f') {
3192 t = t - 'a' + 10;
3193 } else if (t >= 'A' && t <= 'F') {
3194 t = t - 'A' + 10;
3195 } else if (t >= '0' && t <= '9') {
3196 t = t - '0';
3197 } else {
3198 break;
3200 if (t >= b)
3201 error("invalid digit");
3202 bn_lshift(bn, shift, t);
3203 frac_bits += shift;
3204 ch = *p++;
3207 if (ch != 'p' && ch != 'P')
3208 expect("exponent");
3209 ch = *p++;
3210 s = 1;
3211 exp_val = 0;
3212 if (ch == '+') {
3213 ch = *p++;
3214 } else if (ch == '-') {
3215 s = -1;
3216 ch = *p++;
3218 if (ch < '0' || ch > '9')
3219 expect("exponent digits");
3220 while (ch >= '0' && ch <= '9') {
3221 exp_val = exp_val * 10 + ch - '0';
3222 ch = *p++;
3224 exp_val = exp_val * s;
3226 /* now we can generate the number */
3227 /* XXX: should patch directly float number */
3228 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3229 d = ldexp(d, exp_val - frac_bits);
3230 t = toup(ch);
3231 if (t == 'F') {
3232 ch = *p++;
3233 tok = TOK_CFLOAT;
3234 /* float : should handle overflow */
3235 tokc.f = (float)d;
3236 } else if (t == 'L') {
3237 ch = *p++;
3238 tok = TOK_CLDOUBLE;
3239 /* XXX: not large enough */
3240 tokc.ld = (long double)d;
3241 } else {
3242 tok = TOK_CDOUBLE;
3243 tokc.d = d;
3245 } else {
3246 /* decimal floats */
3247 if (ch == '.') {
3248 if (q >= token_buf + STRING_MAX_SIZE)
3249 goto num_too_long;
3250 *q++ = ch;
3251 ch = *p++;
3252 float_frac_parse:
3253 while (ch >= '0' && ch <= '9') {
3254 if (q >= token_buf + STRING_MAX_SIZE)
3255 goto num_too_long;
3256 *q++ = ch;
3257 ch = *p++;
3260 if (ch == 'e' || ch == 'E') {
3261 if (q >= token_buf + STRING_MAX_SIZE)
3262 goto num_too_long;
3263 *q++ = ch;
3264 ch = *p++;
3265 if (ch == '-' || ch == '+') {
3266 if (q >= token_buf + STRING_MAX_SIZE)
3267 goto num_too_long;
3268 *q++ = ch;
3269 ch = *p++;
3271 if (ch < '0' || ch > '9')
3272 expect("exponent digits");
3273 while (ch >= '0' && ch <= '9') {
3274 if (q >= token_buf + STRING_MAX_SIZE)
3275 goto num_too_long;
3276 *q++ = ch;
3277 ch = *p++;
3280 *q = '\0';
3281 t = toup(ch);
3282 errno = 0;
3283 if (t == 'F') {
3284 ch = *p++;
3285 tok = TOK_CFLOAT;
3286 tokc.f = strtof(token_buf, NULL);
3287 } else if (t == 'L') {
3288 ch = *p++;
3289 tok = TOK_CLDOUBLE;
3290 tokc.ld = strtold(token_buf, NULL);
3291 } else {
3292 tok = TOK_CDOUBLE;
3293 tokc.d = strtod(token_buf, NULL);
3296 } else {
3297 unsigned long long n, n1;
3298 int lcount, ucount;
3300 /* integer number */
3301 *q = '\0';
3302 q = token_buf;
3303 if (b == 10 && *q == '0') {
3304 b = 8;
3305 q++;
3307 n = 0;
3308 while(1) {
3309 t = *q++;
3310 /* no need for checks except for base 10 / 8 errors */
3311 if (t == '\0') {
3312 break;
3313 } else if (t >= 'a') {
3314 t = t - 'a' + 10;
3315 } else if (t >= 'A') {
3316 t = t - 'A' + 10;
3317 } else {
3318 t = t - '0';
3319 if (t >= b)
3320 error("invalid digit");
3322 n1 = n;
3323 n = n * b + t;
3324 /* detect overflow */
3325 /* XXX: this test is not reliable */
3326 if (n < n1)
3327 error("integer constant overflow");
3330 /* XXX: not exactly ANSI compliant */
3331 if ((n & 0xffffffff00000000LL) != 0) {
3332 if ((n >> 63) != 0)
3333 tok = TOK_CULLONG;
3334 else
3335 tok = TOK_CLLONG;
3336 } else if (n > 0x7fffffff) {
3337 tok = TOK_CUINT;
3338 } else {
3339 tok = TOK_CINT;
3341 lcount = 0;
3342 ucount = 0;
3343 for(;;) {
3344 t = toup(ch);
3345 if (t == 'L') {
3346 if (lcount >= 2)
3347 error("three 'l's in integer constant");
3348 lcount++;
3349 if (lcount == 2) {
3350 if (tok == TOK_CINT)
3351 tok = TOK_CLLONG;
3352 else if (tok == TOK_CUINT)
3353 tok = TOK_CULLONG;
3355 ch = *p++;
3356 } else if (t == 'U') {
3357 if (ucount >= 1)
3358 error("two 'u's in integer constant");
3359 ucount++;
3360 if (tok == TOK_CINT)
3361 tok = TOK_CUINT;
3362 else if (tok == TOK_CLLONG)
3363 tok = TOK_CULLONG;
3364 ch = *p++;
3365 } else {
3366 break;
3369 if (tok == TOK_CINT || tok == TOK_CUINT)
3370 tokc.ui = n;
3371 else
3372 tokc.ull = n;
3377 #define PARSE2(c1, tok1, c2, tok2) \
3378 case c1: \
3379 PEEKC(c, p); \
3380 if (c == c2) { \
3381 p++; \
3382 tok = tok2; \
3383 } else { \
3384 tok = tok1; \
3386 break;
3388 /* return next token without macro substitution */
3389 static inline void next_nomacro1(void)
3391 int t, c, is_long;
3392 TokenSym *ts;
3393 uint8_t *p, *p1;
3394 unsigned int h;
3396 p = file->buf_ptr;
3397 redo_no_start:
3398 c = *p;
3399 switch(c) {
3400 case ' ':
3401 case '\t':
3402 case '\f':
3403 case '\v':
3404 case '\r':
3405 p++;
3406 goto redo_no_start;
3408 case '\\':
3409 /* first look if it is in fact an end of buffer */
3410 if (p >= file->buf_end) {
3411 file->buf_ptr = p;
3412 handle_eob();
3413 p = file->buf_ptr;
3414 if (p >= file->buf_end)
3415 goto parse_eof;
3416 else
3417 goto redo_no_start;
3418 } else {
3419 file->buf_ptr = p;
3420 ch = *p;
3421 handle_stray();
3422 p = file->buf_ptr;
3423 goto redo_no_start;
3425 parse_eof:
3427 TCCState *s1 = tcc_state;
3428 if (parse_flags & PARSE_FLAG_LINEFEED) {
3429 tok = TOK_LINEFEED;
3430 } else if (s1->include_stack_ptr == s1->include_stack ||
3431 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3432 /* no include left : end of file. */
3433 tok = TOK_EOF;
3434 } else {
3435 /* pop include file */
3437 /* test if previous '#endif' was after a #ifdef at
3438 start of file */
3439 if (tok_flags & TOK_FLAG_ENDIF) {
3440 #ifdef INC_DEBUG
3441 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3442 #endif
3443 add_cached_include(s1, file->inc_type, file->inc_filename,
3444 file->ifndef_macro_saved);
3447 /* add end of include file debug info */
3448 if (do_debug) {
3449 put_stabd(N_EINCL, 0, 0);
3451 /* pop include stack */
3452 tcc_close(file);
3453 s1->include_stack_ptr--;
3454 file = *s1->include_stack_ptr;
3455 p = file->buf_ptr;
3456 goto redo_no_start;
3459 break;
3461 case '\n':
3462 if (parse_flags & PARSE_FLAG_LINEFEED) {
3463 tok = TOK_LINEFEED;
3464 } else {
3465 file->line_num++;
3466 tok_flags |= TOK_FLAG_BOL;
3467 p++;
3468 goto redo_no_start;
3470 break;
3472 case '#':
3473 /* XXX: simplify */
3474 PEEKC(c, p);
3475 if ((tok_flags & TOK_FLAG_BOL) &&
3476 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3477 file->buf_ptr = p;
3478 preprocess(tok_flags & TOK_FLAG_BOF);
3479 p = file->buf_ptr;
3480 goto redo_no_start;
3481 } else {
3482 if (c == '#') {
3483 p++;
3484 tok = TOK_TWOSHARPS;
3485 } else {
3486 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3487 p = parse_line_comment(p - 1);
3488 goto redo_no_start;
3489 } else {
3490 tok = '#';
3494 break;
3496 case 'a': case 'b': case 'c': case 'd':
3497 case 'e': case 'f': case 'g': case 'h':
3498 case 'i': case 'j': case 'k': case 'l':
3499 case 'm': case 'n': case 'o': case 'p':
3500 case 'q': case 'r': case 's': case 't':
3501 case 'u': case 'v': case 'w': case 'x':
3502 case 'y': case 'z':
3503 case 'A': case 'B': case 'C': case 'D':
3504 case 'E': case 'F': case 'G': case 'H':
3505 case 'I': case 'J': case 'K':
3506 case 'M': case 'N': case 'O': case 'P':
3507 case 'Q': case 'R': case 'S': case 'T':
3508 case 'U': case 'V': case 'W': case 'X':
3509 case 'Y': case 'Z':
3510 case '_':
3511 parse_ident_fast:
3512 p1 = p;
3513 h = TOK_HASH_INIT;
3514 h = TOK_HASH_FUNC(h, c);
3515 p++;
3516 for(;;) {
3517 c = *p;
3518 if (!isidnum_table[c])
3519 break;
3520 h = TOK_HASH_FUNC(h, c);
3521 p++;
3523 if (c != '\\') {
3524 TokenSym **pts;
3525 int len;
3527 /* fast case : no stray found, so we have the full token
3528 and we have already hashed it */
3529 len = p - p1;
3530 h &= (TOK_HASH_SIZE - 1);
3531 pts = &hash_ident[h];
3532 for(;;) {
3533 ts = *pts;
3534 if (!ts)
3535 break;
3536 if (ts->len == len && !memcmp(ts->str, p1, len))
3537 goto token_found;
3538 pts = &(ts->hash_next);
3540 ts = tok_alloc_new(pts, p1, len);
3541 token_found: ;
3542 } else {
3543 /* slower case */
3544 cstr_reset(&tokcstr);
3546 while (p1 < p) {
3547 cstr_ccat(&tokcstr, *p1);
3548 p1++;
3550 p--;
3551 PEEKC(c, p);
3552 parse_ident_slow:
3553 while (isidnum_table[c]) {
3554 cstr_ccat(&tokcstr, c);
3555 PEEKC(c, p);
3557 ts = tok_alloc(tokcstr.data, tokcstr.size);
3559 tok = ts->tok;
3560 break;
3561 case 'L':
3562 t = p[1];
3563 if (t != '\\' && t != '\'' && t != '\"') {
3564 /* fast case */
3565 goto parse_ident_fast;
3566 } else {
3567 PEEKC(c, p);
3568 if (c == '\'' || c == '\"') {
3569 is_long = 1;
3570 goto str_const;
3571 } else {
3572 cstr_reset(&tokcstr);
3573 cstr_ccat(&tokcstr, 'L');
3574 goto parse_ident_slow;
3577 break;
3578 case '0': case '1': case '2': case '3':
3579 case '4': case '5': case '6': case '7':
3580 case '8': case '9':
3582 cstr_reset(&tokcstr);
3583 /* after the first digit, accept digits, alpha, '.' or sign if
3584 prefixed by 'eEpP' */
3585 parse_num:
3586 for(;;) {
3587 t = c;
3588 cstr_ccat(&tokcstr, c);
3589 PEEKC(c, p);
3590 if (!(isnum(c) || isid(c) || c == '.' ||
3591 ((c == '+' || c == '-') &&
3592 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3593 break;
3595 /* We add a trailing '\0' to ease parsing */
3596 cstr_ccat(&tokcstr, '\0');
3597 tokc.cstr = &tokcstr;
3598 tok = TOK_PPNUM;
3599 break;
3600 case '.':
3601 /* special dot handling because it can also start a number */
3602 PEEKC(c, p);
3603 if (isnum(c)) {
3604 cstr_reset(&tokcstr);
3605 cstr_ccat(&tokcstr, '.');
3606 goto parse_num;
3607 } else if (c == '.') {
3608 PEEKC(c, p);
3609 if (c != '.')
3610 expect("'.'");
3611 PEEKC(c, p);
3612 tok = TOK_DOTS;
3613 } else {
3614 tok = '.';
3616 break;
3617 case '\'':
3618 case '\"':
3619 is_long = 0;
3620 str_const:
3622 CString str;
3623 int sep;
3625 sep = c;
3627 /* parse the string */
3628 cstr_new(&str);
3629 p = parse_pp_string(p, sep, &str);
3630 cstr_ccat(&str, '\0');
3632 /* eval the escape (should be done as TOK_PPNUM) */
3633 cstr_reset(&tokcstr);
3634 parse_escape_string(&tokcstr, str.data, is_long);
3635 cstr_free(&str);
3637 if (sep == '\'') {
3638 int char_size;
3639 /* XXX: make it portable */
3640 if (!is_long)
3641 char_size = 1;
3642 else
3643 char_size = sizeof(int);
3644 if (tokcstr.size <= char_size)
3645 error("empty character constant");
3646 if (tokcstr.size > 2 * char_size)
3647 warning("multi-character character constant");
3648 if (!is_long) {
3649 tokc.i = *(int8_t *)tokcstr.data;
3650 tok = TOK_CCHAR;
3651 } else {
3652 tokc.i = *(int *)tokcstr.data;
3653 tok = TOK_LCHAR;
3655 } else {
3656 tokc.cstr = &tokcstr;
3657 if (!is_long)
3658 tok = TOK_STR;
3659 else
3660 tok = TOK_LSTR;
3663 break;
3665 case '<':
3666 PEEKC(c, p);
3667 if (c == '=') {
3668 p++;
3669 tok = TOK_LE;
3670 } else if (c == '<') {
3671 PEEKC(c, p);
3672 if (c == '=') {
3673 p++;
3674 tok = TOK_A_SHL;
3675 } else {
3676 tok = TOK_SHL;
3678 } else {
3679 tok = TOK_LT;
3681 break;
3683 case '>':
3684 PEEKC(c, p);
3685 if (c == '=') {
3686 p++;
3687 tok = TOK_GE;
3688 } else if (c == '>') {
3689 PEEKC(c, p);
3690 if (c == '=') {
3691 p++;
3692 tok = TOK_A_SAR;
3693 } else {
3694 tok = TOK_SAR;
3696 } else {
3697 tok = TOK_GT;
3699 break;
3701 case '&':
3702 PEEKC(c, p);
3703 if (c == '&') {
3704 p++;
3705 tok = TOK_LAND;
3706 } else if (c == '=') {
3707 p++;
3708 tok = TOK_A_AND;
3709 } else {
3710 tok = '&';
3712 break;
3714 case '|':
3715 PEEKC(c, p);
3716 if (c == '|') {
3717 p++;
3718 tok = TOK_LOR;
3719 } else if (c == '=') {
3720 p++;
3721 tok = TOK_A_OR;
3722 } else {
3723 tok = '|';
3725 break;
3727 case '+':
3728 PEEKC(c, p);
3729 if (c == '+') {
3730 p++;
3731 tok = TOK_INC;
3732 } else if (c == '=') {
3733 p++;
3734 tok = TOK_A_ADD;
3735 } else {
3736 tok = '+';
3738 break;
3740 case '-':
3741 PEEKC(c, p);
3742 if (c == '-') {
3743 p++;
3744 tok = TOK_DEC;
3745 } else if (c == '=') {
3746 p++;
3747 tok = TOK_A_SUB;
3748 } else if (c == '>') {
3749 p++;
3750 tok = TOK_ARROW;
3751 } else {
3752 tok = '-';
3754 break;
3756 PARSE2('!', '!', '=', TOK_NE)
3757 PARSE2('=', '=', '=', TOK_EQ)
3758 PARSE2('*', '*', '=', TOK_A_MUL)
3759 PARSE2('%', '%', '=', TOK_A_MOD)
3760 PARSE2('^', '^', '=', TOK_A_XOR)
3762 /* comments or operator */
3763 case '/':
3764 PEEKC(c, p);
3765 if (c == '*') {
3766 p = parse_comment(p);
3767 goto redo_no_start;
3768 } else if (c == '/') {
3769 p = parse_line_comment(p);
3770 goto redo_no_start;
3771 } else if (c == '=') {
3772 p++;
3773 tok = TOK_A_DIV;
3774 } else {
3775 tok = '/';
3777 break;
3779 /* simple tokens */
3780 case '(':
3781 case ')':
3782 case '[':
3783 case ']':
3784 case '{':
3785 case '}':
3786 case ',':
3787 case ';':
3788 case ':':
3789 case '?':
3790 case '~':
3791 case '$': /* only used in assembler */
3792 tok = c;
3793 p++;
3794 break;
3795 default:
3796 error("unrecognized character \\x%02x", c);
3797 break;
3799 file->buf_ptr = p;
3800 tok_flags = 0;
3801 #if defined(PARSE_DEBUG)
3802 printf("token = %s\n", get_tok_str(tok, &tokc));
3803 #endif
3806 /* return next token without macro substitution. Can read input from
3807 macro_ptr buffer */
3808 static void next_nomacro(void)
3810 if (macro_ptr) {
3811 redo:
3812 tok = *macro_ptr;
3813 if (tok) {
3814 TOK_GET(tok, macro_ptr, tokc);
3815 if (tok == TOK_LINENUM) {
3816 file->line_num = tokc.i;
3817 goto redo;
3820 } else {
3821 next_nomacro1();
3825 /* substitute args in macro_str and return allocated string */
3826 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3828 int *st, last_tok, t, notfirst;
3829 Sym *s;
3830 CValue cval;
3831 TokenString str;
3832 CString cstr;
3834 tok_str_new(&str);
3835 last_tok = 0;
3836 while(1) {
3837 TOK_GET(t, macro_str, cval);
3838 if (!t)
3839 break;
3840 if (t == '#') {
3841 /* stringize */
3842 TOK_GET(t, macro_str, cval);
3843 if (!t)
3844 break;
3845 s = sym_find2(args, t);
3846 if (s) {
3847 cstr_new(&cstr);
3848 st = (int *)s->c;
3849 notfirst = 0;
3850 while (*st) {
3851 if (notfirst)
3852 cstr_ccat(&cstr, ' ');
3853 TOK_GET(t, st, cval);
3854 cstr_cat(&cstr, get_tok_str(t, &cval));
3855 notfirst = 1;
3857 cstr_ccat(&cstr, '\0');
3858 #ifdef PP_DEBUG
3859 printf("stringize: %s\n", (char *)cstr.data);
3860 #endif
3861 /* add string */
3862 cval.cstr = &cstr;
3863 tok_str_add2(&str, TOK_STR, &cval);
3864 cstr_free(&cstr);
3865 } else {
3866 tok_str_add2(&str, t, &cval);
3868 } else if (t >= TOK_IDENT) {
3869 s = sym_find2(args, t);
3870 if (s) {
3871 st = (int *)s->c;
3872 /* if '##' is present before or after, no arg substitution */
3873 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3874 /* special case for var arg macros : ## eats the
3875 ',' if empty VA_ARGS variable. */
3876 /* XXX: test of the ',' is not 100%
3877 reliable. should fix it to avoid security
3878 problems */
3879 if (gnu_ext && s->type.t &&
3880 last_tok == TOK_TWOSHARPS &&
3881 str.len >= 2 && str.str[str.len - 2] == ',') {
3882 if (*st == 0) {
3883 /* suppress ',' '##' */
3884 str.len -= 2;
3885 } else {
3886 /* suppress '##' and add variable */
3887 str.len--;
3888 goto add_var;
3890 } else {
3891 int t1;
3892 add_var:
3893 for(;;) {
3894 TOK_GET(t1, st, cval);
3895 if (!t1)
3896 break;
3897 tok_str_add2(&str, t1, &cval);
3900 } else {
3901 /* NOTE: the stream cannot be read when macro
3902 substituing an argument */
3903 macro_subst(&str, nested_list, st, 0);
3905 } else {
3906 tok_str_add(&str, t);
3908 } else {
3909 tok_str_add2(&str, t, &cval);
3911 last_tok = t;
3913 tok_str_add(&str, 0);
3914 return str.str;
3917 static char const ab_month_name[12][4] =
3919 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3920 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3923 /* do macro substitution of current token with macro 's' and add
3924 result to (tok_str,tok_len). 'nested_list' is the list of all
3925 macros we got inside to avoid recursing. Return non zero if no
3926 substitution needs to be done */
3927 static int macro_subst_tok(TokenString *tok_str,
3928 Sym **nested_list, Sym *s, int can_read_stream)
3930 Sym *args, *sa, *sa1;
3931 int mstr_allocated, parlevel, *mstr, t, t1;
3932 TokenString str;
3933 char *cstrval;
3934 CValue cval;
3935 CString cstr;
3936 char buf[32];
3938 /* if symbol is a macro, prepare substitution */
3939 /* special macros */
3940 if (tok == TOK___LINE__) {
3941 snprintf(buf, sizeof(buf), "%d", file->line_num);
3942 cstrval = buf;
3943 t1 = TOK_PPNUM;
3944 goto add_cstr1;
3945 } else if (tok == TOK___FILE__) {
3946 cstrval = file->filename;
3947 goto add_cstr;
3948 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3949 time_t ti;
3950 struct tm *tm;
3952 time(&ti);
3953 tm = localtime(&ti);
3954 if (tok == TOK___DATE__) {
3955 snprintf(buf, sizeof(buf), "%s %2d %d",
3956 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3957 } else {
3958 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3959 tm->tm_hour, tm->tm_min, tm->tm_sec);
3961 cstrval = buf;
3962 add_cstr:
3963 t1 = TOK_STR;
3964 add_cstr1:
3965 cstr_new(&cstr);
3966 cstr_cat(&cstr, cstrval);
3967 cstr_ccat(&cstr, '\0');
3968 cval.cstr = &cstr;
3969 tok_str_add2(tok_str, t1, &cval);
3970 cstr_free(&cstr);
3971 } else {
3972 mstr = (int *)s->c;
3973 mstr_allocated = 0;
3974 if (s->type.t == MACRO_FUNC) {
3975 /* NOTE: we do not use next_nomacro to avoid eating the
3976 next token. XXX: find better solution */
3977 if (macro_ptr) {
3978 t = *macro_ptr;
3979 if (t == 0 && can_read_stream) {
3980 /* end of macro stream: we must look at the token
3981 after in the file */
3982 macro_ptr = NULL;
3983 goto parse_stream;
3985 } else {
3986 parse_stream:
3987 /* XXX: incorrect with comments */
3988 ch = file->buf_ptr[0];
3989 while (is_space(ch) || ch == '\n')
3990 cinp();
3991 t = ch;
3993 if (t != '(') /* no macro subst */
3994 return -1;
3996 /* argument macro */
3997 next_nomacro();
3998 next_nomacro();
3999 args = NULL;
4000 sa = s->next;
4001 /* NOTE: empty args are allowed, except if no args */
4002 for(;;) {
4003 /* handle '()' case */
4004 if (!args && !sa && tok == ')')
4005 break;
4006 if (!sa)
4007 error("macro '%s' used with too many args",
4008 get_tok_str(s->v, 0));
4009 tok_str_new(&str);
4010 parlevel = 0;
4011 /* NOTE: non zero sa->t indicates VA_ARGS */
4012 while ((parlevel > 0 ||
4013 (tok != ')' &&
4014 (tok != ',' || sa->type.t))) &&
4015 tok != -1) {
4016 if (tok == '(')
4017 parlevel++;
4018 else if (tok == ')')
4019 parlevel--;
4020 tok_str_add2(&str, tok, &tokc);
4021 next_nomacro();
4023 tok_str_add(&str, 0);
4024 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4025 sa = sa->next;
4026 if (tok == ')') {
4027 /* special case for gcc var args: add an empty
4028 var arg argument if it is omitted */
4029 if (sa && sa->type.t && gnu_ext)
4030 continue;
4031 else
4032 break;
4034 if (tok != ',')
4035 expect(",");
4036 next_nomacro();
4038 if (sa) {
4039 error("macro '%s' used with too few args",
4040 get_tok_str(s->v, 0));
4043 /* now subst each arg */
4044 mstr = macro_arg_subst(nested_list, mstr, args);
4045 /* free memory */
4046 sa = args;
4047 while (sa) {
4048 sa1 = sa->prev;
4049 tok_str_free((int *)sa->c);
4050 sym_free(sa);
4051 sa = sa1;
4053 mstr_allocated = 1;
4055 sym_push2(nested_list, s->v, 0, 0);
4056 macro_subst(tok_str, nested_list, mstr, 1);
4057 /* pop nested defined symbol */
4058 sa1 = *nested_list;
4059 *nested_list = sa1->prev;
4060 sym_free(sa1);
4061 if (mstr_allocated)
4062 tok_str_free(mstr);
4064 return 0;
4067 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4068 return the resulting string (which must be freed). */
4069 static inline int *macro_twosharps(const int *macro_str)
4071 TokenSym *ts;
4072 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4073 int t;
4074 const char *p1, *p2;
4075 CValue cval;
4076 TokenString macro_str1;
4077 CString cstr;
4079 start_macro_ptr = macro_str;
4080 /* we search the first '##' */
4081 for(;;) {
4082 macro_ptr1 = macro_str;
4083 TOK_GET(t, macro_str, cval);
4084 /* nothing more to do if end of string */
4085 if (t == 0)
4086 return NULL;
4087 if (*macro_str == TOK_TWOSHARPS)
4088 break;
4091 /* we saw '##', so we need more processing to handle it */
4092 cstr_new(&cstr);
4093 tok_str_new(&macro_str1);
4094 tok = t;
4095 tokc = cval;
4097 /* add all tokens seen so far */
4098 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4099 TOK_GET(t, ptr, cval);
4100 tok_str_add2(&macro_str1, t, &cval);
4102 saved_macro_ptr = macro_ptr;
4103 /* XXX: get rid of the use of macro_ptr here */
4104 macro_ptr = (int *)macro_str;
4105 for(;;) {
4106 while (*macro_ptr == TOK_TWOSHARPS) {
4107 macro_ptr++;
4108 macro_ptr1 = macro_ptr;
4109 t = *macro_ptr;
4110 if (t) {
4111 TOK_GET(t, macro_ptr, cval);
4112 /* We concatenate the two tokens if we have an
4113 identifier or a preprocessing number */
4114 cstr_reset(&cstr);
4115 p1 = get_tok_str(tok, &tokc);
4116 cstr_cat(&cstr, p1);
4117 p2 = get_tok_str(t, &cval);
4118 cstr_cat(&cstr, p2);
4119 cstr_ccat(&cstr, '\0');
4121 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4122 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4123 if (tok == TOK_PPNUM) {
4124 /* if number, then create a number token */
4125 /* NOTE: no need to allocate because
4126 tok_str_add2() does it */
4127 tokc.cstr = &cstr;
4128 } else {
4129 /* if identifier, we must do a test to
4130 validate we have a correct identifier */
4131 if (t == TOK_PPNUM) {
4132 const char *p;
4133 int c;
4135 p = p2;
4136 for(;;) {
4137 c = *p;
4138 if (c == '\0')
4139 break;
4140 p++;
4141 if (!isnum(c) && !isid(c))
4142 goto error_pasting;
4145 ts = tok_alloc(cstr.data, strlen(cstr.data));
4146 tok = ts->tok; /* modify current token */
4148 } else {
4149 const char *str = cstr.data;
4150 const unsigned char *q;
4152 /* we look for a valid token */
4153 /* XXX: do more extensive checks */
4154 if (!strcmp(str, ">>=")) {
4155 tok = TOK_A_SAR;
4156 } else if (!strcmp(str, "<<=")) {
4157 tok = TOK_A_SHL;
4158 } else if (strlen(str) == 2) {
4159 /* search in two bytes table */
4160 q = tok_two_chars;
4161 for(;;) {
4162 if (!*q)
4163 goto error_pasting;
4164 if (q[0] == str[0] && q[1] == str[1])
4165 break;
4166 q += 3;
4168 tok = q[2];
4169 } else {
4170 error_pasting:
4171 /* NOTE: because get_tok_str use a static buffer,
4172 we must save it */
4173 cstr_reset(&cstr);
4174 p1 = get_tok_str(tok, &tokc);
4175 cstr_cat(&cstr, p1);
4176 cstr_ccat(&cstr, '\0');
4177 p2 = get_tok_str(t, &cval);
4178 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4179 /* cannot merge tokens: just add them separately */
4180 tok_str_add2(&macro_str1, tok, &tokc);
4181 /* XXX: free associated memory ? */
4182 tok = t;
4183 tokc = cval;
4188 tok_str_add2(&macro_str1, tok, &tokc);
4189 next_nomacro();
4190 if (tok == 0)
4191 break;
4193 macro_ptr = (int *)saved_macro_ptr;
4194 cstr_free(&cstr);
4195 tok_str_add(&macro_str1, 0);
4196 return macro_str1.str;
4200 /* do macro substitution of macro_str and add result to
4201 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4202 inside to avoid recursing. */
4203 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4204 const int *macro_str, int can_read_stream)
4206 Sym *s;
4207 int *saved_macro_ptr, *macro_str1;
4208 const int *ptr;
4209 int t, ret;
4210 CValue cval;
4212 /* first scan for '##' operator handling */
4213 ptr = macro_str;
4214 macro_str1 = macro_twosharps(ptr);
4215 if (macro_str1)
4216 ptr = macro_str1;
4217 while (1) {
4218 /* NOTE: ptr == NULL can only happen if tokens are read from
4219 file stream due to a macro function call */
4220 if (ptr == NULL)
4221 break;
4222 TOK_GET(t, ptr, cval);
4223 if (t == 0)
4224 break;
4225 s = define_find(t);
4226 if (s != NULL) {
4227 /* if nested substitution, do nothing */
4228 if (sym_find2(*nested_list, t))
4229 goto no_subst;
4230 saved_macro_ptr = macro_ptr;
4231 macro_ptr = (int *)ptr;
4232 tok = t;
4233 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4234 ptr = (int *)macro_ptr;
4235 macro_ptr = saved_macro_ptr;
4236 if (ret != 0)
4237 goto no_subst;
4238 } else {
4239 no_subst:
4240 tok_str_add2(tok_str, t, &cval);
4243 if (macro_str1)
4244 tok_str_free(macro_str1);
4247 /* return next token with macro substitution */
4248 static void next(void)
4250 Sym *nested_list, *s;
4251 TokenString str;
4253 redo:
4254 next_nomacro();
4255 if (!macro_ptr) {
4256 /* if not reading from macro substituted string, then try
4257 to substitute macros */
4258 if (tok >= TOK_IDENT &&
4259 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4260 s = define_find(tok);
4261 if (s) {
4262 /* we have a macro: we try to substitute */
4263 tok_str_new(&str);
4264 nested_list = NULL;
4265 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4266 /* substitution done, NOTE: maybe empty */
4267 tok_str_add(&str, 0);
4268 macro_ptr = str.str;
4269 macro_ptr_allocated = str.str;
4270 goto redo;
4274 } else {
4275 if (tok == 0) {
4276 /* end of macro or end of unget buffer */
4277 if (unget_buffer_enabled) {
4278 macro_ptr = unget_saved_macro_ptr;
4279 unget_buffer_enabled = 0;
4280 } else {
4281 /* end of macro string: free it */
4282 tok_str_free(macro_ptr_allocated);
4283 macro_ptr = NULL;
4285 goto redo;
4289 /* convert preprocessor tokens into C tokens */
4290 if (tok == TOK_PPNUM &&
4291 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4292 parse_number((char *)tokc.cstr->data);
4296 /* push back current token and set current token to 'last_tok'. Only
4297 identifier case handled for labels. */
4298 static inline void unget_tok(int last_tok)
4300 int i, n;
4301 int *q;
4302 unget_saved_macro_ptr = macro_ptr;
4303 unget_buffer_enabled = 1;
4304 q = unget_saved_buffer;
4305 macro_ptr = q;
4306 *q++ = tok;
4307 n = tok_ext_size(tok) - 1;
4308 for(i=0;i<n;i++)
4309 *q++ = tokc.tab[i];
4310 *q = 0; /* end of token string */
4311 tok = last_tok;
4315 void swap(int *p, int *q)
4317 int t;
4318 t = *p;
4319 *p = *q;
4320 *q = t;
4323 void vsetc(CType *type, int r, CValue *vc)
4325 int v;
4327 if (vtop >= vstack + (VSTACK_SIZE - 1))
4328 error("memory full");
4329 /* cannot let cpu flags if other instruction are generated. Also
4330 avoid leaving VT_JMP anywhere except on the top of the stack
4331 because it would complicate the code generator. */
4332 if (vtop >= vstack) {
4333 v = vtop->r & VT_VALMASK;
4334 if (v == VT_CMP || (v & ~1) == VT_JMP)
4335 gv(RC_INT);
4337 vtop++;
4338 vtop->type = *type;
4339 vtop->r = r;
4340 vtop->r2 = VT_CONST;
4341 vtop->c = *vc;
4344 /* push integer constant */
4345 void vpushi(int v)
4347 CValue cval;
4348 cval.i = v;
4349 vsetc(&int_type, VT_CONST, &cval);
4352 /* Return a static symbol pointing to a section */
4353 static Sym *get_sym_ref(CType *type, Section *sec,
4354 unsigned long offset, unsigned long size)
4356 int v;
4357 Sym *sym;
4359 v = anon_sym++;
4360 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4361 sym->type.ref = type->ref;
4362 sym->r = VT_CONST | VT_SYM;
4363 put_extern_sym(sym, sec, offset, size);
4364 return sym;
4367 /* push a reference to a section offset by adding a dummy symbol */
4368 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4370 CValue cval;
4372 cval.ul = 0;
4373 vsetc(type, VT_CONST | VT_SYM, &cval);
4374 vtop->sym = get_sym_ref(type, sec, offset, size);
4377 /* define a new external reference to a symbol 'v' of type 'u' */
4378 static Sym *external_global_sym(int v, CType *type, int r)
4380 Sym *s;
4382 s = sym_find(v);
4383 if (!s) {
4384 /* push forward reference */
4385 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4386 s->type.ref = type->ref;
4387 s->r = r | VT_CONST | VT_SYM;
4389 return s;
4392 /* define a new external reference to a symbol 'v' of type 'u' */
4393 static Sym *external_sym(int v, CType *type, int r)
4395 Sym *s;
4397 s = sym_find(v);
4398 if (!s) {
4399 /* push forward reference */
4400 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4401 s->type.t |= VT_EXTERN;
4402 } else {
4403 if (!is_compatible_types(&s->type, type))
4404 error("incompatible types for redefinition of '%s'",
4405 get_tok_str(v, NULL));
4407 return s;
4410 /* push a reference to global symbol v */
4411 static void vpush_global_sym(CType *type, int v)
4413 Sym *sym;
4414 CValue cval;
4416 sym = external_global_sym(v, type, 0);
4417 cval.ul = 0;
4418 vsetc(type, VT_CONST | VT_SYM, &cval);
4419 vtop->sym = sym;
4422 void vset(CType *type, int r, int v)
4424 CValue cval;
4426 cval.i = v;
4427 vsetc(type, r, &cval);
4430 void vseti(int r, int v)
4432 CType type;
4433 type.t = VT_INT;
4434 vset(&type, r, v);
4437 void vswap(void)
4439 SValue tmp;
4441 tmp = vtop[0];
4442 vtop[0] = vtop[-1];
4443 vtop[-1] = tmp;
4446 void vpushv(SValue *v)
4448 if (vtop >= vstack + (VSTACK_SIZE - 1))
4449 error("memory full");
4450 vtop++;
4451 *vtop = *v;
4454 void vdup(void)
4456 vpushv(vtop);
4459 /* save r to the memory stack, and mark it as being free */
4460 void save_reg(int r)
4462 int l, saved, size, align;
4463 SValue *p, sv;
4464 CType *type;
4466 /* modify all stack values */
4467 saved = 0;
4468 l = 0;
4469 for(p=vstack;p<=vtop;p++) {
4470 if ((p->r & VT_VALMASK) == r ||
4471 (p->r2 & VT_VALMASK) == r) {
4472 /* must save value on stack if not already done */
4473 if (!saved) {
4474 /* NOTE: must reload 'r' because r might be equal to r2 */
4475 r = p->r & VT_VALMASK;
4476 /* store register in the stack */
4477 type = &p->type;
4478 if ((p->r & VT_LVAL) ||
4479 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4480 type = &int_type;
4481 size = type_size(type, &align);
4482 loc = (loc - size) & -align;
4483 sv.type.t = type->t;
4484 sv.r = VT_LOCAL | VT_LVAL;
4485 sv.c.ul = loc;
4486 store(r, &sv);
4487 #ifdef TCC_TARGET_I386
4488 /* x86 specific: need to pop fp register ST0 if saved */
4489 if (r == TREG_ST0) {
4490 o(0xd9dd); /* fstp %st(1) */
4492 #endif
4493 /* special long long case */
4494 if ((type->t & VT_BTYPE) == VT_LLONG) {
4495 sv.c.ul += 4;
4496 store(p->r2, &sv);
4498 l = loc;
4499 saved = 1;
4501 /* mark that stack entry as being saved on the stack */
4502 if (p->r & VT_LVAL) {
4503 /* also clear the bounded flag because the
4504 relocation address of the function was stored in
4505 p->c.ul */
4506 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4507 } else {
4508 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4510 p->r2 = VT_CONST;
4511 p->c.ul = l;
4516 /* find a register of class 'rc2' with at most one reference on stack.
4517 * If none, call get_reg(rc) */
4518 int get_reg_ex(int rc, int rc2)
4520 int r;
4521 SValue *p;
4523 for(r=0;r<NB_REGS;r++) {
4524 if (reg_classes[r] & rc2) {
4525 int n;
4526 n=0;
4527 for(p = vstack; p <= vtop; p++) {
4528 if ((p->r & VT_VALMASK) == r ||
4529 (p->r2 & VT_VALMASK) == r)
4530 n++;
4532 if (n <= 1)
4533 return r;
4536 return get_reg(rc);
4539 /* find a free register of class 'rc'. If none, save one register */
4540 int get_reg(int rc)
4542 int r;
4543 SValue *p;
4545 /* find a free register */
4546 for(r=0;r<NB_REGS;r++) {
4547 if (reg_classes[r] & rc) {
4548 for(p=vstack;p<=vtop;p++) {
4549 if ((p->r & VT_VALMASK) == r ||
4550 (p->r2 & VT_VALMASK) == r)
4551 goto notfound;
4553 return r;
4555 notfound: ;
4558 /* no register left : free the first one on the stack (VERY
4559 IMPORTANT to start from the bottom to ensure that we don't
4560 spill registers used in gen_opi()) */
4561 for(p=vstack;p<=vtop;p++) {
4562 r = p->r & VT_VALMASK;
4563 if (r < VT_CONST && (reg_classes[r] & rc))
4564 goto save_found;
4565 /* also look at second register (if long long) */
4566 r = p->r2 & VT_VALMASK;
4567 if (r < VT_CONST && (reg_classes[r] & rc)) {
4568 save_found:
4569 save_reg(r);
4570 return r;
4573 /* Should never comes here */
4574 return -1;
4577 /* save registers up to (vtop - n) stack entry */
4578 void save_regs(int n)
4580 int r;
4581 SValue *p, *p1;
4582 p1 = vtop - n;
4583 for(p = vstack;p <= p1; p++) {
4584 r = p->r & VT_VALMASK;
4585 if (r < VT_CONST) {
4586 save_reg(r);
4591 /* move register 's' to 'r', and flush previous value of r to memory
4592 if needed */
4593 void move_reg(int r, int s)
4595 SValue sv;
4597 if (r != s) {
4598 save_reg(r);
4599 sv.type.t = VT_INT;
4600 sv.r = s;
4601 sv.c.ul = 0;
4602 load(r, &sv);
4606 /* get address of vtop (vtop MUST BE an lvalue) */
4607 void gaddrof(void)
4609 vtop->r &= ~VT_LVAL;
4610 /* tricky: if saved lvalue, then we can go back to lvalue */
4611 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4612 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4615 #ifdef CONFIG_TCC_BCHECK
4616 /* generate lvalue bound code */
4617 void gbound(void)
4619 int lval_type;
4620 CType type1;
4622 vtop->r &= ~VT_MUSTBOUND;
4623 /* if lvalue, then use checking code before dereferencing */
4624 if (vtop->r & VT_LVAL) {
4625 /* if not VT_BOUNDED value, then make one */
4626 if (!(vtop->r & VT_BOUNDED)) {
4627 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4628 /* must save type because we must set it to int to get pointer */
4629 type1 = vtop->type;
4630 vtop->type.t = VT_INT;
4631 gaddrof();
4632 vpushi(0);
4633 gen_bounded_ptr_add();
4634 vtop->r |= lval_type;
4635 vtop->type = type1;
4637 /* then check for dereferencing */
4638 gen_bounded_ptr_deref();
4641 #endif
4643 /* store vtop a register belonging to class 'rc'. lvalues are
4644 converted to values. Cannot be used if cannot be converted to
4645 register value (such as structures). */
4646 int gv(int rc)
4648 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4649 unsigned long long ll;
4651 /* NOTE: get_reg can modify vstack[] */
4652 if (vtop->type.t & VT_BITFIELD) {
4653 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4654 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4655 /* remove bit field info to avoid loops */
4656 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4657 /* generate shifts */
4658 vpushi(32 - (bit_pos + bit_size));
4659 gen_op(TOK_SHL);
4660 vpushi(32 - bit_size);
4661 /* NOTE: transformed to SHR if unsigned */
4662 gen_op(TOK_SAR);
4663 r = gv(rc);
4664 } else {
4665 if (is_float(vtop->type.t) &&
4666 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4667 Sym *sym;
4668 int *ptr;
4669 unsigned long offset;
4671 /* XXX: unify with initializers handling ? */
4672 /* CPUs usually cannot use float constants, so we store them
4673 generically in data segment */
4674 size = type_size(&vtop->type, &align);
4675 offset = (data_section->data_offset + align - 1) & -align;
4676 data_section->data_offset = offset;
4677 /* XXX: not portable yet */
4678 ptr = section_ptr_add(data_section, size);
4679 size = size >> 2;
4680 for(i=0;i<size;i++)
4681 ptr[i] = vtop->c.tab[i];
4682 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4683 vtop->r |= VT_LVAL | VT_SYM;
4684 vtop->sym = sym;
4685 vtop->c.ul = 0;
4687 #ifdef CONFIG_TCC_BCHECK
4688 if (vtop->r & VT_MUSTBOUND)
4689 gbound();
4690 #endif
4692 r = vtop->r & VT_VALMASK;
4693 /* need to reload if:
4694 - constant
4695 - lvalue (need to dereference pointer)
4696 - already a register, but not in the right class */
4697 if (r >= VT_CONST ||
4698 (vtop->r & VT_LVAL) ||
4699 !(reg_classes[r] & rc) ||
4700 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4701 !(reg_classes[vtop->r2] & rc))) {
4702 r = get_reg(rc);
4703 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4704 /* two register type load : expand to two words
4705 temporarily */
4706 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4707 /* load constant */
4708 ll = vtop->c.ull;
4709 vtop->c.ui = ll; /* first word */
4710 load(r, vtop);
4711 vtop->r = r; /* save register value */
4712 vpushi(ll >> 32); /* second word */
4713 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4714 (vtop->r & VT_LVAL)) {
4715 /* We do not want to modifier the long long
4716 pointer here, so the safest (and less
4717 efficient) is to save all the other registers
4718 in the stack. XXX: totally inefficient. */
4719 save_regs(1);
4720 /* load from memory */
4721 load(r, vtop);
4722 vdup();
4723 vtop[-1].r = r; /* save register value */
4724 /* increment pointer to get second word */
4725 vtop->type.t = VT_INT;
4726 gaddrof();
4727 vpushi(4);
4728 gen_op('+');
4729 vtop->r |= VT_LVAL;
4730 } else {
4731 /* move registers */
4732 load(r, vtop);
4733 vdup();
4734 vtop[-1].r = r; /* save register value */
4735 vtop->r = vtop[-1].r2;
4737 /* allocate second register */
4738 rc2 = RC_INT;
4739 if (rc == RC_IRET)
4740 rc2 = RC_LRET;
4741 r2 = get_reg(rc2);
4742 load(r2, vtop);
4743 vpop();
4744 /* write second register */
4745 vtop->r2 = r2;
4746 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4747 int t1, t;
4748 /* lvalue of scalar type : need to use lvalue type
4749 because of possible cast */
4750 t = vtop->type.t;
4751 t1 = t;
4752 /* compute memory access type */
4753 if (vtop->r & VT_LVAL_BYTE)
4754 t = VT_BYTE;
4755 else if (vtop->r & VT_LVAL_SHORT)
4756 t = VT_SHORT;
4757 if (vtop->r & VT_LVAL_UNSIGNED)
4758 t |= VT_UNSIGNED;
4759 vtop->type.t = t;
4760 load(r, vtop);
4761 /* restore wanted type */
4762 vtop->type.t = t1;
4763 } else {
4764 /* one register type load */
4765 load(r, vtop);
4768 vtop->r = r;
4769 #ifdef TCC_TARGET_C67
4770 /* uses register pairs for doubles */
4771 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4772 vtop->r2 = r+1;
4773 #endif
4775 return r;
4778 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4779 void gv2(int rc1, int rc2)
4781 int v;
4783 /* generate more generic register first. But VT_JMP or VT_CMP
4784 values must be generated first in all cases to avoid possible
4785 reload errors */
4786 v = vtop[0].r & VT_VALMASK;
4787 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4788 vswap();
4789 gv(rc1);
4790 vswap();
4791 gv(rc2);
4792 /* test if reload is needed for first register */
4793 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4794 vswap();
4795 gv(rc1);
4796 vswap();
4798 } else {
4799 gv(rc2);
4800 vswap();
4801 gv(rc1);
4802 vswap();
4803 /* test if reload is needed for first register */
4804 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4805 gv(rc2);
4810 /* expand long long on stack in two int registers */
4811 void lexpand(void)
4813 int u;
4815 u = vtop->type.t & VT_UNSIGNED;
4816 gv(RC_INT);
4817 vdup();
4818 vtop[0].r = vtop[-1].r2;
4819 vtop[0].r2 = VT_CONST;
4820 vtop[-1].r2 = VT_CONST;
4821 vtop[0].type.t = VT_INT | u;
4822 vtop[-1].type.t = VT_INT | u;
4825 #ifdef TCC_TARGET_ARM
4826 /* expand long long on stack */
4827 void lexpand_nr(void)
4829 int u,v;
4831 u = vtop->type.t & VT_UNSIGNED;
4832 vdup();
4833 vtop->r2 = VT_CONST;
4834 vtop->type.t = VT_INT | u;
4835 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4836 if (v == VT_CONST) {
4837 vtop[-1].c.ui = vtop->c.ull;
4838 vtop->c.ui = vtop->c.ull >> 32;
4839 vtop->r = VT_CONST;
4840 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4841 vtop->c.ui += 4;
4842 vtop->r = vtop[-1].r;
4843 } else if (v > VT_CONST) {
4844 vtop--;
4845 lexpand();
4846 } else
4847 vtop->r = vtop[-1].r2;
4848 vtop[-1].r2 = VT_CONST;
4849 vtop[-1].type.t = VT_INT | u;
4851 #endif
4853 /* build a long long from two ints */
4854 void lbuild(int t)
4856 gv2(RC_INT, RC_INT);
4857 vtop[-1].r2 = vtop[0].r;
4858 vtop[-1].type.t = t;
4859 vpop();
4862 /* rotate n first stack elements to the bottom
4863 I1 ... In -> I2 ... In I1 [top is right]
4865 void vrotb(int n)
4867 int i;
4868 SValue tmp;
4870 tmp = vtop[-n + 1];
4871 for(i=-n+1;i!=0;i++)
4872 vtop[i] = vtop[i+1];
4873 vtop[0] = tmp;
4876 /* rotate n first stack elements to the top
4877 I1 ... In -> In I1 ... I(n-1) [top is right]
4879 void vrott(int n)
4881 int i;
4882 SValue tmp;
4884 tmp = vtop[0];
4885 for(i = 0;i < n - 1; i++)
4886 vtop[-i] = vtop[-i - 1];
4887 vtop[-n + 1] = tmp;
4890 #ifdef TCC_TARGET_ARM
4891 /* like vrott but in other direction
4892 In ... I1 -> I(n-1) ... I1 In [top is right]
4894 void vnrott(int n)
4896 int i;
4897 SValue tmp;
4899 tmp = vtop[-n + 1];
4900 for(i = n - 1; i > 0; i--)
4901 vtop[-i] = vtop[-i + 1];
4902 vtop[0] = tmp;
4904 #endif
4906 /* pop stack value */
4907 void vpop(void)
4909 int v;
4910 v = vtop->r & VT_VALMASK;
4911 #ifdef TCC_TARGET_I386
4912 /* for x86, we need to pop the FP stack */
4913 if (v == TREG_ST0 && !nocode_wanted) {
4914 o(0xd9dd); /* fstp %st(1) */
4915 } else
4916 #endif
4917 if (v == VT_JMP || v == VT_JMPI) {
4918 /* need to put correct jump if && or || without test */
4919 gsym(vtop->c.ul);
4921 vtop--;
4924 /* convert stack entry to register and duplicate its value in another
4925 register */
4926 void gv_dup(void)
4928 int rc, t, r, r1;
4929 SValue sv;
4931 t = vtop->type.t;
4932 if ((t & VT_BTYPE) == VT_LLONG) {
4933 lexpand();
4934 gv_dup();
4935 vswap();
4936 vrotb(3);
4937 gv_dup();
4938 vrotb(4);
4939 /* stack: H L L1 H1 */
4940 lbuild(t);
4941 vrotb(3);
4942 vrotb(3);
4943 vswap();
4944 lbuild(t);
4945 vswap();
4946 } else {
4947 /* duplicate value */
4948 rc = RC_INT;
4949 sv.type.t = VT_INT;
4950 if (is_float(t)) {
4951 rc = RC_FLOAT;
4952 sv.type.t = t;
4954 r = gv(rc);
4955 r1 = get_reg(rc);
4956 sv.r = r;
4957 sv.c.ul = 0;
4958 load(r1, &sv); /* move r to r1 */
4959 vdup();
4960 /* duplicates value */
4961 vtop->r = r1;
4965 /* generate CPU independent (unsigned) long long operations */
4966 void gen_opl(int op)
4968 int t, a, b, op1, c, i;
4969 int func;
4970 SValue tmp;
4972 switch(op) {
4973 case '/':
4974 case TOK_PDIV:
4975 func = TOK___divdi3;
4976 goto gen_func;
4977 case TOK_UDIV:
4978 func = TOK___udivdi3;
4979 goto gen_func;
4980 case '%':
4981 func = TOK___moddi3;
4982 goto gen_func;
4983 case TOK_UMOD:
4984 func = TOK___umoddi3;
4985 gen_func:
4986 /* call generic long long function */
4987 vpush_global_sym(&func_old_type, func);
4988 vrott(3);
4989 gfunc_call(2);
4990 vpushi(0);
4991 vtop->r = REG_IRET;
4992 vtop->r2 = REG_LRET;
4993 break;
4994 case '^':
4995 case '&':
4996 case '|':
4997 case '*':
4998 case '+':
4999 case '-':
5000 t = vtop->type.t;
5001 vswap();
5002 lexpand();
5003 vrotb(3);
5004 lexpand();
5005 /* stack: L1 H1 L2 H2 */
5006 tmp = vtop[0];
5007 vtop[0] = vtop[-3];
5008 vtop[-3] = tmp;
5009 tmp = vtop[-2];
5010 vtop[-2] = vtop[-3];
5011 vtop[-3] = tmp;
5012 vswap();
5013 /* stack: H1 H2 L1 L2 */
5014 if (op == '*') {
5015 vpushv(vtop - 1);
5016 vpushv(vtop - 1);
5017 gen_op(TOK_UMULL);
5018 lexpand();
5019 /* stack: H1 H2 L1 L2 ML MH */
5020 for(i=0;i<4;i++)
5021 vrotb(6);
5022 /* stack: ML MH H1 H2 L1 L2 */
5023 tmp = vtop[0];
5024 vtop[0] = vtop[-2];
5025 vtop[-2] = tmp;
5026 /* stack: ML MH H1 L2 H2 L1 */
5027 gen_op('*');
5028 vrotb(3);
5029 vrotb(3);
5030 gen_op('*');
5031 /* stack: ML MH M1 M2 */
5032 gen_op('+');
5033 gen_op('+');
5034 } else if (op == '+' || op == '-') {
5035 /* XXX: add non carry method too (for MIPS or alpha) */
5036 if (op == '+')
5037 op1 = TOK_ADDC1;
5038 else
5039 op1 = TOK_SUBC1;
5040 gen_op(op1);
5041 /* stack: H1 H2 (L1 op L2) */
5042 vrotb(3);
5043 vrotb(3);
5044 gen_op(op1 + 1); /* TOK_xxxC2 */
5045 } else {
5046 gen_op(op);
5047 /* stack: H1 H2 (L1 op L2) */
5048 vrotb(3);
5049 vrotb(3);
5050 /* stack: (L1 op L2) H1 H2 */
5051 gen_op(op);
5052 /* stack: (L1 op L2) (H1 op H2) */
5054 /* stack: L H */
5055 lbuild(t);
5056 break;
5057 case TOK_SAR:
5058 case TOK_SHR:
5059 case TOK_SHL:
5060 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5061 t = vtop[-1].type.t;
5062 vswap();
5063 lexpand();
5064 vrotb(3);
5065 /* stack: L H shift */
5066 c = (int)vtop->c.i;
5067 /* constant: simpler */
5068 /* NOTE: all comments are for SHL. the other cases are
5069 done by swaping words */
5070 vpop();
5071 if (op != TOK_SHL)
5072 vswap();
5073 if (c >= 32) {
5074 /* stack: L H */
5075 vpop();
5076 if (c > 32) {
5077 vpushi(c - 32);
5078 gen_op(op);
5080 if (op != TOK_SAR) {
5081 vpushi(0);
5082 } else {
5083 gv_dup();
5084 vpushi(31);
5085 gen_op(TOK_SAR);
5087 vswap();
5088 } else {
5089 vswap();
5090 gv_dup();
5091 /* stack: H L L */
5092 vpushi(c);
5093 gen_op(op);
5094 vswap();
5095 vpushi(32 - c);
5096 if (op == TOK_SHL)
5097 gen_op(TOK_SHR);
5098 else
5099 gen_op(TOK_SHL);
5100 vrotb(3);
5101 /* stack: L L H */
5102 vpushi(c);
5103 if (op == TOK_SHL)
5104 gen_op(TOK_SHL);
5105 else
5106 gen_op(TOK_SHR);
5107 gen_op('|');
5109 if (op != TOK_SHL)
5110 vswap();
5111 lbuild(t);
5112 } else {
5113 /* XXX: should provide a faster fallback on x86 ? */
5114 switch(op) {
5115 case TOK_SAR:
5116 func = TOK___sardi3;
5117 goto gen_func;
5118 case TOK_SHR:
5119 func = TOK___shrdi3;
5120 goto gen_func;
5121 case TOK_SHL:
5122 func = TOK___shldi3;
5123 goto gen_func;
5126 break;
5127 default:
5128 /* compare operations */
5129 t = vtop->type.t;
5130 vswap();
5131 lexpand();
5132 vrotb(3);
5133 lexpand();
5134 /* stack: L1 H1 L2 H2 */
5135 tmp = vtop[-1];
5136 vtop[-1] = vtop[-2];
5137 vtop[-2] = tmp;
5138 /* stack: L1 L2 H1 H2 */
5139 /* compare high */
5140 op1 = op;
5141 /* when values are equal, we need to compare low words. since
5142 the jump is inverted, we invert the test too. */
5143 if (op1 == TOK_LT)
5144 op1 = TOK_LE;
5145 else if (op1 == TOK_GT)
5146 op1 = TOK_GE;
5147 else if (op1 == TOK_ULT)
5148 op1 = TOK_ULE;
5149 else if (op1 == TOK_UGT)
5150 op1 = TOK_UGE;
5151 a = 0;
5152 b = 0;
5153 gen_op(op1);
5154 if (op1 != TOK_NE) {
5155 a = gtst(1, 0);
5157 if (op != TOK_EQ) {
5158 /* generate non equal test */
5159 /* XXX: NOT PORTABLE yet */
5160 if (a == 0) {
5161 b = gtst(0, 0);
5162 } else {
5163 #if defined(TCC_TARGET_I386)
5164 b = psym(0x850f, 0);
5165 #elif defined(TCC_TARGET_ARM)
5166 b = ind;
5167 o(0x1A000000 | encbranch(ind, 0, 1));
5168 #elif defined(TCC_TARGET_C67)
5169 error("not implemented");
5170 #else
5171 #error not supported
5172 #endif
5175 /* compare low. Always unsigned */
5176 op1 = op;
5177 if (op1 == TOK_LT)
5178 op1 = TOK_ULT;
5179 else if (op1 == TOK_LE)
5180 op1 = TOK_ULE;
5181 else if (op1 == TOK_GT)
5182 op1 = TOK_UGT;
5183 else if (op1 == TOK_GE)
5184 op1 = TOK_UGE;
5185 gen_op(op1);
5186 a = gtst(1, a);
5187 gsym(b);
5188 vseti(VT_JMPI, a);
5189 break;
5193 /* handle integer constant optimizations and various machine
5194 independent opt */
5195 void gen_opic(int op)
5197 int fc, c1, c2, n;
5198 SValue *v1, *v2;
5200 v1 = vtop - 1;
5201 v2 = vtop;
5202 /* currently, we cannot do computations with forward symbols */
5203 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5204 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5205 if (c1 && c2) {
5206 fc = v2->c.i;
5207 switch(op) {
5208 case '+': v1->c.i += fc; break;
5209 case '-': v1->c.i -= fc; break;
5210 case '&': v1->c.i &= fc; break;
5211 case '^': v1->c.i ^= fc; break;
5212 case '|': v1->c.i |= fc; break;
5213 case '*': v1->c.i *= fc; break;
5215 case TOK_PDIV:
5216 case '/':
5217 case '%':
5218 case TOK_UDIV:
5219 case TOK_UMOD:
5220 /* if division by zero, generate explicit division */
5221 if (fc == 0) {
5222 if (const_wanted)
5223 error("division by zero in constant");
5224 goto general_case;
5226 switch(op) {
5227 default: v1->c.i /= fc; break;
5228 case '%': v1->c.i %= fc; break;
5229 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5230 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5232 break;
5233 case TOK_SHL: v1->c.i <<= fc; break;
5234 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5235 case TOK_SAR: v1->c.i >>= fc; break;
5236 /* tests */
5237 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5238 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5239 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5240 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5241 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5242 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5243 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5244 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5245 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5246 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5247 /* logical */
5248 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5249 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5250 default:
5251 goto general_case;
5253 vtop--;
5254 } else {
5255 /* if commutative ops, put c2 as constant */
5256 if (c1 && (op == '+' || op == '&' || op == '^' ||
5257 op == '|' || op == '*')) {
5258 vswap();
5259 swap(&c1, &c2);
5261 fc = vtop->c.i;
5262 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5263 op == TOK_PDIV) &&
5264 fc == 1) ||
5265 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5266 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5267 fc == 0) ||
5268 (op == '&' &&
5269 fc == -1))) {
5270 /* nothing to do */
5271 vtop--;
5272 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5273 /* try to use shifts instead of muls or divs */
5274 if (fc > 0 && (fc & (fc - 1)) == 0) {
5275 n = -1;
5276 while (fc) {
5277 fc >>= 1;
5278 n++;
5280 vtop->c.i = n;
5281 if (op == '*')
5282 op = TOK_SHL;
5283 else if (op == TOK_PDIV)
5284 op = TOK_SAR;
5285 else
5286 op = TOK_SHR;
5288 goto general_case;
5289 } else if (c2 && (op == '+' || op == '-') &&
5290 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5291 (VT_CONST | VT_SYM)) {
5292 /* symbol + constant case */
5293 if (op == '-')
5294 fc = -fc;
5295 vtop--;
5296 vtop->c.i += fc;
5297 } else {
5298 general_case:
5299 if (!nocode_wanted) {
5300 /* call low level op generator */
5301 gen_opi(op);
5302 } else {
5303 vtop--;
5309 /* generate a floating point operation with constant propagation */
5310 void gen_opif(int op)
5312 int c1, c2;
5313 SValue *v1, *v2;
5314 long double f1, f2;
5316 v1 = vtop - 1;
5317 v2 = vtop;
5318 /* currently, we cannot do computations with forward symbols */
5319 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5320 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5321 if (c1 && c2) {
5322 if (v1->type.t == VT_FLOAT) {
5323 f1 = v1->c.f;
5324 f2 = v2->c.f;
5325 } else if (v1->type.t == VT_DOUBLE) {
5326 f1 = v1->c.d;
5327 f2 = v2->c.d;
5328 } else {
5329 f1 = v1->c.ld;
5330 f2 = v2->c.ld;
5333 /* NOTE: we only do constant propagation if finite number (not
5334 NaN or infinity) (ANSI spec) */
5335 if (!ieee_finite(f1) || !ieee_finite(f2))
5336 goto general_case;
5338 switch(op) {
5339 case '+': f1 += f2; break;
5340 case '-': f1 -= f2; break;
5341 case '*': f1 *= f2; break;
5342 case '/':
5343 if (f2 == 0.0) {
5344 if (const_wanted)
5345 error("division by zero in constant");
5346 goto general_case;
5348 f1 /= f2;
5349 break;
5350 /* XXX: also handles tests ? */
5351 default:
5352 goto general_case;
5354 /* XXX: overflow test ? */
5355 if (v1->type.t == VT_FLOAT) {
5356 v1->c.f = f1;
5357 } else if (v1->type.t == VT_DOUBLE) {
5358 v1->c.d = f1;
5359 } else {
5360 v1->c.ld = f1;
5362 vtop--;
5363 } else {
5364 general_case:
5365 if (!nocode_wanted) {
5366 gen_opf(op);
5367 } else {
5368 vtop--;
5373 static int pointed_size(CType *type)
5375 int align;
5376 return type_size(pointed_type(type), &align);
5379 static inline int is_null_pointer(SValue *p)
5381 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5382 return 0;
5383 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5384 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5387 static inline int is_integer_btype(int bt)
5389 return (bt == VT_BYTE || bt == VT_SHORT ||
5390 bt == VT_INT || bt == VT_LLONG);
5393 /* check types for comparison or substraction of pointers */
5394 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5396 CType *type1, *type2, tmp_type1, tmp_type2;
5397 int bt1, bt2;
5399 /* null pointers are accepted for all comparisons as gcc */
5400 if (is_null_pointer(p1) || is_null_pointer(p2))
5401 return;
5402 type1 = &p1->type;
5403 type2 = &p2->type;
5404 bt1 = type1->t & VT_BTYPE;
5405 bt2 = type2->t & VT_BTYPE;
5406 /* accept comparison between pointer and integer with a warning */
5407 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5408 warning("comparison between pointer and integer");
5409 return;
5412 /* both must be pointers or implicit function pointers */
5413 if (bt1 == VT_PTR) {
5414 type1 = pointed_type(type1);
5415 } else if (bt1 != VT_FUNC)
5416 goto invalid_operands;
5418 if (bt2 == VT_PTR) {
5419 type2 = pointed_type(type2);
5420 } else if (bt2 != VT_FUNC) {
5421 invalid_operands:
5422 error("invalid operands to binary %s", get_tok_str(op, NULL));
5424 if ((type1->t & VT_BTYPE) == VT_VOID ||
5425 (type2->t & VT_BTYPE) == VT_VOID)
5426 return;
5427 tmp_type1 = *type1;
5428 tmp_type2 = *type2;
5429 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5430 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5431 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5432 /* gcc-like error if '-' is used */
5433 if (op == '-')
5434 goto invalid_operands;
5435 else
5436 warning("comparison of distinct pointer types lacks a cast");
5440 /* generic gen_op: handles types problems */
5441 void gen_op(int op)
5443 int u, t1, t2, bt1, bt2, t;
5444 CType type1;
5446 t1 = vtop[-1].type.t;
5447 t2 = vtop[0].type.t;
5448 bt1 = t1 & VT_BTYPE;
5449 bt2 = t2 & VT_BTYPE;
5451 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5452 /* at least one operand is a pointer */
5453 /* relationnal op: must be both pointers */
5454 if (op >= TOK_ULT && op <= TOK_GT) {
5455 check_comparison_pointer_types(vtop - 1, vtop, op);
5456 /* pointers are handled are unsigned */
5457 t = VT_INT | VT_UNSIGNED;
5458 goto std_op;
5460 /* if both pointers, then it must be the '-' op */
5461 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5462 if (op != '-')
5463 error("cannot use pointers here");
5464 check_comparison_pointer_types(vtop - 1, vtop, op);
5465 /* XXX: check that types are compatible */
5466 u = pointed_size(&vtop[-1].type);
5467 gen_opic(op);
5468 /* set to integer type */
5469 vtop->type.t = VT_INT;
5470 vpushi(u);
5471 gen_op(TOK_PDIV);
5472 } else {
5473 /* exactly one pointer : must be '+' or '-'. */
5474 if (op != '-' && op != '+')
5475 error("cannot use pointers here");
5476 /* Put pointer as first operand */
5477 if (bt2 == VT_PTR) {
5478 vswap();
5479 swap(&t1, &t2);
5481 type1 = vtop[-1].type;
5482 /* XXX: cast to int ? (long long case) */
5483 vpushi(pointed_size(&vtop[-1].type));
5484 gen_op('*');
5485 #ifdef CONFIG_TCC_BCHECK
5486 /* if evaluating constant expression, no code should be
5487 generated, so no bound check */
5488 if (do_bounds_check && !const_wanted) {
5489 /* if bounded pointers, we generate a special code to
5490 test bounds */
5491 if (op == '-') {
5492 vpushi(0);
5493 vswap();
5494 gen_op('-');
5496 gen_bounded_ptr_add();
5497 } else
5498 #endif
5500 gen_opic(op);
5502 /* put again type if gen_opic() swaped operands */
5503 vtop->type = type1;
5505 } else if (is_float(bt1) || is_float(bt2)) {
5506 /* compute bigger type and do implicit casts */
5507 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5508 t = VT_LDOUBLE;
5509 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5510 t = VT_DOUBLE;
5511 } else {
5512 t = VT_FLOAT;
5514 /* floats can only be used for a few operations */
5515 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5516 (op < TOK_ULT || op > TOK_GT))
5517 error("invalid operands for binary operation");
5518 goto std_op;
5519 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5520 /* cast to biggest op */
5521 t = VT_LLONG;
5522 /* convert to unsigned if it does not fit in a long long */
5523 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5524 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5525 t |= VT_UNSIGNED;
5526 goto std_op;
5527 } else {
5528 /* integer operations */
5529 t = VT_INT;
5530 /* convert to unsigned if it does not fit in an integer */
5531 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5532 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5533 t |= VT_UNSIGNED;
5534 std_op:
5535 /* XXX: currently, some unsigned operations are explicit, so
5536 we modify them here */
5537 if (t & VT_UNSIGNED) {
5538 if (op == TOK_SAR)
5539 op = TOK_SHR;
5540 else if (op == '/')
5541 op = TOK_UDIV;
5542 else if (op == '%')
5543 op = TOK_UMOD;
5544 else if (op == TOK_LT)
5545 op = TOK_ULT;
5546 else if (op == TOK_GT)
5547 op = TOK_UGT;
5548 else if (op == TOK_LE)
5549 op = TOK_ULE;
5550 else if (op == TOK_GE)
5551 op = TOK_UGE;
5553 vswap();
5554 type1.t = t;
5555 gen_cast(&type1);
5556 vswap();
5557 /* special case for shifts and long long: we keep the shift as
5558 an integer */
5559 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5560 type1.t = VT_INT;
5561 gen_cast(&type1);
5562 if (is_float(t))
5563 gen_opif(op);
5564 else if ((t & VT_BTYPE) == VT_LLONG)
5565 gen_opl(op);
5566 else
5567 gen_opic(op);
5568 if (op >= TOK_ULT && op <= TOK_GT) {
5569 /* relationnal op: the result is an int */
5570 vtop->type.t = VT_INT;
5571 } else {
5572 vtop->type.t = t;
5577 /* generic itof for unsigned long long case */
5578 void gen_cvt_itof1(int t)
5580 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5581 (VT_LLONG | VT_UNSIGNED)) {
5583 if (t == VT_FLOAT)
5584 vpush_global_sym(&func_old_type, TOK___ulltof);
5585 else if (t == VT_DOUBLE)
5586 vpush_global_sym(&func_old_type, TOK___ulltod);
5587 else
5588 vpush_global_sym(&func_old_type, TOK___ulltold);
5589 vrott(2);
5590 gfunc_call(1);
5591 vpushi(0);
5592 vtop->r = REG_FRET;
5593 } else {
5594 gen_cvt_itof(t);
5598 /* generic ftoi for unsigned long long case */
5599 void gen_cvt_ftoi1(int t)
5601 int st;
5603 if (t == (VT_LLONG | VT_UNSIGNED)) {
5604 /* not handled natively */
5605 st = vtop->type.t & VT_BTYPE;
5606 if (st == VT_FLOAT)
5607 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5608 else if (st == VT_DOUBLE)
5609 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5610 else
5611 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5612 vrott(2);
5613 gfunc_call(1);
5614 vpushi(0);
5615 vtop->r = REG_IRET;
5616 vtop->r2 = REG_LRET;
5617 } else {
5618 gen_cvt_ftoi(t);
5622 /* force char or short cast */
5623 void force_charshort_cast(int t)
5625 int bits, dbt;
5626 dbt = t & VT_BTYPE;
5627 /* XXX: add optimization if lvalue : just change type and offset */
5628 if (dbt == VT_BYTE)
5629 bits = 8;
5630 else
5631 bits = 16;
5632 if (t & VT_UNSIGNED) {
5633 vpushi((1 << bits) - 1);
5634 gen_op('&');
5635 } else {
5636 bits = 32 - bits;
5637 vpushi(bits);
5638 gen_op(TOK_SHL);
5639 vpushi(bits);
5640 gen_op(TOK_SAR);
5644 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5645 static void gen_cast(CType *type)
5647 int sbt, dbt, sf, df, c;
5649 /* special delayed cast for char/short */
5650 /* XXX: in some cases (multiple cascaded casts), it may still
5651 be incorrect */
5652 if (vtop->r & VT_MUSTCAST) {
5653 vtop->r &= ~VT_MUSTCAST;
5654 force_charshort_cast(vtop->type.t);
5657 /* bitfields first get cast to ints */
5658 if (vtop->type.t & VT_BITFIELD) {
5659 gv(RC_INT);
5662 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5663 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5665 if (sbt != dbt && !nocode_wanted) {
5666 sf = is_float(sbt);
5667 df = is_float(dbt);
5668 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5669 if (sf && df) {
5670 /* convert from fp to fp */
5671 if (c) {
5672 /* constant case: we can do it now */
5673 /* XXX: in ISOC, cannot do it if error in convert */
5674 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5675 vtop->c.f = (float)vtop->c.d;
5676 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5677 vtop->c.f = (float)vtop->c.ld;
5678 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5679 vtop->c.d = (double)vtop->c.f;
5680 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5681 vtop->c.d = (double)vtop->c.ld;
5682 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5683 vtop->c.ld = (long double)vtop->c.f;
5684 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5685 vtop->c.ld = (long double)vtop->c.d;
5686 } else {
5687 /* non constant case: generate code */
5688 gen_cvt_ftof(dbt);
5690 } else if (df) {
5691 /* convert int to fp */
5692 if (c) {
5693 switch(sbt) {
5694 case VT_LLONG | VT_UNSIGNED:
5695 case VT_LLONG:
5696 /* XXX: add const cases for long long */
5697 goto do_itof;
5698 case VT_INT | VT_UNSIGNED:
5699 switch(dbt) {
5700 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5701 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5702 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5704 break;
5705 default:
5706 switch(dbt) {
5707 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5708 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5709 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5711 break;
5713 } else {
5714 do_itof:
5715 #if !defined(TCC_TARGET_ARM)
5716 gen_cvt_itof1(dbt);
5717 #else
5718 gen_cvt_itof(dbt);
5719 #endif
5721 } else if (sf) {
5722 /* convert fp to int */
5723 /* we handle char/short/etc... with generic code */
5724 if (dbt != (VT_INT | VT_UNSIGNED) &&
5725 dbt != (VT_LLONG | VT_UNSIGNED) &&
5726 dbt != VT_LLONG)
5727 dbt = VT_INT;
5728 if (c) {
5729 switch(dbt) {
5730 case VT_LLONG | VT_UNSIGNED:
5731 case VT_LLONG:
5732 /* XXX: add const cases for long long */
5733 goto do_ftoi;
5734 case VT_INT | VT_UNSIGNED:
5735 switch(sbt) {
5736 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5737 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5738 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5740 break;
5741 default:
5742 /* int case */
5743 switch(sbt) {
5744 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5745 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5746 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5748 break;
5750 } else {
5751 do_ftoi:
5752 gen_cvt_ftoi1(dbt);
5754 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5755 /* additional cast for char/short/bool... */
5756 vtop->type.t = dbt;
5757 gen_cast(type);
5759 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5760 if ((sbt & VT_BTYPE) != VT_LLONG) {
5761 /* scalar to long long */
5762 if (c) {
5763 if (sbt == (VT_INT | VT_UNSIGNED))
5764 vtop->c.ll = vtop->c.ui;
5765 else
5766 vtop->c.ll = vtop->c.i;
5767 } else {
5768 /* machine independent conversion */
5769 gv(RC_INT);
5770 /* generate high word */
5771 if (sbt == (VT_INT | VT_UNSIGNED)) {
5772 vpushi(0);
5773 gv(RC_INT);
5774 } else {
5775 gv_dup();
5776 vpushi(31);
5777 gen_op(TOK_SAR);
5779 /* patch second register */
5780 vtop[-1].r2 = vtop->r;
5781 vpop();
5784 } else if (dbt == VT_BOOL) {
5785 /* scalar to bool */
5786 vpushi(0);
5787 gen_op(TOK_NE);
5788 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5789 (dbt & VT_BTYPE) == VT_SHORT) {
5790 force_charshort_cast(dbt);
5791 } else if ((dbt & VT_BTYPE) == VT_INT) {
5792 /* scalar to int */
5793 if (sbt == VT_LLONG) {
5794 /* from long long: just take low order word */
5795 lexpand();
5796 vpop();
5798 /* if lvalue and single word type, nothing to do because
5799 the lvalue already contains the real type size (see
5800 VT_LVAL_xxx constants) */
5803 vtop->type = *type;
5806 /* return type size. Put alignment at 'a' */
5807 static int type_size(CType *type, int *a)
5809 Sym *s;
5810 int bt;
5812 bt = type->t & VT_BTYPE;
5813 if (bt == VT_STRUCT) {
5814 /* struct/union */
5815 s = type->ref;
5816 *a = s->r;
5817 return s->c;
5818 } else if (bt == VT_PTR) {
5819 if (type->t & VT_ARRAY) {
5820 s = type->ref;
5821 return type_size(&s->type, a) * s->c;
5822 } else {
5823 *a = PTR_SIZE;
5824 return PTR_SIZE;
5826 } else if (bt == VT_LDOUBLE) {
5827 *a = LDOUBLE_ALIGN;
5828 return LDOUBLE_SIZE;
5829 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5830 #ifdef TCC_TARGET_I386
5831 *a = 4;
5832 #else
5833 *a = 8;
5834 #endif
5835 return 8;
5836 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5837 *a = 4;
5838 return 4;
5839 } else if (bt == VT_SHORT) {
5840 *a = 2;
5841 return 2;
5842 } else {
5843 /* char, void, function, _Bool */
5844 *a = 1;
5845 return 1;
5849 /* return the pointed type of t */
5850 static inline CType *pointed_type(CType *type)
5852 return &type->ref->type;
5855 /* modify type so that its it is a pointer to type. */
5856 static void mk_pointer(CType *type)
5858 Sym *s;
5859 s = sym_push(SYM_FIELD, type, 0, -1);
5860 type->t = VT_PTR | (type->t & ~VT_TYPE);
5861 type->ref = s;
5864 /* compare function types. OLD functions match any new functions */
5865 static int is_compatible_func(CType *type1, CType *type2)
5867 Sym *s1, *s2;
5869 s1 = type1->ref;
5870 s2 = type2->ref;
5871 if (!is_compatible_types(&s1->type, &s2->type))
5872 return 0;
5873 /* check func_call */
5874 if (s1->r != s2->r)
5875 return 0;
5876 /* XXX: not complete */
5877 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5878 return 1;
5879 if (s1->c != s2->c)
5880 return 0;
5881 while (s1 != NULL) {
5882 if (s2 == NULL)
5883 return 0;
5884 if (!is_compatible_types(&s1->type, &s2->type))
5885 return 0;
5886 s1 = s1->next;
5887 s2 = s2->next;
5889 if (s2)
5890 return 0;
5891 return 1;
5894 /* return true if type1 and type2 are exactly the same (including
5895 qualifiers).
5897 - enums are not checked as gcc __builtin_types_compatible_p ()
5899 static int is_compatible_types(CType *type1, CType *type2)
5901 int bt1, t1, t2;
5903 t1 = type1->t & VT_TYPE;
5904 t2 = type2->t & VT_TYPE;
5905 /* XXX: bitfields ? */
5906 if (t1 != t2)
5907 return 0;
5908 /* test more complicated cases */
5909 bt1 = t1 & VT_BTYPE;
5910 if (bt1 == VT_PTR) {
5911 type1 = pointed_type(type1);
5912 type2 = pointed_type(type2);
5913 return is_compatible_types(type1, type2);
5914 } else if (bt1 == VT_STRUCT) {
5915 return (type1->ref == type2->ref);
5916 } else if (bt1 == VT_FUNC) {
5917 return is_compatible_func(type1, type2);
5918 } else {
5919 return 1;
5923 /* print a type. If 'varstr' is not NULL, then the variable is also
5924 printed in the type */
5925 /* XXX: union */
5926 /* XXX: add array and function pointers */
5927 void type_to_str(char *buf, int buf_size,
5928 CType *type, const char *varstr)
5930 int bt, v, t;
5931 Sym *s, *sa;
5932 char buf1[256];
5933 const char *tstr;
5935 t = type->t & VT_TYPE;
5936 bt = t & VT_BTYPE;
5937 buf[0] = '\0';
5938 if (t & VT_CONSTANT)
5939 pstrcat(buf, buf_size, "const ");
5940 if (t & VT_VOLATILE)
5941 pstrcat(buf, buf_size, "volatile ");
5942 if (t & VT_UNSIGNED)
5943 pstrcat(buf, buf_size, "unsigned ");
5944 switch(bt) {
5945 case VT_VOID:
5946 tstr = "void";
5947 goto add_tstr;
5948 case VT_BOOL:
5949 tstr = "_Bool";
5950 goto add_tstr;
5951 case VT_BYTE:
5952 tstr = "char";
5953 goto add_tstr;
5954 case VT_SHORT:
5955 tstr = "short";
5956 goto add_tstr;
5957 case VT_INT:
5958 tstr = "int";
5959 goto add_tstr;
5960 case VT_LONG:
5961 tstr = "long";
5962 goto add_tstr;
5963 case VT_LLONG:
5964 tstr = "long long";
5965 goto add_tstr;
5966 case VT_FLOAT:
5967 tstr = "float";
5968 goto add_tstr;
5969 case VT_DOUBLE:
5970 tstr = "double";
5971 goto add_tstr;
5972 case VT_LDOUBLE:
5973 tstr = "long double";
5974 add_tstr:
5975 pstrcat(buf, buf_size, tstr);
5976 break;
5977 case VT_ENUM:
5978 case VT_STRUCT:
5979 if (bt == VT_STRUCT)
5980 tstr = "struct ";
5981 else
5982 tstr = "enum ";
5983 pstrcat(buf, buf_size, tstr);
5984 v = type->ref->v & ~SYM_STRUCT;
5985 if (v >= SYM_FIRST_ANOM)
5986 pstrcat(buf, buf_size, "<anonymous>");
5987 else
5988 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5989 break;
5990 case VT_FUNC:
5991 s = type->ref;
5992 type_to_str(buf, buf_size, &s->type, varstr);
5993 pstrcat(buf, buf_size, "(");
5994 sa = s->next;
5995 while (sa != NULL) {
5996 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5997 pstrcat(buf, buf_size, buf1);
5998 sa = sa->next;
5999 if (sa)
6000 pstrcat(buf, buf_size, ", ");
6002 pstrcat(buf, buf_size, ")");
6003 goto no_var;
6004 case VT_PTR:
6005 s = type->ref;
6006 pstrcpy(buf1, sizeof(buf1), "*");
6007 if (varstr)
6008 pstrcat(buf1, sizeof(buf1), varstr);
6009 type_to_str(buf, buf_size, &s->type, buf1);
6010 goto no_var;
6012 if (varstr) {
6013 pstrcat(buf, buf_size, " ");
6014 pstrcat(buf, buf_size, varstr);
6016 no_var: ;
6019 /* verify type compatibility to store vtop in 'dt' type, and generate
6020 casts if needed. */
6021 static void gen_assign_cast(CType *dt)
6023 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6024 char buf1[256], buf2[256];
6025 int dbt, sbt;
6027 st = &vtop->type; /* source type */
6028 dbt = dt->t & VT_BTYPE;
6029 sbt = st->t & VT_BTYPE;
6030 if (dt->t & VT_CONSTANT)
6031 warning("assignment of read-only location");
6032 switch(dbt) {
6033 case VT_PTR:
6034 /* special cases for pointers */
6035 /* '0' can also be a pointer */
6036 if (is_null_pointer(vtop))
6037 goto type_ok;
6038 /* accept implicit pointer to integer cast with warning */
6039 if (is_integer_btype(sbt)) {
6040 warning("assignment makes pointer from integer without a cast");
6041 goto type_ok;
6043 type1 = pointed_type(dt);
6044 /* a function is implicitely a function pointer */
6045 if (sbt == VT_FUNC) {
6046 if ((type1->t & VT_BTYPE) != VT_VOID &&
6047 !is_compatible_types(pointed_type(dt), st))
6048 goto error;
6049 else
6050 goto type_ok;
6052 if (sbt != VT_PTR)
6053 goto error;
6054 type2 = pointed_type(st);
6055 if ((type1->t & VT_BTYPE) == VT_VOID ||
6056 (type2->t & VT_BTYPE) == VT_VOID) {
6057 /* void * can match anything */
6058 } else {
6059 /* exact type match, except for unsigned */
6060 tmp_type1 = *type1;
6061 tmp_type2 = *type2;
6062 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6063 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6064 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6065 goto error;
6067 /* check const and volatile */
6068 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6069 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6070 warning("assignment discards qualifiers from pointer target type");
6071 break;
6072 case VT_BYTE:
6073 case VT_SHORT:
6074 case VT_INT:
6075 case VT_LLONG:
6076 if (sbt == VT_PTR || sbt == VT_FUNC) {
6077 warning("assignment makes integer from pointer without a cast");
6079 /* XXX: more tests */
6080 break;
6081 case VT_STRUCT:
6082 tmp_type1 = *dt;
6083 tmp_type2 = *st;
6084 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6085 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6086 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6087 error:
6088 type_to_str(buf1, sizeof(buf1), st, NULL);
6089 type_to_str(buf2, sizeof(buf2), dt, NULL);
6090 error("cannot cast '%s' to '%s'", buf1, buf2);
6092 break;
6094 type_ok:
6095 gen_cast(dt);
6098 /* store vtop in lvalue pushed on stack */
6099 void vstore(void)
6101 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6103 ft = vtop[-1].type.t;
6104 sbt = vtop->type.t & VT_BTYPE;
6105 dbt = ft & VT_BTYPE;
6106 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6107 (sbt == VT_INT && dbt == VT_SHORT)) {
6108 /* optimize char/short casts */
6109 delayed_cast = VT_MUSTCAST;
6110 vtop->type.t = ft & VT_TYPE;
6111 /* XXX: factorize */
6112 if (ft & VT_CONSTANT)
6113 warning("assignment of read-only location");
6114 } else {
6115 delayed_cast = 0;
6116 if (!(ft & VT_BITFIELD))
6117 gen_assign_cast(&vtop[-1].type);
6120 if (sbt == VT_STRUCT) {
6121 /* if structure, only generate pointer */
6122 /* structure assignment : generate memcpy */
6123 /* XXX: optimize if small size */
6124 if (!nocode_wanted) {
6125 size = type_size(&vtop->type, &align);
6127 vpush_global_sym(&func_old_type, TOK_memcpy);
6129 /* destination */
6130 vpushv(vtop - 2);
6131 vtop->type.t = VT_INT;
6132 gaddrof();
6133 /* source */
6134 vpushv(vtop - 2);
6135 vtop->type.t = VT_INT;
6136 gaddrof();
6137 /* type size */
6138 vpushi(size);
6139 gfunc_call(3);
6141 vswap();
6142 vpop();
6143 } else {
6144 vswap();
6145 vpop();
6147 /* leave source on stack */
6148 } else if (ft & VT_BITFIELD) {
6149 /* bitfield store handling */
6150 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6151 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6152 /* remove bit field info to avoid loops */
6153 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6155 /* duplicate destination */
6156 vdup();
6157 vtop[-1] = vtop[-2];
6159 /* mask and shift source */
6160 vpushi((1 << bit_size) - 1);
6161 gen_op('&');
6162 vpushi(bit_pos);
6163 gen_op(TOK_SHL);
6164 /* load destination, mask and or with source */
6165 vswap();
6166 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6167 gen_op('&');
6168 gen_op('|');
6169 /* store result */
6170 vstore();
6171 } else {
6172 #ifdef CONFIG_TCC_BCHECK
6173 /* bound check case */
6174 if (vtop[-1].r & VT_MUSTBOUND) {
6175 vswap();
6176 gbound();
6177 vswap();
6179 #endif
6180 if (!nocode_wanted) {
6181 rc = RC_INT;
6182 if (is_float(ft))
6183 rc = RC_FLOAT;
6184 r = gv(rc); /* generate value */
6185 /* if lvalue was saved on stack, must read it */
6186 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6187 SValue sv;
6188 t = get_reg(RC_INT);
6189 sv.type.t = VT_INT;
6190 sv.r = VT_LOCAL | VT_LVAL;
6191 sv.c.ul = vtop[-1].c.ul;
6192 load(t, &sv);
6193 vtop[-1].r = t | VT_LVAL;
6195 store(r, vtop - 1);
6196 /* two word case handling : store second register at word + 4 */
6197 if ((ft & VT_BTYPE) == VT_LLONG) {
6198 vswap();
6199 /* convert to int to increment easily */
6200 vtop->type.t = VT_INT;
6201 gaddrof();
6202 vpushi(4);
6203 gen_op('+');
6204 vtop->r |= VT_LVAL;
6205 vswap();
6206 /* XXX: it works because r2 is spilled last ! */
6207 store(vtop->r2, vtop - 1);
6210 vswap();
6211 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6212 vtop->r |= delayed_cast;
6216 /* post defines POST/PRE add. c is the token ++ or -- */
6217 void inc(int post, int c)
6219 test_lvalue();
6220 vdup(); /* save lvalue */
6221 if (post) {
6222 gv_dup(); /* duplicate value */
6223 vrotb(3);
6224 vrotb(3);
6226 /* add constant */
6227 vpushi(c - TOK_MID);
6228 gen_op('+');
6229 vstore(); /* store value */
6230 if (post)
6231 vpop(); /* if post op, return saved value */
6234 /* Parse GNUC __attribute__ extension. Currently, the following
6235 extensions are recognized:
6236 - aligned(n) : set data/function alignment.
6237 - packed : force data alignment to 1
6238 - section(x) : generate data/code in this section.
6239 - unused : currently ignored, but may be used someday.
6240 - regparm(n) : pass function parameters in registers (i386 only)
6242 static void parse_attribute(AttributeDef *ad)
6244 int t, n;
6246 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6247 next();
6248 skip('(');
6249 skip('(');
6250 while (tok != ')') {
6251 if (tok < TOK_IDENT)
6252 expect("attribute name");
6253 t = tok;
6254 next();
6255 switch(t) {
6256 case TOK_SECTION1:
6257 case TOK_SECTION2:
6258 skip('(');
6259 if (tok != TOK_STR)
6260 expect("section name");
6261 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6262 next();
6263 skip(')');
6264 break;
6265 case TOK_ALIGNED1:
6266 case TOK_ALIGNED2:
6267 if (tok == '(') {
6268 next();
6269 n = expr_const();
6270 if (n <= 0 || (n & (n - 1)) != 0)
6271 error("alignment must be a positive power of two");
6272 skip(')');
6273 } else {
6274 n = MAX_ALIGN;
6276 ad->aligned = n;
6277 break;
6278 case TOK_PACKED1:
6279 case TOK_PACKED2:
6280 ad->packed = 1;
6281 break;
6282 case TOK_UNUSED1:
6283 case TOK_UNUSED2:
6284 /* currently, no need to handle it because tcc does not
6285 track unused objects */
6286 break;
6287 case TOK_NORETURN1:
6288 case TOK_NORETURN2:
6289 /* currently, no need to handle it because tcc does not
6290 track unused objects */
6291 break;
6292 case TOK_CDECL1:
6293 case TOK_CDECL2:
6294 case TOK_CDECL3:
6295 ad->func_call = FUNC_CDECL;
6296 break;
6297 case TOK_STDCALL1:
6298 case TOK_STDCALL2:
6299 case TOK_STDCALL3:
6300 ad->func_call = FUNC_STDCALL;
6301 break;
6302 #ifdef TCC_TARGET_I386
6303 case TOK_REGPARM1:
6304 case TOK_REGPARM2:
6305 skip('(');
6306 n = expr_const();
6307 if (n > 3)
6308 n = 3;
6309 else if (n < 0)
6310 n = 0;
6311 if (n > 0)
6312 ad->func_call = FUNC_FASTCALL1 + n - 1;
6313 skip(')');
6314 break;
6315 #endif
6316 case TOK_DLLEXPORT:
6317 ad->dllexport = 1;
6318 break;
6319 default:
6320 if (tcc_state->warn_unsupported)
6321 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6322 /* skip parameters */
6323 /* XXX: skip parenthesis too */
6324 if (tok == '(') {
6325 next();
6326 while (tok != ')' && tok != -1)
6327 next();
6328 next();
6330 break;
6332 if (tok != ',')
6333 break;
6334 next();
6336 skip(')');
6337 skip(')');
6341 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6342 static void struct_decl(CType *type, int u)
6344 int a, v, size, align, maxalign, c, offset;
6345 int bit_size, bit_pos, bsize, bt, lbit_pos;
6346 Sym *s, *ss, **ps;
6347 AttributeDef ad;
6348 CType type1, btype;
6350 a = tok; /* save decl type */
6351 next();
6352 if (tok != '{') {
6353 v = tok;
6354 next();
6355 /* struct already defined ? return it */
6356 if (v < TOK_IDENT)
6357 expect("struct/union/enum name");
6358 s = struct_find(v);
6359 if (s) {
6360 if (s->type.t != a)
6361 error("invalid type");
6362 goto do_decl;
6364 } else {
6365 v = anon_sym++;
6367 type1.t = a;
6368 /* we put an undefined size for struct/union */
6369 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6370 s->r = 0; /* default alignment is zero as gcc */
6371 /* put struct/union/enum name in type */
6372 do_decl:
6373 type->t = u;
6374 type->ref = s;
6376 if (tok == '{') {
6377 next();
6378 if (s->c != -1)
6379 error("struct/union/enum already defined");
6380 /* cannot be empty */
6381 c = 0;
6382 /* non empty enums are not allowed */
6383 if (a == TOK_ENUM) {
6384 for(;;) {
6385 v = tok;
6386 if (v < TOK_UIDENT)
6387 expect("identifier");
6388 next();
6389 if (tok == '=') {
6390 next();
6391 c = expr_const();
6393 /* enum symbols have static storage */
6394 ss = sym_push(v, &int_type, VT_CONST, c);
6395 ss->type.t |= VT_STATIC;
6396 if (tok != ',')
6397 break;
6398 next();
6399 c++;
6400 /* NOTE: we accept a trailing comma */
6401 if (tok == '}')
6402 break;
6404 skip('}');
6405 } else {
6406 maxalign = 1;
6407 ps = &s->next;
6408 bit_pos = 0;
6409 offset = 0;
6410 while (tok != '}') {
6411 parse_btype(&btype, &ad);
6412 while (1) {
6413 bit_size = -1;
6414 v = 0;
6415 type1 = btype;
6416 if (tok != ':') {
6417 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6418 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6419 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6420 error("invalid type for '%s'",
6421 get_tok_str(v, NULL));
6423 if (tok == ':') {
6424 next();
6425 bit_size = expr_const();
6426 /* XXX: handle v = 0 case for messages */
6427 if (bit_size < 0)
6428 error("negative width in bit-field '%s'",
6429 get_tok_str(v, NULL));
6430 if (v && bit_size == 0)
6431 error("zero width for bit-field '%s'",
6432 get_tok_str(v, NULL));
6434 size = type_size(&type1, &align);
6435 if (ad.aligned) {
6436 if (align < ad.aligned)
6437 align = ad.aligned;
6438 } else if (ad.packed) {
6439 align = 1;
6441 lbit_pos = 0;
6442 if (bit_size >= 0) {
6443 bt = type1.t & VT_BTYPE;
6444 if (bt != VT_INT &&
6445 bt != VT_BYTE &&
6446 bt != VT_SHORT &&
6447 bt != VT_BOOL &&
6448 bt != VT_ENUM)
6449 error("bitfields must have scalar type");
6450 bsize = size * 8;
6451 if (bit_size > bsize) {
6452 error("width of '%s' exceeds its type",
6453 get_tok_str(v, NULL));
6454 } else if (bit_size == bsize) {
6455 /* no need for bit fields */
6456 bit_pos = 0;
6457 } else if (bit_size == 0) {
6458 /* XXX: what to do if only padding in a
6459 structure ? */
6460 /* zero size: means to pad */
6461 if (bit_pos > 0)
6462 bit_pos = bsize;
6463 } else {
6464 /* we do not have enough room ? */
6465 if ((bit_pos + bit_size) > bsize)
6466 bit_pos = 0;
6467 lbit_pos = bit_pos;
6468 /* XXX: handle LSB first */
6469 type1.t |= VT_BITFIELD |
6470 (bit_pos << VT_STRUCT_SHIFT) |
6471 (bit_size << (VT_STRUCT_SHIFT + 6));
6472 bit_pos += bit_size;
6474 } else {
6475 bit_pos = 0;
6477 if (v) {
6478 /* add new memory data only if starting
6479 bit field */
6480 if (lbit_pos == 0) {
6481 if (a == TOK_STRUCT) {
6482 c = (c + align - 1) & -align;
6483 offset = c;
6484 c += size;
6485 } else {
6486 offset = 0;
6487 if (size > c)
6488 c = size;
6490 if (align > maxalign)
6491 maxalign = align;
6493 #if 0
6494 printf("add field %s offset=%d",
6495 get_tok_str(v, NULL), offset);
6496 if (type1.t & VT_BITFIELD) {
6497 printf(" pos=%d size=%d",
6498 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6499 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6501 printf("\n");
6502 #endif
6503 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6504 *ps = ss;
6505 ps = &ss->next;
6507 if (tok == ';' || tok == TOK_EOF)
6508 break;
6509 skip(',');
6511 skip(';');
6513 skip('}');
6514 /* store size and alignment */
6515 s->c = (c + maxalign - 1) & -maxalign;
6516 s->r = maxalign;
6521 /* return 0 if no type declaration. otherwise, return the basic type
6522 and skip it.
6524 static int parse_btype(CType *type, AttributeDef *ad)
6526 int t, u, type_found, typespec_found;
6527 Sym *s;
6528 CType type1;
6530 memset(ad, 0, sizeof(AttributeDef));
6531 type_found = 0;
6532 typespec_found = 0;
6533 t = 0;
6534 while(1) {
6535 switch(tok) {
6536 case TOK_EXTENSION:
6537 /* currently, we really ignore extension */
6538 next();
6539 continue;
6541 /* basic types */
6542 case TOK_CHAR:
6543 u = VT_BYTE;
6544 basic_type:
6545 next();
6546 basic_type1:
6547 if ((t & VT_BTYPE) != 0)
6548 error("too many basic types");
6549 t |= u;
6550 typespec_found = 1;
6551 break;
6552 case TOK_VOID:
6553 u = VT_VOID;
6554 goto basic_type;
6555 case TOK_SHORT:
6556 u = VT_SHORT;
6557 goto basic_type;
6558 case TOK_INT:
6559 next();
6560 typespec_found = 1;
6561 break;
6562 case TOK_LONG:
6563 next();
6564 if ((t & VT_BTYPE) == VT_DOUBLE) {
6565 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6566 } else if ((t & VT_BTYPE) == VT_LONG) {
6567 t = (t & ~VT_BTYPE) | VT_LLONG;
6568 } else {
6569 u = VT_LONG;
6570 goto basic_type1;
6572 break;
6573 case TOK_BOOL:
6574 u = VT_BOOL;
6575 goto basic_type;
6576 case TOK_FLOAT:
6577 u = VT_FLOAT;
6578 goto basic_type;
6579 case TOK_DOUBLE:
6580 next();
6581 if ((t & VT_BTYPE) == VT_LONG) {
6582 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6583 } else {
6584 u = VT_DOUBLE;
6585 goto basic_type1;
6587 break;
6588 case TOK_ENUM:
6589 struct_decl(&type1, VT_ENUM);
6590 basic_type2:
6591 u = type1.t;
6592 type->ref = type1.ref;
6593 goto basic_type1;
6594 case TOK_STRUCT:
6595 case TOK_UNION:
6596 struct_decl(&type1, VT_STRUCT);
6597 goto basic_type2;
6599 /* type modifiers */
6600 case TOK_CONST1:
6601 case TOK_CONST2:
6602 case TOK_CONST3:
6603 t |= VT_CONSTANT;
6604 next();
6605 break;
6606 case TOK_VOLATILE1:
6607 case TOK_VOLATILE2:
6608 case TOK_VOLATILE3:
6609 t |= VT_VOLATILE;
6610 next();
6611 break;
6612 case TOK_SIGNED1:
6613 case TOK_SIGNED2:
6614 case TOK_SIGNED3:
6615 typespec_found = 1;
6616 t |= VT_SIGNED;
6617 next();
6618 break;
6619 case TOK_REGISTER:
6620 case TOK_AUTO:
6621 case TOK_RESTRICT1:
6622 case TOK_RESTRICT2:
6623 case TOK_RESTRICT3:
6624 next();
6625 break;
6626 case TOK_UNSIGNED:
6627 t |= VT_UNSIGNED;
6628 next();
6629 typespec_found = 1;
6630 break;
6632 /* storage */
6633 case TOK_EXTERN:
6634 t |= VT_EXTERN;
6635 next();
6636 break;
6637 case TOK_STATIC:
6638 t |= VT_STATIC;
6639 next();
6640 break;
6641 case TOK_TYPEDEF:
6642 t |= VT_TYPEDEF;
6643 next();
6644 break;
6645 case TOK_INLINE1:
6646 case TOK_INLINE2:
6647 case TOK_INLINE3:
6648 t |= VT_INLINE;
6649 next();
6650 break;
6652 /* GNUC attribute */
6653 case TOK_ATTRIBUTE1:
6654 case TOK_ATTRIBUTE2:
6655 parse_attribute(ad);
6656 break;
6657 /* GNUC typeof */
6658 case TOK_TYPEOF1:
6659 case TOK_TYPEOF2:
6660 case TOK_TYPEOF3:
6661 next();
6662 parse_expr_type(&type1);
6663 goto basic_type2;
6664 default:
6665 if (typespec_found)
6666 goto the_end;
6667 s = sym_find(tok);
6668 if (!s || !(s->type.t & VT_TYPEDEF))
6669 goto the_end;
6670 t |= (s->type.t & ~VT_TYPEDEF);
6671 type->ref = s->type.ref;
6672 next();
6673 break;
6675 type_found = 1;
6677 the_end:
6678 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6679 error("signed and unsigned modifier");
6680 if (tcc_state->char_is_unsigned) {
6681 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6682 t |= VT_UNSIGNED;
6684 t &= ~VT_SIGNED;
6686 /* long is never used as type */
6687 if ((t & VT_BTYPE) == VT_LONG)
6688 t = (t & ~VT_BTYPE) | VT_INT;
6689 type->t = t;
6690 return type_found;
6693 /* convert a function parameter type (array to pointer and function to
6694 function pointer) */
6695 static inline void convert_parameter_type(CType *pt)
6697 /* remove const and volatile qualifiers (XXX: const could be used
6698 to indicate a const function parameter */
6699 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6700 /* array must be transformed to pointer according to ANSI C */
6701 pt->t &= ~VT_ARRAY;
6702 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6703 mk_pointer(pt);
6707 static void post_type(CType *type, AttributeDef *ad)
6709 int n, l, t1;
6710 Sym **plast, *s, *first;
6711 AttributeDef ad1;
6712 CType pt;
6714 if (tok == '(') {
6715 /* function declaration */
6716 next();
6717 l = 0;
6718 first = NULL;
6719 plast = &first;
6720 while (tok != ')') {
6721 /* read param name and compute offset */
6722 if (l != FUNC_OLD) {
6723 if (!parse_btype(&pt, &ad1)) {
6724 if (l) {
6725 error("invalid type");
6726 } else {
6727 l = FUNC_OLD;
6728 goto old_proto;
6731 l = FUNC_NEW;
6732 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6733 break;
6734 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6735 if ((pt.t & VT_BTYPE) == VT_VOID)
6736 error("parameter declared as void");
6737 } else {
6738 old_proto:
6739 n = tok;
6740 pt.t = VT_INT;
6741 next();
6743 convert_parameter_type(&pt);
6744 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6745 *plast = s;
6746 plast = &s->next;
6747 if (tok == ',') {
6748 next();
6749 if (l == FUNC_NEW && tok == TOK_DOTS) {
6750 l = FUNC_ELLIPSIS;
6751 next();
6752 break;
6756 /* if no parameters, then old type prototype */
6757 if (l == 0)
6758 l = FUNC_OLD;
6759 skip(')');
6760 t1 = type->t & VT_STORAGE;
6761 /* NOTE: const is ignored in returned type as it has a special
6762 meaning in gcc / C++ */
6763 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6764 post_type(type, ad);
6765 /* we push a anonymous symbol which will contain the function prototype */
6766 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6767 s->next = first;
6768 type->t = t1 | VT_FUNC;
6769 type->ref = s;
6770 } else if (tok == '[') {
6771 /* array definition */
6772 next();
6773 n = -1;
6774 if (tok != ']') {
6775 n = expr_const();
6776 if (n < 0)
6777 error("invalid array size");
6779 skip(']');
6780 /* parse next post type */
6781 t1 = type->t & VT_STORAGE;
6782 type->t &= ~VT_STORAGE;
6783 post_type(type, ad);
6785 /* we push a anonymous symbol which will contain the array
6786 element type */
6787 s = sym_push(SYM_FIELD, type, 0, n);
6788 type->t = t1 | VT_ARRAY | VT_PTR;
6789 type->ref = s;
6793 /* Parse a type declaration (except basic type), and return the type
6794 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6795 expected. 'type' should contain the basic type. 'ad' is the
6796 attribute definition of the basic type. It can be modified by
6797 type_decl().
6799 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6801 Sym *s;
6802 CType type1, *type2;
6803 int qualifiers;
6805 while (tok == '*') {
6806 qualifiers = 0;
6807 redo:
6808 next();
6809 switch(tok) {
6810 case TOK_CONST1:
6811 case TOK_CONST2:
6812 case TOK_CONST3:
6813 qualifiers |= VT_CONSTANT;
6814 goto redo;
6815 case TOK_VOLATILE1:
6816 case TOK_VOLATILE2:
6817 case TOK_VOLATILE3:
6818 qualifiers |= VT_VOLATILE;
6819 goto redo;
6820 case TOK_RESTRICT1:
6821 case TOK_RESTRICT2:
6822 case TOK_RESTRICT3:
6823 goto redo;
6825 mk_pointer(type);
6826 type->t |= qualifiers;
6829 /* XXX: clarify attribute handling */
6830 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6831 parse_attribute(ad);
6833 /* recursive type */
6834 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6835 type1.t = 0; /* XXX: same as int */
6836 if (tok == '(') {
6837 next();
6838 /* XXX: this is not correct to modify 'ad' at this point, but
6839 the syntax is not clear */
6840 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6841 parse_attribute(ad);
6842 type_decl(&type1, ad, v, td);
6843 skip(')');
6844 } else {
6845 /* type identifier */
6846 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6847 *v = tok;
6848 next();
6849 } else {
6850 if (!(td & TYPE_ABSTRACT))
6851 expect("identifier");
6852 *v = 0;
6855 post_type(type, ad);
6856 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6857 parse_attribute(ad);
6858 if (!type1.t)
6859 return;
6860 /* append type at the end of type1 */
6861 type2 = &type1;
6862 for(;;) {
6863 s = type2->ref;
6864 type2 = &s->type;
6865 if (!type2->t) {
6866 *type2 = *type;
6867 break;
6870 *type = type1;
6873 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6874 static int lvalue_type(int t)
6876 int bt, r;
6877 r = VT_LVAL;
6878 bt = t & VT_BTYPE;
6879 if (bt == VT_BYTE || bt == VT_BOOL)
6880 r |= VT_LVAL_BYTE;
6881 else if (bt == VT_SHORT)
6882 r |= VT_LVAL_SHORT;
6883 else
6884 return r;
6885 if (t & VT_UNSIGNED)
6886 r |= VT_LVAL_UNSIGNED;
6887 return r;
6890 /* indirection with full error checking and bound check */
6891 static void indir(void)
6893 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6894 expect("pointer");
6895 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6896 gv(RC_INT);
6897 vtop->type = *pointed_type(&vtop->type);
6898 /* an array is never an lvalue */
6899 if (!(vtop->type.t & VT_ARRAY)) {
6900 vtop->r |= lvalue_type(vtop->type.t);
6901 /* if bound checking, the referenced pointer must be checked */
6902 if (do_bounds_check)
6903 vtop->r |= VT_MUSTBOUND;
6907 /* pass a parameter to a function and do type checking and casting */
6908 static void gfunc_param_typed(Sym *func, Sym *arg)
6910 int func_type;
6911 CType type;
6913 func_type = func->c;
6914 if (func_type == FUNC_OLD ||
6915 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6916 /* default casting : only need to convert float to double */
6917 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6918 type.t = VT_DOUBLE;
6919 gen_cast(&type);
6921 } else if (arg == NULL) {
6922 error("too many arguments to function");
6923 } else {
6924 type = arg->type;
6925 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6926 gen_assign_cast(&type);
6930 /* parse an expression of the form '(type)' or '(expr)' and return its
6931 type */
6932 static void parse_expr_type(CType *type)
6934 int n;
6935 AttributeDef ad;
6937 skip('(');
6938 if (parse_btype(type, &ad)) {
6939 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6940 } else {
6941 expr_type(type);
6943 skip(')');
6946 static void parse_type(CType *type)
6948 AttributeDef ad;
6949 int n;
6951 if (!parse_btype(type, &ad)) {
6952 expect("type");
6954 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6957 static void vpush_tokc(int t)
6959 CType type;
6960 type.t = t;
6961 vsetc(&type, VT_CONST, &tokc);
6964 static void unary(void)
6966 int n, t, align, size, r;
6967 CType type;
6968 Sym *s;
6969 AttributeDef ad;
6971 /* XXX: GCC 2.95.3 does not generate a table although it should be
6972 better here */
6973 tok_next:
6974 switch(tok) {
6975 case TOK_EXTENSION:
6976 next();
6977 goto tok_next;
6978 case TOK_CINT:
6979 case TOK_CCHAR:
6980 case TOK_LCHAR:
6981 vpushi(tokc.i);
6982 next();
6983 break;
6984 case TOK_CUINT:
6985 vpush_tokc(VT_INT | VT_UNSIGNED);
6986 next();
6987 break;
6988 case TOK_CLLONG:
6989 vpush_tokc(VT_LLONG);
6990 next();
6991 break;
6992 case TOK_CULLONG:
6993 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6994 next();
6995 break;
6996 case TOK_CFLOAT:
6997 vpush_tokc(VT_FLOAT);
6998 next();
6999 break;
7000 case TOK_CDOUBLE:
7001 vpush_tokc(VT_DOUBLE);
7002 next();
7003 break;
7004 case TOK_CLDOUBLE:
7005 vpush_tokc(VT_LDOUBLE);
7006 next();
7007 break;
7008 case TOK___FUNCTION__:
7009 if (!gnu_ext)
7010 goto tok_identifier;
7011 /* fall thru */
7012 case TOK___FUNC__:
7014 void *ptr;
7015 int len;
7016 /* special function name identifier */
7017 len = strlen(funcname) + 1;
7018 /* generate char[len] type */
7019 type.t = VT_BYTE;
7020 mk_pointer(&type);
7021 type.t |= VT_ARRAY;
7022 type.ref->c = len;
7023 vpush_ref(&type, data_section, data_section->data_offset, len);
7024 ptr = section_ptr_add(data_section, len);
7025 memcpy(ptr, funcname, len);
7026 next();
7028 break;
7029 case TOK_LSTR:
7030 t = VT_INT;
7031 goto str_init;
7032 case TOK_STR:
7033 /* string parsing */
7034 t = VT_BYTE;
7035 str_init:
7036 if (tcc_state->warn_write_strings)
7037 t |= VT_CONSTANT;
7038 type.t = t;
7039 mk_pointer(&type);
7040 type.t |= VT_ARRAY;
7041 memset(&ad, 0, sizeof(AttributeDef));
7042 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7043 break;
7044 case '(':
7045 next();
7046 /* cast ? */
7047 if (parse_btype(&type, &ad)) {
7048 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7049 skip(')');
7050 /* check ISOC99 compound literal */
7051 if (tok == '{') {
7052 /* data is allocated locally by default */
7053 if (global_expr)
7054 r = VT_CONST;
7055 else
7056 r = VT_LOCAL;
7057 /* all except arrays are lvalues */
7058 if (!(type.t & VT_ARRAY))
7059 r |= lvalue_type(type.t);
7060 memset(&ad, 0, sizeof(AttributeDef));
7061 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7062 } else {
7063 unary();
7064 gen_cast(&type);
7066 } else if (tok == '{') {
7067 /* save all registers */
7068 save_regs(0);
7069 /* statement expression : we do not accept break/continue
7070 inside as GCC does */
7071 block(NULL, NULL, NULL, NULL, 0, 1);
7072 skip(')');
7073 } else {
7074 gexpr();
7075 skip(')');
7077 break;
7078 case '*':
7079 next();
7080 unary();
7081 indir();
7082 break;
7083 case '&':
7084 next();
7085 unary();
7086 /* functions names must be treated as function pointers,
7087 except for unary '&' and sizeof. Since we consider that
7088 functions are not lvalues, we only have to handle it
7089 there and in function calls. */
7090 /* arrays can also be used although they are not lvalues */
7091 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7092 !(vtop->type.t & VT_ARRAY))
7093 test_lvalue();
7094 mk_pointer(&vtop->type);
7095 gaddrof();
7096 break;
7097 case '!':
7098 next();
7099 unary();
7100 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7101 vtop->c.i = !vtop->c.i;
7102 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7103 vtop->c.i = vtop->c.i ^ 1;
7104 else
7105 vseti(VT_JMP, gtst(1, 0));
7106 break;
7107 case '~':
7108 next();
7109 unary();
7110 vpushi(-1);
7111 gen_op('^');
7112 break;
7113 case '+':
7114 next();
7115 /* in order to force cast, we add zero */
7116 unary();
7117 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7118 error("pointer not accepted for unary plus");
7119 vpushi(0);
7120 gen_op('+');
7121 break;
7122 case TOK_SIZEOF:
7123 case TOK_ALIGNOF1:
7124 case TOK_ALIGNOF2:
7125 t = tok;
7126 next();
7127 if (tok == '(') {
7128 parse_expr_type(&type);
7129 } else {
7130 unary_type(&type);
7132 size = type_size(&type, &align);
7133 if (t == TOK_SIZEOF) {
7134 if (size < 0)
7135 error("sizeof applied to an incomplete type");
7136 vpushi(size);
7137 } else {
7138 vpushi(align);
7140 break;
7142 case TOK_builtin_types_compatible_p:
7144 CType type1, type2;
7145 next();
7146 skip('(');
7147 parse_type(&type1);
7148 skip(',');
7149 parse_type(&type2);
7150 skip(')');
7151 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7152 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7153 vpushi(is_compatible_types(&type1, &type2));
7155 break;
7156 case TOK_builtin_constant_p:
7158 int saved_nocode_wanted, res;
7159 next();
7160 skip('(');
7161 saved_nocode_wanted = nocode_wanted;
7162 nocode_wanted = 1;
7163 gexpr();
7164 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7165 vpop();
7166 nocode_wanted = saved_nocode_wanted;
7167 skip(')');
7168 vpushi(res);
7170 break;
7171 case TOK_INC:
7172 case TOK_DEC:
7173 t = tok;
7174 next();
7175 unary();
7176 inc(0, t);
7177 break;
7178 case '-':
7179 next();
7180 vpushi(0);
7181 unary();
7182 gen_op('-');
7183 break;
7184 case TOK_LAND:
7185 if (!gnu_ext)
7186 goto tok_identifier;
7187 next();
7188 /* allow to take the address of a label */
7189 if (tok < TOK_UIDENT)
7190 expect("label identifier");
7191 s = label_find(tok);
7192 if (!s) {
7193 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7194 } else {
7195 if (s->r == LABEL_DECLARED)
7196 s->r = LABEL_FORWARD;
7198 if (!s->type.t) {
7199 s->type.t = VT_VOID;
7200 mk_pointer(&s->type);
7201 s->type.t |= VT_STATIC;
7203 vset(&s->type, VT_CONST | VT_SYM, 0);
7204 vtop->sym = s;
7205 next();
7206 break;
7207 default:
7208 tok_identifier:
7209 t = tok;
7210 next();
7211 if (t < TOK_UIDENT)
7212 expect("identifier");
7213 s = sym_find(t);
7214 if (!s) {
7215 if (tok != '(')
7216 error("'%s' undeclared", get_tok_str(t, NULL));
7217 /* for simple function calls, we tolerate undeclared
7218 external reference to int() function */
7219 if (tcc_state->warn_implicit_function_declaration)
7220 warning("implicit declaration of function '%s'",
7221 get_tok_str(t, NULL));
7222 s = external_global_sym(t, &func_old_type, 0);
7224 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7225 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7226 /* if referencing an inline function, then we generate a
7227 symbol to it if not already done. It will have the
7228 effect to generate code for it at the end of the
7229 compilation unit. Inline function as always
7230 generated in the text section. */
7231 if (!s->c)
7232 put_extern_sym(s, text_section, 0, 0);
7233 r = VT_SYM | VT_CONST;
7234 } else {
7235 r = s->r;
7237 vset(&s->type, r, s->c);
7238 /* if forward reference, we must point to s */
7239 if (vtop->r & VT_SYM) {
7240 vtop->sym = s;
7241 vtop->c.ul = 0;
7243 break;
7246 /* post operations */
7247 while (1) {
7248 if (tok == TOK_INC || tok == TOK_DEC) {
7249 inc(1, tok);
7250 next();
7251 } else if (tok == '.' || tok == TOK_ARROW) {
7252 /* field */
7253 if (tok == TOK_ARROW)
7254 indir();
7255 test_lvalue();
7256 gaddrof();
7257 next();
7258 /* expect pointer on structure */
7259 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7260 expect("struct or union");
7261 s = vtop->type.ref;
7262 /* find field */
7263 tok |= SYM_FIELD;
7264 while ((s = s->next) != NULL) {
7265 if (s->v == tok)
7266 break;
7268 if (!s)
7269 error("field not found");
7270 /* add field offset to pointer */
7271 vtop->type = char_pointer_type; /* change type to 'char *' */
7272 vpushi(s->c);
7273 gen_op('+');
7274 /* change type to field type, and set to lvalue */
7275 vtop->type = s->type;
7276 /* an array is never an lvalue */
7277 if (!(vtop->type.t & VT_ARRAY)) {
7278 vtop->r |= lvalue_type(vtop->type.t);
7279 /* if bound checking, the referenced pointer must be checked */
7280 if (do_bounds_check)
7281 vtop->r |= VT_MUSTBOUND;
7283 next();
7284 } else if (tok == '[') {
7285 next();
7286 gexpr();
7287 gen_op('+');
7288 indir();
7289 skip(']');
7290 } else if (tok == '(') {
7291 SValue ret;
7292 Sym *sa;
7293 int nb_args;
7295 /* function call */
7296 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7297 /* pointer test (no array accepted) */
7298 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7299 vtop->type = *pointed_type(&vtop->type);
7300 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7301 goto error_func;
7302 } else {
7303 error_func:
7304 expect("function pointer");
7306 } else {
7307 vtop->r &= ~VT_LVAL; /* no lvalue */
7309 /* get return type */
7310 s = vtop->type.ref;
7311 next();
7312 sa = s->next; /* first parameter */
7313 nb_args = 0;
7314 /* compute first implicit argument if a structure is returned */
7315 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7316 /* get some space for the returned structure */
7317 size = type_size(&s->type, &align);
7318 loc = (loc - size) & -align;
7319 ret.type = s->type;
7320 ret.r = VT_LOCAL | VT_LVAL;
7321 /* pass it as 'int' to avoid structure arg passing
7322 problems */
7323 vseti(VT_LOCAL, loc);
7324 ret.c = vtop->c;
7325 nb_args++;
7326 } else {
7327 ret.type = s->type;
7328 ret.r2 = VT_CONST;
7329 /* return in register */
7330 if (is_float(ret.type.t)) {
7331 ret.r = REG_FRET;
7332 } else {
7333 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7334 ret.r2 = REG_LRET;
7335 ret.r = REG_IRET;
7337 ret.c.i = 0;
7339 if (tok != ')') {
7340 for(;;) {
7341 expr_eq();
7342 gfunc_param_typed(s, sa);
7343 nb_args++;
7344 if (sa)
7345 sa = sa->next;
7346 if (tok == ')')
7347 break;
7348 skip(',');
7351 if (sa)
7352 error("too few arguments to function");
7353 skip(')');
7354 if (!nocode_wanted) {
7355 gfunc_call(nb_args);
7356 } else {
7357 vtop -= (nb_args + 1);
7359 /* return value */
7360 vsetc(&ret.type, ret.r, &ret.c);
7361 vtop->r2 = ret.r2;
7362 } else {
7363 break;
7368 static void uneq(void)
7370 int t;
7372 unary();
7373 if (tok == '=' ||
7374 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7375 tok == TOK_A_XOR || tok == TOK_A_OR ||
7376 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7377 test_lvalue();
7378 t = tok;
7379 next();
7380 if (t == '=') {
7381 expr_eq();
7382 } else {
7383 vdup();
7384 expr_eq();
7385 gen_op(t & 0x7f);
7387 vstore();
7391 static void expr_prod(void)
7393 int t;
7395 uneq();
7396 while (tok == '*' || tok == '/' || tok == '%') {
7397 t = tok;
7398 next();
7399 uneq();
7400 gen_op(t);
7404 static void expr_sum(void)
7406 int t;
7408 expr_prod();
7409 while (tok == '+' || tok == '-') {
7410 t = tok;
7411 next();
7412 expr_prod();
7413 gen_op(t);
7417 static void expr_shift(void)
7419 int t;
7421 expr_sum();
7422 while (tok == TOK_SHL || tok == TOK_SAR) {
7423 t = tok;
7424 next();
7425 expr_sum();
7426 gen_op(t);
7430 static void expr_cmp(void)
7432 int t;
7434 expr_shift();
7435 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7436 tok == TOK_ULT || tok == TOK_UGE) {
7437 t = tok;
7438 next();
7439 expr_shift();
7440 gen_op(t);
7444 static void expr_cmpeq(void)
7446 int t;
7448 expr_cmp();
7449 while (tok == TOK_EQ || tok == TOK_NE) {
7450 t = tok;
7451 next();
7452 expr_cmp();
7453 gen_op(t);
7457 static void expr_and(void)
7459 expr_cmpeq();
7460 while (tok == '&') {
7461 next();
7462 expr_cmpeq();
7463 gen_op('&');
7467 static void expr_xor(void)
7469 expr_and();
7470 while (tok == '^') {
7471 next();
7472 expr_and();
7473 gen_op('^');
7477 static void expr_or(void)
7479 expr_xor();
7480 while (tok == '|') {
7481 next();
7482 expr_xor();
7483 gen_op('|');
7487 /* XXX: fix this mess */
7488 static void expr_land_const(void)
7490 expr_or();
7491 while (tok == TOK_LAND) {
7492 next();
7493 expr_or();
7494 gen_op(TOK_LAND);
7498 /* XXX: fix this mess */
7499 static void expr_lor_const(void)
7501 expr_land_const();
7502 while (tok == TOK_LOR) {
7503 next();
7504 expr_land_const();
7505 gen_op(TOK_LOR);
7509 /* only used if non constant */
7510 static void expr_land(void)
7512 int t;
7514 expr_or();
7515 if (tok == TOK_LAND) {
7516 t = 0;
7517 for(;;) {
7518 t = gtst(1, t);
7519 if (tok != TOK_LAND) {
7520 vseti(VT_JMPI, t);
7521 break;
7523 next();
7524 expr_or();
7529 static void expr_lor(void)
7531 int t;
7533 expr_land();
7534 if (tok == TOK_LOR) {
7535 t = 0;
7536 for(;;) {
7537 t = gtst(0, t);
7538 if (tok != TOK_LOR) {
7539 vseti(VT_JMP, t);
7540 break;
7542 next();
7543 expr_land();
7548 /* XXX: better constant handling */
7549 static void expr_eq(void)
7551 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7552 SValue sv;
7553 CType type, type1, type2;
7555 if (const_wanted) {
7556 int c1, c;
7557 expr_lor_const();
7558 if (tok == '?') {
7559 c = vtop->c.i;
7560 vpop();
7561 next();
7562 if (tok == ':' && gnu_ext) {
7563 c1 = c;
7564 } else {
7565 gexpr();
7566 c1 = vtop->c.i;
7567 vpop();
7569 skip(':');
7570 expr_eq();
7571 if (c)
7572 vtop->c.i = c1;
7574 } else {
7575 expr_lor();
7576 if (tok == '?') {
7577 next();
7578 if (vtop != vstack) {
7579 /* needed to avoid having different registers saved in
7580 each branch */
7581 if (is_float(vtop->type.t))
7582 rc = RC_FLOAT;
7583 else
7584 rc = RC_INT;
7585 gv(rc);
7586 save_regs(1);
7588 if (tok == ':' && gnu_ext) {
7589 gv_dup();
7590 tt = gtst(1, 0);
7591 } else {
7592 tt = gtst(1, 0);
7593 gexpr();
7595 type1 = vtop->type;
7596 sv = *vtop; /* save value to handle it later */
7597 vtop--; /* no vpop so that FP stack is not flushed */
7598 skip(':');
7599 u = gjmp(0);
7600 gsym(tt);
7601 expr_eq();
7602 type2 = vtop->type;
7604 t1 = type1.t;
7605 bt1 = t1 & VT_BTYPE;
7606 t2 = type2.t;
7607 bt2 = t2 & VT_BTYPE;
7608 /* cast operands to correct type according to ISOC rules */
7609 if (is_float(bt1) || is_float(bt2)) {
7610 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7611 type.t = VT_LDOUBLE;
7612 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7613 type.t = VT_DOUBLE;
7614 } else {
7615 type.t = VT_FLOAT;
7617 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7618 /* cast to biggest op */
7619 type.t = VT_LLONG;
7620 /* convert to unsigned if it does not fit in a long long */
7621 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7622 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7623 type.t |= VT_UNSIGNED;
7624 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7625 /* XXX: test pointer compatibility */
7626 type = type1;
7627 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7628 /* XXX: test structure compatibility */
7629 type = type1;
7630 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7631 /* NOTE: as an extension, we accept void on only one side */
7632 type.t = VT_VOID;
7633 } else {
7634 /* integer operations */
7635 type.t = VT_INT;
7636 /* convert to unsigned if it does not fit in an integer */
7637 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7638 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7639 type.t |= VT_UNSIGNED;
7642 /* now we convert second operand */
7643 gen_cast(&type);
7644 rc = RC_INT;
7645 if (is_float(type.t)) {
7646 rc = RC_FLOAT;
7647 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7648 /* for long longs, we use fixed registers to avoid having
7649 to handle a complicated move */
7650 rc = RC_IRET;
7653 r2 = gv(rc);
7654 /* this is horrible, but we must also convert first
7655 operand */
7656 tt = gjmp(0);
7657 gsym(u);
7658 /* put again first value and cast it */
7659 *vtop = sv;
7660 gen_cast(&type);
7661 r1 = gv(rc);
7662 move_reg(r2, r1);
7663 vtop->r = r2;
7664 gsym(tt);
7669 static void gexpr(void)
7671 while (1) {
7672 expr_eq();
7673 if (tok != ',')
7674 break;
7675 vpop();
7676 next();
7680 /* parse an expression and return its type without any side effect. */
7681 static void expr_type(CType *type)
7683 int saved_nocode_wanted;
7685 saved_nocode_wanted = nocode_wanted;
7686 nocode_wanted = 1;
7687 gexpr();
7688 *type = vtop->type;
7689 vpop();
7690 nocode_wanted = saved_nocode_wanted;
7693 /* parse a unary expression and return its type without any side
7694 effect. */
7695 static void unary_type(CType *type)
7697 int a;
7699 a = nocode_wanted;
7700 nocode_wanted = 1;
7701 unary();
7702 *type = vtop->type;
7703 vpop();
7704 nocode_wanted = a;
7707 /* parse a constant expression and return value in vtop. */
7708 static void expr_const1(void)
7710 int a;
7711 a = const_wanted;
7712 const_wanted = 1;
7713 expr_eq();
7714 const_wanted = a;
7717 /* parse an integer constant and return its value. */
7718 static int expr_const(void)
7720 int c;
7721 expr_const1();
7722 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7723 expect("constant expression");
7724 c = vtop->c.i;
7725 vpop();
7726 return c;
7729 /* return the label token if current token is a label, otherwise
7730 return zero */
7731 static int is_label(void)
7733 int last_tok;
7735 /* fast test first */
7736 if (tok < TOK_UIDENT)
7737 return 0;
7738 /* no need to save tokc because tok is an identifier */
7739 last_tok = tok;
7740 next();
7741 if (tok == ':') {
7742 next();
7743 return last_tok;
7744 } else {
7745 unget_tok(last_tok);
7746 return 0;
7750 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7751 int case_reg, int is_expr)
7753 int a, b, c, d;
7754 Sym *s;
7756 /* generate line number info */
7757 if (do_debug &&
7758 (last_line_num != file->line_num || last_ind != ind)) {
7759 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7760 last_ind = ind;
7761 last_line_num = file->line_num;
7764 if (is_expr) {
7765 /* default return value is (void) */
7766 vpushi(0);
7767 vtop->type.t = VT_VOID;
7770 if (tok == TOK_IF) {
7771 /* if test */
7772 next();
7773 skip('(');
7774 gexpr();
7775 skip(')');
7776 a = gtst(1, 0);
7777 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7778 c = tok;
7779 if (c == TOK_ELSE) {
7780 next();
7781 d = gjmp(0);
7782 gsym(a);
7783 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7784 gsym(d); /* patch else jmp */
7785 } else
7786 gsym(a);
7787 } else if (tok == TOK_WHILE) {
7788 next();
7789 d = ind;
7790 skip('(');
7791 gexpr();
7792 skip(')');
7793 a = gtst(1, 0);
7794 b = 0;
7795 block(&a, &b, case_sym, def_sym, case_reg, 0);
7796 gjmp_addr(d);
7797 gsym(a);
7798 gsym_addr(b, d);
7799 } else if (tok == '{') {
7800 Sym *llabel;
7802 next();
7803 /* record local declaration stack position */
7804 s = local_stack;
7805 llabel = local_label_stack;
7806 /* handle local labels declarations */
7807 if (tok == TOK_LABEL) {
7808 next();
7809 for(;;) {
7810 if (tok < TOK_UIDENT)
7811 expect("label identifier");
7812 label_push(&local_label_stack, tok, LABEL_DECLARED);
7813 next();
7814 if (tok == ',') {
7815 next();
7816 } else {
7817 skip(';');
7818 break;
7822 while (tok != '}') {
7823 decl(VT_LOCAL);
7824 if (tok != '}') {
7825 if (is_expr)
7826 vpop();
7827 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7830 /* pop locally defined labels */
7831 label_pop(&local_label_stack, llabel);
7832 /* pop locally defined symbols */
7833 sym_pop(&local_stack, s);
7834 next();
7835 } else if (tok == TOK_RETURN) {
7836 next();
7837 if (tok != ';') {
7838 gexpr();
7839 gen_assign_cast(&func_vt);
7840 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7841 CType type;
7842 /* if returning structure, must copy it to implicit
7843 first pointer arg location */
7844 type = func_vt;
7845 mk_pointer(&type);
7846 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7847 indir();
7848 vswap();
7849 /* copy structure value to pointer */
7850 vstore();
7851 } else if (is_float(func_vt.t)) {
7852 gv(RC_FRET);
7853 } else {
7854 gv(RC_IRET);
7856 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7858 skip(';');
7859 rsym = gjmp(rsym); /* jmp */
7860 } else if (tok == TOK_BREAK) {
7861 /* compute jump */
7862 if (!bsym)
7863 error("cannot break");
7864 *bsym = gjmp(*bsym);
7865 next();
7866 skip(';');
7867 } else if (tok == TOK_CONTINUE) {
7868 /* compute jump */
7869 if (!csym)
7870 error("cannot continue");
7871 *csym = gjmp(*csym);
7872 next();
7873 skip(';');
7874 } else if (tok == TOK_FOR) {
7875 int e;
7876 next();
7877 skip('(');
7878 if (tok != ';') {
7879 gexpr();
7880 vpop();
7882 skip(';');
7883 d = ind;
7884 c = ind;
7885 a = 0;
7886 b = 0;
7887 if (tok != ';') {
7888 gexpr();
7889 a = gtst(1, 0);
7891 skip(';');
7892 if (tok != ')') {
7893 e = gjmp(0);
7894 c = ind;
7895 gexpr();
7896 vpop();
7897 gjmp_addr(d);
7898 gsym(e);
7900 skip(')');
7901 block(&a, &b, case_sym, def_sym, case_reg, 0);
7902 gjmp_addr(c);
7903 gsym(a);
7904 gsym_addr(b, c);
7905 } else
7906 if (tok == TOK_DO) {
7907 next();
7908 a = 0;
7909 b = 0;
7910 d = ind;
7911 block(&a, &b, case_sym, def_sym, case_reg, 0);
7912 skip(TOK_WHILE);
7913 skip('(');
7914 gsym(b);
7915 gexpr();
7916 c = gtst(0, 0);
7917 gsym_addr(c, d);
7918 skip(')');
7919 gsym(a);
7920 skip(';');
7921 } else
7922 if (tok == TOK_SWITCH) {
7923 next();
7924 skip('(');
7925 gexpr();
7926 /* XXX: other types than integer */
7927 case_reg = gv(RC_INT);
7928 vpop();
7929 skip(')');
7930 a = 0;
7931 b = gjmp(0); /* jump to first case */
7932 c = 0;
7933 block(&a, csym, &b, &c, case_reg, 0);
7934 /* if no default, jmp after switch */
7935 if (c == 0)
7936 c = ind;
7937 /* default label */
7938 gsym_addr(b, c);
7939 /* break label */
7940 gsym(a);
7941 } else
7942 if (tok == TOK_CASE) {
7943 int v1, v2;
7944 if (!case_sym)
7945 expect("switch");
7946 next();
7947 v1 = expr_const();
7948 v2 = v1;
7949 if (gnu_ext && tok == TOK_DOTS) {
7950 next();
7951 v2 = expr_const();
7952 if (v2 < v1)
7953 warning("empty case range");
7955 /* since a case is like a label, we must skip it with a jmp */
7956 b = gjmp(0);
7957 gsym(*case_sym);
7958 vseti(case_reg, 0);
7959 vpushi(v1);
7960 if (v1 == v2) {
7961 gen_op(TOK_EQ);
7962 *case_sym = gtst(1, 0);
7963 } else {
7964 gen_op(TOK_GE);
7965 *case_sym = gtst(1, 0);
7966 vseti(case_reg, 0);
7967 vpushi(v2);
7968 gen_op(TOK_LE);
7969 *case_sym = gtst(1, *case_sym);
7971 gsym(b);
7972 skip(':');
7973 is_expr = 0;
7974 goto block_after_label;
7975 } else
7976 if (tok == TOK_DEFAULT) {
7977 next();
7978 skip(':');
7979 if (!def_sym)
7980 expect("switch");
7981 if (*def_sym)
7982 error("too many 'default'");
7983 *def_sym = ind;
7984 is_expr = 0;
7985 goto block_after_label;
7986 } else
7987 if (tok == TOK_GOTO) {
7988 next();
7989 if (tok == '*' && gnu_ext) {
7990 /* computed goto */
7991 next();
7992 gexpr();
7993 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7994 expect("pointer");
7995 ggoto();
7996 } else if (tok >= TOK_UIDENT) {
7997 s = label_find(tok);
7998 /* put forward definition if needed */
7999 if (!s) {
8000 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8001 } else {
8002 if (s->r == LABEL_DECLARED)
8003 s->r = LABEL_FORWARD;
8005 /* label already defined */
8006 if (s->r & LABEL_FORWARD)
8007 s->next = (void *)gjmp((long)s->next);
8008 else
8009 gjmp_addr((long)s->next);
8010 next();
8011 } else {
8012 expect("label identifier");
8014 skip(';');
8015 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8016 asm_instr();
8017 } else {
8018 b = is_label();
8019 if (b) {
8020 /* label case */
8021 s = label_find(b);
8022 if (s) {
8023 if (s->r == LABEL_DEFINED)
8024 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8025 gsym((long)s->next);
8026 s->r = LABEL_DEFINED;
8027 } else {
8028 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8030 s->next = (void *)ind;
8031 /* we accept this, but it is a mistake */
8032 block_after_label:
8033 if (tok == '}') {
8034 warning("deprecated use of label at end of compound statement");
8035 } else {
8036 if (is_expr)
8037 vpop();
8038 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8040 } else {
8041 /* expression case */
8042 if (tok != ';') {
8043 if (is_expr) {
8044 vpop();
8045 gexpr();
8046 } else {
8047 gexpr();
8048 vpop();
8051 skip(';');
8056 /* t is the array or struct type. c is the array or struct
8057 address. cur_index/cur_field is the pointer to the current
8058 value. 'size_only' is true if only size info is needed (only used
8059 in arrays) */
8060 static void decl_designator(CType *type, Section *sec, unsigned long c,
8061 int *cur_index, Sym **cur_field,
8062 int size_only)
8064 Sym *s, *f;
8065 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8066 CType type1;
8068 notfirst = 0;
8069 elem_size = 0;
8070 nb_elems = 1;
8071 if (gnu_ext && (l = is_label()) != 0)
8072 goto struct_field;
8073 while (tok == '[' || tok == '.') {
8074 if (tok == '[') {
8075 if (!(type->t & VT_ARRAY))
8076 expect("array type");
8077 s = type->ref;
8078 next();
8079 index = expr_const();
8080 if (index < 0 || (s->c >= 0 && index >= s->c))
8081 expect("invalid index");
8082 if (tok == TOK_DOTS && gnu_ext) {
8083 next();
8084 index_last = expr_const();
8085 if (index_last < 0 ||
8086 (s->c >= 0 && index_last >= s->c) ||
8087 index_last < index)
8088 expect("invalid index");
8089 } else {
8090 index_last = index;
8092 skip(']');
8093 if (!notfirst)
8094 *cur_index = index_last;
8095 type = pointed_type(type);
8096 elem_size = type_size(type, &align);
8097 c += index * elem_size;
8098 /* NOTE: we only support ranges for last designator */
8099 nb_elems = index_last - index + 1;
8100 if (nb_elems != 1) {
8101 notfirst = 1;
8102 break;
8104 } else {
8105 next();
8106 l = tok;
8107 next();
8108 struct_field:
8109 if ((type->t & VT_BTYPE) != VT_STRUCT)
8110 expect("struct/union type");
8111 s = type->ref;
8112 l |= SYM_FIELD;
8113 f = s->next;
8114 while (f) {
8115 if (f->v == l)
8116 break;
8117 f = f->next;
8119 if (!f)
8120 expect("field");
8121 if (!notfirst)
8122 *cur_field = f;
8123 /* XXX: fix this mess by using explicit storage field */
8124 type1 = f->type;
8125 type1.t |= (type->t & ~VT_TYPE);
8126 type = &type1;
8127 c += f->c;
8129 notfirst = 1;
8131 if (notfirst) {
8132 if (tok == '=') {
8133 next();
8134 } else {
8135 if (!gnu_ext)
8136 expect("=");
8138 } else {
8139 if (type->t & VT_ARRAY) {
8140 index = *cur_index;
8141 type = pointed_type(type);
8142 c += index * type_size(type, &align);
8143 } else {
8144 f = *cur_field;
8145 if (!f)
8146 error("too many field init");
8147 /* XXX: fix this mess by using explicit storage field */
8148 type1 = f->type;
8149 type1.t |= (type->t & ~VT_TYPE);
8150 type = &type1;
8151 c += f->c;
8154 decl_initializer(type, sec, c, 0, size_only);
8156 /* XXX: make it more general */
8157 if (!size_only && nb_elems > 1) {
8158 unsigned long c_end;
8159 uint8_t *src, *dst;
8160 int i;
8162 if (!sec)
8163 error("range init not supported yet for dynamic storage");
8164 c_end = c + nb_elems * elem_size;
8165 if (c_end > sec->data_allocated)
8166 section_realloc(sec, c_end);
8167 src = sec->data + c;
8168 dst = src;
8169 for(i = 1; i < nb_elems; i++) {
8170 dst += elem_size;
8171 memcpy(dst, src, elem_size);
8176 #define EXPR_VAL 0
8177 #define EXPR_CONST 1
8178 #define EXPR_ANY 2
8180 /* store a value or an expression directly in global data or in local array */
8181 static void init_putv(CType *type, Section *sec, unsigned long c,
8182 int v, int expr_type)
8184 int saved_global_expr, bt, bit_pos, bit_size;
8185 void *ptr;
8186 unsigned long long bit_mask;
8187 CType dtype;
8189 switch(expr_type) {
8190 case EXPR_VAL:
8191 vpushi(v);
8192 break;
8193 case EXPR_CONST:
8194 /* compound literals must be allocated globally in this case */
8195 saved_global_expr = global_expr;
8196 global_expr = 1;
8197 expr_const1();
8198 global_expr = saved_global_expr;
8199 /* NOTE: symbols are accepted */
8200 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8201 error("initializer element is not constant");
8202 break;
8203 case EXPR_ANY:
8204 expr_eq();
8205 break;
8208 dtype = *type;
8209 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8211 if (sec) {
8212 /* XXX: not portable */
8213 /* XXX: generate error if incorrect relocation */
8214 gen_assign_cast(&dtype);
8215 bt = type->t & VT_BTYPE;
8216 ptr = sec->data + c;
8217 /* XXX: make code faster ? */
8218 if (!(type->t & VT_BITFIELD)) {
8219 bit_pos = 0;
8220 bit_size = 32;
8221 bit_mask = -1LL;
8222 } else {
8223 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8224 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8225 bit_mask = (1LL << bit_size) - 1;
8227 if ((vtop->r & VT_SYM) &&
8228 (bt == VT_BYTE ||
8229 bt == VT_SHORT ||
8230 bt == VT_DOUBLE ||
8231 bt == VT_LDOUBLE ||
8232 bt == VT_LLONG ||
8233 (bt == VT_INT && bit_size != 32)))
8234 error("initializer element is not computable at load time");
8235 switch(bt) {
8236 case VT_BYTE:
8237 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8238 break;
8239 case VT_SHORT:
8240 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8241 break;
8242 case VT_DOUBLE:
8243 *(double *)ptr = vtop->c.d;
8244 break;
8245 case VT_LDOUBLE:
8246 *(long double *)ptr = vtop->c.ld;
8247 break;
8248 case VT_LLONG:
8249 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8250 break;
8251 default:
8252 if (vtop->r & VT_SYM) {
8253 greloc(sec, vtop->sym, c, R_DATA_32);
8255 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8256 break;
8258 vtop--;
8259 } else {
8260 vset(&dtype, VT_LOCAL, c);
8261 vswap();
8262 vstore();
8263 vpop();
8267 /* put zeros for variable based init */
8268 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8270 if (sec) {
8271 /* nothing to do because globals are already set to zero */
8272 } else {
8273 vpush_global_sym(&func_old_type, TOK_memset);
8274 vseti(VT_LOCAL, c);
8275 vpushi(0);
8276 vpushi(size);
8277 gfunc_call(3);
8281 /* 't' contains the type and storage info. 'c' is the offset of the
8282 object in section 'sec'. If 'sec' is NULL, it means stack based
8283 allocation. 'first' is true if array '{' must be read (multi
8284 dimension implicit array init handling). 'size_only' is true if
8285 size only evaluation is wanted (only for arrays). */
8286 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8287 int first, int size_only)
8289 int index, array_length, n, no_oblock, nb, parlevel, i;
8290 int size1, align1, expr_type;
8291 Sym *s, *f;
8292 CType *t1;
8294 if (type->t & VT_ARRAY) {
8295 s = type->ref;
8296 n = s->c;
8297 array_length = 0;
8298 t1 = pointed_type(type);
8299 size1 = type_size(t1, &align1);
8301 no_oblock = 1;
8302 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8303 tok == '{') {
8304 skip('{');
8305 no_oblock = 0;
8308 /* only parse strings here if correct type (otherwise: handle
8309 them as ((w)char *) expressions */
8310 if ((tok == TOK_LSTR &&
8311 (t1->t & VT_BTYPE) == VT_INT) ||
8312 (tok == TOK_STR &&
8313 (t1->t & VT_BTYPE) == VT_BYTE)) {
8314 while (tok == TOK_STR || tok == TOK_LSTR) {
8315 int cstr_len, ch;
8316 CString *cstr;
8318 cstr = tokc.cstr;
8319 /* compute maximum number of chars wanted */
8320 if (tok == TOK_STR)
8321 cstr_len = cstr->size;
8322 else
8323 cstr_len = cstr->size / sizeof(int);
8324 cstr_len--;
8325 nb = cstr_len;
8326 if (n >= 0 && nb > (n - array_length))
8327 nb = n - array_length;
8328 if (!size_only) {
8329 if (cstr_len > nb)
8330 warning("initializer-string for array is too long");
8331 /* in order to go faster for common case (char
8332 string in global variable, we handle it
8333 specifically */
8334 if (sec && tok == TOK_STR && size1 == 1) {
8335 memcpy(sec->data + c + array_length, cstr->data, nb);
8336 } else {
8337 for(i=0;i<nb;i++) {
8338 if (tok == TOK_STR)
8339 ch = ((unsigned char *)cstr->data)[i];
8340 else
8341 ch = ((int *)cstr->data)[i];
8342 init_putv(t1, sec, c + (array_length + i) * size1,
8343 ch, EXPR_VAL);
8347 array_length += nb;
8348 next();
8350 /* only add trailing zero if enough storage (no
8351 warning in this case since it is standard) */
8352 if (n < 0 || array_length < n) {
8353 if (!size_only) {
8354 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8356 array_length++;
8358 } else {
8359 index = 0;
8360 while (tok != '}') {
8361 decl_designator(type, sec, c, &index, NULL, size_only);
8362 if (n >= 0 && index >= n)
8363 error("index too large");
8364 /* must put zero in holes (note that doing it that way
8365 ensures that it even works with designators) */
8366 if (!size_only && array_length < index) {
8367 init_putz(t1, sec, c + array_length * size1,
8368 (index - array_length) * size1);
8370 index++;
8371 if (index > array_length)
8372 array_length = index;
8373 /* special test for multi dimensional arrays (may not
8374 be strictly correct if designators are used at the
8375 same time) */
8376 if (index >= n && no_oblock)
8377 break;
8378 if (tok == '}')
8379 break;
8380 skip(',');
8383 if (!no_oblock)
8384 skip('}');
8385 /* put zeros at the end */
8386 if (!size_only && n >= 0 && array_length < n) {
8387 init_putz(t1, sec, c + array_length * size1,
8388 (n - array_length) * size1);
8390 /* patch type size if needed */
8391 if (n < 0)
8392 s->c = array_length;
8393 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8394 (sec || !first || tok == '{')) {
8395 int par_count;
8397 /* NOTE: the previous test is a specific case for automatic
8398 struct/union init */
8399 /* XXX: union needs only one init */
8401 /* XXX: this test is incorrect for local initializers
8402 beginning with ( without {. It would be much more difficult
8403 to do it correctly (ideally, the expression parser should
8404 be used in all cases) */
8405 par_count = 0;
8406 if (tok == '(') {
8407 AttributeDef ad1;
8408 CType type1;
8409 next();
8410 while (tok == '(') {
8411 par_count++;
8412 next();
8414 if (!parse_btype(&type1, &ad1))
8415 expect("cast");
8416 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8417 #if 0
8418 if (!is_assignable_types(type, &type1))
8419 error("invalid type for cast");
8420 #endif
8421 skip(')');
8423 no_oblock = 1;
8424 if (first || tok == '{') {
8425 skip('{');
8426 no_oblock = 0;
8428 s = type->ref;
8429 f = s->next;
8430 array_length = 0;
8431 index = 0;
8432 n = s->c;
8433 while (tok != '}') {
8434 decl_designator(type, sec, c, NULL, &f, size_only);
8435 index = f->c;
8436 if (!size_only && array_length < index) {
8437 init_putz(type, sec, c + array_length,
8438 index - array_length);
8440 index = index + type_size(&f->type, &align1);
8441 if (index > array_length)
8442 array_length = index;
8443 f = f->next;
8444 if (no_oblock && f == NULL)
8445 break;
8446 if (tok == '}')
8447 break;
8448 skip(',');
8450 /* put zeros at the end */
8451 if (!size_only && array_length < n) {
8452 init_putz(type, sec, c + array_length,
8453 n - array_length);
8455 if (!no_oblock)
8456 skip('}');
8457 while (par_count) {
8458 skip(')');
8459 par_count--;
8461 } else if (tok == '{') {
8462 next();
8463 decl_initializer(type, sec, c, first, size_only);
8464 skip('}');
8465 } else if (size_only) {
8466 /* just skip expression */
8467 parlevel = 0;
8468 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8469 tok != -1) {
8470 if (tok == '(')
8471 parlevel++;
8472 else if (tok == ')')
8473 parlevel--;
8474 next();
8476 } else {
8477 /* currently, we always use constant expression for globals
8478 (may change for scripting case) */
8479 expr_type = EXPR_CONST;
8480 if (!sec)
8481 expr_type = EXPR_ANY;
8482 init_putv(type, sec, c, 0, expr_type);
8486 /* parse an initializer for type 't' if 'has_init' is non zero, and
8487 allocate space in local or global data space ('r' is either
8488 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8489 variable 'v' of scope 'scope' is declared before initializers are
8490 parsed. If 'v' is zero, then a reference to the new object is put
8491 in the value stack. If 'has_init' is 2, a special parsing is done
8492 to handle string constants. */
8493 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8494 int has_init, int v, int scope)
8496 int size, align, addr, data_offset;
8497 int level;
8498 ParseState saved_parse_state;
8499 TokenString init_str;
8500 Section *sec;
8502 size = type_size(type, &align);
8503 /* If unknown size, we must evaluate it before
8504 evaluating initializers because
8505 initializers can generate global data too
8506 (e.g. string pointers or ISOC99 compound
8507 literals). It also simplifies local
8508 initializers handling */
8509 tok_str_new(&init_str);
8510 if (size < 0) {
8511 if (!has_init)
8512 error("unknown type size");
8513 /* get all init string */
8514 if (has_init == 2) {
8515 /* only get strings */
8516 while (tok == TOK_STR || tok == TOK_LSTR) {
8517 tok_str_add_tok(&init_str);
8518 next();
8520 } else {
8521 level = 0;
8522 while (level > 0 || (tok != ',' && tok != ';')) {
8523 if (tok < 0)
8524 error("unexpected end of file in initializer");
8525 tok_str_add_tok(&init_str);
8526 if (tok == '{')
8527 level++;
8528 else if (tok == '}') {
8529 if (level == 0)
8530 break;
8531 level--;
8533 next();
8536 tok_str_add(&init_str, -1);
8537 tok_str_add(&init_str, 0);
8539 /* compute size */
8540 save_parse_state(&saved_parse_state);
8542 macro_ptr = init_str.str;
8543 next();
8544 decl_initializer(type, NULL, 0, 1, 1);
8545 /* prepare second initializer parsing */
8546 macro_ptr = init_str.str;
8547 next();
8549 /* if still unknown size, error */
8550 size = type_size(type, &align);
8551 if (size < 0)
8552 error("unknown type size");
8554 /* take into account specified alignment if bigger */
8555 if (ad->aligned) {
8556 if (ad->aligned > align)
8557 align = ad->aligned;
8558 } else if (ad->packed) {
8559 align = 1;
8561 if ((r & VT_VALMASK) == VT_LOCAL) {
8562 sec = NULL;
8563 if (do_bounds_check && (type->t & VT_ARRAY))
8564 loc--;
8565 loc = (loc - size) & -align;
8566 addr = loc;
8567 /* handles bounds */
8568 /* XXX: currently, since we do only one pass, we cannot track
8569 '&' operators, so we add only arrays */
8570 if (do_bounds_check && (type->t & VT_ARRAY)) {
8571 unsigned long *bounds_ptr;
8572 /* add padding between regions */
8573 loc--;
8574 /* then add local bound info */
8575 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8576 bounds_ptr[0] = addr;
8577 bounds_ptr[1] = size;
8579 if (v) {
8580 /* local variable */
8581 sym_push(v, type, r, addr);
8582 } else {
8583 /* push local reference */
8584 vset(type, r, addr);
8586 } else {
8587 Sym *sym;
8589 sym = NULL;
8590 if (v && scope == VT_CONST) {
8591 /* see if the symbol was already defined */
8592 sym = sym_find(v);
8593 if (sym) {
8594 if (!is_compatible_types(&sym->type, type))
8595 error("incompatible types for redefinition of '%s'",
8596 get_tok_str(v, NULL));
8597 if (sym->type.t & VT_EXTERN) {
8598 /* if the variable is extern, it was not allocated */
8599 sym->type.t &= ~VT_EXTERN;
8600 /* set array size if it was ommited in extern
8601 declaration */
8602 if ((sym->type.t & VT_ARRAY) &&
8603 sym->type.ref->c < 0 &&
8604 type->ref->c >= 0)
8605 sym->type.ref->c = type->ref->c;
8606 } else {
8607 /* we accept several definitions of the same
8608 global variable. this is tricky, because we
8609 must play with the SHN_COMMON type of the symbol */
8610 /* XXX: should check if the variable was already
8611 initialized. It is incorrect to initialized it
8612 twice */
8613 /* no init data, we won't add more to the symbol */
8614 if (!has_init)
8615 goto no_alloc;
8620 /* allocate symbol in corresponding section */
8621 sec = ad->section;
8622 if (!sec) {
8623 if (has_init)
8624 sec = data_section;
8625 else if (tcc_state->nocommon)
8626 sec = bss_section;
8628 if (sec) {
8629 data_offset = sec->data_offset;
8630 data_offset = (data_offset + align - 1) & -align;
8631 addr = data_offset;
8632 /* very important to increment global pointer at this time
8633 because initializers themselves can create new initializers */
8634 data_offset += size;
8635 /* add padding if bound check */
8636 if (do_bounds_check)
8637 data_offset++;
8638 sec->data_offset = data_offset;
8639 /* allocate section space to put the data */
8640 if (sec->sh_type != SHT_NOBITS &&
8641 data_offset > sec->data_allocated)
8642 section_realloc(sec, data_offset);
8643 /* align section if needed */
8644 if (align > sec->sh_addralign)
8645 sec->sh_addralign = align;
8646 } else {
8647 addr = 0; /* avoid warning */
8650 if (v) {
8651 if (scope == VT_CONST) {
8652 if (!sym)
8653 goto do_def;
8654 } else {
8655 do_def:
8656 sym = sym_push(v, type, r | VT_SYM, 0);
8658 /* update symbol definition */
8659 if (sec) {
8660 put_extern_sym(sym, sec, addr, size);
8661 } else {
8662 Elf32_Sym *esym;
8663 /* put a common area */
8664 put_extern_sym(sym, NULL, align, size);
8665 /* XXX: find a nicer way */
8666 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8667 esym->st_shndx = SHN_COMMON;
8669 } else {
8670 CValue cval;
8672 /* push global reference */
8673 sym = get_sym_ref(type, sec, addr, size);
8674 cval.ul = 0;
8675 vsetc(type, VT_CONST | VT_SYM, &cval);
8676 vtop->sym = sym;
8679 /* handles bounds now because the symbol must be defined
8680 before for the relocation */
8681 if (do_bounds_check) {
8682 unsigned long *bounds_ptr;
8684 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8685 /* then add global bound info */
8686 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8687 bounds_ptr[0] = 0; /* relocated */
8688 bounds_ptr[1] = size;
8691 if (has_init) {
8692 decl_initializer(type, sec, addr, 1, 0);
8693 /* restore parse state if needed */
8694 if (init_str.str) {
8695 tok_str_free(init_str.str);
8696 restore_parse_state(&saved_parse_state);
8699 no_alloc: ;
8702 void put_func_debug(Sym *sym)
8704 char buf[512];
8706 /* stabs info */
8707 /* XXX: we put here a dummy type */
8708 snprintf(buf, sizeof(buf), "%s:%c1",
8709 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8710 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8711 cur_text_section, sym->c);
8712 last_ind = 0;
8713 last_line_num = 0;
8716 /* parse an old style function declaration list */
8717 /* XXX: check multiple parameter */
8718 static void func_decl_list(Sym *func_sym)
8720 AttributeDef ad;
8721 int v;
8722 Sym *s;
8723 CType btype, type;
8725 /* parse each declaration */
8726 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8727 if (!parse_btype(&btype, &ad))
8728 expect("declaration list");
8729 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8730 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8731 tok == ';') {
8732 /* we accept no variable after */
8733 } else {
8734 for(;;) {
8735 type = btype;
8736 type_decl(&type, &ad, &v, TYPE_DIRECT);
8737 /* find parameter in function parameter list */
8738 s = func_sym->next;
8739 while (s != NULL) {
8740 if ((s->v & ~SYM_FIELD) == v)
8741 goto found;
8742 s = s->next;
8744 error("declaration for parameter '%s' but no such parameter",
8745 get_tok_str(v, NULL));
8746 found:
8747 /* check that no storage specifier except 'register' was given */
8748 if (type.t & VT_STORAGE)
8749 error("storage class specified for '%s'", get_tok_str(v, NULL));
8750 convert_parameter_type(&type);
8751 /* we can add the type (NOTE: it could be local to the function) */
8752 s->type = type;
8753 /* accept other parameters */
8754 if (tok == ',')
8755 next();
8756 else
8757 break;
8760 skip(';');
8764 /* parse a function defined by symbol 'sym' and generate its code in
8765 'cur_text_section' */
8766 static void gen_function(Sym *sym)
8768 ind = cur_text_section->data_offset;
8769 /* NOTE: we patch the symbol size later */
8770 put_extern_sym(sym, cur_text_section, ind, 0);
8771 funcname = get_tok_str(sym->v, NULL);
8772 func_ind = ind;
8773 /* put debug symbol */
8774 if (do_debug)
8775 put_func_debug(sym);
8776 /* push a dummy symbol to enable local sym storage */
8777 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8778 gfunc_prolog(&sym->type);
8779 rsym = 0;
8780 block(NULL, NULL, NULL, NULL, 0, 0);
8781 gsym(rsym);
8782 gfunc_epilog();
8783 cur_text_section->data_offset = ind;
8784 label_pop(&global_label_stack, NULL);
8785 sym_pop(&local_stack, NULL); /* reset local stack */
8786 /* end of function */
8787 /* patch symbol size */
8788 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8789 ind - func_ind;
8790 if (do_debug) {
8791 put_stabn(N_FUN, 0, 0, ind - func_ind);
8793 funcname = ""; /* for safety */
8794 func_vt.t = VT_VOID; /* for safety */
8795 ind = 0; /* for safety */
8798 static void gen_inline_functions(void)
8800 Sym *sym;
8801 CType *type;
8802 int *str, inline_generated;
8804 /* iterate while inline function are referenced */
8805 for(;;) {
8806 inline_generated = 0;
8807 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8808 type = &sym->type;
8809 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8810 (type->t & (VT_STATIC | VT_INLINE)) ==
8811 (VT_STATIC | VT_INLINE) &&
8812 sym->c != 0) {
8813 /* the function was used: generate its code and
8814 convert it to a normal function */
8815 str = (int *)sym->r;
8816 sym->r = VT_SYM | VT_CONST;
8817 type->t &= ~VT_INLINE;
8819 macro_ptr = str;
8820 next();
8821 cur_text_section = text_section;
8822 gen_function(sym);
8823 macro_ptr = NULL; /* fail safe */
8825 tok_str_free(str);
8826 inline_generated = 1;
8829 if (!inline_generated)
8830 break;
8833 /* free all remaining inline function tokens */
8834 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8835 type = &sym->type;
8836 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8837 (type->t & (VT_STATIC | VT_INLINE)) ==
8838 (VT_STATIC | VT_INLINE)) {
8839 str = (int *)sym->r;
8840 tok_str_free(str);
8841 sym->r = 0; /* fail safe */
8846 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8847 static void decl(int l)
8849 int v, has_init, r;
8850 CType type, btype;
8851 Sym *sym;
8852 AttributeDef ad;
8854 while (1) {
8855 if (!parse_btype(&btype, &ad)) {
8856 /* skip redundant ';' */
8857 /* XXX: find more elegant solution */
8858 if (tok == ';') {
8859 next();
8860 continue;
8862 if (l == VT_CONST &&
8863 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
8864 /* global asm block */
8865 asm_global_instr();
8866 continue;
8868 /* special test for old K&R protos without explicit int
8869 type. Only accepted when defining global data */
8870 if (l == VT_LOCAL || tok < TOK_DEFINE)
8871 break;
8872 btype.t = VT_INT;
8874 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8875 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8876 tok == ';') {
8877 /* we accept no variable after */
8878 next();
8879 continue;
8881 while (1) { /* iterate thru each declaration */
8882 type = btype;
8883 type_decl(&type, &ad, &v, TYPE_DIRECT);
8884 #if 0
8886 char buf[500];
8887 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8888 printf("type = '%s'\n", buf);
8890 #endif
8891 if ((type.t & VT_BTYPE) == VT_FUNC) {
8892 /* if old style function prototype, we accept a
8893 declaration list */
8894 sym = type.ref;
8895 if (sym->c == FUNC_OLD)
8896 func_decl_list(sym);
8899 if (tok == '{') {
8900 if (l == VT_LOCAL)
8901 error("cannot use local functions");
8902 if (!(type.t & VT_FUNC))
8903 expect("function definition");
8905 /* reject abstract declarators in function definition */
8906 sym = type.ref;
8907 while ((sym = sym->next) != NULL)
8908 if (!(sym->v & ~SYM_FIELD))
8909 expect("identifier");
8911 /* XXX: cannot do better now: convert extern line to static inline */
8912 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8913 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8915 sym = sym_find(v);
8916 if (sym) {
8917 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
8918 goto func_error1;
8919 /* specific case: if not func_call defined, we put
8920 the one of the prototype */
8921 /* XXX: should have default value */
8922 if (sym->type.ref->r != FUNC_CDECL &&
8923 type.ref->r == FUNC_CDECL)
8924 type.ref->r = sym->type.ref->r;
8925 if (!is_compatible_types(&sym->type, &type)) {
8926 func_error1:
8927 error("incompatible types for redefinition of '%s'",
8928 get_tok_str(v, NULL));
8930 /* if symbol is already defined, then put complete type */
8931 sym->type = type;
8932 } else {
8933 /* put function symbol */
8934 sym = global_identifier_push(v, type.t, 0);
8935 sym->type.ref = type.ref;
8938 /* static inline functions are just recorded as a kind
8939 of macro. Their code will be emitted at the end of
8940 the compilation unit only if they are used */
8941 if ((type.t & (VT_INLINE | VT_STATIC)) ==
8942 (VT_INLINE | VT_STATIC)) {
8943 TokenString func_str;
8944 int block_level;
8946 tok_str_new(&func_str);
8948 block_level = 0;
8949 for(;;) {
8950 int t;
8951 if (tok == TOK_EOF)
8952 error("unexpected end of file");
8953 tok_str_add_tok(&func_str);
8954 t = tok;
8955 next();
8956 if (t == '{') {
8957 block_level++;
8958 } else if (t == '}') {
8959 block_level--;
8960 if (block_level == 0)
8961 break;
8964 tok_str_add(&func_str, -1);
8965 tok_str_add(&func_str, 0);
8966 sym->r = (int)func_str.str;
8967 } else {
8968 /* compute text section */
8969 cur_text_section = ad.section;
8970 if (!cur_text_section)
8971 cur_text_section = text_section;
8972 sym->r = VT_SYM | VT_CONST;
8973 gen_function(sym);
8975 break;
8976 } else {
8977 if (btype.t & VT_TYPEDEF) {
8978 /* save typedefed type */
8979 /* XXX: test storage specifiers ? */
8980 sym = sym_push(v, &type, 0, 0);
8981 sym->type.t |= VT_TYPEDEF;
8982 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8983 /* external function definition */
8984 /* specific case for func_call attribute */
8985 if (ad.func_call)
8986 type.ref->r = ad.func_call;
8987 external_sym(v, &type, 0);
8988 } else {
8989 /* not lvalue if array */
8990 r = 0;
8991 if (!(type.t & VT_ARRAY))
8992 r |= lvalue_type(type.t);
8993 has_init = (tok == '=');
8994 if ((btype.t & VT_EXTERN) ||
8995 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8996 !has_init && l == VT_CONST && type.ref->c < 0)) {
8997 /* external variable */
8998 /* NOTE: as GCC, uninitialized global static
8999 arrays of null size are considered as
9000 extern */
9001 external_sym(v, &type, r);
9002 } else {
9003 if (type.t & VT_STATIC)
9004 r |= VT_CONST;
9005 else
9006 r |= l;
9007 if (has_init)
9008 next();
9009 decl_initializer_alloc(&type, &ad, r,
9010 has_init, v, l);
9013 if (tok != ',') {
9014 skip(';');
9015 break;
9017 next();
9023 /* better than nothing, but needs extension to handle '-E' option
9024 correctly too */
9025 static void preprocess_init(TCCState *s1)
9027 s1->include_stack_ptr = s1->include_stack;
9028 /* XXX: move that before to avoid having to initialize
9029 file->ifdef_stack_ptr ? */
9030 s1->ifdef_stack_ptr = s1->ifdef_stack;
9031 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9033 /* XXX: not ANSI compliant: bound checking says error */
9034 vtop = vstack - 1;
9037 /* compile the C file opened in 'file'. Return non zero if errors. */
9038 static int tcc_compile(TCCState *s1)
9040 Sym *define_start;
9041 char buf[512];
9042 volatile int section_sym;
9044 #ifdef INC_DEBUG
9045 printf("%s: **** new file\n", file->filename);
9046 #endif
9047 preprocess_init(s1);
9049 funcname = "";
9050 anon_sym = SYM_FIRST_ANOM;
9052 /* file info: full path + filename */
9053 section_sym = 0; /* avoid warning */
9054 if (do_debug) {
9055 section_sym = put_elf_sym(symtab_section, 0, 0,
9056 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9057 text_section->sh_num, NULL);
9058 getcwd(buf, sizeof(buf));
9059 pstrcat(buf, sizeof(buf), "/");
9060 put_stabs_r(buf, N_SO, 0, 0,
9061 text_section->data_offset, text_section, section_sym);
9062 put_stabs_r(file->filename, N_SO, 0, 0,
9063 text_section->data_offset, text_section, section_sym);
9065 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9066 symbols can be safely used */
9067 put_elf_sym(symtab_section, 0, 0,
9068 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9069 SHN_ABS, file->filename);
9071 /* define some often used types */
9072 int_type.t = VT_INT;
9074 char_pointer_type.t = VT_BYTE;
9075 mk_pointer(&char_pointer_type);
9077 func_old_type.t = VT_FUNC;
9078 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9080 #if 0
9081 /* define 'void *alloca(unsigned int)' builtin function */
9083 Sym *s1;
9085 p = anon_sym++;
9086 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9087 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9088 s1->next = NULL;
9089 sym->next = s1;
9090 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9092 #endif
9094 define_start = define_stack;
9096 if (setjmp(s1->error_jmp_buf) == 0) {
9097 s1->nb_errors = 0;
9098 s1->error_set_jmp_enabled = 1;
9100 ch = file->buf_ptr[0];
9101 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9102 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9103 next();
9104 decl(VT_CONST);
9105 if (tok != TOK_EOF)
9106 expect("declaration");
9108 /* end of translation unit info */
9109 if (do_debug) {
9110 put_stabs_r(NULL, N_SO, 0, 0,
9111 text_section->data_offset, text_section, section_sym);
9114 s1->error_set_jmp_enabled = 0;
9116 /* reset define stack, but leave -Dsymbols (may be incorrect if
9117 they are undefined) */
9118 free_defines(define_start);
9120 gen_inline_functions();
9122 sym_pop(&global_stack, NULL);
9124 return s1->nb_errors != 0 ? -1 : 0;
9127 #ifdef LIBTCC
9128 int tcc_compile_string(TCCState *s, const char *str)
9130 BufferedFile bf1, *bf = &bf1;
9131 int ret, len;
9132 char *buf;
9134 /* init file structure */
9135 bf->fd = -1;
9136 /* XXX: avoid copying */
9137 len = strlen(str);
9138 buf = tcc_malloc(len + 1);
9139 if (!buf)
9140 return -1;
9141 memcpy(buf, str, len);
9142 buf[len] = CH_EOB;
9143 bf->buf_ptr = buf;
9144 bf->buf_end = buf + len;
9145 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9146 bf->line_num = 1;
9147 file = bf;
9149 ret = tcc_compile(s);
9151 tcc_free(buf);
9153 /* currently, no need to close */
9154 return ret;
9156 #endif
9158 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9159 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9161 BufferedFile bf1, *bf = &bf1;
9163 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9164 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9165 /* default value */
9166 if (!value)
9167 value = "1";
9168 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9170 /* init file structure */
9171 bf->fd = -1;
9172 bf->buf_ptr = bf->buffer;
9173 bf->buf_end = bf->buffer + strlen(bf->buffer);
9174 *bf->buf_end = CH_EOB;
9175 bf->filename[0] = '\0';
9176 bf->line_num = 1;
9177 file = bf;
9179 s1->include_stack_ptr = s1->include_stack;
9181 /* parse with define parser */
9182 ch = file->buf_ptr[0];
9183 next_nomacro();
9184 parse_define();
9185 file = NULL;
9188 /* undefine a preprocessor symbol */
9189 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9191 TokenSym *ts;
9192 Sym *s;
9193 ts = tok_alloc(sym, strlen(sym));
9194 s = define_find(ts->tok);
9195 /* undefine symbol by putting an invalid name */
9196 if (s)
9197 define_undef(s);
9200 #ifdef CONFIG_TCC_ASM
9202 #ifdef TCC_TARGET_I386
9203 #include "i386-asm.c"
9204 #endif
9205 #include "tccasm.c"
9207 #else
9208 static void asm_instr(void)
9210 error("inline asm() not supported");
9212 static void asm_global_instr(void)
9214 error("inline asm() not supported");
9216 #endif
9218 #include "tccelf.c"
9220 #ifdef TCC_TARGET_COFF
9221 #include "tcccoff.c"
9222 #endif
9224 #ifdef TCC_TARGET_PE
9225 #include "tccpe.c"
9226 #endif
9228 /* print the position in the source file of PC value 'pc' by reading
9229 the stabs debug information */
9230 static void rt_printline(unsigned long wanted_pc)
9232 Stab_Sym *sym, *sym_end;
9233 char func_name[128], last_func_name[128];
9234 unsigned long func_addr, last_pc, pc;
9235 const char *incl_files[INCLUDE_STACK_SIZE];
9236 int incl_index, len, last_line_num, i;
9237 const char *str, *p;
9239 fprintf(stderr, "0x%08lx:", wanted_pc);
9241 func_name[0] = '\0';
9242 func_addr = 0;
9243 incl_index = 0;
9244 last_func_name[0] = '\0';
9245 last_pc = 0xffffffff;
9246 last_line_num = 1;
9247 sym = (Stab_Sym *)stab_section->data + 1;
9248 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9249 while (sym < sym_end) {
9250 switch(sym->n_type) {
9251 /* function start or end */
9252 case N_FUN:
9253 if (sym->n_strx == 0) {
9254 /* we test if between last line and end of function */
9255 pc = sym->n_value + func_addr;
9256 if (wanted_pc >= last_pc && wanted_pc < pc)
9257 goto found;
9258 func_name[0] = '\0';
9259 func_addr = 0;
9260 } else {
9261 str = stabstr_section->data + sym->n_strx;
9262 p = strchr(str, ':');
9263 if (!p) {
9264 pstrcpy(func_name, sizeof(func_name), str);
9265 } else {
9266 len = p - str;
9267 if (len > sizeof(func_name) - 1)
9268 len = sizeof(func_name) - 1;
9269 memcpy(func_name, str, len);
9270 func_name[len] = '\0';
9272 func_addr = sym->n_value;
9274 break;
9275 /* line number info */
9276 case N_SLINE:
9277 pc = sym->n_value + func_addr;
9278 if (wanted_pc >= last_pc && wanted_pc < pc)
9279 goto found;
9280 last_pc = pc;
9281 last_line_num = sym->n_desc;
9282 /* XXX: slow! */
9283 strcpy(last_func_name, func_name);
9284 break;
9285 /* include files */
9286 case N_BINCL:
9287 str = stabstr_section->data + sym->n_strx;
9288 add_incl:
9289 if (incl_index < INCLUDE_STACK_SIZE) {
9290 incl_files[incl_index++] = str;
9292 break;
9293 case N_EINCL:
9294 if (incl_index > 1)
9295 incl_index--;
9296 break;
9297 case N_SO:
9298 if (sym->n_strx == 0) {
9299 incl_index = 0; /* end of translation unit */
9300 } else {
9301 str = stabstr_section->data + sym->n_strx;
9302 /* do not add path */
9303 len = strlen(str);
9304 if (len > 0 && str[len - 1] != '/')
9305 goto add_incl;
9307 break;
9309 sym++;
9312 /* second pass: we try symtab symbols (no line number info) */
9313 incl_index = 0;
9315 Elf32_Sym *sym, *sym_end;
9316 int type;
9318 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9319 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9320 sym < sym_end;
9321 sym++) {
9322 type = ELF32_ST_TYPE(sym->st_info);
9323 if (type == STT_FUNC) {
9324 if (wanted_pc >= sym->st_value &&
9325 wanted_pc < sym->st_value + sym->st_size) {
9326 pstrcpy(last_func_name, sizeof(last_func_name),
9327 strtab_section->data + sym->st_name);
9328 goto found;
9333 /* did not find any info: */
9334 fprintf(stderr, " ???\n");
9335 return;
9336 found:
9337 if (last_func_name[0] != '\0') {
9338 fprintf(stderr, " %s()", last_func_name);
9340 if (incl_index > 0) {
9341 fprintf(stderr, " (%s:%d",
9342 incl_files[incl_index - 1], last_line_num);
9343 for(i = incl_index - 2; i >= 0; i--)
9344 fprintf(stderr, ", included from %s", incl_files[i]);
9345 fprintf(stderr, ")");
9347 fprintf(stderr, "\n");
9350 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9352 #ifdef __i386__
9354 /* fix for glibc 2.1 */
9355 #ifndef REG_EIP
9356 #define REG_EIP EIP
9357 #define REG_EBP EBP
9358 #endif
9360 /* return the PC at frame level 'level'. Return non zero if not found */
9361 static int rt_get_caller_pc(unsigned long *paddr,
9362 ucontext_t *uc, int level)
9364 unsigned long fp;
9365 int i;
9367 if (level == 0) {
9368 #if defined(__FreeBSD__)
9369 *paddr = uc->uc_mcontext.mc_eip;
9370 #elif defined(__dietlibc__)
9371 *paddr = uc->uc_mcontext.eip;
9372 #else
9373 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9374 #endif
9375 return 0;
9376 } else {
9377 #if defined(__FreeBSD__)
9378 fp = uc->uc_mcontext.mc_ebp;
9379 #elif defined(__dietlibc__)
9380 fp = uc->uc_mcontext.ebp;
9381 #else
9382 fp = uc->uc_mcontext.gregs[REG_EBP];
9383 #endif
9384 for(i=1;i<level;i++) {
9385 /* XXX: check address validity with program info */
9386 if (fp <= 0x1000 || fp >= 0xc0000000)
9387 return -1;
9388 fp = ((unsigned long *)fp)[0];
9390 *paddr = ((unsigned long *)fp)[1];
9391 return 0;
9394 #else
9396 #warning add arch specific rt_get_caller_pc()
9398 static int rt_get_caller_pc(unsigned long *paddr,
9399 ucontext_t *uc, int level)
9401 return -1;
9403 #endif
9405 /* emit a run time error at position 'pc' */
9406 void rt_error(ucontext_t *uc, const char *fmt, ...)
9408 va_list ap;
9409 unsigned long pc;
9410 int i;
9412 va_start(ap, fmt);
9413 fprintf(stderr, "Runtime error: ");
9414 vfprintf(stderr, fmt, ap);
9415 fprintf(stderr, "\n");
9416 for(i=0;i<num_callers;i++) {
9417 if (rt_get_caller_pc(&pc, uc, i) < 0)
9418 break;
9419 if (i == 0)
9420 fprintf(stderr, "at ");
9421 else
9422 fprintf(stderr, "by ");
9423 rt_printline(pc);
9425 exit(255);
9426 va_end(ap);
9429 /* signal handler for fatal errors */
9430 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9432 ucontext_t *uc = puc;
9434 switch(signum) {
9435 case SIGFPE:
9436 switch(siginf->si_code) {
9437 case FPE_INTDIV:
9438 case FPE_FLTDIV:
9439 rt_error(uc, "division by zero");
9440 break;
9441 default:
9442 rt_error(uc, "floating point exception");
9443 break;
9445 break;
9446 case SIGBUS:
9447 case SIGSEGV:
9448 if (rt_bound_error_msg && *rt_bound_error_msg)
9449 rt_error(uc, *rt_bound_error_msg);
9450 else
9451 rt_error(uc, "dereferencing invalid pointer");
9452 break;
9453 case SIGILL:
9454 rt_error(uc, "illegal instruction");
9455 break;
9456 case SIGABRT:
9457 rt_error(uc, "abort() called");
9458 break;
9459 default:
9460 rt_error(uc, "caught signal %d", signum);
9461 break;
9463 exit(255);
9465 #endif
9467 /* do all relocations (needed before using tcc_get_symbol()) */
9468 int tcc_relocate(TCCState *s1)
9470 Section *s;
9471 int i;
9473 s1->nb_errors = 0;
9475 #ifdef TCC_TARGET_PE
9476 pe_add_runtime(s1);
9477 #else
9478 tcc_add_runtime(s1);
9479 #endif
9481 relocate_common_syms();
9483 tcc_add_linker_symbols(s1);
9485 build_got_entries(s1);
9487 /* compute relocation address : section are relocated in place. We
9488 also alloc the bss space */
9489 for(i = 1; i < s1->nb_sections; i++) {
9490 s = s1->sections[i];
9491 if (s->sh_flags & SHF_ALLOC) {
9492 if (s->sh_type == SHT_NOBITS)
9493 s->data = tcc_mallocz(s->data_offset);
9494 s->sh_addr = (unsigned long)s->data;
9498 relocate_syms(s1, 1);
9500 if (s1->nb_errors != 0)
9501 return -1;
9503 /* relocate each section */
9504 for(i = 1; i < s1->nb_sections; i++) {
9505 s = s1->sections[i];
9506 if (s->reloc)
9507 relocate_section(s1, s);
9509 return 0;
9512 /* launch the compiled program with the given arguments */
9513 int tcc_run(TCCState *s1, int argc, char **argv)
9515 int (*prog_main)(int, char **);
9517 if (tcc_relocate(s1) < 0)
9518 return -1;
9520 prog_main = tcc_get_symbol_err(s1, "main");
9522 if (do_debug) {
9523 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9524 error("debug mode currently not available for Windows");
9525 #else
9526 struct sigaction sigact;
9527 /* install TCC signal handlers to print debug info on fatal
9528 runtime errors */
9529 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9530 sigact.sa_sigaction = sig_error;
9531 sigemptyset(&sigact.sa_mask);
9532 sigaction(SIGFPE, &sigact, NULL);
9533 sigaction(SIGILL, &sigact, NULL);
9534 sigaction(SIGSEGV, &sigact, NULL);
9535 sigaction(SIGBUS, &sigact, NULL);
9536 sigaction(SIGABRT, &sigact, NULL);
9537 #endif
9540 #ifdef CONFIG_TCC_BCHECK
9541 if (do_bounds_check) {
9542 void (*bound_init)(void);
9544 /* set error function */
9545 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9546 "__bound_error_msg");
9548 /* XXX: use .init section so that it also work in binary ? */
9549 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9550 bound_init();
9552 #endif
9553 return (*prog_main)(argc, argv);
9556 TCCState *tcc_new(void)
9558 const char *p, *r;
9559 TCCState *s;
9560 TokenSym *ts;
9561 int i, c;
9563 s = tcc_mallocz(sizeof(TCCState));
9564 if (!s)
9565 return NULL;
9566 tcc_state = s;
9567 s->output_type = TCC_OUTPUT_MEMORY;
9569 /* init isid table */
9570 for(i=0;i<256;i++)
9571 isidnum_table[i] = isid(i) || isnum(i);
9573 /* add all tokens */
9574 table_ident = NULL;
9575 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9577 tok_ident = TOK_IDENT;
9578 p = tcc_keywords;
9579 while (*p) {
9580 r = p;
9581 for(;;) {
9582 c = *r++;
9583 if (c == '\0')
9584 break;
9586 ts = tok_alloc(p, r - p - 1);
9587 p = r;
9590 /* we add dummy defines for some special macros to speed up tests
9591 and to have working defined() */
9592 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9593 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9594 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9595 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9597 /* standard defines */
9598 tcc_define_symbol(s, "__STDC__", NULL);
9599 #if defined(TCC_TARGET_I386)
9600 tcc_define_symbol(s, "__i386__", NULL);
9601 #endif
9602 #if defined(TCC_TARGET_ARM)
9603 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9604 tcc_define_symbol(s, "__arm_elf__", NULL);
9605 tcc_define_symbol(s, "__arm_elf", NULL);
9606 tcc_define_symbol(s, "arm_elf", NULL);
9607 tcc_define_symbol(s, "__arm__", NULL);
9608 tcc_define_symbol(s, "__arm", NULL);
9609 tcc_define_symbol(s, "arm", NULL);
9610 tcc_define_symbol(s, "__APCS_32__", NULL);
9611 #endif
9612 #if defined(linux)
9613 tcc_define_symbol(s, "__linux__", NULL);
9614 tcc_define_symbol(s, "linux", NULL);
9615 #endif
9616 /* tiny C specific defines */
9617 tcc_define_symbol(s, "__TINYC__", NULL);
9619 /* tiny C & gcc defines */
9620 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9621 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9622 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9624 /* default library paths */
9625 #ifdef TCC_TARGET_PE
9627 char buf[1024];
9628 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
9629 tcc_add_library_path(s, buf);
9631 #else
9632 tcc_add_library_path(s, "/usr/local/lib");
9633 tcc_add_library_path(s, "/usr/lib");
9634 tcc_add_library_path(s, "/lib");
9635 #endif
9637 /* no section zero */
9638 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9640 /* create standard sections */
9641 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9642 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9643 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9645 /* symbols are always generated for linking stage */
9646 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9647 ".strtab",
9648 ".hashtab", SHF_PRIVATE);
9649 strtab_section = symtab_section->link;
9651 /* private symbol table for dynamic symbols */
9652 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9653 ".dynstrtab",
9654 ".dynhashtab", SHF_PRIVATE);
9655 s->alacarte_link = 1;
9657 #ifdef CHAR_IS_UNSIGNED
9658 s->char_is_unsigned = 1;
9659 #endif
9660 return s;
9663 void tcc_delete(TCCState *s1)
9665 int i, n;
9667 /* free -D defines */
9668 free_defines(NULL);
9670 /* free tokens */
9671 n = tok_ident - TOK_IDENT;
9672 for(i = 0; i < n; i++)
9673 tcc_free(table_ident[i]);
9674 tcc_free(table_ident);
9676 /* free all sections */
9678 free_section(symtab_section->hash);
9680 free_section(s1->dynsymtab_section->hash);
9681 free_section(s1->dynsymtab_section->link);
9682 free_section(s1->dynsymtab_section);
9684 for(i = 1; i < s1->nb_sections; i++)
9685 free_section(s1->sections[i]);
9686 tcc_free(s1->sections);
9688 /* free loaded dlls array */
9689 for(i = 0; i < s1->nb_loaded_dlls; i++)
9690 tcc_free(s1->loaded_dlls[i]);
9691 tcc_free(s1->loaded_dlls);
9693 /* library paths */
9694 for(i = 0; i < s1->nb_library_paths; i++)
9695 tcc_free(s1->library_paths[i]);
9696 tcc_free(s1->library_paths);
9698 /* cached includes */
9699 for(i = 0; i < s1->nb_cached_includes; i++)
9700 tcc_free(s1->cached_includes[i]);
9701 tcc_free(s1->cached_includes);
9703 for(i = 0; i < s1->nb_include_paths; i++)
9704 tcc_free(s1->include_paths[i]);
9705 tcc_free(s1->include_paths);
9707 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9708 tcc_free(s1->sysinclude_paths[i]);
9709 tcc_free(s1->sysinclude_paths);
9711 tcc_free(s1);
9714 int tcc_add_include_path(TCCState *s1, const char *pathname)
9716 char *pathname1;
9718 pathname1 = tcc_strdup(pathname);
9719 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9720 return 0;
9723 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9725 char *pathname1;
9727 pathname1 = tcc_strdup(pathname);
9728 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9729 return 0;
9732 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9734 const char *ext, *filename1;
9735 Elf32_Ehdr ehdr;
9736 int fd, ret;
9737 BufferedFile *saved_file;
9739 /* find source file type with extension */
9740 filename1 = strrchr(filename, '/');
9741 if (filename1)
9742 filename1++;
9743 else
9744 filename1 = filename;
9745 ext = strrchr(filename1, '.');
9746 if (ext)
9747 ext++;
9749 /* open the file */
9750 saved_file = file;
9751 file = tcc_open(s1, filename);
9752 if (!file) {
9753 if (flags & AFF_PRINT_ERROR) {
9754 error_noabort("file '%s' not found", filename);
9756 ret = -1;
9757 goto fail1;
9760 if (!ext || !strcmp(ext, "c")) {
9761 /* C file assumed */
9762 ret = tcc_compile(s1);
9763 } else
9764 #ifdef CONFIG_TCC_ASM
9765 if (!strcmp(ext, "S")) {
9766 /* preprocessed assembler */
9767 ret = tcc_assemble(s1, 1);
9768 } else if (!strcmp(ext, "s")) {
9769 /* non preprocessed assembler */
9770 ret = tcc_assemble(s1, 0);
9771 } else
9772 #endif
9773 #ifdef TCC_TARGET_PE
9774 if (!strcmp(ext, "def")) {
9775 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
9776 } else
9777 #endif
9779 fd = file->fd;
9780 /* assume executable format: auto guess file type */
9781 ret = read(fd, &ehdr, sizeof(ehdr));
9782 lseek(fd, 0, SEEK_SET);
9783 if (ret <= 0) {
9784 error_noabort("could not read header");
9785 goto fail;
9786 } else if (ret != sizeof(ehdr)) {
9787 goto try_load_script;
9790 if (ehdr.e_ident[0] == ELFMAG0 &&
9791 ehdr.e_ident[1] == ELFMAG1 &&
9792 ehdr.e_ident[2] == ELFMAG2 &&
9793 ehdr.e_ident[3] == ELFMAG3) {
9794 file->line_num = 0; /* do not display line number if error */
9795 if (ehdr.e_type == ET_REL) {
9796 ret = tcc_load_object_file(s1, fd, 0);
9797 } else if (ehdr.e_type == ET_DYN) {
9798 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9799 #ifdef TCC_TARGET_PE
9800 ret = -1;
9801 #else
9802 void *h;
9803 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9804 if (h)
9805 ret = 0;
9806 else
9807 ret = -1;
9808 #endif
9809 } else {
9810 ret = tcc_load_dll(s1, fd, filename,
9811 (flags & AFF_REFERENCED_DLL) != 0);
9813 } else {
9814 error_noabort("unrecognized ELF file");
9815 goto fail;
9817 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9818 file->line_num = 0; /* do not display line number if error */
9819 ret = tcc_load_archive(s1, fd);
9820 } else
9821 #ifdef TCC_TARGET_COFF
9822 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
9823 ret = tcc_load_coff(s1, fd);
9824 } else
9825 #endif
9827 /* as GNU ld, consider it is an ld script if not recognized */
9828 try_load_script:
9829 ret = tcc_load_ldscript(s1);
9830 if (ret < 0) {
9831 error_noabort("unrecognized file type");
9832 goto fail;
9836 the_end:
9837 tcc_close(file);
9838 fail1:
9839 file = saved_file;
9840 return ret;
9841 fail:
9842 ret = -1;
9843 goto the_end;
9846 int tcc_add_file(TCCState *s, const char *filename)
9848 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9851 int tcc_add_library_path(TCCState *s, const char *pathname)
9853 char *pathname1;
9855 pathname1 = tcc_strdup(pathname);
9856 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9857 return 0;
9860 /* find and load a dll. Return non zero if not found */
9861 /* XXX: add '-rpath' option support ? */
9862 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9864 char buf[1024];
9865 int i;
9867 for(i = 0; i < s->nb_library_paths; i++) {
9868 snprintf(buf, sizeof(buf), "%s/%s",
9869 s->library_paths[i], filename);
9870 if (tcc_add_file_internal(s, buf, flags) == 0)
9871 return 0;
9873 return -1;
9876 /* the library name is the same as the argument of the '-l' option */
9877 int tcc_add_library(TCCState *s, const char *libraryname)
9879 char buf[1024];
9880 int i;
9882 /* first we look for the dynamic library if not static linking */
9883 if (!s->static_link) {
9884 #ifdef TCC_TARGET_PE
9885 snprintf(buf, sizeof(buf), "%s.def", libraryname);
9886 #else
9887 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9888 #endif
9889 if (tcc_add_dll(s, buf, 0) == 0)
9890 return 0;
9893 /* then we look for the static library */
9894 for(i = 0; i < s->nb_library_paths; i++) {
9895 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9896 s->library_paths[i], libraryname);
9897 if (tcc_add_file_internal(s, buf, 0) == 0)
9898 return 0;
9900 return -1;
9903 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9905 add_elf_sym(symtab_section, val, 0,
9906 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9907 SHN_ABS, name);
9908 return 0;
9911 int tcc_set_output_type(TCCState *s, int output_type)
9913 s->output_type = output_type;
9915 if (!s->nostdinc) {
9916 char buf[1024];
9918 /* default include paths */
9919 /* XXX: reverse order needed if -isystem support */
9920 #ifndef TCC_TARGET_PE
9921 tcc_add_sysinclude_path(s, "/usr/local/include");
9922 tcc_add_sysinclude_path(s, "/usr/include");
9923 #endif
9924 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9925 tcc_add_sysinclude_path(s, buf);
9926 #ifdef TCC_TARGET_PE
9927 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
9928 tcc_add_sysinclude_path(s, buf);
9929 #endif
9932 /* if bound checking, then add corresponding sections */
9933 #ifdef CONFIG_TCC_BCHECK
9934 if (do_bounds_check) {
9935 /* define symbol */
9936 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9937 /* create bounds sections */
9938 bounds_section = new_section(s, ".bounds",
9939 SHT_PROGBITS, SHF_ALLOC);
9940 lbounds_section = new_section(s, ".lbounds",
9941 SHT_PROGBITS, SHF_ALLOC);
9943 #endif
9945 if (s->char_is_unsigned) {
9946 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
9949 /* add debug sections */
9950 if (do_debug) {
9951 /* stab symbols */
9952 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9953 stab_section->sh_entsize = sizeof(Stab_Sym);
9954 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9955 put_elf_str(stabstr_section, "");
9956 stab_section->link = stabstr_section;
9957 /* put first entry */
9958 put_stabs("", 0, 0, 0, 0);
9961 /* add libc crt1/crti objects */
9962 #ifndef TCC_TARGET_PE
9963 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9964 !s->nostdlib) {
9965 if (output_type != TCC_OUTPUT_DLL)
9966 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9967 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9969 #endif
9970 return 0;
9973 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9974 #define FD_INVERT 0x0002 /* invert value before storing */
9976 typedef struct FlagDef {
9977 uint16_t offset;
9978 uint16_t flags;
9979 const char *name;
9980 } FlagDef;
9982 static const FlagDef warning_defs[] = {
9983 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9984 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9985 { offsetof(TCCState, warn_error), 0, "error" },
9986 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
9987 "implicit-function-declaration" },
9990 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
9991 const char *name, int value)
9993 int i;
9994 const FlagDef *p;
9995 const char *r;
9997 r = name;
9998 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
9999 r += 3;
10000 value = !value;
10002 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10003 if (!strcmp(r, p->name))
10004 goto found;
10006 return -1;
10007 found:
10008 if (p->flags & FD_INVERT)
10009 value = !value;
10010 *(int *)((uint8_t *)s + p->offset) = value;
10011 return 0;
10015 /* set/reset a warning */
10016 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10018 int i;
10019 const FlagDef *p;
10021 if (!strcmp(warning_name, "all")) {
10022 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10023 if (p->flags & WD_ALL)
10024 *(int *)((uint8_t *)s + p->offset) = 1;
10026 return 0;
10027 } else {
10028 return set_flag(s, warning_defs, countof(warning_defs),
10029 warning_name, value);
10033 static const FlagDef flag_defs[] = {
10034 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10035 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10036 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10039 /* set/reset a flag */
10040 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10042 return set_flag(s, flag_defs, countof(flag_defs),
10043 flag_name, value);
10046 #if !defined(LIBTCC)
10048 /* extract the basename of a file */
10049 static const char *tcc_basename(const char *name)
10051 const char *p;
10052 p = strrchr(name, '/');
10053 #ifdef WIN32
10054 if (!p)
10055 p = strrchr(name, '\\');
10056 #endif
10057 if (!p)
10058 p = name;
10059 else
10060 p++;
10061 return p;
10064 static int64_t getclock_us(void)
10066 #ifdef WIN32
10067 struct _timeb tb;
10068 _ftime(&tb);
10069 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10070 #else
10071 struct timeval tv;
10072 gettimeofday(&tv, NULL);
10073 return tv.tv_sec * 1000000LL + tv.tv_usec;
10074 #endif
10077 void help(void)
10079 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2005 Fabrice Bellard\n"
10080 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10081 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10082 " [infile1 infile2...] [-run infile args...]\n"
10083 "\n"
10084 "General options:\n"
10085 " -v display current version\n"
10086 " -c compile only - generate an object file\n"
10087 " -o outfile set output filename\n"
10088 " -Bdir set tcc internal library path\n"
10089 " -bench output compilation statistics\n"
10090 " -run run compiled source\n"
10091 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10092 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10093 " -w disable all warnings\n"
10094 "Preprocessor options:\n"
10095 " -Idir add include path 'dir'\n"
10096 " -Dsym[=val] define 'sym' with value 'val'\n"
10097 " -Usym undefine 'sym'\n"
10098 "Linker options:\n"
10099 " -Ldir add library path 'dir'\n"
10100 " -llib link with dynamic or static library 'lib'\n"
10101 " -shared generate a shared library\n"
10102 " -static static linking\n"
10103 " -rdynamic export all global symbols to dynamic linker\n"
10104 " -r relocatable output\n"
10105 "Debugger options:\n"
10106 " -g generate runtime debug info\n"
10107 #ifdef CONFIG_TCC_BCHECK
10108 " -b compile with built-in memory and bounds checker (implies -g)\n"
10109 #endif
10110 " -bt N show N callers in stack traces\n"
10114 #define TCC_OPTION_HAS_ARG 0x0001
10115 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10117 typedef struct TCCOption {
10118 const char *name;
10119 uint16_t index;
10120 uint16_t flags;
10121 } TCCOption;
10123 enum {
10124 TCC_OPTION_HELP,
10125 TCC_OPTION_I,
10126 TCC_OPTION_D,
10127 TCC_OPTION_U,
10128 TCC_OPTION_L,
10129 TCC_OPTION_B,
10130 TCC_OPTION_l,
10131 TCC_OPTION_bench,
10132 TCC_OPTION_bt,
10133 TCC_OPTION_b,
10134 TCC_OPTION_g,
10135 TCC_OPTION_c,
10136 TCC_OPTION_static,
10137 TCC_OPTION_shared,
10138 TCC_OPTION_o,
10139 TCC_OPTION_r,
10140 TCC_OPTION_Wl,
10141 TCC_OPTION_W,
10142 TCC_OPTION_O,
10143 TCC_OPTION_m,
10144 TCC_OPTION_f,
10145 TCC_OPTION_nostdinc,
10146 TCC_OPTION_nostdlib,
10147 TCC_OPTION_print_search_dirs,
10148 TCC_OPTION_rdynamic,
10149 TCC_OPTION_run,
10150 TCC_OPTION_v,
10151 TCC_OPTION_w,
10152 TCC_OPTION_pipe,
10155 static const TCCOption tcc_options[] = {
10156 { "h", TCC_OPTION_HELP, 0 },
10157 { "?", TCC_OPTION_HELP, 0 },
10158 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10159 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10160 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10161 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10162 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10163 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10164 { "bench", TCC_OPTION_bench, 0 },
10165 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10166 #ifdef CONFIG_TCC_BCHECK
10167 { "b", TCC_OPTION_b, 0 },
10168 #endif
10169 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10170 { "c", TCC_OPTION_c, 0 },
10171 { "static", TCC_OPTION_static, 0 },
10172 { "shared", TCC_OPTION_shared, 0 },
10173 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10174 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10175 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10176 { "r", TCC_OPTION_r, 0 },
10177 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10178 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10179 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10180 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10181 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10182 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10183 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10184 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10185 { "v", TCC_OPTION_v, 0 },
10186 { "w", TCC_OPTION_w, 0 },
10187 { "pipe", TCC_OPTION_pipe, 0},
10188 { NULL },
10191 /* convert 'str' into an array of space separated strings */
10192 static int expand_args(char ***pargv, const char *str)
10194 const char *s1;
10195 char **argv, *arg;
10196 int argc, len;
10198 argc = 0;
10199 argv = NULL;
10200 for(;;) {
10201 while (is_space(*str))
10202 str++;
10203 if (*str == '\0')
10204 break;
10205 s1 = str;
10206 while (*str != '\0' && !is_space(*str))
10207 str++;
10208 len = str - s1;
10209 arg = tcc_malloc(len + 1);
10210 memcpy(arg, s1, len);
10211 arg[len] = '\0';
10212 dynarray_add((void ***)&argv, &argc, arg);
10214 *pargv = argv;
10215 return argc;
10218 static char **files;
10219 static int nb_files, nb_libraries;
10220 static int multiple_files;
10221 static int print_search_dirs;
10222 static int output_type;
10223 static int reloc_output;
10224 static const char *outfile;
10226 int parse_args(TCCState *s, int argc, char **argv)
10228 int optind;
10229 const TCCOption *popt;
10230 const char *optarg, *p1, *r1;
10231 char *r;
10233 optind = 0;
10234 while (1) {
10235 if (optind >= argc) {
10236 if (nb_files == 0 && !print_search_dirs)
10237 goto show_help;
10238 else
10239 break;
10241 r = argv[optind++];
10242 if (r[0] != '-') {
10243 /* add a new file */
10244 dynarray_add((void ***)&files, &nb_files, r);
10245 if (!multiple_files) {
10246 optind--;
10247 /* argv[0] will be this file */
10248 break;
10250 } else {
10251 /* find option in table (match only the first chars */
10252 popt = tcc_options;
10253 for(;;) {
10254 p1 = popt->name;
10255 if (p1 == NULL)
10256 error("invalid option -- '%s'", r);
10257 r1 = r + 1;
10258 for(;;) {
10259 if (*p1 == '\0')
10260 goto option_found;
10261 if (*r1 != *p1)
10262 break;
10263 p1++;
10264 r1++;
10266 popt++;
10268 option_found:
10269 if (popt->flags & TCC_OPTION_HAS_ARG) {
10270 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10271 optarg = r1;
10272 } else {
10273 if (optind >= argc)
10274 error("argument to '%s' is missing", r);
10275 optarg = argv[optind++];
10277 } else {
10278 if (*r1 != '\0')
10279 goto show_help;
10280 optarg = NULL;
10283 switch(popt->index) {
10284 case TCC_OPTION_HELP:
10285 show_help:
10286 help();
10287 exit(1);
10288 case TCC_OPTION_I:
10289 if (tcc_add_include_path(s, optarg) < 0)
10290 error("too many include paths");
10291 break;
10292 case TCC_OPTION_D:
10294 char *sym, *value;
10295 sym = (char *)optarg;
10296 value = strchr(sym, '=');
10297 if (value) {
10298 *value = '\0';
10299 value++;
10301 tcc_define_symbol(s, sym, value);
10303 break;
10304 case TCC_OPTION_U:
10305 tcc_undefine_symbol(s, optarg);
10306 break;
10307 case TCC_OPTION_L:
10308 tcc_add_library_path(s, optarg);
10309 break;
10310 case TCC_OPTION_B:
10311 /* set tcc utilities path (mainly for tcc development) */
10312 tcc_lib_path = optarg;
10313 break;
10314 case TCC_OPTION_l:
10315 dynarray_add((void ***)&files, &nb_files, r);
10316 nb_libraries++;
10317 break;
10318 case TCC_OPTION_bench:
10319 do_bench = 1;
10320 break;
10321 case TCC_OPTION_bt:
10322 num_callers = atoi(optarg);
10323 break;
10324 #ifdef CONFIG_TCC_BCHECK
10325 case TCC_OPTION_b:
10326 do_bounds_check = 1;
10327 do_debug = 1;
10328 break;
10329 #endif
10330 case TCC_OPTION_g:
10331 do_debug = 1;
10332 break;
10333 case TCC_OPTION_c:
10334 multiple_files = 1;
10335 output_type = TCC_OUTPUT_OBJ;
10336 break;
10337 case TCC_OPTION_static:
10338 s->static_link = 1;
10339 break;
10340 case TCC_OPTION_shared:
10341 output_type = TCC_OUTPUT_DLL;
10342 break;
10343 case TCC_OPTION_o:
10344 multiple_files = 1;
10345 outfile = optarg;
10346 break;
10347 case TCC_OPTION_r:
10348 /* generate a .o merging several output files */
10349 reloc_output = 1;
10350 output_type = TCC_OUTPUT_OBJ;
10351 break;
10352 case TCC_OPTION_nostdinc:
10353 s->nostdinc = 1;
10354 break;
10355 case TCC_OPTION_nostdlib:
10356 s->nostdlib = 1;
10357 break;
10358 case TCC_OPTION_print_search_dirs:
10359 print_search_dirs = 1;
10360 break;
10361 case TCC_OPTION_run:
10363 int argc1;
10364 char **argv1;
10365 argc1 = expand_args(&argv1, optarg);
10366 if (argc1 > 0) {
10367 parse_args(s, argc1, argv1);
10369 multiple_files = 0;
10370 output_type = TCC_OUTPUT_MEMORY;
10372 break;
10373 case TCC_OPTION_v:
10374 printf("tcc version %s\n", TCC_VERSION);
10375 exit(0);
10376 case TCC_OPTION_f:
10377 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10378 goto unsupported_option;
10379 break;
10380 case TCC_OPTION_W:
10381 if (tcc_set_warning(s, optarg, 1) < 0 &&
10382 s->warn_unsupported)
10383 goto unsupported_option;
10384 break;
10385 case TCC_OPTION_w:
10386 s->warn_none = 1;
10387 break;
10388 case TCC_OPTION_rdynamic:
10389 s->rdynamic = 1;
10390 break;
10391 case TCC_OPTION_Wl:
10393 const char *p;
10394 if (strstart(optarg, "-Ttext,", &p)) {
10395 s->text_addr = strtoul(p, NULL, 16);
10396 s->has_text_addr = 1;
10397 } else if (strstart(optarg, "--oformat,", &p)) {
10398 if (strstart(p, "elf32-", NULL)) {
10399 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10400 } else if (!strcmp(p, "binary")) {
10401 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10402 } else
10403 #ifdef TCC_TARGET_COFF
10404 if (!strcmp(p, "coff")) {
10405 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10406 } else
10407 #endif
10409 error("target %s not found", p);
10411 } else {
10412 error("unsupported linker option '%s'", optarg);
10415 break;
10416 default:
10417 if (s->warn_unsupported) {
10418 unsupported_option:
10419 warning("unsupported option '%s'", r);
10421 break;
10425 return optind;
10428 int main(int argc, char **argv)
10430 int i;
10431 TCCState *s;
10432 int nb_objfiles, ret, optind;
10433 char objfilename[1024];
10434 int64_t start_time = 0;
10436 #ifdef WIN32
10437 /* on win32, we suppose the lib and includes are at the location
10438 of 'tcc.exe' */
10440 static char path[1024];
10442 GetModuleFileNameA(NULL, path, sizeof path);
10443 p = d = strlwr(path);
10444 while (*d)
10445 if (*d++ == '\\')
10446 (p = d)[-1] = '/';
10447 *p = '\0';
10448 tcc_lib_path = path;
10450 #endif
10452 s = tcc_new();
10453 output_type = TCC_OUTPUT_EXE;
10454 outfile = NULL;
10455 multiple_files = 1;
10456 files = NULL;
10457 nb_files = 0;
10458 nb_libraries = 0;
10459 reloc_output = 0;
10460 print_search_dirs = 0;
10462 optind = parse_args(s, argc - 1, argv + 1) + 1;
10464 if (print_search_dirs) {
10465 /* enough for Linux kernel */
10466 printf("install: %s/\n", tcc_lib_path);
10467 return 0;
10470 nb_objfiles = nb_files - nb_libraries;
10472 /* if outfile provided without other options, we output an
10473 executable */
10474 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10475 output_type = TCC_OUTPUT_EXE;
10477 /* check -c consistency : only single file handled. XXX: checks file type */
10478 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10479 /* accepts only a single input file */
10480 if (nb_objfiles != 1)
10481 error("cannot specify multiple files with -c");
10482 if (nb_libraries != 0)
10483 error("cannot specify libraries with -c");
10486 /* compute default outfile name */
10487 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
10488 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10489 char *ext;
10490 /* strip path */
10491 pstrcpy(objfilename, sizeof(objfilename) - 1,
10492 tcc_basename(files[0]));
10493 /* add .o extension */
10494 ext = strrchr(objfilename, '.');
10495 if (!ext)
10496 goto default_outfile;
10497 strcpy(ext + 1, "o");
10498 } else {
10499 default_outfile:
10500 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10502 outfile = objfilename;
10505 if (do_bench) {
10506 start_time = getclock_us();
10509 tcc_set_output_type(s, output_type);
10511 /* compile or add each files or library */
10512 for(i = 0;i < nb_files; i++) {
10513 const char *filename;
10515 filename = files[i];
10516 if (filename[0] == '-') {
10517 if (tcc_add_library(s, filename + 2) < 0)
10518 error("cannot find %s", filename);
10519 } else {
10520 if (tcc_add_file(s, filename) < 0) {
10521 ret = 1;
10522 goto the_end;
10527 /* free all files */
10528 tcc_free(files);
10530 if (do_bench) {
10531 double total_time;
10532 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10533 if (total_time < 0.001)
10534 total_time = 0.001;
10535 if (total_bytes < 1)
10536 total_bytes = 1;
10537 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10538 tok_ident - TOK_IDENT, total_lines, total_bytes,
10539 total_time, (int)(total_lines / total_time),
10540 total_bytes / total_time / 1000000.0);
10543 if (s->output_type == TCC_OUTPUT_MEMORY) {
10544 ret = tcc_run(s, argc - optind, argv + optind);
10545 } else
10546 #ifdef TCC_TARGET_PE
10547 if (s->output_type != TCC_OUTPUT_OBJ) {
10548 ret = tcc_output_pe(s, outfile);
10549 } else
10550 #endif
10552 tcc_output_file(s, outfile);
10553 ret = 0;
10555 the_end:
10556 /* XXX: cannot do it with bound checking because of the malloc hooks */
10557 if (!do_bounds_check)
10558 tcc_delete(s);
10560 #ifdef MEM_DEBUG
10561 if (do_bench) {
10562 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10564 #endif
10565 return ret;
10568 #endif