fixed parsing of function parameters
[tinycc.git] / tcc.c
blob76c19a56ab1991bba2ce0e23b516649007950bb4
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 #include <windows.h>
44 #endif
45 #ifndef WIN32
46 #include <sys/time.h>
47 #include <sys/ucontext.h>
48 #include <sys/mman.h>
49 #endif
51 #endif /* !CONFIG_TCCBOOT */
53 #ifndef PAGESIZE
54 #define PAGESIZE 4096
55 #endif
57 #include "elf.h"
58 #include "stab.h"
60 #ifndef O_BINARY
61 #define O_BINARY 0
62 #endif
64 #include "libtcc.h"
66 /* parser debug */
67 //#define PARSE_DEBUG
68 /* preprocessor debug */
69 //#define PP_DEBUG
70 /* include file debug */
71 //#define INC_DEBUG
73 //#define MEM_DEBUG
75 /* assembler debug */
76 //#define ASM_DEBUG
78 /* target selection */
79 //#define TCC_TARGET_I386 /* i386 code generator */
80 //#define TCC_TARGET_ARM /* ARMv4 code generator */
81 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
83 /* default target is I386 */
84 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
85 !defined(TCC_TARGET_C67)
86 #define TCC_TARGET_I386
87 #endif
89 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
90 !defined(TCC_TARGET_C67)
91 #define CONFIG_TCC_BCHECK /* enable bound checking code */
92 #endif
94 #if defined(WIN32) && !defined(TCC_TARGET_PE)
95 #define CONFIG_TCC_STATIC
96 #endif
98 /* define it to include assembler support */
99 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
100 #define CONFIG_TCC_ASM
101 #endif
103 /* object format selection */
104 #if defined(TCC_TARGET_C67)
105 #define TCC_TARGET_COFF
106 #endif
108 #define FALSE 0
109 #define false 0
110 #define TRUE 1
111 #define true 1
112 typedef int BOOL;
114 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
115 executables or dlls */
116 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
118 #define INCLUDE_STACK_SIZE 32
119 #define IFDEF_STACK_SIZE 64
120 #define VSTACK_SIZE 256
121 #define STRING_MAX_SIZE 1024
122 #define PACK_STACK_SIZE 8
124 #define TOK_HASH_SIZE 8192 /* must be a power of two */
125 #define TOK_ALLOC_INCR 512 /* must be a power of two */
126 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
128 /* token symbol management */
129 typedef struct TokenSym {
130 struct TokenSym *hash_next;
131 struct Sym *sym_define; /* direct pointer to define */
132 struct Sym *sym_label; /* direct pointer to label */
133 struct Sym *sym_struct; /* direct pointer to structure */
134 struct Sym *sym_identifier; /* direct pointer to identifier */
135 int tok; /* token number */
136 int len;
137 char str[1];
138 } TokenSym;
140 #ifdef TCC_TARGET_PE
141 typedef unsigned short nwchar_t;
142 #else
143 typedef int nwchar_t;
144 #endif
146 typedef struct CString {
147 int size; /* size in bytes */
148 void *data; /* either 'char *' or 'nwchar_t *' */
149 int size_allocated;
150 void *data_allocated; /* if non NULL, data has been malloced */
151 } CString;
153 /* type definition */
154 typedef struct CType {
155 int t;
156 struct Sym *ref;
157 } CType;
159 /* constant value */
160 typedef union CValue {
161 long double ld;
162 double d;
163 float f;
164 int i;
165 unsigned int ui;
166 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
167 long long ll;
168 unsigned long long ull;
169 struct CString *cstr;
170 void *ptr;
171 int tab[1];
172 } CValue;
174 /* value on stack */
175 typedef struct SValue {
176 CType type; /* type */
177 unsigned short r; /* register + flags */
178 unsigned short r2; /* second register, used for 'long long'
179 type. If not used, set to VT_CONST */
180 CValue c; /* constant, if VT_CONST */
181 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
182 } SValue;
184 /* symbol management */
185 typedef struct Sym {
186 int v; /* symbol token */
187 int r; /* associated register */
188 int c; /* associated number */
189 CType type; /* associated type */
190 struct Sym *next; /* next related symbol */
191 struct Sym *prev; /* prev symbol in stack */
192 struct Sym *prev_tok; /* previous symbol for this token */
193 } Sym;
195 /* section definition */
196 /* XXX: use directly ELF structure for parameters ? */
197 /* special flag to indicate that the section should not be linked to
198 the other ones */
199 #define SHF_PRIVATE 0x80000000
201 typedef struct Section {
202 unsigned long data_offset; /* current data offset */
203 unsigned char *data; /* section data */
204 unsigned long data_allocated; /* used for realloc() handling */
205 int sh_name; /* elf section name (only used during output) */
206 int sh_num; /* elf section number */
207 int sh_type; /* elf section type */
208 int sh_flags; /* elf section flags */
209 int sh_info; /* elf section info */
210 int sh_addralign; /* elf section alignment */
211 int sh_entsize; /* elf entry size */
212 unsigned long sh_size; /* section size (only used during output) */
213 unsigned long sh_addr; /* address at which the section is relocated */
214 unsigned long sh_offset; /* file offset */
215 int nb_hashed_syms; /* used to resize the hash table */
216 struct Section *link; /* link to another section */
217 struct Section *reloc; /* corresponding section for relocation, if any */
218 struct Section *hash; /* hash table for symbols */
219 struct Section *next;
220 char name[1]; /* section name */
221 } Section;
223 typedef struct DLLReference {
224 int level;
225 char name[1];
226 } DLLReference;
228 /* GNUC attribute definition */
229 typedef struct AttributeDef {
230 int aligned;
231 int packed;
232 Section *section;
233 unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
234 unsigned char dllexport;
235 } AttributeDef;
237 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
238 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
239 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
241 /* stored in 'Sym.c' field */
242 #define FUNC_NEW 1 /* ansi function prototype */
243 #define FUNC_OLD 2 /* old function prototype */
244 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
246 /* stored in 'Sym.r' field */
247 #define FUNC_CDECL 0 /* standard c call */
248 #define FUNC_STDCALL 1 /* pascal c call */
249 #define FUNC_FASTCALL1 2 /* first param in %eax */
250 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
251 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
252 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
254 /* field 'Sym.t' for macros */
255 #define MACRO_OBJ 0 /* object like macro */
256 #define MACRO_FUNC 1 /* function like macro */
258 /* field 'Sym.r' for C labels */
259 #define LABEL_DEFINED 0 /* label is defined */
260 #define LABEL_FORWARD 1 /* label is forward defined */
261 #define LABEL_DECLARED 2 /* label is declared but never used */
263 /* type_decl() types */
264 #define TYPE_ABSTRACT 1 /* type without variable */
265 #define TYPE_DIRECT 2 /* type with variable */
267 #define IO_BUF_SIZE 8192
269 typedef struct BufferedFile {
270 uint8_t *buf_ptr;
271 uint8_t *buf_end;
272 int fd;
273 int line_num; /* current line number - here to simplify code */
274 int ifndef_macro; /* #ifndef macro / #endif search */
275 int ifndef_macro_saved; /* saved ifndef_macro */
276 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
277 char inc_type; /* type of include */
278 char inc_filename[512]; /* filename specified by the user */
279 char filename[1024]; /* current filename - here to simplify code */
280 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
281 } BufferedFile;
283 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
284 #define CH_EOF (-1) /* end of file */
286 /* parsing state (used to save parser state to reparse part of the
287 source several times) */
288 typedef struct ParseState {
289 int *macro_ptr;
290 int line_num;
291 int tok;
292 CValue tokc;
293 } ParseState;
295 /* used to record tokens */
296 typedef struct TokenString {
297 int *str;
298 int len;
299 int allocated_len;
300 int last_line_num;
301 } TokenString;
303 /* include file cache, used to find files faster and also to eliminate
304 inclusion if the include file is protected by #ifndef ... #endif */
305 typedef struct CachedInclude {
306 int ifndef_macro;
307 int hash_next; /* -1 if none */
308 char type; /* '"' or '>' to give include type */
309 char filename[1]; /* path specified in #include */
310 } CachedInclude;
312 #define CACHED_INCLUDES_HASH_SIZE 512
314 /* parser */
315 static struct BufferedFile *file;
316 static int ch, tok;
317 static CValue tokc;
318 static CString tokcstr; /* current parsed string, if any */
319 /* additional informations about token */
320 static int tok_flags;
321 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
322 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
323 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
325 static int *macro_ptr, *macro_ptr_allocated;
326 static int *unget_saved_macro_ptr;
327 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
328 static int unget_buffer_enabled;
329 static int parse_flags;
330 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
331 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
332 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
333 token. line feed is also
334 returned at eof */
335 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
337 static Section *text_section, *data_section, *bss_section; /* predefined sections */
338 static Section *cur_text_section; /* current section where function code is
339 generated */
340 #ifdef CONFIG_TCC_ASM
341 static Section *last_text_section; /* to handle .previous asm directive */
342 #endif
343 /* bound check related sections */
344 static Section *bounds_section; /* contains global data bound description */
345 static Section *lbounds_section; /* contains local data bound description */
346 /* symbol sections */
347 static Section *symtab_section, *strtab_section;
349 /* debug sections */
350 static Section *stab_section, *stabstr_section;
352 /* loc : local variable index
353 ind : output code index
354 rsym: return symbol
355 anon_sym: anonymous symbol index
357 static int rsym, anon_sym, ind, loc;
358 /* expression generation modifiers */
359 static int const_wanted; /* true if constant wanted */
360 static int nocode_wanted; /* true if no code generation wanted for an expression */
361 static int global_expr; /* true if compound literals must be allocated
362 globally (used during initializers parsing */
363 static CType func_vt; /* current function return type (used by return
364 instruction) */
365 static int func_vc;
366 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
367 static int tok_ident;
368 static TokenSym **table_ident;
369 static TokenSym *hash_ident[TOK_HASH_SIZE];
370 static char token_buf[STRING_MAX_SIZE + 1];
371 static char *funcname;
372 static Sym *global_stack, *local_stack;
373 static Sym *define_stack;
374 static Sym *global_label_stack, *local_label_stack;
375 /* symbol allocator */
376 #define SYM_POOL_NB (8192 / sizeof(Sym))
377 static Sym *sym_free_first;
379 static SValue vstack[VSTACK_SIZE], *vtop;
380 /* some predefined types */
381 static CType char_pointer_type, func_old_type, int_type;
382 /* true if isid(c) || isnum(c) */
383 static unsigned char isidnum_table[256];
385 /* compile with debug symbol (and use them if error during execution) */
386 static int do_debug = 0;
388 /* compile with built-in memory and bounds checker */
389 static int do_bounds_check = 0;
391 /* display benchmark infos */
392 #if !defined(LIBTCC)
393 static int do_bench = 0;
394 #endif
395 static int total_lines;
396 static int total_bytes;
398 /* use GNU C extensions */
399 static int gnu_ext = 1;
401 /* use Tiny C extensions */
402 static int tcc_ext = 1;
404 /* max number of callers shown if error */
405 static int num_callers = 6;
406 static const char **rt_bound_error_msg;
408 /* XXX: get rid of this ASAP */
409 static struct TCCState *tcc_state;
411 /* give the path of the tcc libraries */
412 static const char *tcc_lib_path = CONFIG_TCCDIR;
414 struct TCCState {
415 int output_type;
417 BufferedFile **include_stack_ptr;
418 int *ifdef_stack_ptr;
420 /* include file handling */
421 char **include_paths;
422 int nb_include_paths;
423 char **sysinclude_paths;
424 int nb_sysinclude_paths;
425 CachedInclude **cached_includes;
426 int nb_cached_includes;
428 char **library_paths;
429 int nb_library_paths;
431 /* array of all loaded dlls (including those referenced by loaded
432 dlls) */
433 DLLReference **loaded_dlls;
434 int nb_loaded_dlls;
436 /* sections */
437 Section **sections;
438 int nb_sections; /* number of sections, including first dummy section */
440 /* got handling */
441 Section *got;
442 Section *plt;
443 unsigned long *got_offsets;
444 int nb_got_offsets;
445 /* give the correspondance from symtab indexes to dynsym indexes */
446 int *symtab_to_dynsym;
448 /* temporary dynamic symbol sections (for dll loading) */
449 Section *dynsymtab_section;
450 /* exported dynamic symbol section */
451 Section *dynsym;
453 int nostdinc; /* if true, no standard headers are added */
454 int nostdlib; /* if true, no standard libraries are added */
456 int nocommon; /* if true, do not use common symbols for .bss data */
458 /* if true, static linking is performed */
459 int static_link;
461 /* if true, all symbols are exported */
462 int rdynamic;
464 /* if true, only link in referenced objects from archive */
465 int alacarte_link;
467 /* address of text section */
468 unsigned long text_addr;
469 int has_text_addr;
471 /* output format, see TCC_OUTPUT_FORMAT_xxx */
472 int output_format;
474 /* C language options */
475 int char_is_unsigned;
476 int leading_underscore;
478 /* warning switches */
479 int warn_write_strings;
480 int warn_unsupported;
481 int warn_error;
482 int warn_none;
483 int warn_implicit_function_declaration;
485 /* error handling */
486 void *error_opaque;
487 void (*error_func)(void *opaque, const char *msg);
488 int error_set_jmp_enabled;
489 jmp_buf error_jmp_buf;
490 int nb_errors;
492 /* tiny assembler state */
493 Sym *asm_labels;
495 /* see include_stack_ptr */
496 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
498 /* see ifdef_stack_ptr */
499 int ifdef_stack[IFDEF_STACK_SIZE];
501 /* see cached_includes */
502 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
504 /* pack stack */
505 int pack_stack[PACK_STACK_SIZE];
506 int *pack_stack_ptr;
509 /* The current value can be: */
510 #define VT_VALMASK 0x00ff
511 #define VT_CONST 0x00f0 /* constant in vc
512 (must be first non register value) */
513 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
514 #define VT_LOCAL 0x00f2 /* offset on stack */
515 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
516 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
517 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
518 #define VT_LVAL 0x0100 /* var is an lvalue */
519 #define VT_SYM 0x0200 /* a symbol value is added */
520 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
521 char/short stored in integer registers) */
522 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
523 dereferencing value */
524 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
525 bounding function call point is in vc */
526 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
527 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
528 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
529 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
531 /* types */
532 #define VT_INT 0 /* integer type */
533 #define VT_BYTE 1 /* signed byte type */
534 #define VT_SHORT 2 /* short type */
535 #define VT_VOID 3 /* void type */
536 #define VT_PTR 4 /* pointer */
537 #define VT_ENUM 5 /* enum definition */
538 #define VT_FUNC 6 /* function type */
539 #define VT_STRUCT 7 /* struct/union definition */
540 #define VT_FLOAT 8 /* IEEE float */
541 #define VT_DOUBLE 9 /* IEEE double */
542 #define VT_LDOUBLE 10 /* IEEE long double */
543 #define VT_BOOL 11 /* ISOC99 boolean type */
544 #define VT_LLONG 12 /* 64 bit integer */
545 #define VT_LONG 13 /* long integer (NEVER USED as type, only
546 during parsing) */
547 #define VT_BTYPE 0x000f /* mask for basic type */
548 #define VT_UNSIGNED 0x0010 /* unsigned type */
549 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
550 #define VT_BITFIELD 0x0040 /* bitfield modifier */
551 #define VT_CONSTANT 0x0800 /* const modifier */
552 #define VT_VOLATILE 0x1000 /* volatile modifier */
553 #define VT_SIGNED 0x2000 /* signed type */
555 /* storage */
556 #define VT_EXTERN 0x00000080 /* extern definition */
557 #define VT_STATIC 0x00000100 /* static variable */
558 #define VT_TYPEDEF 0x00000200 /* typedef definition */
559 #define VT_INLINE 0x00000400 /* inline definition */
561 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
563 /* type mask (except storage) */
564 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
565 #define VT_TYPE (~(VT_STORAGE))
567 /* token values */
569 /* warning: the following compare tokens depend on i386 asm code */
570 #define TOK_ULT 0x92
571 #define TOK_UGE 0x93
572 #define TOK_EQ 0x94
573 #define TOK_NE 0x95
574 #define TOK_ULE 0x96
575 #define TOK_UGT 0x97
576 #define TOK_LT 0x9c
577 #define TOK_GE 0x9d
578 #define TOK_LE 0x9e
579 #define TOK_GT 0x9f
581 #define TOK_LAND 0xa0
582 #define TOK_LOR 0xa1
584 #define TOK_DEC 0xa2
585 #define TOK_MID 0xa3 /* inc/dec, to void constant */
586 #define TOK_INC 0xa4
587 #define TOK_UDIV 0xb0 /* unsigned division */
588 #define TOK_UMOD 0xb1 /* unsigned modulo */
589 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
590 #define TOK_CINT 0xb3 /* number in tokc */
591 #define TOK_CCHAR 0xb4 /* char constant in tokc */
592 #define TOK_STR 0xb5 /* pointer to string in tokc */
593 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
594 #define TOK_LCHAR 0xb7
595 #define TOK_LSTR 0xb8
596 #define TOK_CFLOAT 0xb9 /* float constant */
597 #define TOK_LINENUM 0xba /* line number info */
598 #define TOK_CDOUBLE 0xc0 /* double constant */
599 #define TOK_CLDOUBLE 0xc1 /* long double constant */
600 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
601 #define TOK_ADDC1 0xc3 /* add with carry generation */
602 #define TOK_ADDC2 0xc4 /* add with carry use */
603 #define TOK_SUBC1 0xc5 /* add with carry generation */
604 #define TOK_SUBC2 0xc6 /* add with carry use */
605 #define TOK_CUINT 0xc8 /* unsigned int constant */
606 #define TOK_CLLONG 0xc9 /* long long constant */
607 #define TOK_CULLONG 0xca /* unsigned long long constant */
608 #define TOK_ARROW 0xcb
609 #define TOK_DOTS 0xcc /* three dots */
610 #define TOK_SHR 0xcd /* unsigned shift right */
611 #define TOK_PPNUM 0xce /* preprocessor number */
613 #define TOK_SHL 0x01 /* shift left */
614 #define TOK_SAR 0x02 /* signed shift right */
616 /* assignement operators : normal operator or 0x80 */
617 #define TOK_A_MOD 0xa5
618 #define TOK_A_AND 0xa6
619 #define TOK_A_MUL 0xaa
620 #define TOK_A_ADD 0xab
621 #define TOK_A_SUB 0xad
622 #define TOK_A_DIV 0xaf
623 #define TOK_A_XOR 0xde
624 #define TOK_A_OR 0xfc
625 #define TOK_A_SHL 0x81
626 #define TOK_A_SAR 0x82
628 #ifndef offsetof
629 #define offsetof(type, field) ((size_t) &((type *)0)->field)
630 #endif
632 #ifndef countof
633 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
634 #endif
636 /* WARNING: the content of this string encodes token numbers */
637 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";
639 #define TOK_EOF (-1) /* end of file */
640 #define TOK_LINEFEED 10 /* line feed */
642 /* all identificators and strings have token above that */
643 #define TOK_IDENT 256
645 /* only used for i386 asm opcodes definitions */
646 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
648 #define DEF_BWL(x) \
649 DEF(TOK_ASM_ ## x ## b, #x "b") \
650 DEF(TOK_ASM_ ## x ## w, #x "w") \
651 DEF(TOK_ASM_ ## x ## l, #x "l") \
652 DEF(TOK_ASM_ ## x, #x)
654 #define DEF_WL(x) \
655 DEF(TOK_ASM_ ## x ## w, #x "w") \
656 DEF(TOK_ASM_ ## x ## l, #x "l") \
657 DEF(TOK_ASM_ ## x, #x)
659 #define DEF_FP1(x) \
660 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
661 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
662 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
663 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
665 #define DEF_FP(x) \
666 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
667 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
668 DEF_FP1(x)
670 #define DEF_ASMTEST(x) \
671 DEF_ASM(x ## o) \
672 DEF_ASM(x ## no) \
673 DEF_ASM(x ## b) \
674 DEF_ASM(x ## c) \
675 DEF_ASM(x ## nae) \
676 DEF_ASM(x ## nb) \
677 DEF_ASM(x ## nc) \
678 DEF_ASM(x ## ae) \
679 DEF_ASM(x ## e) \
680 DEF_ASM(x ## z) \
681 DEF_ASM(x ## ne) \
682 DEF_ASM(x ## nz) \
683 DEF_ASM(x ## be) \
684 DEF_ASM(x ## na) \
685 DEF_ASM(x ## nbe) \
686 DEF_ASM(x ## a) \
687 DEF_ASM(x ## s) \
688 DEF_ASM(x ## ns) \
689 DEF_ASM(x ## p) \
690 DEF_ASM(x ## pe) \
691 DEF_ASM(x ## np) \
692 DEF_ASM(x ## po) \
693 DEF_ASM(x ## l) \
694 DEF_ASM(x ## nge) \
695 DEF_ASM(x ## nl) \
696 DEF_ASM(x ## ge) \
697 DEF_ASM(x ## le) \
698 DEF_ASM(x ## ng) \
699 DEF_ASM(x ## nle) \
700 DEF_ASM(x ## g)
702 #define TOK_ASM_int TOK_INT
704 enum tcc_token {
705 TOK_LAST = TOK_IDENT - 1,
706 #define DEF(id, str) id,
707 #include "tcctok.h"
708 #undef DEF
711 static const char tcc_keywords[] =
712 #define DEF(id, str) str "\0"
713 #include "tcctok.h"
714 #undef DEF
717 #define TOK_UIDENT TOK_DEFINE
719 #ifdef WIN32
720 int __stdcall GetModuleFileNameA(void *, char *, int);
721 void *__stdcall GetProcAddress(void *, const char *);
722 void *__stdcall GetModuleHandleA(const char *);
723 void *__stdcall LoadLibraryA(const char *);
724 int __stdcall FreeConsole(void);
726 #define snprintf _snprintf
727 #define vsnprintf _vsnprintf
728 #ifndef __GNUC__
729 #define strtold (long double)strtod
730 #define strtof (float)strtod
731 #define strtoll (long long)strtol
732 #endif
733 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
734 /* currently incorrect */
735 long double strtold(const char *nptr, char **endptr)
737 return (long double)strtod(nptr, endptr);
739 float strtof(const char *nptr, char **endptr)
741 return (float)strtod(nptr, endptr);
743 #else
744 /* XXX: need to define this to use them in non ISOC99 context */
745 extern float strtof (const char *__nptr, char **__endptr);
746 extern long double strtold (const char *__nptr, char **__endptr);
747 #endif
749 static char *pstrcpy(char *buf, int buf_size, const char *s);
750 static char *pstrcat(char *buf, int buf_size, const char *s);
751 static const char *tcc_basename(const char *name);
753 static void next(void);
754 static void next_nomacro(void);
755 static void parse_expr_type(CType *type);
756 static void expr_type(CType *type);
757 static void unary_type(CType *type);
758 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
759 int case_reg, int is_expr);
760 static int expr_const(void);
761 static void expr_eq(void);
762 static void gexpr(void);
763 static void gen_inline_functions(void);
764 static void decl(int l);
765 static void decl_initializer(CType *type, Section *sec, unsigned long c,
766 int first, int size_only);
767 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
768 int has_init, int v, int scope);
769 int gv(int rc);
770 void gv2(int rc1, int rc2);
771 void move_reg(int r, int s);
772 void save_regs(int n);
773 void save_reg(int r);
774 void vpop(void);
775 void vswap(void);
776 void vdup(void);
777 int get_reg(int rc);
778 int get_reg_ex(int rc,int rc2);
780 struct macro_level {
781 struct macro_level *prev;
782 int *p;
785 static void macro_subst(TokenString *tok_str, Sym **nested_list,
786 const int *macro_str, struct macro_level **can_read_stream);
787 void gen_op(int op);
788 void force_charshort_cast(int t);
789 static void gen_cast(CType *type);
790 void vstore(void);
791 static Sym *sym_find(int v);
792 static Sym *sym_push(int v, CType *type, int r, int c);
794 /* type handling */
795 static int type_size(CType *type, int *a);
796 static inline CType *pointed_type(CType *type);
797 static int pointed_size(CType *type);
798 static int lvalue_type(int t);
799 static int parse_btype(CType *type, AttributeDef *ad);
800 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
801 static int is_compatible_types(CType *type1, CType *type2);
803 int ieee_finite(double d);
804 void error(const char *fmt, ...);
805 void vpushi(int v);
806 void vrott(int n);
807 void vnrott(int n);
808 void lexpand_nr(void);
809 static void vpush_global_sym(CType *type, int v);
810 void vset(CType *type, int r, int v);
811 void type_to_str(char *buf, int buf_size,
812 CType *type, const char *varstr);
813 char *get_tok_str(int v, CValue *cv);
814 static Sym *get_sym_ref(CType *type, Section *sec,
815 unsigned long offset, unsigned long size);
816 static Sym *external_global_sym(int v, CType *type, int r);
818 /* section generation */
819 static void section_realloc(Section *sec, unsigned long new_size);
820 static void *section_ptr_add(Section *sec, unsigned long size);
821 static void put_extern_sym(Sym *sym, Section *section,
822 unsigned long value, unsigned long size);
823 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
824 static int put_elf_str(Section *s, const char *sym);
825 static int put_elf_sym(Section *s,
826 unsigned long value, unsigned long size,
827 int info, int other, int shndx, const char *name);
828 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
829 int info, int other, int sh_num, const char *name);
830 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
831 int type, int symbol);
832 static void put_stabs(const char *str, int type, int other, int desc,
833 unsigned long value);
834 static void put_stabs_r(const char *str, int type, int other, int desc,
835 unsigned long value, Section *sec, int sym_index);
836 static void put_stabn(int type, int other, int desc, int value);
837 static void put_stabd(int type, int other, int desc);
838 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
840 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
841 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
842 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
844 /* tcccoff.c */
845 int tcc_output_coff(TCCState *s1, FILE *f);
847 /* tccpe.c */
848 void *resolve_sym(TCCState *s1, const char *sym, int type);
849 int pe_load_def_file(struct TCCState *s1, FILE *fp);
850 void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
851 unsigned long pe_add_runtime(struct TCCState *s1);
852 int tcc_output_pe(struct TCCState *s1, const char *filename);
854 /* tccasm.c */
856 #ifdef CONFIG_TCC_ASM
858 typedef struct ExprValue {
859 uint32_t v;
860 Sym *sym;
861 } ExprValue;
863 #define MAX_ASM_OPERANDS 30
865 typedef struct ASMOperand {
866 int id; /* GCC 3 optionnal identifier (0 if number only supported */
867 char *constraint;
868 char asm_str[16]; /* computed asm string for operand */
869 SValue *vt; /* C value of the expression */
870 int ref_index; /* if >= 0, gives reference to a output constraint */
871 int input_index; /* if >= 0, gives reference to an input constraint */
872 int priority; /* priority, used to assign registers */
873 int reg; /* if >= 0, register number used for this operand */
874 int is_llong; /* true if double register value */
875 int is_memory; /* true if memory operand */
876 int is_rw; /* for '+' modifier */
877 } ASMOperand;
879 static void asm_expr(TCCState *s1, ExprValue *pe);
880 static int asm_int_expr(TCCState *s1);
881 static int find_constraint(ASMOperand *operands, int nb_operands,
882 const char *name, const char **pp);
884 static int tcc_assemble(TCCState *s1, int do_preprocess);
886 #endif
888 static void asm_instr(void);
889 static void asm_global_instr(void);
891 /* true if float/double/long double type */
892 static inline int is_float(int t)
894 int bt;
895 bt = t & VT_BTYPE;
896 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
899 #ifdef TCC_TARGET_I386
900 #include "i386-gen.c"
901 #endif
903 #ifdef TCC_TARGET_ARM
904 #include "arm-gen.c"
905 #endif
907 #ifdef TCC_TARGET_C67
908 #include "c67-gen.c"
909 #endif
911 #ifdef CONFIG_TCC_STATIC
913 #define RTLD_LAZY 0x001
914 #define RTLD_NOW 0x002
915 #define RTLD_GLOBAL 0x100
916 #define RTLD_DEFAULT NULL
918 /* dummy function for profiling */
919 void *dlopen(const char *filename, int flag)
921 return NULL;
924 const char *dlerror(void)
926 return "error";
929 typedef struct TCCSyms {
930 char *str;
931 void *ptr;
932 } TCCSyms;
934 #define TCCSYM(a) { #a, &a, },
936 /* add the symbol you want here if no dynamic linking is done */
937 static TCCSyms tcc_syms[] = {
938 #if !defined(CONFIG_TCCBOOT)
939 TCCSYM(printf)
940 TCCSYM(fprintf)
941 TCCSYM(fopen)
942 TCCSYM(fclose)
943 #endif
944 { NULL, NULL },
947 void *resolve_sym(TCCState *s1, const char *symbol, int type)
949 TCCSyms *p;
950 p = tcc_syms;
951 while (p->str != NULL) {
952 if (!strcmp(p->str, symbol))
953 return p->ptr;
954 p++;
956 return NULL;
959 #elif !defined(WIN32)
961 #include <dlfcn.h>
963 void *resolve_sym(TCCState *s1, const char *sym, int type)
965 return dlsym(RTLD_DEFAULT, sym);
968 #endif
970 /********************************************************/
972 /* we use our own 'finite' function to avoid potential problems with
973 non standard math libs */
974 /* XXX: endianness dependent */
975 int ieee_finite(double d)
977 int *p = (int *)&d;
978 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
981 /* copy a string and truncate it. */
982 static char *pstrcpy(char *buf, int buf_size, const char *s)
984 char *q, *q_end;
985 int c;
987 if (buf_size > 0) {
988 q = buf;
989 q_end = buf + buf_size - 1;
990 while (q < q_end) {
991 c = *s++;
992 if (c == '\0')
993 break;
994 *q++ = c;
996 *q = '\0';
998 return buf;
1001 /* strcat and truncate. */
1002 static char *pstrcat(char *buf, int buf_size, const char *s)
1004 int len;
1005 len = strlen(buf);
1006 if (len < buf_size)
1007 pstrcpy(buf + len, buf_size - len, s);
1008 return buf;
1011 static int strstart(const char *str, const char *val, const char **ptr)
1013 const char *p, *q;
1014 p = str;
1015 q = val;
1016 while (*q != '\0') {
1017 if (*p != *q)
1018 return 0;
1019 p++;
1020 q++;
1022 if (ptr)
1023 *ptr = p;
1024 return 1;
1027 /* memory management */
1028 #ifdef MEM_DEBUG
1029 int mem_cur_size;
1030 int mem_max_size;
1031 #endif
1033 static inline void tcc_free(void *ptr)
1035 #ifdef MEM_DEBUG
1036 mem_cur_size -= malloc_usable_size(ptr);
1037 #endif
1038 free(ptr);
1041 static void *tcc_malloc(unsigned long size)
1043 void *ptr;
1044 ptr = malloc(size);
1045 if (!ptr && size)
1046 error("memory full");
1047 #ifdef MEM_DEBUG
1048 mem_cur_size += malloc_usable_size(ptr);
1049 if (mem_cur_size > mem_max_size)
1050 mem_max_size = mem_cur_size;
1051 #endif
1052 return ptr;
1055 static void *tcc_mallocz(unsigned long size)
1057 void *ptr;
1058 ptr = tcc_malloc(size);
1059 memset(ptr, 0, size);
1060 return ptr;
1063 static inline void *tcc_realloc(void *ptr, unsigned long size)
1065 void *ptr1;
1066 #ifdef MEM_DEBUG
1067 mem_cur_size -= malloc_usable_size(ptr);
1068 #endif
1069 ptr1 = realloc(ptr, size);
1070 #ifdef MEM_DEBUG
1071 /* NOTE: count not correct if alloc error, but not critical */
1072 mem_cur_size += malloc_usable_size(ptr1);
1073 if (mem_cur_size > mem_max_size)
1074 mem_max_size = mem_cur_size;
1075 #endif
1076 return ptr1;
1079 static char *tcc_strdup(const char *str)
1081 char *ptr;
1082 ptr = tcc_malloc(strlen(str) + 1);
1083 strcpy(ptr, str);
1084 return ptr;
1087 #define free(p) use_tcc_free(p)
1088 #define malloc(s) use_tcc_malloc(s)
1089 #define realloc(p, s) use_tcc_realloc(p, s)
1091 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1093 int nb, nb_alloc;
1094 void **pp;
1096 nb = *nb_ptr;
1097 pp = *ptab;
1098 /* every power of two we double array size */
1099 if ((nb & (nb - 1)) == 0) {
1100 if (!nb)
1101 nb_alloc = 1;
1102 else
1103 nb_alloc = nb * 2;
1104 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1105 if (!pp)
1106 error("memory full");
1107 *ptab = pp;
1109 pp[nb++] = data;
1110 *nb_ptr = nb;
1113 /* symbol allocator */
1114 static Sym *__sym_malloc(void)
1116 Sym *sym_pool, *sym, *last_sym;
1117 int i;
1119 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1121 last_sym = sym_free_first;
1122 sym = sym_pool;
1123 for(i = 0; i < SYM_POOL_NB; i++) {
1124 sym->next = last_sym;
1125 last_sym = sym;
1126 sym++;
1128 sym_free_first = last_sym;
1129 return last_sym;
1132 static inline Sym *sym_malloc(void)
1134 Sym *sym;
1135 sym = sym_free_first;
1136 if (!sym)
1137 sym = __sym_malloc();
1138 sym_free_first = sym->next;
1139 return sym;
1142 static inline void sym_free(Sym *sym)
1144 sym->next = sym_free_first;
1145 sym_free_first = sym;
1148 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1150 Section *sec;
1152 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1153 strcpy(sec->name, name);
1154 sec->sh_type = sh_type;
1155 sec->sh_flags = sh_flags;
1156 switch(sh_type) {
1157 case SHT_HASH:
1158 case SHT_REL:
1159 case SHT_DYNSYM:
1160 case SHT_SYMTAB:
1161 case SHT_DYNAMIC:
1162 sec->sh_addralign = 4;
1163 break;
1164 case SHT_STRTAB:
1165 sec->sh_addralign = 1;
1166 break;
1167 default:
1168 sec->sh_addralign = 32; /* default conservative alignment */
1169 break;
1172 /* only add section if not private */
1173 if (!(sh_flags & SHF_PRIVATE)) {
1174 sec->sh_num = s1->nb_sections;
1175 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1177 return sec;
1180 static void free_section(Section *s)
1182 tcc_free(s->data);
1183 tcc_free(s);
1186 /* realloc section and set its content to zero */
1187 static void section_realloc(Section *sec, unsigned long new_size)
1189 unsigned long size;
1190 unsigned char *data;
1192 size = sec->data_allocated;
1193 if (size == 0)
1194 size = 1;
1195 while (size < new_size)
1196 size = size * 2;
1197 data = tcc_realloc(sec->data, size);
1198 if (!data)
1199 error("memory full");
1200 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1201 sec->data = data;
1202 sec->data_allocated = size;
1205 /* reserve at least 'size' bytes in section 'sec' from
1206 sec->data_offset. */
1207 static void *section_ptr_add(Section *sec, unsigned long size)
1209 unsigned long offset, offset1;
1211 offset = sec->data_offset;
1212 offset1 = offset + size;
1213 if (offset1 > sec->data_allocated)
1214 section_realloc(sec, offset1);
1215 sec->data_offset = offset1;
1216 return sec->data + offset;
1219 /* return a reference to a section, and create it if it does not
1220 exists */
1221 Section *find_section(TCCState *s1, const char *name)
1223 Section *sec;
1224 int i;
1225 for(i = 1; i < s1->nb_sections; i++) {
1226 sec = s1->sections[i];
1227 if (!strcmp(name, sec->name))
1228 return sec;
1230 /* sections are created as PROGBITS */
1231 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1234 #define SECTION_ABS ((void *)1)
1236 /* update sym->c so that it points to an external symbol in section
1237 'section' with value 'value' */
1238 static void put_extern_sym2(Sym *sym, Section *section,
1239 unsigned long value, unsigned long size,
1240 int can_add_underscore)
1242 int sym_type, sym_bind, sh_num, info;
1243 Elf32_Sym *esym;
1244 const char *name;
1245 char buf1[256];
1247 if (section == NULL)
1248 sh_num = SHN_UNDEF;
1249 else if (section == SECTION_ABS)
1250 sh_num = SHN_ABS;
1251 else
1252 sh_num = section->sh_num;
1253 if (!sym->c) {
1254 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1255 sym_type = STT_FUNC;
1256 else
1257 sym_type = STT_OBJECT;
1258 if (sym->type.t & VT_STATIC)
1259 sym_bind = STB_LOCAL;
1260 else
1261 sym_bind = STB_GLOBAL;
1263 name = get_tok_str(sym->v, NULL);
1264 #ifdef CONFIG_TCC_BCHECK
1265 if (do_bounds_check) {
1266 char buf[32];
1268 /* XXX: avoid doing that for statics ? */
1269 /* if bound checking is activated, we change some function
1270 names by adding the "__bound" prefix */
1271 switch(sym->v) {
1272 #if 0
1273 /* XXX: we rely only on malloc hooks */
1274 case TOK_malloc:
1275 case TOK_free:
1276 case TOK_realloc:
1277 case TOK_memalign:
1278 case TOK_calloc:
1279 #endif
1280 case TOK_memcpy:
1281 case TOK_memmove:
1282 case TOK_memset:
1283 case TOK_strlen:
1284 case TOK_strcpy:
1285 strcpy(buf, "__bound_");
1286 strcat(buf, name);
1287 name = buf;
1288 break;
1291 #endif
1292 if (tcc_state->leading_underscore && can_add_underscore) {
1293 buf1[0] = '_';
1294 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1295 name = buf1;
1297 info = ELF32_ST_INFO(sym_bind, sym_type);
1298 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
1299 } else {
1300 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1301 esym->st_value = value;
1302 esym->st_size = size;
1303 esym->st_shndx = sh_num;
1307 static void put_extern_sym(Sym *sym, Section *section,
1308 unsigned long value, unsigned long size)
1310 put_extern_sym2(sym, section, value, size, 1);
1313 /* add a new relocation entry to symbol 'sym' in section 's' */
1314 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1316 if (!sym->c)
1317 put_extern_sym(sym, NULL, 0, 0);
1318 /* now we can add ELF relocation info */
1319 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1322 static inline int isid(int c)
1324 return (c >= 'a' && c <= 'z') ||
1325 (c >= 'A' && c <= 'Z') ||
1326 c == '_';
1329 static inline int isnum(int c)
1331 return c >= '0' && c <= '9';
1334 static inline int isoct(int c)
1336 return c >= '0' && c <= '7';
1339 static inline int toup(int c)
1341 if (c >= 'a' && c <= 'z')
1342 return c - 'a' + 'A';
1343 else
1344 return c;
1347 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1349 int len;
1350 len = strlen(buf);
1351 vsnprintf(buf + len, buf_size - len, fmt, ap);
1354 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1356 va_list ap;
1357 va_start(ap, fmt);
1358 strcat_vprintf(buf, buf_size, fmt, ap);
1359 va_end(ap);
1362 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1364 char buf[2048];
1365 BufferedFile **f;
1367 buf[0] = '\0';
1368 if (file) {
1369 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1370 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1371 (*f)->filename, (*f)->line_num);
1372 if (file->line_num > 0) {
1373 strcat_printf(buf, sizeof(buf),
1374 "%s:%d: ", file->filename, file->line_num);
1375 } else {
1376 strcat_printf(buf, sizeof(buf),
1377 "%s: ", file->filename);
1379 } else {
1380 strcat_printf(buf, sizeof(buf),
1381 "tcc: ");
1383 if (is_warning)
1384 strcat_printf(buf, sizeof(buf), "warning: ");
1385 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1387 if (!s1->error_func) {
1388 /* default case: stderr */
1389 fprintf(stderr, "%s\n", buf);
1390 } else {
1391 s1->error_func(s1->error_opaque, buf);
1393 if (!is_warning || s1->warn_error)
1394 s1->nb_errors++;
1397 #ifdef LIBTCC
1398 void tcc_set_error_func(TCCState *s, void *error_opaque,
1399 void (*error_func)(void *opaque, const char *msg))
1401 s->error_opaque = error_opaque;
1402 s->error_func = error_func;
1404 #endif
1406 /* error without aborting current compilation */
1407 void error_noabort(const char *fmt, ...)
1409 TCCState *s1 = tcc_state;
1410 va_list ap;
1412 va_start(ap, fmt);
1413 error1(s1, 0, fmt, ap);
1414 va_end(ap);
1417 void error(const char *fmt, ...)
1419 TCCState *s1 = tcc_state;
1420 va_list ap;
1422 va_start(ap, fmt);
1423 error1(s1, 0, fmt, ap);
1424 va_end(ap);
1425 /* better than nothing: in some cases, we accept to handle errors */
1426 if (s1->error_set_jmp_enabled) {
1427 longjmp(s1->error_jmp_buf, 1);
1428 } else {
1429 /* XXX: eliminate this someday */
1430 exit(1);
1434 void expect(const char *msg)
1436 error("%s expected", msg);
1439 void warning(const char *fmt, ...)
1441 TCCState *s1 = tcc_state;
1442 va_list ap;
1444 if (s1->warn_none)
1445 return;
1447 va_start(ap, fmt);
1448 error1(s1, 1, fmt, ap);
1449 va_end(ap);
1452 void skip(int c)
1454 if (tok != c)
1455 error("'%c' expected", c);
1456 next();
1459 static void test_lvalue(void)
1461 if (!(vtop->r & VT_LVAL))
1462 expect("lvalue");
1465 /* allocate a new token */
1466 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1468 TokenSym *ts, **ptable;
1469 int i;
1471 if (tok_ident >= SYM_FIRST_ANOM)
1472 error("memory full");
1474 /* expand token table if needed */
1475 i = tok_ident - TOK_IDENT;
1476 if ((i % TOK_ALLOC_INCR) == 0) {
1477 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1478 if (!ptable)
1479 error("memory full");
1480 table_ident = ptable;
1483 ts = tcc_malloc(sizeof(TokenSym) + len);
1484 table_ident[i] = ts;
1485 ts->tok = tok_ident++;
1486 ts->sym_define = NULL;
1487 ts->sym_label = NULL;
1488 ts->sym_struct = NULL;
1489 ts->sym_identifier = NULL;
1490 ts->len = len;
1491 ts->hash_next = NULL;
1492 memcpy(ts->str, str, len);
1493 ts->str[len] = '\0';
1494 *pts = ts;
1495 return ts;
1498 #define TOK_HASH_INIT 1
1499 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1501 /* find a token and add it if not found */
1502 static TokenSym *tok_alloc(const char *str, int len)
1504 TokenSym *ts, **pts;
1505 int i;
1506 unsigned int h;
1508 h = TOK_HASH_INIT;
1509 for(i=0;i<len;i++)
1510 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1511 h &= (TOK_HASH_SIZE - 1);
1513 pts = &hash_ident[h];
1514 for(;;) {
1515 ts = *pts;
1516 if (!ts)
1517 break;
1518 if (ts->len == len && !memcmp(ts->str, str, len))
1519 return ts;
1520 pts = &(ts->hash_next);
1522 return tok_alloc_new(pts, str, len);
1525 /* CString handling */
1527 static void cstr_realloc(CString *cstr, int new_size)
1529 int size;
1530 void *data;
1532 size = cstr->size_allocated;
1533 if (size == 0)
1534 size = 8; /* no need to allocate a too small first string */
1535 while (size < new_size)
1536 size = size * 2;
1537 data = tcc_realloc(cstr->data_allocated, size);
1538 if (!data)
1539 error("memory full");
1540 cstr->data_allocated = data;
1541 cstr->size_allocated = size;
1542 cstr->data = data;
1545 /* add a byte */
1546 static inline void cstr_ccat(CString *cstr, int ch)
1548 int size;
1549 size = cstr->size + 1;
1550 if (size > cstr->size_allocated)
1551 cstr_realloc(cstr, size);
1552 ((unsigned char *)cstr->data)[size - 1] = ch;
1553 cstr->size = size;
1556 static void cstr_cat(CString *cstr, const char *str)
1558 int c;
1559 for(;;) {
1560 c = *str;
1561 if (c == '\0')
1562 break;
1563 cstr_ccat(cstr, c);
1564 str++;
1568 /* add a wide char */
1569 static void cstr_wccat(CString *cstr, int ch)
1571 int size;
1572 size = cstr->size + sizeof(nwchar_t);
1573 if (size > cstr->size_allocated)
1574 cstr_realloc(cstr, size);
1575 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1576 cstr->size = size;
1579 static void cstr_new(CString *cstr)
1581 memset(cstr, 0, sizeof(CString));
1584 /* free string and reset it to NULL */
1585 static void cstr_free(CString *cstr)
1587 tcc_free(cstr->data_allocated);
1588 cstr_new(cstr);
1591 #define cstr_reset(cstr) cstr_free(cstr)
1593 /* XXX: unicode ? */
1594 static void add_char(CString *cstr, int c)
1596 if (c == '\'' || c == '\"' || c == '\\') {
1597 /* XXX: could be more precise if char or string */
1598 cstr_ccat(cstr, '\\');
1600 if (c >= 32 && c <= 126) {
1601 cstr_ccat(cstr, c);
1602 } else {
1603 cstr_ccat(cstr, '\\');
1604 if (c == '\n') {
1605 cstr_ccat(cstr, 'n');
1606 } else {
1607 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1608 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1609 cstr_ccat(cstr, '0' + (c & 7));
1614 /* XXX: buffer overflow */
1615 /* XXX: float tokens */
1616 char *get_tok_str(int v, CValue *cv)
1618 static char buf[STRING_MAX_SIZE + 1];
1619 static CString cstr_buf;
1620 CString *cstr;
1621 unsigned char *q;
1622 char *p;
1623 int i, len;
1625 /* NOTE: to go faster, we give a fixed buffer for small strings */
1626 cstr_reset(&cstr_buf);
1627 cstr_buf.data = buf;
1628 cstr_buf.size_allocated = sizeof(buf);
1629 p = buf;
1631 switch(v) {
1632 case TOK_CINT:
1633 case TOK_CUINT:
1634 /* XXX: not quite exact, but only useful for testing */
1635 sprintf(p, "%u", cv->ui);
1636 break;
1637 case TOK_CLLONG:
1638 case TOK_CULLONG:
1639 /* XXX: not quite exact, but only useful for testing */
1640 sprintf(p, "%Lu", cv->ull);
1641 break;
1642 case TOK_CCHAR:
1643 case TOK_LCHAR:
1644 cstr_ccat(&cstr_buf, '\'');
1645 add_char(&cstr_buf, cv->i);
1646 cstr_ccat(&cstr_buf, '\'');
1647 cstr_ccat(&cstr_buf, '\0');
1648 break;
1649 case TOK_PPNUM:
1650 cstr = cv->cstr;
1651 len = cstr->size - 1;
1652 for(i=0;i<len;i++)
1653 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1654 cstr_ccat(&cstr_buf, '\0');
1655 break;
1656 case TOK_STR:
1657 case TOK_LSTR:
1658 cstr = cv->cstr;
1659 cstr_ccat(&cstr_buf, '\"');
1660 if (v == TOK_STR) {
1661 len = cstr->size - 1;
1662 for(i=0;i<len;i++)
1663 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1664 } else {
1665 len = (cstr->size / sizeof(nwchar_t)) - 1;
1666 for(i=0;i<len;i++)
1667 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1669 cstr_ccat(&cstr_buf, '\"');
1670 cstr_ccat(&cstr_buf, '\0');
1671 break;
1672 case TOK_LT:
1673 v = '<';
1674 goto addv;
1675 case TOK_GT:
1676 v = '>';
1677 goto addv;
1678 case TOK_A_SHL:
1679 return strcpy(p, "<<=");
1680 case TOK_A_SAR:
1681 return strcpy(p, ">>=");
1682 default:
1683 if (v < TOK_IDENT) {
1684 /* search in two bytes table */
1685 q = tok_two_chars;
1686 while (*q) {
1687 if (q[2] == v) {
1688 *p++ = q[0];
1689 *p++ = q[1];
1690 *p = '\0';
1691 return buf;
1693 q += 3;
1695 addv:
1696 *p++ = v;
1697 *p = '\0';
1698 } else if (v < tok_ident) {
1699 return table_ident[v - TOK_IDENT]->str;
1700 } else if (v >= SYM_FIRST_ANOM) {
1701 /* special name for anonymous symbol */
1702 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1703 } else {
1704 /* should never happen */
1705 return NULL;
1707 break;
1709 return cstr_buf.data;
1712 /* push, without hashing */
1713 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1715 Sym *s;
1716 s = sym_malloc();
1717 s->v = v;
1718 s->type.t = t;
1719 s->c = c;
1720 s->next = NULL;
1721 /* add in stack */
1722 s->prev = *ps;
1723 *ps = s;
1724 return s;
1727 /* find a symbol and return its associated structure. 's' is the top
1728 of the symbol stack */
1729 static Sym *sym_find2(Sym *s, int v)
1731 while (s) {
1732 if (s->v == v)
1733 return s;
1734 s = s->prev;
1736 return NULL;
1739 /* structure lookup */
1740 static inline Sym *struct_find(int v)
1742 v -= TOK_IDENT;
1743 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1744 return NULL;
1745 return table_ident[v]->sym_struct;
1748 /* find an identifier */
1749 static inline Sym *sym_find(int v)
1751 v -= TOK_IDENT;
1752 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1753 return NULL;
1754 return table_ident[v]->sym_identifier;
1757 /* push a given symbol on the symbol stack */
1758 static Sym *sym_push(int v, CType *type, int r, int c)
1760 Sym *s, **ps;
1761 TokenSym *ts;
1763 if (local_stack)
1764 ps = &local_stack;
1765 else
1766 ps = &global_stack;
1767 s = sym_push2(ps, v, type->t, c);
1768 s->type.ref = type->ref;
1769 s->r = r;
1770 /* don't record fields or anonymous symbols */
1771 /* XXX: simplify */
1772 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1773 /* record symbol in token array */
1774 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1775 if (v & SYM_STRUCT)
1776 ps = &ts->sym_struct;
1777 else
1778 ps = &ts->sym_identifier;
1779 s->prev_tok = *ps;
1780 *ps = s;
1782 return s;
1785 /* push a global identifier */
1786 static Sym *global_identifier_push(int v, int t, int c)
1788 Sym *s, **ps;
1789 s = sym_push2(&global_stack, v, t, c);
1790 /* don't record anonymous symbol */
1791 if (v < SYM_FIRST_ANOM) {
1792 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1793 /* modify the top most local identifier, so that
1794 sym_identifier will point to 's' when popped */
1795 while (*ps != NULL)
1796 ps = &(*ps)->prev_tok;
1797 s->prev_tok = NULL;
1798 *ps = s;
1800 return s;
1803 /* pop symbols until top reaches 'b' */
1804 static void sym_pop(Sym **ptop, Sym *b)
1806 Sym *s, *ss, **ps;
1807 TokenSym *ts;
1808 int v;
1810 s = *ptop;
1811 while(s != b) {
1812 ss = s->prev;
1813 v = s->v;
1814 /* remove symbol in token array */
1815 /* XXX: simplify */
1816 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1817 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1818 if (v & SYM_STRUCT)
1819 ps = &ts->sym_struct;
1820 else
1821 ps = &ts->sym_identifier;
1822 *ps = s->prev_tok;
1824 sym_free(s);
1825 s = ss;
1827 *ptop = b;
1830 /* I/O layer */
1832 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1834 int fd;
1835 BufferedFile *bf;
1836 int i, len;
1838 fd = open(filename, O_RDONLY | O_BINARY);
1839 if (fd < 0)
1840 return NULL;
1841 bf = tcc_malloc(sizeof(BufferedFile));
1842 if (!bf) {
1843 close(fd);
1844 return NULL;
1846 bf->fd = fd;
1847 bf->buf_ptr = bf->buffer;
1848 bf->buf_end = bf->buffer;
1849 bf->buffer[0] = CH_EOB; /* put eob symbol */
1850 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1851 len = strlen(bf->filename);
1852 for (i = 0; i < len; i++)
1853 if (bf->filename[i] == '\\')
1854 bf->filename[i] = '/';
1855 bf->line_num = 1;
1856 bf->ifndef_macro = 0;
1857 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1858 // printf("opening '%s'\n", filename);
1859 return bf;
1862 void tcc_close(BufferedFile *bf)
1864 total_lines += bf->line_num;
1865 close(bf->fd);
1866 tcc_free(bf);
1869 /* fill input buffer and peek next char */
1870 static int tcc_peekc_slow(BufferedFile *bf)
1872 int len;
1873 /* only tries to read if really end of buffer */
1874 if (bf->buf_ptr >= bf->buf_end) {
1875 if (bf->fd != -1) {
1876 #if defined(PARSE_DEBUG)
1877 len = 8;
1878 #else
1879 len = IO_BUF_SIZE;
1880 #endif
1881 len = read(bf->fd, bf->buffer, len);
1882 if (len < 0)
1883 len = 0;
1884 } else {
1885 len = 0;
1887 total_bytes += len;
1888 bf->buf_ptr = bf->buffer;
1889 bf->buf_end = bf->buffer + len;
1890 *bf->buf_end = CH_EOB;
1892 if (bf->buf_ptr < bf->buf_end) {
1893 return bf->buf_ptr[0];
1894 } else {
1895 bf->buf_ptr = bf->buf_end;
1896 return CH_EOF;
1900 /* return the current character, handling end of block if necessary
1901 (but not stray) */
1902 static int handle_eob(void)
1904 return tcc_peekc_slow(file);
1907 /* read next char from current input file and handle end of input buffer */
1908 static inline void inp(void)
1910 ch = *(++(file->buf_ptr));
1911 /* end of buffer/file handling */
1912 if (ch == CH_EOB)
1913 ch = handle_eob();
1916 /* handle '\[\r]\n' */
1917 static void handle_stray(void)
1919 while (ch == '\\') {
1920 inp();
1921 if (ch == '\n') {
1922 file->line_num++;
1923 inp();
1924 } else if (ch == '\r') {
1925 inp();
1926 if (ch != '\n')
1927 goto fail;
1928 file->line_num++;
1929 inp();
1930 } else {
1931 fail:
1932 error("stray '\\' in program");
1937 /* skip the stray and handle the \\n case. Output an error if
1938 incorrect char after the stray */
1939 static int handle_stray1(uint8_t *p)
1941 int c;
1943 if (p >= file->buf_end) {
1944 file->buf_ptr = p;
1945 c = handle_eob();
1946 p = file->buf_ptr;
1947 if (c == '\\')
1948 goto parse_stray;
1949 } else {
1950 parse_stray:
1951 file->buf_ptr = p;
1952 ch = *p;
1953 handle_stray();
1954 p = file->buf_ptr;
1955 c = *p;
1957 return c;
1960 /* handle just the EOB case, but not stray */
1961 #define PEEKC_EOB(c, p)\
1963 p++;\
1964 c = *p;\
1965 if (c == '\\') {\
1966 file->buf_ptr = p;\
1967 c = handle_eob();\
1968 p = file->buf_ptr;\
1972 /* handle the complicated stray case */
1973 #define PEEKC(c, p)\
1975 p++;\
1976 c = *p;\
1977 if (c == '\\') {\
1978 c = handle_stray1(p);\
1979 p = file->buf_ptr;\
1983 /* input with '\[\r]\n' handling. Note that this function cannot
1984 handle other characters after '\', so you cannot call it inside
1985 strings or comments */
1986 static void minp(void)
1988 inp();
1989 if (ch == '\\')
1990 handle_stray();
1994 /* single line C++ comments */
1995 static uint8_t *parse_line_comment(uint8_t *p)
1997 int c;
1999 p++;
2000 for(;;) {
2001 c = *p;
2002 redo:
2003 if (c == '\n' || c == CH_EOF) {
2004 break;
2005 } else if (c == '\\') {
2006 file->buf_ptr = p;
2007 c = handle_eob();
2008 p = file->buf_ptr;
2009 if (c == '\\') {
2010 PEEKC_EOB(c, p);
2011 if (c == '\n') {
2012 file->line_num++;
2013 PEEKC_EOB(c, p);
2014 } else if (c == '\r') {
2015 PEEKC_EOB(c, p);
2016 if (c == '\n') {
2017 file->line_num++;
2018 PEEKC_EOB(c, p);
2021 } else {
2022 goto redo;
2024 } else {
2025 p++;
2028 return p;
2031 /* C comments */
2032 static uint8_t *parse_comment(uint8_t *p)
2034 int c;
2036 p++;
2037 for(;;) {
2038 /* fast skip loop */
2039 for(;;) {
2040 c = *p;
2041 if (c == '\n' || c == '*' || c == '\\')
2042 break;
2043 p++;
2044 c = *p;
2045 if (c == '\n' || c == '*' || c == '\\')
2046 break;
2047 p++;
2049 /* now we can handle all the cases */
2050 if (c == '\n') {
2051 file->line_num++;
2052 p++;
2053 } else if (c == '*') {
2054 p++;
2055 for(;;) {
2056 c = *p;
2057 if (c == '*') {
2058 p++;
2059 } else if (c == '/') {
2060 goto end_of_comment;
2061 } else if (c == '\\') {
2062 file->buf_ptr = p;
2063 c = handle_eob();
2064 p = file->buf_ptr;
2065 if (c == '\\') {
2066 /* skip '\[\r]\n', otherwise just skip the stray */
2067 while (c == '\\') {
2068 PEEKC_EOB(c, p);
2069 if (c == '\n') {
2070 file->line_num++;
2071 PEEKC_EOB(c, p);
2072 } else if (c == '\r') {
2073 PEEKC_EOB(c, p);
2074 if (c == '\n') {
2075 file->line_num++;
2076 PEEKC_EOB(c, p);
2078 } else {
2079 goto after_star;
2083 } else {
2084 break;
2087 after_star: ;
2088 } else {
2089 /* stray, eob or eof */
2090 file->buf_ptr = p;
2091 c = handle_eob();
2092 p = file->buf_ptr;
2093 if (c == CH_EOF) {
2094 error("unexpected end of file in comment");
2095 } else if (c == '\\') {
2096 p++;
2100 end_of_comment:
2101 p++;
2102 return p;
2105 #define cinp minp
2107 /* space exlcuding newline */
2108 static inline int is_space(int ch)
2110 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2113 static inline void skip_spaces(void)
2115 while (is_space(ch))
2116 cinp();
2119 /* parse a string without interpreting escapes */
2120 static uint8_t *parse_pp_string(uint8_t *p,
2121 int sep, CString *str)
2123 int c;
2124 p++;
2125 for(;;) {
2126 c = *p;
2127 if (c == sep) {
2128 break;
2129 } else if (c == '\\') {
2130 file->buf_ptr = p;
2131 c = handle_eob();
2132 p = file->buf_ptr;
2133 if (c == CH_EOF) {
2134 unterminated_string:
2135 /* XXX: indicate line number of start of string */
2136 error("missing terminating %c character", sep);
2137 } else if (c == '\\') {
2138 /* escape : just skip \[\r]\n */
2139 PEEKC_EOB(c, p);
2140 if (c == '\n') {
2141 file->line_num++;
2142 p++;
2143 } else if (c == '\r') {
2144 PEEKC_EOB(c, p);
2145 if (c != '\n')
2146 expect("'\n' after '\r'");
2147 file->line_num++;
2148 p++;
2149 } else if (c == CH_EOF) {
2150 goto unterminated_string;
2151 } else {
2152 if (str) {
2153 cstr_ccat(str, '\\');
2154 cstr_ccat(str, c);
2156 p++;
2159 } else if (c == '\n') {
2160 file->line_num++;
2161 goto add_char;
2162 } else if (c == '\r') {
2163 PEEKC_EOB(c, p);
2164 if (c != '\n') {
2165 if (str)
2166 cstr_ccat(str, '\r');
2167 } else {
2168 file->line_num++;
2169 goto add_char;
2171 } else {
2172 add_char:
2173 if (str)
2174 cstr_ccat(str, c);
2175 p++;
2178 p++;
2179 return p;
2182 /* skip block of text until #else, #elif or #endif. skip also pairs of
2183 #if/#endif */
2184 void preprocess_skip(void)
2186 int a, start_of_line, c;
2187 uint8_t *p;
2189 p = file->buf_ptr;
2190 start_of_line = 1;
2191 a = 0;
2192 for(;;) {
2193 redo_no_start:
2194 c = *p;
2195 switch(c) {
2196 case ' ':
2197 case '\t':
2198 case '\f':
2199 case '\v':
2200 case '\r':
2201 p++;
2202 goto redo_no_start;
2203 case '\n':
2204 start_of_line = 1;
2205 file->line_num++;
2206 p++;
2207 goto redo_no_start;
2208 case '\\':
2209 file->buf_ptr = p;
2210 c = handle_eob();
2211 if (c == CH_EOF) {
2212 expect("#endif");
2213 } else if (c == '\\') {
2214 /* XXX: incorrect: should not give an error */
2215 ch = file->buf_ptr[0];
2216 handle_stray();
2218 p = file->buf_ptr;
2219 goto redo_no_start;
2220 /* skip strings */
2221 case '\"':
2222 case '\'':
2223 p = parse_pp_string(p, c, NULL);
2224 break;
2225 /* skip comments */
2226 case '/':
2227 file->buf_ptr = p;
2228 ch = *p;
2229 minp();
2230 p = file->buf_ptr;
2231 if (ch == '*') {
2232 p = parse_comment(p);
2233 } else if (ch == '/') {
2234 p = parse_line_comment(p);
2236 break;
2238 case '#':
2239 p++;
2240 if (start_of_line) {
2241 file->buf_ptr = p;
2242 next_nomacro();
2243 p = file->buf_ptr;
2244 if (a == 0 &&
2245 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2246 goto the_end;
2247 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2248 a++;
2249 else if (tok == TOK_ENDIF)
2250 a--;
2252 break;
2253 default:
2254 p++;
2255 break;
2257 start_of_line = 0;
2259 the_end: ;
2260 file->buf_ptr = p;
2263 /* ParseState handling */
2265 /* XXX: currently, no include file info is stored. Thus, we cannot display
2266 accurate messages if the function or data definition spans multiple
2267 files */
2269 /* save current parse state in 's' */
2270 void save_parse_state(ParseState *s)
2272 s->line_num = file->line_num;
2273 s->macro_ptr = macro_ptr;
2274 s->tok = tok;
2275 s->tokc = tokc;
2278 /* restore parse state from 's' */
2279 void restore_parse_state(ParseState *s)
2281 file->line_num = s->line_num;
2282 macro_ptr = s->macro_ptr;
2283 tok = s->tok;
2284 tokc = s->tokc;
2287 /* return the number of additional 'ints' necessary to store the
2288 token */
2289 static inline int tok_ext_size(int t)
2291 switch(t) {
2292 /* 4 bytes */
2293 case TOK_CINT:
2294 case TOK_CUINT:
2295 case TOK_CCHAR:
2296 case TOK_LCHAR:
2297 case TOK_CFLOAT:
2298 case TOK_LINENUM:
2299 return 1;
2300 case TOK_STR:
2301 case TOK_LSTR:
2302 case TOK_PPNUM:
2303 error("unsupported token");
2304 return 1;
2305 case TOK_CDOUBLE:
2306 case TOK_CLLONG:
2307 case TOK_CULLONG:
2308 return 2;
2309 case TOK_CLDOUBLE:
2310 return LDOUBLE_SIZE / 4;
2311 default:
2312 return 0;
2316 /* token string handling */
2318 static inline void tok_str_new(TokenString *s)
2320 s->str = NULL;
2321 s->len = 0;
2322 s->allocated_len = 0;
2323 s->last_line_num = -1;
2326 static void tok_str_free(int *str)
2328 tcc_free(str);
2331 static int *tok_str_realloc(TokenString *s)
2333 int *str, len;
2335 if (s->allocated_len == 0) {
2336 len = 8;
2337 } else {
2338 len = s->allocated_len * 2;
2340 str = tcc_realloc(s->str, len * sizeof(int));
2341 if (!str)
2342 error("memory full");
2343 s->allocated_len = len;
2344 s->str = str;
2345 return str;
2348 static void tok_str_add(TokenString *s, int t)
2350 int len, *str;
2352 len = s->len;
2353 str = s->str;
2354 if (len >= s->allocated_len)
2355 str = tok_str_realloc(s);
2356 str[len++] = t;
2357 s->len = len;
2360 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2362 int len, *str;
2364 len = s->len;
2365 str = s->str;
2367 /* allocate space for worst case */
2368 if (len + TOK_MAX_SIZE > s->allocated_len)
2369 str = tok_str_realloc(s);
2370 str[len++] = t;
2371 switch(t) {
2372 case TOK_CINT:
2373 case TOK_CUINT:
2374 case TOK_CCHAR:
2375 case TOK_LCHAR:
2376 case TOK_CFLOAT:
2377 case TOK_LINENUM:
2378 str[len++] = cv->tab[0];
2379 break;
2380 case TOK_PPNUM:
2381 case TOK_STR:
2382 case TOK_LSTR:
2384 int nb_words;
2385 CString *cstr;
2387 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2388 while ((len + nb_words) > s->allocated_len)
2389 str = tok_str_realloc(s);
2390 cstr = (CString *)(str + len);
2391 cstr->data = NULL;
2392 cstr->size = cv->cstr->size;
2393 cstr->data_allocated = NULL;
2394 cstr->size_allocated = cstr->size;
2395 memcpy((char *)cstr + sizeof(CString),
2396 cv->cstr->data, cstr->size);
2397 len += nb_words;
2399 break;
2400 case TOK_CDOUBLE:
2401 case TOK_CLLONG:
2402 case TOK_CULLONG:
2403 #if LDOUBLE_SIZE == 8
2404 case TOK_CLDOUBLE:
2405 #endif
2406 str[len++] = cv->tab[0];
2407 str[len++] = cv->tab[1];
2408 break;
2409 #if LDOUBLE_SIZE == 12
2410 case TOK_CLDOUBLE:
2411 str[len++] = cv->tab[0];
2412 str[len++] = cv->tab[1];
2413 str[len++] = cv->tab[2];
2414 #elif LDOUBLE_SIZE != 8
2415 #error add long double size support
2416 #endif
2417 break;
2418 default:
2419 break;
2421 s->len = len;
2424 /* add the current parse token in token string 's' */
2425 static void tok_str_add_tok(TokenString *s)
2427 CValue cval;
2429 /* save line number info */
2430 if (file->line_num != s->last_line_num) {
2431 s->last_line_num = file->line_num;
2432 cval.i = s->last_line_num;
2433 tok_str_add2(s, TOK_LINENUM, &cval);
2435 tok_str_add2(s, tok, &tokc);
2438 #if LDOUBLE_SIZE == 12
2439 #define LDOUBLE_GET(p, cv) \
2440 cv.tab[0] = p[0]; \
2441 cv.tab[1] = p[1]; \
2442 cv.tab[2] = p[2];
2443 #elif LDOUBLE_SIZE == 8
2444 #define LDOUBLE_GET(p, cv) \
2445 cv.tab[0] = p[0]; \
2446 cv.tab[1] = p[1];
2447 #else
2448 #error add long double size support
2449 #endif
2452 /* get a token from an integer array and increment pointer
2453 accordingly. we code it as a macro to avoid pointer aliasing. */
2454 #define TOK_GET(t, p, cv) \
2456 t = *p++; \
2457 switch(t) { \
2458 case TOK_CINT: \
2459 case TOK_CUINT: \
2460 case TOK_CCHAR: \
2461 case TOK_LCHAR: \
2462 case TOK_CFLOAT: \
2463 case TOK_LINENUM: \
2464 cv.tab[0] = *p++; \
2465 break; \
2466 case TOK_STR: \
2467 case TOK_LSTR: \
2468 case TOK_PPNUM: \
2469 cv.cstr = (CString *)p; \
2470 cv.cstr->data = (char *)p + sizeof(CString);\
2471 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2472 break; \
2473 case TOK_CDOUBLE: \
2474 case TOK_CLLONG: \
2475 case TOK_CULLONG: \
2476 cv.tab[0] = p[0]; \
2477 cv.tab[1] = p[1]; \
2478 p += 2; \
2479 break; \
2480 case TOK_CLDOUBLE: \
2481 LDOUBLE_GET(p, cv); \
2482 p += LDOUBLE_SIZE / 4; \
2483 break; \
2484 default: \
2485 break; \
2489 /* defines handling */
2490 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2492 Sym *s;
2494 s = sym_push2(&define_stack, v, macro_type, (int)str);
2495 s->next = first_arg;
2496 table_ident[v - TOK_IDENT]->sym_define = s;
2499 /* undefined a define symbol. Its name is just set to zero */
2500 static void define_undef(Sym *s)
2502 int v;
2503 v = s->v;
2504 if (v >= TOK_IDENT && v < tok_ident)
2505 table_ident[v - TOK_IDENT]->sym_define = NULL;
2506 s->v = 0;
2509 static inline Sym *define_find(int v)
2511 v -= TOK_IDENT;
2512 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2513 return NULL;
2514 return table_ident[v]->sym_define;
2517 /* free define stack until top reaches 'b' */
2518 static void free_defines(Sym *b)
2520 Sym *top, *top1;
2521 int v;
2523 top = define_stack;
2524 while (top != b) {
2525 top1 = top->prev;
2526 /* do not free args or predefined defines */
2527 if (top->c)
2528 tok_str_free((int *)top->c);
2529 v = top->v;
2530 if (v >= TOK_IDENT && v < tok_ident)
2531 table_ident[v - TOK_IDENT]->sym_define = NULL;
2532 sym_free(top);
2533 top = top1;
2535 define_stack = b;
2538 /* label lookup */
2539 static Sym *label_find(int v)
2541 v -= TOK_IDENT;
2542 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2543 return NULL;
2544 return table_ident[v]->sym_label;
2547 static Sym *label_push(Sym **ptop, int v, int flags)
2549 Sym *s, **ps;
2550 s = sym_push2(ptop, v, 0, 0);
2551 s->r = flags;
2552 ps = &table_ident[v - TOK_IDENT]->sym_label;
2553 if (ptop == &global_label_stack) {
2554 /* modify the top most local identifier, so that
2555 sym_identifier will point to 's' when popped */
2556 while (*ps != NULL)
2557 ps = &(*ps)->prev_tok;
2559 s->prev_tok = *ps;
2560 *ps = s;
2561 return s;
2564 /* pop labels until element last is reached. Look if any labels are
2565 undefined. Define symbols if '&&label' was used. */
2566 static void label_pop(Sym **ptop, Sym *slast)
2568 Sym *s, *s1;
2569 for(s = *ptop; s != slast; s = s1) {
2570 s1 = s->prev;
2571 if (s->r == LABEL_DECLARED) {
2572 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2573 } else if (s->r == LABEL_FORWARD) {
2574 error("label '%s' used but not defined",
2575 get_tok_str(s->v, NULL));
2576 } else {
2577 if (s->c) {
2578 /* define corresponding symbol. A size of
2579 1 is put. */
2580 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2583 /* remove label */
2584 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2585 sym_free(s);
2587 *ptop = slast;
2590 /* eval an expression for #if/#elif */
2591 static int expr_preprocess(void)
2593 int c, t;
2594 TokenString str;
2596 tok_str_new(&str);
2597 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2598 next(); /* do macro subst */
2599 if (tok == TOK_DEFINED) {
2600 next_nomacro();
2601 t = tok;
2602 if (t == '(')
2603 next_nomacro();
2604 c = define_find(tok) != 0;
2605 if (t == '(')
2606 next_nomacro();
2607 tok = TOK_CINT;
2608 tokc.i = c;
2609 } else if (tok >= TOK_IDENT) {
2610 /* if undefined macro */
2611 tok = TOK_CINT;
2612 tokc.i = 0;
2614 tok_str_add_tok(&str);
2616 tok_str_add(&str, -1); /* simulate end of file */
2617 tok_str_add(&str, 0);
2618 /* now evaluate C constant expression */
2619 macro_ptr = str.str;
2620 next();
2621 c = expr_const();
2622 macro_ptr = NULL;
2623 tok_str_free(str.str);
2624 return c != 0;
2627 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2628 static void tok_print(int *str)
2630 int t;
2631 CValue cval;
2633 while (1) {
2634 TOK_GET(t, str, cval);
2635 if (!t)
2636 break;
2637 printf(" %s", get_tok_str(t, &cval));
2639 printf("\n");
2641 #endif
2643 /* parse after #define */
2644 static void parse_define(void)
2646 Sym *s, *first, **ps;
2647 int v, t, varg, is_vaargs, c;
2648 TokenString str;
2650 v = tok;
2651 if (v < TOK_IDENT)
2652 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2653 /* XXX: should check if same macro (ANSI) */
2654 first = NULL;
2655 t = MACRO_OBJ;
2656 /* '(' must be just after macro definition for MACRO_FUNC */
2657 c = file->buf_ptr[0];
2658 if (c == '\\')
2659 c = handle_stray1(file->buf_ptr);
2660 if (c == '(') {
2661 next_nomacro();
2662 next_nomacro();
2663 ps = &first;
2664 while (tok != ')') {
2665 varg = tok;
2666 next_nomacro();
2667 is_vaargs = 0;
2668 if (varg == TOK_DOTS) {
2669 varg = TOK___VA_ARGS__;
2670 is_vaargs = 1;
2671 } else if (tok == TOK_DOTS && gnu_ext) {
2672 is_vaargs = 1;
2673 next_nomacro();
2675 if (varg < TOK_IDENT)
2676 error("badly punctuated parameter list");
2677 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2678 *ps = s;
2679 ps = &s->next;
2680 if (tok != ',')
2681 break;
2682 next_nomacro();
2684 t = MACRO_FUNC;
2686 tok_str_new(&str);
2687 next_nomacro();
2688 /* EOF testing necessary for '-D' handling */
2689 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2690 tok_str_add2(&str, tok, &tokc);
2691 next_nomacro();
2693 tok_str_add(&str, 0);
2694 #ifdef PP_DEBUG
2695 printf("define %s %d: ", get_tok_str(v, NULL), t);
2696 tok_print(str.str);
2697 #endif
2698 define_push(v, t, str.str, first);
2701 static inline int hash_cached_include(int type, const char *filename)
2703 const unsigned char *s;
2704 unsigned int h;
2706 h = TOK_HASH_INIT;
2707 h = TOK_HASH_FUNC(h, type);
2708 s = filename;
2709 while (*s) {
2710 h = TOK_HASH_FUNC(h, *s);
2711 s++;
2713 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2714 return h;
2717 /* XXX: use a token or a hash table to accelerate matching ? */
2718 static CachedInclude *search_cached_include(TCCState *s1,
2719 int type, const char *filename)
2721 CachedInclude *e;
2722 int i, h;
2723 h = hash_cached_include(type, filename);
2724 i = s1->cached_includes_hash[h];
2725 for(;;) {
2726 if (i == 0)
2727 break;
2728 e = s1->cached_includes[i - 1];
2729 if (e->type == type && !strcmp(e->filename, filename))
2730 return e;
2731 i = e->hash_next;
2733 return NULL;
2736 static inline void add_cached_include(TCCState *s1, int type,
2737 const char *filename, int ifndef_macro)
2739 CachedInclude *e;
2740 int h;
2742 if (search_cached_include(s1, type, filename))
2743 return;
2744 #ifdef INC_DEBUG
2745 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2746 #endif
2747 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2748 if (!e)
2749 return;
2750 e->type = type;
2751 strcpy(e->filename, filename);
2752 e->ifndef_macro = ifndef_macro;
2753 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2754 /* add in hash table */
2755 h = hash_cached_include(type, filename);
2756 e->hash_next = s1->cached_includes_hash[h];
2757 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2760 static void pragma_parse(TCCState *s1)
2762 int val;
2764 next();
2765 if (tok == TOK_pack) {
2767 This may be:
2768 #pragma pack(1) // set
2769 #pragma pack() // reset to default
2770 #pragma pack(push,1) // push & set
2771 #pragma pack(pop) // restore previous
2773 next();
2774 skip('(');
2775 if (tok == TOK_ASM_pop) {
2776 next();
2777 if (s1->pack_stack_ptr <= s1->pack_stack) {
2778 stk_error:
2779 error("out of pack stack");
2781 s1->pack_stack_ptr--;
2782 } else {
2783 val = 0;
2784 if (tok != ')') {
2785 if (tok == TOK_ASM_push) {
2786 next();
2787 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2788 goto stk_error;
2789 s1->pack_stack_ptr++;
2790 skip(',');
2792 if (tok != TOK_CINT) {
2793 pack_error:
2794 error("invalid pack pragma");
2796 val = tokc.i;
2797 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2798 goto pack_error;
2799 next();
2801 *s1->pack_stack_ptr = val;
2802 skip(')');
2807 /* is_bof is true if first non space token at beginning of file */
2808 static void preprocess(int is_bof)
2810 TCCState *s1 = tcc_state;
2811 int size, i, c, n, saved_parse_flags;
2812 char buf[1024], *q, *p;
2813 char buf1[1024];
2814 BufferedFile *f;
2815 Sym *s;
2816 CachedInclude *e;
2818 saved_parse_flags = parse_flags;
2819 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2820 PARSE_FLAG_LINEFEED;
2821 next_nomacro();
2822 redo:
2823 switch(tok) {
2824 case TOK_DEFINE:
2825 next_nomacro();
2826 parse_define();
2827 break;
2828 case TOK_UNDEF:
2829 next_nomacro();
2830 s = define_find(tok);
2831 /* undefine symbol by putting an invalid name */
2832 if (s)
2833 define_undef(s);
2834 break;
2835 case TOK_INCLUDE:
2836 case TOK_INCLUDE_NEXT:
2837 ch = file->buf_ptr[0];
2838 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2839 skip_spaces();
2840 if (ch == '<') {
2841 c = '>';
2842 goto read_name;
2843 } else if (ch == '\"') {
2844 c = ch;
2845 read_name:
2846 /* XXX: better stray handling */
2847 minp();
2848 q = buf;
2849 while (ch != c && ch != '\n' && ch != CH_EOF) {
2850 if ((q - buf) < sizeof(buf) - 1)
2851 *q++ = ch;
2852 minp();
2854 *q = '\0';
2855 minp();
2856 #if 0
2857 /* eat all spaces and comments after include */
2858 /* XXX: slightly incorrect */
2859 while (ch1 != '\n' && ch1 != CH_EOF)
2860 inp();
2861 #endif
2862 } else {
2863 /* computed #include : either we have only strings or
2864 we have anything enclosed in '<>' */
2865 next();
2866 buf[0] = '\0';
2867 if (tok == TOK_STR) {
2868 while (tok != TOK_LINEFEED) {
2869 if (tok != TOK_STR) {
2870 include_syntax:
2871 error("'#include' expects \"FILENAME\" or <FILENAME>");
2873 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2874 next();
2876 c = '\"';
2877 } else {
2878 int len;
2879 while (tok != TOK_LINEFEED) {
2880 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2881 next();
2883 len = strlen(buf);
2884 /* check syntax and remove '<>' */
2885 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2886 goto include_syntax;
2887 memmove(buf, buf + 1, len - 2);
2888 buf[len - 2] = '\0';
2889 c = '>';
2893 e = search_cached_include(s1, c, buf);
2894 if (e && define_find(e->ifndef_macro)) {
2895 /* no need to parse the include because the 'ifndef macro'
2896 is defined */
2897 #ifdef INC_DEBUG
2898 printf("%s: skipping %s\n", file->filename, buf);
2899 #endif
2900 } else {
2901 if (c == '\"') {
2902 /* first search in current dir if "header.h" */
2903 size = 0;
2904 p = strrchr(file->filename, '/');
2905 if (p)
2906 size = p + 1 - file->filename;
2907 if (size > sizeof(buf1) - 1)
2908 size = sizeof(buf1) - 1;
2909 memcpy(buf1, file->filename, size);
2910 buf1[size] = '\0';
2911 pstrcat(buf1, sizeof(buf1), buf);
2912 f = tcc_open(s1, buf1);
2913 if (f) {
2914 if (tok == TOK_INCLUDE_NEXT)
2915 tok = TOK_INCLUDE;
2916 else
2917 goto found;
2920 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2921 error("#include recursion too deep");
2922 /* now search in all the include paths */
2923 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2924 for(i = 0; i < n; i++) {
2925 const char *path;
2926 if (i < s1->nb_include_paths)
2927 path = s1->include_paths[i];
2928 else
2929 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2930 pstrcpy(buf1, sizeof(buf1), path);
2931 pstrcat(buf1, sizeof(buf1), "/");
2932 pstrcat(buf1, sizeof(buf1), buf);
2933 f = tcc_open(s1, buf1);
2934 if (f) {
2935 if (tok == TOK_INCLUDE_NEXT)
2936 tok = TOK_INCLUDE;
2937 else
2938 goto found;
2941 error("include file '%s' not found", buf);
2942 f = NULL;
2943 found:
2944 #ifdef INC_DEBUG
2945 printf("%s: including %s\n", file->filename, buf1);
2946 #endif
2947 f->inc_type = c;
2948 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2949 /* push current file in stack */
2950 /* XXX: fix current line init */
2951 *s1->include_stack_ptr++ = file;
2952 file = f;
2953 /* add include file debug info */
2954 if (do_debug) {
2955 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2957 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2958 ch = file->buf_ptr[0];
2959 goto the_end;
2961 break;
2962 case TOK_IFNDEF:
2963 c = 1;
2964 goto do_ifdef;
2965 case TOK_IF:
2966 c = expr_preprocess();
2967 goto do_if;
2968 case TOK_IFDEF:
2969 c = 0;
2970 do_ifdef:
2971 next_nomacro();
2972 if (tok < TOK_IDENT)
2973 error("invalid argument for '#if%sdef'", c ? "n" : "");
2974 if (is_bof) {
2975 if (c) {
2976 #ifdef INC_DEBUG
2977 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2978 #endif
2979 file->ifndef_macro = tok;
2982 c = (define_find(tok) != 0) ^ c;
2983 do_if:
2984 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2985 error("memory full");
2986 *s1->ifdef_stack_ptr++ = c;
2987 goto test_skip;
2988 case TOK_ELSE:
2989 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2990 error("#else without matching #if");
2991 if (s1->ifdef_stack_ptr[-1] & 2)
2992 error("#else after #else");
2993 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2994 goto test_skip;
2995 case TOK_ELIF:
2996 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2997 error("#elif without matching #if");
2998 c = s1->ifdef_stack_ptr[-1];
2999 if (c > 1)
3000 error("#elif after #else");
3001 /* last #if/#elif expression was true: we skip */
3002 if (c == 1)
3003 goto skip;
3004 c = expr_preprocess();
3005 s1->ifdef_stack_ptr[-1] = c;
3006 test_skip:
3007 if (!(c & 1)) {
3008 skip:
3009 preprocess_skip();
3010 is_bof = 0;
3011 goto redo;
3013 break;
3014 case TOK_ENDIF:
3015 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3016 error("#endif without matching #if");
3017 s1->ifdef_stack_ptr--;
3018 /* '#ifndef macro' was at the start of file. Now we check if
3019 an '#endif' is exactly at the end of file */
3020 if (file->ifndef_macro &&
3021 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3022 file->ifndef_macro_saved = file->ifndef_macro;
3023 /* need to set to zero to avoid false matches if another
3024 #ifndef at middle of file */
3025 file->ifndef_macro = 0;
3026 while (tok != TOK_LINEFEED)
3027 next_nomacro();
3028 tok_flags |= TOK_FLAG_ENDIF;
3029 goto the_end;
3031 break;
3032 case TOK_LINE:
3033 next();
3034 if (tok != TOK_CINT)
3035 error("#line");
3036 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3037 next();
3038 if (tok != TOK_LINEFEED) {
3039 if (tok != TOK_STR)
3040 error("#line");
3041 pstrcpy(file->filename, sizeof(file->filename),
3042 (char *)tokc.cstr->data);
3044 break;
3045 case TOK_ERROR:
3046 case TOK_WARNING:
3047 c = tok;
3048 ch = file->buf_ptr[0];
3049 skip_spaces();
3050 q = buf;
3051 while (ch != '\n' && ch != CH_EOF) {
3052 if ((q - buf) < sizeof(buf) - 1)
3053 *q++ = ch;
3054 minp();
3056 *q = '\0';
3057 if (c == TOK_ERROR)
3058 error("#error %s", buf);
3059 else
3060 warning("#warning %s", buf);
3061 break;
3062 case TOK_PRAGMA:
3063 pragma_parse(s1);
3064 break;
3065 default:
3066 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3067 /* '!' is ignored to allow C scripts. numbers are ignored
3068 to emulate cpp behaviour */
3069 } else {
3070 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3071 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
3073 break;
3075 /* ignore other preprocess commands or #! for C scripts */
3076 while (tok != TOK_LINEFEED)
3077 next_nomacro();
3078 the_end:
3079 parse_flags = saved_parse_flags;
3082 /* evaluate escape codes in a string. */
3083 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3085 int c, n;
3086 const uint8_t *p;
3088 p = buf;
3089 for(;;) {
3090 c = *p;
3091 if (c == '\0')
3092 break;
3093 if (c == '\\') {
3094 p++;
3095 /* escape */
3096 c = *p;
3097 switch(c) {
3098 case '0': case '1': case '2': case '3':
3099 case '4': case '5': case '6': case '7':
3100 /* at most three octal digits */
3101 n = c - '0';
3102 p++;
3103 c = *p;
3104 if (isoct(c)) {
3105 n = n * 8 + c - '0';
3106 p++;
3107 c = *p;
3108 if (isoct(c)) {
3109 n = n * 8 + c - '0';
3110 p++;
3113 c = n;
3114 goto add_char_nonext;
3115 case 'x':
3116 p++;
3117 n = 0;
3118 for(;;) {
3119 c = *p;
3120 if (c >= 'a' && c <= 'f')
3121 c = c - 'a' + 10;
3122 else if (c >= 'A' && c <= 'F')
3123 c = c - 'A' + 10;
3124 else if (isnum(c))
3125 c = c - '0';
3126 else
3127 break;
3128 n = n * 16 + c;
3129 p++;
3131 c = n;
3132 goto add_char_nonext;
3133 case 'a':
3134 c = '\a';
3135 break;
3136 case 'b':
3137 c = '\b';
3138 break;
3139 case 'f':
3140 c = '\f';
3141 break;
3142 case 'n':
3143 c = '\n';
3144 break;
3145 case 'r':
3146 c = '\r';
3147 break;
3148 case 't':
3149 c = '\t';
3150 break;
3151 case 'v':
3152 c = '\v';
3153 break;
3154 case 'e':
3155 if (!gnu_ext)
3156 goto invalid_escape;
3157 c = 27;
3158 break;
3159 case '\'':
3160 case '\"':
3161 case '\\':
3162 case '?':
3163 break;
3164 default:
3165 invalid_escape:
3166 if (c >= '!' && c <= '~')
3167 warning("unknown escape sequence: \'\\%c\'", c);
3168 else
3169 warning("unknown escape sequence: \'\\x%x\'", c);
3170 break;
3173 p++;
3174 add_char_nonext:
3175 if (!is_long)
3176 cstr_ccat(outstr, c);
3177 else
3178 cstr_wccat(outstr, c);
3180 /* add a trailing '\0' */
3181 if (!is_long)
3182 cstr_ccat(outstr, '\0');
3183 else
3184 cstr_wccat(outstr, '\0');
3187 /* we use 64 bit numbers */
3188 #define BN_SIZE 2
3190 /* bn = (bn << shift) | or_val */
3191 void bn_lshift(unsigned int *bn, int shift, int or_val)
3193 int i;
3194 unsigned int v;
3195 for(i=0;i<BN_SIZE;i++) {
3196 v = bn[i];
3197 bn[i] = (v << shift) | or_val;
3198 or_val = v >> (32 - shift);
3202 void bn_zero(unsigned int *bn)
3204 int i;
3205 for(i=0;i<BN_SIZE;i++) {
3206 bn[i] = 0;
3210 /* parse number in null terminated string 'p' and return it in the
3211 current token */
3212 void parse_number(const char *p)
3214 int b, t, shift, frac_bits, s, exp_val, ch;
3215 char *q;
3216 unsigned int bn[BN_SIZE];
3217 double d;
3219 /* number */
3220 q = token_buf;
3221 ch = *p++;
3222 t = ch;
3223 ch = *p++;
3224 *q++ = t;
3225 b = 10;
3226 if (t == '.') {
3227 goto float_frac_parse;
3228 } else if (t == '0') {
3229 if (ch == 'x' || ch == 'X') {
3230 q--;
3231 ch = *p++;
3232 b = 16;
3233 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3234 q--;
3235 ch = *p++;
3236 b = 2;
3239 /* parse all digits. cannot check octal numbers at this stage
3240 because of floating point constants */
3241 while (1) {
3242 if (ch >= 'a' && ch <= 'f')
3243 t = ch - 'a' + 10;
3244 else if (ch >= 'A' && ch <= 'F')
3245 t = ch - 'A' + 10;
3246 else if (isnum(ch))
3247 t = ch - '0';
3248 else
3249 break;
3250 if (t >= b)
3251 break;
3252 if (q >= token_buf + STRING_MAX_SIZE) {
3253 num_too_long:
3254 error("number too long");
3256 *q++ = ch;
3257 ch = *p++;
3259 if (ch == '.' ||
3260 ((ch == 'e' || ch == 'E') && b == 10) ||
3261 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3262 if (b != 10) {
3263 /* NOTE: strtox should support that for hexa numbers, but
3264 non ISOC99 libcs do not support it, so we prefer to do
3265 it by hand */
3266 /* hexadecimal or binary floats */
3267 /* XXX: handle overflows */
3268 *q = '\0';
3269 if (b == 16)
3270 shift = 4;
3271 else
3272 shift = 2;
3273 bn_zero(bn);
3274 q = token_buf;
3275 while (1) {
3276 t = *q++;
3277 if (t == '\0') {
3278 break;
3279 } else if (t >= 'a') {
3280 t = t - 'a' + 10;
3281 } else if (t >= 'A') {
3282 t = t - 'A' + 10;
3283 } else {
3284 t = t - '0';
3286 bn_lshift(bn, shift, t);
3288 frac_bits = 0;
3289 if (ch == '.') {
3290 ch = *p++;
3291 while (1) {
3292 t = ch;
3293 if (t >= 'a' && t <= 'f') {
3294 t = t - 'a' + 10;
3295 } else if (t >= 'A' && t <= 'F') {
3296 t = t - 'A' + 10;
3297 } else if (t >= '0' && t <= '9') {
3298 t = t - '0';
3299 } else {
3300 break;
3302 if (t >= b)
3303 error("invalid digit");
3304 bn_lshift(bn, shift, t);
3305 frac_bits += shift;
3306 ch = *p++;
3309 if (ch != 'p' && ch != 'P')
3310 expect("exponent");
3311 ch = *p++;
3312 s = 1;
3313 exp_val = 0;
3314 if (ch == '+') {
3315 ch = *p++;
3316 } else if (ch == '-') {
3317 s = -1;
3318 ch = *p++;
3320 if (ch < '0' || ch > '9')
3321 expect("exponent digits");
3322 while (ch >= '0' && ch <= '9') {
3323 exp_val = exp_val * 10 + ch - '0';
3324 ch = *p++;
3326 exp_val = exp_val * s;
3328 /* now we can generate the number */
3329 /* XXX: should patch directly float number */
3330 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3331 d = ldexp(d, exp_val - frac_bits);
3332 t = toup(ch);
3333 if (t == 'F') {
3334 ch = *p++;
3335 tok = TOK_CFLOAT;
3336 /* float : should handle overflow */
3337 tokc.f = (float)d;
3338 } else if (t == 'L') {
3339 ch = *p++;
3340 tok = TOK_CLDOUBLE;
3341 /* XXX: not large enough */
3342 tokc.ld = (long double)d;
3343 } else {
3344 tok = TOK_CDOUBLE;
3345 tokc.d = d;
3347 } else {
3348 /* decimal floats */
3349 if (ch == '.') {
3350 if (q >= token_buf + STRING_MAX_SIZE)
3351 goto num_too_long;
3352 *q++ = ch;
3353 ch = *p++;
3354 float_frac_parse:
3355 while (ch >= '0' && ch <= '9') {
3356 if (q >= token_buf + STRING_MAX_SIZE)
3357 goto num_too_long;
3358 *q++ = ch;
3359 ch = *p++;
3362 if (ch == 'e' || ch == 'E') {
3363 if (q >= token_buf + STRING_MAX_SIZE)
3364 goto num_too_long;
3365 *q++ = ch;
3366 ch = *p++;
3367 if (ch == '-' || ch == '+') {
3368 if (q >= token_buf + STRING_MAX_SIZE)
3369 goto num_too_long;
3370 *q++ = ch;
3371 ch = *p++;
3373 if (ch < '0' || ch > '9')
3374 expect("exponent digits");
3375 while (ch >= '0' && ch <= '9') {
3376 if (q >= token_buf + STRING_MAX_SIZE)
3377 goto num_too_long;
3378 *q++ = ch;
3379 ch = *p++;
3382 *q = '\0';
3383 t = toup(ch);
3384 errno = 0;
3385 if (t == 'F') {
3386 ch = *p++;
3387 tok = TOK_CFLOAT;
3388 tokc.f = strtof(token_buf, NULL);
3389 } else if (t == 'L') {
3390 ch = *p++;
3391 tok = TOK_CLDOUBLE;
3392 tokc.ld = strtold(token_buf, NULL);
3393 } else {
3394 tok = TOK_CDOUBLE;
3395 tokc.d = strtod(token_buf, NULL);
3398 } else {
3399 unsigned long long n, n1;
3400 int lcount, ucount;
3402 /* integer number */
3403 *q = '\0';
3404 q = token_buf;
3405 if (b == 10 && *q == '0') {
3406 b = 8;
3407 q++;
3409 n = 0;
3410 while(1) {
3411 t = *q++;
3412 /* no need for checks except for base 10 / 8 errors */
3413 if (t == '\0') {
3414 break;
3415 } else if (t >= 'a') {
3416 t = t - 'a' + 10;
3417 } else if (t >= 'A') {
3418 t = t - 'A' + 10;
3419 } else {
3420 t = t - '0';
3421 if (t >= b)
3422 error("invalid digit");
3424 n1 = n;
3425 n = n * b + t;
3426 /* detect overflow */
3427 /* XXX: this test is not reliable */
3428 if (n < n1)
3429 error("integer constant overflow");
3432 /* XXX: not exactly ANSI compliant */
3433 if ((n & 0xffffffff00000000LL) != 0) {
3434 if ((n >> 63) != 0)
3435 tok = TOK_CULLONG;
3436 else
3437 tok = TOK_CLLONG;
3438 } else if (n > 0x7fffffff) {
3439 tok = TOK_CUINT;
3440 } else {
3441 tok = TOK_CINT;
3443 lcount = 0;
3444 ucount = 0;
3445 for(;;) {
3446 t = toup(ch);
3447 if (t == 'L') {
3448 if (lcount >= 2)
3449 error("three 'l's in integer constant");
3450 lcount++;
3451 if (lcount == 2) {
3452 if (tok == TOK_CINT)
3453 tok = TOK_CLLONG;
3454 else if (tok == TOK_CUINT)
3455 tok = TOK_CULLONG;
3457 ch = *p++;
3458 } else if (t == 'U') {
3459 if (ucount >= 1)
3460 error("two 'u's in integer constant");
3461 ucount++;
3462 if (tok == TOK_CINT)
3463 tok = TOK_CUINT;
3464 else if (tok == TOK_CLLONG)
3465 tok = TOK_CULLONG;
3466 ch = *p++;
3467 } else {
3468 break;
3471 if (tok == TOK_CINT || tok == TOK_CUINT)
3472 tokc.ui = n;
3473 else
3474 tokc.ull = n;
3479 #define PARSE2(c1, tok1, c2, tok2) \
3480 case c1: \
3481 PEEKC(c, p); \
3482 if (c == c2) { \
3483 p++; \
3484 tok = tok2; \
3485 } else { \
3486 tok = tok1; \
3488 break;
3490 /* return next token without macro substitution */
3491 static inline void next_nomacro1(void)
3493 int t, c, is_long;
3494 TokenSym *ts;
3495 uint8_t *p, *p1;
3496 unsigned int h;
3498 p = file->buf_ptr;
3499 redo_no_start:
3500 c = *p;
3501 switch(c) {
3502 case ' ':
3503 case '\t':
3504 case '\f':
3505 case '\v':
3506 case '\r':
3507 p++;
3508 goto redo_no_start;
3510 case '\\':
3511 /* first look if it is in fact an end of buffer */
3512 if (p >= file->buf_end) {
3513 file->buf_ptr = p;
3514 handle_eob();
3515 p = file->buf_ptr;
3516 if (p >= file->buf_end)
3517 goto parse_eof;
3518 else
3519 goto redo_no_start;
3520 } else {
3521 file->buf_ptr = p;
3522 ch = *p;
3523 handle_stray();
3524 p = file->buf_ptr;
3525 goto redo_no_start;
3527 parse_eof:
3529 TCCState *s1 = tcc_state;
3530 if (parse_flags & PARSE_FLAG_LINEFEED) {
3531 tok = TOK_LINEFEED;
3532 } else if (s1->include_stack_ptr == s1->include_stack ||
3533 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3534 /* no include left : end of file. */
3535 tok = TOK_EOF;
3536 } else {
3537 /* pop include file */
3539 /* test if previous '#endif' was after a #ifdef at
3540 start of file */
3541 if (tok_flags & TOK_FLAG_ENDIF) {
3542 #ifdef INC_DEBUG
3543 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3544 #endif
3545 add_cached_include(s1, file->inc_type, file->inc_filename,
3546 file->ifndef_macro_saved);
3549 /* add end of include file debug info */
3550 if (do_debug) {
3551 put_stabd(N_EINCL, 0, 0);
3553 /* pop include stack */
3554 tcc_close(file);
3555 s1->include_stack_ptr--;
3556 file = *s1->include_stack_ptr;
3557 p = file->buf_ptr;
3558 goto redo_no_start;
3561 break;
3563 case '\n':
3564 if (parse_flags & PARSE_FLAG_LINEFEED) {
3565 tok = TOK_LINEFEED;
3566 } else {
3567 file->line_num++;
3568 tok_flags |= TOK_FLAG_BOL;
3569 p++;
3570 goto redo_no_start;
3572 break;
3574 case '#':
3575 /* XXX: simplify */
3576 PEEKC(c, p);
3577 if ((tok_flags & TOK_FLAG_BOL) &&
3578 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3579 file->buf_ptr = p;
3580 preprocess(tok_flags & TOK_FLAG_BOF);
3581 p = file->buf_ptr;
3582 goto redo_no_start;
3583 } else {
3584 if (c == '#') {
3585 p++;
3586 tok = TOK_TWOSHARPS;
3587 } else {
3588 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3589 p = parse_line_comment(p - 1);
3590 goto redo_no_start;
3591 } else {
3592 tok = '#';
3596 break;
3598 case 'a': case 'b': case 'c': case 'd':
3599 case 'e': case 'f': case 'g': case 'h':
3600 case 'i': case 'j': case 'k': case 'l':
3601 case 'm': case 'n': case 'o': case 'p':
3602 case 'q': case 'r': case 's': case 't':
3603 case 'u': case 'v': case 'w': case 'x':
3604 case 'y': case 'z':
3605 case 'A': case 'B': case 'C': case 'D':
3606 case 'E': case 'F': case 'G': case 'H':
3607 case 'I': case 'J': case 'K':
3608 case 'M': case 'N': case 'O': case 'P':
3609 case 'Q': case 'R': case 'S': case 'T':
3610 case 'U': case 'V': case 'W': case 'X':
3611 case 'Y': case 'Z':
3612 case '_':
3613 parse_ident_fast:
3614 p1 = p;
3615 h = TOK_HASH_INIT;
3616 h = TOK_HASH_FUNC(h, c);
3617 p++;
3618 for(;;) {
3619 c = *p;
3620 if (!isidnum_table[c])
3621 break;
3622 h = TOK_HASH_FUNC(h, c);
3623 p++;
3625 if (c != '\\') {
3626 TokenSym **pts;
3627 int len;
3629 /* fast case : no stray found, so we have the full token
3630 and we have already hashed it */
3631 len = p - p1;
3632 h &= (TOK_HASH_SIZE - 1);
3633 pts = &hash_ident[h];
3634 for(;;) {
3635 ts = *pts;
3636 if (!ts)
3637 break;
3638 if (ts->len == len && !memcmp(ts->str, p1, len))
3639 goto token_found;
3640 pts = &(ts->hash_next);
3642 ts = tok_alloc_new(pts, p1, len);
3643 token_found: ;
3644 } else {
3645 /* slower case */
3646 cstr_reset(&tokcstr);
3648 while (p1 < p) {
3649 cstr_ccat(&tokcstr, *p1);
3650 p1++;
3652 p--;
3653 PEEKC(c, p);
3654 parse_ident_slow:
3655 while (isidnum_table[c]) {
3656 cstr_ccat(&tokcstr, c);
3657 PEEKC(c, p);
3659 ts = tok_alloc(tokcstr.data, tokcstr.size);
3661 tok = ts->tok;
3662 break;
3663 case 'L':
3664 t = p[1];
3665 if (t != '\\' && t != '\'' && t != '\"') {
3666 /* fast case */
3667 goto parse_ident_fast;
3668 } else {
3669 PEEKC(c, p);
3670 if (c == '\'' || c == '\"') {
3671 is_long = 1;
3672 goto str_const;
3673 } else {
3674 cstr_reset(&tokcstr);
3675 cstr_ccat(&tokcstr, 'L');
3676 goto parse_ident_slow;
3679 break;
3680 case '0': case '1': case '2': case '3':
3681 case '4': case '5': case '6': case '7':
3682 case '8': case '9':
3684 cstr_reset(&tokcstr);
3685 /* after the first digit, accept digits, alpha, '.' or sign if
3686 prefixed by 'eEpP' */
3687 parse_num:
3688 for(;;) {
3689 t = c;
3690 cstr_ccat(&tokcstr, c);
3691 PEEKC(c, p);
3692 if (!(isnum(c) || isid(c) || c == '.' ||
3693 ((c == '+' || c == '-') &&
3694 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3695 break;
3697 /* We add a trailing '\0' to ease parsing */
3698 cstr_ccat(&tokcstr, '\0');
3699 tokc.cstr = &tokcstr;
3700 tok = TOK_PPNUM;
3701 break;
3702 case '.':
3703 /* special dot handling because it can also start a number */
3704 PEEKC(c, p);
3705 if (isnum(c)) {
3706 cstr_reset(&tokcstr);
3707 cstr_ccat(&tokcstr, '.');
3708 goto parse_num;
3709 } else if (c == '.') {
3710 PEEKC(c, p);
3711 if (c != '.')
3712 expect("'.'");
3713 PEEKC(c, p);
3714 tok = TOK_DOTS;
3715 } else {
3716 tok = '.';
3718 break;
3719 case '\'':
3720 case '\"':
3721 is_long = 0;
3722 str_const:
3724 CString str;
3725 int sep;
3727 sep = c;
3729 /* parse the string */
3730 cstr_new(&str);
3731 p = parse_pp_string(p, sep, &str);
3732 cstr_ccat(&str, '\0');
3734 /* eval the escape (should be done as TOK_PPNUM) */
3735 cstr_reset(&tokcstr);
3736 parse_escape_string(&tokcstr, str.data, is_long);
3737 cstr_free(&str);
3739 if (sep == '\'') {
3740 int char_size;
3741 /* XXX: make it portable */
3742 if (!is_long)
3743 char_size = 1;
3744 else
3745 char_size = sizeof(nwchar_t);
3746 if (tokcstr.size <= char_size)
3747 error("empty character constant");
3748 if (tokcstr.size > 2 * char_size)
3749 warning("multi-character character constant");
3750 if (!is_long) {
3751 tokc.i = *(int8_t *)tokcstr.data;
3752 tok = TOK_CCHAR;
3753 } else {
3754 tokc.i = *(nwchar_t *)tokcstr.data;
3755 tok = TOK_LCHAR;
3757 } else {
3758 tokc.cstr = &tokcstr;
3759 if (!is_long)
3760 tok = TOK_STR;
3761 else
3762 tok = TOK_LSTR;
3765 break;
3767 case '<':
3768 PEEKC(c, p);
3769 if (c == '=') {
3770 p++;
3771 tok = TOK_LE;
3772 } else if (c == '<') {
3773 PEEKC(c, p);
3774 if (c == '=') {
3775 p++;
3776 tok = TOK_A_SHL;
3777 } else {
3778 tok = TOK_SHL;
3780 } else {
3781 tok = TOK_LT;
3783 break;
3785 case '>':
3786 PEEKC(c, p);
3787 if (c == '=') {
3788 p++;
3789 tok = TOK_GE;
3790 } else if (c == '>') {
3791 PEEKC(c, p);
3792 if (c == '=') {
3793 p++;
3794 tok = TOK_A_SAR;
3795 } else {
3796 tok = TOK_SAR;
3798 } else {
3799 tok = TOK_GT;
3801 break;
3803 case '&':
3804 PEEKC(c, p);
3805 if (c == '&') {
3806 p++;
3807 tok = TOK_LAND;
3808 } else if (c == '=') {
3809 p++;
3810 tok = TOK_A_AND;
3811 } else {
3812 tok = '&';
3814 break;
3816 case '|':
3817 PEEKC(c, p);
3818 if (c == '|') {
3819 p++;
3820 tok = TOK_LOR;
3821 } else if (c == '=') {
3822 p++;
3823 tok = TOK_A_OR;
3824 } else {
3825 tok = '|';
3827 break;
3829 case '+':
3830 PEEKC(c, p);
3831 if (c == '+') {
3832 p++;
3833 tok = TOK_INC;
3834 } else if (c == '=') {
3835 p++;
3836 tok = TOK_A_ADD;
3837 } else {
3838 tok = '+';
3840 break;
3842 case '-':
3843 PEEKC(c, p);
3844 if (c == '-') {
3845 p++;
3846 tok = TOK_DEC;
3847 } else if (c == '=') {
3848 p++;
3849 tok = TOK_A_SUB;
3850 } else if (c == '>') {
3851 p++;
3852 tok = TOK_ARROW;
3853 } else {
3854 tok = '-';
3856 break;
3858 PARSE2('!', '!', '=', TOK_NE)
3859 PARSE2('=', '=', '=', TOK_EQ)
3860 PARSE2('*', '*', '=', TOK_A_MUL)
3861 PARSE2('%', '%', '=', TOK_A_MOD)
3862 PARSE2('^', '^', '=', TOK_A_XOR)
3864 /* comments or operator */
3865 case '/':
3866 PEEKC(c, p);
3867 if (c == '*') {
3868 p = parse_comment(p);
3869 goto redo_no_start;
3870 } else if (c == '/') {
3871 p = parse_line_comment(p);
3872 goto redo_no_start;
3873 } else if (c == '=') {
3874 p++;
3875 tok = TOK_A_DIV;
3876 } else {
3877 tok = '/';
3879 break;
3881 /* simple tokens */
3882 case '(':
3883 case ')':
3884 case '[':
3885 case ']':
3886 case '{':
3887 case '}':
3888 case ',':
3889 case ';':
3890 case ':':
3891 case '?':
3892 case '~':
3893 case '$': /* only used in assembler */
3894 case '@': /* dito */
3895 tok = c;
3896 p++;
3897 break;
3898 default:
3899 error("unrecognized character \\x%02x", c);
3900 break;
3902 file->buf_ptr = p;
3903 tok_flags = 0;
3904 #if defined(PARSE_DEBUG)
3905 printf("token = %s\n", get_tok_str(tok, &tokc));
3906 #endif
3909 /* return next token without macro substitution. Can read input from
3910 macro_ptr buffer */
3911 static void next_nomacro(void)
3913 if (macro_ptr) {
3914 redo:
3915 tok = *macro_ptr;
3916 if (tok) {
3917 TOK_GET(tok, macro_ptr, tokc);
3918 if (tok == TOK_LINENUM) {
3919 file->line_num = tokc.i;
3920 goto redo;
3923 } else {
3924 next_nomacro1();
3928 /* substitute args in macro_str and return allocated string */
3929 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3931 int *st, last_tok, t, notfirst;
3932 Sym *s;
3933 CValue cval;
3934 TokenString str;
3935 CString cstr;
3937 tok_str_new(&str);
3938 last_tok = 0;
3939 while(1) {
3940 TOK_GET(t, macro_str, cval);
3941 if (!t)
3942 break;
3943 if (t == '#') {
3944 /* stringize */
3945 TOK_GET(t, macro_str, cval);
3946 if (!t)
3947 break;
3948 s = sym_find2(args, t);
3949 if (s) {
3950 cstr_new(&cstr);
3951 st = (int *)s->c;
3952 notfirst = 0;
3953 while (*st) {
3954 if (notfirst)
3955 cstr_ccat(&cstr, ' ');
3956 TOK_GET(t, st, cval);
3957 cstr_cat(&cstr, get_tok_str(t, &cval));
3958 notfirst = 1;
3960 cstr_ccat(&cstr, '\0');
3961 #ifdef PP_DEBUG
3962 printf("stringize: %s\n", (char *)cstr.data);
3963 #endif
3964 /* add string */
3965 cval.cstr = &cstr;
3966 tok_str_add2(&str, TOK_STR, &cval);
3967 cstr_free(&cstr);
3968 } else {
3969 tok_str_add2(&str, t, &cval);
3971 } else if (t >= TOK_IDENT) {
3972 s = sym_find2(args, t);
3973 if (s) {
3974 st = (int *)s->c;
3975 /* if '##' is present before or after, no arg substitution */
3976 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3977 /* special case for var arg macros : ## eats the
3978 ',' if empty VA_ARGS variable. */
3979 /* XXX: test of the ',' is not 100%
3980 reliable. should fix it to avoid security
3981 problems */
3982 if (gnu_ext && s->type.t &&
3983 last_tok == TOK_TWOSHARPS &&
3984 str.len >= 2 && str.str[str.len - 2] == ',') {
3985 if (*st == 0) {
3986 /* suppress ',' '##' */
3987 str.len -= 2;
3988 } else {
3989 /* suppress '##' and add variable */
3990 str.len--;
3991 goto add_var;
3993 } else {
3994 int t1;
3995 add_var:
3996 for(;;) {
3997 TOK_GET(t1, st, cval);
3998 if (!t1)
3999 break;
4000 tok_str_add2(&str, t1, &cval);
4003 } else {
4004 /* NOTE: the stream cannot be read when macro
4005 substituing an argument */
4006 macro_subst(&str, nested_list, st, NULL);
4008 } else {
4009 tok_str_add(&str, t);
4011 } else {
4012 tok_str_add2(&str, t, &cval);
4014 last_tok = t;
4016 tok_str_add(&str, 0);
4017 return str.str;
4020 static char const ab_month_name[12][4] =
4022 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4023 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4026 /* do macro substitution of current token with macro 's' and add
4027 result to (tok_str,tok_len). 'nested_list' is the list of all
4028 macros we got inside to avoid recursing. Return non zero if no
4029 substitution needs to be done */
4030 static int macro_subst_tok(TokenString *tok_str,
4031 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4033 Sym *args, *sa, *sa1;
4034 int mstr_allocated, parlevel, *mstr, t, t1;
4035 TokenString str;
4036 char *cstrval;
4037 CValue cval;
4038 CString cstr;
4039 char buf[32];
4041 /* if symbol is a macro, prepare substitution */
4042 /* special macros */
4043 if (tok == TOK___LINE__) {
4044 snprintf(buf, sizeof(buf), "%d", file->line_num);
4045 cstrval = buf;
4046 t1 = TOK_PPNUM;
4047 goto add_cstr1;
4048 } else if (tok == TOK___FILE__) {
4049 cstrval = file->filename;
4050 goto add_cstr;
4051 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4052 time_t ti;
4053 struct tm *tm;
4055 time(&ti);
4056 tm = localtime(&ti);
4057 if (tok == TOK___DATE__) {
4058 snprintf(buf, sizeof(buf), "%s %2d %d",
4059 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4060 } else {
4061 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4062 tm->tm_hour, tm->tm_min, tm->tm_sec);
4064 cstrval = buf;
4065 add_cstr:
4066 t1 = TOK_STR;
4067 add_cstr1:
4068 cstr_new(&cstr);
4069 cstr_cat(&cstr, cstrval);
4070 cstr_ccat(&cstr, '\0');
4071 cval.cstr = &cstr;
4072 tok_str_add2(tok_str, t1, &cval);
4073 cstr_free(&cstr);
4074 } else {
4075 mstr = (int *)s->c;
4076 mstr_allocated = 0;
4077 if (s->type.t == MACRO_FUNC) {
4078 /* NOTE: we do not use next_nomacro to avoid eating the
4079 next token. XXX: find better solution */
4080 redo:
4081 if (macro_ptr) {
4082 t = *macro_ptr;
4083 if (t == 0 && can_read_stream) {
4084 /* end of macro stream: we must look at the token
4085 after in the file */
4086 struct macro_level *ml = *can_read_stream;
4087 macro_ptr = NULL;
4088 if (ml)
4090 macro_ptr = ml->p;
4091 ml->p = NULL;
4092 *can_read_stream = ml -> prev;
4094 goto redo;
4096 } else {
4097 /* XXX: incorrect with comments */
4098 ch = file->buf_ptr[0];
4099 while (is_space(ch) || ch == '\n')
4100 cinp();
4101 t = ch;
4103 if (t != '(') /* no macro subst */
4104 return -1;
4106 /* argument macro */
4107 next_nomacro();
4108 next_nomacro();
4109 args = NULL;
4110 sa = s->next;
4111 /* NOTE: empty args are allowed, except if no args */
4112 for(;;) {
4113 /* handle '()' case */
4114 if (!args && !sa && tok == ')')
4115 break;
4116 if (!sa)
4117 error("macro '%s' used with too many args",
4118 get_tok_str(s->v, 0));
4119 tok_str_new(&str);
4120 parlevel = 0;
4121 /* NOTE: non zero sa->t indicates VA_ARGS */
4122 while ((parlevel > 0 ||
4123 (tok != ')' &&
4124 (tok != ',' || sa->type.t))) &&
4125 tok != -1) {
4126 if (tok == '(')
4127 parlevel++;
4128 else if (tok == ')')
4129 parlevel--;
4130 tok_str_add2(&str, tok, &tokc);
4131 next_nomacro();
4133 tok_str_add(&str, 0);
4134 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4135 sa = sa->next;
4136 if (tok == ')') {
4137 /* special case for gcc var args: add an empty
4138 var arg argument if it is omitted */
4139 if (sa && sa->type.t && gnu_ext)
4140 continue;
4141 else
4142 break;
4144 if (tok != ',')
4145 expect(",");
4146 next_nomacro();
4148 if (sa) {
4149 error("macro '%s' used with too few args",
4150 get_tok_str(s->v, 0));
4153 /* now subst each arg */
4154 mstr = macro_arg_subst(nested_list, mstr, args);
4155 /* free memory */
4156 sa = args;
4157 while (sa) {
4158 sa1 = sa->prev;
4159 tok_str_free((int *)sa->c);
4160 sym_free(sa);
4161 sa = sa1;
4163 mstr_allocated = 1;
4165 sym_push2(nested_list, s->v, 0, 0);
4166 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4167 /* pop nested defined symbol */
4168 sa1 = *nested_list;
4169 *nested_list = sa1->prev;
4170 sym_free(sa1);
4171 if (mstr_allocated)
4172 tok_str_free(mstr);
4174 return 0;
4177 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4178 return the resulting string (which must be freed). */
4179 static inline int *macro_twosharps(const int *macro_str)
4181 TokenSym *ts;
4182 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4183 int t;
4184 const char *p1, *p2;
4185 CValue cval;
4186 TokenString macro_str1;
4187 CString cstr;
4189 start_macro_ptr = macro_str;
4190 /* we search the first '##' */
4191 for(;;) {
4192 macro_ptr1 = macro_str;
4193 TOK_GET(t, macro_str, cval);
4194 /* nothing more to do if end of string */
4195 if (t == 0)
4196 return NULL;
4197 if (*macro_str == TOK_TWOSHARPS)
4198 break;
4201 /* we saw '##', so we need more processing to handle it */
4202 cstr_new(&cstr);
4203 tok_str_new(&macro_str1);
4204 tok = t;
4205 tokc = cval;
4207 /* add all tokens seen so far */
4208 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4209 TOK_GET(t, ptr, cval);
4210 tok_str_add2(&macro_str1, t, &cval);
4212 saved_macro_ptr = macro_ptr;
4213 /* XXX: get rid of the use of macro_ptr here */
4214 macro_ptr = (int *)macro_str;
4215 for(;;) {
4216 while (*macro_ptr == TOK_TWOSHARPS) {
4217 macro_ptr++;
4218 macro_ptr1 = macro_ptr;
4219 t = *macro_ptr;
4220 if (t) {
4221 TOK_GET(t, macro_ptr, cval);
4222 /* We concatenate the two tokens if we have an
4223 identifier or a preprocessing number */
4224 cstr_reset(&cstr);
4225 p1 = get_tok_str(tok, &tokc);
4226 cstr_cat(&cstr, p1);
4227 p2 = get_tok_str(t, &cval);
4228 cstr_cat(&cstr, p2);
4229 cstr_ccat(&cstr, '\0');
4231 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4232 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4233 if (tok == TOK_PPNUM) {
4234 /* if number, then create a number token */
4235 /* NOTE: no need to allocate because
4236 tok_str_add2() does it */
4237 tokc.cstr = &cstr;
4238 } else {
4239 /* if identifier, we must do a test to
4240 validate we have a correct identifier */
4241 if (t == TOK_PPNUM) {
4242 const char *p;
4243 int c;
4245 p = p2;
4246 for(;;) {
4247 c = *p;
4248 if (c == '\0')
4249 break;
4250 p++;
4251 if (!isnum(c) && !isid(c))
4252 goto error_pasting;
4255 ts = tok_alloc(cstr.data, strlen(cstr.data));
4256 tok = ts->tok; /* modify current token */
4258 } else {
4259 const char *str = cstr.data;
4260 const unsigned char *q;
4262 /* we look for a valid token */
4263 /* XXX: do more extensive checks */
4264 if (!strcmp(str, ">>=")) {
4265 tok = TOK_A_SAR;
4266 } else if (!strcmp(str, "<<=")) {
4267 tok = TOK_A_SHL;
4268 } else if (strlen(str) == 2) {
4269 /* search in two bytes table */
4270 q = tok_two_chars;
4271 for(;;) {
4272 if (!*q)
4273 goto error_pasting;
4274 if (q[0] == str[0] && q[1] == str[1])
4275 break;
4276 q += 3;
4278 tok = q[2];
4279 } else {
4280 error_pasting:
4281 /* NOTE: because get_tok_str use a static buffer,
4282 we must save it */
4283 cstr_reset(&cstr);
4284 p1 = get_tok_str(tok, &tokc);
4285 cstr_cat(&cstr, p1);
4286 cstr_ccat(&cstr, '\0');
4287 p2 = get_tok_str(t, &cval);
4288 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4289 /* cannot merge tokens: just add them separately */
4290 tok_str_add2(&macro_str1, tok, &tokc);
4291 /* XXX: free associated memory ? */
4292 tok = t;
4293 tokc = cval;
4298 tok_str_add2(&macro_str1, tok, &tokc);
4299 next_nomacro();
4300 if (tok == 0)
4301 break;
4303 macro_ptr = (int *)saved_macro_ptr;
4304 cstr_free(&cstr);
4305 tok_str_add(&macro_str1, 0);
4306 return macro_str1.str;
4310 /* do macro substitution of macro_str and add result to
4311 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4312 inside to avoid recursing. */
4313 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4314 const int *macro_str, struct macro_level ** can_read_stream)
4316 Sym *s;
4317 int *macro_str1;
4318 const int *ptr;
4319 int t, ret;
4320 CValue cval;
4321 struct macro_level ml;
4323 /* first scan for '##' operator handling */
4324 ptr = macro_str;
4325 macro_str1 = macro_twosharps(ptr);
4326 if (macro_str1)
4327 ptr = macro_str1;
4328 while (1) {
4329 /* NOTE: ptr == NULL can only happen if tokens are read from
4330 file stream due to a macro function call */
4331 if (ptr == NULL)
4332 break;
4333 TOK_GET(t, ptr, cval);
4334 if (t == 0)
4335 break;
4336 s = define_find(t);
4337 if (s != NULL) {
4338 /* if nested substitution, do nothing */
4339 if (sym_find2(*nested_list, t))
4340 goto no_subst;
4341 ml.p = macro_ptr;
4342 if (can_read_stream)
4343 ml.prev = *can_read_stream, *can_read_stream = &ml;
4344 macro_ptr = (int *)ptr;
4345 tok = t;
4346 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4347 ptr = (int *)macro_ptr;
4348 macro_ptr = ml.p;
4349 if (can_read_stream && *can_read_stream == &ml)
4350 *can_read_stream = ml.prev;
4351 if (ret != 0)
4352 goto no_subst;
4353 } else {
4354 no_subst:
4355 tok_str_add2(tok_str, t, &cval);
4358 if (macro_str1)
4359 tok_str_free(macro_str1);
4362 /* return next token with macro substitution */
4363 static void next(void)
4365 Sym *nested_list, *s;
4366 TokenString str;
4367 struct macro_level *ml;
4369 redo:
4370 next_nomacro();
4371 if (!macro_ptr) {
4372 /* if not reading from macro substituted string, then try
4373 to substitute macros */
4374 if (tok >= TOK_IDENT &&
4375 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4376 s = define_find(tok);
4377 if (s) {
4378 /* we have a macro: we try to substitute */
4379 tok_str_new(&str);
4380 nested_list = NULL;
4381 ml = NULL;
4382 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4383 /* substitution done, NOTE: maybe empty */
4384 tok_str_add(&str, 0);
4385 macro_ptr = str.str;
4386 macro_ptr_allocated = str.str;
4387 goto redo;
4391 } else {
4392 if (tok == 0) {
4393 /* end of macro or end of unget buffer */
4394 if (unget_buffer_enabled) {
4395 macro_ptr = unget_saved_macro_ptr;
4396 unget_buffer_enabled = 0;
4397 } else {
4398 /* end of macro string: free it */
4399 tok_str_free(macro_ptr_allocated);
4400 macro_ptr = NULL;
4402 goto redo;
4406 /* convert preprocessor tokens into C tokens */
4407 if (tok == TOK_PPNUM &&
4408 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4409 parse_number((char *)tokc.cstr->data);
4413 /* push back current token and set current token to 'last_tok'. Only
4414 identifier case handled for labels. */
4415 static inline void unget_tok(int last_tok)
4417 int i, n;
4418 int *q;
4419 unget_saved_macro_ptr = macro_ptr;
4420 unget_buffer_enabled = 1;
4421 q = unget_saved_buffer;
4422 macro_ptr = q;
4423 *q++ = tok;
4424 n = tok_ext_size(tok) - 1;
4425 for(i=0;i<n;i++)
4426 *q++ = tokc.tab[i];
4427 *q = 0; /* end of token string */
4428 tok = last_tok;
4432 void swap(int *p, int *q)
4434 int t;
4435 t = *p;
4436 *p = *q;
4437 *q = t;
4440 void vsetc(CType *type, int r, CValue *vc)
4442 int v;
4444 if (vtop >= vstack + (VSTACK_SIZE - 1))
4445 error("memory full");
4446 /* cannot let cpu flags if other instruction are generated. Also
4447 avoid leaving VT_JMP anywhere except on the top of the stack
4448 because it would complicate the code generator. */
4449 if (vtop >= vstack) {
4450 v = vtop->r & VT_VALMASK;
4451 if (v == VT_CMP || (v & ~1) == VT_JMP)
4452 gv(RC_INT);
4454 vtop++;
4455 vtop->type = *type;
4456 vtop->r = r;
4457 vtop->r2 = VT_CONST;
4458 vtop->c = *vc;
4461 /* push integer constant */
4462 void vpushi(int v)
4464 CValue cval;
4465 cval.i = v;
4466 vsetc(&int_type, VT_CONST, &cval);
4469 /* Return a static symbol pointing to a section */
4470 static Sym *get_sym_ref(CType *type, Section *sec,
4471 unsigned long offset, unsigned long size)
4473 int v;
4474 Sym *sym;
4476 v = anon_sym++;
4477 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4478 sym->type.ref = type->ref;
4479 sym->r = VT_CONST | VT_SYM;
4480 put_extern_sym(sym, sec, offset, size);
4481 return sym;
4484 /* push a reference to a section offset by adding a dummy symbol */
4485 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4487 CValue cval;
4489 cval.ul = 0;
4490 vsetc(type, VT_CONST | VT_SYM, &cval);
4491 vtop->sym = get_sym_ref(type, sec, offset, size);
4494 /* define a new external reference to a symbol 'v' of type 'u' */
4495 static Sym *external_global_sym(int v, CType *type, int r)
4497 Sym *s;
4499 s = sym_find(v);
4500 if (!s) {
4501 /* push forward reference */
4502 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4503 s->type.ref = type->ref;
4504 s->r = r | VT_CONST | VT_SYM;
4506 return s;
4509 /* define a new external reference to a symbol 'v' of type 'u' */
4510 static Sym *external_sym(int v, CType *type, int r)
4512 Sym *s;
4514 s = sym_find(v);
4515 if (!s) {
4516 /* push forward reference */
4517 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4518 s->type.t |= VT_EXTERN;
4519 } else {
4520 if (!is_compatible_types(&s->type, type))
4521 error("incompatible types for redefinition of '%s'",
4522 get_tok_str(v, NULL));
4524 return s;
4527 /* push a reference to global symbol v */
4528 static void vpush_global_sym(CType *type, int v)
4530 Sym *sym;
4531 CValue cval;
4533 sym = external_global_sym(v, type, 0);
4534 cval.ul = 0;
4535 vsetc(type, VT_CONST | VT_SYM, &cval);
4536 vtop->sym = sym;
4539 void vset(CType *type, int r, int v)
4541 CValue cval;
4543 cval.i = v;
4544 vsetc(type, r, &cval);
4547 void vseti(int r, int v)
4549 CType type;
4550 type.t = VT_INT;
4551 vset(&type, r, v);
4554 void vswap(void)
4556 SValue tmp;
4558 tmp = vtop[0];
4559 vtop[0] = vtop[-1];
4560 vtop[-1] = tmp;
4563 void vpushv(SValue *v)
4565 if (vtop >= vstack + (VSTACK_SIZE - 1))
4566 error("memory full");
4567 vtop++;
4568 *vtop = *v;
4571 void vdup(void)
4573 vpushv(vtop);
4576 /* save r to the memory stack, and mark it as being free */
4577 void save_reg(int r)
4579 int l, saved, size, align;
4580 SValue *p, sv;
4581 CType *type;
4583 /* modify all stack values */
4584 saved = 0;
4585 l = 0;
4586 for(p=vstack;p<=vtop;p++) {
4587 if ((p->r & VT_VALMASK) == r ||
4588 (p->r2 & VT_VALMASK) == r) {
4589 /* must save value on stack if not already done */
4590 if (!saved) {
4591 /* NOTE: must reload 'r' because r might be equal to r2 */
4592 r = p->r & VT_VALMASK;
4593 /* store register in the stack */
4594 type = &p->type;
4595 if ((p->r & VT_LVAL) ||
4596 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4597 type = &int_type;
4598 size = type_size(type, &align);
4599 loc = (loc - size) & -align;
4600 sv.type.t = type->t;
4601 sv.r = VT_LOCAL | VT_LVAL;
4602 sv.c.ul = loc;
4603 store(r, &sv);
4604 #ifdef TCC_TARGET_I386
4605 /* x86 specific: need to pop fp register ST0 if saved */
4606 if (r == TREG_ST0) {
4607 o(0xd9dd); /* fstp %st(1) */
4609 #endif
4610 /* special long long case */
4611 if ((type->t & VT_BTYPE) == VT_LLONG) {
4612 sv.c.ul += 4;
4613 store(p->r2, &sv);
4615 l = loc;
4616 saved = 1;
4618 /* mark that stack entry as being saved on the stack */
4619 if (p->r & VT_LVAL) {
4620 /* also clear the bounded flag because the
4621 relocation address of the function was stored in
4622 p->c.ul */
4623 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4624 } else {
4625 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4627 p->r2 = VT_CONST;
4628 p->c.ul = l;
4633 /* find a register of class 'rc2' with at most one reference on stack.
4634 * If none, call get_reg(rc) */
4635 int get_reg_ex(int rc, int rc2)
4637 int r;
4638 SValue *p;
4640 for(r=0;r<NB_REGS;r++) {
4641 if (reg_classes[r] & rc2) {
4642 int n;
4643 n=0;
4644 for(p = vstack; p <= vtop; p++) {
4645 if ((p->r & VT_VALMASK) == r ||
4646 (p->r2 & VT_VALMASK) == r)
4647 n++;
4649 if (n <= 1)
4650 return r;
4653 return get_reg(rc);
4656 /* find a free register of class 'rc'. If none, save one register */
4657 int get_reg(int rc)
4659 int r;
4660 SValue *p;
4662 /* find a free register */
4663 for(r=0;r<NB_REGS;r++) {
4664 if (reg_classes[r] & rc) {
4665 for(p=vstack;p<=vtop;p++) {
4666 if ((p->r & VT_VALMASK) == r ||
4667 (p->r2 & VT_VALMASK) == r)
4668 goto notfound;
4670 return r;
4672 notfound: ;
4675 /* no register left : free the first one on the stack (VERY
4676 IMPORTANT to start from the bottom to ensure that we don't
4677 spill registers used in gen_opi()) */
4678 for(p=vstack;p<=vtop;p++) {
4679 r = p->r & VT_VALMASK;
4680 if (r < VT_CONST && (reg_classes[r] & rc))
4681 goto save_found;
4682 /* also look at second register (if long long) */
4683 r = p->r2 & VT_VALMASK;
4684 if (r < VT_CONST && (reg_classes[r] & rc)) {
4685 save_found:
4686 save_reg(r);
4687 return r;
4690 /* Should never comes here */
4691 return -1;
4694 /* save registers up to (vtop - n) stack entry */
4695 void save_regs(int n)
4697 int r;
4698 SValue *p, *p1;
4699 p1 = vtop - n;
4700 for(p = vstack;p <= p1; p++) {
4701 r = p->r & VT_VALMASK;
4702 if (r < VT_CONST) {
4703 save_reg(r);
4708 /* move register 's' to 'r', and flush previous value of r to memory
4709 if needed */
4710 void move_reg(int r, int s)
4712 SValue sv;
4714 if (r != s) {
4715 save_reg(r);
4716 sv.type.t = VT_INT;
4717 sv.r = s;
4718 sv.c.ul = 0;
4719 load(r, &sv);
4723 /* get address of vtop (vtop MUST BE an lvalue) */
4724 void gaddrof(void)
4726 vtop->r &= ~VT_LVAL;
4727 /* tricky: if saved lvalue, then we can go back to lvalue */
4728 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4729 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4732 #ifdef CONFIG_TCC_BCHECK
4733 /* generate lvalue bound code */
4734 void gbound(void)
4736 int lval_type;
4737 CType type1;
4739 vtop->r &= ~VT_MUSTBOUND;
4740 /* if lvalue, then use checking code before dereferencing */
4741 if (vtop->r & VT_LVAL) {
4742 /* if not VT_BOUNDED value, then make one */
4743 if (!(vtop->r & VT_BOUNDED)) {
4744 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4745 /* must save type because we must set it to int to get pointer */
4746 type1 = vtop->type;
4747 vtop->type.t = VT_INT;
4748 gaddrof();
4749 vpushi(0);
4750 gen_bounded_ptr_add();
4751 vtop->r |= lval_type;
4752 vtop->type = type1;
4754 /* then check for dereferencing */
4755 gen_bounded_ptr_deref();
4758 #endif
4760 /* store vtop a register belonging to class 'rc'. lvalues are
4761 converted to values. Cannot be used if cannot be converted to
4762 register value (such as structures). */
4763 int gv(int rc)
4765 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4766 unsigned long long ll;
4768 /* NOTE: get_reg can modify vstack[] */
4769 if (vtop->type.t & VT_BITFIELD) {
4770 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4771 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4772 /* remove bit field info to avoid loops */
4773 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4774 /* generate shifts */
4775 vpushi(32 - (bit_pos + bit_size));
4776 gen_op(TOK_SHL);
4777 vpushi(32 - bit_size);
4778 /* NOTE: transformed to SHR if unsigned */
4779 gen_op(TOK_SAR);
4780 r = gv(rc);
4781 } else {
4782 if (is_float(vtop->type.t) &&
4783 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4784 Sym *sym;
4785 int *ptr;
4786 unsigned long offset;
4788 /* XXX: unify with initializers handling ? */
4789 /* CPUs usually cannot use float constants, so we store them
4790 generically in data segment */
4791 size = type_size(&vtop->type, &align);
4792 offset = (data_section->data_offset + align - 1) & -align;
4793 data_section->data_offset = offset;
4794 /* XXX: not portable yet */
4795 ptr = section_ptr_add(data_section, size);
4796 size = size >> 2;
4797 for(i=0;i<size;i++)
4798 ptr[i] = vtop->c.tab[i];
4799 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4800 vtop->r |= VT_LVAL | VT_SYM;
4801 vtop->sym = sym;
4802 vtop->c.ul = 0;
4804 #ifdef CONFIG_TCC_BCHECK
4805 if (vtop->r & VT_MUSTBOUND)
4806 gbound();
4807 #endif
4809 r = vtop->r & VT_VALMASK;
4810 /* need to reload if:
4811 - constant
4812 - lvalue (need to dereference pointer)
4813 - already a register, but not in the right class */
4814 if (r >= VT_CONST ||
4815 (vtop->r & VT_LVAL) ||
4816 !(reg_classes[r] & rc) ||
4817 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4818 !(reg_classes[vtop->r2] & rc))) {
4819 r = get_reg(rc);
4820 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4821 /* two register type load : expand to two words
4822 temporarily */
4823 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4824 /* load constant */
4825 ll = vtop->c.ull;
4826 vtop->c.ui = ll; /* first word */
4827 load(r, vtop);
4828 vtop->r = r; /* save register value */
4829 vpushi(ll >> 32); /* second word */
4830 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4831 (vtop->r & VT_LVAL)) {
4832 /* We do not want to modifier the long long
4833 pointer here, so the safest (and less
4834 efficient) is to save all the other registers
4835 in the stack. XXX: totally inefficient. */
4836 save_regs(1);
4837 /* load from memory */
4838 load(r, vtop);
4839 vdup();
4840 vtop[-1].r = r; /* save register value */
4841 /* increment pointer to get second word */
4842 vtop->type.t = VT_INT;
4843 gaddrof();
4844 vpushi(4);
4845 gen_op('+');
4846 vtop->r |= VT_LVAL;
4847 } else {
4848 /* move registers */
4849 load(r, vtop);
4850 vdup();
4851 vtop[-1].r = r; /* save register value */
4852 vtop->r = vtop[-1].r2;
4854 /* allocate second register */
4855 rc2 = RC_INT;
4856 if (rc == RC_IRET)
4857 rc2 = RC_LRET;
4858 r2 = get_reg(rc2);
4859 load(r2, vtop);
4860 vpop();
4861 /* write second register */
4862 vtop->r2 = r2;
4863 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4864 int t1, t;
4865 /* lvalue of scalar type : need to use lvalue type
4866 because of possible cast */
4867 t = vtop->type.t;
4868 t1 = t;
4869 /* compute memory access type */
4870 if (vtop->r & VT_LVAL_BYTE)
4871 t = VT_BYTE;
4872 else if (vtop->r & VT_LVAL_SHORT)
4873 t = VT_SHORT;
4874 if (vtop->r & VT_LVAL_UNSIGNED)
4875 t |= VT_UNSIGNED;
4876 vtop->type.t = t;
4877 load(r, vtop);
4878 /* restore wanted type */
4879 vtop->type.t = t1;
4880 } else {
4881 /* one register type load */
4882 load(r, vtop);
4885 vtop->r = r;
4886 #ifdef TCC_TARGET_C67
4887 /* uses register pairs for doubles */
4888 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4889 vtop->r2 = r+1;
4890 #endif
4892 return r;
4895 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4896 void gv2(int rc1, int rc2)
4898 int v;
4900 /* generate more generic register first. But VT_JMP or VT_CMP
4901 values must be generated first in all cases to avoid possible
4902 reload errors */
4903 v = vtop[0].r & VT_VALMASK;
4904 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4905 vswap();
4906 gv(rc1);
4907 vswap();
4908 gv(rc2);
4909 /* test if reload is needed for first register */
4910 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4911 vswap();
4912 gv(rc1);
4913 vswap();
4915 } else {
4916 gv(rc2);
4917 vswap();
4918 gv(rc1);
4919 vswap();
4920 /* test if reload is needed for first register */
4921 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4922 gv(rc2);
4927 /* expand long long on stack in two int registers */
4928 void lexpand(void)
4930 int u;
4932 u = vtop->type.t & VT_UNSIGNED;
4933 gv(RC_INT);
4934 vdup();
4935 vtop[0].r = vtop[-1].r2;
4936 vtop[0].r2 = VT_CONST;
4937 vtop[-1].r2 = VT_CONST;
4938 vtop[0].type.t = VT_INT | u;
4939 vtop[-1].type.t = VT_INT | u;
4942 #ifdef TCC_TARGET_ARM
4943 /* expand long long on stack */
4944 void lexpand_nr(void)
4946 int u,v;
4948 u = vtop->type.t & VT_UNSIGNED;
4949 vdup();
4950 vtop->r2 = VT_CONST;
4951 vtop->type.t = VT_INT | u;
4952 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4953 if (v == VT_CONST) {
4954 vtop[-1].c.ui = vtop->c.ull;
4955 vtop->c.ui = vtop->c.ull >> 32;
4956 vtop->r = VT_CONST;
4957 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4958 vtop->c.ui += 4;
4959 vtop->r = vtop[-1].r;
4960 } else if (v > VT_CONST) {
4961 vtop--;
4962 lexpand();
4963 } else
4964 vtop->r = vtop[-1].r2;
4965 vtop[-1].r2 = VT_CONST;
4966 vtop[-1].type.t = VT_INT | u;
4968 #endif
4970 /* build a long long from two ints */
4971 void lbuild(int t)
4973 gv2(RC_INT, RC_INT);
4974 vtop[-1].r2 = vtop[0].r;
4975 vtop[-1].type.t = t;
4976 vpop();
4979 /* rotate n first stack elements to the bottom
4980 I1 ... In -> I2 ... In I1 [top is right]
4982 void vrotb(int n)
4984 int i;
4985 SValue tmp;
4987 tmp = vtop[-n + 1];
4988 for(i=-n+1;i!=0;i++)
4989 vtop[i] = vtop[i+1];
4990 vtop[0] = tmp;
4993 /* rotate n first stack elements to the top
4994 I1 ... In -> In I1 ... I(n-1) [top is right]
4996 void vrott(int n)
4998 int i;
4999 SValue tmp;
5001 tmp = vtop[0];
5002 for(i = 0;i < n - 1; i++)
5003 vtop[-i] = vtop[-i - 1];
5004 vtop[-n + 1] = tmp;
5007 #ifdef TCC_TARGET_ARM
5008 /* like vrott but in other direction
5009 In ... I1 -> I(n-1) ... I1 In [top is right]
5011 void vnrott(int n)
5013 int i;
5014 SValue tmp;
5016 tmp = vtop[-n + 1];
5017 for(i = n - 1; i > 0; i--)
5018 vtop[-i] = vtop[-i + 1];
5019 vtop[0] = tmp;
5021 #endif
5023 /* pop stack value */
5024 void vpop(void)
5026 int v;
5027 v = vtop->r & VT_VALMASK;
5028 #ifdef TCC_TARGET_I386
5029 /* for x86, we need to pop the FP stack */
5030 if (v == TREG_ST0 && !nocode_wanted) {
5031 o(0xd9dd); /* fstp %st(1) */
5032 } else
5033 #endif
5034 if (v == VT_JMP || v == VT_JMPI) {
5035 /* need to put correct jump if && or || without test */
5036 gsym(vtop->c.ul);
5038 vtop--;
5041 /* convert stack entry to register and duplicate its value in another
5042 register */
5043 void gv_dup(void)
5045 int rc, t, r, r1;
5046 SValue sv;
5048 t = vtop->type.t;
5049 if ((t & VT_BTYPE) == VT_LLONG) {
5050 lexpand();
5051 gv_dup();
5052 vswap();
5053 vrotb(3);
5054 gv_dup();
5055 vrotb(4);
5056 /* stack: H L L1 H1 */
5057 lbuild(t);
5058 vrotb(3);
5059 vrotb(3);
5060 vswap();
5061 lbuild(t);
5062 vswap();
5063 } else {
5064 /* duplicate value */
5065 rc = RC_INT;
5066 sv.type.t = VT_INT;
5067 if (is_float(t)) {
5068 rc = RC_FLOAT;
5069 sv.type.t = t;
5071 r = gv(rc);
5072 r1 = get_reg(rc);
5073 sv.r = r;
5074 sv.c.ul = 0;
5075 load(r1, &sv); /* move r to r1 */
5076 vdup();
5077 /* duplicates value */
5078 vtop->r = r1;
5082 /* generate CPU independent (unsigned) long long operations */
5083 void gen_opl(int op)
5085 int t, a, b, op1, c, i;
5086 int func;
5087 SValue tmp;
5089 switch(op) {
5090 case '/':
5091 case TOK_PDIV:
5092 func = TOK___divdi3;
5093 goto gen_func;
5094 case TOK_UDIV:
5095 func = TOK___udivdi3;
5096 goto gen_func;
5097 case '%':
5098 func = TOK___moddi3;
5099 goto gen_func;
5100 case TOK_UMOD:
5101 func = TOK___umoddi3;
5102 gen_func:
5103 /* call generic long long function */
5104 vpush_global_sym(&func_old_type, func);
5105 vrott(3);
5106 gfunc_call(2);
5107 vpushi(0);
5108 vtop->r = REG_IRET;
5109 vtop->r2 = REG_LRET;
5110 break;
5111 case '^':
5112 case '&':
5113 case '|':
5114 case '*':
5115 case '+':
5116 case '-':
5117 t = vtop->type.t;
5118 vswap();
5119 lexpand();
5120 vrotb(3);
5121 lexpand();
5122 /* stack: L1 H1 L2 H2 */
5123 tmp = vtop[0];
5124 vtop[0] = vtop[-3];
5125 vtop[-3] = tmp;
5126 tmp = vtop[-2];
5127 vtop[-2] = vtop[-3];
5128 vtop[-3] = tmp;
5129 vswap();
5130 /* stack: H1 H2 L1 L2 */
5131 if (op == '*') {
5132 vpushv(vtop - 1);
5133 vpushv(vtop - 1);
5134 gen_op(TOK_UMULL);
5135 lexpand();
5136 /* stack: H1 H2 L1 L2 ML MH */
5137 for(i=0;i<4;i++)
5138 vrotb(6);
5139 /* stack: ML MH H1 H2 L1 L2 */
5140 tmp = vtop[0];
5141 vtop[0] = vtop[-2];
5142 vtop[-2] = tmp;
5143 /* stack: ML MH H1 L2 H2 L1 */
5144 gen_op('*');
5145 vrotb(3);
5146 vrotb(3);
5147 gen_op('*');
5148 /* stack: ML MH M1 M2 */
5149 gen_op('+');
5150 gen_op('+');
5151 } else if (op == '+' || op == '-') {
5152 /* XXX: add non carry method too (for MIPS or alpha) */
5153 if (op == '+')
5154 op1 = TOK_ADDC1;
5155 else
5156 op1 = TOK_SUBC1;
5157 gen_op(op1);
5158 /* stack: H1 H2 (L1 op L2) */
5159 vrotb(3);
5160 vrotb(3);
5161 gen_op(op1 + 1); /* TOK_xxxC2 */
5162 } else {
5163 gen_op(op);
5164 /* stack: H1 H2 (L1 op L2) */
5165 vrotb(3);
5166 vrotb(3);
5167 /* stack: (L1 op L2) H1 H2 */
5168 gen_op(op);
5169 /* stack: (L1 op L2) (H1 op H2) */
5171 /* stack: L H */
5172 lbuild(t);
5173 break;
5174 case TOK_SAR:
5175 case TOK_SHR:
5176 case TOK_SHL:
5177 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5178 t = vtop[-1].type.t;
5179 vswap();
5180 lexpand();
5181 vrotb(3);
5182 /* stack: L H shift */
5183 c = (int)vtop->c.i;
5184 /* constant: simpler */
5185 /* NOTE: all comments are for SHL. the other cases are
5186 done by swaping words */
5187 vpop();
5188 if (op != TOK_SHL)
5189 vswap();
5190 if (c >= 32) {
5191 /* stack: L H */
5192 vpop();
5193 if (c > 32) {
5194 vpushi(c - 32);
5195 gen_op(op);
5197 if (op != TOK_SAR) {
5198 vpushi(0);
5199 } else {
5200 gv_dup();
5201 vpushi(31);
5202 gen_op(TOK_SAR);
5204 vswap();
5205 } else {
5206 vswap();
5207 gv_dup();
5208 /* stack: H L L */
5209 vpushi(c);
5210 gen_op(op);
5211 vswap();
5212 vpushi(32 - c);
5213 if (op == TOK_SHL)
5214 gen_op(TOK_SHR);
5215 else
5216 gen_op(TOK_SHL);
5217 vrotb(3);
5218 /* stack: L L H */
5219 vpushi(c);
5220 if (op == TOK_SHL)
5221 gen_op(TOK_SHL);
5222 else
5223 gen_op(TOK_SHR);
5224 gen_op('|');
5226 if (op != TOK_SHL)
5227 vswap();
5228 lbuild(t);
5229 } else {
5230 /* XXX: should provide a faster fallback on x86 ? */
5231 switch(op) {
5232 case TOK_SAR:
5233 func = TOK___sardi3;
5234 goto gen_func;
5235 case TOK_SHR:
5236 func = TOK___shrdi3;
5237 goto gen_func;
5238 case TOK_SHL:
5239 func = TOK___shldi3;
5240 goto gen_func;
5243 break;
5244 default:
5245 /* compare operations */
5246 t = vtop->type.t;
5247 vswap();
5248 lexpand();
5249 vrotb(3);
5250 lexpand();
5251 /* stack: L1 H1 L2 H2 */
5252 tmp = vtop[-1];
5253 vtop[-1] = vtop[-2];
5254 vtop[-2] = tmp;
5255 /* stack: L1 L2 H1 H2 */
5256 /* compare high */
5257 op1 = op;
5258 /* when values are equal, we need to compare low words. since
5259 the jump is inverted, we invert the test too. */
5260 if (op1 == TOK_LT)
5261 op1 = TOK_LE;
5262 else if (op1 == TOK_GT)
5263 op1 = TOK_GE;
5264 else if (op1 == TOK_ULT)
5265 op1 = TOK_ULE;
5266 else if (op1 == TOK_UGT)
5267 op1 = TOK_UGE;
5268 a = 0;
5269 b = 0;
5270 gen_op(op1);
5271 if (op1 != TOK_NE) {
5272 a = gtst(1, 0);
5274 if (op != TOK_EQ) {
5275 /* generate non equal test */
5276 /* XXX: NOT PORTABLE yet */
5277 if (a == 0) {
5278 b = gtst(0, 0);
5279 } else {
5280 #if defined(TCC_TARGET_I386)
5281 b = psym(0x850f, 0);
5282 #elif defined(TCC_TARGET_ARM)
5283 b = ind;
5284 o(0x1A000000 | encbranch(ind, 0, 1));
5285 #elif defined(TCC_TARGET_C67)
5286 error("not implemented");
5287 #else
5288 #error not supported
5289 #endif
5292 /* compare low. Always unsigned */
5293 op1 = op;
5294 if (op1 == TOK_LT)
5295 op1 = TOK_ULT;
5296 else if (op1 == TOK_LE)
5297 op1 = TOK_ULE;
5298 else if (op1 == TOK_GT)
5299 op1 = TOK_UGT;
5300 else if (op1 == TOK_GE)
5301 op1 = TOK_UGE;
5302 gen_op(op1);
5303 a = gtst(1, a);
5304 gsym(b);
5305 vseti(VT_JMPI, a);
5306 break;
5310 /* handle integer constant optimizations and various machine
5311 independent opt */
5312 void gen_opic(int op)
5314 int fc, c1, c2, n;
5315 SValue *v1, *v2;
5317 v1 = vtop - 1;
5318 v2 = vtop;
5319 /* currently, we cannot do computations with forward symbols */
5320 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5321 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5322 if (c1 && c2) {
5323 fc = v2->c.i;
5324 switch(op) {
5325 case '+': v1->c.i += fc; break;
5326 case '-': v1->c.i -= fc; break;
5327 case '&': v1->c.i &= fc; break;
5328 case '^': v1->c.i ^= fc; break;
5329 case '|': v1->c.i |= fc; break;
5330 case '*': v1->c.i *= fc; break;
5332 case TOK_PDIV:
5333 case '/':
5334 case '%':
5335 case TOK_UDIV:
5336 case TOK_UMOD:
5337 /* if division by zero, generate explicit division */
5338 if (fc == 0) {
5339 if (const_wanted)
5340 error("division by zero in constant");
5341 goto general_case;
5343 switch(op) {
5344 default: v1->c.i /= fc; break;
5345 case '%': v1->c.i %= fc; break;
5346 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5347 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5349 break;
5350 case TOK_SHL: v1->c.i <<= fc; break;
5351 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5352 case TOK_SAR: v1->c.i >>= fc; break;
5353 /* tests */
5354 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5355 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5356 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5357 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5358 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5359 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5360 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5361 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5362 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5363 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5364 /* logical */
5365 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5366 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5367 default:
5368 goto general_case;
5370 vtop--;
5371 } else {
5372 /* if commutative ops, put c2 as constant */
5373 if (c1 && (op == '+' || op == '&' || op == '^' ||
5374 op == '|' || op == '*')) {
5375 vswap();
5376 swap(&c1, &c2);
5378 fc = vtop->c.i;
5379 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5380 op == TOK_PDIV) &&
5381 fc == 1) ||
5382 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5383 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5384 fc == 0) ||
5385 (op == '&' &&
5386 fc == -1))) {
5387 /* nothing to do */
5388 vtop--;
5389 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5390 /* try to use shifts instead of muls or divs */
5391 if (fc > 0 && (fc & (fc - 1)) == 0) {
5392 n = -1;
5393 while (fc) {
5394 fc >>= 1;
5395 n++;
5397 vtop->c.i = n;
5398 if (op == '*')
5399 op = TOK_SHL;
5400 else if (op == TOK_PDIV)
5401 op = TOK_SAR;
5402 else
5403 op = TOK_SHR;
5405 goto general_case;
5406 } else if (c2 && (op == '+' || op == '-') &&
5407 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5408 (VT_CONST | VT_SYM)) {
5409 /* symbol + constant case */
5410 if (op == '-')
5411 fc = -fc;
5412 vtop--;
5413 vtop->c.i += fc;
5414 } else {
5415 general_case:
5416 if (!nocode_wanted) {
5417 /* call low level op generator */
5418 gen_opi(op);
5419 } else {
5420 vtop--;
5426 /* generate a floating point operation with constant propagation */
5427 void gen_opif(int op)
5429 int c1, c2;
5430 SValue *v1, *v2;
5431 long double f1, f2;
5433 v1 = vtop - 1;
5434 v2 = vtop;
5435 /* currently, we cannot do computations with forward symbols */
5436 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5437 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5438 if (c1 && c2) {
5439 if (v1->type.t == VT_FLOAT) {
5440 f1 = v1->c.f;
5441 f2 = v2->c.f;
5442 } else if (v1->type.t == VT_DOUBLE) {
5443 f1 = v1->c.d;
5444 f2 = v2->c.d;
5445 } else {
5446 f1 = v1->c.ld;
5447 f2 = v2->c.ld;
5450 /* NOTE: we only do constant propagation if finite number (not
5451 NaN or infinity) (ANSI spec) */
5452 if (!ieee_finite(f1) || !ieee_finite(f2))
5453 goto general_case;
5455 switch(op) {
5456 case '+': f1 += f2; break;
5457 case '-': f1 -= f2; break;
5458 case '*': f1 *= f2; break;
5459 case '/':
5460 if (f2 == 0.0) {
5461 if (const_wanted)
5462 error("division by zero in constant");
5463 goto general_case;
5465 f1 /= f2;
5466 break;
5467 /* XXX: also handles tests ? */
5468 default:
5469 goto general_case;
5471 /* XXX: overflow test ? */
5472 if (v1->type.t == VT_FLOAT) {
5473 v1->c.f = f1;
5474 } else if (v1->type.t == VT_DOUBLE) {
5475 v1->c.d = f1;
5476 } else {
5477 v1->c.ld = f1;
5479 vtop--;
5480 } else {
5481 general_case:
5482 if (!nocode_wanted) {
5483 gen_opf(op);
5484 } else {
5485 vtop--;
5490 static int pointed_size(CType *type)
5492 int align;
5493 return type_size(pointed_type(type), &align);
5496 static inline int is_null_pointer(SValue *p)
5498 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5499 return 0;
5500 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5501 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5504 static inline int is_integer_btype(int bt)
5506 return (bt == VT_BYTE || bt == VT_SHORT ||
5507 bt == VT_INT || bt == VT_LLONG);
5510 /* check types for comparison or substraction of pointers */
5511 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5513 CType *type1, *type2, tmp_type1, tmp_type2;
5514 int bt1, bt2;
5516 /* null pointers are accepted for all comparisons as gcc */
5517 if (is_null_pointer(p1) || is_null_pointer(p2))
5518 return;
5519 type1 = &p1->type;
5520 type2 = &p2->type;
5521 bt1 = type1->t & VT_BTYPE;
5522 bt2 = type2->t & VT_BTYPE;
5523 /* accept comparison between pointer and integer with a warning */
5524 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5525 warning("comparison between pointer and integer");
5526 return;
5529 /* both must be pointers or implicit function pointers */
5530 if (bt1 == VT_PTR) {
5531 type1 = pointed_type(type1);
5532 } else if (bt1 != VT_FUNC)
5533 goto invalid_operands;
5535 if (bt2 == VT_PTR) {
5536 type2 = pointed_type(type2);
5537 } else if (bt2 != VT_FUNC) {
5538 invalid_operands:
5539 error("invalid operands to binary %s", get_tok_str(op, NULL));
5541 if ((type1->t & VT_BTYPE) == VT_VOID ||
5542 (type2->t & VT_BTYPE) == VT_VOID)
5543 return;
5544 tmp_type1 = *type1;
5545 tmp_type2 = *type2;
5546 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5547 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5548 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5549 /* gcc-like error if '-' is used */
5550 if (op == '-')
5551 goto invalid_operands;
5552 else
5553 warning("comparison of distinct pointer types lacks a cast");
5557 /* generic gen_op: handles types problems */
5558 void gen_op(int op)
5560 int u, t1, t2, bt1, bt2, t;
5561 CType type1;
5563 t1 = vtop[-1].type.t;
5564 t2 = vtop[0].type.t;
5565 bt1 = t1 & VT_BTYPE;
5566 bt2 = t2 & VT_BTYPE;
5568 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5569 /* at least one operand is a pointer */
5570 /* relationnal op: must be both pointers */
5571 if (op >= TOK_ULT && op <= TOK_GT) {
5572 check_comparison_pointer_types(vtop - 1, vtop, op);
5573 /* pointers are handled are unsigned */
5574 t = VT_INT | VT_UNSIGNED;
5575 goto std_op;
5577 /* if both pointers, then it must be the '-' op */
5578 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5579 if (op != '-')
5580 error("cannot use pointers here");
5581 check_comparison_pointer_types(vtop - 1, vtop, op);
5582 /* XXX: check that types are compatible */
5583 u = pointed_size(&vtop[-1].type);
5584 gen_opic(op);
5585 /* set to integer type */
5586 vtop->type.t = VT_INT;
5587 vpushi(u);
5588 gen_op(TOK_PDIV);
5589 } else {
5590 /* exactly one pointer : must be '+' or '-'. */
5591 if (op != '-' && op != '+')
5592 error("cannot use pointers here");
5593 /* Put pointer as first operand */
5594 if (bt2 == VT_PTR) {
5595 vswap();
5596 swap(&t1, &t2);
5598 type1 = vtop[-1].type;
5599 /* XXX: cast to int ? (long long case) */
5600 vpushi(pointed_size(&vtop[-1].type));
5601 gen_op('*');
5602 #ifdef CONFIG_TCC_BCHECK
5603 /* if evaluating constant expression, no code should be
5604 generated, so no bound check */
5605 if (do_bounds_check && !const_wanted) {
5606 /* if bounded pointers, we generate a special code to
5607 test bounds */
5608 if (op == '-') {
5609 vpushi(0);
5610 vswap();
5611 gen_op('-');
5613 gen_bounded_ptr_add();
5614 } else
5615 #endif
5617 gen_opic(op);
5619 /* put again type if gen_opic() swaped operands */
5620 vtop->type = type1;
5622 } else if (is_float(bt1) || is_float(bt2)) {
5623 /* compute bigger type and do implicit casts */
5624 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5625 t = VT_LDOUBLE;
5626 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5627 t = VT_DOUBLE;
5628 } else {
5629 t = VT_FLOAT;
5631 /* floats can only be used for a few operations */
5632 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5633 (op < TOK_ULT || op > TOK_GT))
5634 error("invalid operands for binary operation");
5635 goto std_op;
5636 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5637 /* cast to biggest op */
5638 t = VT_LLONG;
5639 /* convert to unsigned if it does not fit in a long long */
5640 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5641 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5642 t |= VT_UNSIGNED;
5643 goto std_op;
5644 } else {
5645 /* integer operations */
5646 t = VT_INT;
5647 /* convert to unsigned if it does not fit in an integer */
5648 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5649 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5650 t |= VT_UNSIGNED;
5651 std_op:
5652 /* XXX: currently, some unsigned operations are explicit, so
5653 we modify them here */
5654 if (t & VT_UNSIGNED) {
5655 if (op == TOK_SAR)
5656 op = TOK_SHR;
5657 else if (op == '/')
5658 op = TOK_UDIV;
5659 else if (op == '%')
5660 op = TOK_UMOD;
5661 else if (op == TOK_LT)
5662 op = TOK_ULT;
5663 else if (op == TOK_GT)
5664 op = TOK_UGT;
5665 else if (op == TOK_LE)
5666 op = TOK_ULE;
5667 else if (op == TOK_GE)
5668 op = TOK_UGE;
5670 vswap();
5671 type1.t = t;
5672 gen_cast(&type1);
5673 vswap();
5674 /* special case for shifts and long long: we keep the shift as
5675 an integer */
5676 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5677 type1.t = VT_INT;
5678 gen_cast(&type1);
5679 if (is_float(t))
5680 gen_opif(op);
5681 else if ((t & VT_BTYPE) == VT_LLONG)
5682 gen_opl(op);
5683 else
5684 gen_opic(op);
5685 if (op >= TOK_ULT && op <= TOK_GT) {
5686 /* relationnal op: the result is an int */
5687 vtop->type.t = VT_INT;
5688 } else {
5689 vtop->type.t = t;
5694 /* generic itof for unsigned long long case */
5695 void gen_cvt_itof1(int t)
5697 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5698 (VT_LLONG | VT_UNSIGNED)) {
5700 if (t == VT_FLOAT)
5701 vpush_global_sym(&func_old_type, TOK___ulltof);
5702 else if (t == VT_DOUBLE)
5703 vpush_global_sym(&func_old_type, TOK___ulltod);
5704 else
5705 vpush_global_sym(&func_old_type, TOK___ulltold);
5706 vrott(2);
5707 gfunc_call(1);
5708 vpushi(0);
5709 vtop->r = REG_FRET;
5710 } else {
5711 gen_cvt_itof(t);
5715 /* generic ftoi for unsigned long long case */
5716 void gen_cvt_ftoi1(int t)
5718 int st;
5720 if (t == (VT_LLONG | VT_UNSIGNED)) {
5721 /* not handled natively */
5722 st = vtop->type.t & VT_BTYPE;
5723 if (st == VT_FLOAT)
5724 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5725 else if (st == VT_DOUBLE)
5726 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5727 else
5728 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5729 vrott(2);
5730 gfunc_call(1);
5731 vpushi(0);
5732 vtop->r = REG_IRET;
5733 vtop->r2 = REG_LRET;
5734 } else {
5735 gen_cvt_ftoi(t);
5739 /* force char or short cast */
5740 void force_charshort_cast(int t)
5742 int bits, dbt;
5743 dbt = t & VT_BTYPE;
5744 /* XXX: add optimization if lvalue : just change type and offset */
5745 if (dbt == VT_BYTE)
5746 bits = 8;
5747 else
5748 bits = 16;
5749 if (t & VT_UNSIGNED) {
5750 vpushi((1 << bits) - 1);
5751 gen_op('&');
5752 } else {
5753 bits = 32 - bits;
5754 vpushi(bits);
5755 gen_op(TOK_SHL);
5756 vpushi(bits);
5757 gen_op(TOK_SAR);
5761 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5762 static void gen_cast(CType *type)
5764 int sbt, dbt, sf, df, c;
5766 /* special delayed cast for char/short */
5767 /* XXX: in some cases (multiple cascaded casts), it may still
5768 be incorrect */
5769 if (vtop->r & VT_MUSTCAST) {
5770 vtop->r &= ~VT_MUSTCAST;
5771 force_charshort_cast(vtop->type.t);
5774 /* bitfields first get cast to ints */
5775 if (vtop->type.t & VT_BITFIELD) {
5776 gv(RC_INT);
5779 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5780 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5782 if (sbt != dbt && !nocode_wanted) {
5783 sf = is_float(sbt);
5784 df = is_float(dbt);
5785 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5786 if (sf && df) {
5787 /* convert from fp to fp */
5788 if (c) {
5789 /* constant case: we can do it now */
5790 /* XXX: in ISOC, cannot do it if error in convert */
5791 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5792 vtop->c.f = (float)vtop->c.d;
5793 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5794 vtop->c.f = (float)vtop->c.ld;
5795 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5796 vtop->c.d = (double)vtop->c.f;
5797 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5798 vtop->c.d = (double)vtop->c.ld;
5799 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5800 vtop->c.ld = (long double)vtop->c.f;
5801 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5802 vtop->c.ld = (long double)vtop->c.d;
5803 } else {
5804 /* non constant case: generate code */
5805 gen_cvt_ftof(dbt);
5807 } else if (df) {
5808 /* convert int to fp */
5809 if (c) {
5810 switch(sbt) {
5811 case VT_LLONG | VT_UNSIGNED:
5812 case VT_LLONG:
5813 /* XXX: add const cases for long long */
5814 goto do_itof;
5815 case VT_INT | VT_UNSIGNED:
5816 switch(dbt) {
5817 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5818 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5819 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5821 break;
5822 default:
5823 switch(dbt) {
5824 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5825 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5826 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5828 break;
5830 } else {
5831 do_itof:
5832 #if !defined(TCC_TARGET_ARM)
5833 gen_cvt_itof1(dbt);
5834 #else
5835 gen_cvt_itof(dbt);
5836 #endif
5838 } else if (sf) {
5839 /* convert fp to int */
5840 /* we handle char/short/etc... with generic code */
5841 if (dbt != (VT_INT | VT_UNSIGNED) &&
5842 dbt != (VT_LLONG | VT_UNSIGNED) &&
5843 dbt != VT_LLONG)
5844 dbt = VT_INT;
5845 if (c) {
5846 switch(dbt) {
5847 case VT_LLONG | VT_UNSIGNED:
5848 case VT_LLONG:
5849 /* XXX: add const cases for long long */
5850 goto do_ftoi;
5851 case VT_INT | VT_UNSIGNED:
5852 switch(sbt) {
5853 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5854 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5855 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5857 break;
5858 default:
5859 /* int case */
5860 switch(sbt) {
5861 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5862 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5863 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5865 break;
5867 } else {
5868 do_ftoi:
5869 gen_cvt_ftoi1(dbt);
5871 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5872 /* additional cast for char/short/bool... */
5873 vtop->type.t = dbt;
5874 gen_cast(type);
5876 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5877 if ((sbt & VT_BTYPE) != VT_LLONG) {
5878 /* scalar to long long */
5879 if (c) {
5880 if (sbt == (VT_INT | VT_UNSIGNED))
5881 vtop->c.ll = vtop->c.ui;
5882 else
5883 vtop->c.ll = vtop->c.i;
5884 } else {
5885 /* machine independent conversion */
5886 gv(RC_INT);
5887 /* generate high word */
5888 if (sbt == (VT_INT | VT_UNSIGNED)) {
5889 vpushi(0);
5890 gv(RC_INT);
5891 } else {
5892 gv_dup();
5893 vpushi(31);
5894 gen_op(TOK_SAR);
5896 /* patch second register */
5897 vtop[-1].r2 = vtop->r;
5898 vpop();
5901 } else if (dbt == VT_BOOL) {
5902 /* scalar to bool */
5903 vpushi(0);
5904 gen_op(TOK_NE);
5905 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5906 (dbt & VT_BTYPE) == VT_SHORT) {
5907 force_charshort_cast(dbt);
5908 } else if ((dbt & VT_BTYPE) == VT_INT) {
5909 /* scalar to int */
5910 if (sbt == VT_LLONG) {
5911 /* from long long: just take low order word */
5912 lexpand();
5913 vpop();
5915 /* if lvalue and single word type, nothing to do because
5916 the lvalue already contains the real type size (see
5917 VT_LVAL_xxx constants) */
5920 vtop->type = *type;
5923 /* return type size. Put alignment at 'a' */
5924 static int type_size(CType *type, int *a)
5926 Sym *s;
5927 int bt;
5929 bt = type->t & VT_BTYPE;
5930 if (bt == VT_STRUCT) {
5931 /* struct/union */
5932 s = type->ref;
5933 *a = s->r;
5934 return s->c;
5935 } else if (bt == VT_PTR) {
5936 if (type->t & VT_ARRAY) {
5937 s = type->ref;
5938 return type_size(&s->type, a) * s->c;
5939 } else {
5940 *a = PTR_SIZE;
5941 return PTR_SIZE;
5943 } else if (bt == VT_LDOUBLE) {
5944 *a = LDOUBLE_ALIGN;
5945 return LDOUBLE_SIZE;
5946 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5947 #ifdef TCC_TARGET_I386
5948 *a = 4;
5949 #else
5950 *a = 8;
5951 #endif
5952 return 8;
5953 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5954 *a = 4;
5955 return 4;
5956 } else if (bt == VT_SHORT) {
5957 *a = 2;
5958 return 2;
5959 } else {
5960 /* char, void, function, _Bool */
5961 *a = 1;
5962 return 1;
5966 /* return the pointed type of t */
5967 static inline CType *pointed_type(CType *type)
5969 return &type->ref->type;
5972 /* modify type so that its it is a pointer to type. */
5973 static void mk_pointer(CType *type)
5975 Sym *s;
5976 s = sym_push(SYM_FIELD, type, 0, -1);
5977 type->t = VT_PTR | (type->t & ~VT_TYPE);
5978 type->ref = s;
5981 /* compare function types. OLD functions match any new functions */
5982 static int is_compatible_func(CType *type1, CType *type2)
5984 Sym *s1, *s2;
5986 s1 = type1->ref;
5987 s2 = type2->ref;
5988 if (!is_compatible_types(&s1->type, &s2->type))
5989 return 0;
5990 /* check func_call */
5991 if (s1->r != s2->r)
5992 return 0;
5993 /* XXX: not complete */
5994 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5995 return 1;
5996 if (s1->c != s2->c)
5997 return 0;
5998 while (s1 != NULL) {
5999 if (s2 == NULL)
6000 return 0;
6001 if (!is_compatible_types(&s1->type, &s2->type))
6002 return 0;
6003 s1 = s1->next;
6004 s2 = s2->next;
6006 if (s2)
6007 return 0;
6008 return 1;
6011 /* return true if type1 and type2 are exactly the same (including
6012 qualifiers).
6014 - enums are not checked as gcc __builtin_types_compatible_p ()
6016 static int is_compatible_types(CType *type1, CType *type2)
6018 int bt1, t1, t2;
6020 t1 = type1->t & VT_TYPE;
6021 t2 = type2->t & VT_TYPE;
6022 /* XXX: bitfields ? */
6023 if (t1 != t2)
6024 return 0;
6025 /* test more complicated cases */
6026 bt1 = t1 & VT_BTYPE;
6027 if (bt1 == VT_PTR) {
6028 type1 = pointed_type(type1);
6029 type2 = pointed_type(type2);
6030 return is_compatible_types(type1, type2);
6031 } else if (bt1 == VT_STRUCT) {
6032 return (type1->ref == type2->ref);
6033 } else if (bt1 == VT_FUNC) {
6034 return is_compatible_func(type1, type2);
6035 } else {
6036 return 1;
6040 /* print a type. If 'varstr' is not NULL, then the variable is also
6041 printed in the type */
6042 /* XXX: union */
6043 /* XXX: add array and function pointers */
6044 void type_to_str(char *buf, int buf_size,
6045 CType *type, const char *varstr)
6047 int bt, v, t;
6048 Sym *s, *sa;
6049 char buf1[256];
6050 const char *tstr;
6052 t = type->t & VT_TYPE;
6053 bt = t & VT_BTYPE;
6054 buf[0] = '\0';
6055 if (t & VT_CONSTANT)
6056 pstrcat(buf, buf_size, "const ");
6057 if (t & VT_VOLATILE)
6058 pstrcat(buf, buf_size, "volatile ");
6059 if (t & VT_UNSIGNED)
6060 pstrcat(buf, buf_size, "unsigned ");
6061 switch(bt) {
6062 case VT_VOID:
6063 tstr = "void";
6064 goto add_tstr;
6065 case VT_BOOL:
6066 tstr = "_Bool";
6067 goto add_tstr;
6068 case VT_BYTE:
6069 tstr = "char";
6070 goto add_tstr;
6071 case VT_SHORT:
6072 tstr = "short";
6073 goto add_tstr;
6074 case VT_INT:
6075 tstr = "int";
6076 goto add_tstr;
6077 case VT_LONG:
6078 tstr = "long";
6079 goto add_tstr;
6080 case VT_LLONG:
6081 tstr = "long long";
6082 goto add_tstr;
6083 case VT_FLOAT:
6084 tstr = "float";
6085 goto add_tstr;
6086 case VT_DOUBLE:
6087 tstr = "double";
6088 goto add_tstr;
6089 case VT_LDOUBLE:
6090 tstr = "long double";
6091 add_tstr:
6092 pstrcat(buf, buf_size, tstr);
6093 break;
6094 case VT_ENUM:
6095 case VT_STRUCT:
6096 if (bt == VT_STRUCT)
6097 tstr = "struct ";
6098 else
6099 tstr = "enum ";
6100 pstrcat(buf, buf_size, tstr);
6101 v = type->ref->v & ~SYM_STRUCT;
6102 if (v >= SYM_FIRST_ANOM)
6103 pstrcat(buf, buf_size, "<anonymous>");
6104 else
6105 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6106 break;
6107 case VT_FUNC:
6108 s = type->ref;
6109 type_to_str(buf, buf_size, &s->type, varstr);
6110 pstrcat(buf, buf_size, "(");
6111 sa = s->next;
6112 while (sa != NULL) {
6113 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6114 pstrcat(buf, buf_size, buf1);
6115 sa = sa->next;
6116 if (sa)
6117 pstrcat(buf, buf_size, ", ");
6119 pstrcat(buf, buf_size, ")");
6120 goto no_var;
6121 case VT_PTR:
6122 s = type->ref;
6123 pstrcpy(buf1, sizeof(buf1), "*");
6124 if (varstr)
6125 pstrcat(buf1, sizeof(buf1), varstr);
6126 type_to_str(buf, buf_size, &s->type, buf1);
6127 goto no_var;
6129 if (varstr) {
6130 pstrcat(buf, buf_size, " ");
6131 pstrcat(buf, buf_size, varstr);
6133 no_var: ;
6136 /* verify type compatibility to store vtop in 'dt' type, and generate
6137 casts if needed. */
6138 static void gen_assign_cast(CType *dt)
6140 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6141 char buf1[256], buf2[256];
6142 int dbt, sbt;
6144 st = &vtop->type; /* source type */
6145 dbt = dt->t & VT_BTYPE;
6146 sbt = st->t & VT_BTYPE;
6147 if (dt->t & VT_CONSTANT)
6148 warning("assignment of read-only location");
6149 switch(dbt) {
6150 case VT_PTR:
6151 /* special cases for pointers */
6152 /* '0' can also be a pointer */
6153 if (is_null_pointer(vtop))
6154 goto type_ok;
6155 /* accept implicit pointer to integer cast with warning */
6156 if (is_integer_btype(sbt)) {
6157 warning("assignment makes pointer from integer without a cast");
6158 goto type_ok;
6160 type1 = pointed_type(dt);
6161 /* a function is implicitely a function pointer */
6162 if (sbt == VT_FUNC) {
6163 if ((type1->t & VT_BTYPE) != VT_VOID &&
6164 !is_compatible_types(pointed_type(dt), st))
6165 goto error;
6166 else
6167 goto type_ok;
6169 if (sbt != VT_PTR)
6170 goto error;
6171 type2 = pointed_type(st);
6172 if ((type1->t & VT_BTYPE) == VT_VOID ||
6173 (type2->t & VT_BTYPE) == VT_VOID) {
6174 /* void * can match anything */
6175 } else {
6176 /* exact type match, except for unsigned */
6177 tmp_type1 = *type1;
6178 tmp_type2 = *type2;
6179 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6180 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6181 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6182 goto error;
6184 /* check const and volatile */
6185 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6186 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6187 warning("assignment discards qualifiers from pointer target type");
6188 break;
6189 case VT_BYTE:
6190 case VT_SHORT:
6191 case VT_INT:
6192 case VT_LLONG:
6193 if (sbt == VT_PTR || sbt == VT_FUNC) {
6194 warning("assignment makes integer from pointer without a cast");
6196 /* XXX: more tests */
6197 break;
6198 case VT_STRUCT:
6199 tmp_type1 = *dt;
6200 tmp_type2 = *st;
6201 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6202 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6203 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6204 error:
6205 type_to_str(buf1, sizeof(buf1), st, NULL);
6206 type_to_str(buf2, sizeof(buf2), dt, NULL);
6207 error("cannot cast '%s' to '%s'", buf1, buf2);
6209 break;
6211 type_ok:
6212 gen_cast(dt);
6215 /* store vtop in lvalue pushed on stack */
6216 void vstore(void)
6218 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6220 ft = vtop[-1].type.t;
6221 sbt = vtop->type.t & VT_BTYPE;
6222 dbt = ft & VT_BTYPE;
6223 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6224 (sbt == VT_INT && dbt == VT_SHORT)) {
6225 /* optimize char/short casts */
6226 delayed_cast = VT_MUSTCAST;
6227 vtop->type.t = ft & VT_TYPE;
6228 /* XXX: factorize */
6229 if (ft & VT_CONSTANT)
6230 warning("assignment of read-only location");
6231 } else {
6232 delayed_cast = 0;
6233 if (!(ft & VT_BITFIELD))
6234 gen_assign_cast(&vtop[-1].type);
6237 if (sbt == VT_STRUCT) {
6238 /* if structure, only generate pointer */
6239 /* structure assignment : generate memcpy */
6240 /* XXX: optimize if small size */
6241 if (!nocode_wanted) {
6242 size = type_size(&vtop->type, &align);
6244 vpush_global_sym(&func_old_type, TOK_memcpy);
6246 /* destination */
6247 vpushv(vtop - 2);
6248 vtop->type.t = VT_INT;
6249 gaddrof();
6250 /* source */
6251 vpushv(vtop - 2);
6252 vtop->type.t = VT_INT;
6253 gaddrof();
6254 /* type size */
6255 vpushi(size);
6256 gfunc_call(3);
6258 vswap();
6259 vpop();
6260 } else {
6261 vswap();
6262 vpop();
6264 /* leave source on stack */
6265 } else if (ft & VT_BITFIELD) {
6266 /* bitfield store handling */
6267 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6268 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6269 /* remove bit field info to avoid loops */
6270 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6272 /* duplicate destination */
6273 vdup();
6274 vtop[-1] = vtop[-2];
6276 /* mask and shift source */
6277 vpushi((1 << bit_size) - 1);
6278 gen_op('&');
6279 vpushi(bit_pos);
6280 gen_op(TOK_SHL);
6281 /* load destination, mask and or with source */
6282 vswap();
6283 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6284 gen_op('&');
6285 gen_op('|');
6286 /* store result */
6287 vstore();
6288 } else {
6289 #ifdef CONFIG_TCC_BCHECK
6290 /* bound check case */
6291 if (vtop[-1].r & VT_MUSTBOUND) {
6292 vswap();
6293 gbound();
6294 vswap();
6296 #endif
6297 if (!nocode_wanted) {
6298 rc = RC_INT;
6299 if (is_float(ft))
6300 rc = RC_FLOAT;
6301 r = gv(rc); /* generate value */
6302 /* if lvalue was saved on stack, must read it */
6303 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6304 SValue sv;
6305 t = get_reg(RC_INT);
6306 sv.type.t = VT_INT;
6307 sv.r = VT_LOCAL | VT_LVAL;
6308 sv.c.ul = vtop[-1].c.ul;
6309 load(t, &sv);
6310 vtop[-1].r = t | VT_LVAL;
6312 store(r, vtop - 1);
6313 /* two word case handling : store second register at word + 4 */
6314 if ((ft & VT_BTYPE) == VT_LLONG) {
6315 vswap();
6316 /* convert to int to increment easily */
6317 vtop->type.t = VT_INT;
6318 gaddrof();
6319 vpushi(4);
6320 gen_op('+');
6321 vtop->r |= VT_LVAL;
6322 vswap();
6323 /* XXX: it works because r2 is spilled last ! */
6324 store(vtop->r2, vtop - 1);
6327 vswap();
6328 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6329 vtop->r |= delayed_cast;
6333 /* post defines POST/PRE add. c is the token ++ or -- */
6334 void inc(int post, int c)
6336 test_lvalue();
6337 vdup(); /* save lvalue */
6338 if (post) {
6339 gv_dup(); /* duplicate value */
6340 vrotb(3);
6341 vrotb(3);
6343 /* add constant */
6344 vpushi(c - TOK_MID);
6345 gen_op('+');
6346 vstore(); /* store value */
6347 if (post)
6348 vpop(); /* if post op, return saved value */
6351 /* Parse GNUC __attribute__ extension. Currently, the following
6352 extensions are recognized:
6353 - aligned(n) : set data/function alignment.
6354 - packed : force data alignment to 1
6355 - section(x) : generate data/code in this section.
6356 - unused : currently ignored, but may be used someday.
6357 - regparm(n) : pass function parameters in registers (i386 only)
6359 static void parse_attribute(AttributeDef *ad)
6361 int t, n;
6363 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6364 next();
6365 skip('(');
6366 skip('(');
6367 while (tok != ')') {
6368 if (tok < TOK_IDENT)
6369 expect("attribute name");
6370 t = tok;
6371 next();
6372 switch(t) {
6373 case TOK_SECTION1:
6374 case TOK_SECTION2:
6375 skip('(');
6376 if (tok != TOK_STR)
6377 expect("section name");
6378 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6379 next();
6380 skip(')');
6381 break;
6382 case TOK_ALIGNED1:
6383 case TOK_ALIGNED2:
6384 if (tok == '(') {
6385 next();
6386 n = expr_const();
6387 if (n <= 0 || (n & (n - 1)) != 0)
6388 error("alignment must be a positive power of two");
6389 skip(')');
6390 } else {
6391 n = MAX_ALIGN;
6393 ad->aligned = n;
6394 break;
6395 case TOK_PACKED1:
6396 case TOK_PACKED2:
6397 ad->packed = 1;
6398 break;
6399 case TOK_UNUSED1:
6400 case TOK_UNUSED2:
6401 /* currently, no need to handle it because tcc does not
6402 track unused objects */
6403 break;
6404 case TOK_NORETURN1:
6405 case TOK_NORETURN2:
6406 /* currently, no need to handle it because tcc does not
6407 track unused objects */
6408 break;
6409 case TOK_CDECL1:
6410 case TOK_CDECL2:
6411 case TOK_CDECL3:
6412 ad->func_call = FUNC_CDECL;
6413 break;
6414 case TOK_STDCALL1:
6415 case TOK_STDCALL2:
6416 case TOK_STDCALL3:
6417 ad->func_call = FUNC_STDCALL;
6418 break;
6419 #ifdef TCC_TARGET_I386
6420 case TOK_REGPARM1:
6421 case TOK_REGPARM2:
6422 skip('(');
6423 n = expr_const();
6424 if (n > 3)
6425 n = 3;
6426 else if (n < 0)
6427 n = 0;
6428 if (n > 0)
6429 ad->func_call = FUNC_FASTCALL1 + n - 1;
6430 skip(')');
6431 break;
6432 case TOK_FASTCALL1:
6433 case TOK_FASTCALL2:
6434 case TOK_FASTCALL3:
6435 ad->func_call = FUNC_FASTCALLW;
6436 break;
6437 #endif
6438 case TOK_DLLEXPORT:
6439 ad->dllexport = 1;
6440 break;
6441 default:
6442 if (tcc_state->warn_unsupported)
6443 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6444 /* skip parameters */
6445 /* XXX: skip parenthesis too */
6446 if (tok == '(') {
6447 next();
6448 while (tok != ')' && tok != -1)
6449 next();
6450 next();
6452 break;
6454 if (tok != ',')
6455 break;
6456 next();
6458 skip(')');
6459 skip(')');
6463 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6464 static void struct_decl(CType *type, int u)
6466 int a, v, size, align, maxalign, c, offset;
6467 int bit_size, bit_pos, bsize, bt, lbit_pos;
6468 Sym *s, *ss, *ass, **ps;
6469 AttributeDef ad;
6470 CType type1, btype;
6472 a = tok; /* save decl type */
6473 next();
6474 if (tok != '{') {
6475 v = tok;
6476 next();
6477 /* struct already defined ? return it */
6478 if (v < TOK_IDENT)
6479 expect("struct/union/enum name");
6480 s = struct_find(v);
6481 if (s) {
6482 if (s->type.t != a)
6483 error("invalid type");
6484 goto do_decl;
6486 } else {
6487 v = anon_sym++;
6489 type1.t = a;
6490 /* we put an undefined size for struct/union */
6491 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6492 s->r = 0; /* default alignment is zero as gcc */
6493 /* put struct/union/enum name in type */
6494 do_decl:
6495 type->t = u;
6496 type->ref = s;
6498 if (tok == '{') {
6499 next();
6500 if (s->c != -1)
6501 error("struct/union/enum already defined");
6502 /* cannot be empty */
6503 c = 0;
6504 /* non empty enums are not allowed */
6505 if (a == TOK_ENUM) {
6506 for(;;) {
6507 v = tok;
6508 if (v < TOK_UIDENT)
6509 expect("identifier");
6510 next();
6511 if (tok == '=') {
6512 next();
6513 c = expr_const();
6515 /* enum symbols have static storage */
6516 ss = sym_push(v, &int_type, VT_CONST, c);
6517 ss->type.t |= VT_STATIC;
6518 if (tok != ',')
6519 break;
6520 next();
6521 c++;
6522 /* NOTE: we accept a trailing comma */
6523 if (tok == '}')
6524 break;
6526 skip('}');
6527 } else {
6528 maxalign = 1;
6529 ps = &s->next;
6530 bit_pos = 0;
6531 offset = 0;
6532 while (tok != '}') {
6533 parse_btype(&btype, &ad);
6534 while (1) {
6535 bit_size = -1;
6536 v = 0;
6537 type1 = btype;
6538 if (tok != ':') {
6539 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6540 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6541 expect("identifier");
6542 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6543 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6544 error("invalid type for '%s'",
6545 get_tok_str(v, NULL));
6547 if (tok == ':') {
6548 next();
6549 bit_size = expr_const();
6550 /* XXX: handle v = 0 case for messages */
6551 if (bit_size < 0)
6552 error("negative width in bit-field '%s'",
6553 get_tok_str(v, NULL));
6554 if (v && bit_size == 0)
6555 error("zero width for bit-field '%s'",
6556 get_tok_str(v, NULL));
6558 size = type_size(&type1, &align);
6559 if (ad.aligned) {
6560 if (align < ad.aligned)
6561 align = ad.aligned;
6562 } else if (ad.packed) {
6563 align = 1;
6564 } else if (*tcc_state->pack_stack_ptr) {
6565 if (align > *tcc_state->pack_stack_ptr)
6566 align = *tcc_state->pack_stack_ptr;
6568 lbit_pos = 0;
6569 if (bit_size >= 0) {
6570 bt = type1.t & VT_BTYPE;
6571 if (bt != VT_INT &&
6572 bt != VT_BYTE &&
6573 bt != VT_SHORT &&
6574 bt != VT_BOOL &&
6575 bt != VT_ENUM)
6576 error("bitfields must have scalar type");
6577 bsize = size * 8;
6578 if (bit_size > bsize) {
6579 error("width of '%s' exceeds its type",
6580 get_tok_str(v, NULL));
6581 } else if (bit_size == bsize) {
6582 /* no need for bit fields */
6583 bit_pos = 0;
6584 } else if (bit_size == 0) {
6585 /* XXX: what to do if only padding in a
6586 structure ? */
6587 /* zero size: means to pad */
6588 if (bit_pos > 0)
6589 bit_pos = bsize;
6590 } else {
6591 /* we do not have enough room ? */
6592 if ((bit_pos + bit_size) > bsize)
6593 bit_pos = 0;
6594 lbit_pos = bit_pos;
6595 /* XXX: handle LSB first */
6596 type1.t |= VT_BITFIELD |
6597 (bit_pos << VT_STRUCT_SHIFT) |
6598 (bit_size << (VT_STRUCT_SHIFT + 6));
6599 bit_pos += bit_size;
6601 } else {
6602 bit_pos = 0;
6604 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
6605 /* add new memory data only if starting
6606 bit field */
6607 if (lbit_pos == 0) {
6608 if (a == TOK_STRUCT) {
6609 c = (c + align - 1) & -align;
6610 offset = c;
6611 c += size;
6612 } else {
6613 offset = 0;
6614 if (size > c)
6615 c = size;
6617 if (align > maxalign)
6618 maxalign = align;
6620 #if 0
6621 printf("add field %s offset=%d",
6622 get_tok_str(v, NULL), offset);
6623 if (type1.t & VT_BITFIELD) {
6624 printf(" pos=%d size=%d",
6625 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6626 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6628 printf("\n");
6629 #endif
6631 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
6632 ass = type1.ref;
6633 while ((ass = ass->next) != NULL) {
6634 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
6635 *ps = ss;
6636 ps = &ss->next;
6638 } else if (v) {
6639 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6640 *ps = ss;
6641 ps = &ss->next;
6643 if (tok == ';' || tok == TOK_EOF)
6644 break;
6645 skip(',');
6647 skip(';');
6649 skip('}');
6650 /* store size and alignment */
6651 s->c = (c + maxalign - 1) & -maxalign;
6652 s->r = maxalign;
6657 /* return 0 if no type declaration. otherwise, return the basic type
6658 and skip it.
6660 static int parse_btype(CType *type, AttributeDef *ad)
6662 int t, u, type_found, typespec_found;
6663 Sym *s;
6664 CType type1;
6666 memset(ad, 0, sizeof(AttributeDef));
6667 type_found = 0;
6668 typespec_found = 0;
6669 t = 0;
6670 while(1) {
6671 switch(tok) {
6672 case TOK_EXTENSION:
6673 /* currently, we really ignore extension */
6674 next();
6675 continue;
6677 /* basic types */
6678 case TOK_CHAR:
6679 u = VT_BYTE;
6680 basic_type:
6681 next();
6682 basic_type1:
6683 if ((t & VT_BTYPE) != 0)
6684 error("too many basic types");
6685 t |= u;
6686 typespec_found = 1;
6687 break;
6688 case TOK_VOID:
6689 u = VT_VOID;
6690 goto basic_type;
6691 case TOK_SHORT:
6692 u = VT_SHORT;
6693 goto basic_type;
6694 case TOK_INT:
6695 next();
6696 typespec_found = 1;
6697 break;
6698 case TOK_LONG:
6699 next();
6700 if ((t & VT_BTYPE) == VT_DOUBLE) {
6701 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6702 } else if ((t & VT_BTYPE) == VT_LONG) {
6703 t = (t & ~VT_BTYPE) | VT_LLONG;
6704 } else {
6705 u = VT_LONG;
6706 goto basic_type1;
6708 break;
6709 case TOK_BOOL:
6710 u = VT_BOOL;
6711 goto basic_type;
6712 case TOK_FLOAT:
6713 u = VT_FLOAT;
6714 goto basic_type;
6715 case TOK_DOUBLE:
6716 next();
6717 if ((t & VT_BTYPE) == VT_LONG) {
6718 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6719 } else {
6720 u = VT_DOUBLE;
6721 goto basic_type1;
6723 break;
6724 case TOK_ENUM:
6725 struct_decl(&type1, VT_ENUM);
6726 basic_type2:
6727 u = type1.t;
6728 type->ref = type1.ref;
6729 goto basic_type1;
6730 case TOK_STRUCT:
6731 case TOK_UNION:
6732 struct_decl(&type1, VT_STRUCT);
6733 goto basic_type2;
6735 /* type modifiers */
6736 case TOK_CONST1:
6737 case TOK_CONST2:
6738 case TOK_CONST3:
6739 t |= VT_CONSTANT;
6740 next();
6741 break;
6742 case TOK_VOLATILE1:
6743 case TOK_VOLATILE2:
6744 case TOK_VOLATILE3:
6745 t |= VT_VOLATILE;
6746 next();
6747 break;
6748 case TOK_SIGNED1:
6749 case TOK_SIGNED2:
6750 case TOK_SIGNED3:
6751 typespec_found = 1;
6752 t |= VT_SIGNED;
6753 next();
6754 break;
6755 case TOK_REGISTER:
6756 case TOK_AUTO:
6757 case TOK_RESTRICT1:
6758 case TOK_RESTRICT2:
6759 case TOK_RESTRICT3:
6760 next();
6761 break;
6762 case TOK_UNSIGNED:
6763 t |= VT_UNSIGNED;
6764 next();
6765 typespec_found = 1;
6766 break;
6768 /* storage */
6769 case TOK_EXTERN:
6770 t |= VT_EXTERN;
6771 next();
6772 break;
6773 case TOK_STATIC:
6774 t |= VT_STATIC;
6775 next();
6776 break;
6777 case TOK_TYPEDEF:
6778 t |= VT_TYPEDEF;
6779 next();
6780 break;
6781 case TOK_INLINE1:
6782 case TOK_INLINE2:
6783 case TOK_INLINE3:
6784 t |= VT_INLINE;
6785 next();
6786 break;
6788 /* GNUC attribute */
6789 case TOK_ATTRIBUTE1:
6790 case TOK_ATTRIBUTE2:
6791 parse_attribute(ad);
6792 break;
6793 /* GNUC typeof */
6794 case TOK_TYPEOF1:
6795 case TOK_TYPEOF2:
6796 case TOK_TYPEOF3:
6797 next();
6798 parse_expr_type(&type1);
6799 goto basic_type2;
6800 default:
6801 if (typespec_found)
6802 goto the_end;
6803 s = sym_find(tok);
6804 if (!s || !(s->type.t & VT_TYPEDEF))
6805 goto the_end;
6806 t |= (s->type.t & ~VT_TYPEDEF);
6807 type->ref = s->type.ref;
6808 next();
6809 break;
6811 type_found = 1;
6813 the_end:
6814 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6815 error("signed and unsigned modifier");
6816 if (tcc_state->char_is_unsigned) {
6817 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6818 t |= VT_UNSIGNED;
6820 t &= ~VT_SIGNED;
6822 /* long is never used as type */
6823 if ((t & VT_BTYPE) == VT_LONG)
6824 t = (t & ~VT_BTYPE) | VT_INT;
6825 type->t = t;
6826 return type_found;
6829 /* convert a function parameter type (array to pointer and function to
6830 function pointer) */
6831 static inline void convert_parameter_type(CType *pt)
6833 /* remove const and volatile qualifiers (XXX: const could be used
6834 to indicate a const function parameter */
6835 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6836 /* array must be transformed to pointer according to ANSI C */
6837 pt->t &= ~VT_ARRAY;
6838 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6839 mk_pointer(pt);
6843 static void post_type(CType *type, AttributeDef *ad)
6845 int n, l, t1;
6846 Sym **plast, *s, *first;
6847 AttributeDef ad1;
6848 CType pt;
6850 if (tok == '(') {
6851 /* function declaration */
6852 next();
6853 l = 0;
6854 first = NULL;
6855 plast = &first;
6856 if (tok != ')') {
6857 for(;;) {
6858 /* read param name and compute offset */
6859 if (l != FUNC_OLD) {
6860 if (!parse_btype(&pt, &ad1)) {
6861 if (l) {
6862 error("invalid type");
6863 } else {
6864 l = FUNC_OLD;
6865 goto old_proto;
6868 l = FUNC_NEW;
6869 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6870 break;
6871 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6872 if ((pt.t & VT_BTYPE) == VT_VOID)
6873 error("parameter declared as void");
6874 } else {
6875 old_proto:
6876 n = tok;
6877 if (n < TOK_UIDENT)
6878 expect("identifier");
6879 pt.t = VT_INT;
6880 next();
6882 convert_parameter_type(&pt);
6883 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6884 *plast = s;
6885 plast = &s->next;
6886 if (tok == ')')
6887 break;
6888 skip(',');
6889 if (l == FUNC_NEW && tok == TOK_DOTS) {
6890 l = FUNC_ELLIPSIS;
6891 next();
6892 break;
6896 /* if no parameters, then old type prototype */
6897 if (l == 0)
6898 l = FUNC_OLD;
6899 skip(')');
6900 t1 = type->t & VT_STORAGE;
6901 /* NOTE: const is ignored in returned type as it has a special
6902 meaning in gcc / C++ */
6903 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6904 post_type(type, ad);
6905 /* we push a anonymous symbol which will contain the function prototype */
6906 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6907 s->next = first;
6908 type->t = t1 | VT_FUNC;
6909 type->ref = s;
6910 } else if (tok == '[') {
6911 /* array definition */
6912 next();
6913 n = -1;
6914 if (tok != ']') {
6915 n = expr_const();
6916 if (n < 0)
6917 error("invalid array size");
6919 skip(']');
6920 /* parse next post type */
6921 t1 = type->t & VT_STORAGE;
6922 type->t &= ~VT_STORAGE;
6923 post_type(type, ad);
6925 /* we push a anonymous symbol which will contain the array
6926 element type */
6927 s = sym_push(SYM_FIELD, type, 0, n);
6928 type->t = t1 | VT_ARRAY | VT_PTR;
6929 type->ref = s;
6933 /* Parse a type declaration (except basic type), and return the type
6934 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6935 expected. 'type' should contain the basic type. 'ad' is the
6936 attribute definition of the basic type. It can be modified by
6937 type_decl().
6939 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6941 Sym *s;
6942 CType type1, *type2;
6943 int qualifiers;
6945 while (tok == '*') {
6946 qualifiers = 0;
6947 redo:
6948 next();
6949 switch(tok) {
6950 case TOK_CONST1:
6951 case TOK_CONST2:
6952 case TOK_CONST3:
6953 qualifiers |= VT_CONSTANT;
6954 goto redo;
6955 case TOK_VOLATILE1:
6956 case TOK_VOLATILE2:
6957 case TOK_VOLATILE3:
6958 qualifiers |= VT_VOLATILE;
6959 goto redo;
6960 case TOK_RESTRICT1:
6961 case TOK_RESTRICT2:
6962 case TOK_RESTRICT3:
6963 goto redo;
6965 mk_pointer(type);
6966 type->t |= qualifiers;
6969 /* XXX: clarify attribute handling */
6970 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6971 parse_attribute(ad);
6973 /* recursive type */
6974 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6975 type1.t = 0; /* XXX: same as int */
6976 if (tok == '(') {
6977 next();
6978 /* XXX: this is not correct to modify 'ad' at this point, but
6979 the syntax is not clear */
6980 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6981 parse_attribute(ad);
6982 type_decl(&type1, ad, v, td);
6983 skip(')');
6984 } else {
6985 /* type identifier */
6986 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6987 *v = tok;
6988 next();
6989 } else {
6990 if (!(td & TYPE_ABSTRACT))
6991 expect("identifier");
6992 *v = 0;
6995 post_type(type, ad);
6996 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6997 parse_attribute(ad);
6998 if (!type1.t)
6999 return;
7000 /* append type at the end of type1 */
7001 type2 = &type1;
7002 for(;;) {
7003 s = type2->ref;
7004 type2 = &s->type;
7005 if (!type2->t) {
7006 *type2 = *type;
7007 break;
7010 *type = type1;
7013 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7014 static int lvalue_type(int t)
7016 int bt, r;
7017 r = VT_LVAL;
7018 bt = t & VT_BTYPE;
7019 if (bt == VT_BYTE || bt == VT_BOOL)
7020 r |= VT_LVAL_BYTE;
7021 else if (bt == VT_SHORT)
7022 r |= VT_LVAL_SHORT;
7023 else
7024 return r;
7025 if (t & VT_UNSIGNED)
7026 r |= VT_LVAL_UNSIGNED;
7027 return r;
7030 /* indirection with full error checking and bound check */
7031 static void indir(void)
7033 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7034 expect("pointer");
7035 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7036 gv(RC_INT);
7037 vtop->type = *pointed_type(&vtop->type);
7038 /* an array is never an lvalue */
7039 if (!(vtop->type.t & VT_ARRAY)) {
7040 vtop->r |= lvalue_type(vtop->type.t);
7041 /* if bound checking, the referenced pointer must be checked */
7042 if (do_bounds_check)
7043 vtop->r |= VT_MUSTBOUND;
7047 /* pass a parameter to a function and do type checking and casting */
7048 static void gfunc_param_typed(Sym *func, Sym *arg)
7050 int func_type;
7051 CType type;
7053 func_type = func->c;
7054 if (func_type == FUNC_OLD ||
7055 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7056 /* default casting : only need to convert float to double */
7057 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7058 type.t = VT_DOUBLE;
7059 gen_cast(&type);
7061 } else if (arg == NULL) {
7062 error("too many arguments to function");
7063 } else {
7064 type = arg->type;
7065 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7066 gen_assign_cast(&type);
7070 /* parse an expression of the form '(type)' or '(expr)' and return its
7071 type */
7072 static void parse_expr_type(CType *type)
7074 int n;
7075 AttributeDef ad;
7077 skip('(');
7078 if (parse_btype(type, &ad)) {
7079 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7080 } else {
7081 expr_type(type);
7083 skip(')');
7086 static void parse_type(CType *type)
7088 AttributeDef ad;
7089 int n;
7091 if (!parse_btype(type, &ad)) {
7092 expect("type");
7094 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7097 static void vpush_tokc(int t)
7099 CType type;
7100 type.t = t;
7101 vsetc(&type, VT_CONST, &tokc);
7104 static void unary(void)
7106 int n, t, align, size, r;
7107 CType type;
7108 Sym *s;
7109 AttributeDef ad;
7111 /* XXX: GCC 2.95.3 does not generate a table although it should be
7112 better here */
7113 tok_next:
7114 switch(tok) {
7115 case TOK_EXTENSION:
7116 next();
7117 goto tok_next;
7118 case TOK_CINT:
7119 case TOK_CCHAR:
7120 case TOK_LCHAR:
7121 vpushi(tokc.i);
7122 next();
7123 break;
7124 case TOK_CUINT:
7125 vpush_tokc(VT_INT | VT_UNSIGNED);
7126 next();
7127 break;
7128 case TOK_CLLONG:
7129 vpush_tokc(VT_LLONG);
7130 next();
7131 break;
7132 case TOK_CULLONG:
7133 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7134 next();
7135 break;
7136 case TOK_CFLOAT:
7137 vpush_tokc(VT_FLOAT);
7138 next();
7139 break;
7140 case TOK_CDOUBLE:
7141 vpush_tokc(VT_DOUBLE);
7142 next();
7143 break;
7144 case TOK_CLDOUBLE:
7145 vpush_tokc(VT_LDOUBLE);
7146 next();
7147 break;
7148 case TOK___FUNCTION__:
7149 if (!gnu_ext)
7150 goto tok_identifier;
7151 /* fall thru */
7152 case TOK___FUNC__:
7154 void *ptr;
7155 int len;
7156 /* special function name identifier */
7157 len = strlen(funcname) + 1;
7158 /* generate char[len] type */
7159 type.t = VT_BYTE;
7160 mk_pointer(&type);
7161 type.t |= VT_ARRAY;
7162 type.ref->c = len;
7163 vpush_ref(&type, data_section, data_section->data_offset, len);
7164 ptr = section_ptr_add(data_section, len);
7165 memcpy(ptr, funcname, len);
7166 next();
7168 break;
7169 case TOK_LSTR:
7170 #ifdef TCC_TARGET_PE
7171 t = VT_SHORT | VT_UNSIGNED;
7172 #else
7173 t = VT_INT;
7174 #endif
7175 goto str_init;
7176 case TOK_STR:
7177 /* string parsing */
7178 t = VT_BYTE;
7179 str_init:
7180 if (tcc_state->warn_write_strings)
7181 t |= VT_CONSTANT;
7182 type.t = t;
7183 mk_pointer(&type);
7184 type.t |= VT_ARRAY;
7185 memset(&ad, 0, sizeof(AttributeDef));
7186 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7187 break;
7188 case '(':
7189 next();
7190 /* cast ? */
7191 if (parse_btype(&type, &ad)) {
7192 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7193 skip(')');
7194 /* check ISOC99 compound literal */
7195 if (tok == '{') {
7196 /* data is allocated locally by default */
7197 if (global_expr)
7198 r = VT_CONST;
7199 else
7200 r = VT_LOCAL;
7201 /* all except arrays are lvalues */
7202 if (!(type.t & VT_ARRAY))
7203 r |= lvalue_type(type.t);
7204 memset(&ad, 0, sizeof(AttributeDef));
7205 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7206 } else {
7207 unary();
7208 gen_cast(&type);
7210 } else if (tok == '{') {
7211 /* save all registers */
7212 save_regs(0);
7213 /* statement expression : we do not accept break/continue
7214 inside as GCC does */
7215 block(NULL, NULL, NULL, NULL, 0, 1);
7216 skip(')');
7217 } else {
7218 gexpr();
7219 skip(')');
7221 break;
7222 case '*':
7223 next();
7224 unary();
7225 indir();
7226 break;
7227 case '&':
7228 next();
7229 unary();
7230 /* functions names must be treated as function pointers,
7231 except for unary '&' and sizeof. Since we consider that
7232 functions are not lvalues, we only have to handle it
7233 there and in function calls. */
7234 /* arrays can also be used although they are not lvalues */
7235 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7236 !(vtop->type.t & VT_ARRAY))
7237 test_lvalue();
7238 mk_pointer(&vtop->type);
7239 gaddrof();
7240 break;
7241 case '!':
7242 next();
7243 unary();
7244 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7245 vtop->c.i = !vtop->c.i;
7246 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7247 vtop->c.i = vtop->c.i ^ 1;
7248 else
7249 vseti(VT_JMP, gtst(1, 0));
7250 break;
7251 case '~':
7252 next();
7253 unary();
7254 vpushi(-1);
7255 gen_op('^');
7256 break;
7257 case '+':
7258 next();
7259 /* in order to force cast, we add zero */
7260 unary();
7261 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7262 error("pointer not accepted for unary plus");
7263 vpushi(0);
7264 gen_op('+');
7265 break;
7266 case TOK_SIZEOF:
7267 case TOK_ALIGNOF1:
7268 case TOK_ALIGNOF2:
7269 t = tok;
7270 next();
7271 if (tok == '(') {
7272 parse_expr_type(&type);
7273 } else {
7274 unary_type(&type);
7276 size = type_size(&type, &align);
7277 if (t == TOK_SIZEOF) {
7278 if (size < 0)
7279 error("sizeof applied to an incomplete type");
7280 vpushi(size);
7281 } else {
7282 vpushi(align);
7284 break;
7286 case TOK_builtin_types_compatible_p:
7288 CType type1, type2;
7289 next();
7290 skip('(');
7291 parse_type(&type1);
7292 skip(',');
7293 parse_type(&type2);
7294 skip(')');
7295 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7296 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7297 vpushi(is_compatible_types(&type1, &type2));
7299 break;
7300 case TOK_builtin_constant_p:
7302 int saved_nocode_wanted, res;
7303 next();
7304 skip('(');
7305 saved_nocode_wanted = nocode_wanted;
7306 nocode_wanted = 1;
7307 gexpr();
7308 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7309 vpop();
7310 nocode_wanted = saved_nocode_wanted;
7311 skip(')');
7312 vpushi(res);
7314 break;
7315 case TOK_INC:
7316 case TOK_DEC:
7317 t = tok;
7318 next();
7319 unary();
7320 inc(0, t);
7321 break;
7322 case '-':
7323 next();
7324 vpushi(0);
7325 unary();
7326 gen_op('-');
7327 break;
7328 case TOK_LAND:
7329 if (!gnu_ext)
7330 goto tok_identifier;
7331 next();
7332 /* allow to take the address of a label */
7333 if (tok < TOK_UIDENT)
7334 expect("label identifier");
7335 s = label_find(tok);
7336 if (!s) {
7337 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7338 } else {
7339 if (s->r == LABEL_DECLARED)
7340 s->r = LABEL_FORWARD;
7342 if (!s->type.t) {
7343 s->type.t = VT_VOID;
7344 mk_pointer(&s->type);
7345 s->type.t |= VT_STATIC;
7347 vset(&s->type, VT_CONST | VT_SYM, 0);
7348 vtop->sym = s;
7349 next();
7350 break;
7351 default:
7352 tok_identifier:
7353 t = tok;
7354 next();
7355 if (t < TOK_UIDENT)
7356 expect("identifier");
7357 s = sym_find(t);
7358 if (!s) {
7359 if (tok != '(')
7360 error("'%s' undeclared", get_tok_str(t, NULL));
7361 /* for simple function calls, we tolerate undeclared
7362 external reference to int() function */
7363 if (tcc_state->warn_implicit_function_declaration)
7364 warning("implicit declaration of function '%s'",
7365 get_tok_str(t, NULL));
7366 s = external_global_sym(t, &func_old_type, 0);
7368 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7369 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7370 /* if referencing an inline function, then we generate a
7371 symbol to it if not already done. It will have the
7372 effect to generate code for it at the end of the
7373 compilation unit. Inline function as always
7374 generated in the text section. */
7375 if (!s->c)
7376 put_extern_sym(s, text_section, 0, 0);
7377 r = VT_SYM | VT_CONST;
7378 } else {
7379 r = s->r;
7381 vset(&s->type, r, s->c);
7382 /* if forward reference, we must point to s */
7383 if (vtop->r & VT_SYM) {
7384 vtop->sym = s;
7385 vtop->c.ul = 0;
7387 break;
7390 /* post operations */
7391 while (1) {
7392 if (tok == TOK_INC || tok == TOK_DEC) {
7393 inc(1, tok);
7394 next();
7395 } else if (tok == '.' || tok == TOK_ARROW) {
7396 /* field */
7397 if (tok == TOK_ARROW)
7398 indir();
7399 test_lvalue();
7400 gaddrof();
7401 next();
7402 /* expect pointer on structure */
7403 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7404 expect("struct or union");
7405 s = vtop->type.ref;
7406 /* find field */
7407 tok |= SYM_FIELD;
7408 while ((s = s->next) != NULL) {
7409 if (s->v == tok)
7410 break;
7412 if (!s)
7413 error("field not found");
7414 /* add field offset to pointer */
7415 vtop->type = char_pointer_type; /* change type to 'char *' */
7416 vpushi(s->c);
7417 gen_op('+');
7418 /* change type to field type, and set to lvalue */
7419 vtop->type = s->type;
7420 /* an array is never an lvalue */
7421 if (!(vtop->type.t & VT_ARRAY)) {
7422 vtop->r |= lvalue_type(vtop->type.t);
7423 /* if bound checking, the referenced pointer must be checked */
7424 if (do_bounds_check)
7425 vtop->r |= VT_MUSTBOUND;
7427 next();
7428 } else if (tok == '[') {
7429 next();
7430 gexpr();
7431 gen_op('+');
7432 indir();
7433 skip(']');
7434 } else if (tok == '(') {
7435 SValue ret;
7436 Sym *sa;
7437 int nb_args;
7439 /* function call */
7440 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7441 /* pointer test (no array accepted) */
7442 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7443 vtop->type = *pointed_type(&vtop->type);
7444 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7445 goto error_func;
7446 } else {
7447 error_func:
7448 expect("function pointer");
7450 } else {
7451 vtop->r &= ~VT_LVAL; /* no lvalue */
7453 /* get return type */
7454 s = vtop->type.ref;
7455 next();
7456 sa = s->next; /* first parameter */
7457 nb_args = 0;
7458 /* compute first implicit argument if a structure is returned */
7459 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7460 /* get some space for the returned structure */
7461 size = type_size(&s->type, &align);
7462 loc = (loc - size) & -align;
7463 ret.type = s->type;
7464 ret.r = VT_LOCAL | VT_LVAL;
7465 /* pass it as 'int' to avoid structure arg passing
7466 problems */
7467 vseti(VT_LOCAL, loc);
7468 ret.c = vtop->c;
7469 nb_args++;
7470 } else {
7471 ret.type = s->type;
7472 ret.r2 = VT_CONST;
7473 /* return in register */
7474 if (is_float(ret.type.t)) {
7475 ret.r = REG_FRET;
7476 } else {
7477 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7478 ret.r2 = REG_LRET;
7479 ret.r = REG_IRET;
7481 ret.c.i = 0;
7483 if (tok != ')') {
7484 for(;;) {
7485 expr_eq();
7486 gfunc_param_typed(s, sa);
7487 nb_args++;
7488 if (sa)
7489 sa = sa->next;
7490 if (tok == ')')
7491 break;
7492 skip(',');
7495 if (sa)
7496 error("too few arguments to function");
7497 skip(')');
7498 if (!nocode_wanted) {
7499 gfunc_call(nb_args);
7500 } else {
7501 vtop -= (nb_args + 1);
7503 /* return value */
7504 vsetc(&ret.type, ret.r, &ret.c);
7505 vtop->r2 = ret.r2;
7506 } else {
7507 break;
7512 static void uneq(void)
7514 int t;
7516 unary();
7517 if (tok == '=' ||
7518 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7519 tok == TOK_A_XOR || tok == TOK_A_OR ||
7520 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7521 test_lvalue();
7522 t = tok;
7523 next();
7524 if (t == '=') {
7525 expr_eq();
7526 } else {
7527 vdup();
7528 expr_eq();
7529 gen_op(t & 0x7f);
7531 vstore();
7535 static void expr_prod(void)
7537 int t;
7539 uneq();
7540 while (tok == '*' || tok == '/' || tok == '%') {
7541 t = tok;
7542 next();
7543 uneq();
7544 gen_op(t);
7548 static void expr_sum(void)
7550 int t;
7552 expr_prod();
7553 while (tok == '+' || tok == '-') {
7554 t = tok;
7555 next();
7556 expr_prod();
7557 gen_op(t);
7561 static void expr_shift(void)
7563 int t;
7565 expr_sum();
7566 while (tok == TOK_SHL || tok == TOK_SAR) {
7567 t = tok;
7568 next();
7569 expr_sum();
7570 gen_op(t);
7574 static void expr_cmp(void)
7576 int t;
7578 expr_shift();
7579 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7580 tok == TOK_ULT || tok == TOK_UGE) {
7581 t = tok;
7582 next();
7583 expr_shift();
7584 gen_op(t);
7588 static void expr_cmpeq(void)
7590 int t;
7592 expr_cmp();
7593 while (tok == TOK_EQ || tok == TOK_NE) {
7594 t = tok;
7595 next();
7596 expr_cmp();
7597 gen_op(t);
7601 static void expr_and(void)
7603 expr_cmpeq();
7604 while (tok == '&') {
7605 next();
7606 expr_cmpeq();
7607 gen_op('&');
7611 static void expr_xor(void)
7613 expr_and();
7614 while (tok == '^') {
7615 next();
7616 expr_and();
7617 gen_op('^');
7621 static void expr_or(void)
7623 expr_xor();
7624 while (tok == '|') {
7625 next();
7626 expr_xor();
7627 gen_op('|');
7631 /* XXX: fix this mess */
7632 static void expr_land_const(void)
7634 expr_or();
7635 while (tok == TOK_LAND) {
7636 next();
7637 expr_or();
7638 gen_op(TOK_LAND);
7642 /* XXX: fix this mess */
7643 static void expr_lor_const(void)
7645 expr_land_const();
7646 while (tok == TOK_LOR) {
7647 next();
7648 expr_land_const();
7649 gen_op(TOK_LOR);
7653 /* only used if non constant */
7654 static void expr_land(void)
7656 int t;
7658 expr_or();
7659 if (tok == TOK_LAND) {
7660 t = 0;
7661 for(;;) {
7662 t = gtst(1, t);
7663 if (tok != TOK_LAND) {
7664 vseti(VT_JMPI, t);
7665 break;
7667 next();
7668 expr_or();
7673 static void expr_lor(void)
7675 int t;
7677 expr_land();
7678 if (tok == TOK_LOR) {
7679 t = 0;
7680 for(;;) {
7681 t = gtst(0, t);
7682 if (tok != TOK_LOR) {
7683 vseti(VT_JMP, t);
7684 break;
7686 next();
7687 expr_land();
7692 /* XXX: better constant handling */
7693 static void expr_eq(void)
7695 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7696 SValue sv;
7697 CType type, type1, type2;
7699 if (const_wanted) {
7700 int c1, c;
7701 expr_lor_const();
7702 if (tok == '?') {
7703 c = vtop->c.i;
7704 vpop();
7705 next();
7706 if (tok == ':' && gnu_ext) {
7707 c1 = c;
7708 } else {
7709 gexpr();
7710 c1 = vtop->c.i;
7711 vpop();
7713 skip(':');
7714 expr_eq();
7715 if (c)
7716 vtop->c.i = c1;
7718 } else {
7719 expr_lor();
7720 if (tok == '?') {
7721 next();
7722 if (vtop != vstack) {
7723 /* needed to avoid having different registers saved in
7724 each branch */
7725 if (is_float(vtop->type.t))
7726 rc = RC_FLOAT;
7727 else
7728 rc = RC_INT;
7729 gv(rc);
7730 save_regs(1);
7732 if (tok == ':' && gnu_ext) {
7733 gv_dup();
7734 tt = gtst(1, 0);
7735 } else {
7736 tt = gtst(1, 0);
7737 gexpr();
7739 type1 = vtop->type;
7740 sv = *vtop; /* save value to handle it later */
7741 vtop--; /* no vpop so that FP stack is not flushed */
7742 skip(':');
7743 u = gjmp(0);
7744 gsym(tt);
7745 expr_eq();
7746 type2 = vtop->type;
7748 t1 = type1.t;
7749 bt1 = t1 & VT_BTYPE;
7750 t2 = type2.t;
7751 bt2 = t2 & VT_BTYPE;
7752 /* cast operands to correct type according to ISOC rules */
7753 if (is_float(bt1) || is_float(bt2)) {
7754 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7755 type.t = VT_LDOUBLE;
7756 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7757 type.t = VT_DOUBLE;
7758 } else {
7759 type.t = VT_FLOAT;
7761 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7762 /* cast to biggest op */
7763 type.t = VT_LLONG;
7764 /* convert to unsigned if it does not fit in a long long */
7765 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7766 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7767 type.t |= VT_UNSIGNED;
7768 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7769 /* XXX: test pointer compatibility */
7770 type = type1;
7771 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7772 /* XXX: test structure compatibility */
7773 type = type1;
7774 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7775 /* NOTE: as an extension, we accept void on only one side */
7776 type.t = VT_VOID;
7777 } else {
7778 /* integer operations */
7779 type.t = VT_INT;
7780 /* convert to unsigned if it does not fit in an integer */
7781 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7782 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7783 type.t |= VT_UNSIGNED;
7786 /* now we convert second operand */
7787 gen_cast(&type);
7788 rc = RC_INT;
7789 if (is_float(type.t)) {
7790 rc = RC_FLOAT;
7791 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7792 /* for long longs, we use fixed registers to avoid having
7793 to handle a complicated move */
7794 rc = RC_IRET;
7797 r2 = gv(rc);
7798 /* this is horrible, but we must also convert first
7799 operand */
7800 tt = gjmp(0);
7801 gsym(u);
7802 /* put again first value and cast it */
7803 *vtop = sv;
7804 gen_cast(&type);
7805 r1 = gv(rc);
7806 move_reg(r2, r1);
7807 vtop->r = r2;
7808 gsym(tt);
7813 static void gexpr(void)
7815 while (1) {
7816 expr_eq();
7817 if (tok != ',')
7818 break;
7819 vpop();
7820 next();
7824 /* parse an expression and return its type without any side effect. */
7825 static void expr_type(CType *type)
7827 int saved_nocode_wanted;
7829 saved_nocode_wanted = nocode_wanted;
7830 nocode_wanted = 1;
7831 gexpr();
7832 *type = vtop->type;
7833 vpop();
7834 nocode_wanted = saved_nocode_wanted;
7837 /* parse a unary expression and return its type without any side
7838 effect. */
7839 static void unary_type(CType *type)
7841 int a;
7843 a = nocode_wanted;
7844 nocode_wanted = 1;
7845 unary();
7846 *type = vtop->type;
7847 vpop();
7848 nocode_wanted = a;
7851 /* parse a constant expression and return value in vtop. */
7852 static void expr_const1(void)
7854 int a;
7855 a = const_wanted;
7856 const_wanted = 1;
7857 expr_eq();
7858 const_wanted = a;
7861 /* parse an integer constant and return its value. */
7862 static int expr_const(void)
7864 int c;
7865 expr_const1();
7866 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7867 expect("constant expression");
7868 c = vtop->c.i;
7869 vpop();
7870 return c;
7873 /* return the label token if current token is a label, otherwise
7874 return zero */
7875 static int is_label(void)
7877 int last_tok;
7879 /* fast test first */
7880 if (tok < TOK_UIDENT)
7881 return 0;
7882 /* no need to save tokc because tok is an identifier */
7883 last_tok = tok;
7884 next();
7885 if (tok == ':') {
7886 next();
7887 return last_tok;
7888 } else {
7889 unget_tok(last_tok);
7890 return 0;
7894 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7895 int case_reg, int is_expr)
7897 int a, b, c, d;
7898 Sym *s;
7900 /* generate line number info */
7901 if (do_debug &&
7902 (last_line_num != file->line_num || last_ind != ind)) {
7903 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7904 last_ind = ind;
7905 last_line_num = file->line_num;
7908 if (is_expr) {
7909 /* default return value is (void) */
7910 vpushi(0);
7911 vtop->type.t = VT_VOID;
7914 if (tok == TOK_IF) {
7915 /* if test */
7916 next();
7917 skip('(');
7918 gexpr();
7919 skip(')');
7920 a = gtst(1, 0);
7921 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7922 c = tok;
7923 if (c == TOK_ELSE) {
7924 next();
7925 d = gjmp(0);
7926 gsym(a);
7927 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7928 gsym(d); /* patch else jmp */
7929 } else
7930 gsym(a);
7931 } else if (tok == TOK_WHILE) {
7932 next();
7933 d = ind;
7934 skip('(');
7935 gexpr();
7936 skip(')');
7937 a = gtst(1, 0);
7938 b = 0;
7939 block(&a, &b, case_sym, def_sym, case_reg, 0);
7940 gjmp_addr(d);
7941 gsym(a);
7942 gsym_addr(b, d);
7943 } else if (tok == '{') {
7944 Sym *llabel;
7946 next();
7947 /* record local declaration stack position */
7948 s = local_stack;
7949 llabel = local_label_stack;
7950 /* handle local labels declarations */
7951 if (tok == TOK_LABEL) {
7952 next();
7953 for(;;) {
7954 if (tok < TOK_UIDENT)
7955 expect("label identifier");
7956 label_push(&local_label_stack, tok, LABEL_DECLARED);
7957 next();
7958 if (tok == ',') {
7959 next();
7960 } else {
7961 skip(';');
7962 break;
7966 while (tok != '}') {
7967 decl(VT_LOCAL);
7968 if (tok != '}') {
7969 if (is_expr)
7970 vpop();
7971 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7974 /* pop locally defined labels */
7975 label_pop(&local_label_stack, llabel);
7976 /* pop locally defined symbols */
7977 sym_pop(&local_stack, s);
7978 next();
7979 } else if (tok == TOK_RETURN) {
7980 next();
7981 if (tok != ';') {
7982 gexpr();
7983 gen_assign_cast(&func_vt);
7984 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7985 CType type;
7986 /* if returning structure, must copy it to implicit
7987 first pointer arg location */
7988 type = func_vt;
7989 mk_pointer(&type);
7990 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7991 indir();
7992 vswap();
7993 /* copy structure value to pointer */
7994 vstore();
7995 } else if (is_float(func_vt.t)) {
7996 gv(RC_FRET);
7997 } else {
7998 gv(RC_IRET);
8000 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8002 skip(';');
8003 rsym = gjmp(rsym); /* jmp */
8004 } else if (tok == TOK_BREAK) {
8005 /* compute jump */
8006 if (!bsym)
8007 error("cannot break");
8008 *bsym = gjmp(*bsym);
8009 next();
8010 skip(';');
8011 } else if (tok == TOK_CONTINUE) {
8012 /* compute jump */
8013 if (!csym)
8014 error("cannot continue");
8015 *csym = gjmp(*csym);
8016 next();
8017 skip(';');
8018 } else if (tok == TOK_FOR) {
8019 int e;
8020 next();
8021 skip('(');
8022 if (tok != ';') {
8023 gexpr();
8024 vpop();
8026 skip(';');
8027 d = ind;
8028 c = ind;
8029 a = 0;
8030 b = 0;
8031 if (tok != ';') {
8032 gexpr();
8033 a = gtst(1, 0);
8035 skip(';');
8036 if (tok != ')') {
8037 e = gjmp(0);
8038 c = ind;
8039 gexpr();
8040 vpop();
8041 gjmp_addr(d);
8042 gsym(e);
8044 skip(')');
8045 block(&a, &b, case_sym, def_sym, case_reg, 0);
8046 gjmp_addr(c);
8047 gsym(a);
8048 gsym_addr(b, c);
8049 } else
8050 if (tok == TOK_DO) {
8051 next();
8052 a = 0;
8053 b = 0;
8054 d = ind;
8055 block(&a, &b, case_sym, def_sym, case_reg, 0);
8056 skip(TOK_WHILE);
8057 skip('(');
8058 gsym(b);
8059 gexpr();
8060 c = gtst(0, 0);
8061 gsym_addr(c, d);
8062 skip(')');
8063 gsym(a);
8064 skip(';');
8065 } else
8066 if (tok == TOK_SWITCH) {
8067 next();
8068 skip('(');
8069 gexpr();
8070 /* XXX: other types than integer */
8071 case_reg = gv(RC_INT);
8072 vpop();
8073 skip(')');
8074 a = 0;
8075 b = gjmp(0); /* jump to first case */
8076 c = 0;
8077 block(&a, csym, &b, &c, case_reg, 0);
8078 /* if no default, jmp after switch */
8079 if (c == 0)
8080 c = ind;
8081 /* default label */
8082 gsym_addr(b, c);
8083 /* break label */
8084 gsym(a);
8085 } else
8086 if (tok == TOK_CASE) {
8087 int v1, v2;
8088 if (!case_sym)
8089 expect("switch");
8090 next();
8091 v1 = expr_const();
8092 v2 = v1;
8093 if (gnu_ext && tok == TOK_DOTS) {
8094 next();
8095 v2 = expr_const();
8096 if (v2 < v1)
8097 warning("empty case range");
8099 /* since a case is like a label, we must skip it with a jmp */
8100 b = gjmp(0);
8101 gsym(*case_sym);
8102 vseti(case_reg, 0);
8103 vpushi(v1);
8104 if (v1 == v2) {
8105 gen_op(TOK_EQ);
8106 *case_sym = gtst(1, 0);
8107 } else {
8108 gen_op(TOK_GE);
8109 *case_sym = gtst(1, 0);
8110 vseti(case_reg, 0);
8111 vpushi(v2);
8112 gen_op(TOK_LE);
8113 *case_sym = gtst(1, *case_sym);
8115 gsym(b);
8116 skip(':');
8117 is_expr = 0;
8118 goto block_after_label;
8119 } else
8120 if (tok == TOK_DEFAULT) {
8121 next();
8122 skip(':');
8123 if (!def_sym)
8124 expect("switch");
8125 if (*def_sym)
8126 error("too many 'default'");
8127 *def_sym = ind;
8128 is_expr = 0;
8129 goto block_after_label;
8130 } else
8131 if (tok == TOK_GOTO) {
8132 next();
8133 if (tok == '*' && gnu_ext) {
8134 /* computed goto */
8135 next();
8136 gexpr();
8137 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8138 expect("pointer");
8139 ggoto();
8140 } else if (tok >= TOK_UIDENT) {
8141 s = label_find(tok);
8142 /* put forward definition if needed */
8143 if (!s) {
8144 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8145 } else {
8146 if (s->r == LABEL_DECLARED)
8147 s->r = LABEL_FORWARD;
8149 /* label already defined */
8150 if (s->r & LABEL_FORWARD)
8151 s->next = (void *)gjmp((long)s->next);
8152 else
8153 gjmp_addr((long)s->next);
8154 next();
8155 } else {
8156 expect("label identifier");
8158 skip(';');
8159 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8160 asm_instr();
8161 } else {
8162 b = is_label();
8163 if (b) {
8164 /* label case */
8165 s = label_find(b);
8166 if (s) {
8167 if (s->r == LABEL_DEFINED)
8168 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8169 gsym((long)s->next);
8170 s->r = LABEL_DEFINED;
8171 } else {
8172 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8174 s->next = (void *)ind;
8175 /* we accept this, but it is a mistake */
8176 block_after_label:
8177 if (tok == '}') {
8178 warning("deprecated use of label at end of compound statement");
8179 } else {
8180 if (is_expr)
8181 vpop();
8182 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8184 } else {
8185 /* expression case */
8186 if (tok != ';') {
8187 if (is_expr) {
8188 vpop();
8189 gexpr();
8190 } else {
8191 gexpr();
8192 vpop();
8195 skip(';');
8200 /* t is the array or struct type. c is the array or struct
8201 address. cur_index/cur_field is the pointer to the current
8202 value. 'size_only' is true if only size info is needed (only used
8203 in arrays) */
8204 static void decl_designator(CType *type, Section *sec, unsigned long c,
8205 int *cur_index, Sym **cur_field,
8206 int size_only)
8208 Sym *s, *f;
8209 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8210 CType type1;
8212 notfirst = 0;
8213 elem_size = 0;
8214 nb_elems = 1;
8215 if (gnu_ext && (l = is_label()) != 0)
8216 goto struct_field;
8217 while (tok == '[' || tok == '.') {
8218 if (tok == '[') {
8219 if (!(type->t & VT_ARRAY))
8220 expect("array type");
8221 s = type->ref;
8222 next();
8223 index = expr_const();
8224 if (index < 0 || (s->c >= 0 && index >= s->c))
8225 expect("invalid index");
8226 if (tok == TOK_DOTS && gnu_ext) {
8227 next();
8228 index_last = expr_const();
8229 if (index_last < 0 ||
8230 (s->c >= 0 && index_last >= s->c) ||
8231 index_last < index)
8232 expect("invalid index");
8233 } else {
8234 index_last = index;
8236 skip(']');
8237 if (!notfirst)
8238 *cur_index = index_last;
8239 type = pointed_type(type);
8240 elem_size = type_size(type, &align);
8241 c += index * elem_size;
8242 /* NOTE: we only support ranges for last designator */
8243 nb_elems = index_last - index + 1;
8244 if (nb_elems != 1) {
8245 notfirst = 1;
8246 break;
8248 } else {
8249 next();
8250 l = tok;
8251 next();
8252 struct_field:
8253 if ((type->t & VT_BTYPE) != VT_STRUCT)
8254 expect("struct/union type");
8255 s = type->ref;
8256 l |= SYM_FIELD;
8257 f = s->next;
8258 while (f) {
8259 if (f->v == l)
8260 break;
8261 f = f->next;
8263 if (!f)
8264 expect("field");
8265 if (!notfirst)
8266 *cur_field = f;
8267 /* XXX: fix this mess by using explicit storage field */
8268 type1 = f->type;
8269 type1.t |= (type->t & ~VT_TYPE);
8270 type = &type1;
8271 c += f->c;
8273 notfirst = 1;
8275 if (notfirst) {
8276 if (tok == '=') {
8277 next();
8278 } else {
8279 if (!gnu_ext)
8280 expect("=");
8282 } else {
8283 if (type->t & VT_ARRAY) {
8284 index = *cur_index;
8285 type = pointed_type(type);
8286 c += index * type_size(type, &align);
8287 } else {
8288 f = *cur_field;
8289 if (!f)
8290 error("too many field init");
8291 /* XXX: fix this mess by using explicit storage field */
8292 type1 = f->type;
8293 type1.t |= (type->t & ~VT_TYPE);
8294 type = &type1;
8295 c += f->c;
8298 decl_initializer(type, sec, c, 0, size_only);
8300 /* XXX: make it more general */
8301 if (!size_only && nb_elems > 1) {
8302 unsigned long c_end;
8303 uint8_t *src, *dst;
8304 int i;
8306 if (!sec)
8307 error("range init not supported yet for dynamic storage");
8308 c_end = c + nb_elems * elem_size;
8309 if (c_end > sec->data_allocated)
8310 section_realloc(sec, c_end);
8311 src = sec->data + c;
8312 dst = src;
8313 for(i = 1; i < nb_elems; i++) {
8314 dst += elem_size;
8315 memcpy(dst, src, elem_size);
8320 #define EXPR_VAL 0
8321 #define EXPR_CONST 1
8322 #define EXPR_ANY 2
8324 /* store a value or an expression directly in global data or in local array */
8325 static void init_putv(CType *type, Section *sec, unsigned long c,
8326 int v, int expr_type)
8328 int saved_global_expr, bt, bit_pos, bit_size;
8329 void *ptr;
8330 unsigned long long bit_mask;
8331 CType dtype;
8333 switch(expr_type) {
8334 case EXPR_VAL:
8335 vpushi(v);
8336 break;
8337 case EXPR_CONST:
8338 /* compound literals must be allocated globally in this case */
8339 saved_global_expr = global_expr;
8340 global_expr = 1;
8341 expr_const1();
8342 global_expr = saved_global_expr;
8343 /* NOTE: symbols are accepted */
8344 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8345 error("initializer element is not constant");
8346 break;
8347 case EXPR_ANY:
8348 expr_eq();
8349 break;
8352 dtype = *type;
8353 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8355 if (sec) {
8356 /* XXX: not portable */
8357 /* XXX: generate error if incorrect relocation */
8358 gen_assign_cast(&dtype);
8359 bt = type->t & VT_BTYPE;
8360 ptr = sec->data + c;
8361 /* XXX: make code faster ? */
8362 if (!(type->t & VT_BITFIELD)) {
8363 bit_pos = 0;
8364 bit_size = 32;
8365 bit_mask = -1LL;
8366 } else {
8367 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8368 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8369 bit_mask = (1LL << bit_size) - 1;
8371 if ((vtop->r & VT_SYM) &&
8372 (bt == VT_BYTE ||
8373 bt == VT_SHORT ||
8374 bt == VT_DOUBLE ||
8375 bt == VT_LDOUBLE ||
8376 bt == VT_LLONG ||
8377 (bt == VT_INT && bit_size != 32)))
8378 error("initializer element is not computable at load time");
8379 switch(bt) {
8380 case VT_BYTE:
8381 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8382 break;
8383 case VT_SHORT:
8384 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8385 break;
8386 case VT_DOUBLE:
8387 *(double *)ptr = vtop->c.d;
8388 break;
8389 case VT_LDOUBLE:
8390 *(long double *)ptr = vtop->c.ld;
8391 break;
8392 case VT_LLONG:
8393 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8394 break;
8395 default:
8396 if (vtop->r & VT_SYM) {
8397 greloc(sec, vtop->sym, c, R_DATA_32);
8399 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8400 break;
8402 vtop--;
8403 } else {
8404 vset(&dtype, VT_LOCAL, c);
8405 vswap();
8406 vstore();
8407 vpop();
8411 /* put zeros for variable based init */
8412 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8414 if (sec) {
8415 /* nothing to do because globals are already set to zero */
8416 } else {
8417 vpush_global_sym(&func_old_type, TOK_memset);
8418 vseti(VT_LOCAL, c);
8419 vpushi(0);
8420 vpushi(size);
8421 gfunc_call(3);
8425 /* 't' contains the type and storage info. 'c' is the offset of the
8426 object in section 'sec'. If 'sec' is NULL, it means stack based
8427 allocation. 'first' is true if array '{' must be read (multi
8428 dimension implicit array init handling). 'size_only' is true if
8429 size only evaluation is wanted (only for arrays). */
8430 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8431 int first, int size_only)
8433 int index, array_length, n, no_oblock, nb, parlevel, i;
8434 int size1, align1, expr_type;
8435 Sym *s, *f;
8436 CType *t1;
8438 if (type->t & VT_ARRAY) {
8439 s = type->ref;
8440 n = s->c;
8441 array_length = 0;
8442 t1 = pointed_type(type);
8443 size1 = type_size(t1, &align1);
8445 no_oblock = 1;
8446 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8447 tok == '{') {
8448 skip('{');
8449 no_oblock = 0;
8452 /* only parse strings here if correct type (otherwise: handle
8453 them as ((w)char *) expressions */
8454 if ((tok == TOK_LSTR &&
8455 #ifdef TCC_TARGET_PE
8456 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)) ||
8457 #else
8458 (t1->t & VT_BTYPE) == VT_INT) ||
8459 #endif
8460 (tok == TOK_STR &&
8461 (t1->t & VT_BTYPE) == VT_BYTE)) {
8462 while (tok == TOK_STR || tok == TOK_LSTR) {
8463 int cstr_len, ch;
8464 CString *cstr;
8466 cstr = tokc.cstr;
8467 /* compute maximum number of chars wanted */
8468 if (tok == TOK_STR)
8469 cstr_len = cstr->size;
8470 else
8471 cstr_len = cstr->size / sizeof(nwchar_t);
8472 cstr_len--;
8473 nb = cstr_len;
8474 if (n >= 0 && nb > (n - array_length))
8475 nb = n - array_length;
8476 if (!size_only) {
8477 if (cstr_len > nb)
8478 warning("initializer-string for array is too long");
8479 /* in order to go faster for common case (char
8480 string in global variable, we handle it
8481 specifically */
8482 if (sec && tok == TOK_STR && size1 == 1) {
8483 memcpy(sec->data + c + array_length, cstr->data, nb);
8484 } else {
8485 for(i=0;i<nb;i++) {
8486 if (tok == TOK_STR)
8487 ch = ((unsigned char *)cstr->data)[i];
8488 else
8489 ch = ((nwchar_t *)cstr->data)[i];
8490 init_putv(t1, sec, c + (array_length + i) * size1,
8491 ch, EXPR_VAL);
8495 array_length += nb;
8496 next();
8498 /* only add trailing zero if enough storage (no
8499 warning in this case since it is standard) */
8500 if (n < 0 || array_length < n) {
8501 if (!size_only) {
8502 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8504 array_length++;
8506 } else {
8507 index = 0;
8508 while (tok != '}') {
8509 decl_designator(type, sec, c, &index, NULL, size_only);
8510 if (n >= 0 && index >= n)
8511 error("index too large");
8512 /* must put zero in holes (note that doing it that way
8513 ensures that it even works with designators) */
8514 if (!size_only && array_length < index) {
8515 init_putz(t1, sec, c + array_length * size1,
8516 (index - array_length) * size1);
8518 index++;
8519 if (index > array_length)
8520 array_length = index;
8521 /* special test for multi dimensional arrays (may not
8522 be strictly correct if designators are used at the
8523 same time) */
8524 if (index >= n && no_oblock)
8525 break;
8526 if (tok == '}')
8527 break;
8528 skip(',');
8531 if (!no_oblock)
8532 skip('}');
8533 /* put zeros at the end */
8534 if (!size_only && n >= 0 && array_length < n) {
8535 init_putz(t1, sec, c + array_length * size1,
8536 (n - array_length) * size1);
8538 /* patch type size if needed */
8539 if (n < 0)
8540 s->c = array_length;
8541 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8542 (sec || !first || tok == '{')) {
8543 int par_count;
8545 /* NOTE: the previous test is a specific case for automatic
8546 struct/union init */
8547 /* XXX: union needs only one init */
8549 /* XXX: this test is incorrect for local initializers
8550 beginning with ( without {. It would be much more difficult
8551 to do it correctly (ideally, the expression parser should
8552 be used in all cases) */
8553 par_count = 0;
8554 if (tok == '(') {
8555 AttributeDef ad1;
8556 CType type1;
8557 next();
8558 while (tok == '(') {
8559 par_count++;
8560 next();
8562 if (!parse_btype(&type1, &ad1))
8563 expect("cast");
8564 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8565 #if 0
8566 if (!is_assignable_types(type, &type1))
8567 error("invalid type for cast");
8568 #endif
8569 skip(')');
8571 no_oblock = 1;
8572 if (first || tok == '{') {
8573 skip('{');
8574 no_oblock = 0;
8576 s = type->ref;
8577 f = s->next;
8578 array_length = 0;
8579 index = 0;
8580 n = s->c;
8581 while (tok != '}') {
8582 decl_designator(type, sec, c, NULL, &f, size_only);
8583 index = f->c;
8584 if (!size_only && array_length < index) {
8585 init_putz(type, sec, c + array_length,
8586 index - array_length);
8588 index = index + type_size(&f->type, &align1);
8589 if (index > array_length)
8590 array_length = index;
8591 f = f->next;
8592 if (no_oblock && f == NULL)
8593 break;
8594 if (tok == '}')
8595 break;
8596 skip(',');
8598 /* put zeros at the end */
8599 if (!size_only && array_length < n) {
8600 init_putz(type, sec, c + array_length,
8601 n - array_length);
8603 if (!no_oblock)
8604 skip('}');
8605 while (par_count) {
8606 skip(')');
8607 par_count--;
8609 } else if (tok == '{') {
8610 next();
8611 decl_initializer(type, sec, c, first, size_only);
8612 skip('}');
8613 } else if (size_only) {
8614 /* just skip expression */
8615 parlevel = 0;
8616 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8617 tok != -1) {
8618 if (tok == '(')
8619 parlevel++;
8620 else if (tok == ')')
8621 parlevel--;
8622 next();
8624 } else {
8625 /* currently, we always use constant expression for globals
8626 (may change for scripting case) */
8627 expr_type = EXPR_CONST;
8628 if (!sec)
8629 expr_type = EXPR_ANY;
8630 init_putv(type, sec, c, 0, expr_type);
8634 /* parse an initializer for type 't' if 'has_init' is non zero, and
8635 allocate space in local or global data space ('r' is either
8636 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8637 variable 'v' of scope 'scope' is declared before initializers are
8638 parsed. If 'v' is zero, then a reference to the new object is put
8639 in the value stack. If 'has_init' is 2, a special parsing is done
8640 to handle string constants. */
8641 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8642 int has_init, int v, int scope)
8644 int size, align, addr, data_offset;
8645 int level;
8646 ParseState saved_parse_state;
8647 TokenString init_str;
8648 Section *sec;
8650 size = type_size(type, &align);
8651 /* If unknown size, we must evaluate it before
8652 evaluating initializers because
8653 initializers can generate global data too
8654 (e.g. string pointers or ISOC99 compound
8655 literals). It also simplifies local
8656 initializers handling */
8657 tok_str_new(&init_str);
8658 if (size < 0) {
8659 if (!has_init)
8660 error("unknown type size");
8661 /* get all init string */
8662 if (has_init == 2) {
8663 /* only get strings */
8664 while (tok == TOK_STR || tok == TOK_LSTR) {
8665 tok_str_add_tok(&init_str);
8666 next();
8668 } else {
8669 level = 0;
8670 while (level > 0 || (tok != ',' && tok != ';')) {
8671 if (tok < 0)
8672 error("unexpected end of file in initializer");
8673 tok_str_add_tok(&init_str);
8674 if (tok == '{')
8675 level++;
8676 else if (tok == '}') {
8677 if (level == 0)
8678 break;
8679 level--;
8681 next();
8684 tok_str_add(&init_str, -1);
8685 tok_str_add(&init_str, 0);
8687 /* compute size */
8688 save_parse_state(&saved_parse_state);
8690 macro_ptr = init_str.str;
8691 next();
8692 decl_initializer(type, NULL, 0, 1, 1);
8693 /* prepare second initializer parsing */
8694 macro_ptr = init_str.str;
8695 next();
8697 /* if still unknown size, error */
8698 size = type_size(type, &align);
8699 if (size < 0)
8700 error("unknown type size");
8702 /* take into account specified alignment if bigger */
8703 if (ad->aligned) {
8704 if (ad->aligned > align)
8705 align = ad->aligned;
8706 } else if (ad->packed) {
8707 align = 1;
8709 if ((r & VT_VALMASK) == VT_LOCAL) {
8710 sec = NULL;
8711 if (do_bounds_check && (type->t & VT_ARRAY))
8712 loc--;
8713 loc = (loc - size) & -align;
8714 addr = loc;
8715 /* handles bounds */
8716 /* XXX: currently, since we do only one pass, we cannot track
8717 '&' operators, so we add only arrays */
8718 if (do_bounds_check && (type->t & VT_ARRAY)) {
8719 unsigned long *bounds_ptr;
8720 /* add padding between regions */
8721 loc--;
8722 /* then add local bound info */
8723 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8724 bounds_ptr[0] = addr;
8725 bounds_ptr[1] = size;
8727 if (v) {
8728 /* local variable */
8729 sym_push(v, type, r, addr);
8730 } else {
8731 /* push local reference */
8732 vset(type, r, addr);
8734 } else {
8735 Sym *sym;
8737 sym = NULL;
8738 if (v && scope == VT_CONST) {
8739 /* see if the symbol was already defined */
8740 sym = sym_find(v);
8741 if (sym) {
8742 if (!is_compatible_types(&sym->type, type))
8743 error("incompatible types for redefinition of '%s'",
8744 get_tok_str(v, NULL));
8745 if (sym->type.t & VT_EXTERN) {
8746 /* if the variable is extern, it was not allocated */
8747 sym->type.t &= ~VT_EXTERN;
8748 /* set array size if it was ommited in extern
8749 declaration */
8750 if ((sym->type.t & VT_ARRAY) &&
8751 sym->type.ref->c < 0 &&
8752 type->ref->c >= 0)
8753 sym->type.ref->c = type->ref->c;
8754 } else {
8755 /* we accept several definitions of the same
8756 global variable. this is tricky, because we
8757 must play with the SHN_COMMON type of the symbol */
8758 /* XXX: should check if the variable was already
8759 initialized. It is incorrect to initialized it
8760 twice */
8761 /* no init data, we won't add more to the symbol */
8762 if (!has_init)
8763 goto no_alloc;
8768 /* allocate symbol in corresponding section */
8769 sec = ad->section;
8770 if (!sec) {
8771 if (has_init)
8772 sec = data_section;
8773 else if (tcc_state->nocommon)
8774 sec = bss_section;
8776 if (sec) {
8777 data_offset = sec->data_offset;
8778 data_offset = (data_offset + align - 1) & -align;
8779 addr = data_offset;
8780 /* very important to increment global pointer at this time
8781 because initializers themselves can create new initializers */
8782 data_offset += size;
8783 /* add padding if bound check */
8784 if (do_bounds_check)
8785 data_offset++;
8786 sec->data_offset = data_offset;
8787 /* allocate section space to put the data */
8788 if (sec->sh_type != SHT_NOBITS &&
8789 data_offset > sec->data_allocated)
8790 section_realloc(sec, data_offset);
8791 /* align section if needed */
8792 if (align > sec->sh_addralign)
8793 sec->sh_addralign = align;
8794 } else {
8795 addr = 0; /* avoid warning */
8798 if (v) {
8799 if (scope == VT_CONST) {
8800 if (!sym)
8801 goto do_def;
8802 } else {
8803 do_def:
8804 sym = sym_push(v, type, r | VT_SYM, 0);
8806 /* update symbol definition */
8807 if (sec) {
8808 put_extern_sym(sym, sec, addr, size);
8809 } else {
8810 Elf32_Sym *esym;
8811 /* put a common area */
8812 put_extern_sym(sym, NULL, align, size);
8813 /* XXX: find a nicer way */
8814 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8815 esym->st_shndx = SHN_COMMON;
8817 } else {
8818 CValue cval;
8820 /* push global reference */
8821 sym = get_sym_ref(type, sec, addr, size);
8822 cval.ul = 0;
8823 vsetc(type, VT_CONST | VT_SYM, &cval);
8824 vtop->sym = sym;
8827 /* handles bounds now because the symbol must be defined
8828 before for the relocation */
8829 if (do_bounds_check) {
8830 unsigned long *bounds_ptr;
8832 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8833 /* then add global bound info */
8834 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8835 bounds_ptr[0] = 0; /* relocated */
8836 bounds_ptr[1] = size;
8839 if (has_init) {
8840 decl_initializer(type, sec, addr, 1, 0);
8841 /* restore parse state if needed */
8842 if (init_str.str) {
8843 tok_str_free(init_str.str);
8844 restore_parse_state(&saved_parse_state);
8847 no_alloc: ;
8850 void put_func_debug(Sym *sym)
8852 char buf[512];
8854 /* stabs info */
8855 /* XXX: we put here a dummy type */
8856 snprintf(buf, sizeof(buf), "%s:%c1",
8857 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8858 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8859 cur_text_section, sym->c);
8860 last_ind = 0;
8861 last_line_num = 0;
8864 /* parse an old style function declaration list */
8865 /* XXX: check multiple parameter */
8866 static void func_decl_list(Sym *func_sym)
8868 AttributeDef ad;
8869 int v;
8870 Sym *s;
8871 CType btype, type;
8873 /* parse each declaration */
8874 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8875 if (!parse_btype(&btype, &ad))
8876 expect("declaration list");
8877 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8878 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8879 tok == ';') {
8880 /* we accept no variable after */
8881 } else {
8882 for(;;) {
8883 type = btype;
8884 type_decl(&type, &ad, &v, TYPE_DIRECT);
8885 /* find parameter in function parameter list */
8886 s = func_sym->next;
8887 while (s != NULL) {
8888 if ((s->v & ~SYM_FIELD) == v)
8889 goto found;
8890 s = s->next;
8892 error("declaration for parameter '%s' but no such parameter",
8893 get_tok_str(v, NULL));
8894 found:
8895 /* check that no storage specifier except 'register' was given */
8896 if (type.t & VT_STORAGE)
8897 error("storage class specified for '%s'", get_tok_str(v, NULL));
8898 convert_parameter_type(&type);
8899 /* we can add the type (NOTE: it could be local to the function) */
8900 s->type = type;
8901 /* accept other parameters */
8902 if (tok == ',')
8903 next();
8904 else
8905 break;
8908 skip(';');
8912 /* parse a function defined by symbol 'sym' and generate its code in
8913 'cur_text_section' */
8914 static void gen_function(Sym *sym)
8916 ind = cur_text_section->data_offset;
8917 /* NOTE: we patch the symbol size later */
8918 put_extern_sym(sym, cur_text_section, ind, 0);
8919 funcname = get_tok_str(sym->v, NULL);
8920 func_ind = ind;
8921 /* put debug symbol */
8922 if (do_debug)
8923 put_func_debug(sym);
8924 /* push a dummy symbol to enable local sym storage */
8925 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8926 gfunc_prolog(&sym->type);
8927 rsym = 0;
8928 block(NULL, NULL, NULL, NULL, 0, 0);
8929 gsym(rsym);
8930 gfunc_epilog();
8931 cur_text_section->data_offset = ind;
8932 label_pop(&global_label_stack, NULL);
8933 sym_pop(&local_stack, NULL); /* reset local stack */
8934 /* end of function */
8935 /* patch symbol size */
8936 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8937 ind - func_ind;
8938 if (do_debug) {
8939 put_stabn(N_FUN, 0, 0, ind - func_ind);
8941 funcname = ""; /* for safety */
8942 func_vt.t = VT_VOID; /* for safety */
8943 ind = 0; /* for safety */
8946 static void gen_inline_functions(void)
8948 Sym *sym;
8949 CType *type;
8950 int *str, inline_generated;
8952 /* iterate while inline function are referenced */
8953 for(;;) {
8954 inline_generated = 0;
8955 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8956 type = &sym->type;
8957 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8958 (type->t & (VT_STATIC | VT_INLINE)) ==
8959 (VT_STATIC | VT_INLINE) &&
8960 sym->c != 0) {
8961 /* the function was used: generate its code and
8962 convert it to a normal function */
8963 str = (int *)sym->r;
8964 sym->r = VT_SYM | VT_CONST;
8965 type->t &= ~VT_INLINE;
8967 macro_ptr = str;
8968 next();
8969 cur_text_section = text_section;
8970 gen_function(sym);
8971 macro_ptr = NULL; /* fail safe */
8973 tok_str_free(str);
8974 inline_generated = 1;
8977 if (!inline_generated)
8978 break;
8981 /* free all remaining inline function tokens */
8982 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8983 type = &sym->type;
8984 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8985 (type->t & (VT_STATIC | VT_INLINE)) ==
8986 (VT_STATIC | VT_INLINE)) {
8987 str = (int *)sym->r;
8988 tok_str_free(str);
8989 sym->r = 0; /* fail safe */
8994 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8995 static void decl(int l)
8997 int v, has_init, r;
8998 CType type, btype;
8999 Sym *sym;
9000 AttributeDef ad;
9002 while (1) {
9003 if (!parse_btype(&btype, &ad)) {
9004 /* skip redundant ';' */
9005 /* XXX: find more elegant solution */
9006 if (tok == ';') {
9007 next();
9008 continue;
9010 if (l == VT_CONST &&
9011 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9012 /* global asm block */
9013 asm_global_instr();
9014 continue;
9016 /* special test for old K&R protos without explicit int
9017 type. Only accepted when defining global data */
9018 if (l == VT_LOCAL || tok < TOK_DEFINE)
9019 break;
9020 btype.t = VT_INT;
9022 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9023 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9024 tok == ';') {
9025 /* we accept no variable after */
9026 next();
9027 continue;
9029 while (1) { /* iterate thru each declaration */
9030 type = btype;
9031 type_decl(&type, &ad, &v, TYPE_DIRECT);
9032 #if 0
9034 char buf[500];
9035 type_to_str(buf, sizeof(buf), &type, get_tok_str(v, NULL));
9036 printf("type = '%s'\n", buf);
9038 #endif
9039 if ((type.t & VT_BTYPE) == VT_FUNC) {
9040 /* if old style function prototype, we accept a
9041 declaration list */
9042 sym = type.ref;
9043 if (sym->c == FUNC_OLD)
9044 func_decl_list(sym);
9047 if (tok == '{') {
9048 if (l == VT_LOCAL)
9049 error("cannot use local functions");
9050 if ((type.t & VT_BTYPE) != VT_FUNC)
9051 expect("function definition");
9053 /* reject abstract declarators in function definition */
9054 sym = type.ref;
9055 while ((sym = sym->next) != NULL)
9056 if (!(sym->v & ~SYM_FIELD))
9057 expect("identifier");
9059 /* XXX: cannot do better now: convert extern line to static inline */
9060 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9061 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9063 sym = sym_find(v);
9064 if (sym) {
9065 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9066 goto func_error1;
9067 /* specific case: if not func_call defined, we put
9068 the one of the prototype */
9069 /* XXX: should have default value */
9070 if (sym->type.ref->r != FUNC_CDECL &&
9071 type.ref->r == FUNC_CDECL)
9072 type.ref->r = sym->type.ref->r;
9073 if (!is_compatible_types(&sym->type, &type)) {
9074 func_error1:
9075 error("incompatible types for redefinition of '%s'",
9076 get_tok_str(v, NULL));
9078 /* if symbol is already defined, then put complete type */
9079 sym->type = type;
9080 } else {
9081 /* put function symbol */
9082 sym = global_identifier_push(v, type.t, 0);
9083 sym->type.ref = type.ref;
9086 /* static inline functions are just recorded as a kind
9087 of macro. Their code will be emitted at the end of
9088 the compilation unit only if they are used */
9089 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9090 (VT_INLINE | VT_STATIC)) {
9091 TokenString func_str;
9092 int block_level;
9094 tok_str_new(&func_str);
9096 block_level = 0;
9097 for(;;) {
9098 int t;
9099 if (tok == TOK_EOF)
9100 error("unexpected end of file");
9101 tok_str_add_tok(&func_str);
9102 t = tok;
9103 next();
9104 if (t == '{') {
9105 block_level++;
9106 } else if (t == '}') {
9107 block_level--;
9108 if (block_level == 0)
9109 break;
9112 tok_str_add(&func_str, -1);
9113 tok_str_add(&func_str, 0);
9114 sym->r = (int)func_str.str;
9115 } else {
9116 /* compute text section */
9117 cur_text_section = ad.section;
9118 if (!cur_text_section)
9119 cur_text_section = text_section;
9120 sym->r = VT_SYM | VT_CONST;
9121 gen_function(sym);
9122 #ifdef TCC_TARGET_PE
9123 if (ad.dllexport) {
9124 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
9126 #endif
9128 break;
9129 } else {
9130 if (btype.t & VT_TYPEDEF) {
9131 /* save typedefed type */
9132 /* XXX: test storage specifiers ? */
9133 sym = sym_push(v, &type, 0, 0);
9134 sym->type.t |= VT_TYPEDEF;
9135 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9136 /* external function definition */
9137 /* specific case for func_call attribute */
9138 if (ad.func_call)
9139 type.ref->r = ad.func_call;
9140 external_sym(v, &type, 0);
9141 } else {
9142 /* not lvalue if array */
9143 r = 0;
9144 if (!(type.t & VT_ARRAY))
9145 r |= lvalue_type(type.t);
9146 has_init = (tok == '=');
9147 if ((btype.t & VT_EXTERN) ||
9148 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9149 !has_init && l == VT_CONST && type.ref->c < 0)) {
9150 /* external variable */
9151 /* NOTE: as GCC, uninitialized global static
9152 arrays of null size are considered as
9153 extern */
9154 external_sym(v, &type, r);
9155 } else {
9156 if (type.t & VT_STATIC)
9157 r |= VT_CONST;
9158 else
9159 r |= l;
9160 if (has_init)
9161 next();
9162 decl_initializer_alloc(&type, &ad, r,
9163 has_init, v, l);
9166 if (tok != ',') {
9167 skip(';');
9168 break;
9170 next();
9176 /* better than nothing, but needs extension to handle '-E' option
9177 correctly too */
9178 static void preprocess_init(TCCState *s1)
9180 s1->include_stack_ptr = s1->include_stack;
9181 /* XXX: move that before to avoid having to initialize
9182 file->ifdef_stack_ptr ? */
9183 s1->ifdef_stack_ptr = s1->ifdef_stack;
9184 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9186 /* XXX: not ANSI compliant: bound checking says error */
9187 vtop = vstack - 1;
9188 s1->pack_stack[0] = 0;
9189 s1->pack_stack_ptr = s1->pack_stack;
9192 /* compile the C file opened in 'file'. Return non zero if errors. */
9193 static int tcc_compile(TCCState *s1)
9195 Sym *define_start;
9196 char buf[512];
9197 volatile int section_sym;
9199 #ifdef INC_DEBUG
9200 printf("%s: **** new file\n", file->filename);
9201 #endif
9202 preprocess_init(s1);
9204 funcname = "";
9205 anon_sym = SYM_FIRST_ANOM;
9207 /* file info: full path + filename */
9208 section_sym = 0; /* avoid warning */
9209 if (do_debug) {
9210 section_sym = put_elf_sym(symtab_section, 0, 0,
9211 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9212 text_section->sh_num, NULL);
9213 getcwd(buf, sizeof(buf));
9214 pstrcat(buf, sizeof(buf), "/");
9215 put_stabs_r(buf, N_SO, 0, 0,
9216 text_section->data_offset, text_section, section_sym);
9217 put_stabs_r(file->filename, N_SO, 0, 0,
9218 text_section->data_offset, text_section, section_sym);
9220 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9221 symbols can be safely used */
9222 put_elf_sym(symtab_section, 0, 0,
9223 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9224 SHN_ABS, file->filename);
9226 /* define some often used types */
9227 int_type.t = VT_INT;
9229 char_pointer_type.t = VT_BYTE;
9230 mk_pointer(&char_pointer_type);
9232 func_old_type.t = VT_FUNC;
9233 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9235 #if 0
9236 /* define 'void *alloca(unsigned int)' builtin function */
9238 Sym *s1;
9240 p = anon_sym++;
9241 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9242 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9243 s1->next = NULL;
9244 sym->next = s1;
9245 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9247 #endif
9249 define_start = define_stack;
9251 if (setjmp(s1->error_jmp_buf) == 0) {
9252 s1->nb_errors = 0;
9253 s1->error_set_jmp_enabled = 1;
9255 ch = file->buf_ptr[0];
9256 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9257 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9258 next();
9259 decl(VT_CONST);
9260 if (tok != TOK_EOF)
9261 expect("declaration");
9263 /* end of translation unit info */
9264 if (do_debug) {
9265 put_stabs_r(NULL, N_SO, 0, 0,
9266 text_section->data_offset, text_section, section_sym);
9269 s1->error_set_jmp_enabled = 0;
9271 /* reset define stack, but leave -Dsymbols (may be incorrect if
9272 they are undefined) */
9273 free_defines(define_start);
9275 gen_inline_functions();
9277 sym_pop(&global_stack, NULL);
9279 return s1->nb_errors != 0 ? -1 : 0;
9282 #ifdef LIBTCC
9283 int tcc_compile_string(TCCState *s, const char *str)
9285 BufferedFile bf1, *bf = &bf1;
9286 int ret, len;
9287 char *buf;
9289 /* init file structure */
9290 bf->fd = -1;
9291 /* XXX: avoid copying */
9292 len = strlen(str);
9293 buf = tcc_malloc(len + 1);
9294 if (!buf)
9295 return -1;
9296 memcpy(buf, str, len);
9297 buf[len] = CH_EOB;
9298 bf->buf_ptr = buf;
9299 bf->buf_end = buf + len;
9300 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9301 bf->line_num = 1;
9302 file = bf;
9304 ret = tcc_compile(s);
9306 tcc_free(buf);
9308 /* currently, no need to close */
9309 return ret;
9311 #endif
9313 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9314 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9316 BufferedFile bf1, *bf = &bf1;
9318 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9319 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9320 /* default value */
9321 if (!value)
9322 value = "1";
9323 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9325 /* init file structure */
9326 bf->fd = -1;
9327 bf->buf_ptr = bf->buffer;
9328 bf->buf_end = bf->buffer + strlen(bf->buffer);
9329 *bf->buf_end = CH_EOB;
9330 bf->filename[0] = '\0';
9331 bf->line_num = 1;
9332 file = bf;
9334 s1->include_stack_ptr = s1->include_stack;
9336 /* parse with define parser */
9337 ch = file->buf_ptr[0];
9338 next_nomacro();
9339 parse_define();
9340 file = NULL;
9343 /* undefine a preprocessor symbol */
9344 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9346 TokenSym *ts;
9347 Sym *s;
9348 ts = tok_alloc(sym, strlen(sym));
9349 s = define_find(ts->tok);
9350 /* undefine symbol by putting an invalid name */
9351 if (s)
9352 define_undef(s);
9355 #ifdef CONFIG_TCC_ASM
9357 #ifdef TCC_TARGET_I386
9358 #include "i386-asm.c"
9359 #endif
9360 #include "tccasm.c"
9362 #else
9363 static void asm_instr(void)
9365 error("inline asm() not supported");
9367 static void asm_global_instr(void)
9369 error("inline asm() not supported");
9371 #endif
9373 #include "tccelf.c"
9375 #ifdef TCC_TARGET_COFF
9376 #include "tcccoff.c"
9377 #endif
9379 #ifdef TCC_TARGET_PE
9380 #include "tccpe.c"
9381 #endif
9383 /* print the position in the source file of PC value 'pc' by reading
9384 the stabs debug information */
9385 static void rt_printline(unsigned long wanted_pc)
9387 Stab_Sym *sym, *sym_end;
9388 char func_name[128], last_func_name[128];
9389 unsigned long func_addr, last_pc, pc;
9390 const char *incl_files[INCLUDE_STACK_SIZE];
9391 int incl_index, len, last_line_num, i;
9392 const char *str, *p;
9394 fprintf(stderr, "0x%08lx:", wanted_pc);
9396 func_name[0] = '\0';
9397 func_addr = 0;
9398 incl_index = 0;
9399 last_func_name[0] = '\0';
9400 last_pc = 0xffffffff;
9401 last_line_num = 1;
9402 sym = (Stab_Sym *)stab_section->data + 1;
9403 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9404 while (sym < sym_end) {
9405 switch(sym->n_type) {
9406 /* function start or end */
9407 case N_FUN:
9408 if (sym->n_strx == 0) {
9409 /* we test if between last line and end of function */
9410 pc = sym->n_value + func_addr;
9411 if (wanted_pc >= last_pc && wanted_pc < pc)
9412 goto found;
9413 func_name[0] = '\0';
9414 func_addr = 0;
9415 } else {
9416 str = stabstr_section->data + sym->n_strx;
9417 p = strchr(str, ':');
9418 if (!p) {
9419 pstrcpy(func_name, sizeof(func_name), str);
9420 } else {
9421 len = p - str;
9422 if (len > sizeof(func_name) - 1)
9423 len = sizeof(func_name) - 1;
9424 memcpy(func_name, str, len);
9425 func_name[len] = '\0';
9427 func_addr = sym->n_value;
9429 break;
9430 /* line number info */
9431 case N_SLINE:
9432 pc = sym->n_value + func_addr;
9433 if (wanted_pc >= last_pc && wanted_pc < pc)
9434 goto found;
9435 last_pc = pc;
9436 last_line_num = sym->n_desc;
9437 /* XXX: slow! */
9438 strcpy(last_func_name, func_name);
9439 break;
9440 /* include files */
9441 case N_BINCL:
9442 str = stabstr_section->data + sym->n_strx;
9443 add_incl:
9444 if (incl_index < INCLUDE_STACK_SIZE) {
9445 incl_files[incl_index++] = str;
9447 break;
9448 case N_EINCL:
9449 if (incl_index > 1)
9450 incl_index--;
9451 break;
9452 case N_SO:
9453 if (sym->n_strx == 0) {
9454 incl_index = 0; /* end of translation unit */
9455 } else {
9456 str = stabstr_section->data + sym->n_strx;
9457 /* do not add path */
9458 len = strlen(str);
9459 if (len > 0 && str[len - 1] != '/')
9460 goto add_incl;
9462 break;
9464 sym++;
9467 /* second pass: we try symtab symbols (no line number info) */
9468 incl_index = 0;
9470 Elf32_Sym *sym, *sym_end;
9471 int type;
9473 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9474 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9475 sym < sym_end;
9476 sym++) {
9477 type = ELF32_ST_TYPE(sym->st_info);
9478 if (type == STT_FUNC) {
9479 if (wanted_pc >= sym->st_value &&
9480 wanted_pc < sym->st_value + sym->st_size) {
9481 pstrcpy(last_func_name, sizeof(last_func_name),
9482 strtab_section->data + sym->st_name);
9483 goto found;
9488 /* did not find any info: */
9489 fprintf(stderr, " ???\n");
9490 return;
9491 found:
9492 if (last_func_name[0] != '\0') {
9493 fprintf(stderr, " %s()", last_func_name);
9495 if (incl_index > 0) {
9496 fprintf(stderr, " (%s:%d",
9497 incl_files[incl_index - 1], last_line_num);
9498 for(i = incl_index - 2; i >= 0; i--)
9499 fprintf(stderr, ", included from %s", incl_files[i]);
9500 fprintf(stderr, ")");
9502 fprintf(stderr, "\n");
9505 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9507 #ifdef __i386__
9509 /* fix for glibc 2.1 */
9510 #ifndef REG_EIP
9511 #define REG_EIP EIP
9512 #define REG_EBP EBP
9513 #endif
9515 /* return the PC at frame level 'level'. Return non zero if not found */
9516 static int rt_get_caller_pc(unsigned long *paddr,
9517 ucontext_t *uc, int level)
9519 unsigned long fp;
9520 int i;
9522 if (level == 0) {
9523 #if defined(__FreeBSD__)
9524 *paddr = uc->uc_mcontext.mc_eip;
9525 #elif defined(__dietlibc__)
9526 *paddr = uc->uc_mcontext.eip;
9527 #else
9528 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9529 #endif
9530 return 0;
9531 } else {
9532 #if defined(__FreeBSD__)
9533 fp = uc->uc_mcontext.mc_ebp;
9534 #elif defined(__dietlibc__)
9535 fp = uc->uc_mcontext.ebp;
9536 #else
9537 fp = uc->uc_mcontext.gregs[REG_EBP];
9538 #endif
9539 for(i=1;i<level;i++) {
9540 /* XXX: check address validity with program info */
9541 if (fp <= 0x1000 || fp >= 0xc0000000)
9542 return -1;
9543 fp = ((unsigned long *)fp)[0];
9545 *paddr = ((unsigned long *)fp)[1];
9546 return 0;
9549 #else
9551 #warning add arch specific rt_get_caller_pc()
9553 static int rt_get_caller_pc(unsigned long *paddr,
9554 ucontext_t *uc, int level)
9556 return -1;
9558 #endif
9560 /* emit a run time error at position 'pc' */
9561 void rt_error(ucontext_t *uc, const char *fmt, ...)
9563 va_list ap;
9564 unsigned long pc;
9565 int i;
9567 va_start(ap, fmt);
9568 fprintf(stderr, "Runtime error: ");
9569 vfprintf(stderr, fmt, ap);
9570 fprintf(stderr, "\n");
9571 for(i=0;i<num_callers;i++) {
9572 if (rt_get_caller_pc(&pc, uc, i) < 0)
9573 break;
9574 if (i == 0)
9575 fprintf(stderr, "at ");
9576 else
9577 fprintf(stderr, "by ");
9578 rt_printline(pc);
9580 exit(255);
9581 va_end(ap);
9584 /* signal handler for fatal errors */
9585 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9587 ucontext_t *uc = puc;
9589 switch(signum) {
9590 case SIGFPE:
9591 switch(siginf->si_code) {
9592 case FPE_INTDIV:
9593 case FPE_FLTDIV:
9594 rt_error(uc, "division by zero");
9595 break;
9596 default:
9597 rt_error(uc, "floating point exception");
9598 break;
9600 break;
9601 case SIGBUS:
9602 case SIGSEGV:
9603 if (rt_bound_error_msg && *rt_bound_error_msg)
9604 rt_error(uc, *rt_bound_error_msg);
9605 else
9606 rt_error(uc, "dereferencing invalid pointer");
9607 break;
9608 case SIGILL:
9609 rt_error(uc, "illegal instruction");
9610 break;
9611 case SIGABRT:
9612 rt_error(uc, "abort() called");
9613 break;
9614 default:
9615 rt_error(uc, "caught signal %d", signum);
9616 break;
9618 exit(255);
9620 #endif
9622 /* do all relocations (needed before using tcc_get_symbol()) */
9623 int tcc_relocate(TCCState *s1)
9625 Section *s;
9626 int i;
9628 s1->nb_errors = 0;
9630 #ifdef TCC_TARGET_PE
9631 pe_add_runtime(s1);
9632 #else
9633 tcc_add_runtime(s1);
9634 #endif
9636 relocate_common_syms();
9638 tcc_add_linker_symbols(s1);
9640 build_got_entries(s1);
9642 /* compute relocation address : section are relocated in place. We
9643 also alloc the bss space */
9644 for(i = 1; i < s1->nb_sections; i++) {
9645 s = s1->sections[i];
9646 if (s->sh_flags & SHF_ALLOC) {
9647 if (s->sh_type == SHT_NOBITS)
9648 s->data = tcc_mallocz(s->data_offset);
9649 s->sh_addr = (unsigned long)s->data;
9653 relocate_syms(s1, 1);
9655 if (s1->nb_errors != 0)
9656 return -1;
9658 /* relocate each section */
9659 for(i = 1; i < s1->nb_sections; i++) {
9660 s = s1->sections[i];
9661 if (s->reloc)
9662 relocate_section(s1, s);
9665 /* mark executable sections as executable in memory */
9666 for(i = 1; i < s1->nb_sections; i++) {
9667 s = s1->sections[i];
9668 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
9669 (SHF_ALLOC | SHF_EXECINSTR)) {
9670 #ifdef WIN32
9672 DWORD old_protect;
9673 VirtualProtect(s->data, s->data_offset,
9674 PAGE_EXECUTE_READWRITE, &old_protect);
9676 #else
9678 unsigned long start, end;
9679 start = (unsigned long)(s->data) & ~(PAGESIZE - 1);
9680 end = (unsigned long)(s->data + s->data_offset);
9681 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
9682 mprotect((void *)start, end - start,
9683 PROT_READ | PROT_WRITE | PROT_EXEC);
9685 #endif
9688 return 0;
9691 /* launch the compiled program with the given arguments */
9692 int tcc_run(TCCState *s1, int argc, char **argv)
9694 int (*prog_main)(int, char **);
9696 if (tcc_relocate(s1) < 0)
9697 return -1;
9699 prog_main = tcc_get_symbol_err(s1, "main");
9701 if (do_debug) {
9702 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9703 error("debug mode currently not available for Windows");
9704 #else
9705 struct sigaction sigact;
9706 /* install TCC signal handlers to print debug info on fatal
9707 runtime errors */
9708 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9709 sigact.sa_sigaction = sig_error;
9710 sigemptyset(&sigact.sa_mask);
9711 sigaction(SIGFPE, &sigact, NULL);
9712 sigaction(SIGILL, &sigact, NULL);
9713 sigaction(SIGSEGV, &sigact, NULL);
9714 sigaction(SIGBUS, &sigact, NULL);
9715 sigaction(SIGABRT, &sigact, NULL);
9716 #endif
9719 #ifdef CONFIG_TCC_BCHECK
9720 if (do_bounds_check) {
9721 void (*bound_init)(void);
9723 /* set error function */
9724 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9725 "__bound_error_msg");
9727 /* XXX: use .init section so that it also work in binary ? */
9728 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9729 bound_init();
9731 #endif
9732 return (*prog_main)(argc, argv);
9735 TCCState *tcc_new(void)
9737 const char *p, *r;
9738 TCCState *s;
9739 TokenSym *ts;
9740 int i, c;
9742 s = tcc_mallocz(sizeof(TCCState));
9743 if (!s)
9744 return NULL;
9745 tcc_state = s;
9746 s->output_type = TCC_OUTPUT_MEMORY;
9748 /* init isid table */
9749 for(i=0;i<256;i++)
9750 isidnum_table[i] = isid(i) || isnum(i);
9752 /* add all tokens */
9753 table_ident = NULL;
9754 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9756 tok_ident = TOK_IDENT;
9757 p = tcc_keywords;
9758 while (*p) {
9759 r = p;
9760 for(;;) {
9761 c = *r++;
9762 if (c == '\0')
9763 break;
9765 ts = tok_alloc(p, r - p - 1);
9766 p = r;
9769 /* we add dummy defines for some special macros to speed up tests
9770 and to have working defined() */
9771 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9772 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9773 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9774 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9776 /* standard defines */
9777 tcc_define_symbol(s, "__STDC__", NULL);
9778 #if defined(TCC_TARGET_I386)
9779 tcc_define_symbol(s, "__i386__", NULL);
9780 #endif
9781 #if defined(TCC_TARGET_ARM)
9782 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9783 tcc_define_symbol(s, "__arm_elf__", NULL);
9784 tcc_define_symbol(s, "__arm_elf", NULL);
9785 tcc_define_symbol(s, "arm_elf", NULL);
9786 tcc_define_symbol(s, "__arm__", NULL);
9787 tcc_define_symbol(s, "__arm", NULL);
9788 tcc_define_symbol(s, "arm", NULL);
9789 tcc_define_symbol(s, "__APCS_32__", NULL);
9790 #endif
9791 #if defined(linux)
9792 tcc_define_symbol(s, "__linux__", NULL);
9793 tcc_define_symbol(s, "linux", NULL);
9794 #endif
9795 /* tiny C specific defines */
9796 tcc_define_symbol(s, "__TINYC__", NULL);
9798 /* tiny C & gcc defines */
9799 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9800 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9801 #ifdef TCC_TARGET_PE
9802 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
9803 #else
9804 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9805 #endif
9807 /* default library paths */
9808 #ifdef TCC_TARGET_PE
9810 char buf[1024];
9811 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
9812 tcc_add_library_path(s, buf);
9814 #else
9815 tcc_add_library_path(s, "/usr/local/lib");
9816 tcc_add_library_path(s, "/usr/lib");
9817 tcc_add_library_path(s, "/lib");
9818 #endif
9820 /* no section zero */
9821 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9823 /* create standard sections */
9824 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9825 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9826 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9828 /* symbols are always generated for linking stage */
9829 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9830 ".strtab",
9831 ".hashtab", SHF_PRIVATE);
9832 strtab_section = symtab_section->link;
9834 /* private symbol table for dynamic symbols */
9835 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9836 ".dynstrtab",
9837 ".dynhashtab", SHF_PRIVATE);
9838 s->alacarte_link = 1;
9840 #ifdef CHAR_IS_UNSIGNED
9841 s->char_is_unsigned = 1;
9842 #endif
9843 #if defined(TCC_TARGET_PE) && 0
9844 /* XXX: currently the PE linker is not ready to support that */
9845 s->leading_underscore = 1;
9846 #endif
9847 return s;
9850 void tcc_delete(TCCState *s1)
9852 int i, n;
9854 /* free -D defines */
9855 free_defines(NULL);
9857 /* free tokens */
9858 n = tok_ident - TOK_IDENT;
9859 for(i = 0; i < n; i++)
9860 tcc_free(table_ident[i]);
9861 tcc_free(table_ident);
9863 /* free all sections */
9865 free_section(symtab_section->hash);
9867 free_section(s1->dynsymtab_section->hash);
9868 free_section(s1->dynsymtab_section->link);
9869 free_section(s1->dynsymtab_section);
9871 for(i = 1; i < s1->nb_sections; i++)
9872 free_section(s1->sections[i]);
9873 tcc_free(s1->sections);
9875 /* free loaded dlls array */
9876 for(i = 0; i < s1->nb_loaded_dlls; i++)
9877 tcc_free(s1->loaded_dlls[i]);
9878 tcc_free(s1->loaded_dlls);
9880 /* library paths */
9881 for(i = 0; i < s1->nb_library_paths; i++)
9882 tcc_free(s1->library_paths[i]);
9883 tcc_free(s1->library_paths);
9885 /* cached includes */
9886 for(i = 0; i < s1->nb_cached_includes; i++)
9887 tcc_free(s1->cached_includes[i]);
9888 tcc_free(s1->cached_includes);
9890 for(i = 0; i < s1->nb_include_paths; i++)
9891 tcc_free(s1->include_paths[i]);
9892 tcc_free(s1->include_paths);
9894 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9895 tcc_free(s1->sysinclude_paths[i]);
9896 tcc_free(s1->sysinclude_paths);
9898 tcc_free(s1);
9901 int tcc_add_include_path(TCCState *s1, const char *pathname)
9903 char *pathname1;
9905 pathname1 = tcc_strdup(pathname);
9906 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9907 return 0;
9910 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9912 char *pathname1;
9914 pathname1 = tcc_strdup(pathname);
9915 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9916 return 0;
9919 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9921 const char *ext, *filename1;
9922 Elf32_Ehdr ehdr;
9923 int fd, ret;
9924 BufferedFile *saved_file;
9926 /* find source file type with extension */
9927 filename1 = strrchr(filename, '/');
9928 if (filename1)
9929 filename1++;
9930 else
9931 filename1 = filename;
9932 ext = strrchr(filename1, '.');
9933 if (ext)
9934 ext++;
9936 /* open the file */
9937 saved_file = file;
9938 file = tcc_open(s1, filename);
9939 if (!file) {
9940 if (flags & AFF_PRINT_ERROR) {
9941 error_noabort("file '%s' not found", filename);
9943 ret = -1;
9944 goto fail1;
9947 if (!ext || !strcmp(ext, "c")) {
9948 /* C file assumed */
9949 ret = tcc_compile(s1);
9950 } else
9951 #ifdef CONFIG_TCC_ASM
9952 if (!strcmp(ext, "S")) {
9953 /* preprocessed assembler */
9954 ret = tcc_assemble(s1, 1);
9955 } else if (!strcmp(ext, "s")) {
9956 /* non preprocessed assembler */
9957 ret = tcc_assemble(s1, 0);
9958 } else
9959 #endif
9960 #ifdef TCC_TARGET_PE
9961 if (!strcmp(ext, "def")) {
9962 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
9963 } else
9964 #endif
9966 fd = file->fd;
9967 /* assume executable format: auto guess file type */
9968 ret = read(fd, &ehdr, sizeof(ehdr));
9969 lseek(fd, 0, SEEK_SET);
9970 if (ret <= 0) {
9971 error_noabort("could not read header");
9972 goto fail;
9973 } else if (ret != sizeof(ehdr)) {
9974 goto try_load_script;
9977 if (ehdr.e_ident[0] == ELFMAG0 &&
9978 ehdr.e_ident[1] == ELFMAG1 &&
9979 ehdr.e_ident[2] == ELFMAG2 &&
9980 ehdr.e_ident[3] == ELFMAG3) {
9981 file->line_num = 0; /* do not display line number if error */
9982 if (ehdr.e_type == ET_REL) {
9983 ret = tcc_load_object_file(s1, fd, 0);
9984 } else if (ehdr.e_type == ET_DYN) {
9985 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9986 #ifdef TCC_TARGET_PE
9987 ret = -1;
9988 #else
9989 void *h;
9990 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9991 if (h)
9992 ret = 0;
9993 else
9994 ret = -1;
9995 #endif
9996 } else {
9997 ret = tcc_load_dll(s1, fd, filename,
9998 (flags & AFF_REFERENCED_DLL) != 0);
10000 } else {
10001 error_noabort("unrecognized ELF file");
10002 goto fail;
10004 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10005 file->line_num = 0; /* do not display line number if error */
10006 ret = tcc_load_archive(s1, fd);
10007 } else
10008 #ifdef TCC_TARGET_COFF
10009 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10010 ret = tcc_load_coff(s1, fd);
10011 } else
10012 #endif
10014 /* as GNU ld, consider it is an ld script if not recognized */
10015 try_load_script:
10016 ret = tcc_load_ldscript(s1);
10017 if (ret < 0) {
10018 error_noabort("unrecognized file type");
10019 goto fail;
10023 the_end:
10024 tcc_close(file);
10025 fail1:
10026 file = saved_file;
10027 return ret;
10028 fail:
10029 ret = -1;
10030 goto the_end;
10033 int tcc_add_file(TCCState *s, const char *filename)
10035 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10038 int tcc_add_library_path(TCCState *s, const char *pathname)
10040 char *pathname1;
10042 pathname1 = tcc_strdup(pathname);
10043 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10044 return 0;
10047 /* find and load a dll. Return non zero if not found */
10048 /* XXX: add '-rpath' option support ? */
10049 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10051 char buf[1024];
10052 int i;
10054 for(i = 0; i < s->nb_library_paths; i++) {
10055 snprintf(buf, sizeof(buf), "%s/%s",
10056 s->library_paths[i], filename);
10057 if (tcc_add_file_internal(s, buf, flags) == 0)
10058 return 0;
10060 return -1;
10063 /* the library name is the same as the argument of the '-l' option */
10064 int tcc_add_library(TCCState *s, const char *libraryname)
10066 char buf[1024];
10067 int i;
10069 /* first we look for the dynamic library if not static linking */
10070 if (!s->static_link) {
10071 #ifdef TCC_TARGET_PE
10072 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10073 #else
10074 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10075 #endif
10076 if (tcc_add_dll(s, buf, 0) == 0)
10077 return 0;
10080 /* then we look for the static library */
10081 for(i = 0; i < s->nb_library_paths; i++) {
10082 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10083 s->library_paths[i], libraryname);
10084 if (tcc_add_file_internal(s, buf, 0) == 0)
10085 return 0;
10087 return -1;
10090 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10092 add_elf_sym(symtab_section, val, 0,
10093 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10094 SHN_ABS, name);
10095 return 0;
10098 int tcc_set_output_type(TCCState *s, int output_type)
10100 s->output_type = output_type;
10102 if (!s->nostdinc) {
10103 char buf[1024];
10105 /* default include paths */
10106 /* XXX: reverse order needed if -isystem support */
10107 #ifndef TCC_TARGET_PE
10108 tcc_add_sysinclude_path(s, "/usr/local/include");
10109 tcc_add_sysinclude_path(s, "/usr/include");
10110 #endif
10111 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10112 tcc_add_sysinclude_path(s, buf);
10113 #ifdef TCC_TARGET_PE
10114 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10115 tcc_add_sysinclude_path(s, buf);
10116 #endif
10119 /* if bound checking, then add corresponding sections */
10120 #ifdef CONFIG_TCC_BCHECK
10121 if (do_bounds_check) {
10122 /* define symbol */
10123 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10124 /* create bounds sections */
10125 bounds_section = new_section(s, ".bounds",
10126 SHT_PROGBITS, SHF_ALLOC);
10127 lbounds_section = new_section(s, ".lbounds",
10128 SHT_PROGBITS, SHF_ALLOC);
10130 #endif
10132 if (s->char_is_unsigned) {
10133 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10136 /* add debug sections */
10137 if (do_debug) {
10138 /* stab symbols */
10139 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10140 stab_section->sh_entsize = sizeof(Stab_Sym);
10141 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10142 put_elf_str(stabstr_section, "");
10143 stab_section->link = stabstr_section;
10144 /* put first entry */
10145 put_stabs("", 0, 0, 0, 0);
10148 /* add libc crt1/crti objects */
10149 #ifndef TCC_TARGET_PE
10150 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10151 !s->nostdlib) {
10152 if (output_type != TCC_OUTPUT_DLL)
10153 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10154 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10156 #endif
10157 return 0;
10160 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10161 #define FD_INVERT 0x0002 /* invert value before storing */
10163 typedef struct FlagDef {
10164 uint16_t offset;
10165 uint16_t flags;
10166 const char *name;
10167 } FlagDef;
10169 static const FlagDef warning_defs[] = {
10170 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10171 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10172 { offsetof(TCCState, warn_error), 0, "error" },
10173 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10174 "implicit-function-declaration" },
10177 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10178 const char *name, int value)
10180 int i;
10181 const FlagDef *p;
10182 const char *r;
10184 r = name;
10185 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10186 r += 3;
10187 value = !value;
10189 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10190 if (!strcmp(r, p->name))
10191 goto found;
10193 return -1;
10194 found:
10195 if (p->flags & FD_INVERT)
10196 value = !value;
10197 *(int *)((uint8_t *)s + p->offset) = value;
10198 return 0;
10202 /* set/reset a warning */
10203 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10205 int i;
10206 const FlagDef *p;
10208 if (!strcmp(warning_name, "all")) {
10209 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10210 if (p->flags & WD_ALL)
10211 *(int *)((uint8_t *)s + p->offset) = 1;
10213 return 0;
10214 } else {
10215 return set_flag(s, warning_defs, countof(warning_defs),
10216 warning_name, value);
10220 static const FlagDef flag_defs[] = {
10221 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10222 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10223 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10224 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10227 /* set/reset a flag */
10228 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10230 return set_flag(s, flag_defs, countof(flag_defs),
10231 flag_name, value);
10234 #if !defined(LIBTCC)
10236 /* extract the basename of a file */
10237 static const char *tcc_basename(const char *name)
10239 const char *p;
10240 p = strrchr(name, '/');
10241 #ifdef WIN32
10242 if (!p)
10243 p = strrchr(name, '\\');
10244 #endif
10245 if (!p)
10246 p = name;
10247 else
10248 p++;
10249 return p;
10252 static int64_t getclock_us(void)
10254 #ifdef WIN32
10255 struct _timeb tb;
10256 _ftime(&tb);
10257 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10258 #else
10259 struct timeval tv;
10260 gettimeofday(&tv, NULL);
10261 return tv.tv_sec * 1000000LL + tv.tv_usec;
10262 #endif
10265 void help(void)
10267 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2005 Fabrice Bellard\n"
10268 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10269 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10270 " [infile1 infile2...] [-run infile args...]\n"
10271 "\n"
10272 "General options:\n"
10273 " -v display current version\n"
10274 " -c compile only - generate an object file\n"
10275 " -o outfile set output filename\n"
10276 " -Bdir set tcc internal library path\n"
10277 " -bench output compilation statistics\n"
10278 " -run run compiled source\n"
10279 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10280 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10281 " -w disable all warnings\n"
10282 "Preprocessor options:\n"
10283 " -Idir add include path 'dir'\n"
10284 " -Dsym[=val] define 'sym' with value 'val'\n"
10285 " -Usym undefine 'sym'\n"
10286 "Linker options:\n"
10287 " -Ldir add library path 'dir'\n"
10288 " -llib link with dynamic or static library 'lib'\n"
10289 " -shared generate a shared library\n"
10290 " -static static linking\n"
10291 " -rdynamic export all global symbols to dynamic linker\n"
10292 " -r relocatable output\n"
10293 "Debugger options:\n"
10294 " -g generate runtime debug info\n"
10295 #ifdef CONFIG_TCC_BCHECK
10296 " -b compile with built-in memory and bounds checker (implies -g)\n"
10297 #endif
10298 " -bt N show N callers in stack traces\n"
10302 #define TCC_OPTION_HAS_ARG 0x0001
10303 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10305 typedef struct TCCOption {
10306 const char *name;
10307 uint16_t index;
10308 uint16_t flags;
10309 } TCCOption;
10311 enum {
10312 TCC_OPTION_HELP,
10313 TCC_OPTION_I,
10314 TCC_OPTION_D,
10315 TCC_OPTION_U,
10316 TCC_OPTION_L,
10317 TCC_OPTION_B,
10318 TCC_OPTION_l,
10319 TCC_OPTION_bench,
10320 TCC_OPTION_bt,
10321 TCC_OPTION_b,
10322 TCC_OPTION_g,
10323 TCC_OPTION_c,
10324 TCC_OPTION_static,
10325 TCC_OPTION_shared,
10326 TCC_OPTION_o,
10327 TCC_OPTION_r,
10328 TCC_OPTION_Wl,
10329 TCC_OPTION_W,
10330 TCC_OPTION_O,
10331 TCC_OPTION_m,
10332 TCC_OPTION_f,
10333 TCC_OPTION_nostdinc,
10334 TCC_OPTION_nostdlib,
10335 TCC_OPTION_print_search_dirs,
10336 TCC_OPTION_rdynamic,
10337 TCC_OPTION_run,
10338 TCC_OPTION_v,
10339 TCC_OPTION_w,
10340 TCC_OPTION_pipe,
10343 static const TCCOption tcc_options[] = {
10344 { "h", TCC_OPTION_HELP, 0 },
10345 { "?", TCC_OPTION_HELP, 0 },
10346 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10347 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10348 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10349 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10350 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10351 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10352 { "bench", TCC_OPTION_bench, 0 },
10353 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10354 #ifdef CONFIG_TCC_BCHECK
10355 { "b", TCC_OPTION_b, 0 },
10356 #endif
10357 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10358 { "c", TCC_OPTION_c, 0 },
10359 { "static", TCC_OPTION_static, 0 },
10360 { "shared", TCC_OPTION_shared, 0 },
10361 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10362 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10363 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10364 { "r", TCC_OPTION_r, 0 },
10365 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10366 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10367 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10368 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10369 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10370 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10371 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10372 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10373 { "v", TCC_OPTION_v, 0 },
10374 { "w", TCC_OPTION_w, 0 },
10375 { "pipe", TCC_OPTION_pipe, 0},
10376 { NULL },
10379 /* convert 'str' into an array of space separated strings */
10380 static int expand_args(char ***pargv, const char *str)
10382 const char *s1;
10383 char **argv, *arg;
10384 int argc, len;
10386 argc = 0;
10387 argv = NULL;
10388 for(;;) {
10389 while (is_space(*str))
10390 str++;
10391 if (*str == '\0')
10392 break;
10393 s1 = str;
10394 while (*str != '\0' && !is_space(*str))
10395 str++;
10396 len = str - s1;
10397 arg = tcc_malloc(len + 1);
10398 memcpy(arg, s1, len);
10399 arg[len] = '\0';
10400 dynarray_add((void ***)&argv, &argc, arg);
10402 *pargv = argv;
10403 return argc;
10406 static char **files;
10407 static int nb_files, nb_libraries;
10408 static int multiple_files;
10409 static int print_search_dirs;
10410 static int output_type;
10411 static int reloc_output;
10412 static const char *outfile;
10414 int parse_args(TCCState *s, int argc, char **argv)
10416 int optind;
10417 const TCCOption *popt;
10418 const char *optarg, *p1, *r1;
10419 char *r;
10421 optind = 0;
10422 while (1) {
10423 if (optind >= argc) {
10424 if (nb_files == 0 && !print_search_dirs)
10425 goto show_help;
10426 else
10427 break;
10429 r = argv[optind++];
10430 if (r[0] != '-') {
10431 /* add a new file */
10432 dynarray_add((void ***)&files, &nb_files, r);
10433 if (!multiple_files) {
10434 optind--;
10435 /* argv[0] will be this file */
10436 break;
10438 } else {
10439 /* find option in table (match only the first chars */
10440 popt = tcc_options;
10441 for(;;) {
10442 p1 = popt->name;
10443 if (p1 == NULL)
10444 error("invalid option -- '%s'", r);
10445 r1 = r + 1;
10446 for(;;) {
10447 if (*p1 == '\0')
10448 goto option_found;
10449 if (*r1 != *p1)
10450 break;
10451 p1++;
10452 r1++;
10454 popt++;
10456 option_found:
10457 if (popt->flags & TCC_OPTION_HAS_ARG) {
10458 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10459 optarg = r1;
10460 } else {
10461 if (optind >= argc)
10462 error("argument to '%s' is missing", r);
10463 optarg = argv[optind++];
10465 } else {
10466 if (*r1 != '\0')
10467 goto show_help;
10468 optarg = NULL;
10471 switch(popt->index) {
10472 case TCC_OPTION_HELP:
10473 show_help:
10474 help();
10475 exit(1);
10476 case TCC_OPTION_I:
10477 if (tcc_add_include_path(s, optarg) < 0)
10478 error("too many include paths");
10479 break;
10480 case TCC_OPTION_D:
10482 char *sym, *value;
10483 sym = (char *)optarg;
10484 value = strchr(sym, '=');
10485 if (value) {
10486 *value = '\0';
10487 value++;
10489 tcc_define_symbol(s, sym, value);
10491 break;
10492 case TCC_OPTION_U:
10493 tcc_undefine_symbol(s, optarg);
10494 break;
10495 case TCC_OPTION_L:
10496 tcc_add_library_path(s, optarg);
10497 break;
10498 case TCC_OPTION_B:
10499 /* set tcc utilities path (mainly for tcc development) */
10500 tcc_lib_path = optarg;
10501 break;
10502 case TCC_OPTION_l:
10503 dynarray_add((void ***)&files, &nb_files, r);
10504 nb_libraries++;
10505 break;
10506 case TCC_OPTION_bench:
10507 do_bench = 1;
10508 break;
10509 case TCC_OPTION_bt:
10510 num_callers = atoi(optarg);
10511 break;
10512 #ifdef CONFIG_TCC_BCHECK
10513 case TCC_OPTION_b:
10514 do_bounds_check = 1;
10515 do_debug = 1;
10516 break;
10517 #endif
10518 case TCC_OPTION_g:
10519 do_debug = 1;
10520 break;
10521 case TCC_OPTION_c:
10522 multiple_files = 1;
10523 output_type = TCC_OUTPUT_OBJ;
10524 break;
10525 case TCC_OPTION_static:
10526 s->static_link = 1;
10527 break;
10528 case TCC_OPTION_shared:
10529 output_type = TCC_OUTPUT_DLL;
10530 break;
10531 case TCC_OPTION_o:
10532 multiple_files = 1;
10533 outfile = optarg;
10534 break;
10535 case TCC_OPTION_r:
10536 /* generate a .o merging several output files */
10537 reloc_output = 1;
10538 output_type = TCC_OUTPUT_OBJ;
10539 break;
10540 case TCC_OPTION_nostdinc:
10541 s->nostdinc = 1;
10542 break;
10543 case TCC_OPTION_nostdlib:
10544 s->nostdlib = 1;
10545 break;
10546 case TCC_OPTION_print_search_dirs:
10547 print_search_dirs = 1;
10548 break;
10549 case TCC_OPTION_run:
10551 int argc1;
10552 char **argv1;
10553 argc1 = expand_args(&argv1, optarg);
10554 if (argc1 > 0) {
10555 parse_args(s, argc1, argv1);
10557 multiple_files = 0;
10558 output_type = TCC_OUTPUT_MEMORY;
10560 break;
10561 case TCC_OPTION_v:
10562 printf("tcc version %s\n", TCC_VERSION);
10563 exit(0);
10564 case TCC_OPTION_f:
10565 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10566 goto unsupported_option;
10567 break;
10568 case TCC_OPTION_W:
10569 if (tcc_set_warning(s, optarg, 1) < 0 &&
10570 s->warn_unsupported)
10571 goto unsupported_option;
10572 break;
10573 case TCC_OPTION_w:
10574 s->warn_none = 1;
10575 break;
10576 case TCC_OPTION_rdynamic:
10577 s->rdynamic = 1;
10578 break;
10579 case TCC_OPTION_Wl:
10581 const char *p;
10582 if (strstart(optarg, "-Ttext,", &p)) {
10583 s->text_addr = strtoul(p, NULL, 16);
10584 s->has_text_addr = 1;
10585 } else if (strstart(optarg, "--oformat,", &p)) {
10586 if (strstart(p, "elf32-", NULL)) {
10587 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10588 } else if (!strcmp(p, "binary")) {
10589 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10590 } else
10591 #ifdef TCC_TARGET_COFF
10592 if (!strcmp(p, "coff")) {
10593 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10594 } else
10595 #endif
10597 error("target %s not found", p);
10599 } else {
10600 error("unsupported linker option '%s'", optarg);
10603 break;
10604 default:
10605 if (s->warn_unsupported) {
10606 unsupported_option:
10607 warning("unsupported option '%s'", r);
10609 break;
10613 return optind;
10616 int main(int argc, char **argv)
10618 int i;
10619 TCCState *s;
10620 int nb_objfiles, ret, optind;
10621 char objfilename[1024];
10622 int64_t start_time = 0;
10624 #ifdef WIN32
10625 /* on win32, we suppose the lib and includes are at the location
10626 of 'tcc.exe' */
10628 static char path[1024];
10629 char *p, *d;
10631 GetModuleFileNameA(NULL, path, sizeof path);
10632 p = d = strlwr(path);
10633 while (*d)
10635 if (*d == '\\') *d = '/', p = d;
10636 ++d;
10638 *p = '\0';
10639 tcc_lib_path = path;
10641 #endif
10643 s = tcc_new();
10644 output_type = TCC_OUTPUT_EXE;
10645 outfile = NULL;
10646 multiple_files = 1;
10647 files = NULL;
10648 nb_files = 0;
10649 nb_libraries = 0;
10650 reloc_output = 0;
10651 print_search_dirs = 0;
10653 optind = parse_args(s, argc - 1, argv + 1) + 1;
10655 if (print_search_dirs) {
10656 /* enough for Linux kernel */
10657 printf("install: %s/\n", tcc_lib_path);
10658 return 0;
10661 nb_objfiles = nb_files - nb_libraries;
10663 /* if outfile provided without other options, we output an
10664 executable */
10665 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10666 output_type = TCC_OUTPUT_EXE;
10668 /* check -c consistency : only single file handled. XXX: checks file type */
10669 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10670 /* accepts only a single input file */
10671 if (nb_objfiles != 1)
10672 error("cannot specify multiple files with -c");
10673 if (nb_libraries != 0)
10674 error("cannot specify libraries with -c");
10677 if (output_type != TCC_OUTPUT_MEMORY) {
10678 if (!outfile) {
10679 /* compute default outfile name */
10680 pstrcpy(objfilename, sizeof(objfilename) - 1,
10681 /* strip path */
10682 tcc_basename(files[0]));
10683 #ifdef TCC_TARGET_PE
10684 pe_guess_outfile(objfilename, output_type);
10685 #else
10686 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10687 char *ext = strrchr(objfilename, '.');
10688 if (!ext)
10689 goto default_outfile;
10690 /* add .o extension */
10691 strcpy(ext + 1, "o");
10692 } else {
10693 default_outfile:
10694 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10696 #endif
10697 outfile = objfilename;
10701 if (do_bench) {
10702 start_time = getclock_us();
10705 tcc_set_output_type(s, output_type);
10707 /* compile or add each files or library */
10708 for(i = 0;i < nb_files; i++) {
10709 const char *filename;
10711 filename = files[i];
10712 if (filename[0] == '-') {
10713 if (tcc_add_library(s, filename + 2) < 0)
10714 error("cannot find %s", filename);
10715 } else {
10716 if (tcc_add_file(s, filename) < 0) {
10717 ret = 1;
10718 goto the_end;
10723 /* free all files */
10724 tcc_free(files);
10726 if (do_bench) {
10727 double total_time;
10728 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10729 if (total_time < 0.001)
10730 total_time = 0.001;
10731 if (total_bytes < 1)
10732 total_bytes = 1;
10733 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10734 tok_ident - TOK_IDENT, total_lines, total_bytes,
10735 total_time, (int)(total_lines / total_time),
10736 total_bytes / total_time / 1000000.0);
10739 if (s->output_type == TCC_OUTPUT_MEMORY) {
10740 ret = tcc_run(s, argc - optind, argv + optind);
10741 } else
10742 #ifdef TCC_TARGET_PE
10743 if (s->output_type != TCC_OUTPUT_OBJ) {
10744 ret = tcc_output_pe(s, outfile);
10745 } else
10746 #endif
10748 tcc_output_file(s, outfile);
10749 ret = 0;
10751 the_end:
10752 /* XXX: cannot do it with bound checking because of the malloc hooks */
10753 if (!do_bounds_check)
10754 tcc_delete(s);
10756 #ifdef MEM_DEBUG
10757 if (do_bench) {
10758 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10760 #endif
10761 return ret;
10764 #endif