Bug fix: A long long value used as a test expression ignores the upper 32 bits at...
[tinycc/daniel.git] / tcc.c
blobac2216265ad212cf56bf8155e14c5b1dfb5e50ab
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;
508 /* output file for preprocessing */
509 FILE *outfile;
512 /* The current value can be: */
513 #define VT_VALMASK 0x00ff
514 #define VT_CONST 0x00f0 /* constant in vc
515 (must be first non register value) */
516 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
517 #define VT_LOCAL 0x00f2 /* offset on stack */
518 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
519 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
520 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
521 #define VT_LVAL 0x0100 /* var is an lvalue */
522 #define VT_SYM 0x0200 /* a symbol value is added */
523 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
524 char/short stored in integer registers) */
525 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
526 dereferencing value */
527 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
528 bounding function call point is in vc */
529 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
530 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
531 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
532 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
534 /* types */
535 #define VT_INT 0 /* integer type */
536 #define VT_BYTE 1 /* signed byte type */
537 #define VT_SHORT 2 /* short type */
538 #define VT_VOID 3 /* void type */
539 #define VT_PTR 4 /* pointer */
540 #define VT_ENUM 5 /* enum definition */
541 #define VT_FUNC 6 /* function type */
542 #define VT_STRUCT 7 /* struct/union definition */
543 #define VT_FLOAT 8 /* IEEE float */
544 #define VT_DOUBLE 9 /* IEEE double */
545 #define VT_LDOUBLE 10 /* IEEE long double */
546 #define VT_BOOL 11 /* ISOC99 boolean type */
547 #define VT_LLONG 12 /* 64 bit integer */
548 #define VT_LONG 13 /* long integer (NEVER USED as type, only
549 during parsing) */
550 #define VT_BTYPE 0x000f /* mask for basic type */
551 #define VT_UNSIGNED 0x0010 /* unsigned type */
552 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
553 #define VT_BITFIELD 0x0040 /* bitfield modifier */
554 #define VT_CONSTANT 0x0800 /* const modifier */
555 #define VT_VOLATILE 0x1000 /* volatile modifier */
556 #define VT_SIGNED 0x2000 /* signed type */
558 /* storage */
559 #define VT_EXTERN 0x00000080 /* extern definition */
560 #define VT_STATIC 0x00000100 /* static variable */
561 #define VT_TYPEDEF 0x00000200 /* typedef definition */
562 #define VT_INLINE 0x00000400 /* inline definition */
564 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
566 /* type mask (except storage) */
567 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
568 #define VT_TYPE (~(VT_STORAGE))
570 /* token values */
572 /* warning: the following compare tokens depend on i386 asm code */
573 #define TOK_ULT 0x92
574 #define TOK_UGE 0x93
575 #define TOK_EQ 0x94
576 #define TOK_NE 0x95
577 #define TOK_ULE 0x96
578 #define TOK_UGT 0x97
579 #define TOK_LT 0x9c
580 #define TOK_GE 0x9d
581 #define TOK_LE 0x9e
582 #define TOK_GT 0x9f
584 #define TOK_LAND 0xa0
585 #define TOK_LOR 0xa1
587 #define TOK_DEC 0xa2
588 #define TOK_MID 0xa3 /* inc/dec, to void constant */
589 #define TOK_INC 0xa4
590 #define TOK_UDIV 0xb0 /* unsigned division */
591 #define TOK_UMOD 0xb1 /* unsigned modulo */
592 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
593 #define TOK_CINT 0xb3 /* number in tokc */
594 #define TOK_CCHAR 0xb4 /* char constant in tokc */
595 #define TOK_STR 0xb5 /* pointer to string in tokc */
596 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
597 #define TOK_LCHAR 0xb7
598 #define TOK_LSTR 0xb8
599 #define TOK_CFLOAT 0xb9 /* float constant */
600 #define TOK_LINENUM 0xba /* line number info */
601 #define TOK_CDOUBLE 0xc0 /* double constant */
602 #define TOK_CLDOUBLE 0xc1 /* long double constant */
603 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
604 #define TOK_ADDC1 0xc3 /* add with carry generation */
605 #define TOK_ADDC2 0xc4 /* add with carry use */
606 #define TOK_SUBC1 0xc5 /* add with carry generation */
607 #define TOK_SUBC2 0xc6 /* add with carry use */
608 #define TOK_CUINT 0xc8 /* unsigned int constant */
609 #define TOK_CLLONG 0xc9 /* long long constant */
610 #define TOK_CULLONG 0xca /* unsigned long long constant */
611 #define TOK_ARROW 0xcb
612 #define TOK_DOTS 0xcc /* three dots */
613 #define TOK_SHR 0xcd /* unsigned shift right */
614 #define TOK_PPNUM 0xce /* preprocessor number */
616 #define TOK_SHL 0x01 /* shift left */
617 #define TOK_SAR 0x02 /* signed shift right */
619 /* assignement operators : normal operator or 0x80 */
620 #define TOK_A_MOD 0xa5
621 #define TOK_A_AND 0xa6
622 #define TOK_A_MUL 0xaa
623 #define TOK_A_ADD 0xab
624 #define TOK_A_SUB 0xad
625 #define TOK_A_DIV 0xaf
626 #define TOK_A_XOR 0xde
627 #define TOK_A_OR 0xfc
628 #define TOK_A_SHL 0x81
629 #define TOK_A_SAR 0x82
631 #ifndef offsetof
632 #define offsetof(type, field) ((size_t) &((type *)0)->field)
633 #endif
635 #ifndef countof
636 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
637 #endif
639 /* WARNING: the content of this string encodes token numbers */
640 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";
642 #define TOK_EOF (-1) /* end of file */
643 #define TOK_LINEFEED 10 /* line feed */
645 /* all identificators and strings have token above that */
646 #define TOK_IDENT 256
648 /* only used for i386 asm opcodes definitions */
649 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
651 #define DEF_BWL(x) \
652 DEF(TOK_ASM_ ## x ## b, #x "b") \
653 DEF(TOK_ASM_ ## x ## w, #x "w") \
654 DEF(TOK_ASM_ ## x ## l, #x "l") \
655 DEF(TOK_ASM_ ## x, #x)
657 #define DEF_WL(x) \
658 DEF(TOK_ASM_ ## x ## w, #x "w") \
659 DEF(TOK_ASM_ ## x ## l, #x "l") \
660 DEF(TOK_ASM_ ## x, #x)
662 #define DEF_FP1(x) \
663 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
664 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
665 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
666 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
668 #define DEF_FP(x) \
669 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
670 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
671 DEF_FP1(x)
673 #define DEF_ASMTEST(x) \
674 DEF_ASM(x ## o) \
675 DEF_ASM(x ## no) \
676 DEF_ASM(x ## b) \
677 DEF_ASM(x ## c) \
678 DEF_ASM(x ## nae) \
679 DEF_ASM(x ## nb) \
680 DEF_ASM(x ## nc) \
681 DEF_ASM(x ## ae) \
682 DEF_ASM(x ## e) \
683 DEF_ASM(x ## z) \
684 DEF_ASM(x ## ne) \
685 DEF_ASM(x ## nz) \
686 DEF_ASM(x ## be) \
687 DEF_ASM(x ## na) \
688 DEF_ASM(x ## nbe) \
689 DEF_ASM(x ## a) \
690 DEF_ASM(x ## s) \
691 DEF_ASM(x ## ns) \
692 DEF_ASM(x ## p) \
693 DEF_ASM(x ## pe) \
694 DEF_ASM(x ## np) \
695 DEF_ASM(x ## po) \
696 DEF_ASM(x ## l) \
697 DEF_ASM(x ## nge) \
698 DEF_ASM(x ## nl) \
699 DEF_ASM(x ## ge) \
700 DEF_ASM(x ## le) \
701 DEF_ASM(x ## ng) \
702 DEF_ASM(x ## nle) \
703 DEF_ASM(x ## g)
705 #define TOK_ASM_int TOK_INT
707 enum tcc_token {
708 TOK_LAST = TOK_IDENT - 1,
709 #define DEF(id, str) id,
710 #include "tcctok.h"
711 #undef DEF
714 static const char tcc_keywords[] =
715 #define DEF(id, str) str "\0"
716 #include "tcctok.h"
717 #undef DEF
720 #define TOK_UIDENT TOK_DEFINE
722 #ifdef WIN32
723 int __stdcall GetModuleFileNameA(void *, char *, int);
724 void *__stdcall GetProcAddress(void *, const char *);
725 void *__stdcall GetModuleHandleA(const char *);
726 void *__stdcall LoadLibraryA(const char *);
727 int __stdcall FreeConsole(void);
729 #define snprintf _snprintf
730 #define vsnprintf _vsnprintf
731 #ifndef __GNUC__
732 #define strtold (long double)strtod
733 #define strtof (float)strtod
734 #define strtoll (long long)strtol
735 #endif
736 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
737 /* currently incorrect */
738 long double strtold(const char *nptr, char **endptr)
740 return (long double)strtod(nptr, endptr);
742 float strtof(const char *nptr, char **endptr)
744 return (float)strtod(nptr, endptr);
746 #else
747 /* XXX: need to define this to use them in non ISOC99 context */
748 extern float strtof (const char *__nptr, char **__endptr);
749 extern long double strtold (const char *__nptr, char **__endptr);
750 #endif
752 static char *pstrcpy(char *buf, int buf_size, const char *s);
753 static char *pstrcat(char *buf, int buf_size, const char *s);
754 static const char *tcc_basename(const char *name);
756 static void next(void);
757 static void next_nomacro(void);
758 static void parse_expr_type(CType *type);
759 static void expr_type(CType *type);
760 static void unary_type(CType *type);
761 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
762 int case_reg, int is_expr);
763 static int expr_const(void);
764 static void expr_eq(void);
765 static void gexpr(void);
766 static void gen_inline_functions(void);
767 static void decl(int l);
768 static void decl_initializer(CType *type, Section *sec, unsigned long c,
769 int first, int size_only);
770 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
771 int has_init, int v, int scope);
772 int gv(int rc);
773 void gv2(int rc1, int rc2);
774 void move_reg(int r, int s);
775 void save_regs(int n);
776 void save_reg(int r);
777 void vpop(void);
778 void vswap(void);
779 void vdup(void);
780 int get_reg(int rc);
781 int get_reg_ex(int rc,int rc2);
783 struct macro_level {
784 struct macro_level *prev;
785 int *p;
788 static void macro_subst(TokenString *tok_str, Sym **nested_list,
789 const int *macro_str, struct macro_level **can_read_stream);
790 void gen_op(int op);
791 void force_charshort_cast(int t);
792 static void gen_cast(CType *type);
793 void vstore(void);
794 static Sym *sym_find(int v);
795 static Sym *sym_push(int v, CType *type, int r, int c);
797 /* type handling */
798 static int type_size(CType *type, int *a);
799 static inline CType *pointed_type(CType *type);
800 static int pointed_size(CType *type);
801 static int lvalue_type(int t);
802 static int parse_btype(CType *type, AttributeDef *ad);
803 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
804 static int is_compatible_types(CType *type1, CType *type2);
806 int ieee_finite(double d);
807 void error(const char *fmt, ...);
808 void vpushi(int v);
809 void vrott(int n);
810 void vnrott(int n);
811 void lexpand_nr(void);
812 static void vpush_global_sym(CType *type, int v);
813 void vset(CType *type, int r, int v);
814 void type_to_str(char *buf, int buf_size,
815 CType *type, const char *varstr);
816 char *get_tok_str(int v, CValue *cv);
817 static Sym *get_sym_ref(CType *type, Section *sec,
818 unsigned long offset, unsigned long size);
819 static Sym *external_global_sym(int v, CType *type, int r);
821 /* section generation */
822 static void section_realloc(Section *sec, unsigned long new_size);
823 static void *section_ptr_add(Section *sec, unsigned long size);
824 static void put_extern_sym(Sym *sym, Section *section,
825 unsigned long value, unsigned long size);
826 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
827 static int put_elf_str(Section *s, const char *sym);
828 static int put_elf_sym(Section *s,
829 unsigned long value, unsigned long size,
830 int info, int other, int shndx, const char *name);
831 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
832 int info, int other, int sh_num, const char *name);
833 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
834 int type, int symbol);
835 static void put_stabs(const char *str, int type, int other, int desc,
836 unsigned long value);
837 static void put_stabs_r(const char *str, int type, int other, int desc,
838 unsigned long value, Section *sec, int sym_index);
839 static void put_stabn(int type, int other, int desc, int value);
840 static void put_stabd(int type, int other, int desc);
841 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
843 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
844 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
845 #define AFF_PREPROCESS 0x0004 /* preprocess file */
846 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
848 /* tcccoff.c */
849 int tcc_output_coff(TCCState *s1, FILE *f);
851 /* tccpe.c */
852 void *resolve_sym(TCCState *s1, const char *sym, int type);
853 int pe_load_def_file(struct TCCState *s1, FILE *fp);
854 void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
855 unsigned long pe_add_runtime(struct TCCState *s1);
856 int tcc_output_pe(struct TCCState *s1, const char *filename);
858 /* tccasm.c */
860 #ifdef CONFIG_TCC_ASM
862 typedef struct ExprValue {
863 uint32_t v;
864 Sym *sym;
865 } ExprValue;
867 #define MAX_ASM_OPERANDS 30
869 typedef struct ASMOperand {
870 int id; /* GCC 3 optionnal identifier (0 if number only supported */
871 char *constraint;
872 char asm_str[16]; /* computed asm string for operand */
873 SValue *vt; /* C value of the expression */
874 int ref_index; /* if >= 0, gives reference to a output constraint */
875 int input_index; /* if >= 0, gives reference to an input constraint */
876 int priority; /* priority, used to assign registers */
877 int reg; /* if >= 0, register number used for this operand */
878 int is_llong; /* true if double register value */
879 int is_memory; /* true if memory operand */
880 int is_rw; /* for '+' modifier */
881 } ASMOperand;
883 static void asm_expr(TCCState *s1, ExprValue *pe);
884 static int asm_int_expr(TCCState *s1);
885 static int find_constraint(ASMOperand *operands, int nb_operands,
886 const char *name, const char **pp);
888 static int tcc_assemble(TCCState *s1, int do_preprocess);
890 #endif
892 static void asm_instr(void);
893 static void asm_global_instr(void);
895 /* true if float/double/long double type */
896 static inline int is_float(int t)
898 int bt;
899 bt = t & VT_BTYPE;
900 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
903 #ifdef TCC_TARGET_I386
904 #include "i386-gen.c"
905 #endif
907 #ifdef TCC_TARGET_ARM
908 #include "arm-gen.c"
909 #endif
911 #ifdef TCC_TARGET_C67
912 #include "c67-gen.c"
913 #endif
915 #ifdef CONFIG_TCC_STATIC
917 #define RTLD_LAZY 0x001
918 #define RTLD_NOW 0x002
919 #define RTLD_GLOBAL 0x100
920 #define RTLD_DEFAULT NULL
922 /* dummy function for profiling */
923 void *dlopen(const char *filename, int flag)
925 return NULL;
928 const char *dlerror(void)
930 return "error";
933 typedef struct TCCSyms {
934 char *str;
935 void *ptr;
936 } TCCSyms;
938 #define TCCSYM(a) { #a, &a, },
940 /* add the symbol you want here if no dynamic linking is done */
941 static TCCSyms tcc_syms[] = {
942 #if !defined(CONFIG_TCCBOOT)
943 TCCSYM(printf)
944 TCCSYM(fprintf)
945 TCCSYM(fopen)
946 TCCSYM(fclose)
947 #endif
948 { NULL, NULL },
951 void *resolve_sym(TCCState *s1, const char *symbol, int type)
953 TCCSyms *p;
954 p = tcc_syms;
955 while (p->str != NULL) {
956 if (!strcmp(p->str, symbol))
957 return p->ptr;
958 p++;
960 return NULL;
963 #elif !defined(WIN32)
965 #include <dlfcn.h>
967 void *resolve_sym(TCCState *s1, const char *sym, int type)
969 return dlsym(RTLD_DEFAULT, sym);
972 #endif
974 /********************************************************/
976 /* we use our own 'finite' function to avoid potential problems with
977 non standard math libs */
978 /* XXX: endianness dependent */
979 int ieee_finite(double d)
981 int *p = (int *)&d;
982 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
985 /* copy a string and truncate it. */
986 static char *pstrcpy(char *buf, int buf_size, const char *s)
988 char *q, *q_end;
989 int c;
991 if (buf_size > 0) {
992 q = buf;
993 q_end = buf + buf_size - 1;
994 while (q < q_end) {
995 c = *s++;
996 if (c == '\0')
997 break;
998 *q++ = c;
1000 *q = '\0';
1002 return buf;
1005 /* strcat and truncate. */
1006 static char *pstrcat(char *buf, int buf_size, const char *s)
1008 int len;
1009 len = strlen(buf);
1010 if (len < buf_size)
1011 pstrcpy(buf + len, buf_size - len, s);
1012 return buf;
1015 static int strstart(const char *str, const char *val, const char **ptr)
1017 const char *p, *q;
1018 p = str;
1019 q = val;
1020 while (*q != '\0') {
1021 if (*p != *q)
1022 return 0;
1023 p++;
1024 q++;
1026 if (ptr)
1027 *ptr = p;
1028 return 1;
1031 /* memory management */
1032 #ifdef MEM_DEBUG
1033 int mem_cur_size;
1034 int mem_max_size;
1035 #endif
1037 static inline void tcc_free(void *ptr)
1039 #ifdef MEM_DEBUG
1040 mem_cur_size -= malloc_usable_size(ptr);
1041 #endif
1042 free(ptr);
1045 static void *tcc_malloc(unsigned long size)
1047 void *ptr;
1048 ptr = malloc(size);
1049 if (!ptr && size)
1050 error("memory full");
1051 #ifdef MEM_DEBUG
1052 mem_cur_size += malloc_usable_size(ptr);
1053 if (mem_cur_size > mem_max_size)
1054 mem_max_size = mem_cur_size;
1055 #endif
1056 return ptr;
1059 static void *tcc_mallocz(unsigned long size)
1061 void *ptr;
1062 ptr = tcc_malloc(size);
1063 memset(ptr, 0, size);
1064 return ptr;
1067 static inline void *tcc_realloc(void *ptr, unsigned long size)
1069 void *ptr1;
1070 #ifdef MEM_DEBUG
1071 mem_cur_size -= malloc_usable_size(ptr);
1072 #endif
1073 ptr1 = realloc(ptr, size);
1074 #ifdef MEM_DEBUG
1075 /* NOTE: count not correct if alloc error, but not critical */
1076 mem_cur_size += malloc_usable_size(ptr1);
1077 if (mem_cur_size > mem_max_size)
1078 mem_max_size = mem_cur_size;
1079 #endif
1080 return ptr1;
1083 static char *tcc_strdup(const char *str)
1085 char *ptr;
1086 ptr = tcc_malloc(strlen(str) + 1);
1087 strcpy(ptr, str);
1088 return ptr;
1091 #define free(p) use_tcc_free(p)
1092 #define malloc(s) use_tcc_malloc(s)
1093 #define realloc(p, s) use_tcc_realloc(p, s)
1095 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1097 int nb, nb_alloc;
1098 void **pp;
1100 nb = *nb_ptr;
1101 pp = *ptab;
1102 /* every power of two we double array size */
1103 if ((nb & (nb - 1)) == 0) {
1104 if (!nb)
1105 nb_alloc = 1;
1106 else
1107 nb_alloc = nb * 2;
1108 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1109 if (!pp)
1110 error("memory full");
1111 *ptab = pp;
1113 pp[nb++] = data;
1114 *nb_ptr = nb;
1117 /* symbol allocator */
1118 static Sym *__sym_malloc(void)
1120 Sym *sym_pool, *sym, *last_sym;
1121 int i;
1123 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1125 last_sym = sym_free_first;
1126 sym = sym_pool;
1127 for(i = 0; i < SYM_POOL_NB; i++) {
1128 sym->next = last_sym;
1129 last_sym = sym;
1130 sym++;
1132 sym_free_first = last_sym;
1133 return last_sym;
1136 static inline Sym *sym_malloc(void)
1138 Sym *sym;
1139 sym = sym_free_first;
1140 if (!sym)
1141 sym = __sym_malloc();
1142 sym_free_first = sym->next;
1143 return sym;
1146 static inline void sym_free(Sym *sym)
1148 sym->next = sym_free_first;
1149 sym_free_first = sym;
1152 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1154 Section *sec;
1156 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1157 strcpy(sec->name, name);
1158 sec->sh_type = sh_type;
1159 sec->sh_flags = sh_flags;
1160 switch(sh_type) {
1161 case SHT_HASH:
1162 case SHT_REL:
1163 case SHT_DYNSYM:
1164 case SHT_SYMTAB:
1165 case SHT_DYNAMIC:
1166 sec->sh_addralign = 4;
1167 break;
1168 case SHT_STRTAB:
1169 sec->sh_addralign = 1;
1170 break;
1171 default:
1172 sec->sh_addralign = 32; /* default conservative alignment */
1173 break;
1176 /* only add section if not private */
1177 if (!(sh_flags & SHF_PRIVATE)) {
1178 sec->sh_num = s1->nb_sections;
1179 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1181 return sec;
1184 static void free_section(Section *s)
1186 tcc_free(s->data);
1187 tcc_free(s);
1190 /* realloc section and set its content to zero */
1191 static void section_realloc(Section *sec, unsigned long new_size)
1193 unsigned long size;
1194 unsigned char *data;
1196 size = sec->data_allocated;
1197 if (size == 0)
1198 size = 1;
1199 while (size < new_size)
1200 size = size * 2;
1201 data = tcc_realloc(sec->data, size);
1202 if (!data)
1203 error("memory full");
1204 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1205 sec->data = data;
1206 sec->data_allocated = size;
1209 /* reserve at least 'size' bytes in section 'sec' from
1210 sec->data_offset. */
1211 static void *section_ptr_add(Section *sec, unsigned long size)
1213 unsigned long offset, offset1;
1215 offset = sec->data_offset;
1216 offset1 = offset + size;
1217 if (offset1 > sec->data_allocated)
1218 section_realloc(sec, offset1);
1219 sec->data_offset = offset1;
1220 return sec->data + offset;
1223 /* return a reference to a section, and create it if it does not
1224 exists */
1225 Section *find_section(TCCState *s1, const char *name)
1227 Section *sec;
1228 int i;
1229 for(i = 1; i < s1->nb_sections; i++) {
1230 sec = s1->sections[i];
1231 if (!strcmp(name, sec->name))
1232 return sec;
1234 /* sections are created as PROGBITS */
1235 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1238 #define SECTION_ABS ((void *)1)
1240 /* update sym->c so that it points to an external symbol in section
1241 'section' with value 'value' */
1242 static void put_extern_sym2(Sym *sym, Section *section,
1243 unsigned long value, unsigned long size,
1244 int can_add_underscore)
1246 int sym_type, sym_bind, sh_num, info;
1247 Elf32_Sym *esym;
1248 const char *name;
1249 char buf1[256];
1251 if (section == NULL)
1252 sh_num = SHN_UNDEF;
1253 else if (section == SECTION_ABS)
1254 sh_num = SHN_ABS;
1255 else
1256 sh_num = section->sh_num;
1257 if (!sym->c) {
1258 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1259 sym_type = STT_FUNC;
1260 else
1261 sym_type = STT_OBJECT;
1262 if (sym->type.t & VT_STATIC)
1263 sym_bind = STB_LOCAL;
1264 else
1265 sym_bind = STB_GLOBAL;
1267 name = get_tok_str(sym->v, NULL);
1268 #ifdef CONFIG_TCC_BCHECK
1269 if (do_bounds_check) {
1270 char buf[32];
1272 /* XXX: avoid doing that for statics ? */
1273 /* if bound checking is activated, we change some function
1274 names by adding the "__bound" prefix */
1275 switch(sym->v) {
1276 #if 0
1277 /* XXX: we rely only on malloc hooks */
1278 case TOK_malloc:
1279 case TOK_free:
1280 case TOK_realloc:
1281 case TOK_memalign:
1282 case TOK_calloc:
1283 #endif
1284 case TOK_memcpy:
1285 case TOK_memmove:
1286 case TOK_memset:
1287 case TOK_strlen:
1288 case TOK_strcpy:
1289 strcpy(buf, "__bound_");
1290 strcat(buf, name);
1291 name = buf;
1292 break;
1295 #endif
1296 if (tcc_state->leading_underscore && can_add_underscore) {
1297 buf1[0] = '_';
1298 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1299 name = buf1;
1301 info = ELF32_ST_INFO(sym_bind, sym_type);
1302 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
1303 } else {
1304 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1305 esym->st_value = value;
1306 esym->st_size = size;
1307 esym->st_shndx = sh_num;
1311 static void put_extern_sym(Sym *sym, Section *section,
1312 unsigned long value, unsigned long size)
1314 put_extern_sym2(sym, section, value, size, 1);
1317 /* add a new relocation entry to symbol 'sym' in section 's' */
1318 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1320 if (!sym->c)
1321 put_extern_sym(sym, NULL, 0, 0);
1322 /* now we can add ELF relocation info */
1323 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1326 static inline int isid(int c)
1328 return (c >= 'a' && c <= 'z') ||
1329 (c >= 'A' && c <= 'Z') ||
1330 c == '_';
1333 static inline int isnum(int c)
1335 return c >= '0' && c <= '9';
1338 static inline int isoct(int c)
1340 return c >= '0' && c <= '7';
1343 static inline int toup(int c)
1345 if (c >= 'a' && c <= 'z')
1346 return c - 'a' + 'A';
1347 else
1348 return c;
1351 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1353 int len;
1354 len = strlen(buf);
1355 vsnprintf(buf + len, buf_size - len, fmt, ap);
1358 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1360 va_list ap;
1361 va_start(ap, fmt);
1362 strcat_vprintf(buf, buf_size, fmt, ap);
1363 va_end(ap);
1366 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1368 char buf[2048];
1369 BufferedFile **f;
1371 buf[0] = '\0';
1372 if (file) {
1373 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1374 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1375 (*f)->filename, (*f)->line_num);
1376 if (file->line_num > 0) {
1377 strcat_printf(buf, sizeof(buf),
1378 "%s:%d: ", file->filename, file->line_num);
1379 } else {
1380 strcat_printf(buf, sizeof(buf),
1381 "%s: ", file->filename);
1383 } else {
1384 strcat_printf(buf, sizeof(buf),
1385 "tcc: ");
1387 if (is_warning)
1388 strcat_printf(buf, sizeof(buf), "warning: ");
1389 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1391 if (!s1->error_func) {
1392 /* default case: stderr */
1393 fprintf(stderr, "%s\n", buf);
1394 } else {
1395 s1->error_func(s1->error_opaque, buf);
1397 if (!is_warning || s1->warn_error)
1398 s1->nb_errors++;
1401 #ifdef LIBTCC
1402 void tcc_set_error_func(TCCState *s, void *error_opaque,
1403 void (*error_func)(void *opaque, const char *msg))
1405 s->error_opaque = error_opaque;
1406 s->error_func = error_func;
1408 #endif
1410 /* error without aborting current compilation */
1411 void error_noabort(const char *fmt, ...)
1413 TCCState *s1 = tcc_state;
1414 va_list ap;
1416 va_start(ap, fmt);
1417 error1(s1, 0, fmt, ap);
1418 va_end(ap);
1421 void error(const char *fmt, ...)
1423 TCCState *s1 = tcc_state;
1424 va_list ap;
1426 va_start(ap, fmt);
1427 error1(s1, 0, fmt, ap);
1428 va_end(ap);
1429 /* better than nothing: in some cases, we accept to handle errors */
1430 if (s1->error_set_jmp_enabled) {
1431 longjmp(s1->error_jmp_buf, 1);
1432 } else {
1433 /* XXX: eliminate this someday */
1434 exit(1);
1438 void expect(const char *msg)
1440 error("%s expected", msg);
1443 void warning(const char *fmt, ...)
1445 TCCState *s1 = tcc_state;
1446 va_list ap;
1448 if (s1->warn_none)
1449 return;
1451 va_start(ap, fmt);
1452 error1(s1, 1, fmt, ap);
1453 va_end(ap);
1456 void skip(int c)
1458 if (tok != c)
1459 error("'%c' expected", c);
1460 next();
1463 static void test_lvalue(void)
1465 if (!(vtop->r & VT_LVAL))
1466 expect("lvalue");
1469 /* allocate a new token */
1470 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1472 TokenSym *ts, **ptable;
1473 int i;
1475 if (tok_ident >= SYM_FIRST_ANOM)
1476 error("memory full");
1478 /* expand token table if needed */
1479 i = tok_ident - TOK_IDENT;
1480 if ((i % TOK_ALLOC_INCR) == 0) {
1481 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1482 if (!ptable)
1483 error("memory full");
1484 table_ident = ptable;
1487 ts = tcc_malloc(sizeof(TokenSym) + len);
1488 table_ident[i] = ts;
1489 ts->tok = tok_ident++;
1490 ts->sym_define = NULL;
1491 ts->sym_label = NULL;
1492 ts->sym_struct = NULL;
1493 ts->sym_identifier = NULL;
1494 ts->len = len;
1495 ts->hash_next = NULL;
1496 memcpy(ts->str, str, len);
1497 ts->str[len] = '\0';
1498 *pts = ts;
1499 return ts;
1502 #define TOK_HASH_INIT 1
1503 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1505 /* find a token and add it if not found */
1506 static TokenSym *tok_alloc(const char *str, int len)
1508 TokenSym *ts, **pts;
1509 int i;
1510 unsigned int h;
1512 h = TOK_HASH_INIT;
1513 for(i=0;i<len;i++)
1514 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1515 h &= (TOK_HASH_SIZE - 1);
1517 pts = &hash_ident[h];
1518 for(;;) {
1519 ts = *pts;
1520 if (!ts)
1521 break;
1522 if (ts->len == len && !memcmp(ts->str, str, len))
1523 return ts;
1524 pts = &(ts->hash_next);
1526 return tok_alloc_new(pts, str, len);
1529 /* CString handling */
1531 static void cstr_realloc(CString *cstr, int new_size)
1533 int size;
1534 void *data;
1536 size = cstr->size_allocated;
1537 if (size == 0)
1538 size = 8; /* no need to allocate a too small first string */
1539 while (size < new_size)
1540 size = size * 2;
1541 data = tcc_realloc(cstr->data_allocated, size);
1542 if (!data)
1543 error("memory full");
1544 cstr->data_allocated = data;
1545 cstr->size_allocated = size;
1546 cstr->data = data;
1549 /* add a byte */
1550 static inline void cstr_ccat(CString *cstr, int ch)
1552 int size;
1553 size = cstr->size + 1;
1554 if (size > cstr->size_allocated)
1555 cstr_realloc(cstr, size);
1556 ((unsigned char *)cstr->data)[size - 1] = ch;
1557 cstr->size = size;
1560 static void cstr_cat(CString *cstr, const char *str)
1562 int c;
1563 for(;;) {
1564 c = *str;
1565 if (c == '\0')
1566 break;
1567 cstr_ccat(cstr, c);
1568 str++;
1572 /* add a wide char */
1573 static void cstr_wccat(CString *cstr, int ch)
1575 int size;
1576 size = cstr->size + sizeof(nwchar_t);
1577 if (size > cstr->size_allocated)
1578 cstr_realloc(cstr, size);
1579 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1580 cstr->size = size;
1583 static void cstr_new(CString *cstr)
1585 memset(cstr, 0, sizeof(CString));
1588 /* free string and reset it to NULL */
1589 static void cstr_free(CString *cstr)
1591 tcc_free(cstr->data_allocated);
1592 cstr_new(cstr);
1595 #define cstr_reset(cstr) cstr_free(cstr)
1597 /* XXX: unicode ? */
1598 static void add_char(CString *cstr, int c)
1600 if (c == '\'' || c == '\"' || c == '\\') {
1601 /* XXX: could be more precise if char or string */
1602 cstr_ccat(cstr, '\\');
1604 if (c >= 32 && c <= 126) {
1605 cstr_ccat(cstr, c);
1606 } else {
1607 cstr_ccat(cstr, '\\');
1608 if (c == '\n') {
1609 cstr_ccat(cstr, 'n');
1610 } else {
1611 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1612 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1613 cstr_ccat(cstr, '0' + (c & 7));
1618 /* XXX: buffer overflow */
1619 /* XXX: float tokens */
1620 char *get_tok_str(int v, CValue *cv)
1622 static char buf[STRING_MAX_SIZE + 1];
1623 static CString cstr_buf;
1624 CString *cstr;
1625 unsigned char *q;
1626 char *p;
1627 int i, len;
1629 /* NOTE: to go faster, we give a fixed buffer for small strings */
1630 cstr_reset(&cstr_buf);
1631 cstr_buf.data = buf;
1632 cstr_buf.size_allocated = sizeof(buf);
1633 p = buf;
1635 switch(v) {
1636 case TOK_CINT:
1637 case TOK_CUINT:
1638 /* XXX: not quite exact, but only useful for testing */
1639 sprintf(p, "%u", cv->ui);
1640 break;
1641 case TOK_CLLONG:
1642 case TOK_CULLONG:
1643 /* XXX: not quite exact, but only useful for testing */
1644 sprintf(p, "%Lu", cv->ull);
1645 break;
1646 case TOK_CCHAR:
1647 case TOK_LCHAR:
1648 cstr_ccat(&cstr_buf, '\'');
1649 add_char(&cstr_buf, cv->i);
1650 cstr_ccat(&cstr_buf, '\'');
1651 cstr_ccat(&cstr_buf, '\0');
1652 break;
1653 case TOK_PPNUM:
1654 cstr = cv->cstr;
1655 len = cstr->size - 1;
1656 for(i=0;i<len;i++)
1657 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1658 cstr_ccat(&cstr_buf, '\0');
1659 break;
1660 case TOK_STR:
1661 case TOK_LSTR:
1662 cstr = cv->cstr;
1663 cstr_ccat(&cstr_buf, '\"');
1664 if (v == TOK_STR) {
1665 len = cstr->size - 1;
1666 for(i=0;i<len;i++)
1667 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1668 } else {
1669 len = (cstr->size / sizeof(nwchar_t)) - 1;
1670 for(i=0;i<len;i++)
1671 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1673 cstr_ccat(&cstr_buf, '\"');
1674 cstr_ccat(&cstr_buf, '\0');
1675 break;
1676 case TOK_LT:
1677 v = '<';
1678 goto addv;
1679 case TOK_GT:
1680 v = '>';
1681 goto addv;
1682 case TOK_DOTS:
1683 return strcpy(p, "...");
1684 case TOK_A_SHL:
1685 return strcpy(p, "<<=");
1686 case TOK_A_SAR:
1687 return strcpy(p, ">>=");
1688 default:
1689 if (v < TOK_IDENT) {
1690 /* search in two bytes table */
1691 q = tok_two_chars;
1692 while (*q) {
1693 if (q[2] == v) {
1694 *p++ = q[0];
1695 *p++ = q[1];
1696 *p = '\0';
1697 return buf;
1699 q += 3;
1701 addv:
1702 *p++ = v;
1703 *p = '\0';
1704 } else if (v < tok_ident) {
1705 return table_ident[v - TOK_IDENT]->str;
1706 } else if (v >= SYM_FIRST_ANOM) {
1707 /* special name for anonymous symbol */
1708 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1709 } else {
1710 /* should never happen */
1711 return NULL;
1713 break;
1715 return cstr_buf.data;
1718 /* push, without hashing */
1719 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1721 Sym *s;
1722 s = sym_malloc();
1723 s->v = v;
1724 s->type.t = t;
1725 s->c = c;
1726 s->next = NULL;
1727 /* add in stack */
1728 s->prev = *ps;
1729 *ps = s;
1730 return s;
1733 /* find a symbol and return its associated structure. 's' is the top
1734 of the symbol stack */
1735 static Sym *sym_find2(Sym *s, int v)
1737 while (s) {
1738 if (s->v == v)
1739 return s;
1740 s = s->prev;
1742 return NULL;
1745 /* structure lookup */
1746 static inline Sym *struct_find(int v)
1748 v -= TOK_IDENT;
1749 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1750 return NULL;
1751 return table_ident[v]->sym_struct;
1754 /* find an identifier */
1755 static inline Sym *sym_find(int v)
1757 v -= TOK_IDENT;
1758 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1759 return NULL;
1760 return table_ident[v]->sym_identifier;
1763 /* push a given symbol on the symbol stack */
1764 static Sym *sym_push(int v, CType *type, int r, int c)
1766 Sym *s, **ps;
1767 TokenSym *ts;
1769 if (local_stack)
1770 ps = &local_stack;
1771 else
1772 ps = &global_stack;
1773 s = sym_push2(ps, v, type->t, c);
1774 s->type.ref = type->ref;
1775 s->r = r;
1776 /* don't record fields or anonymous symbols */
1777 /* XXX: simplify */
1778 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1779 /* record symbol in token array */
1780 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1781 if (v & SYM_STRUCT)
1782 ps = &ts->sym_struct;
1783 else
1784 ps = &ts->sym_identifier;
1785 s->prev_tok = *ps;
1786 *ps = s;
1788 return s;
1791 /* push a global identifier */
1792 static Sym *global_identifier_push(int v, int t, int c)
1794 Sym *s, **ps;
1795 s = sym_push2(&global_stack, v, t, c);
1796 /* don't record anonymous symbol */
1797 if (v < SYM_FIRST_ANOM) {
1798 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1799 /* modify the top most local identifier, so that
1800 sym_identifier will point to 's' when popped */
1801 while (*ps != NULL)
1802 ps = &(*ps)->prev_tok;
1803 s->prev_tok = NULL;
1804 *ps = s;
1806 return s;
1809 /* pop symbols until top reaches 'b' */
1810 static void sym_pop(Sym **ptop, Sym *b)
1812 Sym *s, *ss, **ps;
1813 TokenSym *ts;
1814 int v;
1816 s = *ptop;
1817 while(s != b) {
1818 ss = s->prev;
1819 v = s->v;
1820 /* remove symbol in token array */
1821 /* XXX: simplify */
1822 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1823 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1824 if (v & SYM_STRUCT)
1825 ps = &ts->sym_struct;
1826 else
1827 ps = &ts->sym_identifier;
1828 *ps = s->prev_tok;
1830 sym_free(s);
1831 s = ss;
1833 *ptop = b;
1836 /* I/O layer */
1838 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1840 int fd;
1841 BufferedFile *bf;
1842 int i, len;
1844 fd = open(filename, O_RDONLY | O_BINARY);
1845 if (fd < 0)
1846 return NULL;
1847 bf = tcc_malloc(sizeof(BufferedFile));
1848 if (!bf) {
1849 close(fd);
1850 return NULL;
1852 bf->fd = fd;
1853 bf->buf_ptr = bf->buffer;
1854 bf->buf_end = bf->buffer;
1855 bf->buffer[0] = CH_EOB; /* put eob symbol */
1856 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1857 len = strlen(bf->filename);
1858 for (i = 0; i < len; i++)
1859 if (bf->filename[i] == '\\')
1860 bf->filename[i] = '/';
1861 bf->line_num = 1;
1862 bf->ifndef_macro = 0;
1863 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1864 // printf("opening '%s'\n", filename);
1865 return bf;
1868 void tcc_close(BufferedFile *bf)
1870 total_lines += bf->line_num;
1871 close(bf->fd);
1872 tcc_free(bf);
1875 /* fill input buffer and peek next char */
1876 static int tcc_peekc_slow(BufferedFile *bf)
1878 int len;
1879 /* only tries to read if really end of buffer */
1880 if (bf->buf_ptr >= bf->buf_end) {
1881 if (bf->fd != -1) {
1882 #if defined(PARSE_DEBUG)
1883 len = 8;
1884 #else
1885 len = IO_BUF_SIZE;
1886 #endif
1887 len = read(bf->fd, bf->buffer, len);
1888 if (len < 0)
1889 len = 0;
1890 } else {
1891 len = 0;
1893 total_bytes += len;
1894 bf->buf_ptr = bf->buffer;
1895 bf->buf_end = bf->buffer + len;
1896 *bf->buf_end = CH_EOB;
1898 if (bf->buf_ptr < bf->buf_end) {
1899 return bf->buf_ptr[0];
1900 } else {
1901 bf->buf_ptr = bf->buf_end;
1902 return CH_EOF;
1906 /* return the current character, handling end of block if necessary
1907 (but not stray) */
1908 static int handle_eob(void)
1910 return tcc_peekc_slow(file);
1913 /* read next char from current input file and handle end of input buffer */
1914 static inline void inp(void)
1916 ch = *(++(file->buf_ptr));
1917 /* end of buffer/file handling */
1918 if (ch == CH_EOB)
1919 ch = handle_eob();
1922 /* handle '\[\r]\n' */
1923 static void handle_stray(void)
1925 while (ch == '\\') {
1926 inp();
1927 if (ch == '\n') {
1928 file->line_num++;
1929 inp();
1930 } else if (ch == '\r') {
1931 inp();
1932 if (ch != '\n')
1933 goto fail;
1934 file->line_num++;
1935 inp();
1936 } else {
1937 fail:
1938 error("stray '\\' in program");
1943 /* skip the stray and handle the \\n case. Output an error if
1944 incorrect char after the stray */
1945 static int handle_stray1(uint8_t *p)
1947 int c;
1949 if (p >= file->buf_end) {
1950 file->buf_ptr = p;
1951 c = handle_eob();
1952 p = file->buf_ptr;
1953 if (c == '\\')
1954 goto parse_stray;
1955 } else {
1956 parse_stray:
1957 file->buf_ptr = p;
1958 ch = *p;
1959 handle_stray();
1960 p = file->buf_ptr;
1961 c = *p;
1963 return c;
1966 /* handle just the EOB case, but not stray */
1967 #define PEEKC_EOB(c, p)\
1969 p++;\
1970 c = *p;\
1971 if (c == '\\') {\
1972 file->buf_ptr = p;\
1973 c = handle_eob();\
1974 p = file->buf_ptr;\
1978 /* handle the complicated stray case */
1979 #define PEEKC(c, p)\
1981 p++;\
1982 c = *p;\
1983 if (c == '\\') {\
1984 c = handle_stray1(p);\
1985 p = file->buf_ptr;\
1989 /* input with '\[\r]\n' handling. Note that this function cannot
1990 handle other characters after '\', so you cannot call it inside
1991 strings or comments */
1992 static void minp(void)
1994 inp();
1995 if (ch == '\\')
1996 handle_stray();
2000 /* single line C++ comments */
2001 static uint8_t *parse_line_comment(uint8_t *p)
2003 int c;
2005 p++;
2006 for(;;) {
2007 c = *p;
2008 redo:
2009 if (c == '\n' || c == CH_EOF) {
2010 break;
2011 } else if (c == '\\') {
2012 file->buf_ptr = p;
2013 c = handle_eob();
2014 p = file->buf_ptr;
2015 if (c == '\\') {
2016 PEEKC_EOB(c, p);
2017 if (c == '\n') {
2018 file->line_num++;
2019 PEEKC_EOB(c, p);
2020 } else if (c == '\r') {
2021 PEEKC_EOB(c, p);
2022 if (c == '\n') {
2023 file->line_num++;
2024 PEEKC_EOB(c, p);
2027 } else {
2028 goto redo;
2030 } else {
2031 p++;
2034 return p;
2037 /* C comments */
2038 static uint8_t *parse_comment(uint8_t *p)
2040 int c;
2042 p++;
2043 for(;;) {
2044 /* fast skip loop */
2045 for(;;) {
2046 c = *p;
2047 if (c == '\n' || c == '*' || c == '\\')
2048 break;
2049 p++;
2050 c = *p;
2051 if (c == '\n' || c == '*' || c == '\\')
2052 break;
2053 p++;
2055 /* now we can handle all the cases */
2056 if (c == '\n') {
2057 file->line_num++;
2058 p++;
2059 } else if (c == '*') {
2060 p++;
2061 for(;;) {
2062 c = *p;
2063 if (c == '*') {
2064 p++;
2065 } else if (c == '/') {
2066 goto end_of_comment;
2067 } else if (c == '\\') {
2068 file->buf_ptr = p;
2069 c = handle_eob();
2070 p = file->buf_ptr;
2071 if (c == '\\') {
2072 /* skip '\[\r]\n', otherwise just skip the stray */
2073 while (c == '\\') {
2074 PEEKC_EOB(c, p);
2075 if (c == '\n') {
2076 file->line_num++;
2077 PEEKC_EOB(c, p);
2078 } else if (c == '\r') {
2079 PEEKC_EOB(c, p);
2080 if (c == '\n') {
2081 file->line_num++;
2082 PEEKC_EOB(c, p);
2084 } else {
2085 goto after_star;
2089 } else {
2090 break;
2093 after_star: ;
2094 } else {
2095 /* stray, eob or eof */
2096 file->buf_ptr = p;
2097 c = handle_eob();
2098 p = file->buf_ptr;
2099 if (c == CH_EOF) {
2100 error("unexpected end of file in comment");
2101 } else if (c == '\\') {
2102 p++;
2106 end_of_comment:
2107 p++;
2108 return p;
2111 #define cinp minp
2113 /* space exlcuding newline */
2114 static inline int is_space(int ch)
2116 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2119 static inline void skip_spaces(void)
2121 while (is_space(ch))
2122 cinp();
2125 /* parse a string without interpreting escapes */
2126 static uint8_t *parse_pp_string(uint8_t *p,
2127 int sep, CString *str)
2129 int c;
2130 p++;
2131 for(;;) {
2132 c = *p;
2133 if (c == sep) {
2134 break;
2135 } else if (c == '\\') {
2136 file->buf_ptr = p;
2137 c = handle_eob();
2138 p = file->buf_ptr;
2139 if (c == CH_EOF) {
2140 unterminated_string:
2141 /* XXX: indicate line number of start of string */
2142 error("missing terminating %c character", sep);
2143 } else if (c == '\\') {
2144 /* escape : just skip \[\r]\n */
2145 PEEKC_EOB(c, p);
2146 if (c == '\n') {
2147 file->line_num++;
2148 p++;
2149 } else if (c == '\r') {
2150 PEEKC_EOB(c, p);
2151 if (c != '\n')
2152 expect("'\n' after '\r'");
2153 file->line_num++;
2154 p++;
2155 } else if (c == CH_EOF) {
2156 goto unterminated_string;
2157 } else {
2158 if (str) {
2159 cstr_ccat(str, '\\');
2160 cstr_ccat(str, c);
2162 p++;
2165 } else if (c == '\n') {
2166 file->line_num++;
2167 goto add_char;
2168 } else if (c == '\r') {
2169 PEEKC_EOB(c, p);
2170 if (c != '\n') {
2171 if (str)
2172 cstr_ccat(str, '\r');
2173 } else {
2174 file->line_num++;
2175 goto add_char;
2177 } else {
2178 add_char:
2179 if (str)
2180 cstr_ccat(str, c);
2181 p++;
2184 p++;
2185 return p;
2188 /* skip block of text until #else, #elif or #endif. skip also pairs of
2189 #if/#endif */
2190 void preprocess_skip(void)
2192 int a, start_of_line, c;
2193 uint8_t *p;
2195 p = file->buf_ptr;
2196 start_of_line = 1;
2197 a = 0;
2198 for(;;) {
2199 redo_no_start:
2200 c = *p;
2201 switch(c) {
2202 case ' ':
2203 case '\t':
2204 case '\f':
2205 case '\v':
2206 case '\r':
2207 p++;
2208 goto redo_no_start;
2209 case '\n':
2210 start_of_line = 1;
2211 file->line_num++;
2212 p++;
2213 goto redo_no_start;
2214 case '\\':
2215 file->buf_ptr = p;
2216 c = handle_eob();
2217 if (c == CH_EOF) {
2218 expect("#endif");
2219 } else if (c == '\\') {
2220 /* XXX: incorrect: should not give an error */
2221 ch = file->buf_ptr[0];
2222 handle_stray();
2224 p = file->buf_ptr;
2225 goto redo_no_start;
2226 /* skip strings */
2227 case '\"':
2228 case '\'':
2229 p = parse_pp_string(p, c, NULL);
2230 break;
2231 /* skip comments */
2232 case '/':
2233 file->buf_ptr = p;
2234 ch = *p;
2235 minp();
2236 p = file->buf_ptr;
2237 if (ch == '*') {
2238 p = parse_comment(p);
2239 } else if (ch == '/') {
2240 p = parse_line_comment(p);
2242 break;
2244 case '#':
2245 p++;
2246 if (start_of_line) {
2247 file->buf_ptr = p;
2248 next_nomacro();
2249 p = file->buf_ptr;
2250 if (a == 0 &&
2251 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2252 goto the_end;
2253 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2254 a++;
2255 else if (tok == TOK_ENDIF)
2256 a--;
2258 break;
2259 default:
2260 p++;
2261 break;
2263 start_of_line = 0;
2265 the_end: ;
2266 file->buf_ptr = p;
2269 /* ParseState handling */
2271 /* XXX: currently, no include file info is stored. Thus, we cannot display
2272 accurate messages if the function or data definition spans multiple
2273 files */
2275 /* save current parse state in 's' */
2276 void save_parse_state(ParseState *s)
2278 s->line_num = file->line_num;
2279 s->macro_ptr = macro_ptr;
2280 s->tok = tok;
2281 s->tokc = tokc;
2284 /* restore parse state from 's' */
2285 void restore_parse_state(ParseState *s)
2287 file->line_num = s->line_num;
2288 macro_ptr = s->macro_ptr;
2289 tok = s->tok;
2290 tokc = s->tokc;
2293 /* return the number of additional 'ints' necessary to store the
2294 token */
2295 static inline int tok_ext_size(int t)
2297 switch(t) {
2298 /* 4 bytes */
2299 case TOK_CINT:
2300 case TOK_CUINT:
2301 case TOK_CCHAR:
2302 case TOK_LCHAR:
2303 case TOK_CFLOAT:
2304 case TOK_LINENUM:
2305 return 1;
2306 case TOK_STR:
2307 case TOK_LSTR:
2308 case TOK_PPNUM:
2309 error("unsupported token");
2310 return 1;
2311 case TOK_CDOUBLE:
2312 case TOK_CLLONG:
2313 case TOK_CULLONG:
2314 return 2;
2315 case TOK_CLDOUBLE:
2316 return LDOUBLE_SIZE / 4;
2317 default:
2318 return 0;
2322 /* token string handling */
2324 static inline void tok_str_new(TokenString *s)
2326 s->str = NULL;
2327 s->len = 0;
2328 s->allocated_len = 0;
2329 s->last_line_num = -1;
2332 static void tok_str_free(int *str)
2334 tcc_free(str);
2337 static int *tok_str_realloc(TokenString *s)
2339 int *str, len;
2341 if (s->allocated_len == 0) {
2342 len = 8;
2343 } else {
2344 len = s->allocated_len * 2;
2346 str = tcc_realloc(s->str, len * sizeof(int));
2347 if (!str)
2348 error("memory full");
2349 s->allocated_len = len;
2350 s->str = str;
2351 return str;
2354 static void tok_str_add(TokenString *s, int t)
2356 int len, *str;
2358 len = s->len;
2359 str = s->str;
2360 if (len >= s->allocated_len)
2361 str = tok_str_realloc(s);
2362 str[len++] = t;
2363 s->len = len;
2366 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2368 int len, *str;
2370 len = s->len;
2371 str = s->str;
2373 /* allocate space for worst case */
2374 if (len + TOK_MAX_SIZE > s->allocated_len)
2375 str = tok_str_realloc(s);
2376 str[len++] = t;
2377 switch(t) {
2378 case TOK_CINT:
2379 case TOK_CUINT:
2380 case TOK_CCHAR:
2381 case TOK_LCHAR:
2382 case TOK_CFLOAT:
2383 case TOK_LINENUM:
2384 str[len++] = cv->tab[0];
2385 break;
2386 case TOK_PPNUM:
2387 case TOK_STR:
2388 case TOK_LSTR:
2390 int nb_words;
2391 CString *cstr;
2393 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2394 while ((len + nb_words) > s->allocated_len)
2395 str = tok_str_realloc(s);
2396 cstr = (CString *)(str + len);
2397 cstr->data = NULL;
2398 cstr->size = cv->cstr->size;
2399 cstr->data_allocated = NULL;
2400 cstr->size_allocated = cstr->size;
2401 memcpy((char *)cstr + sizeof(CString),
2402 cv->cstr->data, cstr->size);
2403 len += nb_words;
2405 break;
2406 case TOK_CDOUBLE:
2407 case TOK_CLLONG:
2408 case TOK_CULLONG:
2409 #if LDOUBLE_SIZE == 8
2410 case TOK_CLDOUBLE:
2411 #endif
2412 str[len++] = cv->tab[0];
2413 str[len++] = cv->tab[1];
2414 break;
2415 #if LDOUBLE_SIZE == 12
2416 case TOK_CLDOUBLE:
2417 str[len++] = cv->tab[0];
2418 str[len++] = cv->tab[1];
2419 str[len++] = cv->tab[2];
2420 #elif LDOUBLE_SIZE != 8
2421 #error add long double size support
2422 #endif
2423 break;
2424 default:
2425 break;
2427 s->len = len;
2430 /* add the current parse token in token string 's' */
2431 static void tok_str_add_tok(TokenString *s)
2433 CValue cval;
2435 /* save line number info */
2436 if (file->line_num != s->last_line_num) {
2437 s->last_line_num = file->line_num;
2438 cval.i = s->last_line_num;
2439 tok_str_add2(s, TOK_LINENUM, &cval);
2441 tok_str_add2(s, tok, &tokc);
2444 #if LDOUBLE_SIZE == 12
2445 #define LDOUBLE_GET(p, cv) \
2446 cv.tab[0] = p[0]; \
2447 cv.tab[1] = p[1]; \
2448 cv.tab[2] = p[2];
2449 #elif LDOUBLE_SIZE == 8
2450 #define LDOUBLE_GET(p, cv) \
2451 cv.tab[0] = p[0]; \
2452 cv.tab[1] = p[1];
2453 #else
2454 #error add long double size support
2455 #endif
2458 /* get a token from an integer array and increment pointer
2459 accordingly. we code it as a macro to avoid pointer aliasing. */
2460 #define TOK_GET(t, p, cv) \
2462 t = *p++; \
2463 switch(t) { \
2464 case TOK_CINT: \
2465 case TOK_CUINT: \
2466 case TOK_CCHAR: \
2467 case TOK_LCHAR: \
2468 case TOK_CFLOAT: \
2469 case TOK_LINENUM: \
2470 cv.tab[0] = *p++; \
2471 break; \
2472 case TOK_STR: \
2473 case TOK_LSTR: \
2474 case TOK_PPNUM: \
2475 cv.cstr = (CString *)p; \
2476 cv.cstr->data = (char *)p + sizeof(CString);\
2477 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2478 break; \
2479 case TOK_CDOUBLE: \
2480 case TOK_CLLONG: \
2481 case TOK_CULLONG: \
2482 cv.tab[0] = p[0]; \
2483 cv.tab[1] = p[1]; \
2484 p += 2; \
2485 break; \
2486 case TOK_CLDOUBLE: \
2487 LDOUBLE_GET(p, cv); \
2488 p += LDOUBLE_SIZE / 4; \
2489 break; \
2490 default: \
2491 break; \
2495 /* defines handling */
2496 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2498 Sym *s;
2500 s = sym_push2(&define_stack, v, macro_type, (int)str);
2501 s->next = first_arg;
2502 table_ident[v - TOK_IDENT]->sym_define = s;
2505 /* undefined a define symbol. Its name is just set to zero */
2506 static void define_undef(Sym *s)
2508 int v;
2509 v = s->v;
2510 if (v >= TOK_IDENT && v < tok_ident)
2511 table_ident[v - TOK_IDENT]->sym_define = NULL;
2512 s->v = 0;
2515 static inline Sym *define_find(int v)
2517 v -= TOK_IDENT;
2518 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2519 return NULL;
2520 return table_ident[v]->sym_define;
2523 /* free define stack until top reaches 'b' */
2524 static void free_defines(Sym *b)
2526 Sym *top, *top1;
2527 int v;
2529 top = define_stack;
2530 while (top != b) {
2531 top1 = top->prev;
2532 /* do not free args or predefined defines */
2533 if (top->c)
2534 tok_str_free((int *)top->c);
2535 v = top->v;
2536 if (v >= TOK_IDENT && v < tok_ident)
2537 table_ident[v - TOK_IDENT]->sym_define = NULL;
2538 sym_free(top);
2539 top = top1;
2541 define_stack = b;
2544 /* label lookup */
2545 static Sym *label_find(int v)
2547 v -= TOK_IDENT;
2548 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2549 return NULL;
2550 return table_ident[v]->sym_label;
2553 static Sym *label_push(Sym **ptop, int v, int flags)
2555 Sym *s, **ps;
2556 s = sym_push2(ptop, v, 0, 0);
2557 s->r = flags;
2558 ps = &table_ident[v - TOK_IDENT]->sym_label;
2559 if (ptop == &global_label_stack) {
2560 /* modify the top most local identifier, so that
2561 sym_identifier will point to 's' when popped */
2562 while (*ps != NULL)
2563 ps = &(*ps)->prev_tok;
2565 s->prev_tok = *ps;
2566 *ps = s;
2567 return s;
2570 /* pop labels until element last is reached. Look if any labels are
2571 undefined. Define symbols if '&&label' was used. */
2572 static void label_pop(Sym **ptop, Sym *slast)
2574 Sym *s, *s1;
2575 for(s = *ptop; s != slast; s = s1) {
2576 s1 = s->prev;
2577 if (s->r == LABEL_DECLARED) {
2578 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2579 } else if (s->r == LABEL_FORWARD) {
2580 error("label '%s' used but not defined",
2581 get_tok_str(s->v, NULL));
2582 } else {
2583 if (s->c) {
2584 /* define corresponding symbol. A size of
2585 1 is put. */
2586 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2589 /* remove label */
2590 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2591 sym_free(s);
2593 *ptop = slast;
2596 /* eval an expression for #if/#elif */
2597 static int expr_preprocess(void)
2599 int c, t;
2600 TokenString str;
2602 tok_str_new(&str);
2603 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2604 next(); /* do macro subst */
2605 if (tok == TOK_DEFINED) {
2606 next_nomacro();
2607 t = tok;
2608 if (t == '(')
2609 next_nomacro();
2610 c = define_find(tok) != 0;
2611 if (t == '(')
2612 next_nomacro();
2613 tok = TOK_CINT;
2614 tokc.i = c;
2615 } else if (tok >= TOK_IDENT) {
2616 /* if undefined macro */
2617 tok = TOK_CINT;
2618 tokc.i = 0;
2620 tok_str_add_tok(&str);
2622 tok_str_add(&str, -1); /* simulate end of file */
2623 tok_str_add(&str, 0);
2624 /* now evaluate C constant expression */
2625 macro_ptr = str.str;
2626 next();
2627 c = expr_const();
2628 macro_ptr = NULL;
2629 tok_str_free(str.str);
2630 return c != 0;
2633 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2634 static void tok_print(int *str)
2636 int t;
2637 CValue cval;
2639 while (1) {
2640 TOK_GET(t, str, cval);
2641 if (!t)
2642 break;
2643 printf(" %s", get_tok_str(t, &cval));
2645 printf("\n");
2647 #endif
2649 /* parse after #define */
2650 static void parse_define(void)
2652 Sym *s, *first, **ps;
2653 int v, t, varg, is_vaargs, c;
2654 TokenString str;
2656 v = tok;
2657 if (v < TOK_IDENT)
2658 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2659 /* XXX: should check if same macro (ANSI) */
2660 first = NULL;
2661 t = MACRO_OBJ;
2662 /* '(' must be just after macro definition for MACRO_FUNC */
2663 c = file->buf_ptr[0];
2664 if (c == '\\')
2665 c = handle_stray1(file->buf_ptr);
2666 if (c == '(') {
2667 next_nomacro();
2668 next_nomacro();
2669 ps = &first;
2670 while (tok != ')') {
2671 varg = tok;
2672 next_nomacro();
2673 is_vaargs = 0;
2674 if (varg == TOK_DOTS) {
2675 varg = TOK___VA_ARGS__;
2676 is_vaargs = 1;
2677 } else if (tok == TOK_DOTS && gnu_ext) {
2678 is_vaargs = 1;
2679 next_nomacro();
2681 if (varg < TOK_IDENT)
2682 error("badly punctuated parameter list");
2683 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2684 *ps = s;
2685 ps = &s->next;
2686 if (tok != ',')
2687 break;
2688 next_nomacro();
2690 t = MACRO_FUNC;
2692 tok_str_new(&str);
2693 next_nomacro();
2694 /* EOF testing necessary for '-D' handling */
2695 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2696 tok_str_add2(&str, tok, &tokc);
2697 next_nomacro();
2699 tok_str_add(&str, 0);
2700 #ifdef PP_DEBUG
2701 printf("define %s %d: ", get_tok_str(v, NULL), t);
2702 tok_print(str.str);
2703 #endif
2704 define_push(v, t, str.str, first);
2707 static inline int hash_cached_include(int type, const char *filename)
2709 const unsigned char *s;
2710 unsigned int h;
2712 h = TOK_HASH_INIT;
2713 h = TOK_HASH_FUNC(h, type);
2714 s = filename;
2715 while (*s) {
2716 h = TOK_HASH_FUNC(h, *s);
2717 s++;
2719 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2720 return h;
2723 /* XXX: use a token or a hash table to accelerate matching ? */
2724 static CachedInclude *search_cached_include(TCCState *s1,
2725 int type, const char *filename)
2727 CachedInclude *e;
2728 int i, h;
2729 h = hash_cached_include(type, filename);
2730 i = s1->cached_includes_hash[h];
2731 for(;;) {
2732 if (i == 0)
2733 break;
2734 e = s1->cached_includes[i - 1];
2735 if (e->type == type && !strcmp(e->filename, filename))
2736 return e;
2737 i = e->hash_next;
2739 return NULL;
2742 static inline void add_cached_include(TCCState *s1, int type,
2743 const char *filename, int ifndef_macro)
2745 CachedInclude *e;
2746 int h;
2748 if (search_cached_include(s1, type, filename))
2749 return;
2750 #ifdef INC_DEBUG
2751 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2752 #endif
2753 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2754 if (!e)
2755 return;
2756 e->type = type;
2757 strcpy(e->filename, filename);
2758 e->ifndef_macro = ifndef_macro;
2759 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2760 /* add in hash table */
2761 h = hash_cached_include(type, filename);
2762 e->hash_next = s1->cached_includes_hash[h];
2763 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2766 static void pragma_parse(TCCState *s1)
2768 int val;
2770 next();
2771 if (tok == TOK_pack) {
2773 This may be:
2774 #pragma pack(1) // set
2775 #pragma pack() // reset to default
2776 #pragma pack(push,1) // push & set
2777 #pragma pack(pop) // restore previous
2779 next();
2780 skip('(');
2781 if (tok == TOK_ASM_pop) {
2782 next();
2783 if (s1->pack_stack_ptr <= s1->pack_stack) {
2784 stk_error:
2785 error("out of pack stack");
2787 s1->pack_stack_ptr--;
2788 } else {
2789 val = 0;
2790 if (tok != ')') {
2791 if (tok == TOK_ASM_push) {
2792 next();
2793 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2794 goto stk_error;
2795 s1->pack_stack_ptr++;
2796 skip(',');
2798 if (tok != TOK_CINT) {
2799 pack_error:
2800 error("invalid pack pragma");
2802 val = tokc.i;
2803 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2804 goto pack_error;
2805 next();
2807 *s1->pack_stack_ptr = val;
2808 skip(')');
2813 /* is_bof is true if first non space token at beginning of file */
2814 static void preprocess(int is_bof)
2816 TCCState *s1 = tcc_state;
2817 int size, i, c, n, saved_parse_flags;
2818 char buf[1024], *q, *p;
2819 char buf1[1024];
2820 BufferedFile *f;
2821 Sym *s;
2822 CachedInclude *e;
2824 saved_parse_flags = parse_flags;
2825 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2826 PARSE_FLAG_LINEFEED;
2827 next_nomacro();
2828 redo:
2829 switch(tok) {
2830 case TOK_DEFINE:
2831 next_nomacro();
2832 parse_define();
2833 break;
2834 case TOK_UNDEF:
2835 next_nomacro();
2836 s = define_find(tok);
2837 /* undefine symbol by putting an invalid name */
2838 if (s)
2839 define_undef(s);
2840 break;
2841 case TOK_INCLUDE:
2842 case TOK_INCLUDE_NEXT:
2843 ch = file->buf_ptr[0];
2844 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2845 skip_spaces();
2846 if (ch == '<') {
2847 c = '>';
2848 goto read_name;
2849 } else if (ch == '\"') {
2850 c = ch;
2851 read_name:
2852 /* XXX: better stray handling */
2853 minp();
2854 q = buf;
2855 while (ch != c && ch != '\n' && ch != CH_EOF) {
2856 if ((q - buf) < sizeof(buf) - 1)
2857 *q++ = ch;
2858 minp();
2860 *q = '\0';
2861 minp();
2862 #if 0
2863 /* eat all spaces and comments after include */
2864 /* XXX: slightly incorrect */
2865 while (ch1 != '\n' && ch1 != CH_EOF)
2866 inp();
2867 #endif
2868 } else {
2869 /* computed #include : either we have only strings or
2870 we have anything enclosed in '<>' */
2871 next();
2872 buf[0] = '\0';
2873 if (tok == TOK_STR) {
2874 while (tok != TOK_LINEFEED) {
2875 if (tok != TOK_STR) {
2876 include_syntax:
2877 error("'#include' expects \"FILENAME\" or <FILENAME>");
2879 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2880 next();
2882 c = '\"';
2883 } else {
2884 int len;
2885 while (tok != TOK_LINEFEED) {
2886 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2887 next();
2889 len = strlen(buf);
2890 /* check syntax and remove '<>' */
2891 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2892 goto include_syntax;
2893 memmove(buf, buf + 1, len - 2);
2894 buf[len - 2] = '\0';
2895 c = '>';
2899 e = search_cached_include(s1, c, buf);
2900 if (e && define_find(e->ifndef_macro)) {
2901 /* no need to parse the include because the 'ifndef macro'
2902 is defined */
2903 #ifdef INC_DEBUG
2904 printf("%s: skipping %s\n", file->filename, buf);
2905 #endif
2906 } else {
2907 if (c == '\"') {
2908 /* first search in current dir if "header.h" */
2909 size = 0;
2910 p = strrchr(file->filename, '/');
2911 if (p)
2912 size = p + 1 - file->filename;
2913 if (size > sizeof(buf1) - 1)
2914 size = sizeof(buf1) - 1;
2915 memcpy(buf1, file->filename, size);
2916 buf1[size] = '\0';
2917 pstrcat(buf1, sizeof(buf1), buf);
2918 f = tcc_open(s1, buf1);
2919 if (f) {
2920 if (tok == TOK_INCLUDE_NEXT)
2921 tok = TOK_INCLUDE;
2922 else
2923 goto found;
2926 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2927 error("#include recursion too deep");
2928 /* now search in all the include paths */
2929 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2930 for(i = 0; i < n; i++) {
2931 const char *path;
2932 if (i < s1->nb_include_paths)
2933 path = s1->include_paths[i];
2934 else
2935 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2936 pstrcpy(buf1, sizeof(buf1), path);
2937 pstrcat(buf1, sizeof(buf1), "/");
2938 pstrcat(buf1, sizeof(buf1), buf);
2939 f = tcc_open(s1, buf1);
2940 if (f) {
2941 if (tok == TOK_INCLUDE_NEXT)
2942 tok = TOK_INCLUDE;
2943 else
2944 goto found;
2947 error("include file '%s' not found", buf);
2948 f = NULL;
2949 found:
2950 #ifdef INC_DEBUG
2951 printf("%s: including %s\n", file->filename, buf1);
2952 #endif
2953 f->inc_type = c;
2954 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2955 /* push current file in stack */
2956 /* XXX: fix current line init */
2957 *s1->include_stack_ptr++ = file;
2958 file = f;
2959 /* add include file debug info */
2960 if (do_debug) {
2961 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2963 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2964 ch = file->buf_ptr[0];
2965 goto the_end;
2967 break;
2968 case TOK_IFNDEF:
2969 c = 1;
2970 goto do_ifdef;
2971 case TOK_IF:
2972 c = expr_preprocess();
2973 goto do_if;
2974 case TOK_IFDEF:
2975 c = 0;
2976 do_ifdef:
2977 next_nomacro();
2978 if (tok < TOK_IDENT)
2979 error("invalid argument for '#if%sdef'", c ? "n" : "");
2980 if (is_bof) {
2981 if (c) {
2982 #ifdef INC_DEBUG
2983 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2984 #endif
2985 file->ifndef_macro = tok;
2988 c = (define_find(tok) != 0) ^ c;
2989 do_if:
2990 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2991 error("memory full");
2992 *s1->ifdef_stack_ptr++ = c;
2993 goto test_skip;
2994 case TOK_ELSE:
2995 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2996 error("#else without matching #if");
2997 if (s1->ifdef_stack_ptr[-1] & 2)
2998 error("#else after #else");
2999 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3000 goto test_skip;
3001 case TOK_ELIF:
3002 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3003 error("#elif without matching #if");
3004 c = s1->ifdef_stack_ptr[-1];
3005 if (c > 1)
3006 error("#elif after #else");
3007 /* last #if/#elif expression was true: we skip */
3008 if (c == 1)
3009 goto skip;
3010 c = expr_preprocess();
3011 s1->ifdef_stack_ptr[-1] = c;
3012 test_skip:
3013 if (!(c & 1)) {
3014 skip:
3015 preprocess_skip();
3016 is_bof = 0;
3017 goto redo;
3019 break;
3020 case TOK_ENDIF:
3021 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3022 error("#endif without matching #if");
3023 s1->ifdef_stack_ptr--;
3024 /* '#ifndef macro' was at the start of file. Now we check if
3025 an '#endif' is exactly at the end of file */
3026 if (file->ifndef_macro &&
3027 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3028 file->ifndef_macro_saved = file->ifndef_macro;
3029 /* need to set to zero to avoid false matches if another
3030 #ifndef at middle of file */
3031 file->ifndef_macro = 0;
3032 while (tok != TOK_LINEFEED)
3033 next_nomacro();
3034 tok_flags |= TOK_FLAG_ENDIF;
3035 goto the_end;
3037 break;
3038 case TOK_LINE:
3039 next();
3040 if (tok != TOK_CINT)
3041 error("#line");
3042 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3043 next();
3044 if (tok != TOK_LINEFEED) {
3045 if (tok != TOK_STR)
3046 error("#line");
3047 pstrcpy(file->filename, sizeof(file->filename),
3048 (char *)tokc.cstr->data);
3050 break;
3051 case TOK_ERROR:
3052 case TOK_WARNING:
3053 c = tok;
3054 ch = file->buf_ptr[0];
3055 skip_spaces();
3056 q = buf;
3057 while (ch != '\n' && ch != CH_EOF) {
3058 if ((q - buf) < sizeof(buf) - 1)
3059 *q++ = ch;
3060 minp();
3062 *q = '\0';
3063 if (c == TOK_ERROR)
3064 error("#error %s", buf);
3065 else
3066 warning("#warning %s", buf);
3067 break;
3068 case TOK_PRAGMA:
3069 pragma_parse(s1);
3070 break;
3071 default:
3072 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3073 /* '!' is ignored to allow C scripts. numbers are ignored
3074 to emulate cpp behaviour */
3075 } else {
3076 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3077 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
3079 break;
3081 /* ignore other preprocess commands or #! for C scripts */
3082 while (tok != TOK_LINEFEED)
3083 next_nomacro();
3084 the_end:
3085 parse_flags = saved_parse_flags;
3088 /* evaluate escape codes in a string. */
3089 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3091 int c, n;
3092 const uint8_t *p;
3094 p = buf;
3095 for(;;) {
3096 c = *p;
3097 if (c == '\0')
3098 break;
3099 if (c == '\\') {
3100 p++;
3101 /* escape */
3102 c = *p;
3103 switch(c) {
3104 case '0': case '1': case '2': case '3':
3105 case '4': case '5': case '6': case '7':
3106 /* at most three octal digits */
3107 n = c - '0';
3108 p++;
3109 c = *p;
3110 if (isoct(c)) {
3111 n = n * 8 + c - '0';
3112 p++;
3113 c = *p;
3114 if (isoct(c)) {
3115 n = n * 8 + c - '0';
3116 p++;
3119 c = n;
3120 goto add_char_nonext;
3121 case 'x':
3122 p++;
3123 n = 0;
3124 for(;;) {
3125 c = *p;
3126 if (c >= 'a' && c <= 'f')
3127 c = c - 'a' + 10;
3128 else if (c >= 'A' && c <= 'F')
3129 c = c - 'A' + 10;
3130 else if (isnum(c))
3131 c = c - '0';
3132 else
3133 break;
3134 n = n * 16 + c;
3135 p++;
3137 c = n;
3138 goto add_char_nonext;
3139 case 'a':
3140 c = '\a';
3141 break;
3142 case 'b':
3143 c = '\b';
3144 break;
3145 case 'f':
3146 c = '\f';
3147 break;
3148 case 'n':
3149 c = '\n';
3150 break;
3151 case 'r':
3152 c = '\r';
3153 break;
3154 case 't':
3155 c = '\t';
3156 break;
3157 case 'v':
3158 c = '\v';
3159 break;
3160 case 'e':
3161 if (!gnu_ext)
3162 goto invalid_escape;
3163 c = 27;
3164 break;
3165 case '\'':
3166 case '\"':
3167 case '\\':
3168 case '?':
3169 break;
3170 default:
3171 invalid_escape:
3172 if (c >= '!' && c <= '~')
3173 warning("unknown escape sequence: \'\\%c\'", c);
3174 else
3175 warning("unknown escape sequence: \'\\x%x\'", c);
3176 break;
3179 p++;
3180 add_char_nonext:
3181 if (!is_long)
3182 cstr_ccat(outstr, c);
3183 else
3184 cstr_wccat(outstr, c);
3186 /* add a trailing '\0' */
3187 if (!is_long)
3188 cstr_ccat(outstr, '\0');
3189 else
3190 cstr_wccat(outstr, '\0');
3193 /* we use 64 bit numbers */
3194 #define BN_SIZE 2
3196 /* bn = (bn << shift) | or_val */
3197 void bn_lshift(unsigned int *bn, int shift, int or_val)
3199 int i;
3200 unsigned int v;
3201 for(i=0;i<BN_SIZE;i++) {
3202 v = bn[i];
3203 bn[i] = (v << shift) | or_val;
3204 or_val = v >> (32 - shift);
3208 void bn_zero(unsigned int *bn)
3210 int i;
3211 for(i=0;i<BN_SIZE;i++) {
3212 bn[i] = 0;
3216 /* parse number in null terminated string 'p' and return it in the
3217 current token */
3218 void parse_number(const char *p)
3220 int b, t, shift, frac_bits, s, exp_val, ch;
3221 char *q;
3222 unsigned int bn[BN_SIZE];
3223 double d;
3225 /* number */
3226 q = token_buf;
3227 ch = *p++;
3228 t = ch;
3229 ch = *p++;
3230 *q++ = t;
3231 b = 10;
3232 if (t == '.') {
3233 goto float_frac_parse;
3234 } else if (t == '0') {
3235 if (ch == 'x' || ch == 'X') {
3236 q--;
3237 ch = *p++;
3238 b = 16;
3239 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3240 q--;
3241 ch = *p++;
3242 b = 2;
3245 /* parse all digits. cannot check octal numbers at this stage
3246 because of floating point constants */
3247 while (1) {
3248 if (ch >= 'a' && ch <= 'f')
3249 t = ch - 'a' + 10;
3250 else if (ch >= 'A' && ch <= 'F')
3251 t = ch - 'A' + 10;
3252 else if (isnum(ch))
3253 t = ch - '0';
3254 else
3255 break;
3256 if (t >= b)
3257 break;
3258 if (q >= token_buf + STRING_MAX_SIZE) {
3259 num_too_long:
3260 error("number too long");
3262 *q++ = ch;
3263 ch = *p++;
3265 if (ch == '.' ||
3266 ((ch == 'e' || ch == 'E') && b == 10) ||
3267 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3268 if (b != 10) {
3269 /* NOTE: strtox should support that for hexa numbers, but
3270 non ISOC99 libcs do not support it, so we prefer to do
3271 it by hand */
3272 /* hexadecimal or binary floats */
3273 /* XXX: handle overflows */
3274 *q = '\0';
3275 if (b == 16)
3276 shift = 4;
3277 else
3278 shift = 2;
3279 bn_zero(bn);
3280 q = token_buf;
3281 while (1) {
3282 t = *q++;
3283 if (t == '\0') {
3284 break;
3285 } else if (t >= 'a') {
3286 t = t - 'a' + 10;
3287 } else if (t >= 'A') {
3288 t = t - 'A' + 10;
3289 } else {
3290 t = t - '0';
3292 bn_lshift(bn, shift, t);
3294 frac_bits = 0;
3295 if (ch == '.') {
3296 ch = *p++;
3297 while (1) {
3298 t = ch;
3299 if (t >= 'a' && t <= 'f') {
3300 t = t - 'a' + 10;
3301 } else if (t >= 'A' && t <= 'F') {
3302 t = t - 'A' + 10;
3303 } else if (t >= '0' && t <= '9') {
3304 t = t - '0';
3305 } else {
3306 break;
3308 if (t >= b)
3309 error("invalid digit");
3310 bn_lshift(bn, shift, t);
3311 frac_bits += shift;
3312 ch = *p++;
3315 if (ch != 'p' && ch != 'P')
3316 expect("exponent");
3317 ch = *p++;
3318 s = 1;
3319 exp_val = 0;
3320 if (ch == '+') {
3321 ch = *p++;
3322 } else if (ch == '-') {
3323 s = -1;
3324 ch = *p++;
3326 if (ch < '0' || ch > '9')
3327 expect("exponent digits");
3328 while (ch >= '0' && ch <= '9') {
3329 exp_val = exp_val * 10 + ch - '0';
3330 ch = *p++;
3332 exp_val = exp_val * s;
3334 /* now we can generate the number */
3335 /* XXX: should patch directly float number */
3336 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3337 d = ldexp(d, exp_val - frac_bits);
3338 t = toup(ch);
3339 if (t == 'F') {
3340 ch = *p++;
3341 tok = TOK_CFLOAT;
3342 /* float : should handle overflow */
3343 tokc.f = (float)d;
3344 } else if (t == 'L') {
3345 ch = *p++;
3346 tok = TOK_CLDOUBLE;
3347 /* XXX: not large enough */
3348 tokc.ld = (long double)d;
3349 } else {
3350 tok = TOK_CDOUBLE;
3351 tokc.d = d;
3353 } else {
3354 /* decimal floats */
3355 if (ch == '.') {
3356 if (q >= token_buf + STRING_MAX_SIZE)
3357 goto num_too_long;
3358 *q++ = ch;
3359 ch = *p++;
3360 float_frac_parse:
3361 while (ch >= '0' && ch <= '9') {
3362 if (q >= token_buf + STRING_MAX_SIZE)
3363 goto num_too_long;
3364 *q++ = ch;
3365 ch = *p++;
3368 if (ch == 'e' || ch == 'E') {
3369 if (q >= token_buf + STRING_MAX_SIZE)
3370 goto num_too_long;
3371 *q++ = ch;
3372 ch = *p++;
3373 if (ch == '-' || ch == '+') {
3374 if (q >= token_buf + STRING_MAX_SIZE)
3375 goto num_too_long;
3376 *q++ = ch;
3377 ch = *p++;
3379 if (ch < '0' || ch > '9')
3380 expect("exponent digits");
3381 while (ch >= '0' && ch <= '9') {
3382 if (q >= token_buf + STRING_MAX_SIZE)
3383 goto num_too_long;
3384 *q++ = ch;
3385 ch = *p++;
3388 *q = '\0';
3389 t = toup(ch);
3390 errno = 0;
3391 if (t == 'F') {
3392 ch = *p++;
3393 tok = TOK_CFLOAT;
3394 tokc.f = strtof(token_buf, NULL);
3395 } else if (t == 'L') {
3396 ch = *p++;
3397 tok = TOK_CLDOUBLE;
3398 tokc.ld = strtold(token_buf, NULL);
3399 } else {
3400 tok = TOK_CDOUBLE;
3401 tokc.d = strtod(token_buf, NULL);
3404 } else {
3405 unsigned long long n, n1;
3406 int lcount, ucount;
3408 /* integer number */
3409 *q = '\0';
3410 q = token_buf;
3411 if (b == 10 && *q == '0') {
3412 b = 8;
3413 q++;
3415 n = 0;
3416 while(1) {
3417 t = *q++;
3418 /* no need for checks except for base 10 / 8 errors */
3419 if (t == '\0') {
3420 break;
3421 } else if (t >= 'a') {
3422 t = t - 'a' + 10;
3423 } else if (t >= 'A') {
3424 t = t - 'A' + 10;
3425 } else {
3426 t = t - '0';
3427 if (t >= b)
3428 error("invalid digit");
3430 n1 = n;
3431 n = n * b + t;
3432 /* detect overflow */
3433 /* XXX: this test is not reliable */
3434 if (n < n1)
3435 error("integer constant overflow");
3438 /* XXX: not exactly ANSI compliant */
3439 if ((n & 0xffffffff00000000LL) != 0) {
3440 if ((n >> 63) != 0)
3441 tok = TOK_CULLONG;
3442 else
3443 tok = TOK_CLLONG;
3444 } else if (n > 0x7fffffff) {
3445 tok = TOK_CUINT;
3446 } else {
3447 tok = TOK_CINT;
3449 lcount = 0;
3450 ucount = 0;
3451 for(;;) {
3452 t = toup(ch);
3453 if (t == 'L') {
3454 if (lcount >= 2)
3455 error("three 'l's in integer constant");
3456 lcount++;
3457 if (lcount == 2) {
3458 if (tok == TOK_CINT)
3459 tok = TOK_CLLONG;
3460 else if (tok == TOK_CUINT)
3461 tok = TOK_CULLONG;
3463 ch = *p++;
3464 } else if (t == 'U') {
3465 if (ucount >= 1)
3466 error("two 'u's in integer constant");
3467 ucount++;
3468 if (tok == TOK_CINT)
3469 tok = TOK_CUINT;
3470 else if (tok == TOK_CLLONG)
3471 tok = TOK_CULLONG;
3472 ch = *p++;
3473 } else {
3474 break;
3477 if (tok == TOK_CINT || tok == TOK_CUINT)
3478 tokc.ui = n;
3479 else
3480 tokc.ull = n;
3485 #define PARSE2(c1, tok1, c2, tok2) \
3486 case c1: \
3487 PEEKC(c, p); \
3488 if (c == c2) { \
3489 p++; \
3490 tok = tok2; \
3491 } else { \
3492 tok = tok1; \
3494 break;
3496 /* return next token without macro substitution */
3497 static inline void next_nomacro1(void)
3499 int t, c, is_long;
3500 TokenSym *ts;
3501 uint8_t *p, *p1;
3502 unsigned int h;
3504 p = file->buf_ptr;
3505 redo_no_start:
3506 c = *p;
3507 switch(c) {
3508 case ' ':
3509 case '\t':
3510 case '\f':
3511 case '\v':
3512 case '\r':
3513 p++;
3514 goto redo_no_start;
3516 case '\\':
3517 /* first look if it is in fact an end of buffer */
3518 if (p >= file->buf_end) {
3519 file->buf_ptr = p;
3520 handle_eob();
3521 p = file->buf_ptr;
3522 if (p >= file->buf_end)
3523 goto parse_eof;
3524 else
3525 goto redo_no_start;
3526 } else {
3527 file->buf_ptr = p;
3528 ch = *p;
3529 handle_stray();
3530 p = file->buf_ptr;
3531 goto redo_no_start;
3533 parse_eof:
3535 TCCState *s1 = tcc_state;
3536 if (parse_flags & PARSE_FLAG_LINEFEED) {
3537 tok = TOK_LINEFEED;
3538 } else if (s1->include_stack_ptr == s1->include_stack ||
3539 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3540 /* no include left : end of file. */
3541 tok = TOK_EOF;
3542 } else {
3543 /* pop include file */
3545 /* test if previous '#endif' was after a #ifdef at
3546 start of file */
3547 if (tok_flags & TOK_FLAG_ENDIF) {
3548 #ifdef INC_DEBUG
3549 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3550 #endif
3551 add_cached_include(s1, file->inc_type, file->inc_filename,
3552 file->ifndef_macro_saved);
3555 /* add end of include file debug info */
3556 if (do_debug) {
3557 put_stabd(N_EINCL, 0, 0);
3559 /* pop include stack */
3560 tcc_close(file);
3561 s1->include_stack_ptr--;
3562 file = *s1->include_stack_ptr;
3563 p = file->buf_ptr;
3564 goto redo_no_start;
3567 break;
3569 case '\n':
3570 if (parse_flags & PARSE_FLAG_LINEFEED) {
3571 tok = TOK_LINEFEED;
3572 } else {
3573 file->line_num++;
3574 tok_flags |= TOK_FLAG_BOL;
3575 p++;
3576 goto redo_no_start;
3578 break;
3580 case '#':
3581 /* XXX: simplify */
3582 PEEKC(c, p);
3583 if ((tok_flags & TOK_FLAG_BOL) &&
3584 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3585 file->buf_ptr = p;
3586 preprocess(tok_flags & TOK_FLAG_BOF);
3587 p = file->buf_ptr;
3588 goto redo_no_start;
3589 } else {
3590 if (c == '#') {
3591 p++;
3592 tok = TOK_TWOSHARPS;
3593 } else {
3594 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3595 p = parse_line_comment(p - 1);
3596 goto redo_no_start;
3597 } else {
3598 tok = '#';
3602 break;
3604 case 'a': case 'b': case 'c': case 'd':
3605 case 'e': case 'f': case 'g': case 'h':
3606 case 'i': case 'j': case 'k': case 'l':
3607 case 'm': case 'n': case 'o': case 'p':
3608 case 'q': case 'r': case 's': case 't':
3609 case 'u': case 'v': case 'w': case 'x':
3610 case 'y': case 'z':
3611 case 'A': case 'B': case 'C': case 'D':
3612 case 'E': case 'F': case 'G': case 'H':
3613 case 'I': case 'J': case 'K':
3614 case 'M': case 'N': case 'O': case 'P':
3615 case 'Q': case 'R': case 'S': case 'T':
3616 case 'U': case 'V': case 'W': case 'X':
3617 case 'Y': case 'Z':
3618 case '_':
3619 parse_ident_fast:
3620 p1 = p;
3621 h = TOK_HASH_INIT;
3622 h = TOK_HASH_FUNC(h, c);
3623 p++;
3624 for(;;) {
3625 c = *p;
3626 if (!isidnum_table[c])
3627 break;
3628 h = TOK_HASH_FUNC(h, c);
3629 p++;
3631 if (c != '\\') {
3632 TokenSym **pts;
3633 int len;
3635 /* fast case : no stray found, so we have the full token
3636 and we have already hashed it */
3637 len = p - p1;
3638 h &= (TOK_HASH_SIZE - 1);
3639 pts = &hash_ident[h];
3640 for(;;) {
3641 ts = *pts;
3642 if (!ts)
3643 break;
3644 if (ts->len == len && !memcmp(ts->str, p1, len))
3645 goto token_found;
3646 pts = &(ts->hash_next);
3648 ts = tok_alloc_new(pts, p1, len);
3649 token_found: ;
3650 } else {
3651 /* slower case */
3652 cstr_reset(&tokcstr);
3654 while (p1 < p) {
3655 cstr_ccat(&tokcstr, *p1);
3656 p1++;
3658 p--;
3659 PEEKC(c, p);
3660 parse_ident_slow:
3661 while (isidnum_table[c]) {
3662 cstr_ccat(&tokcstr, c);
3663 PEEKC(c, p);
3665 ts = tok_alloc(tokcstr.data, tokcstr.size);
3667 tok = ts->tok;
3668 break;
3669 case 'L':
3670 t = p[1];
3671 if (t != '\\' && t != '\'' && t != '\"') {
3672 /* fast case */
3673 goto parse_ident_fast;
3674 } else {
3675 PEEKC(c, p);
3676 if (c == '\'' || c == '\"') {
3677 is_long = 1;
3678 goto str_const;
3679 } else {
3680 cstr_reset(&tokcstr);
3681 cstr_ccat(&tokcstr, 'L');
3682 goto parse_ident_slow;
3685 break;
3686 case '0': case '1': case '2': case '3':
3687 case '4': case '5': case '6': case '7':
3688 case '8': case '9':
3690 cstr_reset(&tokcstr);
3691 /* after the first digit, accept digits, alpha, '.' or sign if
3692 prefixed by 'eEpP' */
3693 parse_num:
3694 for(;;) {
3695 t = c;
3696 cstr_ccat(&tokcstr, c);
3697 PEEKC(c, p);
3698 if (!(isnum(c) || isid(c) || c == '.' ||
3699 ((c == '+' || c == '-') &&
3700 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3701 break;
3703 /* We add a trailing '\0' to ease parsing */
3704 cstr_ccat(&tokcstr, '\0');
3705 tokc.cstr = &tokcstr;
3706 tok = TOK_PPNUM;
3707 break;
3708 case '.':
3709 /* special dot handling because it can also start a number */
3710 PEEKC(c, p);
3711 if (isnum(c)) {
3712 cstr_reset(&tokcstr);
3713 cstr_ccat(&tokcstr, '.');
3714 goto parse_num;
3715 } else if (c == '.') {
3716 PEEKC(c, p);
3717 if (c != '.')
3718 expect("'.'");
3719 PEEKC(c, p);
3720 tok = TOK_DOTS;
3721 } else {
3722 tok = '.';
3724 break;
3725 case '\'':
3726 case '\"':
3727 is_long = 0;
3728 str_const:
3730 CString str;
3731 int sep;
3733 sep = c;
3735 /* parse the string */
3736 cstr_new(&str);
3737 p = parse_pp_string(p, sep, &str);
3738 cstr_ccat(&str, '\0');
3740 /* eval the escape (should be done as TOK_PPNUM) */
3741 cstr_reset(&tokcstr);
3742 parse_escape_string(&tokcstr, str.data, is_long);
3743 cstr_free(&str);
3745 if (sep == '\'') {
3746 int char_size;
3747 /* XXX: make it portable */
3748 if (!is_long)
3749 char_size = 1;
3750 else
3751 char_size = sizeof(nwchar_t);
3752 if (tokcstr.size <= char_size)
3753 error("empty character constant");
3754 if (tokcstr.size > 2 * char_size)
3755 warning("multi-character character constant");
3756 if (!is_long) {
3757 tokc.i = *(int8_t *)tokcstr.data;
3758 tok = TOK_CCHAR;
3759 } else {
3760 tokc.i = *(nwchar_t *)tokcstr.data;
3761 tok = TOK_LCHAR;
3763 } else {
3764 tokc.cstr = &tokcstr;
3765 if (!is_long)
3766 tok = TOK_STR;
3767 else
3768 tok = TOK_LSTR;
3771 break;
3773 case '<':
3774 PEEKC(c, p);
3775 if (c == '=') {
3776 p++;
3777 tok = TOK_LE;
3778 } else if (c == '<') {
3779 PEEKC(c, p);
3780 if (c == '=') {
3781 p++;
3782 tok = TOK_A_SHL;
3783 } else {
3784 tok = TOK_SHL;
3786 } else {
3787 tok = TOK_LT;
3789 break;
3791 case '>':
3792 PEEKC(c, p);
3793 if (c == '=') {
3794 p++;
3795 tok = TOK_GE;
3796 } else if (c == '>') {
3797 PEEKC(c, p);
3798 if (c == '=') {
3799 p++;
3800 tok = TOK_A_SAR;
3801 } else {
3802 tok = TOK_SAR;
3804 } else {
3805 tok = TOK_GT;
3807 break;
3809 case '&':
3810 PEEKC(c, p);
3811 if (c == '&') {
3812 p++;
3813 tok = TOK_LAND;
3814 } else if (c == '=') {
3815 p++;
3816 tok = TOK_A_AND;
3817 } else {
3818 tok = '&';
3820 break;
3822 case '|':
3823 PEEKC(c, p);
3824 if (c == '|') {
3825 p++;
3826 tok = TOK_LOR;
3827 } else if (c == '=') {
3828 p++;
3829 tok = TOK_A_OR;
3830 } else {
3831 tok = '|';
3833 break;
3835 case '+':
3836 PEEKC(c, p);
3837 if (c == '+') {
3838 p++;
3839 tok = TOK_INC;
3840 } else if (c == '=') {
3841 p++;
3842 tok = TOK_A_ADD;
3843 } else {
3844 tok = '+';
3846 break;
3848 case '-':
3849 PEEKC(c, p);
3850 if (c == '-') {
3851 p++;
3852 tok = TOK_DEC;
3853 } else if (c == '=') {
3854 p++;
3855 tok = TOK_A_SUB;
3856 } else if (c == '>') {
3857 p++;
3858 tok = TOK_ARROW;
3859 } else {
3860 tok = '-';
3862 break;
3864 PARSE2('!', '!', '=', TOK_NE)
3865 PARSE2('=', '=', '=', TOK_EQ)
3866 PARSE2('*', '*', '=', TOK_A_MUL)
3867 PARSE2('%', '%', '=', TOK_A_MOD)
3868 PARSE2('^', '^', '=', TOK_A_XOR)
3870 /* comments or operator */
3871 case '/':
3872 PEEKC(c, p);
3873 if (c == '*') {
3874 p = parse_comment(p);
3875 goto redo_no_start;
3876 } else if (c == '/') {
3877 p = parse_line_comment(p);
3878 goto redo_no_start;
3879 } else if (c == '=') {
3880 p++;
3881 tok = TOK_A_DIV;
3882 } else {
3883 tok = '/';
3885 break;
3887 /* simple tokens */
3888 case '(':
3889 case ')':
3890 case '[':
3891 case ']':
3892 case '{':
3893 case '}':
3894 case ',':
3895 case ';':
3896 case ':':
3897 case '?':
3898 case '~':
3899 case '$': /* only used in assembler */
3900 case '@': /* dito */
3901 tok = c;
3902 p++;
3903 break;
3904 default:
3905 error("unrecognized character \\x%02x", c);
3906 break;
3908 file->buf_ptr = p;
3909 tok_flags = 0;
3910 #if defined(PARSE_DEBUG)
3911 printf("token = %s\n", get_tok_str(tok, &tokc));
3912 #endif
3915 /* return next token without macro substitution. Can read input from
3916 macro_ptr buffer */
3917 static void next_nomacro(void)
3919 if (macro_ptr) {
3920 redo:
3921 tok = *macro_ptr;
3922 if (tok) {
3923 TOK_GET(tok, macro_ptr, tokc);
3924 if (tok == TOK_LINENUM) {
3925 file->line_num = tokc.i;
3926 goto redo;
3929 } else {
3930 next_nomacro1();
3934 /* substitute args in macro_str and return allocated string */
3935 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3937 int *st, last_tok, t, notfirst;
3938 Sym *s;
3939 CValue cval;
3940 TokenString str;
3941 CString cstr;
3943 tok_str_new(&str);
3944 last_tok = 0;
3945 while(1) {
3946 TOK_GET(t, macro_str, cval);
3947 if (!t)
3948 break;
3949 if (t == '#') {
3950 /* stringize */
3951 TOK_GET(t, macro_str, cval);
3952 if (!t)
3953 break;
3954 s = sym_find2(args, t);
3955 if (s) {
3956 cstr_new(&cstr);
3957 st = (int *)s->c;
3958 notfirst = 0;
3959 while (*st) {
3960 if (notfirst)
3961 cstr_ccat(&cstr, ' ');
3962 TOK_GET(t, st, cval);
3963 cstr_cat(&cstr, get_tok_str(t, &cval));
3964 notfirst = 1;
3966 cstr_ccat(&cstr, '\0');
3967 #ifdef PP_DEBUG
3968 printf("stringize: %s\n", (char *)cstr.data);
3969 #endif
3970 /* add string */
3971 cval.cstr = &cstr;
3972 tok_str_add2(&str, TOK_STR, &cval);
3973 cstr_free(&cstr);
3974 } else {
3975 tok_str_add2(&str, t, &cval);
3977 } else if (t >= TOK_IDENT) {
3978 s = sym_find2(args, t);
3979 if (s) {
3980 st = (int *)s->c;
3981 /* if '##' is present before or after, no arg substitution */
3982 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3983 /* special case for var arg macros : ## eats the
3984 ',' if empty VA_ARGS variable. */
3985 /* XXX: test of the ',' is not 100%
3986 reliable. should fix it to avoid security
3987 problems */
3988 if (gnu_ext && s->type.t &&
3989 last_tok == TOK_TWOSHARPS &&
3990 str.len >= 2 && str.str[str.len - 2] == ',') {
3991 if (*st == 0) {
3992 /* suppress ',' '##' */
3993 str.len -= 2;
3994 } else {
3995 /* suppress '##' and add variable */
3996 str.len--;
3997 goto add_var;
3999 } else {
4000 int t1;
4001 add_var:
4002 for(;;) {
4003 TOK_GET(t1, st, cval);
4004 if (!t1)
4005 break;
4006 tok_str_add2(&str, t1, &cval);
4009 } else {
4010 /* NOTE: the stream cannot be read when macro
4011 substituing an argument */
4012 macro_subst(&str, nested_list, st, NULL);
4014 } else {
4015 tok_str_add(&str, t);
4017 } else {
4018 tok_str_add2(&str, t, &cval);
4020 last_tok = t;
4022 tok_str_add(&str, 0);
4023 return str.str;
4026 static char const ab_month_name[12][4] =
4028 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4029 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4032 /* do macro substitution of current token with macro 's' and add
4033 result to (tok_str,tok_len). 'nested_list' is the list of all
4034 macros we got inside to avoid recursing. Return non zero if no
4035 substitution needs to be done */
4036 static int macro_subst_tok(TokenString *tok_str,
4037 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4039 Sym *args, *sa, *sa1;
4040 int mstr_allocated, parlevel, *mstr, t, t1;
4041 TokenString str;
4042 char *cstrval;
4043 CValue cval;
4044 CString cstr;
4045 char buf[32];
4047 /* if symbol is a macro, prepare substitution */
4048 /* special macros */
4049 if (tok == TOK___LINE__) {
4050 snprintf(buf, sizeof(buf), "%d", file->line_num);
4051 cstrval = buf;
4052 t1 = TOK_PPNUM;
4053 goto add_cstr1;
4054 } else if (tok == TOK___FILE__) {
4055 cstrval = file->filename;
4056 goto add_cstr;
4057 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4058 time_t ti;
4059 struct tm *tm;
4061 time(&ti);
4062 tm = localtime(&ti);
4063 if (tok == TOK___DATE__) {
4064 snprintf(buf, sizeof(buf), "%s %2d %d",
4065 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4066 } else {
4067 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4068 tm->tm_hour, tm->tm_min, tm->tm_sec);
4070 cstrval = buf;
4071 add_cstr:
4072 t1 = TOK_STR;
4073 add_cstr1:
4074 cstr_new(&cstr);
4075 cstr_cat(&cstr, cstrval);
4076 cstr_ccat(&cstr, '\0');
4077 cval.cstr = &cstr;
4078 tok_str_add2(tok_str, t1, &cval);
4079 cstr_free(&cstr);
4080 } else {
4081 mstr = (int *)s->c;
4082 mstr_allocated = 0;
4083 if (s->type.t == MACRO_FUNC) {
4084 /* NOTE: we do not use next_nomacro to avoid eating the
4085 next token. XXX: find better solution */
4086 redo:
4087 if (macro_ptr) {
4088 t = *macro_ptr;
4089 if (t == 0 && can_read_stream) {
4090 /* end of macro stream: we must look at the token
4091 after in the file */
4092 struct macro_level *ml = *can_read_stream;
4093 macro_ptr = NULL;
4094 if (ml)
4096 macro_ptr = ml->p;
4097 ml->p = NULL;
4098 *can_read_stream = ml -> prev;
4100 goto redo;
4102 } else {
4103 /* XXX: incorrect with comments */
4104 ch = file->buf_ptr[0];
4105 while (is_space(ch) || ch == '\n')
4106 cinp();
4107 t = ch;
4109 if (t != '(') /* no macro subst */
4110 return -1;
4112 /* argument macro */
4113 next_nomacro();
4114 next_nomacro();
4115 args = NULL;
4116 sa = s->next;
4117 /* NOTE: empty args are allowed, except if no args */
4118 for(;;) {
4119 /* handle '()' case */
4120 if (!args && !sa && tok == ')')
4121 break;
4122 if (!sa)
4123 error("macro '%s' used with too many args",
4124 get_tok_str(s->v, 0));
4125 tok_str_new(&str);
4126 parlevel = 0;
4127 /* NOTE: non zero sa->t indicates VA_ARGS */
4128 while ((parlevel > 0 ||
4129 (tok != ')' &&
4130 (tok != ',' || sa->type.t))) &&
4131 tok != -1) {
4132 if (tok == '(')
4133 parlevel++;
4134 else if (tok == ')')
4135 parlevel--;
4136 tok_str_add2(&str, tok, &tokc);
4137 next_nomacro();
4139 tok_str_add(&str, 0);
4140 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4141 sa = sa->next;
4142 if (tok == ')') {
4143 /* special case for gcc var args: add an empty
4144 var arg argument if it is omitted */
4145 if (sa && sa->type.t && gnu_ext)
4146 continue;
4147 else
4148 break;
4150 if (tok != ',')
4151 expect(",");
4152 next_nomacro();
4154 if (sa) {
4155 error("macro '%s' used with too few args",
4156 get_tok_str(s->v, 0));
4159 /* now subst each arg */
4160 mstr = macro_arg_subst(nested_list, mstr, args);
4161 /* free memory */
4162 sa = args;
4163 while (sa) {
4164 sa1 = sa->prev;
4165 tok_str_free((int *)sa->c);
4166 sym_free(sa);
4167 sa = sa1;
4169 mstr_allocated = 1;
4171 sym_push2(nested_list, s->v, 0, 0);
4172 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4173 /* pop nested defined symbol */
4174 sa1 = *nested_list;
4175 *nested_list = sa1->prev;
4176 sym_free(sa1);
4177 if (mstr_allocated)
4178 tok_str_free(mstr);
4180 return 0;
4183 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4184 return the resulting string (which must be freed). */
4185 static inline int *macro_twosharps(const int *macro_str)
4187 TokenSym *ts;
4188 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4189 int t;
4190 const char *p1, *p2;
4191 CValue cval;
4192 TokenString macro_str1;
4193 CString cstr;
4195 start_macro_ptr = macro_str;
4196 /* we search the first '##' */
4197 for(;;) {
4198 macro_ptr1 = macro_str;
4199 TOK_GET(t, macro_str, cval);
4200 /* nothing more to do if end of string */
4201 if (t == 0)
4202 return NULL;
4203 if (*macro_str == TOK_TWOSHARPS)
4204 break;
4207 /* we saw '##', so we need more processing to handle it */
4208 cstr_new(&cstr);
4209 tok_str_new(&macro_str1);
4210 tok = t;
4211 tokc = cval;
4213 /* add all tokens seen so far */
4214 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4215 TOK_GET(t, ptr, cval);
4216 tok_str_add2(&macro_str1, t, &cval);
4218 saved_macro_ptr = macro_ptr;
4219 /* XXX: get rid of the use of macro_ptr here */
4220 macro_ptr = (int *)macro_str;
4221 for(;;) {
4222 while (*macro_ptr == TOK_TWOSHARPS) {
4223 macro_ptr++;
4224 macro_ptr1 = macro_ptr;
4225 t = *macro_ptr;
4226 if (t) {
4227 TOK_GET(t, macro_ptr, cval);
4228 /* We concatenate the two tokens if we have an
4229 identifier or a preprocessing number */
4230 cstr_reset(&cstr);
4231 p1 = get_tok_str(tok, &tokc);
4232 cstr_cat(&cstr, p1);
4233 p2 = get_tok_str(t, &cval);
4234 cstr_cat(&cstr, p2);
4235 cstr_ccat(&cstr, '\0');
4237 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4238 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4239 if (tok == TOK_PPNUM) {
4240 /* if number, then create a number token */
4241 /* NOTE: no need to allocate because
4242 tok_str_add2() does it */
4243 cstr_reset(&tokcstr);
4244 tokcstr = cstr;
4245 cstr_new(&cstr);
4246 tokc.cstr = &tokcstr;
4247 } else {
4248 /* if identifier, we must do a test to
4249 validate we have a correct identifier */
4250 if (t == TOK_PPNUM) {
4251 const char *p;
4252 int c;
4254 p = p2;
4255 for(;;) {
4256 c = *p;
4257 if (c == '\0')
4258 break;
4259 p++;
4260 if (!isnum(c) && !isid(c))
4261 goto error_pasting;
4264 ts = tok_alloc(cstr.data, strlen(cstr.data));
4265 tok = ts->tok; /* modify current token */
4267 } else {
4268 const char *str = cstr.data;
4269 const unsigned char *q;
4271 /* we look for a valid token */
4272 /* XXX: do more extensive checks */
4273 if (!strcmp(str, ">>=")) {
4274 tok = TOK_A_SAR;
4275 } else if (!strcmp(str, "<<=")) {
4276 tok = TOK_A_SHL;
4277 } else if (strlen(str) == 2) {
4278 /* search in two bytes table */
4279 q = tok_two_chars;
4280 for(;;) {
4281 if (!*q)
4282 goto error_pasting;
4283 if (q[0] == str[0] && q[1] == str[1])
4284 break;
4285 q += 3;
4287 tok = q[2];
4288 } else {
4289 error_pasting:
4290 /* NOTE: because get_tok_str use a static buffer,
4291 we must save it */
4292 cstr_reset(&cstr);
4293 p1 = get_tok_str(tok, &tokc);
4294 cstr_cat(&cstr, p1);
4295 cstr_ccat(&cstr, '\0');
4296 p2 = get_tok_str(t, &cval);
4297 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4298 /* cannot merge tokens: just add them separately */
4299 tok_str_add2(&macro_str1, tok, &tokc);
4300 /* XXX: free associated memory ? */
4301 tok = t;
4302 tokc = cval;
4307 tok_str_add2(&macro_str1, tok, &tokc);
4308 next_nomacro();
4309 if (tok == 0)
4310 break;
4312 macro_ptr = (int *)saved_macro_ptr;
4313 cstr_free(&cstr);
4314 tok_str_add(&macro_str1, 0);
4315 return macro_str1.str;
4319 /* do macro substitution of macro_str and add result to
4320 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4321 inside to avoid recursing. */
4322 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4323 const int *macro_str, struct macro_level ** can_read_stream)
4325 Sym *s;
4326 int *macro_str1;
4327 const int *ptr;
4328 int t, ret;
4329 CValue cval;
4330 struct macro_level ml;
4332 /* first scan for '##' operator handling */
4333 ptr = macro_str;
4334 macro_str1 = macro_twosharps(ptr);
4335 if (macro_str1)
4336 ptr = macro_str1;
4337 while (1) {
4338 /* NOTE: ptr == NULL can only happen if tokens are read from
4339 file stream due to a macro function call */
4340 if (ptr == NULL)
4341 break;
4342 TOK_GET(t, ptr, cval);
4343 if (t == 0)
4344 break;
4345 s = define_find(t);
4346 if (s != NULL) {
4347 /* if nested substitution, do nothing */
4348 if (sym_find2(*nested_list, t))
4349 goto no_subst;
4350 ml.p = macro_ptr;
4351 if (can_read_stream)
4352 ml.prev = *can_read_stream, *can_read_stream = &ml;
4353 macro_ptr = (int *)ptr;
4354 tok = t;
4355 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4356 ptr = (int *)macro_ptr;
4357 macro_ptr = ml.p;
4358 if (can_read_stream && *can_read_stream == &ml)
4359 *can_read_stream = ml.prev;
4360 if (ret != 0)
4361 goto no_subst;
4362 } else {
4363 no_subst:
4364 tok_str_add2(tok_str, t, &cval);
4367 if (macro_str1)
4368 tok_str_free(macro_str1);
4371 /* return next token with macro substitution */
4372 static void next(void)
4374 Sym *nested_list, *s;
4375 TokenString str;
4376 struct macro_level *ml;
4378 redo:
4379 next_nomacro();
4380 if (!macro_ptr) {
4381 /* if not reading from macro substituted string, then try
4382 to substitute macros */
4383 if (tok >= TOK_IDENT &&
4384 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4385 s = define_find(tok);
4386 if (s) {
4387 /* we have a macro: we try to substitute */
4388 tok_str_new(&str);
4389 nested_list = NULL;
4390 ml = NULL;
4391 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4392 /* substitution done, NOTE: maybe empty */
4393 tok_str_add(&str, 0);
4394 macro_ptr = str.str;
4395 macro_ptr_allocated = str.str;
4396 goto redo;
4400 } else {
4401 if (tok == 0) {
4402 /* end of macro or end of unget buffer */
4403 if (unget_buffer_enabled) {
4404 macro_ptr = unget_saved_macro_ptr;
4405 unget_buffer_enabled = 0;
4406 } else {
4407 /* end of macro string: free it */
4408 tok_str_free(macro_ptr_allocated);
4409 macro_ptr = NULL;
4411 goto redo;
4415 /* convert preprocessor tokens into C tokens */
4416 if (tok == TOK_PPNUM &&
4417 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4418 parse_number((char *)tokc.cstr->data);
4422 /* push back current token and set current token to 'last_tok'. Only
4423 identifier case handled for labels. */
4424 static inline void unget_tok(int last_tok)
4426 int i, n;
4427 int *q;
4428 unget_saved_macro_ptr = macro_ptr;
4429 unget_buffer_enabled = 1;
4430 q = unget_saved_buffer;
4431 macro_ptr = q;
4432 *q++ = tok;
4433 n = tok_ext_size(tok) - 1;
4434 for(i=0;i<n;i++)
4435 *q++ = tokc.tab[i];
4436 *q = 0; /* end of token string */
4437 tok = last_tok;
4441 void swap(int *p, int *q)
4443 int t;
4444 t = *p;
4445 *p = *q;
4446 *q = t;
4449 void vsetc(CType *type, int r, CValue *vc)
4451 int v;
4453 if (vtop >= vstack + (VSTACK_SIZE - 1))
4454 error("memory full");
4455 /* cannot let cpu flags if other instruction are generated. Also
4456 avoid leaving VT_JMP anywhere except on the top of the stack
4457 because it would complicate the code generator. */
4458 if (vtop >= vstack) {
4459 v = vtop->r & VT_VALMASK;
4460 if (v == VT_CMP || (v & ~1) == VT_JMP)
4461 gv(RC_INT);
4463 vtop++;
4464 vtop->type = *type;
4465 vtop->r = r;
4466 vtop->r2 = VT_CONST;
4467 vtop->c = *vc;
4470 /* push integer constant */
4471 void vpushi(int v)
4473 CValue cval;
4474 cval.i = v;
4475 vsetc(&int_type, VT_CONST, &cval);
4478 /* Return a static symbol pointing to a section */
4479 static Sym *get_sym_ref(CType *type, Section *sec,
4480 unsigned long offset, unsigned long size)
4482 int v;
4483 Sym *sym;
4485 v = anon_sym++;
4486 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4487 sym->type.ref = type->ref;
4488 sym->r = VT_CONST | VT_SYM;
4489 put_extern_sym(sym, sec, offset, size);
4490 return sym;
4493 /* push a reference to a section offset by adding a dummy symbol */
4494 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4496 CValue cval;
4498 cval.ul = 0;
4499 vsetc(type, VT_CONST | VT_SYM, &cval);
4500 vtop->sym = get_sym_ref(type, sec, offset, size);
4503 /* define a new external reference to a symbol 'v' of type 'u' */
4504 static Sym *external_global_sym(int v, CType *type, int r)
4506 Sym *s;
4508 s = sym_find(v);
4509 if (!s) {
4510 /* push forward reference */
4511 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4512 s->type.ref = type->ref;
4513 s->r = r | VT_CONST | VT_SYM;
4515 return s;
4518 /* define a new external reference to a symbol 'v' of type 'u' */
4519 static Sym *external_sym(int v, CType *type, int r)
4521 Sym *s;
4523 s = sym_find(v);
4524 if (!s) {
4525 /* push forward reference */
4526 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4527 s->type.t |= VT_EXTERN;
4528 } else {
4529 if (!is_compatible_types(&s->type, type))
4530 error("incompatible types for redefinition of '%s'",
4531 get_tok_str(v, NULL));
4533 return s;
4536 /* push a reference to global symbol v */
4537 static void vpush_global_sym(CType *type, int v)
4539 Sym *sym;
4540 CValue cval;
4542 sym = external_global_sym(v, type, 0);
4543 cval.ul = 0;
4544 vsetc(type, VT_CONST | VT_SYM, &cval);
4545 vtop->sym = sym;
4548 void vset(CType *type, int r, int v)
4550 CValue cval;
4552 cval.i = v;
4553 vsetc(type, r, &cval);
4556 void vseti(int r, int v)
4558 CType type;
4559 type.t = VT_INT;
4560 vset(&type, r, v);
4563 void vswap(void)
4565 SValue tmp;
4567 tmp = vtop[0];
4568 vtop[0] = vtop[-1];
4569 vtop[-1] = tmp;
4572 void vpushv(SValue *v)
4574 if (vtop >= vstack + (VSTACK_SIZE - 1))
4575 error("memory full");
4576 vtop++;
4577 *vtop = *v;
4580 void vdup(void)
4582 vpushv(vtop);
4585 /* save r to the memory stack, and mark it as being free */
4586 void save_reg(int r)
4588 int l, saved, size, align;
4589 SValue *p, sv;
4590 CType *type;
4592 /* modify all stack values */
4593 saved = 0;
4594 l = 0;
4595 for(p=vstack;p<=vtop;p++) {
4596 if ((p->r & VT_VALMASK) == r ||
4597 (p->r2 & VT_VALMASK) == r) {
4598 /* must save value on stack if not already done */
4599 if (!saved) {
4600 /* NOTE: must reload 'r' because r might be equal to r2 */
4601 r = p->r & VT_VALMASK;
4602 /* store register in the stack */
4603 type = &p->type;
4604 if ((p->r & VT_LVAL) ||
4605 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4606 type = &int_type;
4607 size = type_size(type, &align);
4608 loc = (loc - size) & -align;
4609 sv.type.t = type->t;
4610 sv.r = VT_LOCAL | VT_LVAL;
4611 sv.c.ul = loc;
4612 store(r, &sv);
4613 #ifdef TCC_TARGET_I386
4614 /* x86 specific: need to pop fp register ST0 if saved */
4615 if (r == TREG_ST0) {
4616 o(0xd9dd); /* fstp %st(1) */
4618 #endif
4619 /* special long long case */
4620 if ((type->t & VT_BTYPE) == VT_LLONG) {
4621 sv.c.ul += 4;
4622 store(p->r2, &sv);
4624 l = loc;
4625 saved = 1;
4627 /* mark that stack entry as being saved on the stack */
4628 if (p->r & VT_LVAL) {
4629 /* also clear the bounded flag because the
4630 relocation address of the function was stored in
4631 p->c.ul */
4632 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4633 } else {
4634 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4636 p->r2 = VT_CONST;
4637 p->c.ul = l;
4642 /* find a register of class 'rc2' with at most one reference on stack.
4643 * If none, call get_reg(rc) */
4644 int get_reg_ex(int rc, int rc2)
4646 int r;
4647 SValue *p;
4649 for(r=0;r<NB_REGS;r++) {
4650 if (reg_classes[r] & rc2) {
4651 int n;
4652 n=0;
4653 for(p = vstack; p <= vtop; p++) {
4654 if ((p->r & VT_VALMASK) == r ||
4655 (p->r2 & VT_VALMASK) == r)
4656 n++;
4658 if (n <= 1)
4659 return r;
4662 return get_reg(rc);
4665 /* find a free register of class 'rc'. If none, save one register */
4666 int get_reg(int rc)
4668 int r;
4669 SValue *p;
4671 /* find a free register */
4672 for(r=0;r<NB_REGS;r++) {
4673 if (reg_classes[r] & rc) {
4674 for(p=vstack;p<=vtop;p++) {
4675 if ((p->r & VT_VALMASK) == r ||
4676 (p->r2 & VT_VALMASK) == r)
4677 goto notfound;
4679 return r;
4681 notfound: ;
4684 /* no register left : free the first one on the stack (VERY
4685 IMPORTANT to start from the bottom to ensure that we don't
4686 spill registers used in gen_opi()) */
4687 for(p=vstack;p<=vtop;p++) {
4688 r = p->r & VT_VALMASK;
4689 if (r < VT_CONST && (reg_classes[r] & rc))
4690 goto save_found;
4691 /* also look at second register (if long long) */
4692 r = p->r2 & VT_VALMASK;
4693 if (r < VT_CONST && (reg_classes[r] & rc)) {
4694 save_found:
4695 save_reg(r);
4696 return r;
4699 /* Should never comes here */
4700 return -1;
4703 /* save registers up to (vtop - n) stack entry */
4704 void save_regs(int n)
4706 int r;
4707 SValue *p, *p1;
4708 p1 = vtop - n;
4709 for(p = vstack;p <= p1; p++) {
4710 r = p->r & VT_VALMASK;
4711 if (r < VT_CONST) {
4712 save_reg(r);
4717 /* move register 's' to 'r', and flush previous value of r to memory
4718 if needed */
4719 void move_reg(int r, int s)
4721 SValue sv;
4723 if (r != s) {
4724 save_reg(r);
4725 sv.type.t = VT_INT;
4726 sv.r = s;
4727 sv.c.ul = 0;
4728 load(r, &sv);
4732 /* get address of vtop (vtop MUST BE an lvalue) */
4733 void gaddrof(void)
4735 vtop->r &= ~VT_LVAL;
4736 /* tricky: if saved lvalue, then we can go back to lvalue */
4737 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4738 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4741 #ifdef CONFIG_TCC_BCHECK
4742 /* generate lvalue bound code */
4743 void gbound(void)
4745 int lval_type;
4746 CType type1;
4748 vtop->r &= ~VT_MUSTBOUND;
4749 /* if lvalue, then use checking code before dereferencing */
4750 if (vtop->r & VT_LVAL) {
4751 /* if not VT_BOUNDED value, then make one */
4752 if (!(vtop->r & VT_BOUNDED)) {
4753 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4754 /* must save type because we must set it to int to get pointer */
4755 type1 = vtop->type;
4756 vtop->type.t = VT_INT;
4757 gaddrof();
4758 vpushi(0);
4759 gen_bounded_ptr_add();
4760 vtop->r |= lval_type;
4761 vtop->type = type1;
4763 /* then check for dereferencing */
4764 gen_bounded_ptr_deref();
4767 #endif
4769 /* store vtop a register belonging to class 'rc'. lvalues are
4770 converted to values. Cannot be used if cannot be converted to
4771 register value (such as structures). */
4772 int gv(int rc)
4774 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4775 unsigned long long ll;
4777 /* NOTE: get_reg can modify vstack[] */
4778 if (vtop->type.t & VT_BITFIELD) {
4779 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4780 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4781 /* remove bit field info to avoid loops */
4782 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4783 /* generate shifts */
4784 vpushi(32 - (bit_pos + bit_size));
4785 gen_op(TOK_SHL);
4786 vpushi(32 - bit_size);
4787 /* NOTE: transformed to SHR if unsigned */
4788 gen_op(TOK_SAR);
4789 r = gv(rc);
4790 } else {
4791 if (is_float(vtop->type.t) &&
4792 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4793 Sym *sym;
4794 int *ptr;
4795 unsigned long offset;
4797 /* XXX: unify with initializers handling ? */
4798 /* CPUs usually cannot use float constants, so we store them
4799 generically in data segment */
4800 size = type_size(&vtop->type, &align);
4801 offset = (data_section->data_offset + align - 1) & -align;
4802 data_section->data_offset = offset;
4803 /* XXX: not portable yet */
4804 ptr = section_ptr_add(data_section, size);
4805 size = size >> 2;
4806 for(i=0;i<size;i++)
4807 ptr[i] = vtop->c.tab[i];
4808 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4809 vtop->r |= VT_LVAL | VT_SYM;
4810 vtop->sym = sym;
4811 vtop->c.ul = 0;
4813 #ifdef CONFIG_TCC_BCHECK
4814 if (vtop->r & VT_MUSTBOUND)
4815 gbound();
4816 #endif
4818 r = vtop->r & VT_VALMASK;
4819 /* need to reload if:
4820 - constant
4821 - lvalue (need to dereference pointer)
4822 - already a register, but not in the right class */
4823 if (r >= VT_CONST ||
4824 (vtop->r & VT_LVAL) ||
4825 !(reg_classes[r] & rc) ||
4826 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4827 !(reg_classes[vtop->r2] & rc))) {
4828 r = get_reg(rc);
4829 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4830 /* two register type load : expand to two words
4831 temporarily */
4832 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4833 /* load constant */
4834 ll = vtop->c.ull;
4835 vtop->c.ui = ll; /* first word */
4836 load(r, vtop);
4837 vtop->r = r; /* save register value */
4838 vpushi(ll >> 32); /* second word */
4839 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4840 (vtop->r & VT_LVAL)) {
4841 /* We do not want to modifier the long long
4842 pointer here, so the safest (and less
4843 efficient) is to save all the other registers
4844 in the stack. XXX: totally inefficient. */
4845 save_regs(1);
4846 /* load from memory */
4847 load(r, vtop);
4848 vdup();
4849 vtop[-1].r = r; /* save register value */
4850 /* increment pointer to get second word */
4851 vtop->type.t = VT_INT;
4852 gaddrof();
4853 vpushi(4);
4854 gen_op('+');
4855 vtop->r |= VT_LVAL;
4856 } else {
4857 /* move registers */
4858 load(r, vtop);
4859 vdup();
4860 vtop[-1].r = r; /* save register value */
4861 vtop->r = vtop[-1].r2;
4863 /* allocate second register */
4864 rc2 = RC_INT;
4865 if (rc == RC_IRET)
4866 rc2 = RC_LRET;
4867 r2 = get_reg(rc2);
4868 load(r2, vtop);
4869 vpop();
4870 /* write second register */
4871 vtop->r2 = r2;
4872 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4873 int t1, t;
4874 /* lvalue of scalar type : need to use lvalue type
4875 because of possible cast */
4876 t = vtop->type.t;
4877 t1 = t;
4878 /* compute memory access type */
4879 if (vtop->r & VT_LVAL_BYTE)
4880 t = VT_BYTE;
4881 else if (vtop->r & VT_LVAL_SHORT)
4882 t = VT_SHORT;
4883 if (vtop->r & VT_LVAL_UNSIGNED)
4884 t |= VT_UNSIGNED;
4885 vtop->type.t = t;
4886 load(r, vtop);
4887 /* restore wanted type */
4888 vtop->type.t = t1;
4889 } else {
4890 /* one register type load */
4891 load(r, vtop);
4894 vtop->r = r;
4895 #ifdef TCC_TARGET_C67
4896 /* uses register pairs for doubles */
4897 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4898 vtop->r2 = r+1;
4899 #endif
4901 return r;
4904 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4905 void gv2(int rc1, int rc2)
4907 int v;
4909 /* generate more generic register first. But VT_JMP or VT_CMP
4910 values must be generated first in all cases to avoid possible
4911 reload errors */
4912 v = vtop[0].r & VT_VALMASK;
4913 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4914 vswap();
4915 gv(rc1);
4916 vswap();
4917 gv(rc2);
4918 /* test if reload is needed for first register */
4919 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4920 vswap();
4921 gv(rc1);
4922 vswap();
4924 } else {
4925 gv(rc2);
4926 vswap();
4927 gv(rc1);
4928 vswap();
4929 /* test if reload is needed for first register */
4930 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4931 gv(rc2);
4936 /* expand long long on stack in two int registers */
4937 void lexpand(void)
4939 int u;
4941 u = vtop->type.t & VT_UNSIGNED;
4942 gv(RC_INT);
4943 vdup();
4944 vtop[0].r = vtop[-1].r2;
4945 vtop[0].r2 = VT_CONST;
4946 vtop[-1].r2 = VT_CONST;
4947 vtop[0].type.t = VT_INT | u;
4948 vtop[-1].type.t = VT_INT | u;
4951 #ifdef TCC_TARGET_ARM
4952 /* expand long long on stack */
4953 void lexpand_nr(void)
4955 int u,v;
4957 u = vtop->type.t & VT_UNSIGNED;
4958 vdup();
4959 vtop->r2 = VT_CONST;
4960 vtop->type.t = VT_INT | u;
4961 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4962 if (v == VT_CONST) {
4963 vtop[-1].c.ui = vtop->c.ull;
4964 vtop->c.ui = vtop->c.ull >> 32;
4965 vtop->r = VT_CONST;
4966 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4967 vtop->c.ui += 4;
4968 vtop->r = vtop[-1].r;
4969 } else if (v > VT_CONST) {
4970 vtop--;
4971 lexpand();
4972 } else
4973 vtop->r = vtop[-1].r2;
4974 vtop[-1].r2 = VT_CONST;
4975 vtop[-1].type.t = VT_INT | u;
4977 #endif
4979 /* build a long long from two ints */
4980 void lbuild(int t)
4982 gv2(RC_INT, RC_INT);
4983 vtop[-1].r2 = vtop[0].r;
4984 vtop[-1].type.t = t;
4985 vpop();
4988 /* rotate n first stack elements to the bottom
4989 I1 ... In -> I2 ... In I1 [top is right]
4991 void vrotb(int n)
4993 int i;
4994 SValue tmp;
4996 tmp = vtop[-n + 1];
4997 for(i=-n+1;i!=0;i++)
4998 vtop[i] = vtop[i+1];
4999 vtop[0] = tmp;
5002 /* rotate n first stack elements to the top
5003 I1 ... In -> In I1 ... I(n-1) [top is right]
5005 void vrott(int n)
5007 int i;
5008 SValue tmp;
5010 tmp = vtop[0];
5011 for(i = 0;i < n - 1; i++)
5012 vtop[-i] = vtop[-i - 1];
5013 vtop[-n + 1] = tmp;
5016 #ifdef TCC_TARGET_ARM
5017 /* like vrott but in other direction
5018 In ... I1 -> I(n-1) ... I1 In [top is right]
5020 void vnrott(int n)
5022 int i;
5023 SValue tmp;
5025 tmp = vtop[-n + 1];
5026 for(i = n - 1; i > 0; i--)
5027 vtop[-i] = vtop[-i + 1];
5028 vtop[0] = tmp;
5030 #endif
5032 /* pop stack value */
5033 void vpop(void)
5035 int v;
5036 v = vtop->r & VT_VALMASK;
5037 #ifdef TCC_TARGET_I386
5038 /* for x86, we need to pop the FP stack */
5039 if (v == TREG_ST0 && !nocode_wanted) {
5040 o(0xd9dd); /* fstp %st(1) */
5041 } else
5042 #endif
5043 if (v == VT_JMP || v == VT_JMPI) {
5044 /* need to put correct jump if && or || without test */
5045 gsym(vtop->c.ul);
5047 vtop--;
5050 /* convert stack entry to register and duplicate its value in another
5051 register */
5052 void gv_dup(void)
5054 int rc, t, r, r1;
5055 SValue sv;
5057 t = vtop->type.t;
5058 if ((t & VT_BTYPE) == VT_LLONG) {
5059 lexpand();
5060 gv_dup();
5061 vswap();
5062 vrotb(3);
5063 gv_dup();
5064 vrotb(4);
5065 /* stack: H L L1 H1 */
5066 lbuild(t);
5067 vrotb(3);
5068 vrotb(3);
5069 vswap();
5070 lbuild(t);
5071 vswap();
5072 } else {
5073 /* duplicate value */
5074 rc = RC_INT;
5075 sv.type.t = VT_INT;
5076 if (is_float(t)) {
5077 rc = RC_FLOAT;
5078 sv.type.t = t;
5080 r = gv(rc);
5081 r1 = get_reg(rc);
5082 sv.r = r;
5083 sv.c.ul = 0;
5084 load(r1, &sv); /* move r to r1 */
5085 vdup();
5086 /* duplicates value */
5087 vtop->r = r1;
5091 /* generate CPU independent (unsigned) long long operations */
5092 void gen_opl(int op)
5094 int t, a, b, op1, c, i;
5095 int func;
5096 SValue tmp;
5098 switch(op) {
5099 case '/':
5100 case TOK_PDIV:
5101 func = TOK___divdi3;
5102 goto gen_func;
5103 case TOK_UDIV:
5104 func = TOK___udivdi3;
5105 goto gen_func;
5106 case '%':
5107 func = TOK___moddi3;
5108 goto gen_func;
5109 case TOK_UMOD:
5110 func = TOK___umoddi3;
5111 gen_func:
5112 /* call generic long long function */
5113 vpush_global_sym(&func_old_type, func);
5114 vrott(3);
5115 gfunc_call(2);
5116 vpushi(0);
5117 vtop->r = REG_IRET;
5118 vtop->r2 = REG_LRET;
5119 break;
5120 case '^':
5121 case '&':
5122 case '|':
5123 case '*':
5124 case '+':
5125 case '-':
5126 t = vtop->type.t;
5127 vswap();
5128 lexpand();
5129 vrotb(3);
5130 lexpand();
5131 /* stack: L1 H1 L2 H2 */
5132 tmp = vtop[0];
5133 vtop[0] = vtop[-3];
5134 vtop[-3] = tmp;
5135 tmp = vtop[-2];
5136 vtop[-2] = vtop[-3];
5137 vtop[-3] = tmp;
5138 vswap();
5139 /* stack: H1 H2 L1 L2 */
5140 if (op == '*') {
5141 vpushv(vtop - 1);
5142 vpushv(vtop - 1);
5143 gen_op(TOK_UMULL);
5144 lexpand();
5145 /* stack: H1 H2 L1 L2 ML MH */
5146 for(i=0;i<4;i++)
5147 vrotb(6);
5148 /* stack: ML MH H1 H2 L1 L2 */
5149 tmp = vtop[0];
5150 vtop[0] = vtop[-2];
5151 vtop[-2] = tmp;
5152 /* stack: ML MH H1 L2 H2 L1 */
5153 gen_op('*');
5154 vrotb(3);
5155 vrotb(3);
5156 gen_op('*');
5157 /* stack: ML MH M1 M2 */
5158 gen_op('+');
5159 gen_op('+');
5160 } else if (op == '+' || op == '-') {
5161 /* XXX: add non carry method too (for MIPS or alpha) */
5162 if (op == '+')
5163 op1 = TOK_ADDC1;
5164 else
5165 op1 = TOK_SUBC1;
5166 gen_op(op1);
5167 /* stack: H1 H2 (L1 op L2) */
5168 vrotb(3);
5169 vrotb(3);
5170 gen_op(op1 + 1); /* TOK_xxxC2 */
5171 } else {
5172 gen_op(op);
5173 /* stack: H1 H2 (L1 op L2) */
5174 vrotb(3);
5175 vrotb(3);
5176 /* stack: (L1 op L2) H1 H2 */
5177 gen_op(op);
5178 /* stack: (L1 op L2) (H1 op H2) */
5180 /* stack: L H */
5181 lbuild(t);
5182 break;
5183 case TOK_SAR:
5184 case TOK_SHR:
5185 case TOK_SHL:
5186 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5187 t = vtop[-1].type.t;
5188 vswap();
5189 lexpand();
5190 vrotb(3);
5191 /* stack: L H shift */
5192 c = (int)vtop->c.i;
5193 /* constant: simpler */
5194 /* NOTE: all comments are for SHL. the other cases are
5195 done by swaping words */
5196 vpop();
5197 if (op != TOK_SHL)
5198 vswap();
5199 if (c >= 32) {
5200 /* stack: L H */
5201 vpop();
5202 if (c > 32) {
5203 vpushi(c - 32);
5204 gen_op(op);
5206 if (op != TOK_SAR) {
5207 vpushi(0);
5208 } else {
5209 gv_dup();
5210 vpushi(31);
5211 gen_op(TOK_SAR);
5213 vswap();
5214 } else {
5215 vswap();
5216 gv_dup();
5217 /* stack: H L L */
5218 vpushi(c);
5219 gen_op(op);
5220 vswap();
5221 vpushi(32 - c);
5222 if (op == TOK_SHL)
5223 gen_op(TOK_SHR);
5224 else
5225 gen_op(TOK_SHL);
5226 vrotb(3);
5227 /* stack: L L H */
5228 vpushi(c);
5229 if (op == TOK_SHL)
5230 gen_op(TOK_SHL);
5231 else
5232 gen_op(TOK_SHR);
5233 gen_op('|');
5235 if (op != TOK_SHL)
5236 vswap();
5237 lbuild(t);
5238 } else {
5239 /* XXX: should provide a faster fallback on x86 ? */
5240 switch(op) {
5241 case TOK_SAR:
5242 func = TOK___sardi3;
5243 goto gen_func;
5244 case TOK_SHR:
5245 func = TOK___shrdi3;
5246 goto gen_func;
5247 case TOK_SHL:
5248 func = TOK___shldi3;
5249 goto gen_func;
5252 break;
5253 default:
5254 /* compare operations */
5255 t = vtop->type.t;
5256 vswap();
5257 lexpand();
5258 vrotb(3);
5259 lexpand();
5260 /* stack: L1 H1 L2 H2 */
5261 tmp = vtop[-1];
5262 vtop[-1] = vtop[-2];
5263 vtop[-2] = tmp;
5264 /* stack: L1 L2 H1 H2 */
5265 /* compare high */
5266 op1 = op;
5267 /* when values are equal, we need to compare low words. since
5268 the jump is inverted, we invert the test too. */
5269 if (op1 == TOK_LT)
5270 op1 = TOK_LE;
5271 else if (op1 == TOK_GT)
5272 op1 = TOK_GE;
5273 else if (op1 == TOK_ULT)
5274 op1 = TOK_ULE;
5275 else if (op1 == TOK_UGT)
5276 op1 = TOK_UGE;
5277 a = 0;
5278 b = 0;
5279 gen_op(op1);
5280 if (op1 != TOK_NE) {
5281 a = gtst(1, 0);
5283 if (op != TOK_EQ) {
5284 /* generate non equal test */
5285 /* XXX: NOT PORTABLE yet */
5286 if (a == 0) {
5287 b = gtst(0, 0);
5288 } else {
5289 #if defined(TCC_TARGET_I386)
5290 b = psym(0x850f, 0);
5291 #elif defined(TCC_TARGET_ARM)
5292 b = ind;
5293 o(0x1A000000 | encbranch(ind, 0, 1));
5294 #elif defined(TCC_TARGET_C67)
5295 error("not implemented");
5296 #else
5297 #error not supported
5298 #endif
5301 /* compare low. Always unsigned */
5302 op1 = op;
5303 if (op1 == TOK_LT)
5304 op1 = TOK_ULT;
5305 else if (op1 == TOK_LE)
5306 op1 = TOK_ULE;
5307 else if (op1 == TOK_GT)
5308 op1 = TOK_UGT;
5309 else if (op1 == TOK_GE)
5310 op1 = TOK_UGE;
5311 gen_op(op1);
5312 a = gtst(1, a);
5313 gsym(b);
5314 vseti(VT_JMPI, a);
5315 break;
5319 /* handle integer constant optimizations and various machine
5320 independent opt */
5321 void gen_opic(int op)
5323 int fc, c1, c2, n;
5324 SValue *v1, *v2;
5326 v1 = vtop - 1;
5327 v2 = vtop;
5328 /* currently, we cannot do computations with forward symbols */
5329 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5330 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5331 if (c1 && c2) {
5332 fc = v2->c.i;
5333 switch(op) {
5334 case '+': v1->c.i += fc; break;
5335 case '-': v1->c.i -= fc; break;
5336 case '&': v1->c.i &= fc; break;
5337 case '^': v1->c.i ^= fc; break;
5338 case '|': v1->c.i |= fc; break;
5339 case '*': v1->c.i *= fc; break;
5341 case TOK_PDIV:
5342 case '/':
5343 case '%':
5344 case TOK_UDIV:
5345 case TOK_UMOD:
5346 /* if division by zero, generate explicit division */
5347 if (fc == 0) {
5348 if (const_wanted)
5349 error("division by zero in constant");
5350 goto general_case;
5352 switch(op) {
5353 default: v1->c.i /= fc; break;
5354 case '%': v1->c.i %= fc; break;
5355 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5356 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5358 break;
5359 case TOK_SHL: v1->c.i <<= fc; break;
5360 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5361 case TOK_SAR: v1->c.i >>= fc; break;
5362 /* tests */
5363 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5364 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5365 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5366 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5367 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5368 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5369 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5370 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5371 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5372 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5373 /* logical */
5374 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5375 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5376 default:
5377 goto general_case;
5379 vtop--;
5380 } else {
5381 /* if commutative ops, put c2 as constant */
5382 if (c1 && (op == '+' || op == '&' || op == '^' ||
5383 op == '|' || op == '*')) {
5384 vswap();
5385 swap(&c1, &c2);
5387 fc = vtop->c.i;
5388 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5389 op == TOK_PDIV) &&
5390 fc == 1) ||
5391 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5392 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5393 fc == 0) ||
5394 (op == '&' &&
5395 fc == -1))) {
5396 /* nothing to do */
5397 vtop--;
5398 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5399 /* try to use shifts instead of muls or divs */
5400 if (fc > 0 && (fc & (fc - 1)) == 0) {
5401 n = -1;
5402 while (fc) {
5403 fc >>= 1;
5404 n++;
5406 vtop->c.i = n;
5407 if (op == '*')
5408 op = TOK_SHL;
5409 else if (op == TOK_PDIV)
5410 op = TOK_SAR;
5411 else
5412 op = TOK_SHR;
5414 goto general_case;
5415 } else if (c2 && (op == '+' || op == '-') &&
5416 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5417 (VT_CONST | VT_SYM)) {
5418 /* symbol + constant case */
5419 if (op == '-')
5420 fc = -fc;
5421 vtop--;
5422 vtop->c.i += fc;
5423 } else {
5424 general_case:
5425 if (!nocode_wanted) {
5426 /* call low level op generator */
5427 gen_opi(op);
5428 } else {
5429 vtop--;
5435 /* generate a floating point operation with constant propagation */
5436 void gen_opif(int op)
5438 int c1, c2;
5439 SValue *v1, *v2;
5440 long double f1, f2;
5442 v1 = vtop - 1;
5443 v2 = vtop;
5444 /* currently, we cannot do computations with forward symbols */
5445 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5446 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5447 if (c1 && c2) {
5448 if (v1->type.t == VT_FLOAT) {
5449 f1 = v1->c.f;
5450 f2 = v2->c.f;
5451 } else if (v1->type.t == VT_DOUBLE) {
5452 f1 = v1->c.d;
5453 f2 = v2->c.d;
5454 } else {
5455 f1 = v1->c.ld;
5456 f2 = v2->c.ld;
5459 /* NOTE: we only do constant propagation if finite number (not
5460 NaN or infinity) (ANSI spec) */
5461 if (!ieee_finite(f1) || !ieee_finite(f2))
5462 goto general_case;
5464 switch(op) {
5465 case '+': f1 += f2; break;
5466 case '-': f1 -= f2; break;
5467 case '*': f1 *= f2; break;
5468 case '/':
5469 if (f2 == 0.0) {
5470 if (const_wanted)
5471 error("division by zero in constant");
5472 goto general_case;
5474 f1 /= f2;
5475 break;
5476 /* XXX: also handles tests ? */
5477 default:
5478 goto general_case;
5480 /* XXX: overflow test ? */
5481 if (v1->type.t == VT_FLOAT) {
5482 v1->c.f = f1;
5483 } else if (v1->type.t == VT_DOUBLE) {
5484 v1->c.d = f1;
5485 } else {
5486 v1->c.ld = f1;
5488 vtop--;
5489 } else {
5490 general_case:
5491 if (!nocode_wanted) {
5492 gen_opf(op);
5493 } else {
5494 vtop--;
5499 static int pointed_size(CType *type)
5501 int align;
5502 return type_size(pointed_type(type), &align);
5505 static inline int is_null_pointer(SValue *p)
5507 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5508 return 0;
5509 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5510 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5513 static inline int is_integer_btype(int bt)
5515 return (bt == VT_BYTE || bt == VT_SHORT ||
5516 bt == VT_INT || bt == VT_LLONG);
5519 /* check types for comparison or substraction of pointers */
5520 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5522 CType *type1, *type2, tmp_type1, tmp_type2;
5523 int bt1, bt2;
5525 /* null pointers are accepted for all comparisons as gcc */
5526 if (is_null_pointer(p1) || is_null_pointer(p2))
5527 return;
5528 type1 = &p1->type;
5529 type2 = &p2->type;
5530 bt1 = type1->t & VT_BTYPE;
5531 bt2 = type2->t & VT_BTYPE;
5532 /* accept comparison between pointer and integer with a warning */
5533 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5534 warning("comparison between pointer and integer");
5535 return;
5538 /* both must be pointers or implicit function pointers */
5539 if (bt1 == VT_PTR) {
5540 type1 = pointed_type(type1);
5541 } else if (bt1 != VT_FUNC)
5542 goto invalid_operands;
5544 if (bt2 == VT_PTR) {
5545 type2 = pointed_type(type2);
5546 } else if (bt2 != VT_FUNC) {
5547 invalid_operands:
5548 error("invalid operands to binary %s", get_tok_str(op, NULL));
5550 if ((type1->t & VT_BTYPE) == VT_VOID ||
5551 (type2->t & VT_BTYPE) == VT_VOID)
5552 return;
5553 tmp_type1 = *type1;
5554 tmp_type2 = *type2;
5555 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5556 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5557 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5558 /* gcc-like error if '-' is used */
5559 if (op == '-')
5560 goto invalid_operands;
5561 else
5562 warning("comparison of distinct pointer types lacks a cast");
5566 /* generic gen_op: handles types problems */
5567 void gen_op(int op)
5569 int u, t1, t2, bt1, bt2, t;
5570 CType type1;
5572 t1 = vtop[-1].type.t;
5573 t2 = vtop[0].type.t;
5574 bt1 = t1 & VT_BTYPE;
5575 bt2 = t2 & VT_BTYPE;
5577 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5578 /* at least one operand is a pointer */
5579 /* relationnal op: must be both pointers */
5580 if (op >= TOK_ULT && op <= TOK_GT) {
5581 check_comparison_pointer_types(vtop - 1, vtop, op);
5582 /* pointers are handled are unsigned */
5583 t = VT_INT | VT_UNSIGNED;
5584 goto std_op;
5586 /* if both pointers, then it must be the '-' op */
5587 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5588 if (op != '-')
5589 error("cannot use pointers here");
5590 check_comparison_pointer_types(vtop - 1, vtop, op);
5591 /* XXX: check that types are compatible */
5592 u = pointed_size(&vtop[-1].type);
5593 gen_opic(op);
5594 /* set to integer type */
5595 vtop->type.t = VT_INT;
5596 vpushi(u);
5597 gen_op(TOK_PDIV);
5598 } else {
5599 /* exactly one pointer : must be '+' or '-'. */
5600 if (op != '-' && op != '+')
5601 error("cannot use pointers here");
5602 /* Put pointer as first operand */
5603 if (bt2 == VT_PTR) {
5604 vswap();
5605 swap(&t1, &t2);
5607 type1 = vtop[-1].type;
5608 /* XXX: cast to int ? (long long case) */
5609 vpushi(pointed_size(&vtop[-1].type));
5610 gen_op('*');
5611 #ifdef CONFIG_TCC_BCHECK
5612 /* if evaluating constant expression, no code should be
5613 generated, so no bound check */
5614 if (do_bounds_check && !const_wanted) {
5615 /* if bounded pointers, we generate a special code to
5616 test bounds */
5617 if (op == '-') {
5618 vpushi(0);
5619 vswap();
5620 gen_op('-');
5622 gen_bounded_ptr_add();
5623 } else
5624 #endif
5626 gen_opic(op);
5628 /* put again type if gen_opic() swaped operands */
5629 vtop->type = type1;
5631 } else if (is_float(bt1) || is_float(bt2)) {
5632 /* compute bigger type and do implicit casts */
5633 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5634 t = VT_LDOUBLE;
5635 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5636 t = VT_DOUBLE;
5637 } else {
5638 t = VT_FLOAT;
5640 /* floats can only be used for a few operations */
5641 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5642 (op < TOK_ULT || op > TOK_GT))
5643 error("invalid operands for binary operation");
5644 goto std_op;
5645 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5646 /* cast to biggest op */
5647 t = VT_LLONG;
5648 /* convert to unsigned if it does not fit in a long long */
5649 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5650 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5651 t |= VT_UNSIGNED;
5652 goto std_op;
5653 } else {
5654 /* integer operations */
5655 t = VT_INT;
5656 /* convert to unsigned if it does not fit in an integer */
5657 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5658 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5659 t |= VT_UNSIGNED;
5660 std_op:
5661 /* XXX: currently, some unsigned operations are explicit, so
5662 we modify them here */
5663 if (t & VT_UNSIGNED) {
5664 if (op == TOK_SAR)
5665 op = TOK_SHR;
5666 else if (op == '/')
5667 op = TOK_UDIV;
5668 else if (op == '%')
5669 op = TOK_UMOD;
5670 else if (op == TOK_LT)
5671 op = TOK_ULT;
5672 else if (op == TOK_GT)
5673 op = TOK_UGT;
5674 else if (op == TOK_LE)
5675 op = TOK_ULE;
5676 else if (op == TOK_GE)
5677 op = TOK_UGE;
5679 vswap();
5680 type1.t = t;
5681 gen_cast(&type1);
5682 vswap();
5683 /* special case for shifts and long long: we keep the shift as
5684 an integer */
5685 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5686 type1.t = VT_INT;
5687 gen_cast(&type1);
5688 if (is_float(t))
5689 gen_opif(op);
5690 else if ((t & VT_BTYPE) == VT_LLONG)
5691 gen_opl(op);
5692 else
5693 gen_opic(op);
5694 if (op >= TOK_ULT && op <= TOK_GT) {
5695 /* relationnal op: the result is an int */
5696 vtop->type.t = VT_INT;
5697 } else {
5698 vtop->type.t = t;
5703 /* generic itof for unsigned long long case */
5704 void gen_cvt_itof1(int t)
5706 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5707 (VT_LLONG | VT_UNSIGNED)) {
5709 if (t == VT_FLOAT)
5710 vpush_global_sym(&func_old_type, TOK___ulltof);
5711 else if (t == VT_DOUBLE)
5712 vpush_global_sym(&func_old_type, TOK___ulltod);
5713 else
5714 vpush_global_sym(&func_old_type, TOK___ulltold);
5715 vrott(2);
5716 gfunc_call(1);
5717 vpushi(0);
5718 vtop->r = REG_FRET;
5719 } else {
5720 gen_cvt_itof(t);
5724 /* generic ftoi for unsigned long long case */
5725 void gen_cvt_ftoi1(int t)
5727 int st;
5729 if (t == (VT_LLONG | VT_UNSIGNED)) {
5730 /* not handled natively */
5731 st = vtop->type.t & VT_BTYPE;
5732 if (st == VT_FLOAT)
5733 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5734 else if (st == VT_DOUBLE)
5735 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5736 else
5737 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5738 vrott(2);
5739 gfunc_call(1);
5740 vpushi(0);
5741 vtop->r = REG_IRET;
5742 vtop->r2 = REG_LRET;
5743 } else {
5744 gen_cvt_ftoi(t);
5748 /* force char or short cast */
5749 void force_charshort_cast(int t)
5751 int bits, dbt;
5752 dbt = t & VT_BTYPE;
5753 /* XXX: add optimization if lvalue : just change type and offset */
5754 if (dbt == VT_BYTE)
5755 bits = 8;
5756 else
5757 bits = 16;
5758 if (t & VT_UNSIGNED) {
5759 vpushi((1 << bits) - 1);
5760 gen_op('&');
5761 } else {
5762 bits = 32 - bits;
5763 vpushi(bits);
5764 gen_op(TOK_SHL);
5765 vpushi(bits);
5766 gen_op(TOK_SAR);
5770 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5771 static void gen_cast(CType *type)
5773 int sbt, dbt, sf, df, c;
5775 /* special delayed cast for char/short */
5776 /* XXX: in some cases (multiple cascaded casts), it may still
5777 be incorrect */
5778 if (vtop->r & VT_MUSTCAST) {
5779 vtop->r &= ~VT_MUSTCAST;
5780 force_charshort_cast(vtop->type.t);
5783 /* bitfields first get cast to ints */
5784 if (vtop->type.t & VT_BITFIELD) {
5785 gv(RC_INT);
5788 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5789 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5791 if (sbt != dbt && !nocode_wanted) {
5792 sf = is_float(sbt);
5793 df = is_float(dbt);
5794 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5795 if (sf && df) {
5796 /* convert from fp to fp */
5797 if (c) {
5798 /* constant case: we can do it now */
5799 /* XXX: in ISOC, cannot do it if error in convert */
5800 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5801 vtop->c.f = (float)vtop->c.d;
5802 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5803 vtop->c.f = (float)vtop->c.ld;
5804 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5805 vtop->c.d = (double)vtop->c.f;
5806 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5807 vtop->c.d = (double)vtop->c.ld;
5808 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5809 vtop->c.ld = (long double)vtop->c.f;
5810 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5811 vtop->c.ld = (long double)vtop->c.d;
5812 } else {
5813 /* non constant case: generate code */
5814 gen_cvt_ftof(dbt);
5816 } else if (df) {
5817 /* convert int to fp */
5818 if (c) {
5819 switch(sbt) {
5820 case VT_LLONG | VT_UNSIGNED:
5821 case VT_LLONG:
5822 /* XXX: add const cases for long long */
5823 goto do_itof;
5824 case VT_INT | VT_UNSIGNED:
5825 switch(dbt) {
5826 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5827 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5828 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5830 break;
5831 default:
5832 switch(dbt) {
5833 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5834 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5835 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5837 break;
5839 } else {
5840 do_itof:
5841 #if !defined(TCC_TARGET_ARM)
5842 gen_cvt_itof1(dbt);
5843 #else
5844 gen_cvt_itof(dbt);
5845 #endif
5847 } else if (sf) {
5848 /* convert fp to int */
5849 /* we handle char/short/etc... with generic code */
5850 if (dbt != (VT_INT | VT_UNSIGNED) &&
5851 dbt != (VT_LLONG | VT_UNSIGNED) &&
5852 dbt != VT_LLONG)
5853 dbt = VT_INT;
5854 if (c) {
5855 switch(dbt) {
5856 case VT_LLONG | VT_UNSIGNED:
5857 case VT_LLONG:
5858 /* XXX: add const cases for long long */
5859 goto do_ftoi;
5860 case VT_INT | VT_UNSIGNED:
5861 switch(sbt) {
5862 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5863 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5864 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5866 break;
5867 default:
5868 /* int case */
5869 switch(sbt) {
5870 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5871 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5872 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5874 break;
5876 } else {
5877 do_ftoi:
5878 gen_cvt_ftoi1(dbt);
5880 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5881 /* additional cast for char/short/bool... */
5882 vtop->type.t = dbt;
5883 gen_cast(type);
5885 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5886 if ((sbt & VT_BTYPE) != VT_LLONG) {
5887 /* scalar to long long */
5888 if (c) {
5889 if (sbt == (VT_INT | VT_UNSIGNED))
5890 vtop->c.ll = vtop->c.ui;
5891 else
5892 vtop->c.ll = vtop->c.i;
5893 } else {
5894 /* machine independent conversion */
5895 gv(RC_INT);
5896 /* generate high word */
5897 if (sbt == (VT_INT | VT_UNSIGNED)) {
5898 vpushi(0);
5899 gv(RC_INT);
5900 } else {
5901 gv_dup();
5902 vpushi(31);
5903 gen_op(TOK_SAR);
5905 /* patch second register */
5906 vtop[-1].r2 = vtop->r;
5907 vpop();
5910 } else if (dbt == VT_BOOL) {
5911 /* scalar to bool */
5912 vpushi(0);
5913 gen_op(TOK_NE);
5914 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5915 (dbt & VT_BTYPE) == VT_SHORT) {
5916 force_charshort_cast(dbt);
5917 } else if ((dbt & VT_BTYPE) == VT_INT) {
5918 /* scalar to int */
5919 if (sbt == VT_LLONG) {
5920 /* from long long: just take low order word */
5921 lexpand();
5922 vpop();
5924 /* if lvalue and single word type, nothing to do because
5925 the lvalue already contains the real type size (see
5926 VT_LVAL_xxx constants) */
5929 vtop->type = *type;
5932 /* return type size. Put alignment at 'a' */
5933 static int type_size(CType *type, int *a)
5935 Sym *s;
5936 int bt;
5938 bt = type->t & VT_BTYPE;
5939 if (bt == VT_STRUCT) {
5940 /* struct/union */
5941 s = type->ref;
5942 *a = s->r;
5943 return s->c;
5944 } else if (bt == VT_PTR) {
5945 if (type->t & VT_ARRAY) {
5946 s = type->ref;
5947 return type_size(&s->type, a) * s->c;
5948 } else {
5949 *a = PTR_SIZE;
5950 return PTR_SIZE;
5952 } else if (bt == VT_LDOUBLE) {
5953 *a = LDOUBLE_ALIGN;
5954 return LDOUBLE_SIZE;
5955 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5956 #ifdef TCC_TARGET_I386
5957 *a = 4;
5958 #else
5959 *a = 8;
5960 #endif
5961 return 8;
5962 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5963 *a = 4;
5964 return 4;
5965 } else if (bt == VT_SHORT) {
5966 *a = 2;
5967 return 2;
5968 } else {
5969 /* char, void, function, _Bool */
5970 *a = 1;
5971 return 1;
5975 /* return the pointed type of t */
5976 static inline CType *pointed_type(CType *type)
5978 return &type->ref->type;
5981 /* modify type so that its it is a pointer to type. */
5982 static void mk_pointer(CType *type)
5984 Sym *s;
5985 s = sym_push(SYM_FIELD, type, 0, -1);
5986 type->t = VT_PTR | (type->t & ~VT_TYPE);
5987 type->ref = s;
5990 /* compare function types. OLD functions match any new functions */
5991 static int is_compatible_func(CType *type1, CType *type2)
5993 Sym *s1, *s2;
5995 s1 = type1->ref;
5996 s2 = type2->ref;
5997 if (!is_compatible_types(&s1->type, &s2->type))
5998 return 0;
5999 /* check func_call */
6000 if (s1->r != s2->r)
6001 return 0;
6002 /* XXX: not complete */
6003 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6004 return 1;
6005 if (s1->c != s2->c)
6006 return 0;
6007 while (s1 != NULL) {
6008 if (s2 == NULL)
6009 return 0;
6010 if (!is_compatible_types(&s1->type, &s2->type))
6011 return 0;
6012 s1 = s1->next;
6013 s2 = s2->next;
6015 if (s2)
6016 return 0;
6017 return 1;
6020 /* return true if type1 and type2 are exactly the same (including
6021 qualifiers).
6023 - enums are not checked as gcc __builtin_types_compatible_p ()
6025 static int is_compatible_types(CType *type1, CType *type2)
6027 int bt1, t1, t2;
6029 t1 = type1->t & VT_TYPE;
6030 t2 = type2->t & VT_TYPE;
6031 /* XXX: bitfields ? */
6032 if (t1 != t2)
6033 return 0;
6034 /* test more complicated cases */
6035 bt1 = t1 & VT_BTYPE;
6036 if (bt1 == VT_PTR) {
6037 type1 = pointed_type(type1);
6038 type2 = pointed_type(type2);
6039 return is_compatible_types(type1, type2);
6040 } else if (bt1 == VT_STRUCT) {
6041 return (type1->ref == type2->ref);
6042 } else if (bt1 == VT_FUNC) {
6043 return is_compatible_func(type1, type2);
6044 } else {
6045 return 1;
6049 /* print a type. If 'varstr' is not NULL, then the variable is also
6050 printed in the type */
6051 /* XXX: union */
6052 /* XXX: add array and function pointers */
6053 void type_to_str(char *buf, int buf_size,
6054 CType *type, const char *varstr)
6056 int bt, v, t;
6057 Sym *s, *sa;
6058 char buf1[256];
6059 const char *tstr;
6061 t = type->t & VT_TYPE;
6062 bt = t & VT_BTYPE;
6063 buf[0] = '\0';
6064 if (t & VT_CONSTANT)
6065 pstrcat(buf, buf_size, "const ");
6066 if (t & VT_VOLATILE)
6067 pstrcat(buf, buf_size, "volatile ");
6068 if (t & VT_UNSIGNED)
6069 pstrcat(buf, buf_size, "unsigned ");
6070 switch(bt) {
6071 case VT_VOID:
6072 tstr = "void";
6073 goto add_tstr;
6074 case VT_BOOL:
6075 tstr = "_Bool";
6076 goto add_tstr;
6077 case VT_BYTE:
6078 tstr = "char";
6079 goto add_tstr;
6080 case VT_SHORT:
6081 tstr = "short";
6082 goto add_tstr;
6083 case VT_INT:
6084 tstr = "int";
6085 goto add_tstr;
6086 case VT_LONG:
6087 tstr = "long";
6088 goto add_tstr;
6089 case VT_LLONG:
6090 tstr = "long long";
6091 goto add_tstr;
6092 case VT_FLOAT:
6093 tstr = "float";
6094 goto add_tstr;
6095 case VT_DOUBLE:
6096 tstr = "double";
6097 goto add_tstr;
6098 case VT_LDOUBLE:
6099 tstr = "long double";
6100 add_tstr:
6101 pstrcat(buf, buf_size, tstr);
6102 break;
6103 case VT_ENUM:
6104 case VT_STRUCT:
6105 if (bt == VT_STRUCT)
6106 tstr = "struct ";
6107 else
6108 tstr = "enum ";
6109 pstrcat(buf, buf_size, tstr);
6110 v = type->ref->v & ~SYM_STRUCT;
6111 if (v >= SYM_FIRST_ANOM)
6112 pstrcat(buf, buf_size, "<anonymous>");
6113 else
6114 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6115 break;
6116 case VT_FUNC:
6117 s = type->ref;
6118 type_to_str(buf, buf_size, &s->type, varstr);
6119 pstrcat(buf, buf_size, "(");
6120 sa = s->next;
6121 while (sa != NULL) {
6122 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6123 pstrcat(buf, buf_size, buf1);
6124 sa = sa->next;
6125 if (sa)
6126 pstrcat(buf, buf_size, ", ");
6128 pstrcat(buf, buf_size, ")");
6129 goto no_var;
6130 case VT_PTR:
6131 s = type->ref;
6132 pstrcpy(buf1, sizeof(buf1), "*");
6133 if (varstr)
6134 pstrcat(buf1, sizeof(buf1), varstr);
6135 type_to_str(buf, buf_size, &s->type, buf1);
6136 goto no_var;
6138 if (varstr) {
6139 pstrcat(buf, buf_size, " ");
6140 pstrcat(buf, buf_size, varstr);
6142 no_var: ;
6145 /* verify type compatibility to store vtop in 'dt' type, and generate
6146 casts if needed. */
6147 static void gen_assign_cast(CType *dt)
6149 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6150 char buf1[256], buf2[256];
6151 int dbt, sbt;
6153 st = &vtop->type; /* source type */
6154 dbt = dt->t & VT_BTYPE;
6155 sbt = st->t & VT_BTYPE;
6156 if (dt->t & VT_CONSTANT)
6157 warning("assignment of read-only location");
6158 switch(dbt) {
6159 case VT_PTR:
6160 /* special cases for pointers */
6161 /* '0' can also be a pointer */
6162 if (is_null_pointer(vtop))
6163 goto type_ok;
6164 /* accept implicit pointer to integer cast with warning */
6165 if (is_integer_btype(sbt)) {
6166 warning("assignment makes pointer from integer without a cast");
6167 goto type_ok;
6169 type1 = pointed_type(dt);
6170 /* a function is implicitely a function pointer */
6171 if (sbt == VT_FUNC) {
6172 if ((type1->t & VT_BTYPE) != VT_VOID &&
6173 !is_compatible_types(pointed_type(dt), st))
6174 goto error;
6175 else
6176 goto type_ok;
6178 if (sbt != VT_PTR)
6179 goto error;
6180 type2 = pointed_type(st);
6181 if ((type1->t & VT_BTYPE) == VT_VOID ||
6182 (type2->t & VT_BTYPE) == VT_VOID) {
6183 /* void * can match anything */
6184 } else {
6185 /* exact type match, except for unsigned */
6186 tmp_type1 = *type1;
6187 tmp_type2 = *type2;
6188 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6189 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6190 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6191 goto error;
6193 /* check const and volatile */
6194 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6195 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6196 warning("assignment discards qualifiers from pointer target type");
6197 break;
6198 case VT_BYTE:
6199 case VT_SHORT:
6200 case VT_INT:
6201 case VT_LLONG:
6202 if (sbt == VT_PTR || sbt == VT_FUNC) {
6203 warning("assignment makes integer from pointer without a cast");
6205 /* XXX: more tests */
6206 break;
6207 case VT_STRUCT:
6208 tmp_type1 = *dt;
6209 tmp_type2 = *st;
6210 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6211 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6212 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6213 error:
6214 type_to_str(buf1, sizeof(buf1), st, NULL);
6215 type_to_str(buf2, sizeof(buf2), dt, NULL);
6216 error("cannot cast '%s' to '%s'", buf1, buf2);
6218 break;
6220 type_ok:
6221 gen_cast(dt);
6224 /* store vtop in lvalue pushed on stack */
6225 void vstore(void)
6227 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6229 ft = vtop[-1].type.t;
6230 sbt = vtop->type.t & VT_BTYPE;
6231 dbt = ft & VT_BTYPE;
6232 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6233 (sbt == VT_INT && dbt == VT_SHORT)) {
6234 /* optimize char/short casts */
6235 delayed_cast = VT_MUSTCAST;
6236 vtop->type.t = ft & VT_TYPE;
6237 /* XXX: factorize */
6238 if (ft & VT_CONSTANT)
6239 warning("assignment of read-only location");
6240 } else {
6241 delayed_cast = 0;
6242 if (!(ft & VT_BITFIELD))
6243 gen_assign_cast(&vtop[-1].type);
6246 if (sbt == VT_STRUCT) {
6247 /* if structure, only generate pointer */
6248 /* structure assignment : generate memcpy */
6249 /* XXX: optimize if small size */
6250 if (!nocode_wanted) {
6251 size = type_size(&vtop->type, &align);
6253 vpush_global_sym(&func_old_type, TOK_memcpy);
6255 /* destination */
6256 vpushv(vtop - 2);
6257 vtop->type.t = VT_INT;
6258 gaddrof();
6259 /* source */
6260 vpushv(vtop - 2);
6261 vtop->type.t = VT_INT;
6262 gaddrof();
6263 /* type size */
6264 vpushi(size);
6265 gfunc_call(3);
6267 vswap();
6268 vpop();
6269 } else {
6270 vswap();
6271 vpop();
6273 /* leave source on stack */
6274 } else if (ft & VT_BITFIELD) {
6275 /* bitfield store handling */
6276 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6277 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6278 /* remove bit field info to avoid loops */
6279 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6281 /* duplicate destination */
6282 vdup();
6283 vtop[-1] = vtop[-2];
6285 /* mask and shift source */
6286 vpushi((1 << bit_size) - 1);
6287 gen_op('&');
6288 vpushi(bit_pos);
6289 gen_op(TOK_SHL);
6290 /* load destination, mask and or with source */
6291 vswap();
6292 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6293 gen_op('&');
6294 gen_op('|');
6295 /* store result */
6296 vstore();
6297 } else {
6298 #ifdef CONFIG_TCC_BCHECK
6299 /* bound check case */
6300 if (vtop[-1].r & VT_MUSTBOUND) {
6301 vswap();
6302 gbound();
6303 vswap();
6305 #endif
6306 if (!nocode_wanted) {
6307 rc = RC_INT;
6308 if (is_float(ft))
6309 rc = RC_FLOAT;
6310 r = gv(rc); /* generate value */
6311 /* if lvalue was saved on stack, must read it */
6312 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6313 SValue sv;
6314 t = get_reg(RC_INT);
6315 sv.type.t = VT_INT;
6316 sv.r = VT_LOCAL | VT_LVAL;
6317 sv.c.ul = vtop[-1].c.ul;
6318 load(t, &sv);
6319 vtop[-1].r = t | VT_LVAL;
6321 store(r, vtop - 1);
6322 /* two word case handling : store second register at word + 4 */
6323 if ((ft & VT_BTYPE) == VT_LLONG) {
6324 vswap();
6325 /* convert to int to increment easily */
6326 vtop->type.t = VT_INT;
6327 gaddrof();
6328 vpushi(4);
6329 gen_op('+');
6330 vtop->r |= VT_LVAL;
6331 vswap();
6332 /* XXX: it works because r2 is spilled last ! */
6333 store(vtop->r2, vtop - 1);
6336 vswap();
6337 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6338 vtop->r |= delayed_cast;
6342 /* post defines POST/PRE add. c is the token ++ or -- */
6343 void inc(int post, int c)
6345 test_lvalue();
6346 vdup(); /* save lvalue */
6347 if (post) {
6348 gv_dup(); /* duplicate value */
6349 vrotb(3);
6350 vrotb(3);
6352 /* add constant */
6353 vpushi(c - TOK_MID);
6354 gen_op('+');
6355 vstore(); /* store value */
6356 if (post)
6357 vpop(); /* if post op, return saved value */
6360 /* Parse GNUC __attribute__ extension. Currently, the following
6361 extensions are recognized:
6362 - aligned(n) : set data/function alignment.
6363 - packed : force data alignment to 1
6364 - section(x) : generate data/code in this section.
6365 - unused : currently ignored, but may be used someday.
6366 - regparm(n) : pass function parameters in registers (i386 only)
6368 static void parse_attribute(AttributeDef *ad)
6370 int t, n;
6372 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6373 next();
6374 skip('(');
6375 skip('(');
6376 while (tok != ')') {
6377 if (tok < TOK_IDENT)
6378 expect("attribute name");
6379 t = tok;
6380 next();
6381 switch(t) {
6382 case TOK_SECTION1:
6383 case TOK_SECTION2:
6384 skip('(');
6385 if (tok != TOK_STR)
6386 expect("section name");
6387 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6388 next();
6389 skip(')');
6390 break;
6391 case TOK_ALIGNED1:
6392 case TOK_ALIGNED2:
6393 if (tok == '(') {
6394 next();
6395 n = expr_const();
6396 if (n <= 0 || (n & (n - 1)) != 0)
6397 error("alignment must be a positive power of two");
6398 skip(')');
6399 } else {
6400 n = MAX_ALIGN;
6402 ad->aligned = n;
6403 break;
6404 case TOK_PACKED1:
6405 case TOK_PACKED2:
6406 ad->packed = 1;
6407 break;
6408 case TOK_UNUSED1:
6409 case TOK_UNUSED2:
6410 /* currently, no need to handle it because tcc does not
6411 track unused objects */
6412 break;
6413 case TOK_NORETURN1:
6414 case TOK_NORETURN2:
6415 /* currently, no need to handle it because tcc does not
6416 track unused objects */
6417 break;
6418 case TOK_CDECL1:
6419 case TOK_CDECL2:
6420 case TOK_CDECL3:
6421 ad->func_call = FUNC_CDECL;
6422 break;
6423 case TOK_STDCALL1:
6424 case TOK_STDCALL2:
6425 case TOK_STDCALL3:
6426 ad->func_call = FUNC_STDCALL;
6427 break;
6428 #ifdef TCC_TARGET_I386
6429 case TOK_REGPARM1:
6430 case TOK_REGPARM2:
6431 skip('(');
6432 n = expr_const();
6433 if (n > 3)
6434 n = 3;
6435 else if (n < 0)
6436 n = 0;
6437 if (n > 0)
6438 ad->func_call = FUNC_FASTCALL1 + n - 1;
6439 skip(')');
6440 break;
6441 case TOK_FASTCALL1:
6442 case TOK_FASTCALL2:
6443 case TOK_FASTCALL3:
6444 ad->func_call = FUNC_FASTCALLW;
6445 break;
6446 #endif
6447 case TOK_DLLEXPORT:
6448 ad->dllexport = 1;
6449 break;
6450 default:
6451 if (tcc_state->warn_unsupported)
6452 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6453 /* skip parameters */
6454 /* XXX: skip parenthesis too */
6455 if (tok == '(') {
6456 next();
6457 while (tok != ')' && tok != -1)
6458 next();
6459 next();
6461 break;
6463 if (tok != ',')
6464 break;
6465 next();
6467 skip(')');
6468 skip(')');
6472 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6473 static void struct_decl(CType *type, int u)
6475 int a, v, size, align, maxalign, c, offset;
6476 int bit_size, bit_pos, bsize, bt, lbit_pos;
6477 Sym *s, *ss, *ass, **ps;
6478 AttributeDef ad;
6479 CType type1, btype;
6481 a = tok; /* save decl type */
6482 next();
6483 if (tok != '{') {
6484 v = tok;
6485 next();
6486 /* struct already defined ? return it */
6487 if (v < TOK_IDENT)
6488 expect("struct/union/enum name");
6489 s = struct_find(v);
6490 if (s) {
6491 if (s->type.t != a)
6492 error("invalid type");
6493 goto do_decl;
6495 } else {
6496 v = anon_sym++;
6498 type1.t = a;
6499 /* we put an undefined size for struct/union */
6500 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6501 s->r = 0; /* default alignment is zero as gcc */
6502 /* put struct/union/enum name in type */
6503 do_decl:
6504 type->t = u;
6505 type->ref = s;
6507 if (tok == '{') {
6508 next();
6509 if (s->c != -1)
6510 error("struct/union/enum already defined");
6511 /* cannot be empty */
6512 c = 0;
6513 /* non empty enums are not allowed */
6514 if (a == TOK_ENUM) {
6515 for(;;) {
6516 v = tok;
6517 if (v < TOK_UIDENT)
6518 expect("identifier");
6519 next();
6520 if (tok == '=') {
6521 next();
6522 c = expr_const();
6524 /* enum symbols have static storage */
6525 ss = sym_push(v, &int_type, VT_CONST, c);
6526 ss->type.t |= VT_STATIC;
6527 if (tok != ',')
6528 break;
6529 next();
6530 c++;
6531 /* NOTE: we accept a trailing comma */
6532 if (tok == '}')
6533 break;
6535 skip('}');
6536 } else {
6537 maxalign = 1;
6538 ps = &s->next;
6539 bit_pos = 0;
6540 offset = 0;
6541 while (tok != '}') {
6542 parse_btype(&btype, &ad);
6543 while (1) {
6544 bit_size = -1;
6545 v = 0;
6546 type1 = btype;
6547 if (tok != ':') {
6548 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6549 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6550 expect("identifier");
6551 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6552 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6553 error("invalid type for '%s'",
6554 get_tok_str(v, NULL));
6556 if (tok == ':') {
6557 next();
6558 bit_size = expr_const();
6559 /* XXX: handle v = 0 case for messages */
6560 if (bit_size < 0)
6561 error("negative width in bit-field '%s'",
6562 get_tok_str(v, NULL));
6563 if (v && bit_size == 0)
6564 error("zero width for bit-field '%s'",
6565 get_tok_str(v, NULL));
6567 size = type_size(&type1, &align);
6568 if (ad.aligned) {
6569 if (align < ad.aligned)
6570 align = ad.aligned;
6571 } else if (ad.packed) {
6572 align = 1;
6573 } else if (*tcc_state->pack_stack_ptr) {
6574 if (align > *tcc_state->pack_stack_ptr)
6575 align = *tcc_state->pack_stack_ptr;
6577 lbit_pos = 0;
6578 if (bit_size >= 0) {
6579 bt = type1.t & VT_BTYPE;
6580 if (bt != VT_INT &&
6581 bt != VT_BYTE &&
6582 bt != VT_SHORT &&
6583 bt != VT_BOOL &&
6584 bt != VT_ENUM)
6585 error("bitfields must have scalar type");
6586 bsize = size * 8;
6587 if (bit_size > bsize) {
6588 error("width of '%s' exceeds its type",
6589 get_tok_str(v, NULL));
6590 } else if (bit_size == bsize) {
6591 /* no need for bit fields */
6592 bit_pos = 0;
6593 } else if (bit_size == 0) {
6594 /* XXX: what to do if only padding in a
6595 structure ? */
6596 /* zero size: means to pad */
6597 if (bit_pos > 0)
6598 bit_pos = bsize;
6599 } else {
6600 /* we do not have enough room ? */
6601 if ((bit_pos + bit_size) > bsize)
6602 bit_pos = 0;
6603 lbit_pos = bit_pos;
6604 /* XXX: handle LSB first */
6605 type1.t |= VT_BITFIELD |
6606 (bit_pos << VT_STRUCT_SHIFT) |
6607 (bit_size << (VT_STRUCT_SHIFT + 6));
6608 bit_pos += bit_size;
6610 } else {
6611 bit_pos = 0;
6613 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
6614 /* add new memory data only if starting
6615 bit field */
6616 if (lbit_pos == 0) {
6617 if (a == TOK_STRUCT) {
6618 c = (c + align - 1) & -align;
6619 offset = c;
6620 c += size;
6621 } else {
6622 offset = 0;
6623 if (size > c)
6624 c = size;
6626 if (align > maxalign)
6627 maxalign = align;
6629 #if 0
6630 printf("add field %s offset=%d",
6631 get_tok_str(v, NULL), offset);
6632 if (type1.t & VT_BITFIELD) {
6633 printf(" pos=%d size=%d",
6634 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6635 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6637 printf("\n");
6638 #endif
6640 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
6641 ass = type1.ref;
6642 while ((ass = ass->next) != NULL) {
6643 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
6644 *ps = ss;
6645 ps = &ss->next;
6647 } else if (v) {
6648 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6649 *ps = ss;
6650 ps = &ss->next;
6652 if (tok == ';' || tok == TOK_EOF)
6653 break;
6654 skip(',');
6656 skip(';');
6658 skip('}');
6659 /* store size and alignment */
6660 s->c = (c + maxalign - 1) & -maxalign;
6661 s->r = maxalign;
6666 /* return 0 if no type declaration. otherwise, return the basic type
6667 and skip it.
6669 static int parse_btype(CType *type, AttributeDef *ad)
6671 int t, u, type_found, typespec_found;
6672 Sym *s;
6673 CType type1;
6675 memset(ad, 0, sizeof(AttributeDef));
6676 type_found = 0;
6677 typespec_found = 0;
6678 t = 0;
6679 while(1) {
6680 switch(tok) {
6681 case TOK_EXTENSION:
6682 /* currently, we really ignore extension */
6683 next();
6684 continue;
6686 /* basic types */
6687 case TOK_CHAR:
6688 u = VT_BYTE;
6689 basic_type:
6690 next();
6691 basic_type1:
6692 if ((t & VT_BTYPE) != 0)
6693 error("too many basic types");
6694 t |= u;
6695 typespec_found = 1;
6696 break;
6697 case TOK_VOID:
6698 u = VT_VOID;
6699 goto basic_type;
6700 case TOK_SHORT:
6701 u = VT_SHORT;
6702 goto basic_type;
6703 case TOK_INT:
6704 next();
6705 typespec_found = 1;
6706 break;
6707 case TOK_LONG:
6708 next();
6709 if ((t & VT_BTYPE) == VT_DOUBLE) {
6710 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6711 } else if ((t & VT_BTYPE) == VT_LONG) {
6712 t = (t & ~VT_BTYPE) | VT_LLONG;
6713 } else {
6714 u = VT_LONG;
6715 goto basic_type1;
6717 break;
6718 case TOK_BOOL:
6719 u = VT_BOOL;
6720 goto basic_type;
6721 case TOK_FLOAT:
6722 u = VT_FLOAT;
6723 goto basic_type;
6724 case TOK_DOUBLE:
6725 next();
6726 if ((t & VT_BTYPE) == VT_LONG) {
6727 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6728 } else {
6729 u = VT_DOUBLE;
6730 goto basic_type1;
6732 break;
6733 case TOK_ENUM:
6734 struct_decl(&type1, VT_ENUM);
6735 basic_type2:
6736 u = type1.t;
6737 type->ref = type1.ref;
6738 goto basic_type1;
6739 case TOK_STRUCT:
6740 case TOK_UNION:
6741 struct_decl(&type1, VT_STRUCT);
6742 goto basic_type2;
6744 /* type modifiers */
6745 case TOK_CONST1:
6746 case TOK_CONST2:
6747 case TOK_CONST3:
6748 t |= VT_CONSTANT;
6749 next();
6750 break;
6751 case TOK_VOLATILE1:
6752 case TOK_VOLATILE2:
6753 case TOK_VOLATILE3:
6754 t |= VT_VOLATILE;
6755 next();
6756 break;
6757 case TOK_SIGNED1:
6758 case TOK_SIGNED2:
6759 case TOK_SIGNED3:
6760 typespec_found = 1;
6761 t |= VT_SIGNED;
6762 next();
6763 break;
6764 case TOK_REGISTER:
6765 case TOK_AUTO:
6766 case TOK_RESTRICT1:
6767 case TOK_RESTRICT2:
6768 case TOK_RESTRICT3:
6769 next();
6770 break;
6771 case TOK_UNSIGNED:
6772 t |= VT_UNSIGNED;
6773 next();
6774 typespec_found = 1;
6775 break;
6777 /* storage */
6778 case TOK_EXTERN:
6779 t |= VT_EXTERN;
6780 next();
6781 break;
6782 case TOK_STATIC:
6783 t |= VT_STATIC;
6784 next();
6785 break;
6786 case TOK_TYPEDEF:
6787 t |= VT_TYPEDEF;
6788 next();
6789 break;
6790 case TOK_INLINE1:
6791 case TOK_INLINE2:
6792 case TOK_INLINE3:
6793 t |= VT_INLINE;
6794 next();
6795 break;
6797 /* GNUC attribute */
6798 case TOK_ATTRIBUTE1:
6799 case TOK_ATTRIBUTE2:
6800 parse_attribute(ad);
6801 break;
6802 /* GNUC typeof */
6803 case TOK_TYPEOF1:
6804 case TOK_TYPEOF2:
6805 case TOK_TYPEOF3:
6806 next();
6807 parse_expr_type(&type1);
6808 goto basic_type2;
6809 default:
6810 if (typespec_found)
6811 goto the_end;
6812 s = sym_find(tok);
6813 if (!s || !(s->type.t & VT_TYPEDEF))
6814 goto the_end;
6815 t |= (s->type.t & ~VT_TYPEDEF);
6816 type->ref = s->type.ref;
6817 next();
6818 break;
6820 type_found = 1;
6822 the_end:
6823 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6824 error("signed and unsigned modifier");
6825 if (tcc_state->char_is_unsigned) {
6826 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6827 t |= VT_UNSIGNED;
6829 t &= ~VT_SIGNED;
6831 /* long is never used as type */
6832 if ((t & VT_BTYPE) == VT_LONG)
6833 t = (t & ~VT_BTYPE) | VT_INT;
6834 type->t = t;
6835 return type_found;
6838 /* convert a function parameter type (array to pointer and function to
6839 function pointer) */
6840 static inline void convert_parameter_type(CType *pt)
6842 /* remove const and volatile qualifiers (XXX: const could be used
6843 to indicate a const function parameter */
6844 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6845 /* array must be transformed to pointer according to ANSI C */
6846 pt->t &= ~VT_ARRAY;
6847 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6848 mk_pointer(pt);
6852 static void post_type(CType *type, AttributeDef *ad)
6854 int n, l, t1;
6855 Sym **plast, *s, *first;
6856 AttributeDef ad1;
6857 CType pt;
6859 if (tok == '(') {
6860 /* function declaration */
6861 next();
6862 l = 0;
6863 first = NULL;
6864 plast = &first;
6865 if (tok != ')') {
6866 for(;;) {
6867 /* read param name and compute offset */
6868 if (l != FUNC_OLD) {
6869 if (!parse_btype(&pt, &ad1)) {
6870 if (l) {
6871 error("invalid type");
6872 } else {
6873 l = FUNC_OLD;
6874 goto old_proto;
6877 l = FUNC_NEW;
6878 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6879 break;
6880 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6881 if ((pt.t & VT_BTYPE) == VT_VOID)
6882 error("parameter declared as void");
6883 } else {
6884 old_proto:
6885 n = tok;
6886 if (n < TOK_UIDENT)
6887 expect("identifier");
6888 pt.t = VT_INT;
6889 next();
6891 convert_parameter_type(&pt);
6892 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6893 *plast = s;
6894 plast = &s->next;
6895 if (tok == ')')
6896 break;
6897 skip(',');
6898 if (l == FUNC_NEW && tok == TOK_DOTS) {
6899 l = FUNC_ELLIPSIS;
6900 next();
6901 break;
6905 /* if no parameters, then old type prototype */
6906 if (l == 0)
6907 l = FUNC_OLD;
6908 skip(')');
6909 t1 = type->t & VT_STORAGE;
6910 /* NOTE: const is ignored in returned type as it has a special
6911 meaning in gcc / C++ */
6912 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6913 post_type(type, ad);
6914 /* we push a anonymous symbol which will contain the function prototype */
6915 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6916 s->next = first;
6917 type->t = t1 | VT_FUNC;
6918 type->ref = s;
6919 } else if (tok == '[') {
6920 /* array definition */
6921 next();
6922 n = -1;
6923 if (tok != ']') {
6924 n = expr_const();
6925 if (n < 0)
6926 error("invalid array size");
6928 skip(']');
6929 /* parse next post type */
6930 t1 = type->t & VT_STORAGE;
6931 type->t &= ~VT_STORAGE;
6932 post_type(type, ad);
6934 /* we push a anonymous symbol which will contain the array
6935 element type */
6936 s = sym_push(SYM_FIELD, type, 0, n);
6937 type->t = t1 | VT_ARRAY | VT_PTR;
6938 type->ref = s;
6942 /* Parse a type declaration (except basic type), and return the type
6943 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6944 expected. 'type' should contain the basic type. 'ad' is the
6945 attribute definition of the basic type. It can be modified by
6946 type_decl().
6948 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6950 Sym *s;
6951 CType type1, *type2;
6952 int qualifiers;
6954 while (tok == '*') {
6955 qualifiers = 0;
6956 redo:
6957 next();
6958 switch(tok) {
6959 case TOK_CONST1:
6960 case TOK_CONST2:
6961 case TOK_CONST3:
6962 qualifiers |= VT_CONSTANT;
6963 goto redo;
6964 case TOK_VOLATILE1:
6965 case TOK_VOLATILE2:
6966 case TOK_VOLATILE3:
6967 qualifiers |= VT_VOLATILE;
6968 goto redo;
6969 case TOK_RESTRICT1:
6970 case TOK_RESTRICT2:
6971 case TOK_RESTRICT3:
6972 goto redo;
6974 mk_pointer(type);
6975 type->t |= qualifiers;
6978 /* XXX: clarify attribute handling */
6979 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6980 parse_attribute(ad);
6982 /* recursive type */
6983 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6984 type1.t = 0; /* XXX: same as int */
6985 if (tok == '(') {
6986 next();
6987 /* XXX: this is not correct to modify 'ad' at this point, but
6988 the syntax is not clear */
6989 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6990 parse_attribute(ad);
6991 type_decl(&type1, ad, v, td);
6992 skip(')');
6993 } else {
6994 /* type identifier */
6995 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6996 *v = tok;
6997 next();
6998 } else {
6999 if (!(td & TYPE_ABSTRACT))
7000 expect("identifier");
7001 *v = 0;
7004 post_type(type, ad);
7005 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7006 parse_attribute(ad);
7007 if (!type1.t)
7008 return;
7009 /* append type at the end of type1 */
7010 type2 = &type1;
7011 for(;;) {
7012 s = type2->ref;
7013 type2 = &s->type;
7014 if (!type2->t) {
7015 *type2 = *type;
7016 break;
7019 *type = type1;
7022 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7023 static int lvalue_type(int t)
7025 int bt, r;
7026 r = VT_LVAL;
7027 bt = t & VT_BTYPE;
7028 if (bt == VT_BYTE || bt == VT_BOOL)
7029 r |= VT_LVAL_BYTE;
7030 else if (bt == VT_SHORT)
7031 r |= VT_LVAL_SHORT;
7032 else
7033 return r;
7034 if (t & VT_UNSIGNED)
7035 r |= VT_LVAL_UNSIGNED;
7036 return r;
7039 /* indirection with full error checking and bound check */
7040 static void indir(void)
7042 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7043 expect("pointer");
7044 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7045 gv(RC_INT);
7046 vtop->type = *pointed_type(&vtop->type);
7047 /* an array is never an lvalue */
7048 if (!(vtop->type.t & VT_ARRAY)) {
7049 vtop->r |= lvalue_type(vtop->type.t);
7050 /* if bound checking, the referenced pointer must be checked */
7051 if (do_bounds_check)
7052 vtop->r |= VT_MUSTBOUND;
7056 /* pass a parameter to a function and do type checking and casting */
7057 static void gfunc_param_typed(Sym *func, Sym *arg)
7059 int func_type;
7060 CType type;
7062 func_type = func->c;
7063 if (func_type == FUNC_OLD ||
7064 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7065 /* default casting : only need to convert float to double */
7066 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7067 type.t = VT_DOUBLE;
7068 gen_cast(&type);
7070 } else if (arg == NULL) {
7071 error("too many arguments to function");
7072 } else {
7073 type = arg->type;
7074 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7075 gen_assign_cast(&type);
7079 /* parse an expression of the form '(type)' or '(expr)' and return its
7080 type */
7081 static void parse_expr_type(CType *type)
7083 int n;
7084 AttributeDef ad;
7086 skip('(');
7087 if (parse_btype(type, &ad)) {
7088 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7089 } else {
7090 expr_type(type);
7092 skip(')');
7095 static void parse_type(CType *type)
7097 AttributeDef ad;
7098 int n;
7100 if (!parse_btype(type, &ad)) {
7101 expect("type");
7103 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7106 static void vpush_tokc(int t)
7108 CType type;
7109 type.t = t;
7110 vsetc(&type, VT_CONST, &tokc);
7113 static void unary(void)
7115 int n, t, align, size, r;
7116 CType type;
7117 Sym *s;
7118 AttributeDef ad;
7120 /* XXX: GCC 2.95.3 does not generate a table although it should be
7121 better here */
7122 tok_next:
7123 switch(tok) {
7124 case TOK_EXTENSION:
7125 next();
7126 goto tok_next;
7127 case TOK_CINT:
7128 case TOK_CCHAR:
7129 case TOK_LCHAR:
7130 vpushi(tokc.i);
7131 next();
7132 break;
7133 case TOK_CUINT:
7134 vpush_tokc(VT_INT | VT_UNSIGNED);
7135 next();
7136 break;
7137 case TOK_CLLONG:
7138 vpush_tokc(VT_LLONG);
7139 next();
7140 break;
7141 case TOK_CULLONG:
7142 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7143 next();
7144 break;
7145 case TOK_CFLOAT:
7146 vpush_tokc(VT_FLOAT);
7147 next();
7148 break;
7149 case TOK_CDOUBLE:
7150 vpush_tokc(VT_DOUBLE);
7151 next();
7152 break;
7153 case TOK_CLDOUBLE:
7154 vpush_tokc(VT_LDOUBLE);
7155 next();
7156 break;
7157 case TOK___FUNCTION__:
7158 if (!gnu_ext)
7159 goto tok_identifier;
7160 /* fall thru */
7161 case TOK___FUNC__:
7163 void *ptr;
7164 int len;
7165 /* special function name identifier */
7166 len = strlen(funcname) + 1;
7167 /* generate char[len] type */
7168 type.t = VT_BYTE;
7169 mk_pointer(&type);
7170 type.t |= VT_ARRAY;
7171 type.ref->c = len;
7172 vpush_ref(&type, data_section, data_section->data_offset, len);
7173 ptr = section_ptr_add(data_section, len);
7174 memcpy(ptr, funcname, len);
7175 next();
7177 break;
7178 case TOK_LSTR:
7179 #ifdef TCC_TARGET_PE
7180 t = VT_SHORT | VT_UNSIGNED;
7181 #else
7182 t = VT_INT;
7183 #endif
7184 goto str_init;
7185 case TOK_STR:
7186 /* string parsing */
7187 t = VT_BYTE;
7188 str_init:
7189 if (tcc_state->warn_write_strings)
7190 t |= VT_CONSTANT;
7191 type.t = t;
7192 mk_pointer(&type);
7193 type.t |= VT_ARRAY;
7194 memset(&ad, 0, sizeof(AttributeDef));
7195 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7196 break;
7197 case '(':
7198 next();
7199 /* cast ? */
7200 if (parse_btype(&type, &ad)) {
7201 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7202 skip(')');
7203 /* check ISOC99 compound literal */
7204 if (tok == '{') {
7205 /* data is allocated locally by default */
7206 if (global_expr)
7207 r = VT_CONST;
7208 else
7209 r = VT_LOCAL;
7210 /* all except arrays are lvalues */
7211 if (!(type.t & VT_ARRAY))
7212 r |= lvalue_type(type.t);
7213 memset(&ad, 0, sizeof(AttributeDef));
7214 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7215 } else {
7216 unary();
7217 gen_cast(&type);
7219 } else if (tok == '{') {
7220 /* save all registers */
7221 save_regs(0);
7222 /* statement expression : we do not accept break/continue
7223 inside as GCC does */
7224 block(NULL, NULL, NULL, NULL, 0, 1);
7225 skip(')');
7226 } else {
7227 gexpr();
7228 skip(')');
7230 break;
7231 case '*':
7232 next();
7233 unary();
7234 indir();
7235 break;
7236 case '&':
7237 next();
7238 unary();
7239 /* functions names must be treated as function pointers,
7240 except for unary '&' and sizeof. Since we consider that
7241 functions are not lvalues, we only have to handle it
7242 there and in function calls. */
7243 /* arrays can also be used although they are not lvalues */
7244 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7245 !(vtop->type.t & VT_ARRAY))
7246 test_lvalue();
7247 mk_pointer(&vtop->type);
7248 gaddrof();
7249 break;
7250 case '!':
7251 next();
7252 unary();
7253 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7254 vtop->c.i = !vtop->c.i;
7255 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7256 vtop->c.i = vtop->c.i ^ 1;
7257 else
7258 vseti(VT_JMP, gtst(1, 0));
7259 break;
7260 case '~':
7261 next();
7262 unary();
7263 vpushi(-1);
7264 gen_op('^');
7265 break;
7266 case '+':
7267 next();
7268 /* in order to force cast, we add zero */
7269 unary();
7270 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7271 error("pointer not accepted for unary plus");
7272 vpushi(0);
7273 gen_op('+');
7274 break;
7275 case TOK_SIZEOF:
7276 case TOK_ALIGNOF1:
7277 case TOK_ALIGNOF2:
7278 t = tok;
7279 next();
7280 if (tok == '(') {
7281 parse_expr_type(&type);
7282 } else {
7283 unary_type(&type);
7285 size = type_size(&type, &align);
7286 if (t == TOK_SIZEOF) {
7287 if (size < 0)
7288 error("sizeof applied to an incomplete type");
7289 vpushi(size);
7290 } else {
7291 vpushi(align);
7293 break;
7295 case TOK_builtin_types_compatible_p:
7297 CType type1, type2;
7298 next();
7299 skip('(');
7300 parse_type(&type1);
7301 skip(',');
7302 parse_type(&type2);
7303 skip(')');
7304 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7305 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7306 vpushi(is_compatible_types(&type1, &type2));
7308 break;
7309 case TOK_builtin_constant_p:
7311 int saved_nocode_wanted, res;
7312 next();
7313 skip('(');
7314 saved_nocode_wanted = nocode_wanted;
7315 nocode_wanted = 1;
7316 gexpr();
7317 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7318 vpop();
7319 nocode_wanted = saved_nocode_wanted;
7320 skip(')');
7321 vpushi(res);
7323 break;
7324 case TOK_INC:
7325 case TOK_DEC:
7326 t = tok;
7327 next();
7328 unary();
7329 inc(0, t);
7330 break;
7331 case '-':
7332 next();
7333 vpushi(0);
7334 unary();
7335 gen_op('-');
7336 break;
7337 case TOK_LAND:
7338 if (!gnu_ext)
7339 goto tok_identifier;
7340 next();
7341 /* allow to take the address of a label */
7342 if (tok < TOK_UIDENT)
7343 expect("label identifier");
7344 s = label_find(tok);
7345 if (!s) {
7346 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7347 } else {
7348 if (s->r == LABEL_DECLARED)
7349 s->r = LABEL_FORWARD;
7351 if (!s->type.t) {
7352 s->type.t = VT_VOID;
7353 mk_pointer(&s->type);
7354 s->type.t |= VT_STATIC;
7356 vset(&s->type, VT_CONST | VT_SYM, 0);
7357 vtop->sym = s;
7358 next();
7359 break;
7360 default:
7361 tok_identifier:
7362 t = tok;
7363 next();
7364 if (t < TOK_UIDENT)
7365 expect("identifier");
7366 s = sym_find(t);
7367 if (!s) {
7368 if (tok != '(')
7369 error("'%s' undeclared", get_tok_str(t, NULL));
7370 /* for simple function calls, we tolerate undeclared
7371 external reference to int() function */
7372 if (tcc_state->warn_implicit_function_declaration)
7373 warning("implicit declaration of function '%s'",
7374 get_tok_str(t, NULL));
7375 s = external_global_sym(t, &func_old_type, 0);
7377 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7378 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7379 /* if referencing an inline function, then we generate a
7380 symbol to it if not already done. It will have the
7381 effect to generate code for it at the end of the
7382 compilation unit. Inline function as always
7383 generated in the text section. */
7384 if (!s->c)
7385 put_extern_sym(s, text_section, 0, 0);
7386 r = VT_SYM | VT_CONST;
7387 } else {
7388 r = s->r;
7390 vset(&s->type, r, s->c);
7391 /* if forward reference, we must point to s */
7392 if (vtop->r & VT_SYM) {
7393 vtop->sym = s;
7394 vtop->c.ul = 0;
7396 break;
7399 /* post operations */
7400 while (1) {
7401 if (tok == TOK_INC || tok == TOK_DEC) {
7402 inc(1, tok);
7403 next();
7404 } else if (tok == '.' || tok == TOK_ARROW) {
7405 /* field */
7406 if (tok == TOK_ARROW)
7407 indir();
7408 test_lvalue();
7409 gaddrof();
7410 next();
7411 /* expect pointer on structure */
7412 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7413 expect("struct or union");
7414 s = vtop->type.ref;
7415 /* find field */
7416 tok |= SYM_FIELD;
7417 while ((s = s->next) != NULL) {
7418 if (s->v == tok)
7419 break;
7421 if (!s)
7422 error("field not found");
7423 /* add field offset to pointer */
7424 vtop->type = char_pointer_type; /* change type to 'char *' */
7425 vpushi(s->c);
7426 gen_op('+');
7427 /* change type to field type, and set to lvalue */
7428 vtop->type = s->type;
7429 /* an array is never an lvalue */
7430 if (!(vtop->type.t & VT_ARRAY)) {
7431 vtop->r |= lvalue_type(vtop->type.t);
7432 /* if bound checking, the referenced pointer must be checked */
7433 if (do_bounds_check)
7434 vtop->r |= VT_MUSTBOUND;
7436 next();
7437 } else if (tok == '[') {
7438 next();
7439 gexpr();
7440 gen_op('+');
7441 indir();
7442 skip(']');
7443 } else if (tok == '(') {
7444 SValue ret;
7445 Sym *sa;
7446 int nb_args;
7448 /* function call */
7449 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7450 /* pointer test (no array accepted) */
7451 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7452 vtop->type = *pointed_type(&vtop->type);
7453 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7454 goto error_func;
7455 } else {
7456 error_func:
7457 expect("function pointer");
7459 } else {
7460 vtop->r &= ~VT_LVAL; /* no lvalue */
7462 /* get return type */
7463 s = vtop->type.ref;
7464 next();
7465 sa = s->next; /* first parameter */
7466 nb_args = 0;
7467 /* compute first implicit argument if a structure is returned */
7468 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7469 /* get some space for the returned structure */
7470 size = type_size(&s->type, &align);
7471 loc = (loc - size) & -align;
7472 ret.type = s->type;
7473 ret.r = VT_LOCAL | VT_LVAL;
7474 /* pass it as 'int' to avoid structure arg passing
7475 problems */
7476 vseti(VT_LOCAL, loc);
7477 ret.c = vtop->c;
7478 nb_args++;
7479 } else {
7480 ret.type = s->type;
7481 ret.r2 = VT_CONST;
7482 /* return in register */
7483 if (is_float(ret.type.t)) {
7484 ret.r = REG_FRET;
7485 } else {
7486 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7487 ret.r2 = REG_LRET;
7488 ret.r = REG_IRET;
7490 ret.c.i = 0;
7492 if (tok != ')') {
7493 for(;;) {
7494 expr_eq();
7495 gfunc_param_typed(s, sa);
7496 nb_args++;
7497 if (sa)
7498 sa = sa->next;
7499 if (tok == ')')
7500 break;
7501 skip(',');
7504 if (sa)
7505 error("too few arguments to function");
7506 skip(')');
7507 if (!nocode_wanted) {
7508 gfunc_call(nb_args);
7509 } else {
7510 vtop -= (nb_args + 1);
7512 /* return value */
7513 vsetc(&ret.type, ret.r, &ret.c);
7514 vtop->r2 = ret.r2;
7515 } else {
7516 break;
7521 static void uneq(void)
7523 int t;
7525 unary();
7526 if (tok == '=' ||
7527 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7528 tok == TOK_A_XOR || tok == TOK_A_OR ||
7529 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7530 test_lvalue();
7531 t = tok;
7532 next();
7533 if (t == '=') {
7534 expr_eq();
7535 } else {
7536 vdup();
7537 expr_eq();
7538 gen_op(t & 0x7f);
7540 vstore();
7544 static void expr_prod(void)
7546 int t;
7548 uneq();
7549 while (tok == '*' || tok == '/' || tok == '%') {
7550 t = tok;
7551 next();
7552 uneq();
7553 gen_op(t);
7557 static void expr_sum(void)
7559 int t;
7561 expr_prod();
7562 while (tok == '+' || tok == '-') {
7563 t = tok;
7564 next();
7565 expr_prod();
7566 gen_op(t);
7570 static void expr_shift(void)
7572 int t;
7574 expr_sum();
7575 while (tok == TOK_SHL || tok == TOK_SAR) {
7576 t = tok;
7577 next();
7578 expr_sum();
7579 gen_op(t);
7583 static void expr_cmp(void)
7585 int t;
7587 expr_shift();
7588 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7589 tok == TOK_ULT || tok == TOK_UGE) {
7590 t = tok;
7591 next();
7592 expr_shift();
7593 gen_op(t);
7597 static void expr_cmpeq(void)
7599 int t;
7601 expr_cmp();
7602 while (tok == TOK_EQ || tok == TOK_NE) {
7603 t = tok;
7604 next();
7605 expr_cmp();
7606 gen_op(t);
7610 static void expr_and(void)
7612 expr_cmpeq();
7613 while (tok == '&') {
7614 next();
7615 expr_cmpeq();
7616 gen_op('&');
7620 static void expr_xor(void)
7622 expr_and();
7623 while (tok == '^') {
7624 next();
7625 expr_and();
7626 gen_op('^');
7630 static void expr_or(void)
7632 expr_xor();
7633 while (tok == '|') {
7634 next();
7635 expr_xor();
7636 gen_op('|');
7640 /* XXX: fix this mess */
7641 static void expr_land_const(void)
7643 expr_or();
7644 while (tok == TOK_LAND) {
7645 next();
7646 expr_or();
7647 gen_op(TOK_LAND);
7651 /* XXX: fix this mess */
7652 static void expr_lor_const(void)
7654 expr_land_const();
7655 while (tok == TOK_LOR) {
7656 next();
7657 expr_land_const();
7658 gen_op(TOK_LOR);
7662 /* only used if non constant */
7663 static void expr_land(void)
7665 int t;
7667 expr_or();
7668 if (tok == TOK_LAND) {
7669 t = 0;
7670 for(;;) {
7671 t = gtst(1, t);
7672 if (tok != TOK_LAND) {
7673 vseti(VT_JMPI, t);
7674 break;
7676 next();
7677 expr_or();
7682 static void expr_lor(void)
7684 int t;
7686 expr_land();
7687 if (tok == TOK_LOR) {
7688 t = 0;
7689 for(;;) {
7690 t = gtst(0, t);
7691 if (tok != TOK_LOR) {
7692 vseti(VT_JMP, t);
7693 break;
7695 next();
7696 expr_land();
7701 /* XXX: better constant handling */
7702 static void expr_eq(void)
7704 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7705 SValue sv;
7706 CType type, type1, type2;
7708 if (const_wanted) {
7709 int c1, c;
7710 expr_lor_const();
7711 if (tok == '?') {
7712 c = vtop->c.i;
7713 vpop();
7714 next();
7715 if (tok == ':' && gnu_ext) {
7716 c1 = c;
7717 } else {
7718 gexpr();
7719 c1 = vtop->c.i;
7720 vpop();
7722 skip(':');
7723 expr_eq();
7724 if (c)
7725 vtop->c.i = c1;
7727 } else {
7728 expr_lor();
7729 if (tok == '?') {
7730 next();
7731 if (vtop != vstack) {
7732 /* needed to avoid having different registers saved in
7733 each branch */
7734 if (is_float(vtop->type.t))
7735 rc = RC_FLOAT;
7736 else
7737 rc = RC_INT;
7738 gv(rc);
7739 save_regs(1);
7741 if (tok == ':' && gnu_ext) {
7742 gv_dup();
7743 tt = gtst(1, 0);
7744 } else {
7745 tt = gtst(1, 0);
7746 gexpr();
7748 type1 = vtop->type;
7749 sv = *vtop; /* save value to handle it later */
7750 vtop--; /* no vpop so that FP stack is not flushed */
7751 skip(':');
7752 u = gjmp(0);
7753 gsym(tt);
7754 expr_eq();
7755 type2 = vtop->type;
7757 t1 = type1.t;
7758 bt1 = t1 & VT_BTYPE;
7759 t2 = type2.t;
7760 bt2 = t2 & VT_BTYPE;
7761 /* cast operands to correct type according to ISOC rules */
7762 if (is_float(bt1) || is_float(bt2)) {
7763 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7764 type.t = VT_LDOUBLE;
7765 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7766 type.t = VT_DOUBLE;
7767 } else {
7768 type.t = VT_FLOAT;
7770 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7771 /* cast to biggest op */
7772 type.t = VT_LLONG;
7773 /* convert to unsigned if it does not fit in a long long */
7774 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7775 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7776 type.t |= VT_UNSIGNED;
7777 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7778 /* XXX: test pointer compatibility */
7779 type = type1;
7780 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7781 /* XXX: test structure compatibility */
7782 type = type1;
7783 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7784 /* NOTE: as an extension, we accept void on only one side */
7785 type.t = VT_VOID;
7786 } else {
7787 /* integer operations */
7788 type.t = VT_INT;
7789 /* convert to unsigned if it does not fit in an integer */
7790 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7791 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7792 type.t |= VT_UNSIGNED;
7795 /* now we convert second operand */
7796 gen_cast(&type);
7797 rc = RC_INT;
7798 if (is_float(type.t)) {
7799 rc = RC_FLOAT;
7800 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7801 /* for long longs, we use fixed registers to avoid having
7802 to handle a complicated move */
7803 rc = RC_IRET;
7806 r2 = gv(rc);
7807 /* this is horrible, but we must also convert first
7808 operand */
7809 tt = gjmp(0);
7810 gsym(u);
7811 /* put again first value and cast it */
7812 *vtop = sv;
7813 gen_cast(&type);
7814 r1 = gv(rc);
7815 move_reg(r2, r1);
7816 vtop->r = r2;
7817 gsym(tt);
7822 static void gexpr(void)
7824 while (1) {
7825 expr_eq();
7826 if (tok != ',')
7827 break;
7828 vpop();
7829 next();
7833 /* parse an expression and return its type without any side effect. */
7834 static void expr_type(CType *type)
7836 int saved_nocode_wanted;
7838 saved_nocode_wanted = nocode_wanted;
7839 nocode_wanted = 1;
7840 gexpr();
7841 *type = vtop->type;
7842 vpop();
7843 nocode_wanted = saved_nocode_wanted;
7846 /* parse a unary expression and return its type without any side
7847 effect. */
7848 static void unary_type(CType *type)
7850 int a;
7852 a = nocode_wanted;
7853 nocode_wanted = 1;
7854 unary();
7855 *type = vtop->type;
7856 vpop();
7857 nocode_wanted = a;
7860 /* parse a constant expression and return value in vtop. */
7861 static void expr_const1(void)
7863 int a;
7864 a = const_wanted;
7865 const_wanted = 1;
7866 expr_eq();
7867 const_wanted = a;
7870 /* parse an integer constant and return its value. */
7871 static int expr_const(void)
7873 int c;
7874 expr_const1();
7875 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7876 expect("constant expression");
7877 c = vtop->c.i;
7878 vpop();
7879 return c;
7882 /* return the label token if current token is a label, otherwise
7883 return zero */
7884 static int is_label(void)
7886 int last_tok;
7888 /* fast test first */
7889 if (tok < TOK_UIDENT)
7890 return 0;
7891 /* no need to save tokc because tok is an identifier */
7892 last_tok = tok;
7893 next();
7894 if (tok == ':') {
7895 next();
7896 return last_tok;
7897 } else {
7898 unget_tok(last_tok);
7899 return 0;
7903 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7904 int case_reg, int is_expr)
7906 int a, b, c, d;
7907 Sym *s;
7909 /* generate line number info */
7910 if (do_debug &&
7911 (last_line_num != file->line_num || last_ind != ind)) {
7912 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7913 last_ind = ind;
7914 last_line_num = file->line_num;
7917 if (is_expr) {
7918 /* default return value is (void) */
7919 vpushi(0);
7920 vtop->type.t = VT_VOID;
7923 if (tok == TOK_IF) {
7924 /* if test */
7925 next();
7926 skip('(');
7927 gexpr();
7928 skip(')');
7929 a = gtst(1, 0);
7930 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7931 c = tok;
7932 if (c == TOK_ELSE) {
7933 next();
7934 d = gjmp(0);
7935 gsym(a);
7936 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7937 gsym(d); /* patch else jmp */
7938 } else
7939 gsym(a);
7940 } else if (tok == TOK_WHILE) {
7941 next();
7942 d = ind;
7943 skip('(');
7944 gexpr();
7945 skip(')');
7946 a = gtst(1, 0);
7947 b = 0;
7948 block(&a, &b, case_sym, def_sym, case_reg, 0);
7949 gjmp_addr(d);
7950 gsym(a);
7951 gsym_addr(b, d);
7952 } else if (tok == '{') {
7953 Sym *llabel;
7955 next();
7956 /* record local declaration stack position */
7957 s = local_stack;
7958 llabel = local_label_stack;
7959 /* handle local labels declarations */
7960 if (tok == TOK_LABEL) {
7961 next();
7962 for(;;) {
7963 if (tok < TOK_UIDENT)
7964 expect("label identifier");
7965 label_push(&local_label_stack, tok, LABEL_DECLARED);
7966 next();
7967 if (tok == ',') {
7968 next();
7969 } else {
7970 skip(';');
7971 break;
7975 while (tok != '}') {
7976 decl(VT_LOCAL);
7977 if (tok != '}') {
7978 if (is_expr)
7979 vpop();
7980 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7983 /* pop locally defined labels */
7984 label_pop(&local_label_stack, llabel);
7985 /* pop locally defined symbols */
7986 sym_pop(&local_stack, s);
7987 next();
7988 } else if (tok == TOK_RETURN) {
7989 next();
7990 if (tok != ';') {
7991 gexpr();
7992 gen_assign_cast(&func_vt);
7993 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7994 CType type;
7995 /* if returning structure, must copy it to implicit
7996 first pointer arg location */
7997 type = func_vt;
7998 mk_pointer(&type);
7999 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8000 indir();
8001 vswap();
8002 /* copy structure value to pointer */
8003 vstore();
8004 } else if (is_float(func_vt.t)) {
8005 gv(RC_FRET);
8006 } else {
8007 gv(RC_IRET);
8009 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8011 skip(';');
8012 rsym = gjmp(rsym); /* jmp */
8013 } else if (tok == TOK_BREAK) {
8014 /* compute jump */
8015 if (!bsym)
8016 error("cannot break");
8017 *bsym = gjmp(*bsym);
8018 next();
8019 skip(';');
8020 } else if (tok == TOK_CONTINUE) {
8021 /* compute jump */
8022 if (!csym)
8023 error("cannot continue");
8024 *csym = gjmp(*csym);
8025 next();
8026 skip(';');
8027 } else if (tok == TOK_FOR) {
8028 int e;
8029 next();
8030 skip('(');
8031 if (tok != ';') {
8032 gexpr();
8033 vpop();
8035 skip(';');
8036 d = ind;
8037 c = ind;
8038 a = 0;
8039 b = 0;
8040 if (tok != ';') {
8041 gexpr();
8042 a = gtst(1, 0);
8044 skip(';');
8045 if (tok != ')') {
8046 e = gjmp(0);
8047 c = ind;
8048 gexpr();
8049 vpop();
8050 gjmp_addr(d);
8051 gsym(e);
8053 skip(')');
8054 block(&a, &b, case_sym, def_sym, case_reg, 0);
8055 gjmp_addr(c);
8056 gsym(a);
8057 gsym_addr(b, c);
8058 } else
8059 if (tok == TOK_DO) {
8060 next();
8061 a = 0;
8062 b = 0;
8063 d = ind;
8064 block(&a, &b, case_sym, def_sym, case_reg, 0);
8065 skip(TOK_WHILE);
8066 skip('(');
8067 gsym(b);
8068 gexpr();
8069 c = gtst(0, 0);
8070 gsym_addr(c, d);
8071 skip(')');
8072 gsym(a);
8073 skip(';');
8074 } else
8075 if (tok == TOK_SWITCH) {
8076 next();
8077 skip('(');
8078 gexpr();
8079 /* XXX: other types than integer */
8080 case_reg = gv(RC_INT);
8081 vpop();
8082 skip(')');
8083 a = 0;
8084 b = gjmp(0); /* jump to first case */
8085 c = 0;
8086 block(&a, csym, &b, &c, case_reg, 0);
8087 /* if no default, jmp after switch */
8088 if (c == 0)
8089 c = ind;
8090 /* default label */
8091 gsym_addr(b, c);
8092 /* break label */
8093 gsym(a);
8094 } else
8095 if (tok == TOK_CASE) {
8096 int v1, v2;
8097 if (!case_sym)
8098 expect("switch");
8099 next();
8100 v1 = expr_const();
8101 v2 = v1;
8102 if (gnu_ext && tok == TOK_DOTS) {
8103 next();
8104 v2 = expr_const();
8105 if (v2 < v1)
8106 warning("empty case range");
8108 /* since a case is like a label, we must skip it with a jmp */
8109 b = gjmp(0);
8110 gsym(*case_sym);
8111 vseti(case_reg, 0);
8112 vpushi(v1);
8113 if (v1 == v2) {
8114 gen_op(TOK_EQ);
8115 *case_sym = gtst(1, 0);
8116 } else {
8117 gen_op(TOK_GE);
8118 *case_sym = gtst(1, 0);
8119 vseti(case_reg, 0);
8120 vpushi(v2);
8121 gen_op(TOK_LE);
8122 *case_sym = gtst(1, *case_sym);
8124 gsym(b);
8125 skip(':');
8126 is_expr = 0;
8127 goto block_after_label;
8128 } else
8129 if (tok == TOK_DEFAULT) {
8130 next();
8131 skip(':');
8132 if (!def_sym)
8133 expect("switch");
8134 if (*def_sym)
8135 error("too many 'default'");
8136 *def_sym = ind;
8137 is_expr = 0;
8138 goto block_after_label;
8139 } else
8140 if (tok == TOK_GOTO) {
8141 next();
8142 if (tok == '*' && gnu_ext) {
8143 /* computed goto */
8144 next();
8145 gexpr();
8146 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8147 expect("pointer");
8148 ggoto();
8149 } else if (tok >= TOK_UIDENT) {
8150 s = label_find(tok);
8151 /* put forward definition if needed */
8152 if (!s) {
8153 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8154 } else {
8155 if (s->r == LABEL_DECLARED)
8156 s->r = LABEL_FORWARD;
8158 /* label already defined */
8159 if (s->r & LABEL_FORWARD)
8160 s->next = (void *)gjmp((long)s->next);
8161 else
8162 gjmp_addr((long)s->next);
8163 next();
8164 } else {
8165 expect("label identifier");
8167 skip(';');
8168 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8169 asm_instr();
8170 } else {
8171 b = is_label();
8172 if (b) {
8173 /* label case */
8174 s = label_find(b);
8175 if (s) {
8176 if (s->r == LABEL_DEFINED)
8177 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8178 gsym((long)s->next);
8179 s->r = LABEL_DEFINED;
8180 } else {
8181 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8183 s->next = (void *)ind;
8184 /* we accept this, but it is a mistake */
8185 block_after_label:
8186 if (tok == '}') {
8187 warning("deprecated use of label at end of compound statement");
8188 } else {
8189 if (is_expr)
8190 vpop();
8191 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8193 } else {
8194 /* expression case */
8195 if (tok != ';') {
8196 if (is_expr) {
8197 vpop();
8198 gexpr();
8199 } else {
8200 gexpr();
8201 vpop();
8204 skip(';');
8209 /* t is the array or struct type. c is the array or struct
8210 address. cur_index/cur_field is the pointer to the current
8211 value. 'size_only' is true if only size info is needed (only used
8212 in arrays) */
8213 static void decl_designator(CType *type, Section *sec, unsigned long c,
8214 int *cur_index, Sym **cur_field,
8215 int size_only)
8217 Sym *s, *f;
8218 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8219 CType type1;
8221 notfirst = 0;
8222 elem_size = 0;
8223 nb_elems = 1;
8224 if (gnu_ext && (l = is_label()) != 0)
8225 goto struct_field;
8226 while (tok == '[' || tok == '.') {
8227 if (tok == '[') {
8228 if (!(type->t & VT_ARRAY))
8229 expect("array type");
8230 s = type->ref;
8231 next();
8232 index = expr_const();
8233 if (index < 0 || (s->c >= 0 && index >= s->c))
8234 expect("invalid index");
8235 if (tok == TOK_DOTS && gnu_ext) {
8236 next();
8237 index_last = expr_const();
8238 if (index_last < 0 ||
8239 (s->c >= 0 && index_last >= s->c) ||
8240 index_last < index)
8241 expect("invalid index");
8242 } else {
8243 index_last = index;
8245 skip(']');
8246 if (!notfirst)
8247 *cur_index = index_last;
8248 type = pointed_type(type);
8249 elem_size = type_size(type, &align);
8250 c += index * elem_size;
8251 /* NOTE: we only support ranges for last designator */
8252 nb_elems = index_last - index + 1;
8253 if (nb_elems != 1) {
8254 notfirst = 1;
8255 break;
8257 } else {
8258 next();
8259 l = tok;
8260 next();
8261 struct_field:
8262 if ((type->t & VT_BTYPE) != VT_STRUCT)
8263 expect("struct/union type");
8264 s = type->ref;
8265 l |= SYM_FIELD;
8266 f = s->next;
8267 while (f) {
8268 if (f->v == l)
8269 break;
8270 f = f->next;
8272 if (!f)
8273 expect("field");
8274 if (!notfirst)
8275 *cur_field = f;
8276 /* XXX: fix this mess by using explicit storage field */
8277 type1 = f->type;
8278 type1.t |= (type->t & ~VT_TYPE);
8279 type = &type1;
8280 c += f->c;
8282 notfirst = 1;
8284 if (notfirst) {
8285 if (tok == '=') {
8286 next();
8287 } else {
8288 if (!gnu_ext)
8289 expect("=");
8291 } else {
8292 if (type->t & VT_ARRAY) {
8293 index = *cur_index;
8294 type = pointed_type(type);
8295 c += index * type_size(type, &align);
8296 } else {
8297 f = *cur_field;
8298 if (!f)
8299 error("too many field init");
8300 /* XXX: fix this mess by using explicit storage field */
8301 type1 = f->type;
8302 type1.t |= (type->t & ~VT_TYPE);
8303 type = &type1;
8304 c += f->c;
8307 decl_initializer(type, sec, c, 0, size_only);
8309 /* XXX: make it more general */
8310 if (!size_only && nb_elems > 1) {
8311 unsigned long c_end;
8312 uint8_t *src, *dst;
8313 int i;
8315 if (!sec)
8316 error("range init not supported yet for dynamic storage");
8317 c_end = c + nb_elems * elem_size;
8318 if (c_end > sec->data_allocated)
8319 section_realloc(sec, c_end);
8320 src = sec->data + c;
8321 dst = src;
8322 for(i = 1; i < nb_elems; i++) {
8323 dst += elem_size;
8324 memcpy(dst, src, elem_size);
8329 #define EXPR_VAL 0
8330 #define EXPR_CONST 1
8331 #define EXPR_ANY 2
8333 /* store a value or an expression directly in global data or in local array */
8334 static void init_putv(CType *type, Section *sec, unsigned long c,
8335 int v, int expr_type)
8337 int saved_global_expr, bt, bit_pos, bit_size;
8338 void *ptr;
8339 unsigned long long bit_mask;
8340 CType dtype;
8342 switch(expr_type) {
8343 case EXPR_VAL:
8344 vpushi(v);
8345 break;
8346 case EXPR_CONST:
8347 /* compound literals must be allocated globally in this case */
8348 saved_global_expr = global_expr;
8349 global_expr = 1;
8350 expr_const1();
8351 global_expr = saved_global_expr;
8352 /* NOTE: symbols are accepted */
8353 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8354 error("initializer element is not constant");
8355 break;
8356 case EXPR_ANY:
8357 expr_eq();
8358 break;
8361 dtype = *type;
8362 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8364 if (sec) {
8365 /* XXX: not portable */
8366 /* XXX: generate error if incorrect relocation */
8367 gen_assign_cast(&dtype);
8368 bt = type->t & VT_BTYPE;
8369 ptr = sec->data + c;
8370 /* XXX: make code faster ? */
8371 if (!(type->t & VT_BITFIELD)) {
8372 bit_pos = 0;
8373 bit_size = 32;
8374 bit_mask = -1LL;
8375 } else {
8376 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8377 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8378 bit_mask = (1LL << bit_size) - 1;
8380 if ((vtop->r & VT_SYM) &&
8381 (bt == VT_BYTE ||
8382 bt == VT_SHORT ||
8383 bt == VT_DOUBLE ||
8384 bt == VT_LDOUBLE ||
8385 bt == VT_LLONG ||
8386 (bt == VT_INT && bit_size != 32)))
8387 error("initializer element is not computable at load time");
8388 switch(bt) {
8389 case VT_BYTE:
8390 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8391 break;
8392 case VT_SHORT:
8393 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8394 break;
8395 case VT_DOUBLE:
8396 *(double *)ptr = vtop->c.d;
8397 break;
8398 case VT_LDOUBLE:
8399 *(long double *)ptr = vtop->c.ld;
8400 break;
8401 case VT_LLONG:
8402 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8403 break;
8404 default:
8405 if (vtop->r & VT_SYM) {
8406 greloc(sec, vtop->sym, c, R_DATA_32);
8408 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8409 break;
8411 vtop--;
8412 } else {
8413 vset(&dtype, VT_LOCAL, c);
8414 vswap();
8415 vstore();
8416 vpop();
8420 /* put zeros for variable based init */
8421 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8423 if (sec) {
8424 /* nothing to do because globals are already set to zero */
8425 } else {
8426 vpush_global_sym(&func_old_type, TOK_memset);
8427 vseti(VT_LOCAL, c);
8428 vpushi(0);
8429 vpushi(size);
8430 gfunc_call(3);
8434 /* 't' contains the type and storage info. 'c' is the offset of the
8435 object in section 'sec'. If 'sec' is NULL, it means stack based
8436 allocation. 'first' is true if array '{' must be read (multi
8437 dimension implicit array init handling). 'size_only' is true if
8438 size only evaluation is wanted (only for arrays). */
8439 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8440 int first, int size_only)
8442 int index, array_length, n, no_oblock, nb, parlevel, i;
8443 int size1, align1, expr_type;
8444 Sym *s, *f;
8445 CType *t1;
8447 if (type->t & VT_ARRAY) {
8448 s = type->ref;
8449 n = s->c;
8450 array_length = 0;
8451 t1 = pointed_type(type);
8452 size1 = type_size(t1, &align1);
8454 no_oblock = 1;
8455 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8456 tok == '{') {
8457 skip('{');
8458 no_oblock = 0;
8461 /* only parse strings here if correct type (otherwise: handle
8462 them as ((w)char *) expressions */
8463 if ((tok == TOK_LSTR &&
8464 #ifdef TCC_TARGET_PE
8465 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)) ||
8466 #else
8467 (t1->t & VT_BTYPE) == VT_INT) ||
8468 #endif
8469 (tok == TOK_STR &&
8470 (t1->t & VT_BTYPE) == VT_BYTE)) {
8471 while (tok == TOK_STR || tok == TOK_LSTR) {
8472 int cstr_len, ch;
8473 CString *cstr;
8475 cstr = tokc.cstr;
8476 /* compute maximum number of chars wanted */
8477 if (tok == TOK_STR)
8478 cstr_len = cstr->size;
8479 else
8480 cstr_len = cstr->size / sizeof(nwchar_t);
8481 cstr_len--;
8482 nb = cstr_len;
8483 if (n >= 0 && nb > (n - array_length))
8484 nb = n - array_length;
8485 if (!size_only) {
8486 if (cstr_len > nb)
8487 warning("initializer-string for array is too long");
8488 /* in order to go faster for common case (char
8489 string in global variable, we handle it
8490 specifically */
8491 if (sec && tok == TOK_STR && size1 == 1) {
8492 memcpy(sec->data + c + array_length, cstr->data, nb);
8493 } else {
8494 for(i=0;i<nb;i++) {
8495 if (tok == TOK_STR)
8496 ch = ((unsigned char *)cstr->data)[i];
8497 else
8498 ch = ((nwchar_t *)cstr->data)[i];
8499 init_putv(t1, sec, c + (array_length + i) * size1,
8500 ch, EXPR_VAL);
8504 array_length += nb;
8505 next();
8507 /* only add trailing zero if enough storage (no
8508 warning in this case since it is standard) */
8509 if (n < 0 || array_length < n) {
8510 if (!size_only) {
8511 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8513 array_length++;
8515 } else {
8516 index = 0;
8517 while (tok != '}') {
8518 decl_designator(type, sec, c, &index, NULL, size_only);
8519 if (n >= 0 && index >= n)
8520 error("index too large");
8521 /* must put zero in holes (note that doing it that way
8522 ensures that it even works with designators) */
8523 if (!size_only && array_length < index) {
8524 init_putz(t1, sec, c + array_length * size1,
8525 (index - array_length) * size1);
8527 index++;
8528 if (index > array_length)
8529 array_length = index;
8530 /* special test for multi dimensional arrays (may not
8531 be strictly correct if designators are used at the
8532 same time) */
8533 if (index >= n && no_oblock)
8534 break;
8535 if (tok == '}')
8536 break;
8537 skip(',');
8540 if (!no_oblock)
8541 skip('}');
8542 /* put zeros at the end */
8543 if (!size_only && n >= 0 && array_length < n) {
8544 init_putz(t1, sec, c + array_length * size1,
8545 (n - array_length) * size1);
8547 /* patch type size if needed */
8548 if (n < 0)
8549 s->c = array_length;
8550 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8551 (sec || !first || tok == '{')) {
8552 int par_count;
8554 /* NOTE: the previous test is a specific case for automatic
8555 struct/union init */
8556 /* XXX: union needs only one init */
8558 /* XXX: this test is incorrect for local initializers
8559 beginning with ( without {. It would be much more difficult
8560 to do it correctly (ideally, the expression parser should
8561 be used in all cases) */
8562 par_count = 0;
8563 if (tok == '(') {
8564 AttributeDef ad1;
8565 CType type1;
8566 next();
8567 while (tok == '(') {
8568 par_count++;
8569 next();
8571 if (!parse_btype(&type1, &ad1))
8572 expect("cast");
8573 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8574 #if 0
8575 if (!is_assignable_types(type, &type1))
8576 error("invalid type for cast");
8577 #endif
8578 skip(')');
8580 no_oblock = 1;
8581 if (first || tok == '{') {
8582 skip('{');
8583 no_oblock = 0;
8585 s = type->ref;
8586 f = s->next;
8587 array_length = 0;
8588 index = 0;
8589 n = s->c;
8590 while (tok != '}') {
8591 decl_designator(type, sec, c, NULL, &f, size_only);
8592 index = f->c;
8593 if (!size_only && array_length < index) {
8594 init_putz(type, sec, c + array_length,
8595 index - array_length);
8597 index = index + type_size(&f->type, &align1);
8598 if (index > array_length)
8599 array_length = index;
8600 f = f->next;
8601 if (no_oblock && f == NULL)
8602 break;
8603 if (tok == '}')
8604 break;
8605 skip(',');
8607 /* put zeros at the end */
8608 if (!size_only && array_length < n) {
8609 init_putz(type, sec, c + array_length,
8610 n - array_length);
8612 if (!no_oblock)
8613 skip('}');
8614 while (par_count) {
8615 skip(')');
8616 par_count--;
8618 } else if (tok == '{') {
8619 next();
8620 decl_initializer(type, sec, c, first, size_only);
8621 skip('}');
8622 } else if (size_only) {
8623 /* just skip expression */
8624 parlevel = 0;
8625 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8626 tok != -1) {
8627 if (tok == '(')
8628 parlevel++;
8629 else if (tok == ')')
8630 parlevel--;
8631 next();
8633 } else {
8634 /* currently, we always use constant expression for globals
8635 (may change for scripting case) */
8636 expr_type = EXPR_CONST;
8637 if (!sec)
8638 expr_type = EXPR_ANY;
8639 init_putv(type, sec, c, 0, expr_type);
8643 /* parse an initializer for type 't' if 'has_init' is non zero, and
8644 allocate space in local or global data space ('r' is either
8645 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8646 variable 'v' of scope 'scope' is declared before initializers are
8647 parsed. If 'v' is zero, then a reference to the new object is put
8648 in the value stack. If 'has_init' is 2, a special parsing is done
8649 to handle string constants. */
8650 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8651 int has_init, int v, int scope)
8653 int size, align, addr, data_offset;
8654 int level;
8655 ParseState saved_parse_state;
8656 TokenString init_str;
8657 Section *sec;
8659 size = type_size(type, &align);
8660 /* If unknown size, we must evaluate it before
8661 evaluating initializers because
8662 initializers can generate global data too
8663 (e.g. string pointers or ISOC99 compound
8664 literals). It also simplifies local
8665 initializers handling */
8666 tok_str_new(&init_str);
8667 if (size < 0) {
8668 if (!has_init)
8669 error("unknown type size");
8670 /* get all init string */
8671 if (has_init == 2) {
8672 /* only get strings */
8673 while (tok == TOK_STR || tok == TOK_LSTR) {
8674 tok_str_add_tok(&init_str);
8675 next();
8677 } else {
8678 level = 0;
8679 while (level > 0 || (tok != ',' && tok != ';')) {
8680 if (tok < 0)
8681 error("unexpected end of file in initializer");
8682 tok_str_add_tok(&init_str);
8683 if (tok == '{')
8684 level++;
8685 else if (tok == '}') {
8686 if (level == 0)
8687 break;
8688 level--;
8690 next();
8693 tok_str_add(&init_str, -1);
8694 tok_str_add(&init_str, 0);
8696 /* compute size */
8697 save_parse_state(&saved_parse_state);
8699 macro_ptr = init_str.str;
8700 next();
8701 decl_initializer(type, NULL, 0, 1, 1);
8702 /* prepare second initializer parsing */
8703 macro_ptr = init_str.str;
8704 next();
8706 /* if still unknown size, error */
8707 size = type_size(type, &align);
8708 if (size < 0)
8709 error("unknown type size");
8711 /* take into account specified alignment if bigger */
8712 if (ad->aligned) {
8713 if (ad->aligned > align)
8714 align = ad->aligned;
8715 } else if (ad->packed) {
8716 align = 1;
8718 if ((r & VT_VALMASK) == VT_LOCAL) {
8719 sec = NULL;
8720 if (do_bounds_check && (type->t & VT_ARRAY))
8721 loc--;
8722 loc = (loc - size) & -align;
8723 addr = loc;
8724 /* handles bounds */
8725 /* XXX: currently, since we do only one pass, we cannot track
8726 '&' operators, so we add only arrays */
8727 if (do_bounds_check && (type->t & VT_ARRAY)) {
8728 unsigned long *bounds_ptr;
8729 /* add padding between regions */
8730 loc--;
8731 /* then add local bound info */
8732 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8733 bounds_ptr[0] = addr;
8734 bounds_ptr[1] = size;
8736 if (v) {
8737 /* local variable */
8738 sym_push(v, type, r, addr);
8739 } else {
8740 /* push local reference */
8741 vset(type, r, addr);
8743 } else {
8744 Sym *sym;
8746 sym = NULL;
8747 if (v && scope == VT_CONST) {
8748 /* see if the symbol was already defined */
8749 sym = sym_find(v);
8750 if (sym) {
8751 if (!is_compatible_types(&sym->type, type))
8752 error("incompatible types for redefinition of '%s'",
8753 get_tok_str(v, NULL));
8754 if (sym->type.t & VT_EXTERN) {
8755 /* if the variable is extern, it was not allocated */
8756 sym->type.t &= ~VT_EXTERN;
8757 /* set array size if it was ommited in extern
8758 declaration */
8759 if ((sym->type.t & VT_ARRAY) &&
8760 sym->type.ref->c < 0 &&
8761 type->ref->c >= 0)
8762 sym->type.ref->c = type->ref->c;
8763 } else {
8764 /* we accept several definitions of the same
8765 global variable. this is tricky, because we
8766 must play with the SHN_COMMON type of the symbol */
8767 /* XXX: should check if the variable was already
8768 initialized. It is incorrect to initialized it
8769 twice */
8770 /* no init data, we won't add more to the symbol */
8771 if (!has_init)
8772 goto no_alloc;
8777 /* allocate symbol in corresponding section */
8778 sec = ad->section;
8779 if (!sec) {
8780 if (has_init)
8781 sec = data_section;
8782 else if (tcc_state->nocommon)
8783 sec = bss_section;
8785 if (sec) {
8786 data_offset = sec->data_offset;
8787 data_offset = (data_offset + align - 1) & -align;
8788 addr = data_offset;
8789 /* very important to increment global pointer at this time
8790 because initializers themselves can create new initializers */
8791 data_offset += size;
8792 /* add padding if bound check */
8793 if (do_bounds_check)
8794 data_offset++;
8795 sec->data_offset = data_offset;
8796 /* allocate section space to put the data */
8797 if (sec->sh_type != SHT_NOBITS &&
8798 data_offset > sec->data_allocated)
8799 section_realloc(sec, data_offset);
8800 /* align section if needed */
8801 if (align > sec->sh_addralign)
8802 sec->sh_addralign = align;
8803 } else {
8804 addr = 0; /* avoid warning */
8807 if (v) {
8808 if (scope == VT_CONST) {
8809 if (!sym)
8810 goto do_def;
8811 } else {
8812 do_def:
8813 sym = sym_push(v, type, r | VT_SYM, 0);
8815 /* update symbol definition */
8816 if (sec) {
8817 put_extern_sym(sym, sec, addr, size);
8818 } else {
8819 Elf32_Sym *esym;
8820 /* put a common area */
8821 put_extern_sym(sym, NULL, align, size);
8822 /* XXX: find a nicer way */
8823 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8824 esym->st_shndx = SHN_COMMON;
8826 } else {
8827 CValue cval;
8829 /* push global reference */
8830 sym = get_sym_ref(type, sec, addr, size);
8831 cval.ul = 0;
8832 vsetc(type, VT_CONST | VT_SYM, &cval);
8833 vtop->sym = sym;
8836 /* handles bounds now because the symbol must be defined
8837 before for the relocation */
8838 if (do_bounds_check) {
8839 unsigned long *bounds_ptr;
8841 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8842 /* then add global bound info */
8843 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8844 bounds_ptr[0] = 0; /* relocated */
8845 bounds_ptr[1] = size;
8848 if (has_init) {
8849 decl_initializer(type, sec, addr, 1, 0);
8850 /* restore parse state if needed */
8851 if (init_str.str) {
8852 tok_str_free(init_str.str);
8853 restore_parse_state(&saved_parse_state);
8856 no_alloc: ;
8859 void put_func_debug(Sym *sym)
8861 char buf[512];
8863 /* stabs info */
8864 /* XXX: we put here a dummy type */
8865 snprintf(buf, sizeof(buf), "%s:%c1",
8866 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8867 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8868 cur_text_section, sym->c);
8869 last_ind = 0;
8870 last_line_num = 0;
8873 /* parse an old style function declaration list */
8874 /* XXX: check multiple parameter */
8875 static void func_decl_list(Sym *func_sym)
8877 AttributeDef ad;
8878 int v;
8879 Sym *s;
8880 CType btype, type;
8882 /* parse each declaration */
8883 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8884 if (!parse_btype(&btype, &ad))
8885 expect("declaration list");
8886 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8887 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8888 tok == ';') {
8889 /* we accept no variable after */
8890 } else {
8891 for(;;) {
8892 type = btype;
8893 type_decl(&type, &ad, &v, TYPE_DIRECT);
8894 /* find parameter in function parameter list */
8895 s = func_sym->next;
8896 while (s != NULL) {
8897 if ((s->v & ~SYM_FIELD) == v)
8898 goto found;
8899 s = s->next;
8901 error("declaration for parameter '%s' but no such parameter",
8902 get_tok_str(v, NULL));
8903 found:
8904 /* check that no storage specifier except 'register' was given */
8905 if (type.t & VT_STORAGE)
8906 error("storage class specified for '%s'", get_tok_str(v, NULL));
8907 convert_parameter_type(&type);
8908 /* we can add the type (NOTE: it could be local to the function) */
8909 s->type = type;
8910 /* accept other parameters */
8911 if (tok == ',')
8912 next();
8913 else
8914 break;
8917 skip(';');
8921 /* parse a function defined by symbol 'sym' and generate its code in
8922 'cur_text_section' */
8923 static void gen_function(Sym *sym)
8925 ind = cur_text_section->data_offset;
8926 /* NOTE: we patch the symbol size later */
8927 put_extern_sym(sym, cur_text_section, ind, 0);
8928 funcname = get_tok_str(sym->v, NULL);
8929 func_ind = ind;
8930 /* put debug symbol */
8931 if (do_debug)
8932 put_func_debug(sym);
8933 /* push a dummy symbol to enable local sym storage */
8934 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8935 gfunc_prolog(&sym->type);
8936 rsym = 0;
8937 block(NULL, NULL, NULL, NULL, 0, 0);
8938 gsym(rsym);
8939 gfunc_epilog();
8940 cur_text_section->data_offset = ind;
8941 label_pop(&global_label_stack, NULL);
8942 sym_pop(&local_stack, NULL); /* reset local stack */
8943 /* end of function */
8944 /* patch symbol size */
8945 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8946 ind - func_ind;
8947 if (do_debug) {
8948 put_stabn(N_FUN, 0, 0, ind - func_ind);
8950 funcname = ""; /* for safety */
8951 func_vt.t = VT_VOID; /* for safety */
8952 ind = 0; /* for safety */
8955 static void gen_inline_functions(void)
8957 Sym *sym;
8958 CType *type;
8959 int *str, inline_generated;
8961 /* iterate while inline function are referenced */
8962 for(;;) {
8963 inline_generated = 0;
8964 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8965 type = &sym->type;
8966 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8967 (type->t & (VT_STATIC | VT_INLINE)) ==
8968 (VT_STATIC | VT_INLINE) &&
8969 sym->c != 0) {
8970 /* the function was used: generate its code and
8971 convert it to a normal function */
8972 str = (int *)sym->r;
8973 sym->r = VT_SYM | VT_CONST;
8974 type->t &= ~VT_INLINE;
8976 macro_ptr = str;
8977 next();
8978 cur_text_section = text_section;
8979 gen_function(sym);
8980 macro_ptr = NULL; /* fail safe */
8982 tok_str_free(str);
8983 inline_generated = 1;
8986 if (!inline_generated)
8987 break;
8990 /* free all remaining inline function tokens */
8991 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8992 type = &sym->type;
8993 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8994 (type->t & (VT_STATIC | VT_INLINE)) ==
8995 (VT_STATIC | VT_INLINE)) {
8996 str = (int *)sym->r;
8997 tok_str_free(str);
8998 sym->r = 0; /* fail safe */
9003 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9004 static void decl(int l)
9006 int v, has_init, r;
9007 CType type, btype;
9008 Sym *sym;
9009 AttributeDef ad;
9011 while (1) {
9012 if (!parse_btype(&btype, &ad)) {
9013 /* skip redundant ';' */
9014 /* XXX: find more elegant solution */
9015 if (tok == ';') {
9016 next();
9017 continue;
9019 if (l == VT_CONST &&
9020 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9021 /* global asm block */
9022 asm_global_instr();
9023 continue;
9025 /* special test for old K&R protos without explicit int
9026 type. Only accepted when defining global data */
9027 if (l == VT_LOCAL || tok < TOK_DEFINE)
9028 break;
9029 btype.t = VT_INT;
9031 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9032 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9033 tok == ';') {
9034 /* we accept no variable after */
9035 next();
9036 continue;
9038 while (1) { /* iterate thru each declaration */
9039 type = btype;
9040 type_decl(&type, &ad, &v, TYPE_DIRECT);
9041 #if 0
9043 char buf[500];
9044 type_to_str(buf, sizeof(buf), &type, get_tok_str(v, NULL));
9045 printf("type = '%s'\n", buf);
9047 #endif
9048 if ((type.t & VT_BTYPE) == VT_FUNC) {
9049 /* if old style function prototype, we accept a
9050 declaration list */
9051 sym = type.ref;
9052 if (sym->c == FUNC_OLD)
9053 func_decl_list(sym);
9056 if (tok == '{') {
9057 if (l == VT_LOCAL)
9058 error("cannot use local functions");
9059 if ((type.t & VT_BTYPE) != VT_FUNC)
9060 expect("function definition");
9062 /* reject abstract declarators in function definition */
9063 sym = type.ref;
9064 while ((sym = sym->next) != NULL)
9065 if (!(sym->v & ~SYM_FIELD))
9066 expect("identifier");
9068 /* XXX: cannot do better now: convert extern line to static inline */
9069 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9070 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9072 sym = sym_find(v);
9073 if (sym) {
9074 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9075 goto func_error1;
9076 /* specific case: if not func_call defined, we put
9077 the one of the prototype */
9078 /* XXX: should have default value */
9079 if (sym->type.ref->r != FUNC_CDECL &&
9080 type.ref->r == FUNC_CDECL)
9081 type.ref->r = sym->type.ref->r;
9082 if (!is_compatible_types(&sym->type, &type)) {
9083 func_error1:
9084 error("incompatible types for redefinition of '%s'",
9085 get_tok_str(v, NULL));
9087 /* if symbol is already defined, then put complete type */
9088 sym->type = type;
9089 } else {
9090 /* put function symbol */
9091 sym = global_identifier_push(v, type.t, 0);
9092 sym->type.ref = type.ref;
9095 /* static inline functions are just recorded as a kind
9096 of macro. Their code will be emitted at the end of
9097 the compilation unit only if they are used */
9098 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9099 (VT_INLINE | VT_STATIC)) {
9100 TokenString func_str;
9101 int block_level;
9103 tok_str_new(&func_str);
9105 block_level = 0;
9106 for(;;) {
9107 int t;
9108 if (tok == TOK_EOF)
9109 error("unexpected end of file");
9110 tok_str_add_tok(&func_str);
9111 t = tok;
9112 next();
9113 if (t == '{') {
9114 block_level++;
9115 } else if (t == '}') {
9116 block_level--;
9117 if (block_level == 0)
9118 break;
9121 tok_str_add(&func_str, -1);
9122 tok_str_add(&func_str, 0);
9123 sym->r = (int)func_str.str;
9124 } else {
9125 /* compute text section */
9126 cur_text_section = ad.section;
9127 if (!cur_text_section)
9128 cur_text_section = text_section;
9129 sym->r = VT_SYM | VT_CONST;
9130 gen_function(sym);
9131 #ifdef TCC_TARGET_PE
9132 if (ad.dllexport) {
9133 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
9135 #endif
9137 break;
9138 } else {
9139 if (btype.t & VT_TYPEDEF) {
9140 /* save typedefed type */
9141 /* XXX: test storage specifiers ? */
9142 sym = sym_push(v, &type, 0, 0);
9143 sym->type.t |= VT_TYPEDEF;
9144 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9145 /* external function definition */
9146 /* specific case for func_call attribute */
9147 if (ad.func_call)
9148 type.ref->r = ad.func_call;
9149 external_sym(v, &type, 0);
9150 } else {
9151 /* not lvalue if array */
9152 r = 0;
9153 if (!(type.t & VT_ARRAY))
9154 r |= lvalue_type(type.t);
9155 has_init = (tok == '=');
9156 if ((btype.t & VT_EXTERN) ||
9157 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9158 !has_init && l == VT_CONST && type.ref->c < 0)) {
9159 /* external variable */
9160 /* NOTE: as GCC, uninitialized global static
9161 arrays of null size are considered as
9162 extern */
9163 external_sym(v, &type, r);
9164 } else {
9165 if (type.t & VT_STATIC)
9166 r |= VT_CONST;
9167 else
9168 r |= l;
9169 if (has_init)
9170 next();
9171 decl_initializer_alloc(&type, &ad, r,
9172 has_init, v, l);
9175 if (tok != ',') {
9176 skip(';');
9177 break;
9179 next();
9185 /* better than nothing, but needs extension to handle '-E' option
9186 correctly too */
9187 static void preprocess_init(TCCState *s1)
9189 s1->include_stack_ptr = s1->include_stack;
9190 /* XXX: move that before to avoid having to initialize
9191 file->ifdef_stack_ptr ? */
9192 s1->ifdef_stack_ptr = s1->ifdef_stack;
9193 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9195 /* XXX: not ANSI compliant: bound checking says error */
9196 vtop = vstack - 1;
9197 s1->pack_stack[0] = 0;
9198 s1->pack_stack_ptr = s1->pack_stack;
9201 /* compile the C file opened in 'file'. Return non zero if errors. */
9202 static int tcc_compile(TCCState *s1)
9204 Sym *define_start;
9205 char buf[512];
9206 volatile int section_sym;
9208 #ifdef INC_DEBUG
9209 printf("%s: **** new file\n", file->filename);
9210 #endif
9211 preprocess_init(s1);
9213 funcname = "";
9214 anon_sym = SYM_FIRST_ANOM;
9216 /* file info: full path + filename */
9217 section_sym = 0; /* avoid warning */
9218 if (do_debug) {
9219 section_sym = put_elf_sym(symtab_section, 0, 0,
9220 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9221 text_section->sh_num, NULL);
9222 getcwd(buf, sizeof(buf));
9223 pstrcat(buf, sizeof(buf), "/");
9224 put_stabs_r(buf, N_SO, 0, 0,
9225 text_section->data_offset, text_section, section_sym);
9226 put_stabs_r(file->filename, N_SO, 0, 0,
9227 text_section->data_offset, text_section, section_sym);
9229 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9230 symbols can be safely used */
9231 put_elf_sym(symtab_section, 0, 0,
9232 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9233 SHN_ABS, file->filename);
9235 /* define some often used types */
9236 int_type.t = VT_INT;
9238 char_pointer_type.t = VT_BYTE;
9239 mk_pointer(&char_pointer_type);
9241 func_old_type.t = VT_FUNC;
9242 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9244 #if 0
9245 /* define 'void *alloca(unsigned int)' builtin function */
9247 Sym *s1;
9249 p = anon_sym++;
9250 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9251 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9252 s1->next = NULL;
9253 sym->next = s1;
9254 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9256 #endif
9258 define_start = define_stack;
9260 if (setjmp(s1->error_jmp_buf) == 0) {
9261 s1->nb_errors = 0;
9262 s1->error_set_jmp_enabled = 1;
9264 ch = file->buf_ptr[0];
9265 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9266 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9267 next();
9268 decl(VT_CONST);
9269 if (tok != TOK_EOF)
9270 expect("declaration");
9272 /* end of translation unit info */
9273 if (do_debug) {
9274 put_stabs_r(NULL, N_SO, 0, 0,
9275 text_section->data_offset, text_section, section_sym);
9278 s1->error_set_jmp_enabled = 0;
9280 /* reset define stack, but leave -Dsymbols (may be incorrect if
9281 they are undefined) */
9282 free_defines(define_start);
9284 gen_inline_functions();
9286 sym_pop(&global_stack, NULL);
9288 return s1->nb_errors != 0 ? -1 : 0;
9291 /* Preprocess the current file */
9292 /* XXX: add line and file infos, add options to preserve spaces */
9293 static int tcc_preprocess(TCCState *s1)
9295 Sym *define_start;
9296 int last_is_space;
9298 preprocess_init(s1);
9300 define_start = define_stack;
9302 ch = file->buf_ptr[0];
9303 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9304 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9305 PARSE_FLAG_LINEFEED;
9306 last_is_space = 1;
9307 next();
9308 for(;;) {
9309 if (tok == TOK_EOF)
9310 break;
9311 if (!last_is_space) {
9312 fputc(' ', s1->outfile);
9314 fputs(get_tok_str(tok, &tokc), s1->outfile);
9315 if (tok == TOK_LINEFEED) {
9316 last_is_space = 1;
9317 /* XXX: suppress that hack */
9318 parse_flags &= ~PARSE_FLAG_LINEFEED;
9319 next();
9320 parse_flags |= PARSE_FLAG_LINEFEED;
9321 } else {
9322 last_is_space = 0;
9323 next();
9327 free_defines(define_start);
9329 return 0;
9332 #ifdef LIBTCC
9333 int tcc_compile_string(TCCState *s, const char *str)
9335 BufferedFile bf1, *bf = &bf1;
9336 int ret, len;
9337 char *buf;
9339 /* init file structure */
9340 bf->fd = -1;
9341 /* XXX: avoid copying */
9342 len = strlen(str);
9343 buf = tcc_malloc(len + 1);
9344 if (!buf)
9345 return -1;
9346 memcpy(buf, str, len);
9347 buf[len] = CH_EOB;
9348 bf->buf_ptr = buf;
9349 bf->buf_end = buf + len;
9350 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9351 bf->line_num = 1;
9352 file = bf;
9354 ret = tcc_compile(s);
9356 tcc_free(buf);
9358 /* currently, no need to close */
9359 return ret;
9361 #endif
9363 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9364 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9366 BufferedFile bf1, *bf = &bf1;
9368 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9369 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9370 /* default value */
9371 if (!value)
9372 value = "1";
9373 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9375 /* init file structure */
9376 bf->fd = -1;
9377 bf->buf_ptr = bf->buffer;
9378 bf->buf_end = bf->buffer + strlen(bf->buffer);
9379 *bf->buf_end = CH_EOB;
9380 bf->filename[0] = '\0';
9381 bf->line_num = 1;
9382 file = bf;
9384 s1->include_stack_ptr = s1->include_stack;
9386 /* parse with define parser */
9387 ch = file->buf_ptr[0];
9388 next_nomacro();
9389 parse_define();
9390 file = NULL;
9393 /* undefine a preprocessor symbol */
9394 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9396 TokenSym *ts;
9397 Sym *s;
9398 ts = tok_alloc(sym, strlen(sym));
9399 s = define_find(ts->tok);
9400 /* undefine symbol by putting an invalid name */
9401 if (s)
9402 define_undef(s);
9405 #ifdef CONFIG_TCC_ASM
9407 #ifdef TCC_TARGET_I386
9408 #include "i386-asm.c"
9409 #endif
9410 #include "tccasm.c"
9412 #else
9413 static void asm_instr(void)
9415 error("inline asm() not supported");
9417 static void asm_global_instr(void)
9419 error("inline asm() not supported");
9421 #endif
9423 #include "tccelf.c"
9425 #ifdef TCC_TARGET_COFF
9426 #include "tcccoff.c"
9427 #endif
9429 #ifdef TCC_TARGET_PE
9430 #include "tccpe.c"
9431 #endif
9433 /* print the position in the source file of PC value 'pc' by reading
9434 the stabs debug information */
9435 static void rt_printline(unsigned long wanted_pc)
9437 Stab_Sym *sym, *sym_end;
9438 char func_name[128], last_func_name[128];
9439 unsigned long func_addr, last_pc, pc;
9440 const char *incl_files[INCLUDE_STACK_SIZE];
9441 int incl_index, len, last_line_num, i;
9442 const char *str, *p;
9444 fprintf(stderr, "0x%08lx:", wanted_pc);
9446 func_name[0] = '\0';
9447 func_addr = 0;
9448 incl_index = 0;
9449 last_func_name[0] = '\0';
9450 last_pc = 0xffffffff;
9451 last_line_num = 1;
9452 sym = (Stab_Sym *)stab_section->data + 1;
9453 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9454 while (sym < sym_end) {
9455 switch(sym->n_type) {
9456 /* function start or end */
9457 case N_FUN:
9458 if (sym->n_strx == 0) {
9459 /* we test if between last line and end of function */
9460 pc = sym->n_value + func_addr;
9461 if (wanted_pc >= last_pc && wanted_pc < pc)
9462 goto found;
9463 func_name[0] = '\0';
9464 func_addr = 0;
9465 } else {
9466 str = stabstr_section->data + sym->n_strx;
9467 p = strchr(str, ':');
9468 if (!p) {
9469 pstrcpy(func_name, sizeof(func_name), str);
9470 } else {
9471 len = p - str;
9472 if (len > sizeof(func_name) - 1)
9473 len = sizeof(func_name) - 1;
9474 memcpy(func_name, str, len);
9475 func_name[len] = '\0';
9477 func_addr = sym->n_value;
9479 break;
9480 /* line number info */
9481 case N_SLINE:
9482 pc = sym->n_value + func_addr;
9483 if (wanted_pc >= last_pc && wanted_pc < pc)
9484 goto found;
9485 last_pc = pc;
9486 last_line_num = sym->n_desc;
9487 /* XXX: slow! */
9488 strcpy(last_func_name, func_name);
9489 break;
9490 /* include files */
9491 case N_BINCL:
9492 str = stabstr_section->data + sym->n_strx;
9493 add_incl:
9494 if (incl_index < INCLUDE_STACK_SIZE) {
9495 incl_files[incl_index++] = str;
9497 break;
9498 case N_EINCL:
9499 if (incl_index > 1)
9500 incl_index--;
9501 break;
9502 case N_SO:
9503 if (sym->n_strx == 0) {
9504 incl_index = 0; /* end of translation unit */
9505 } else {
9506 str = stabstr_section->data + sym->n_strx;
9507 /* do not add path */
9508 len = strlen(str);
9509 if (len > 0 && str[len - 1] != '/')
9510 goto add_incl;
9512 break;
9514 sym++;
9517 /* second pass: we try symtab symbols (no line number info) */
9518 incl_index = 0;
9520 Elf32_Sym *sym, *sym_end;
9521 int type;
9523 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9524 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9525 sym < sym_end;
9526 sym++) {
9527 type = ELF32_ST_TYPE(sym->st_info);
9528 if (type == STT_FUNC) {
9529 if (wanted_pc >= sym->st_value &&
9530 wanted_pc < sym->st_value + sym->st_size) {
9531 pstrcpy(last_func_name, sizeof(last_func_name),
9532 strtab_section->data + sym->st_name);
9533 goto found;
9538 /* did not find any info: */
9539 fprintf(stderr, " ???\n");
9540 return;
9541 found:
9542 if (last_func_name[0] != '\0') {
9543 fprintf(stderr, " %s()", last_func_name);
9545 if (incl_index > 0) {
9546 fprintf(stderr, " (%s:%d",
9547 incl_files[incl_index - 1], last_line_num);
9548 for(i = incl_index - 2; i >= 0; i--)
9549 fprintf(stderr, ", included from %s", incl_files[i]);
9550 fprintf(stderr, ")");
9552 fprintf(stderr, "\n");
9555 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9557 #ifdef __i386__
9559 /* fix for glibc 2.1 */
9560 #ifndef REG_EIP
9561 #define REG_EIP EIP
9562 #define REG_EBP EBP
9563 #endif
9565 /* return the PC at frame level 'level'. Return non zero if not found */
9566 static int rt_get_caller_pc(unsigned long *paddr,
9567 ucontext_t *uc, int level)
9569 unsigned long fp;
9570 int i;
9572 if (level == 0) {
9573 #if defined(__FreeBSD__)
9574 *paddr = uc->uc_mcontext.mc_eip;
9575 #elif defined(__dietlibc__)
9576 *paddr = uc->uc_mcontext.eip;
9577 #else
9578 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9579 #endif
9580 return 0;
9581 } else {
9582 #if defined(__FreeBSD__)
9583 fp = uc->uc_mcontext.mc_ebp;
9584 #elif defined(__dietlibc__)
9585 fp = uc->uc_mcontext.ebp;
9586 #else
9587 fp = uc->uc_mcontext.gregs[REG_EBP];
9588 #endif
9589 for(i=1;i<level;i++) {
9590 /* XXX: check address validity with program info */
9591 if (fp <= 0x1000 || fp >= 0xc0000000)
9592 return -1;
9593 fp = ((unsigned long *)fp)[0];
9595 *paddr = ((unsigned long *)fp)[1];
9596 return 0;
9599 #else
9601 #warning add arch specific rt_get_caller_pc()
9603 static int rt_get_caller_pc(unsigned long *paddr,
9604 ucontext_t *uc, int level)
9606 return -1;
9608 #endif
9610 /* emit a run time error at position 'pc' */
9611 void rt_error(ucontext_t *uc, const char *fmt, ...)
9613 va_list ap;
9614 unsigned long pc;
9615 int i;
9617 va_start(ap, fmt);
9618 fprintf(stderr, "Runtime error: ");
9619 vfprintf(stderr, fmt, ap);
9620 fprintf(stderr, "\n");
9621 for(i=0;i<num_callers;i++) {
9622 if (rt_get_caller_pc(&pc, uc, i) < 0)
9623 break;
9624 if (i == 0)
9625 fprintf(stderr, "at ");
9626 else
9627 fprintf(stderr, "by ");
9628 rt_printline(pc);
9630 exit(255);
9631 va_end(ap);
9634 /* signal handler for fatal errors */
9635 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9637 ucontext_t *uc = puc;
9639 switch(signum) {
9640 case SIGFPE:
9641 switch(siginf->si_code) {
9642 case FPE_INTDIV:
9643 case FPE_FLTDIV:
9644 rt_error(uc, "division by zero");
9645 break;
9646 default:
9647 rt_error(uc, "floating point exception");
9648 break;
9650 break;
9651 case SIGBUS:
9652 case SIGSEGV:
9653 if (rt_bound_error_msg && *rt_bound_error_msg)
9654 rt_error(uc, *rt_bound_error_msg);
9655 else
9656 rt_error(uc, "dereferencing invalid pointer");
9657 break;
9658 case SIGILL:
9659 rt_error(uc, "illegal instruction");
9660 break;
9661 case SIGABRT:
9662 rt_error(uc, "abort() called");
9663 break;
9664 default:
9665 rt_error(uc, "caught signal %d", signum);
9666 break;
9668 exit(255);
9670 #endif
9672 /* do all relocations (needed before using tcc_get_symbol()) */
9673 int tcc_relocate(TCCState *s1)
9675 Section *s;
9676 int i;
9678 s1->nb_errors = 0;
9680 #ifdef TCC_TARGET_PE
9681 pe_add_runtime(s1);
9682 #else
9683 tcc_add_runtime(s1);
9684 #endif
9686 relocate_common_syms();
9688 tcc_add_linker_symbols(s1);
9690 build_got_entries(s1);
9692 /* compute relocation address : section are relocated in place. We
9693 also alloc the bss space */
9694 for(i = 1; i < s1->nb_sections; i++) {
9695 s = s1->sections[i];
9696 if (s->sh_flags & SHF_ALLOC) {
9697 if (s->sh_type == SHT_NOBITS)
9698 s->data = tcc_mallocz(s->data_offset);
9699 s->sh_addr = (unsigned long)s->data;
9703 relocate_syms(s1, 1);
9705 if (s1->nb_errors != 0)
9706 return -1;
9708 /* relocate each section */
9709 for(i = 1; i < s1->nb_sections; i++) {
9710 s = s1->sections[i];
9711 if (s->reloc)
9712 relocate_section(s1, s);
9715 /* mark executable sections as executable in memory */
9716 for(i = 1; i < s1->nb_sections; i++) {
9717 s = s1->sections[i];
9718 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
9719 (SHF_ALLOC | SHF_EXECINSTR)) {
9720 #ifdef WIN32
9722 DWORD old_protect;
9723 VirtualProtect(s->data, s->data_offset,
9724 PAGE_EXECUTE_READWRITE, &old_protect);
9726 #else
9728 unsigned long start, end;
9729 start = (unsigned long)(s->data) & ~(PAGESIZE - 1);
9730 end = (unsigned long)(s->data + s->data_offset);
9731 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
9732 mprotect((void *)start, end - start,
9733 PROT_READ | PROT_WRITE | PROT_EXEC);
9735 #endif
9738 return 0;
9741 /* launch the compiled program with the given arguments */
9742 int tcc_run(TCCState *s1, int argc, char **argv)
9744 int (*prog_main)(int, char **);
9746 if (tcc_relocate(s1) < 0)
9747 return -1;
9749 prog_main = tcc_get_symbol_err(s1, "main");
9751 if (do_debug) {
9752 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9753 error("debug mode currently not available for Windows");
9754 #else
9755 struct sigaction sigact;
9756 /* install TCC signal handlers to print debug info on fatal
9757 runtime errors */
9758 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9759 sigact.sa_sigaction = sig_error;
9760 sigemptyset(&sigact.sa_mask);
9761 sigaction(SIGFPE, &sigact, NULL);
9762 sigaction(SIGILL, &sigact, NULL);
9763 sigaction(SIGSEGV, &sigact, NULL);
9764 sigaction(SIGBUS, &sigact, NULL);
9765 sigaction(SIGABRT, &sigact, NULL);
9766 #endif
9769 #ifdef CONFIG_TCC_BCHECK
9770 if (do_bounds_check) {
9771 void (*bound_init)(void);
9773 /* set error function */
9774 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9775 "__bound_error_msg");
9777 /* XXX: use .init section so that it also work in binary ? */
9778 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9779 bound_init();
9781 #endif
9782 return (*prog_main)(argc, argv);
9785 TCCState *tcc_new(void)
9787 const char *p, *r;
9788 TCCState *s;
9789 TokenSym *ts;
9790 int i, c;
9792 s = tcc_mallocz(sizeof(TCCState));
9793 if (!s)
9794 return NULL;
9795 tcc_state = s;
9796 s->output_type = TCC_OUTPUT_MEMORY;
9798 /* init isid table */
9799 for(i=0;i<256;i++)
9800 isidnum_table[i] = isid(i) || isnum(i);
9802 /* add all tokens */
9803 table_ident = NULL;
9804 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9806 tok_ident = TOK_IDENT;
9807 p = tcc_keywords;
9808 while (*p) {
9809 r = p;
9810 for(;;) {
9811 c = *r++;
9812 if (c == '\0')
9813 break;
9815 ts = tok_alloc(p, r - p - 1);
9816 p = r;
9819 /* we add dummy defines for some special macros to speed up tests
9820 and to have working defined() */
9821 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9822 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9823 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9824 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9826 /* standard defines */
9827 tcc_define_symbol(s, "__STDC__", NULL);
9828 #if defined(TCC_TARGET_I386)
9829 tcc_define_symbol(s, "__i386__", NULL);
9830 #endif
9831 #if defined(TCC_TARGET_ARM)
9832 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9833 tcc_define_symbol(s, "__arm_elf__", NULL);
9834 tcc_define_symbol(s, "__arm_elf", NULL);
9835 tcc_define_symbol(s, "arm_elf", NULL);
9836 tcc_define_symbol(s, "__arm__", NULL);
9837 tcc_define_symbol(s, "__arm", NULL);
9838 tcc_define_symbol(s, "arm", NULL);
9839 tcc_define_symbol(s, "__APCS_32__", NULL);
9840 #endif
9841 #if defined(linux)
9842 tcc_define_symbol(s, "__linux__", NULL);
9843 tcc_define_symbol(s, "linux", NULL);
9844 #endif
9845 /* tiny C specific defines */
9846 tcc_define_symbol(s, "__TINYC__", NULL);
9848 /* tiny C & gcc defines */
9849 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9850 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9851 #ifdef TCC_TARGET_PE
9852 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
9853 #else
9854 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9855 #endif
9857 /* default library paths */
9858 #ifdef TCC_TARGET_PE
9860 char buf[1024];
9861 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
9862 tcc_add_library_path(s, buf);
9864 #else
9865 tcc_add_library_path(s, "/usr/local/lib");
9866 tcc_add_library_path(s, "/usr/lib");
9867 tcc_add_library_path(s, "/lib");
9868 #endif
9870 /* no section zero */
9871 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9873 /* create standard sections */
9874 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9875 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9876 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9878 /* symbols are always generated for linking stage */
9879 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9880 ".strtab",
9881 ".hashtab", SHF_PRIVATE);
9882 strtab_section = symtab_section->link;
9884 /* private symbol table for dynamic symbols */
9885 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9886 ".dynstrtab",
9887 ".dynhashtab", SHF_PRIVATE);
9888 s->alacarte_link = 1;
9890 #ifdef CHAR_IS_UNSIGNED
9891 s->char_is_unsigned = 1;
9892 #endif
9893 #if defined(TCC_TARGET_PE) && 0
9894 /* XXX: currently the PE linker is not ready to support that */
9895 s->leading_underscore = 1;
9896 #endif
9897 return s;
9900 void tcc_delete(TCCState *s1)
9902 int i, n;
9904 /* free -D defines */
9905 free_defines(NULL);
9907 /* free tokens */
9908 n = tok_ident - TOK_IDENT;
9909 for(i = 0; i < n; i++)
9910 tcc_free(table_ident[i]);
9911 tcc_free(table_ident);
9913 /* free all sections */
9915 free_section(symtab_section->hash);
9917 free_section(s1->dynsymtab_section->hash);
9918 free_section(s1->dynsymtab_section->link);
9919 free_section(s1->dynsymtab_section);
9921 for(i = 1; i < s1->nb_sections; i++)
9922 free_section(s1->sections[i]);
9923 tcc_free(s1->sections);
9925 /* free loaded dlls array */
9926 for(i = 0; i < s1->nb_loaded_dlls; i++)
9927 tcc_free(s1->loaded_dlls[i]);
9928 tcc_free(s1->loaded_dlls);
9930 /* library paths */
9931 for(i = 0; i < s1->nb_library_paths; i++)
9932 tcc_free(s1->library_paths[i]);
9933 tcc_free(s1->library_paths);
9935 /* cached includes */
9936 for(i = 0; i < s1->nb_cached_includes; i++)
9937 tcc_free(s1->cached_includes[i]);
9938 tcc_free(s1->cached_includes);
9940 for(i = 0; i < s1->nb_include_paths; i++)
9941 tcc_free(s1->include_paths[i]);
9942 tcc_free(s1->include_paths);
9944 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9945 tcc_free(s1->sysinclude_paths[i]);
9946 tcc_free(s1->sysinclude_paths);
9948 tcc_free(s1);
9951 int tcc_add_include_path(TCCState *s1, const char *pathname)
9953 char *pathname1;
9955 pathname1 = tcc_strdup(pathname);
9956 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9957 return 0;
9960 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9962 char *pathname1;
9964 pathname1 = tcc_strdup(pathname);
9965 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9966 return 0;
9969 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9971 const char *ext, *filename1;
9972 Elf32_Ehdr ehdr;
9973 int fd, ret;
9974 BufferedFile *saved_file;
9976 /* find source file type with extension */
9977 filename1 = strrchr(filename, '/');
9978 if (filename1)
9979 filename1++;
9980 else
9981 filename1 = filename;
9982 ext = strrchr(filename1, '.');
9983 if (ext)
9984 ext++;
9986 /* open the file */
9987 saved_file = file;
9988 file = tcc_open(s1, filename);
9989 if (!file) {
9990 if (flags & AFF_PRINT_ERROR) {
9991 error_noabort("file '%s' not found", filename);
9993 ret = -1;
9994 goto fail1;
9997 if (flags & AFF_PREPROCESS) {
9998 ret = tcc_preprocess(s1);
9999 } else if (!ext || !strcmp(ext, "c")) {
10000 /* C file assumed */
10001 ret = tcc_compile(s1);
10002 } else
10003 #ifdef CONFIG_TCC_ASM
10004 if (!strcmp(ext, "S")) {
10005 /* preprocessed assembler */
10006 ret = tcc_assemble(s1, 1);
10007 } else if (!strcmp(ext, "s")) {
10008 /* non preprocessed assembler */
10009 ret = tcc_assemble(s1, 0);
10010 } else
10011 #endif
10012 #ifdef TCC_TARGET_PE
10013 if (!strcmp(ext, "def")) {
10014 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
10015 } else
10016 #endif
10018 fd = file->fd;
10019 /* assume executable format: auto guess file type */
10020 ret = read(fd, &ehdr, sizeof(ehdr));
10021 lseek(fd, 0, SEEK_SET);
10022 if (ret <= 0) {
10023 error_noabort("could not read header");
10024 goto fail;
10025 } else if (ret != sizeof(ehdr)) {
10026 goto try_load_script;
10029 if (ehdr.e_ident[0] == ELFMAG0 &&
10030 ehdr.e_ident[1] == ELFMAG1 &&
10031 ehdr.e_ident[2] == ELFMAG2 &&
10032 ehdr.e_ident[3] == ELFMAG3) {
10033 file->line_num = 0; /* do not display line number if error */
10034 if (ehdr.e_type == ET_REL) {
10035 ret = tcc_load_object_file(s1, fd, 0);
10036 } else if (ehdr.e_type == ET_DYN) {
10037 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10038 #ifdef TCC_TARGET_PE
10039 ret = -1;
10040 #else
10041 void *h;
10042 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10043 if (h)
10044 ret = 0;
10045 else
10046 ret = -1;
10047 #endif
10048 } else {
10049 ret = tcc_load_dll(s1, fd, filename,
10050 (flags & AFF_REFERENCED_DLL) != 0);
10052 } else {
10053 error_noabort("unrecognized ELF file");
10054 goto fail;
10056 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10057 file->line_num = 0; /* do not display line number if error */
10058 ret = tcc_load_archive(s1, fd);
10059 } else
10060 #ifdef TCC_TARGET_COFF
10061 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10062 ret = tcc_load_coff(s1, fd);
10063 } else
10064 #endif
10066 /* as GNU ld, consider it is an ld script if not recognized */
10067 try_load_script:
10068 ret = tcc_load_ldscript(s1);
10069 if (ret < 0) {
10070 error_noabort("unrecognized file type");
10071 goto fail;
10075 the_end:
10076 tcc_close(file);
10077 fail1:
10078 file = saved_file;
10079 return ret;
10080 fail:
10081 ret = -1;
10082 goto the_end;
10085 int tcc_add_file(TCCState *s, const char *filename)
10087 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10090 int tcc_add_library_path(TCCState *s, const char *pathname)
10092 char *pathname1;
10094 pathname1 = tcc_strdup(pathname);
10095 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10096 return 0;
10099 /* find and load a dll. Return non zero if not found */
10100 /* XXX: add '-rpath' option support ? */
10101 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10103 char buf[1024];
10104 int i;
10106 for(i = 0; i < s->nb_library_paths; i++) {
10107 snprintf(buf, sizeof(buf), "%s/%s",
10108 s->library_paths[i], filename);
10109 if (tcc_add_file_internal(s, buf, flags) == 0)
10110 return 0;
10112 return -1;
10115 /* the library name is the same as the argument of the '-l' option */
10116 int tcc_add_library(TCCState *s, const char *libraryname)
10118 char buf[1024];
10119 int i;
10121 /* first we look for the dynamic library if not static linking */
10122 if (!s->static_link) {
10123 #ifdef TCC_TARGET_PE
10124 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10125 #else
10126 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10127 #endif
10128 if (tcc_add_dll(s, buf, 0) == 0)
10129 return 0;
10132 /* then we look for the static library */
10133 for(i = 0; i < s->nb_library_paths; i++) {
10134 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10135 s->library_paths[i], libraryname);
10136 if (tcc_add_file_internal(s, buf, 0) == 0)
10137 return 0;
10139 return -1;
10142 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10144 add_elf_sym(symtab_section, val, 0,
10145 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10146 SHN_ABS, name);
10147 return 0;
10150 int tcc_set_output_type(TCCState *s, int output_type)
10152 s->output_type = output_type;
10154 if (!s->nostdinc) {
10155 char buf[1024];
10157 /* default include paths */
10158 /* XXX: reverse order needed if -isystem support */
10159 #ifndef TCC_TARGET_PE
10160 tcc_add_sysinclude_path(s, "/usr/local/include");
10161 tcc_add_sysinclude_path(s, "/usr/include");
10162 #endif
10163 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10164 tcc_add_sysinclude_path(s, buf);
10165 #ifdef TCC_TARGET_PE
10166 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10167 tcc_add_sysinclude_path(s, buf);
10168 #endif
10171 /* if bound checking, then add corresponding sections */
10172 #ifdef CONFIG_TCC_BCHECK
10173 if (do_bounds_check) {
10174 /* define symbol */
10175 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10176 /* create bounds sections */
10177 bounds_section = new_section(s, ".bounds",
10178 SHT_PROGBITS, SHF_ALLOC);
10179 lbounds_section = new_section(s, ".lbounds",
10180 SHT_PROGBITS, SHF_ALLOC);
10182 #endif
10184 if (s->char_is_unsigned) {
10185 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10188 /* add debug sections */
10189 if (do_debug) {
10190 /* stab symbols */
10191 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10192 stab_section->sh_entsize = sizeof(Stab_Sym);
10193 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10194 put_elf_str(stabstr_section, "");
10195 stab_section->link = stabstr_section;
10196 /* put first entry */
10197 put_stabs("", 0, 0, 0, 0);
10200 /* add libc crt1/crti objects */
10201 #ifndef TCC_TARGET_PE
10202 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10203 !s->nostdlib) {
10204 if (output_type != TCC_OUTPUT_DLL)
10205 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10206 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10208 #endif
10209 return 0;
10212 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10213 #define FD_INVERT 0x0002 /* invert value before storing */
10215 typedef struct FlagDef {
10216 uint16_t offset;
10217 uint16_t flags;
10218 const char *name;
10219 } FlagDef;
10221 static const FlagDef warning_defs[] = {
10222 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10223 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10224 { offsetof(TCCState, warn_error), 0, "error" },
10225 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10226 "implicit-function-declaration" },
10229 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10230 const char *name, int value)
10232 int i;
10233 const FlagDef *p;
10234 const char *r;
10236 r = name;
10237 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10238 r += 3;
10239 value = !value;
10241 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10242 if (!strcmp(r, p->name))
10243 goto found;
10245 return -1;
10246 found:
10247 if (p->flags & FD_INVERT)
10248 value = !value;
10249 *(int *)((uint8_t *)s + p->offset) = value;
10250 return 0;
10254 /* set/reset a warning */
10255 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10257 int i;
10258 const FlagDef *p;
10260 if (!strcmp(warning_name, "all")) {
10261 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10262 if (p->flags & WD_ALL)
10263 *(int *)((uint8_t *)s + p->offset) = 1;
10265 return 0;
10266 } else {
10267 return set_flag(s, warning_defs, countof(warning_defs),
10268 warning_name, value);
10272 static const FlagDef flag_defs[] = {
10273 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10274 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10275 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10276 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10279 /* set/reset a flag */
10280 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10282 return set_flag(s, flag_defs, countof(flag_defs),
10283 flag_name, value);
10286 #if !defined(LIBTCC)
10288 /* extract the basename of a file */
10289 static const char *tcc_basename(const char *name)
10291 const char *p;
10292 p = strrchr(name, '/');
10293 #ifdef WIN32
10294 if (!p)
10295 p = strrchr(name, '\\');
10296 #endif
10297 if (!p)
10298 p = name;
10299 else
10300 p++;
10301 return p;
10304 static int64_t getclock_us(void)
10306 #ifdef WIN32
10307 struct _timeb tb;
10308 _ftime(&tb);
10309 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10310 #else
10311 struct timeval tv;
10312 gettimeofday(&tv, NULL);
10313 return tv.tv_sec * 1000000LL + tv.tv_usec;
10314 #endif
10317 void help(void)
10319 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10320 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10321 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10322 " [infile1 infile2...] [-run infile args...]\n"
10323 "\n"
10324 "General options:\n"
10325 " -v display current version\n"
10326 " -c compile only - generate an object file\n"
10327 " -o outfile set output filename\n"
10328 " -Bdir set tcc internal library path\n"
10329 " -bench output compilation statistics\n"
10330 " -run run compiled source\n"
10331 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10332 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10333 " -w disable all warnings\n"
10334 "Preprocessor options:\n"
10335 " -E preprocess only\n"
10336 " -Idir add include path 'dir'\n"
10337 " -Dsym[=val] define 'sym' with value 'val'\n"
10338 " -Usym undefine 'sym'\n"
10339 "Linker options:\n"
10340 " -Ldir add library path 'dir'\n"
10341 " -llib link with dynamic or static library 'lib'\n"
10342 " -shared generate a shared library\n"
10343 " -static static linking\n"
10344 " -rdynamic export all global symbols to dynamic linker\n"
10345 " -r relocatable output\n"
10346 "Debugger options:\n"
10347 " -g generate runtime debug info\n"
10348 #ifdef CONFIG_TCC_BCHECK
10349 " -b compile with built-in memory and bounds checker (implies -g)\n"
10350 #endif
10351 " -bt N show N callers in stack traces\n"
10355 #define TCC_OPTION_HAS_ARG 0x0001
10356 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10358 typedef struct TCCOption {
10359 const char *name;
10360 uint16_t index;
10361 uint16_t flags;
10362 } TCCOption;
10364 enum {
10365 TCC_OPTION_HELP,
10366 TCC_OPTION_I,
10367 TCC_OPTION_D,
10368 TCC_OPTION_U,
10369 TCC_OPTION_L,
10370 TCC_OPTION_B,
10371 TCC_OPTION_l,
10372 TCC_OPTION_bench,
10373 TCC_OPTION_bt,
10374 TCC_OPTION_b,
10375 TCC_OPTION_g,
10376 TCC_OPTION_c,
10377 TCC_OPTION_static,
10378 TCC_OPTION_shared,
10379 TCC_OPTION_o,
10380 TCC_OPTION_r,
10381 TCC_OPTION_Wl,
10382 TCC_OPTION_W,
10383 TCC_OPTION_O,
10384 TCC_OPTION_m,
10385 TCC_OPTION_f,
10386 TCC_OPTION_nostdinc,
10387 TCC_OPTION_nostdlib,
10388 TCC_OPTION_print_search_dirs,
10389 TCC_OPTION_rdynamic,
10390 TCC_OPTION_run,
10391 TCC_OPTION_v,
10392 TCC_OPTION_w,
10393 TCC_OPTION_pipe,
10394 TCC_OPTION_E,
10397 static const TCCOption tcc_options[] = {
10398 { "h", TCC_OPTION_HELP, 0 },
10399 { "?", TCC_OPTION_HELP, 0 },
10400 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10401 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10402 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10403 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10404 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10405 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10406 { "bench", TCC_OPTION_bench, 0 },
10407 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10408 #ifdef CONFIG_TCC_BCHECK
10409 { "b", TCC_OPTION_b, 0 },
10410 #endif
10411 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10412 { "c", TCC_OPTION_c, 0 },
10413 { "static", TCC_OPTION_static, 0 },
10414 { "shared", TCC_OPTION_shared, 0 },
10415 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10416 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10417 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10418 { "r", TCC_OPTION_r, 0 },
10419 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10420 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10421 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10422 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10423 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10424 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10425 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10426 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10427 { "v", TCC_OPTION_v, 0 },
10428 { "w", TCC_OPTION_w, 0 },
10429 { "pipe", TCC_OPTION_pipe, 0},
10430 { "E", TCC_OPTION_E, 0},
10431 { NULL },
10434 /* convert 'str' into an array of space separated strings */
10435 static int expand_args(char ***pargv, const char *str)
10437 const char *s1;
10438 char **argv, *arg;
10439 int argc, len;
10441 argc = 0;
10442 argv = NULL;
10443 for(;;) {
10444 while (is_space(*str))
10445 str++;
10446 if (*str == '\0')
10447 break;
10448 s1 = str;
10449 while (*str != '\0' && !is_space(*str))
10450 str++;
10451 len = str - s1;
10452 arg = tcc_malloc(len + 1);
10453 memcpy(arg, s1, len);
10454 arg[len] = '\0';
10455 dynarray_add((void ***)&argv, &argc, arg);
10457 *pargv = argv;
10458 return argc;
10461 static char **files;
10462 static int nb_files, nb_libraries;
10463 static int multiple_files;
10464 static int print_search_dirs;
10465 static int output_type;
10466 static int reloc_output;
10467 static const char *outfile;
10469 int parse_args(TCCState *s, int argc, char **argv)
10471 int optind;
10472 const TCCOption *popt;
10473 const char *optarg, *p1, *r1;
10474 char *r;
10476 optind = 0;
10477 while (1) {
10478 if (optind >= argc) {
10479 if (nb_files == 0 && !print_search_dirs)
10480 goto show_help;
10481 else
10482 break;
10484 r = argv[optind++];
10485 if (r[0] != '-') {
10486 /* add a new file */
10487 dynarray_add((void ***)&files, &nb_files, r);
10488 if (!multiple_files) {
10489 optind--;
10490 /* argv[0] will be this file */
10491 break;
10493 } else {
10494 /* find option in table (match only the first chars */
10495 popt = tcc_options;
10496 for(;;) {
10497 p1 = popt->name;
10498 if (p1 == NULL)
10499 error("invalid option -- '%s'", r);
10500 r1 = r + 1;
10501 for(;;) {
10502 if (*p1 == '\0')
10503 goto option_found;
10504 if (*r1 != *p1)
10505 break;
10506 p1++;
10507 r1++;
10509 popt++;
10511 option_found:
10512 if (popt->flags & TCC_OPTION_HAS_ARG) {
10513 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10514 optarg = r1;
10515 } else {
10516 if (optind >= argc)
10517 error("argument to '%s' is missing", r);
10518 optarg = argv[optind++];
10520 } else {
10521 if (*r1 != '\0')
10522 goto show_help;
10523 optarg = NULL;
10526 switch(popt->index) {
10527 case TCC_OPTION_HELP:
10528 show_help:
10529 help();
10530 exit(1);
10531 case TCC_OPTION_I:
10532 if (tcc_add_include_path(s, optarg) < 0)
10533 error("too many include paths");
10534 break;
10535 case TCC_OPTION_D:
10537 char *sym, *value;
10538 sym = (char *)optarg;
10539 value = strchr(sym, '=');
10540 if (value) {
10541 *value = '\0';
10542 value++;
10544 tcc_define_symbol(s, sym, value);
10546 break;
10547 case TCC_OPTION_U:
10548 tcc_undefine_symbol(s, optarg);
10549 break;
10550 case TCC_OPTION_L:
10551 tcc_add_library_path(s, optarg);
10552 break;
10553 case TCC_OPTION_B:
10554 /* set tcc utilities path (mainly for tcc development) */
10555 tcc_lib_path = optarg;
10556 break;
10557 case TCC_OPTION_l:
10558 dynarray_add((void ***)&files, &nb_files, r);
10559 nb_libraries++;
10560 break;
10561 case TCC_OPTION_bench:
10562 do_bench = 1;
10563 break;
10564 case TCC_OPTION_bt:
10565 num_callers = atoi(optarg);
10566 break;
10567 #ifdef CONFIG_TCC_BCHECK
10568 case TCC_OPTION_b:
10569 do_bounds_check = 1;
10570 do_debug = 1;
10571 break;
10572 #endif
10573 case TCC_OPTION_g:
10574 do_debug = 1;
10575 break;
10576 case TCC_OPTION_c:
10577 multiple_files = 1;
10578 output_type = TCC_OUTPUT_OBJ;
10579 break;
10580 case TCC_OPTION_static:
10581 s->static_link = 1;
10582 break;
10583 case TCC_OPTION_shared:
10584 output_type = TCC_OUTPUT_DLL;
10585 break;
10586 case TCC_OPTION_o:
10587 multiple_files = 1;
10588 outfile = optarg;
10589 break;
10590 case TCC_OPTION_r:
10591 /* generate a .o merging several output files */
10592 reloc_output = 1;
10593 output_type = TCC_OUTPUT_OBJ;
10594 break;
10595 case TCC_OPTION_nostdinc:
10596 s->nostdinc = 1;
10597 break;
10598 case TCC_OPTION_nostdlib:
10599 s->nostdlib = 1;
10600 break;
10601 case TCC_OPTION_print_search_dirs:
10602 print_search_dirs = 1;
10603 break;
10604 case TCC_OPTION_run:
10606 int argc1;
10607 char **argv1;
10608 argc1 = expand_args(&argv1, optarg);
10609 if (argc1 > 0) {
10610 parse_args(s, argc1, argv1);
10612 multiple_files = 0;
10613 output_type = TCC_OUTPUT_MEMORY;
10615 break;
10616 case TCC_OPTION_v:
10617 printf("tcc version %s\n", TCC_VERSION);
10618 exit(0);
10619 case TCC_OPTION_f:
10620 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10621 goto unsupported_option;
10622 break;
10623 case TCC_OPTION_W:
10624 if (tcc_set_warning(s, optarg, 1) < 0 &&
10625 s->warn_unsupported)
10626 goto unsupported_option;
10627 break;
10628 case TCC_OPTION_w:
10629 s->warn_none = 1;
10630 break;
10631 case TCC_OPTION_rdynamic:
10632 s->rdynamic = 1;
10633 break;
10634 case TCC_OPTION_Wl:
10636 const char *p;
10637 if (strstart(optarg, "-Ttext,", &p)) {
10638 s->text_addr = strtoul(p, NULL, 16);
10639 s->has_text_addr = 1;
10640 } else if (strstart(optarg, "--oformat,", &p)) {
10641 if (strstart(p, "elf32-", NULL)) {
10642 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10643 } else if (!strcmp(p, "binary")) {
10644 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10645 } else
10646 #ifdef TCC_TARGET_COFF
10647 if (!strcmp(p, "coff")) {
10648 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10649 } else
10650 #endif
10652 error("target %s not found", p);
10654 } else {
10655 error("unsupported linker option '%s'", optarg);
10658 break;
10659 case TCC_OPTION_E:
10660 output_type = TCC_OUTPUT_PREPROCESS;
10661 break;
10662 default:
10663 if (s->warn_unsupported) {
10664 unsupported_option:
10665 warning("unsupported option '%s'", r);
10667 break;
10671 return optind;
10674 int main(int argc, char **argv)
10676 int i;
10677 TCCState *s;
10678 int nb_objfiles, ret, optind;
10679 char objfilename[1024];
10680 int64_t start_time = 0;
10682 #ifdef WIN32
10683 /* on win32, we suppose the lib and includes are at the location
10684 of 'tcc.exe' */
10686 static char path[1024];
10687 char *p, *d;
10689 GetModuleFileNameA(NULL, path, sizeof path);
10690 p = d = strlwr(path);
10691 while (*d)
10693 if (*d == '\\') *d = '/', p = d;
10694 ++d;
10696 *p = '\0';
10697 tcc_lib_path = path;
10699 #endif
10701 s = tcc_new();
10702 output_type = TCC_OUTPUT_EXE;
10703 outfile = NULL;
10704 multiple_files = 1;
10705 files = NULL;
10706 nb_files = 0;
10707 nb_libraries = 0;
10708 reloc_output = 0;
10709 print_search_dirs = 0;
10711 optind = parse_args(s, argc - 1, argv + 1) + 1;
10713 if (print_search_dirs) {
10714 /* enough for Linux kernel */
10715 printf("install: %s/\n", tcc_lib_path);
10716 return 0;
10719 nb_objfiles = nb_files - nb_libraries;
10721 /* if outfile provided without other options, we output an
10722 executable */
10723 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10724 output_type = TCC_OUTPUT_EXE;
10726 /* check -c consistency : only single file handled. XXX: checks file type */
10727 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10728 /* accepts only a single input file */
10729 if (nb_objfiles != 1)
10730 error("cannot specify multiple files with -c");
10731 if (nb_libraries != 0)
10732 error("cannot specify libraries with -c");
10736 if (output_type == TCC_OUTPUT_PREPROCESS) {
10737 if (!outfile) {
10738 s->outfile = stdout;
10739 } else {
10740 s->outfile = fopen(outfile, "wb");
10741 if (!s->outfile)
10742 error("could not open '%s", outfile);
10744 } else if (output_type != TCC_OUTPUT_MEMORY) {
10745 if (!outfile) {
10746 /* compute default outfile name */
10747 pstrcpy(objfilename, sizeof(objfilename) - 1,
10748 /* strip path */
10749 tcc_basename(files[0]));
10750 #ifdef TCC_TARGET_PE
10751 pe_guess_outfile(objfilename, output_type);
10752 #else
10753 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10754 char *ext = strrchr(objfilename, '.');
10755 if (!ext)
10756 goto default_outfile;
10757 /* add .o extension */
10758 strcpy(ext + 1, "o");
10759 } else {
10760 default_outfile:
10761 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10763 #endif
10764 outfile = objfilename;
10768 if (do_bench) {
10769 start_time = getclock_us();
10772 tcc_set_output_type(s, output_type);
10774 /* compile or add each files or library */
10775 for(i = 0;i < nb_files; i++) {
10776 const char *filename;
10778 filename = files[i];
10779 if (output_type == TCC_OUTPUT_PREPROCESS) {
10780 tcc_add_file_internal(s, filename,
10781 AFF_PRINT_ERROR | AFF_PREPROCESS);
10782 } else {
10783 if (filename[0] == '-') {
10784 if (tcc_add_library(s, filename + 2) < 0)
10785 error("cannot find %s", filename);
10786 } else {
10787 if (tcc_add_file(s, filename) < 0) {
10788 ret = 1;
10789 goto the_end;
10795 /* free all files */
10796 tcc_free(files);
10798 if (do_bench) {
10799 double total_time;
10800 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10801 if (total_time < 0.001)
10802 total_time = 0.001;
10803 if (total_bytes < 1)
10804 total_bytes = 1;
10805 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10806 tok_ident - TOK_IDENT, total_lines, total_bytes,
10807 total_time, (int)(total_lines / total_time),
10808 total_bytes / total_time / 1000000.0);
10811 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
10812 if (outfile)
10813 fclose(s->outfile);
10814 ret = 0;
10815 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
10816 ret = tcc_run(s, argc - optind, argv + optind);
10817 } else
10818 #ifdef TCC_TARGET_PE
10819 if (s->output_type != TCC_OUTPUT_OBJ) {
10820 ret = tcc_output_pe(s, outfile);
10821 } else
10822 #endif
10824 tcc_output_file(s, outfile);
10825 ret = 0;
10827 the_end:
10828 /* XXX: cannot do it with bound checking because of the malloc hooks */
10829 if (!do_bounds_check)
10830 tcc_delete(s);
10832 #ifdef MEM_DEBUG
10833 if (do_bench) {
10834 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10836 #endif
10837 return ret;
10840 #endif