fixed sign extension in some type conversions (Dave Dodge)
[tinycc.git] / tcc.c
blobf6e3babd518bea02fe0592384de8268c36047606
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 compare_types(CType *type1, CType *type2, int unqualified);
805 static int is_compatible_types(CType *type1, CType *type2);
806 static int is_compatible_parameter_types(CType *type1, CType *type2);
808 int ieee_finite(double d);
809 void error(const char *fmt, ...);
810 void vpushi(int v);
811 void vrott(int n);
812 void vnrott(int n);
813 void lexpand_nr(void);
814 static void vpush_global_sym(CType *type, int v);
815 void vset(CType *type, int r, int v);
816 void type_to_str(char *buf, int buf_size,
817 CType *type, const char *varstr);
818 char *get_tok_str(int v, CValue *cv);
819 static Sym *get_sym_ref(CType *type, Section *sec,
820 unsigned long offset, unsigned long size);
821 static Sym *external_global_sym(int v, CType *type, int r);
823 /* section generation */
824 static void section_realloc(Section *sec, unsigned long new_size);
825 static void *section_ptr_add(Section *sec, unsigned long size);
826 static void put_extern_sym(Sym *sym, Section *section,
827 unsigned long value, unsigned long size);
828 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
829 static int put_elf_str(Section *s, const char *sym);
830 static int put_elf_sym(Section *s,
831 unsigned long value, unsigned long size,
832 int info, int other, int shndx, const char *name);
833 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
834 int info, int other, int sh_num, const char *name);
835 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
836 int type, int symbol);
837 static void put_stabs(const char *str, int type, int other, int desc,
838 unsigned long value);
839 static void put_stabs_r(const char *str, int type, int other, int desc,
840 unsigned long value, Section *sec, int sym_index);
841 static void put_stabn(int type, int other, int desc, int value);
842 static void put_stabd(int type, int other, int desc);
843 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
845 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
846 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
847 #define AFF_PREPROCESS 0x0004 /* preprocess file */
848 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
850 /* tcccoff.c */
851 int tcc_output_coff(TCCState *s1, FILE *f);
853 /* tccpe.c */
854 void *resolve_sym(TCCState *s1, const char *sym, int type);
855 int pe_load_def_file(struct TCCState *s1, FILE *fp);
856 void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
857 unsigned long pe_add_runtime(struct TCCState *s1);
858 int tcc_output_pe(struct TCCState *s1, const char *filename);
860 /* tccasm.c */
862 #ifdef CONFIG_TCC_ASM
864 typedef struct ExprValue {
865 uint32_t v;
866 Sym *sym;
867 } ExprValue;
869 #define MAX_ASM_OPERANDS 30
871 typedef struct ASMOperand {
872 int id; /* GCC 3 optionnal identifier (0 if number only supported */
873 char *constraint;
874 char asm_str[16]; /* computed asm string for operand */
875 SValue *vt; /* C value of the expression */
876 int ref_index; /* if >= 0, gives reference to a output constraint */
877 int input_index; /* if >= 0, gives reference to an input constraint */
878 int priority; /* priority, used to assign registers */
879 int reg; /* if >= 0, register number used for this operand */
880 int is_llong; /* true if double register value */
881 int is_memory; /* true if memory operand */
882 int is_rw; /* for '+' modifier */
883 } ASMOperand;
885 static void asm_expr(TCCState *s1, ExprValue *pe);
886 static int asm_int_expr(TCCState *s1);
887 static int find_constraint(ASMOperand *operands, int nb_operands,
888 const char *name, const char **pp);
890 static int tcc_assemble(TCCState *s1, int do_preprocess);
892 #endif
894 static void asm_instr(void);
895 static void asm_global_instr(void);
897 /* true if float/double/long double type */
898 static inline int is_float(int t)
900 int bt;
901 bt = t & VT_BTYPE;
902 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
905 #ifdef TCC_TARGET_I386
906 #include "i386-gen.c"
907 #endif
909 #ifdef TCC_TARGET_ARM
910 #include "arm-gen.c"
911 #endif
913 #ifdef TCC_TARGET_C67
914 #include "c67-gen.c"
915 #endif
917 #ifdef CONFIG_TCC_STATIC
919 #define RTLD_LAZY 0x001
920 #define RTLD_NOW 0x002
921 #define RTLD_GLOBAL 0x100
922 #define RTLD_DEFAULT NULL
924 /* dummy function for profiling */
925 void *dlopen(const char *filename, int flag)
927 return NULL;
930 const char *dlerror(void)
932 return "error";
935 typedef struct TCCSyms {
936 char *str;
937 void *ptr;
938 } TCCSyms;
940 #define TCCSYM(a) { #a, &a, },
942 /* add the symbol you want here if no dynamic linking is done */
943 static TCCSyms tcc_syms[] = {
944 #if !defined(CONFIG_TCCBOOT)
945 TCCSYM(printf)
946 TCCSYM(fprintf)
947 TCCSYM(fopen)
948 TCCSYM(fclose)
949 #endif
950 { NULL, NULL },
953 void *resolve_sym(TCCState *s1, const char *symbol, int type)
955 TCCSyms *p;
956 p = tcc_syms;
957 while (p->str != NULL) {
958 if (!strcmp(p->str, symbol))
959 return p->ptr;
960 p++;
962 return NULL;
965 #elif !defined(WIN32)
967 #include <dlfcn.h>
969 void *resolve_sym(TCCState *s1, const char *sym, int type)
971 return dlsym(RTLD_DEFAULT, sym);
974 #endif
976 /********************************************************/
978 /* we use our own 'finite' function to avoid potential problems with
979 non standard math libs */
980 /* XXX: endianness dependent */
981 int ieee_finite(double d)
983 int *p = (int *)&d;
984 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
987 /* copy a string and truncate it. */
988 static char *pstrcpy(char *buf, int buf_size, const char *s)
990 char *q, *q_end;
991 int c;
993 if (buf_size > 0) {
994 q = buf;
995 q_end = buf + buf_size - 1;
996 while (q < q_end) {
997 c = *s++;
998 if (c == '\0')
999 break;
1000 *q++ = c;
1002 *q = '\0';
1004 return buf;
1007 /* strcat and truncate. */
1008 static char *pstrcat(char *buf, int buf_size, const char *s)
1010 int len;
1011 len = strlen(buf);
1012 if (len < buf_size)
1013 pstrcpy(buf + len, buf_size - len, s);
1014 return buf;
1017 static int strstart(const char *str, const char *val, const char **ptr)
1019 const char *p, *q;
1020 p = str;
1021 q = val;
1022 while (*q != '\0') {
1023 if (*p != *q)
1024 return 0;
1025 p++;
1026 q++;
1028 if (ptr)
1029 *ptr = p;
1030 return 1;
1033 /* memory management */
1034 #ifdef MEM_DEBUG
1035 int mem_cur_size;
1036 int mem_max_size;
1037 #endif
1039 static inline void tcc_free(void *ptr)
1041 #ifdef MEM_DEBUG
1042 mem_cur_size -= malloc_usable_size(ptr);
1043 #endif
1044 free(ptr);
1047 static void *tcc_malloc(unsigned long size)
1049 void *ptr;
1050 ptr = malloc(size);
1051 if (!ptr && size)
1052 error("memory full");
1053 #ifdef MEM_DEBUG
1054 mem_cur_size += malloc_usable_size(ptr);
1055 if (mem_cur_size > mem_max_size)
1056 mem_max_size = mem_cur_size;
1057 #endif
1058 return ptr;
1061 static void *tcc_mallocz(unsigned long size)
1063 void *ptr;
1064 ptr = tcc_malloc(size);
1065 memset(ptr, 0, size);
1066 return ptr;
1069 static inline void *tcc_realloc(void *ptr, unsigned long size)
1071 void *ptr1;
1072 #ifdef MEM_DEBUG
1073 mem_cur_size -= malloc_usable_size(ptr);
1074 #endif
1075 ptr1 = realloc(ptr, size);
1076 #ifdef MEM_DEBUG
1077 /* NOTE: count not correct if alloc error, but not critical */
1078 mem_cur_size += malloc_usable_size(ptr1);
1079 if (mem_cur_size > mem_max_size)
1080 mem_max_size = mem_cur_size;
1081 #endif
1082 return ptr1;
1085 static char *tcc_strdup(const char *str)
1087 char *ptr;
1088 ptr = tcc_malloc(strlen(str) + 1);
1089 strcpy(ptr, str);
1090 return ptr;
1093 #define free(p) use_tcc_free(p)
1094 #define malloc(s) use_tcc_malloc(s)
1095 #define realloc(p, s) use_tcc_realloc(p, s)
1097 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1099 int nb, nb_alloc;
1100 void **pp;
1102 nb = *nb_ptr;
1103 pp = *ptab;
1104 /* every power of two we double array size */
1105 if ((nb & (nb - 1)) == 0) {
1106 if (!nb)
1107 nb_alloc = 1;
1108 else
1109 nb_alloc = nb * 2;
1110 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1111 if (!pp)
1112 error("memory full");
1113 *ptab = pp;
1115 pp[nb++] = data;
1116 *nb_ptr = nb;
1119 /* symbol allocator */
1120 static Sym *__sym_malloc(void)
1122 Sym *sym_pool, *sym, *last_sym;
1123 int i;
1125 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1127 last_sym = sym_free_first;
1128 sym = sym_pool;
1129 for(i = 0; i < SYM_POOL_NB; i++) {
1130 sym->next = last_sym;
1131 last_sym = sym;
1132 sym++;
1134 sym_free_first = last_sym;
1135 return last_sym;
1138 static inline Sym *sym_malloc(void)
1140 Sym *sym;
1141 sym = sym_free_first;
1142 if (!sym)
1143 sym = __sym_malloc();
1144 sym_free_first = sym->next;
1145 return sym;
1148 static inline void sym_free(Sym *sym)
1150 sym->next = sym_free_first;
1151 sym_free_first = sym;
1154 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1156 Section *sec;
1158 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1159 strcpy(sec->name, name);
1160 sec->sh_type = sh_type;
1161 sec->sh_flags = sh_flags;
1162 switch(sh_type) {
1163 case SHT_HASH:
1164 case SHT_REL:
1165 case SHT_DYNSYM:
1166 case SHT_SYMTAB:
1167 case SHT_DYNAMIC:
1168 sec->sh_addralign = 4;
1169 break;
1170 case SHT_STRTAB:
1171 sec->sh_addralign = 1;
1172 break;
1173 default:
1174 sec->sh_addralign = 32; /* default conservative alignment */
1175 break;
1178 /* only add section if not private */
1179 if (!(sh_flags & SHF_PRIVATE)) {
1180 sec->sh_num = s1->nb_sections;
1181 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1183 return sec;
1186 static void free_section(Section *s)
1188 tcc_free(s->data);
1189 tcc_free(s);
1192 /* realloc section and set its content to zero */
1193 static void section_realloc(Section *sec, unsigned long new_size)
1195 unsigned long size;
1196 unsigned char *data;
1198 size = sec->data_allocated;
1199 if (size == 0)
1200 size = 1;
1201 while (size < new_size)
1202 size = size * 2;
1203 data = tcc_realloc(sec->data, size);
1204 if (!data)
1205 error("memory full");
1206 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1207 sec->data = data;
1208 sec->data_allocated = size;
1211 /* reserve at least 'size' bytes in section 'sec' from
1212 sec->data_offset. */
1213 static void *section_ptr_add(Section *sec, unsigned long size)
1215 unsigned long offset, offset1;
1217 offset = sec->data_offset;
1218 offset1 = offset + size;
1219 if (offset1 > sec->data_allocated)
1220 section_realloc(sec, offset1);
1221 sec->data_offset = offset1;
1222 return sec->data + offset;
1225 /* return a reference to a section, and create it if it does not
1226 exists */
1227 Section *find_section(TCCState *s1, const char *name)
1229 Section *sec;
1230 int i;
1231 for(i = 1; i < s1->nb_sections; i++) {
1232 sec = s1->sections[i];
1233 if (!strcmp(name, sec->name))
1234 return sec;
1236 /* sections are created as PROGBITS */
1237 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1240 #define SECTION_ABS ((void *)1)
1242 /* update sym->c so that it points to an external symbol in section
1243 'section' with value 'value' */
1244 static void put_extern_sym2(Sym *sym, Section *section,
1245 unsigned long value, unsigned long size,
1246 int can_add_underscore)
1248 int sym_type, sym_bind, sh_num, info;
1249 Elf32_Sym *esym;
1250 const char *name;
1251 char buf1[256];
1253 if (section == NULL)
1254 sh_num = SHN_UNDEF;
1255 else if (section == SECTION_ABS)
1256 sh_num = SHN_ABS;
1257 else
1258 sh_num = section->sh_num;
1259 if (!sym->c) {
1260 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1261 sym_type = STT_FUNC;
1262 else
1263 sym_type = STT_OBJECT;
1264 if (sym->type.t & VT_STATIC)
1265 sym_bind = STB_LOCAL;
1266 else
1267 sym_bind = STB_GLOBAL;
1269 name = get_tok_str(sym->v, NULL);
1270 #ifdef CONFIG_TCC_BCHECK
1271 if (do_bounds_check) {
1272 char buf[32];
1274 /* XXX: avoid doing that for statics ? */
1275 /* if bound checking is activated, we change some function
1276 names by adding the "__bound" prefix */
1277 switch(sym->v) {
1278 #if 0
1279 /* XXX: we rely only on malloc hooks */
1280 case TOK_malloc:
1281 case TOK_free:
1282 case TOK_realloc:
1283 case TOK_memalign:
1284 case TOK_calloc:
1285 #endif
1286 case TOK_memcpy:
1287 case TOK_memmove:
1288 case TOK_memset:
1289 case TOK_strlen:
1290 case TOK_strcpy:
1291 strcpy(buf, "__bound_");
1292 strcat(buf, name);
1293 name = buf;
1294 break;
1297 #endif
1298 if (tcc_state->leading_underscore && can_add_underscore) {
1299 buf1[0] = '_';
1300 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1301 name = buf1;
1303 info = ELF32_ST_INFO(sym_bind, sym_type);
1304 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
1305 } else {
1306 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1307 esym->st_value = value;
1308 esym->st_size = size;
1309 esym->st_shndx = sh_num;
1313 static void put_extern_sym(Sym *sym, Section *section,
1314 unsigned long value, unsigned long size)
1316 put_extern_sym2(sym, section, value, size, 1);
1319 /* add a new relocation entry to symbol 'sym' in section 's' */
1320 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1322 if (!sym->c)
1323 put_extern_sym(sym, NULL, 0, 0);
1324 /* now we can add ELF relocation info */
1325 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1328 static inline int isid(int c)
1330 return (c >= 'a' && c <= 'z') ||
1331 (c >= 'A' && c <= 'Z') ||
1332 c == '_';
1335 static inline int isnum(int c)
1337 return c >= '0' && c <= '9';
1340 static inline int isoct(int c)
1342 return c >= '0' && c <= '7';
1345 static inline int toup(int c)
1347 if (c >= 'a' && c <= 'z')
1348 return c - 'a' + 'A';
1349 else
1350 return c;
1353 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1355 int len;
1356 len = strlen(buf);
1357 vsnprintf(buf + len, buf_size - len, fmt, ap);
1360 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1362 va_list ap;
1363 va_start(ap, fmt);
1364 strcat_vprintf(buf, buf_size, fmt, ap);
1365 va_end(ap);
1368 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1370 char buf[2048];
1371 BufferedFile **f;
1373 buf[0] = '\0';
1374 if (file) {
1375 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1376 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1377 (*f)->filename, (*f)->line_num);
1378 if (file->line_num > 0) {
1379 strcat_printf(buf, sizeof(buf),
1380 "%s:%d: ", file->filename, file->line_num);
1381 } else {
1382 strcat_printf(buf, sizeof(buf),
1383 "%s: ", file->filename);
1385 } else {
1386 strcat_printf(buf, sizeof(buf),
1387 "tcc: ");
1389 if (is_warning)
1390 strcat_printf(buf, sizeof(buf), "warning: ");
1391 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1393 if (!s1->error_func) {
1394 /* default case: stderr */
1395 fprintf(stderr, "%s\n", buf);
1396 } else {
1397 s1->error_func(s1->error_opaque, buf);
1399 if (!is_warning || s1->warn_error)
1400 s1->nb_errors++;
1403 #ifdef LIBTCC
1404 void tcc_set_error_func(TCCState *s, void *error_opaque,
1405 void (*error_func)(void *opaque, const char *msg))
1407 s->error_opaque = error_opaque;
1408 s->error_func = error_func;
1410 #endif
1412 /* error without aborting current compilation */
1413 void error_noabort(const char *fmt, ...)
1415 TCCState *s1 = tcc_state;
1416 va_list ap;
1418 va_start(ap, fmt);
1419 error1(s1, 0, fmt, ap);
1420 va_end(ap);
1423 void error(const char *fmt, ...)
1425 TCCState *s1 = tcc_state;
1426 va_list ap;
1428 va_start(ap, fmt);
1429 error1(s1, 0, fmt, ap);
1430 va_end(ap);
1431 /* better than nothing: in some cases, we accept to handle errors */
1432 if (s1->error_set_jmp_enabled) {
1433 longjmp(s1->error_jmp_buf, 1);
1434 } else {
1435 /* XXX: eliminate this someday */
1436 exit(1);
1440 void expect(const char *msg)
1442 error("%s expected", msg);
1445 void warning(const char *fmt, ...)
1447 TCCState *s1 = tcc_state;
1448 va_list ap;
1450 if (s1->warn_none)
1451 return;
1453 va_start(ap, fmt);
1454 error1(s1, 1, fmt, ap);
1455 va_end(ap);
1458 void skip(int c)
1460 if (tok != c)
1461 error("'%c' expected", c);
1462 next();
1465 static void test_lvalue(void)
1467 if (!(vtop->r & VT_LVAL))
1468 expect("lvalue");
1471 /* allocate a new token */
1472 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1474 TokenSym *ts, **ptable;
1475 int i;
1477 if (tok_ident >= SYM_FIRST_ANOM)
1478 error("memory full");
1480 /* expand token table if needed */
1481 i = tok_ident - TOK_IDENT;
1482 if ((i % TOK_ALLOC_INCR) == 0) {
1483 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1484 if (!ptable)
1485 error("memory full");
1486 table_ident = ptable;
1489 ts = tcc_malloc(sizeof(TokenSym) + len);
1490 table_ident[i] = ts;
1491 ts->tok = tok_ident++;
1492 ts->sym_define = NULL;
1493 ts->sym_label = NULL;
1494 ts->sym_struct = NULL;
1495 ts->sym_identifier = NULL;
1496 ts->len = len;
1497 ts->hash_next = NULL;
1498 memcpy(ts->str, str, len);
1499 ts->str[len] = '\0';
1500 *pts = ts;
1501 return ts;
1504 #define TOK_HASH_INIT 1
1505 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1507 /* find a token and add it if not found */
1508 static TokenSym *tok_alloc(const char *str, int len)
1510 TokenSym *ts, **pts;
1511 int i;
1512 unsigned int h;
1514 h = TOK_HASH_INIT;
1515 for(i=0;i<len;i++)
1516 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1517 h &= (TOK_HASH_SIZE - 1);
1519 pts = &hash_ident[h];
1520 for(;;) {
1521 ts = *pts;
1522 if (!ts)
1523 break;
1524 if (ts->len == len && !memcmp(ts->str, str, len))
1525 return ts;
1526 pts = &(ts->hash_next);
1528 return tok_alloc_new(pts, str, len);
1531 /* CString handling */
1533 static void cstr_realloc(CString *cstr, int new_size)
1535 int size;
1536 void *data;
1538 size = cstr->size_allocated;
1539 if (size == 0)
1540 size = 8; /* no need to allocate a too small first string */
1541 while (size < new_size)
1542 size = size * 2;
1543 data = tcc_realloc(cstr->data_allocated, size);
1544 if (!data)
1545 error("memory full");
1546 cstr->data_allocated = data;
1547 cstr->size_allocated = size;
1548 cstr->data = data;
1551 /* add a byte */
1552 static inline void cstr_ccat(CString *cstr, int ch)
1554 int size;
1555 size = cstr->size + 1;
1556 if (size > cstr->size_allocated)
1557 cstr_realloc(cstr, size);
1558 ((unsigned char *)cstr->data)[size - 1] = ch;
1559 cstr->size = size;
1562 static void cstr_cat(CString *cstr, const char *str)
1564 int c;
1565 for(;;) {
1566 c = *str;
1567 if (c == '\0')
1568 break;
1569 cstr_ccat(cstr, c);
1570 str++;
1574 /* add a wide char */
1575 static void cstr_wccat(CString *cstr, int ch)
1577 int size;
1578 size = cstr->size + sizeof(nwchar_t);
1579 if (size > cstr->size_allocated)
1580 cstr_realloc(cstr, size);
1581 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1582 cstr->size = size;
1585 static void cstr_new(CString *cstr)
1587 memset(cstr, 0, sizeof(CString));
1590 /* free string and reset it to NULL */
1591 static void cstr_free(CString *cstr)
1593 tcc_free(cstr->data_allocated);
1594 cstr_new(cstr);
1597 #define cstr_reset(cstr) cstr_free(cstr)
1599 /* XXX: unicode ? */
1600 static void add_char(CString *cstr, int c)
1602 if (c == '\'' || c == '\"' || c == '\\') {
1603 /* XXX: could be more precise if char or string */
1604 cstr_ccat(cstr, '\\');
1606 if (c >= 32 && c <= 126) {
1607 cstr_ccat(cstr, c);
1608 } else {
1609 cstr_ccat(cstr, '\\');
1610 if (c == '\n') {
1611 cstr_ccat(cstr, 'n');
1612 } else {
1613 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1614 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1615 cstr_ccat(cstr, '0' + (c & 7));
1620 /* XXX: buffer overflow */
1621 /* XXX: float tokens */
1622 char *get_tok_str(int v, CValue *cv)
1624 static char buf[STRING_MAX_SIZE + 1];
1625 static CString cstr_buf;
1626 CString *cstr;
1627 unsigned char *q;
1628 char *p;
1629 int i, len;
1631 /* NOTE: to go faster, we give a fixed buffer for small strings */
1632 cstr_reset(&cstr_buf);
1633 cstr_buf.data = buf;
1634 cstr_buf.size_allocated = sizeof(buf);
1635 p = buf;
1637 switch(v) {
1638 case TOK_CINT:
1639 case TOK_CUINT:
1640 /* XXX: not quite exact, but only useful for testing */
1641 sprintf(p, "%u", cv->ui);
1642 break;
1643 case TOK_CLLONG:
1644 case TOK_CULLONG:
1645 /* XXX: not quite exact, but only useful for testing */
1646 sprintf(p, "%Lu", cv->ull);
1647 break;
1648 case TOK_CCHAR:
1649 case TOK_LCHAR:
1650 cstr_ccat(&cstr_buf, '\'');
1651 add_char(&cstr_buf, cv->i);
1652 cstr_ccat(&cstr_buf, '\'');
1653 cstr_ccat(&cstr_buf, '\0');
1654 break;
1655 case TOK_PPNUM:
1656 cstr = cv->cstr;
1657 len = cstr->size - 1;
1658 for(i=0;i<len;i++)
1659 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1660 cstr_ccat(&cstr_buf, '\0');
1661 break;
1662 case TOK_STR:
1663 case TOK_LSTR:
1664 cstr = cv->cstr;
1665 cstr_ccat(&cstr_buf, '\"');
1666 if (v == TOK_STR) {
1667 len = cstr->size - 1;
1668 for(i=0;i<len;i++)
1669 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1670 } else {
1671 len = (cstr->size / sizeof(nwchar_t)) - 1;
1672 for(i=0;i<len;i++)
1673 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1675 cstr_ccat(&cstr_buf, '\"');
1676 cstr_ccat(&cstr_buf, '\0');
1677 break;
1678 case TOK_LT:
1679 v = '<';
1680 goto addv;
1681 case TOK_GT:
1682 v = '>';
1683 goto addv;
1684 case TOK_DOTS:
1685 return strcpy(p, "...");
1686 case TOK_A_SHL:
1687 return strcpy(p, "<<=");
1688 case TOK_A_SAR:
1689 return strcpy(p, ">>=");
1690 default:
1691 if (v < TOK_IDENT) {
1692 /* search in two bytes table */
1693 q = tok_two_chars;
1694 while (*q) {
1695 if (q[2] == v) {
1696 *p++ = q[0];
1697 *p++ = q[1];
1698 *p = '\0';
1699 return buf;
1701 q += 3;
1703 addv:
1704 *p++ = v;
1705 *p = '\0';
1706 } else if (v < tok_ident) {
1707 return table_ident[v - TOK_IDENT]->str;
1708 } else if (v >= SYM_FIRST_ANOM) {
1709 /* special name for anonymous symbol */
1710 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1711 } else {
1712 /* should never happen */
1713 return NULL;
1715 break;
1717 return cstr_buf.data;
1720 /* push, without hashing */
1721 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1723 Sym *s;
1724 s = sym_malloc();
1725 s->v = v;
1726 s->type.t = t;
1727 s->c = c;
1728 s->next = NULL;
1729 /* add in stack */
1730 s->prev = *ps;
1731 *ps = s;
1732 return s;
1735 /* find a symbol and return its associated structure. 's' is the top
1736 of the symbol stack */
1737 static Sym *sym_find2(Sym *s, int v)
1739 while (s) {
1740 if (s->v == v)
1741 return s;
1742 s = s->prev;
1744 return NULL;
1747 /* structure lookup */
1748 static inline Sym *struct_find(int v)
1750 v -= TOK_IDENT;
1751 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1752 return NULL;
1753 return table_ident[v]->sym_struct;
1756 /* find an identifier */
1757 static inline Sym *sym_find(int v)
1759 v -= TOK_IDENT;
1760 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1761 return NULL;
1762 return table_ident[v]->sym_identifier;
1765 /* push a given symbol on the symbol stack */
1766 static Sym *sym_push(int v, CType *type, int r, int c)
1768 Sym *s, **ps;
1769 TokenSym *ts;
1771 if (local_stack)
1772 ps = &local_stack;
1773 else
1774 ps = &global_stack;
1775 s = sym_push2(ps, v, type->t, c);
1776 s->type.ref = type->ref;
1777 s->r = r;
1778 /* don't record fields or anonymous symbols */
1779 /* XXX: simplify */
1780 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1781 /* record symbol in token array */
1782 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1783 if (v & SYM_STRUCT)
1784 ps = &ts->sym_struct;
1785 else
1786 ps = &ts->sym_identifier;
1787 s->prev_tok = *ps;
1788 *ps = s;
1790 return s;
1793 /* push a global identifier */
1794 static Sym *global_identifier_push(int v, int t, int c)
1796 Sym *s, **ps;
1797 s = sym_push2(&global_stack, v, t, c);
1798 /* don't record anonymous symbol */
1799 if (v < SYM_FIRST_ANOM) {
1800 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1801 /* modify the top most local identifier, so that
1802 sym_identifier will point to 's' when popped */
1803 while (*ps != NULL)
1804 ps = &(*ps)->prev_tok;
1805 s->prev_tok = NULL;
1806 *ps = s;
1808 return s;
1811 /* pop symbols until top reaches 'b' */
1812 static void sym_pop(Sym **ptop, Sym *b)
1814 Sym *s, *ss, **ps;
1815 TokenSym *ts;
1816 int v;
1818 s = *ptop;
1819 while(s != b) {
1820 ss = s->prev;
1821 v = s->v;
1822 /* remove symbol in token array */
1823 /* XXX: simplify */
1824 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1825 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1826 if (v & SYM_STRUCT)
1827 ps = &ts->sym_struct;
1828 else
1829 ps = &ts->sym_identifier;
1830 *ps = s->prev_tok;
1832 sym_free(s);
1833 s = ss;
1835 *ptop = b;
1838 /* I/O layer */
1840 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1842 int fd;
1843 BufferedFile *bf;
1844 int i, len;
1846 fd = open(filename, O_RDONLY | O_BINARY);
1847 if (fd < 0)
1848 return NULL;
1849 bf = tcc_malloc(sizeof(BufferedFile));
1850 if (!bf) {
1851 close(fd);
1852 return NULL;
1854 bf->fd = fd;
1855 bf->buf_ptr = bf->buffer;
1856 bf->buf_end = bf->buffer;
1857 bf->buffer[0] = CH_EOB; /* put eob symbol */
1858 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1859 len = strlen(bf->filename);
1860 for (i = 0; i < len; i++)
1861 if (bf->filename[i] == '\\')
1862 bf->filename[i] = '/';
1863 bf->line_num = 1;
1864 bf->ifndef_macro = 0;
1865 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1866 // printf("opening '%s'\n", filename);
1867 return bf;
1870 void tcc_close(BufferedFile *bf)
1872 total_lines += bf->line_num;
1873 close(bf->fd);
1874 tcc_free(bf);
1877 /* fill input buffer and peek next char */
1878 static int tcc_peekc_slow(BufferedFile *bf)
1880 int len;
1881 /* only tries to read if really end of buffer */
1882 if (bf->buf_ptr >= bf->buf_end) {
1883 if (bf->fd != -1) {
1884 #if defined(PARSE_DEBUG)
1885 len = 8;
1886 #else
1887 len = IO_BUF_SIZE;
1888 #endif
1889 len = read(bf->fd, bf->buffer, len);
1890 if (len < 0)
1891 len = 0;
1892 } else {
1893 len = 0;
1895 total_bytes += len;
1896 bf->buf_ptr = bf->buffer;
1897 bf->buf_end = bf->buffer + len;
1898 *bf->buf_end = CH_EOB;
1900 if (bf->buf_ptr < bf->buf_end) {
1901 return bf->buf_ptr[0];
1902 } else {
1903 bf->buf_ptr = bf->buf_end;
1904 return CH_EOF;
1908 /* return the current character, handling end of block if necessary
1909 (but not stray) */
1910 static int handle_eob(void)
1912 return tcc_peekc_slow(file);
1915 /* read next char from current input file and handle end of input buffer */
1916 static inline void inp(void)
1918 ch = *(++(file->buf_ptr));
1919 /* end of buffer/file handling */
1920 if (ch == CH_EOB)
1921 ch = handle_eob();
1924 /* handle '\[\r]\n' */
1925 static void handle_stray(void)
1927 while (ch == '\\') {
1928 inp();
1929 if (ch == '\n') {
1930 file->line_num++;
1931 inp();
1932 } else if (ch == '\r') {
1933 inp();
1934 if (ch != '\n')
1935 goto fail;
1936 file->line_num++;
1937 inp();
1938 } else {
1939 fail:
1940 error("stray '\\' in program");
1945 /* skip the stray and handle the \\n case. Output an error if
1946 incorrect char after the stray */
1947 static int handle_stray1(uint8_t *p)
1949 int c;
1951 if (p >= file->buf_end) {
1952 file->buf_ptr = p;
1953 c = handle_eob();
1954 p = file->buf_ptr;
1955 if (c == '\\')
1956 goto parse_stray;
1957 } else {
1958 parse_stray:
1959 file->buf_ptr = p;
1960 ch = *p;
1961 handle_stray();
1962 p = file->buf_ptr;
1963 c = *p;
1965 return c;
1968 /* handle just the EOB case, but not stray */
1969 #define PEEKC_EOB(c, p)\
1971 p++;\
1972 c = *p;\
1973 if (c == '\\') {\
1974 file->buf_ptr = p;\
1975 c = handle_eob();\
1976 p = file->buf_ptr;\
1980 /* handle the complicated stray case */
1981 #define PEEKC(c, p)\
1983 p++;\
1984 c = *p;\
1985 if (c == '\\') {\
1986 c = handle_stray1(p);\
1987 p = file->buf_ptr;\
1991 /* input with '\[\r]\n' handling. Note that this function cannot
1992 handle other characters after '\', so you cannot call it inside
1993 strings or comments */
1994 static void minp(void)
1996 inp();
1997 if (ch == '\\')
1998 handle_stray();
2002 /* single line C++ comments */
2003 static uint8_t *parse_line_comment(uint8_t *p)
2005 int c;
2007 p++;
2008 for(;;) {
2009 c = *p;
2010 redo:
2011 if (c == '\n' || c == CH_EOF) {
2012 break;
2013 } else if (c == '\\') {
2014 file->buf_ptr = p;
2015 c = handle_eob();
2016 p = file->buf_ptr;
2017 if (c == '\\') {
2018 PEEKC_EOB(c, p);
2019 if (c == '\n') {
2020 file->line_num++;
2021 PEEKC_EOB(c, p);
2022 } else if (c == '\r') {
2023 PEEKC_EOB(c, p);
2024 if (c == '\n') {
2025 file->line_num++;
2026 PEEKC_EOB(c, p);
2029 } else {
2030 goto redo;
2032 } else {
2033 p++;
2036 return p;
2039 /* C comments */
2040 static uint8_t *parse_comment(uint8_t *p)
2042 int c;
2044 p++;
2045 for(;;) {
2046 /* fast skip loop */
2047 for(;;) {
2048 c = *p;
2049 if (c == '\n' || c == '*' || c == '\\')
2050 break;
2051 p++;
2052 c = *p;
2053 if (c == '\n' || c == '*' || c == '\\')
2054 break;
2055 p++;
2057 /* now we can handle all the cases */
2058 if (c == '\n') {
2059 file->line_num++;
2060 p++;
2061 } else if (c == '*') {
2062 p++;
2063 for(;;) {
2064 c = *p;
2065 if (c == '*') {
2066 p++;
2067 } else if (c == '/') {
2068 goto end_of_comment;
2069 } else if (c == '\\') {
2070 file->buf_ptr = p;
2071 c = handle_eob();
2072 p = file->buf_ptr;
2073 if (c == '\\') {
2074 /* skip '\[\r]\n', otherwise just skip the stray */
2075 while (c == '\\') {
2076 PEEKC_EOB(c, p);
2077 if (c == '\n') {
2078 file->line_num++;
2079 PEEKC_EOB(c, p);
2080 } else if (c == '\r') {
2081 PEEKC_EOB(c, p);
2082 if (c == '\n') {
2083 file->line_num++;
2084 PEEKC_EOB(c, p);
2086 } else {
2087 goto after_star;
2091 } else {
2092 break;
2095 after_star: ;
2096 } else {
2097 /* stray, eob or eof */
2098 file->buf_ptr = p;
2099 c = handle_eob();
2100 p = file->buf_ptr;
2101 if (c == CH_EOF) {
2102 error("unexpected end of file in comment");
2103 } else if (c == '\\') {
2104 p++;
2108 end_of_comment:
2109 p++;
2110 return p;
2113 #define cinp minp
2115 /* space exlcuding newline */
2116 static inline int is_space(int ch)
2118 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2121 static inline void skip_spaces(void)
2123 while (is_space(ch))
2124 cinp();
2127 /* parse a string without interpreting escapes */
2128 static uint8_t *parse_pp_string(uint8_t *p,
2129 int sep, CString *str)
2131 int c;
2132 p++;
2133 for(;;) {
2134 c = *p;
2135 if (c == sep) {
2136 break;
2137 } else if (c == '\\') {
2138 file->buf_ptr = p;
2139 c = handle_eob();
2140 p = file->buf_ptr;
2141 if (c == CH_EOF) {
2142 unterminated_string:
2143 /* XXX: indicate line number of start of string */
2144 error("missing terminating %c character", sep);
2145 } else if (c == '\\') {
2146 /* escape : just skip \[\r]\n */
2147 PEEKC_EOB(c, p);
2148 if (c == '\n') {
2149 file->line_num++;
2150 p++;
2151 } else if (c == '\r') {
2152 PEEKC_EOB(c, p);
2153 if (c != '\n')
2154 expect("'\n' after '\r'");
2155 file->line_num++;
2156 p++;
2157 } else if (c == CH_EOF) {
2158 goto unterminated_string;
2159 } else {
2160 if (str) {
2161 cstr_ccat(str, '\\');
2162 cstr_ccat(str, c);
2164 p++;
2167 } else if (c == '\n') {
2168 file->line_num++;
2169 goto add_char;
2170 } else if (c == '\r') {
2171 PEEKC_EOB(c, p);
2172 if (c != '\n') {
2173 if (str)
2174 cstr_ccat(str, '\r');
2175 } else {
2176 file->line_num++;
2177 goto add_char;
2179 } else {
2180 add_char:
2181 if (str)
2182 cstr_ccat(str, c);
2183 p++;
2186 p++;
2187 return p;
2190 /* skip block of text until #else, #elif or #endif. skip also pairs of
2191 #if/#endif */
2192 void preprocess_skip(void)
2194 int a, start_of_line, c;
2195 uint8_t *p;
2197 p = file->buf_ptr;
2198 start_of_line = 1;
2199 a = 0;
2200 for(;;) {
2201 redo_no_start:
2202 c = *p;
2203 switch(c) {
2204 case ' ':
2205 case '\t':
2206 case '\f':
2207 case '\v':
2208 case '\r':
2209 p++;
2210 goto redo_no_start;
2211 case '\n':
2212 start_of_line = 1;
2213 file->line_num++;
2214 p++;
2215 goto redo_no_start;
2216 case '\\':
2217 file->buf_ptr = p;
2218 c = handle_eob();
2219 if (c == CH_EOF) {
2220 expect("#endif");
2221 } else if (c == '\\') {
2222 /* XXX: incorrect: should not give an error */
2223 ch = file->buf_ptr[0];
2224 handle_stray();
2226 p = file->buf_ptr;
2227 goto redo_no_start;
2228 /* skip strings */
2229 case '\"':
2230 case '\'':
2231 p = parse_pp_string(p, c, NULL);
2232 break;
2233 /* skip comments */
2234 case '/':
2235 file->buf_ptr = p;
2236 ch = *p;
2237 minp();
2238 p = file->buf_ptr;
2239 if (ch == '*') {
2240 p = parse_comment(p);
2241 } else if (ch == '/') {
2242 p = parse_line_comment(p);
2244 break;
2246 case '#':
2247 p++;
2248 if (start_of_line) {
2249 file->buf_ptr = p;
2250 next_nomacro();
2251 p = file->buf_ptr;
2252 if (a == 0 &&
2253 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2254 goto the_end;
2255 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2256 a++;
2257 else if (tok == TOK_ENDIF)
2258 a--;
2260 break;
2261 default:
2262 p++;
2263 break;
2265 start_of_line = 0;
2267 the_end: ;
2268 file->buf_ptr = p;
2271 /* ParseState handling */
2273 /* XXX: currently, no include file info is stored. Thus, we cannot display
2274 accurate messages if the function or data definition spans multiple
2275 files */
2277 /* save current parse state in 's' */
2278 void save_parse_state(ParseState *s)
2280 s->line_num = file->line_num;
2281 s->macro_ptr = macro_ptr;
2282 s->tok = tok;
2283 s->tokc = tokc;
2286 /* restore parse state from 's' */
2287 void restore_parse_state(ParseState *s)
2289 file->line_num = s->line_num;
2290 macro_ptr = s->macro_ptr;
2291 tok = s->tok;
2292 tokc = s->tokc;
2295 /* return the number of additional 'ints' necessary to store the
2296 token */
2297 static inline int tok_ext_size(int t)
2299 switch(t) {
2300 /* 4 bytes */
2301 case TOK_CINT:
2302 case TOK_CUINT:
2303 case TOK_CCHAR:
2304 case TOK_LCHAR:
2305 case TOK_CFLOAT:
2306 case TOK_LINENUM:
2307 return 1;
2308 case TOK_STR:
2309 case TOK_LSTR:
2310 case TOK_PPNUM:
2311 error("unsupported token");
2312 return 1;
2313 case TOK_CDOUBLE:
2314 case TOK_CLLONG:
2315 case TOK_CULLONG:
2316 return 2;
2317 case TOK_CLDOUBLE:
2318 return LDOUBLE_SIZE / 4;
2319 default:
2320 return 0;
2324 /* token string handling */
2326 static inline void tok_str_new(TokenString *s)
2328 s->str = NULL;
2329 s->len = 0;
2330 s->allocated_len = 0;
2331 s->last_line_num = -1;
2334 static void tok_str_free(int *str)
2336 tcc_free(str);
2339 static int *tok_str_realloc(TokenString *s)
2341 int *str, len;
2343 if (s->allocated_len == 0) {
2344 len = 8;
2345 } else {
2346 len = s->allocated_len * 2;
2348 str = tcc_realloc(s->str, len * sizeof(int));
2349 if (!str)
2350 error("memory full");
2351 s->allocated_len = len;
2352 s->str = str;
2353 return str;
2356 static void tok_str_add(TokenString *s, int t)
2358 int len, *str;
2360 len = s->len;
2361 str = s->str;
2362 if (len >= s->allocated_len)
2363 str = tok_str_realloc(s);
2364 str[len++] = t;
2365 s->len = len;
2368 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2370 int len, *str;
2372 len = s->len;
2373 str = s->str;
2375 /* allocate space for worst case */
2376 if (len + TOK_MAX_SIZE > s->allocated_len)
2377 str = tok_str_realloc(s);
2378 str[len++] = t;
2379 switch(t) {
2380 case TOK_CINT:
2381 case TOK_CUINT:
2382 case TOK_CCHAR:
2383 case TOK_LCHAR:
2384 case TOK_CFLOAT:
2385 case TOK_LINENUM:
2386 str[len++] = cv->tab[0];
2387 break;
2388 case TOK_PPNUM:
2389 case TOK_STR:
2390 case TOK_LSTR:
2392 int nb_words;
2393 CString *cstr;
2395 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2396 while ((len + nb_words) > s->allocated_len)
2397 str = tok_str_realloc(s);
2398 cstr = (CString *)(str + len);
2399 cstr->data = NULL;
2400 cstr->size = cv->cstr->size;
2401 cstr->data_allocated = NULL;
2402 cstr->size_allocated = cstr->size;
2403 memcpy((char *)cstr + sizeof(CString),
2404 cv->cstr->data, cstr->size);
2405 len += nb_words;
2407 break;
2408 case TOK_CDOUBLE:
2409 case TOK_CLLONG:
2410 case TOK_CULLONG:
2411 #if LDOUBLE_SIZE == 8
2412 case TOK_CLDOUBLE:
2413 #endif
2414 str[len++] = cv->tab[0];
2415 str[len++] = cv->tab[1];
2416 break;
2417 #if LDOUBLE_SIZE == 12
2418 case TOK_CLDOUBLE:
2419 str[len++] = cv->tab[0];
2420 str[len++] = cv->tab[1];
2421 str[len++] = cv->tab[2];
2422 #elif LDOUBLE_SIZE != 8
2423 #error add long double size support
2424 #endif
2425 break;
2426 default:
2427 break;
2429 s->len = len;
2432 /* add the current parse token in token string 's' */
2433 static void tok_str_add_tok(TokenString *s)
2435 CValue cval;
2437 /* save line number info */
2438 if (file->line_num != s->last_line_num) {
2439 s->last_line_num = file->line_num;
2440 cval.i = s->last_line_num;
2441 tok_str_add2(s, TOK_LINENUM, &cval);
2443 tok_str_add2(s, tok, &tokc);
2446 #if LDOUBLE_SIZE == 12
2447 #define LDOUBLE_GET(p, cv) \
2448 cv.tab[0] = p[0]; \
2449 cv.tab[1] = p[1]; \
2450 cv.tab[2] = p[2];
2451 #elif LDOUBLE_SIZE == 8
2452 #define LDOUBLE_GET(p, cv) \
2453 cv.tab[0] = p[0]; \
2454 cv.tab[1] = p[1];
2455 #else
2456 #error add long double size support
2457 #endif
2460 /* get a token from an integer array and increment pointer
2461 accordingly. we code it as a macro to avoid pointer aliasing. */
2462 #define TOK_GET(t, p, cv) \
2464 t = *p++; \
2465 switch(t) { \
2466 case TOK_CINT: \
2467 case TOK_CUINT: \
2468 case TOK_CCHAR: \
2469 case TOK_LCHAR: \
2470 case TOK_CFLOAT: \
2471 case TOK_LINENUM: \
2472 cv.tab[0] = *p++; \
2473 break; \
2474 case TOK_STR: \
2475 case TOK_LSTR: \
2476 case TOK_PPNUM: \
2477 cv.cstr = (CString *)p; \
2478 cv.cstr->data = (char *)p + sizeof(CString);\
2479 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2480 break; \
2481 case TOK_CDOUBLE: \
2482 case TOK_CLLONG: \
2483 case TOK_CULLONG: \
2484 cv.tab[0] = p[0]; \
2485 cv.tab[1] = p[1]; \
2486 p += 2; \
2487 break; \
2488 case TOK_CLDOUBLE: \
2489 LDOUBLE_GET(p, cv); \
2490 p += LDOUBLE_SIZE / 4; \
2491 break; \
2492 default: \
2493 break; \
2497 /* defines handling */
2498 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2500 Sym *s;
2502 s = sym_push2(&define_stack, v, macro_type, (int)str);
2503 s->next = first_arg;
2504 table_ident[v - TOK_IDENT]->sym_define = s;
2507 /* undefined a define symbol. Its name is just set to zero */
2508 static void define_undef(Sym *s)
2510 int v;
2511 v = s->v;
2512 if (v >= TOK_IDENT && v < tok_ident)
2513 table_ident[v - TOK_IDENT]->sym_define = NULL;
2514 s->v = 0;
2517 static inline Sym *define_find(int v)
2519 v -= TOK_IDENT;
2520 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2521 return NULL;
2522 return table_ident[v]->sym_define;
2525 /* free define stack until top reaches 'b' */
2526 static void free_defines(Sym *b)
2528 Sym *top, *top1;
2529 int v;
2531 top = define_stack;
2532 while (top != b) {
2533 top1 = top->prev;
2534 /* do not free args or predefined defines */
2535 if (top->c)
2536 tok_str_free((int *)top->c);
2537 v = top->v;
2538 if (v >= TOK_IDENT && v < tok_ident)
2539 table_ident[v - TOK_IDENT]->sym_define = NULL;
2540 sym_free(top);
2541 top = top1;
2543 define_stack = b;
2546 /* label lookup */
2547 static Sym *label_find(int v)
2549 v -= TOK_IDENT;
2550 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2551 return NULL;
2552 return table_ident[v]->sym_label;
2555 static Sym *label_push(Sym **ptop, int v, int flags)
2557 Sym *s, **ps;
2558 s = sym_push2(ptop, v, 0, 0);
2559 s->r = flags;
2560 ps = &table_ident[v - TOK_IDENT]->sym_label;
2561 if (ptop == &global_label_stack) {
2562 /* modify the top most local identifier, so that
2563 sym_identifier will point to 's' when popped */
2564 while (*ps != NULL)
2565 ps = &(*ps)->prev_tok;
2567 s->prev_tok = *ps;
2568 *ps = s;
2569 return s;
2572 /* pop labels until element last is reached. Look if any labels are
2573 undefined. Define symbols if '&&label' was used. */
2574 static void label_pop(Sym **ptop, Sym *slast)
2576 Sym *s, *s1;
2577 for(s = *ptop; s != slast; s = s1) {
2578 s1 = s->prev;
2579 if (s->r == LABEL_DECLARED) {
2580 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2581 } else if (s->r == LABEL_FORWARD) {
2582 error("label '%s' used but not defined",
2583 get_tok_str(s->v, NULL));
2584 } else {
2585 if (s->c) {
2586 /* define corresponding symbol. A size of
2587 1 is put. */
2588 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2591 /* remove label */
2592 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2593 sym_free(s);
2595 *ptop = slast;
2598 /* eval an expression for #if/#elif */
2599 static int expr_preprocess(void)
2601 int c, t;
2602 TokenString str;
2604 tok_str_new(&str);
2605 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2606 next(); /* do macro subst */
2607 if (tok == TOK_DEFINED) {
2608 next_nomacro();
2609 t = tok;
2610 if (t == '(')
2611 next_nomacro();
2612 c = define_find(tok) != 0;
2613 if (t == '(')
2614 next_nomacro();
2615 tok = TOK_CINT;
2616 tokc.i = c;
2617 } else if (tok >= TOK_IDENT) {
2618 /* if undefined macro */
2619 tok = TOK_CINT;
2620 tokc.i = 0;
2622 tok_str_add_tok(&str);
2624 tok_str_add(&str, -1); /* simulate end of file */
2625 tok_str_add(&str, 0);
2626 /* now evaluate C constant expression */
2627 macro_ptr = str.str;
2628 next();
2629 c = expr_const();
2630 macro_ptr = NULL;
2631 tok_str_free(str.str);
2632 return c != 0;
2635 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2636 static void tok_print(int *str)
2638 int t;
2639 CValue cval;
2641 while (1) {
2642 TOK_GET(t, str, cval);
2643 if (!t)
2644 break;
2645 printf(" %s", get_tok_str(t, &cval));
2647 printf("\n");
2649 #endif
2651 /* parse after #define */
2652 static void parse_define(void)
2654 Sym *s, *first, **ps;
2655 int v, t, varg, is_vaargs, c;
2656 TokenString str;
2658 v = tok;
2659 if (v < TOK_IDENT)
2660 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2661 /* XXX: should check if same macro (ANSI) */
2662 first = NULL;
2663 t = MACRO_OBJ;
2664 /* '(' must be just after macro definition for MACRO_FUNC */
2665 c = file->buf_ptr[0];
2666 if (c == '\\')
2667 c = handle_stray1(file->buf_ptr);
2668 if (c == '(') {
2669 next_nomacro();
2670 next_nomacro();
2671 ps = &first;
2672 while (tok != ')') {
2673 varg = tok;
2674 next_nomacro();
2675 is_vaargs = 0;
2676 if (varg == TOK_DOTS) {
2677 varg = TOK___VA_ARGS__;
2678 is_vaargs = 1;
2679 } else if (tok == TOK_DOTS && gnu_ext) {
2680 is_vaargs = 1;
2681 next_nomacro();
2683 if (varg < TOK_IDENT)
2684 error("badly punctuated parameter list");
2685 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2686 *ps = s;
2687 ps = &s->next;
2688 if (tok != ',')
2689 break;
2690 next_nomacro();
2692 t = MACRO_FUNC;
2694 tok_str_new(&str);
2695 next_nomacro();
2696 /* EOF testing necessary for '-D' handling */
2697 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2698 tok_str_add2(&str, tok, &tokc);
2699 next_nomacro();
2701 tok_str_add(&str, 0);
2702 #ifdef PP_DEBUG
2703 printf("define %s %d: ", get_tok_str(v, NULL), t);
2704 tok_print(str.str);
2705 #endif
2706 define_push(v, t, str.str, first);
2709 static inline int hash_cached_include(int type, const char *filename)
2711 const unsigned char *s;
2712 unsigned int h;
2714 h = TOK_HASH_INIT;
2715 h = TOK_HASH_FUNC(h, type);
2716 s = filename;
2717 while (*s) {
2718 h = TOK_HASH_FUNC(h, *s);
2719 s++;
2721 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2722 return h;
2725 /* XXX: use a token or a hash table to accelerate matching ? */
2726 static CachedInclude *search_cached_include(TCCState *s1,
2727 int type, const char *filename)
2729 CachedInclude *e;
2730 int i, h;
2731 h = hash_cached_include(type, filename);
2732 i = s1->cached_includes_hash[h];
2733 for(;;) {
2734 if (i == 0)
2735 break;
2736 e = s1->cached_includes[i - 1];
2737 if (e->type == type && !strcmp(e->filename, filename))
2738 return e;
2739 i = e->hash_next;
2741 return NULL;
2744 static inline void add_cached_include(TCCState *s1, int type,
2745 const char *filename, int ifndef_macro)
2747 CachedInclude *e;
2748 int h;
2750 if (search_cached_include(s1, type, filename))
2751 return;
2752 #ifdef INC_DEBUG
2753 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2754 #endif
2755 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2756 if (!e)
2757 return;
2758 e->type = type;
2759 strcpy(e->filename, filename);
2760 e->ifndef_macro = ifndef_macro;
2761 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2762 /* add in hash table */
2763 h = hash_cached_include(type, filename);
2764 e->hash_next = s1->cached_includes_hash[h];
2765 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2768 static void pragma_parse(TCCState *s1)
2770 int val;
2772 next();
2773 if (tok == TOK_pack) {
2775 This may be:
2776 #pragma pack(1) // set
2777 #pragma pack() // reset to default
2778 #pragma pack(push,1) // push & set
2779 #pragma pack(pop) // restore previous
2781 next();
2782 skip('(');
2783 if (tok == TOK_ASM_pop) {
2784 next();
2785 if (s1->pack_stack_ptr <= s1->pack_stack) {
2786 stk_error:
2787 error("out of pack stack");
2789 s1->pack_stack_ptr--;
2790 } else {
2791 val = 0;
2792 if (tok != ')') {
2793 if (tok == TOK_ASM_push) {
2794 next();
2795 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2796 goto stk_error;
2797 s1->pack_stack_ptr++;
2798 skip(',');
2800 if (tok != TOK_CINT) {
2801 pack_error:
2802 error("invalid pack pragma");
2804 val = tokc.i;
2805 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2806 goto pack_error;
2807 next();
2809 *s1->pack_stack_ptr = val;
2810 skip(')');
2815 /* is_bof is true if first non space token at beginning of file */
2816 static void preprocess(int is_bof)
2818 TCCState *s1 = tcc_state;
2819 int size, i, c, n, saved_parse_flags;
2820 char buf[1024], *q, *p;
2821 char buf1[1024];
2822 BufferedFile *f;
2823 Sym *s;
2824 CachedInclude *e;
2826 saved_parse_flags = parse_flags;
2827 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2828 PARSE_FLAG_LINEFEED;
2829 next_nomacro();
2830 redo:
2831 switch(tok) {
2832 case TOK_DEFINE:
2833 next_nomacro();
2834 parse_define();
2835 break;
2836 case TOK_UNDEF:
2837 next_nomacro();
2838 s = define_find(tok);
2839 /* undefine symbol by putting an invalid name */
2840 if (s)
2841 define_undef(s);
2842 break;
2843 case TOK_INCLUDE:
2844 case TOK_INCLUDE_NEXT:
2845 ch = file->buf_ptr[0];
2846 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2847 skip_spaces();
2848 if (ch == '<') {
2849 c = '>';
2850 goto read_name;
2851 } else if (ch == '\"') {
2852 c = ch;
2853 read_name:
2854 /* XXX: better stray handling */
2855 minp();
2856 q = buf;
2857 while (ch != c && ch != '\n' && ch != CH_EOF) {
2858 if ((q - buf) < sizeof(buf) - 1)
2859 *q++ = ch;
2860 minp();
2862 *q = '\0';
2863 minp();
2864 #if 0
2865 /* eat all spaces and comments after include */
2866 /* XXX: slightly incorrect */
2867 while (ch1 != '\n' && ch1 != CH_EOF)
2868 inp();
2869 #endif
2870 } else {
2871 /* computed #include : either we have only strings or
2872 we have anything enclosed in '<>' */
2873 next();
2874 buf[0] = '\0';
2875 if (tok == TOK_STR) {
2876 while (tok != TOK_LINEFEED) {
2877 if (tok != TOK_STR) {
2878 include_syntax:
2879 error("'#include' expects \"FILENAME\" or <FILENAME>");
2881 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2882 next();
2884 c = '\"';
2885 } else {
2886 int len;
2887 while (tok != TOK_LINEFEED) {
2888 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2889 next();
2891 len = strlen(buf);
2892 /* check syntax and remove '<>' */
2893 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2894 goto include_syntax;
2895 memmove(buf, buf + 1, len - 2);
2896 buf[len - 2] = '\0';
2897 c = '>';
2901 e = search_cached_include(s1, c, buf);
2902 if (e && define_find(e->ifndef_macro)) {
2903 /* no need to parse the include because the 'ifndef macro'
2904 is defined */
2905 #ifdef INC_DEBUG
2906 printf("%s: skipping %s\n", file->filename, buf);
2907 #endif
2908 } else {
2909 if (c == '\"') {
2910 /* first search in current dir if "header.h" */
2911 size = 0;
2912 p = strrchr(file->filename, '/');
2913 if (p)
2914 size = p + 1 - file->filename;
2915 if (size > sizeof(buf1) - 1)
2916 size = sizeof(buf1) - 1;
2917 memcpy(buf1, file->filename, size);
2918 buf1[size] = '\0';
2919 pstrcat(buf1, sizeof(buf1), buf);
2920 f = tcc_open(s1, buf1);
2921 if (f) {
2922 if (tok == TOK_INCLUDE_NEXT)
2923 tok = TOK_INCLUDE;
2924 else
2925 goto found;
2928 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2929 error("#include recursion too deep");
2930 /* now search in all the include paths */
2931 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2932 for(i = 0; i < n; i++) {
2933 const char *path;
2934 if (i < s1->nb_include_paths)
2935 path = s1->include_paths[i];
2936 else
2937 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2938 pstrcpy(buf1, sizeof(buf1), path);
2939 pstrcat(buf1, sizeof(buf1), "/");
2940 pstrcat(buf1, sizeof(buf1), buf);
2941 f = tcc_open(s1, buf1);
2942 if (f) {
2943 if (tok == TOK_INCLUDE_NEXT)
2944 tok = TOK_INCLUDE;
2945 else
2946 goto found;
2949 error("include file '%s' not found", buf);
2950 f = NULL;
2951 found:
2952 #ifdef INC_DEBUG
2953 printf("%s: including %s\n", file->filename, buf1);
2954 #endif
2955 f->inc_type = c;
2956 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2957 /* push current file in stack */
2958 /* XXX: fix current line init */
2959 *s1->include_stack_ptr++ = file;
2960 file = f;
2961 /* add include file debug info */
2962 if (do_debug) {
2963 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2965 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2966 ch = file->buf_ptr[0];
2967 goto the_end;
2969 break;
2970 case TOK_IFNDEF:
2971 c = 1;
2972 goto do_ifdef;
2973 case TOK_IF:
2974 c = expr_preprocess();
2975 goto do_if;
2976 case TOK_IFDEF:
2977 c = 0;
2978 do_ifdef:
2979 next_nomacro();
2980 if (tok < TOK_IDENT)
2981 error("invalid argument for '#if%sdef'", c ? "n" : "");
2982 if (is_bof) {
2983 if (c) {
2984 #ifdef INC_DEBUG
2985 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2986 #endif
2987 file->ifndef_macro = tok;
2990 c = (define_find(tok) != 0) ^ c;
2991 do_if:
2992 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2993 error("memory full");
2994 *s1->ifdef_stack_ptr++ = c;
2995 goto test_skip;
2996 case TOK_ELSE:
2997 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2998 error("#else without matching #if");
2999 if (s1->ifdef_stack_ptr[-1] & 2)
3000 error("#else after #else");
3001 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3002 goto test_skip;
3003 case TOK_ELIF:
3004 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3005 error("#elif without matching #if");
3006 c = s1->ifdef_stack_ptr[-1];
3007 if (c > 1)
3008 error("#elif after #else");
3009 /* last #if/#elif expression was true: we skip */
3010 if (c == 1)
3011 goto skip;
3012 c = expr_preprocess();
3013 s1->ifdef_stack_ptr[-1] = c;
3014 test_skip:
3015 if (!(c & 1)) {
3016 skip:
3017 preprocess_skip();
3018 is_bof = 0;
3019 goto redo;
3021 break;
3022 case TOK_ENDIF:
3023 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3024 error("#endif without matching #if");
3025 s1->ifdef_stack_ptr--;
3026 /* '#ifndef macro' was at the start of file. Now we check if
3027 an '#endif' is exactly at the end of file */
3028 if (file->ifndef_macro &&
3029 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3030 file->ifndef_macro_saved = file->ifndef_macro;
3031 /* need to set to zero to avoid false matches if another
3032 #ifndef at middle of file */
3033 file->ifndef_macro = 0;
3034 while (tok != TOK_LINEFEED)
3035 next_nomacro();
3036 tok_flags |= TOK_FLAG_ENDIF;
3037 goto the_end;
3039 break;
3040 case TOK_LINE:
3041 next();
3042 if (tok != TOK_CINT)
3043 error("#line");
3044 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3045 next();
3046 if (tok != TOK_LINEFEED) {
3047 if (tok != TOK_STR)
3048 error("#line");
3049 pstrcpy(file->filename, sizeof(file->filename),
3050 (char *)tokc.cstr->data);
3052 break;
3053 case TOK_ERROR:
3054 case TOK_WARNING:
3055 c = tok;
3056 ch = file->buf_ptr[0];
3057 skip_spaces();
3058 q = buf;
3059 while (ch != '\n' && ch != CH_EOF) {
3060 if ((q - buf) < sizeof(buf) - 1)
3061 *q++ = ch;
3062 minp();
3064 *q = '\0';
3065 if (c == TOK_ERROR)
3066 error("#error %s", buf);
3067 else
3068 warning("#warning %s", buf);
3069 break;
3070 case TOK_PRAGMA:
3071 pragma_parse(s1);
3072 break;
3073 default:
3074 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3075 /* '!' is ignored to allow C scripts. numbers are ignored
3076 to emulate cpp behaviour */
3077 } else {
3078 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3079 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
3081 break;
3083 /* ignore other preprocess commands or #! for C scripts */
3084 while (tok != TOK_LINEFEED)
3085 next_nomacro();
3086 the_end:
3087 parse_flags = saved_parse_flags;
3090 /* evaluate escape codes in a string. */
3091 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3093 int c, n;
3094 const uint8_t *p;
3096 p = buf;
3097 for(;;) {
3098 c = *p;
3099 if (c == '\0')
3100 break;
3101 if (c == '\\') {
3102 p++;
3103 /* escape */
3104 c = *p;
3105 switch(c) {
3106 case '0': case '1': case '2': case '3':
3107 case '4': case '5': case '6': case '7':
3108 /* at most three octal digits */
3109 n = c - '0';
3110 p++;
3111 c = *p;
3112 if (isoct(c)) {
3113 n = n * 8 + c - '0';
3114 p++;
3115 c = *p;
3116 if (isoct(c)) {
3117 n = n * 8 + c - '0';
3118 p++;
3121 c = n;
3122 goto add_char_nonext;
3123 case 'x':
3124 p++;
3125 n = 0;
3126 for(;;) {
3127 c = *p;
3128 if (c >= 'a' && c <= 'f')
3129 c = c - 'a' + 10;
3130 else if (c >= 'A' && c <= 'F')
3131 c = c - 'A' + 10;
3132 else if (isnum(c))
3133 c = c - '0';
3134 else
3135 break;
3136 n = n * 16 + c;
3137 p++;
3139 c = n;
3140 goto add_char_nonext;
3141 case 'a':
3142 c = '\a';
3143 break;
3144 case 'b':
3145 c = '\b';
3146 break;
3147 case 'f':
3148 c = '\f';
3149 break;
3150 case 'n':
3151 c = '\n';
3152 break;
3153 case 'r':
3154 c = '\r';
3155 break;
3156 case 't':
3157 c = '\t';
3158 break;
3159 case 'v':
3160 c = '\v';
3161 break;
3162 case 'e':
3163 if (!gnu_ext)
3164 goto invalid_escape;
3165 c = 27;
3166 break;
3167 case '\'':
3168 case '\"':
3169 case '\\':
3170 case '?':
3171 break;
3172 default:
3173 invalid_escape:
3174 if (c >= '!' && c <= '~')
3175 warning("unknown escape sequence: \'\\%c\'", c);
3176 else
3177 warning("unknown escape sequence: \'\\x%x\'", c);
3178 break;
3181 p++;
3182 add_char_nonext:
3183 if (!is_long)
3184 cstr_ccat(outstr, c);
3185 else
3186 cstr_wccat(outstr, c);
3188 /* add a trailing '\0' */
3189 if (!is_long)
3190 cstr_ccat(outstr, '\0');
3191 else
3192 cstr_wccat(outstr, '\0');
3195 /* we use 64 bit numbers */
3196 #define BN_SIZE 2
3198 /* bn = (bn << shift) | or_val */
3199 void bn_lshift(unsigned int *bn, int shift, int or_val)
3201 int i;
3202 unsigned int v;
3203 for(i=0;i<BN_SIZE;i++) {
3204 v = bn[i];
3205 bn[i] = (v << shift) | or_val;
3206 or_val = v >> (32 - shift);
3210 void bn_zero(unsigned int *bn)
3212 int i;
3213 for(i=0;i<BN_SIZE;i++) {
3214 bn[i] = 0;
3218 /* parse number in null terminated string 'p' and return it in the
3219 current token */
3220 void parse_number(const char *p)
3222 int b, t, shift, frac_bits, s, exp_val, ch;
3223 char *q;
3224 unsigned int bn[BN_SIZE];
3225 double d;
3227 /* number */
3228 q = token_buf;
3229 ch = *p++;
3230 t = ch;
3231 ch = *p++;
3232 *q++ = t;
3233 b = 10;
3234 if (t == '.') {
3235 goto float_frac_parse;
3236 } else if (t == '0') {
3237 if (ch == 'x' || ch == 'X') {
3238 q--;
3239 ch = *p++;
3240 b = 16;
3241 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3242 q--;
3243 ch = *p++;
3244 b = 2;
3247 /* parse all digits. cannot check octal numbers at this stage
3248 because of floating point constants */
3249 while (1) {
3250 if (ch >= 'a' && ch <= 'f')
3251 t = ch - 'a' + 10;
3252 else if (ch >= 'A' && ch <= 'F')
3253 t = ch - 'A' + 10;
3254 else if (isnum(ch))
3255 t = ch - '0';
3256 else
3257 break;
3258 if (t >= b)
3259 break;
3260 if (q >= token_buf + STRING_MAX_SIZE) {
3261 num_too_long:
3262 error("number too long");
3264 *q++ = ch;
3265 ch = *p++;
3267 if (ch == '.' ||
3268 ((ch == 'e' || ch == 'E') && b == 10) ||
3269 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3270 if (b != 10) {
3271 /* NOTE: strtox should support that for hexa numbers, but
3272 non ISOC99 libcs do not support it, so we prefer to do
3273 it by hand */
3274 /* hexadecimal or binary floats */
3275 /* XXX: handle overflows */
3276 *q = '\0';
3277 if (b == 16)
3278 shift = 4;
3279 else
3280 shift = 2;
3281 bn_zero(bn);
3282 q = token_buf;
3283 while (1) {
3284 t = *q++;
3285 if (t == '\0') {
3286 break;
3287 } else if (t >= 'a') {
3288 t = t - 'a' + 10;
3289 } else if (t >= 'A') {
3290 t = t - 'A' + 10;
3291 } else {
3292 t = t - '0';
3294 bn_lshift(bn, shift, t);
3296 frac_bits = 0;
3297 if (ch == '.') {
3298 ch = *p++;
3299 while (1) {
3300 t = ch;
3301 if (t >= 'a' && t <= 'f') {
3302 t = t - 'a' + 10;
3303 } else if (t >= 'A' && t <= 'F') {
3304 t = t - 'A' + 10;
3305 } else if (t >= '0' && t <= '9') {
3306 t = t - '0';
3307 } else {
3308 break;
3310 if (t >= b)
3311 error("invalid digit");
3312 bn_lshift(bn, shift, t);
3313 frac_bits += shift;
3314 ch = *p++;
3317 if (ch != 'p' && ch != 'P')
3318 expect("exponent");
3319 ch = *p++;
3320 s = 1;
3321 exp_val = 0;
3322 if (ch == '+') {
3323 ch = *p++;
3324 } else if (ch == '-') {
3325 s = -1;
3326 ch = *p++;
3328 if (ch < '0' || ch > '9')
3329 expect("exponent digits");
3330 while (ch >= '0' && ch <= '9') {
3331 exp_val = exp_val * 10 + ch - '0';
3332 ch = *p++;
3334 exp_val = exp_val * s;
3336 /* now we can generate the number */
3337 /* XXX: should patch directly float number */
3338 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3339 d = ldexp(d, exp_val - frac_bits);
3340 t = toup(ch);
3341 if (t == 'F') {
3342 ch = *p++;
3343 tok = TOK_CFLOAT;
3344 /* float : should handle overflow */
3345 tokc.f = (float)d;
3346 } else if (t == 'L') {
3347 ch = *p++;
3348 tok = TOK_CLDOUBLE;
3349 /* XXX: not large enough */
3350 tokc.ld = (long double)d;
3351 } else {
3352 tok = TOK_CDOUBLE;
3353 tokc.d = d;
3355 } else {
3356 /* decimal floats */
3357 if (ch == '.') {
3358 if (q >= token_buf + STRING_MAX_SIZE)
3359 goto num_too_long;
3360 *q++ = ch;
3361 ch = *p++;
3362 float_frac_parse:
3363 while (ch >= '0' && ch <= '9') {
3364 if (q >= token_buf + STRING_MAX_SIZE)
3365 goto num_too_long;
3366 *q++ = ch;
3367 ch = *p++;
3370 if (ch == 'e' || ch == 'E') {
3371 if (q >= token_buf + STRING_MAX_SIZE)
3372 goto num_too_long;
3373 *q++ = ch;
3374 ch = *p++;
3375 if (ch == '-' || ch == '+') {
3376 if (q >= token_buf + STRING_MAX_SIZE)
3377 goto num_too_long;
3378 *q++ = ch;
3379 ch = *p++;
3381 if (ch < '0' || ch > '9')
3382 expect("exponent digits");
3383 while (ch >= '0' && ch <= '9') {
3384 if (q >= token_buf + STRING_MAX_SIZE)
3385 goto num_too_long;
3386 *q++ = ch;
3387 ch = *p++;
3390 *q = '\0';
3391 t = toup(ch);
3392 errno = 0;
3393 if (t == 'F') {
3394 ch = *p++;
3395 tok = TOK_CFLOAT;
3396 tokc.f = strtof(token_buf, NULL);
3397 } else if (t == 'L') {
3398 ch = *p++;
3399 tok = TOK_CLDOUBLE;
3400 tokc.ld = strtold(token_buf, NULL);
3401 } else {
3402 tok = TOK_CDOUBLE;
3403 tokc.d = strtod(token_buf, NULL);
3406 } else {
3407 unsigned long long n, n1;
3408 int lcount, ucount;
3410 /* integer number */
3411 *q = '\0';
3412 q = token_buf;
3413 if (b == 10 && *q == '0') {
3414 b = 8;
3415 q++;
3417 n = 0;
3418 while(1) {
3419 t = *q++;
3420 /* no need for checks except for base 10 / 8 errors */
3421 if (t == '\0') {
3422 break;
3423 } else if (t >= 'a') {
3424 t = t - 'a' + 10;
3425 } else if (t >= 'A') {
3426 t = t - 'A' + 10;
3427 } else {
3428 t = t - '0';
3429 if (t >= b)
3430 error("invalid digit");
3432 n1 = n;
3433 n = n * b + t;
3434 /* detect overflow */
3435 /* XXX: this test is not reliable */
3436 if (n < n1)
3437 error("integer constant overflow");
3440 /* XXX: not exactly ANSI compliant */
3441 if ((n & 0xffffffff00000000LL) != 0) {
3442 if ((n >> 63) != 0)
3443 tok = TOK_CULLONG;
3444 else
3445 tok = TOK_CLLONG;
3446 } else if (n > 0x7fffffff) {
3447 tok = TOK_CUINT;
3448 } else {
3449 tok = TOK_CINT;
3451 lcount = 0;
3452 ucount = 0;
3453 for(;;) {
3454 t = toup(ch);
3455 if (t == 'L') {
3456 if (lcount >= 2)
3457 error("three 'l's in integer constant");
3458 lcount++;
3459 if (lcount == 2) {
3460 if (tok == TOK_CINT)
3461 tok = TOK_CLLONG;
3462 else if (tok == TOK_CUINT)
3463 tok = TOK_CULLONG;
3465 ch = *p++;
3466 } else if (t == 'U') {
3467 if (ucount >= 1)
3468 error("two 'u's in integer constant");
3469 ucount++;
3470 if (tok == TOK_CINT)
3471 tok = TOK_CUINT;
3472 else if (tok == TOK_CLLONG)
3473 tok = TOK_CULLONG;
3474 ch = *p++;
3475 } else {
3476 break;
3479 if (tok == TOK_CINT || tok == TOK_CUINT)
3480 tokc.ui = n;
3481 else
3482 tokc.ull = n;
3487 #define PARSE2(c1, tok1, c2, tok2) \
3488 case c1: \
3489 PEEKC(c, p); \
3490 if (c == c2) { \
3491 p++; \
3492 tok = tok2; \
3493 } else { \
3494 tok = tok1; \
3496 break;
3498 /* return next token without macro substitution */
3499 static inline void next_nomacro1(void)
3501 int t, c, is_long;
3502 TokenSym *ts;
3503 uint8_t *p, *p1;
3504 unsigned int h;
3506 p = file->buf_ptr;
3507 redo_no_start:
3508 c = *p;
3509 switch(c) {
3510 case ' ':
3511 case '\t':
3512 case '\f':
3513 case '\v':
3514 case '\r':
3515 p++;
3516 goto redo_no_start;
3518 case '\\':
3519 /* first look if it is in fact an end of buffer */
3520 if (p >= file->buf_end) {
3521 file->buf_ptr = p;
3522 handle_eob();
3523 p = file->buf_ptr;
3524 if (p >= file->buf_end)
3525 goto parse_eof;
3526 else
3527 goto redo_no_start;
3528 } else {
3529 file->buf_ptr = p;
3530 ch = *p;
3531 handle_stray();
3532 p = file->buf_ptr;
3533 goto redo_no_start;
3535 parse_eof:
3537 TCCState *s1 = tcc_state;
3538 if (parse_flags & PARSE_FLAG_LINEFEED) {
3539 tok = TOK_LINEFEED;
3540 } else if (s1->include_stack_ptr == s1->include_stack ||
3541 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3542 /* no include left : end of file. */
3543 tok = TOK_EOF;
3544 } else {
3545 /* pop include file */
3547 /* test if previous '#endif' was after a #ifdef at
3548 start of file */
3549 if (tok_flags & TOK_FLAG_ENDIF) {
3550 #ifdef INC_DEBUG
3551 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3552 #endif
3553 add_cached_include(s1, file->inc_type, file->inc_filename,
3554 file->ifndef_macro_saved);
3557 /* add end of include file debug info */
3558 if (do_debug) {
3559 put_stabd(N_EINCL, 0, 0);
3561 /* pop include stack */
3562 tcc_close(file);
3563 s1->include_stack_ptr--;
3564 file = *s1->include_stack_ptr;
3565 p = file->buf_ptr;
3566 goto redo_no_start;
3569 break;
3571 case '\n':
3572 if (parse_flags & PARSE_FLAG_LINEFEED) {
3573 tok = TOK_LINEFEED;
3574 } else {
3575 file->line_num++;
3576 tok_flags |= TOK_FLAG_BOL;
3577 p++;
3578 goto redo_no_start;
3580 break;
3582 case '#':
3583 /* XXX: simplify */
3584 PEEKC(c, p);
3585 if ((tok_flags & TOK_FLAG_BOL) &&
3586 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3587 file->buf_ptr = p;
3588 preprocess(tok_flags & TOK_FLAG_BOF);
3589 p = file->buf_ptr;
3590 goto redo_no_start;
3591 } else {
3592 if (c == '#') {
3593 p++;
3594 tok = TOK_TWOSHARPS;
3595 } else {
3596 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3597 p = parse_line_comment(p - 1);
3598 goto redo_no_start;
3599 } else {
3600 tok = '#';
3604 break;
3606 case 'a': case 'b': case 'c': case 'd':
3607 case 'e': case 'f': case 'g': case 'h':
3608 case 'i': case 'j': case 'k': case 'l':
3609 case 'm': case 'n': case 'o': case 'p':
3610 case 'q': case 'r': case 's': case 't':
3611 case 'u': case 'v': case 'w': case 'x':
3612 case 'y': case 'z':
3613 case 'A': case 'B': case 'C': case 'D':
3614 case 'E': case 'F': case 'G': case 'H':
3615 case 'I': case 'J': case 'K':
3616 case 'M': case 'N': case 'O': case 'P':
3617 case 'Q': case 'R': case 'S': case 'T':
3618 case 'U': case 'V': case 'W': case 'X':
3619 case 'Y': case 'Z':
3620 case '_':
3621 parse_ident_fast:
3622 p1 = p;
3623 h = TOK_HASH_INIT;
3624 h = TOK_HASH_FUNC(h, c);
3625 p++;
3626 for(;;) {
3627 c = *p;
3628 if (!isidnum_table[c])
3629 break;
3630 h = TOK_HASH_FUNC(h, c);
3631 p++;
3633 if (c != '\\') {
3634 TokenSym **pts;
3635 int len;
3637 /* fast case : no stray found, so we have the full token
3638 and we have already hashed it */
3639 len = p - p1;
3640 h &= (TOK_HASH_SIZE - 1);
3641 pts = &hash_ident[h];
3642 for(;;) {
3643 ts = *pts;
3644 if (!ts)
3645 break;
3646 if (ts->len == len && !memcmp(ts->str, p1, len))
3647 goto token_found;
3648 pts = &(ts->hash_next);
3650 ts = tok_alloc_new(pts, p1, len);
3651 token_found: ;
3652 } else {
3653 /* slower case */
3654 cstr_reset(&tokcstr);
3656 while (p1 < p) {
3657 cstr_ccat(&tokcstr, *p1);
3658 p1++;
3660 p--;
3661 PEEKC(c, p);
3662 parse_ident_slow:
3663 while (isidnum_table[c]) {
3664 cstr_ccat(&tokcstr, c);
3665 PEEKC(c, p);
3667 ts = tok_alloc(tokcstr.data, tokcstr.size);
3669 tok = ts->tok;
3670 break;
3671 case 'L':
3672 t = p[1];
3673 if (t != '\\' && t != '\'' && t != '\"') {
3674 /* fast case */
3675 goto parse_ident_fast;
3676 } else {
3677 PEEKC(c, p);
3678 if (c == '\'' || c == '\"') {
3679 is_long = 1;
3680 goto str_const;
3681 } else {
3682 cstr_reset(&tokcstr);
3683 cstr_ccat(&tokcstr, 'L');
3684 goto parse_ident_slow;
3687 break;
3688 case '0': case '1': case '2': case '3':
3689 case '4': case '5': case '6': case '7':
3690 case '8': case '9':
3692 cstr_reset(&tokcstr);
3693 /* after the first digit, accept digits, alpha, '.' or sign if
3694 prefixed by 'eEpP' */
3695 parse_num:
3696 for(;;) {
3697 t = c;
3698 cstr_ccat(&tokcstr, c);
3699 PEEKC(c, p);
3700 if (!(isnum(c) || isid(c) || c == '.' ||
3701 ((c == '+' || c == '-') &&
3702 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3703 break;
3705 /* We add a trailing '\0' to ease parsing */
3706 cstr_ccat(&tokcstr, '\0');
3707 tokc.cstr = &tokcstr;
3708 tok = TOK_PPNUM;
3709 break;
3710 case '.':
3711 /* special dot handling because it can also start a number */
3712 PEEKC(c, p);
3713 if (isnum(c)) {
3714 cstr_reset(&tokcstr);
3715 cstr_ccat(&tokcstr, '.');
3716 goto parse_num;
3717 } else if (c == '.') {
3718 PEEKC(c, p);
3719 if (c != '.')
3720 expect("'.'");
3721 PEEKC(c, p);
3722 tok = TOK_DOTS;
3723 } else {
3724 tok = '.';
3726 break;
3727 case '\'':
3728 case '\"':
3729 is_long = 0;
3730 str_const:
3732 CString str;
3733 int sep;
3735 sep = c;
3737 /* parse the string */
3738 cstr_new(&str);
3739 p = parse_pp_string(p, sep, &str);
3740 cstr_ccat(&str, '\0');
3742 /* eval the escape (should be done as TOK_PPNUM) */
3743 cstr_reset(&tokcstr);
3744 parse_escape_string(&tokcstr, str.data, is_long);
3745 cstr_free(&str);
3747 if (sep == '\'') {
3748 int char_size;
3749 /* XXX: make it portable */
3750 if (!is_long)
3751 char_size = 1;
3752 else
3753 char_size = sizeof(nwchar_t);
3754 if (tokcstr.size <= char_size)
3755 error("empty character constant");
3756 if (tokcstr.size > 2 * char_size)
3757 warning("multi-character character constant");
3758 if (!is_long) {
3759 tokc.i = *(int8_t *)tokcstr.data;
3760 tok = TOK_CCHAR;
3761 } else {
3762 tokc.i = *(nwchar_t *)tokcstr.data;
3763 tok = TOK_LCHAR;
3765 } else {
3766 tokc.cstr = &tokcstr;
3767 if (!is_long)
3768 tok = TOK_STR;
3769 else
3770 tok = TOK_LSTR;
3773 break;
3775 case '<':
3776 PEEKC(c, p);
3777 if (c == '=') {
3778 p++;
3779 tok = TOK_LE;
3780 } else if (c == '<') {
3781 PEEKC(c, p);
3782 if (c == '=') {
3783 p++;
3784 tok = TOK_A_SHL;
3785 } else {
3786 tok = TOK_SHL;
3788 } else {
3789 tok = TOK_LT;
3791 break;
3793 case '>':
3794 PEEKC(c, p);
3795 if (c == '=') {
3796 p++;
3797 tok = TOK_GE;
3798 } else if (c == '>') {
3799 PEEKC(c, p);
3800 if (c == '=') {
3801 p++;
3802 tok = TOK_A_SAR;
3803 } else {
3804 tok = TOK_SAR;
3806 } else {
3807 tok = TOK_GT;
3809 break;
3811 case '&':
3812 PEEKC(c, p);
3813 if (c == '&') {
3814 p++;
3815 tok = TOK_LAND;
3816 } else if (c == '=') {
3817 p++;
3818 tok = TOK_A_AND;
3819 } else {
3820 tok = '&';
3822 break;
3824 case '|':
3825 PEEKC(c, p);
3826 if (c == '|') {
3827 p++;
3828 tok = TOK_LOR;
3829 } else if (c == '=') {
3830 p++;
3831 tok = TOK_A_OR;
3832 } else {
3833 tok = '|';
3835 break;
3837 case '+':
3838 PEEKC(c, p);
3839 if (c == '+') {
3840 p++;
3841 tok = TOK_INC;
3842 } else if (c == '=') {
3843 p++;
3844 tok = TOK_A_ADD;
3845 } else {
3846 tok = '+';
3848 break;
3850 case '-':
3851 PEEKC(c, p);
3852 if (c == '-') {
3853 p++;
3854 tok = TOK_DEC;
3855 } else if (c == '=') {
3856 p++;
3857 tok = TOK_A_SUB;
3858 } else if (c == '>') {
3859 p++;
3860 tok = TOK_ARROW;
3861 } else {
3862 tok = '-';
3864 break;
3866 PARSE2('!', '!', '=', TOK_NE)
3867 PARSE2('=', '=', '=', TOK_EQ)
3868 PARSE2('*', '*', '=', TOK_A_MUL)
3869 PARSE2('%', '%', '=', TOK_A_MOD)
3870 PARSE2('^', '^', '=', TOK_A_XOR)
3872 /* comments or operator */
3873 case '/':
3874 PEEKC(c, p);
3875 if (c == '*') {
3876 p = parse_comment(p);
3877 goto redo_no_start;
3878 } else if (c == '/') {
3879 p = parse_line_comment(p);
3880 goto redo_no_start;
3881 } else if (c == '=') {
3882 p++;
3883 tok = TOK_A_DIV;
3884 } else {
3885 tok = '/';
3887 break;
3889 /* simple tokens */
3890 case '(':
3891 case ')':
3892 case '[':
3893 case ']':
3894 case '{':
3895 case '}':
3896 case ',':
3897 case ';':
3898 case ':':
3899 case '?':
3900 case '~':
3901 case '$': /* only used in assembler */
3902 case '@': /* dito */
3903 tok = c;
3904 p++;
3905 break;
3906 default:
3907 error("unrecognized character \\x%02x", c);
3908 break;
3910 file->buf_ptr = p;
3911 tok_flags = 0;
3912 #if defined(PARSE_DEBUG)
3913 printf("token = %s\n", get_tok_str(tok, &tokc));
3914 #endif
3917 /* return next token without macro substitution. Can read input from
3918 macro_ptr buffer */
3919 static void next_nomacro(void)
3921 if (macro_ptr) {
3922 redo:
3923 tok = *macro_ptr;
3924 if (tok) {
3925 TOK_GET(tok, macro_ptr, tokc);
3926 if (tok == TOK_LINENUM) {
3927 file->line_num = tokc.i;
3928 goto redo;
3931 } else {
3932 next_nomacro1();
3936 /* substitute args in macro_str and return allocated string */
3937 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3939 int *st, last_tok, t, notfirst;
3940 Sym *s;
3941 CValue cval;
3942 TokenString str;
3943 CString cstr;
3945 tok_str_new(&str);
3946 last_tok = 0;
3947 while(1) {
3948 TOK_GET(t, macro_str, cval);
3949 if (!t)
3950 break;
3951 if (t == '#') {
3952 /* stringize */
3953 TOK_GET(t, macro_str, cval);
3954 if (!t)
3955 break;
3956 s = sym_find2(args, t);
3957 if (s) {
3958 cstr_new(&cstr);
3959 st = (int *)s->c;
3960 notfirst = 0;
3961 while (*st) {
3962 if (notfirst)
3963 cstr_ccat(&cstr, ' ');
3964 TOK_GET(t, st, cval);
3965 cstr_cat(&cstr, get_tok_str(t, &cval));
3966 notfirst = 1;
3968 cstr_ccat(&cstr, '\0');
3969 #ifdef PP_DEBUG
3970 printf("stringize: %s\n", (char *)cstr.data);
3971 #endif
3972 /* add string */
3973 cval.cstr = &cstr;
3974 tok_str_add2(&str, TOK_STR, &cval);
3975 cstr_free(&cstr);
3976 } else {
3977 tok_str_add2(&str, t, &cval);
3979 } else if (t >= TOK_IDENT) {
3980 s = sym_find2(args, t);
3981 if (s) {
3982 st = (int *)s->c;
3983 /* if '##' is present before or after, no arg substitution */
3984 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3985 /* special case for var arg macros : ## eats the
3986 ',' if empty VA_ARGS variable. */
3987 /* XXX: test of the ',' is not 100%
3988 reliable. should fix it to avoid security
3989 problems */
3990 if (gnu_ext && s->type.t &&
3991 last_tok == TOK_TWOSHARPS &&
3992 str.len >= 2 && str.str[str.len - 2] == ',') {
3993 if (*st == 0) {
3994 /* suppress ',' '##' */
3995 str.len -= 2;
3996 } else {
3997 /* suppress '##' and add variable */
3998 str.len--;
3999 goto add_var;
4001 } else {
4002 int t1;
4003 add_var:
4004 for(;;) {
4005 TOK_GET(t1, st, cval);
4006 if (!t1)
4007 break;
4008 tok_str_add2(&str, t1, &cval);
4011 } else {
4012 /* NOTE: the stream cannot be read when macro
4013 substituing an argument */
4014 macro_subst(&str, nested_list, st, NULL);
4016 } else {
4017 tok_str_add(&str, t);
4019 } else {
4020 tok_str_add2(&str, t, &cval);
4022 last_tok = t;
4024 tok_str_add(&str, 0);
4025 return str.str;
4028 static char const ab_month_name[12][4] =
4030 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4031 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4034 /* do macro substitution of current token with macro 's' and add
4035 result to (tok_str,tok_len). 'nested_list' is the list of all
4036 macros we got inside to avoid recursing. Return non zero if no
4037 substitution needs to be done */
4038 static int macro_subst_tok(TokenString *tok_str,
4039 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4041 Sym *args, *sa, *sa1;
4042 int mstr_allocated, parlevel, *mstr, t, t1;
4043 TokenString str;
4044 char *cstrval;
4045 CValue cval;
4046 CString cstr;
4047 char buf[32];
4049 /* if symbol is a macro, prepare substitution */
4050 /* special macros */
4051 if (tok == TOK___LINE__) {
4052 snprintf(buf, sizeof(buf), "%d", file->line_num);
4053 cstrval = buf;
4054 t1 = TOK_PPNUM;
4055 goto add_cstr1;
4056 } else if (tok == TOK___FILE__) {
4057 cstrval = file->filename;
4058 goto add_cstr;
4059 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4060 time_t ti;
4061 struct tm *tm;
4063 time(&ti);
4064 tm = localtime(&ti);
4065 if (tok == TOK___DATE__) {
4066 snprintf(buf, sizeof(buf), "%s %2d %d",
4067 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4068 } else {
4069 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4070 tm->tm_hour, tm->tm_min, tm->tm_sec);
4072 cstrval = buf;
4073 add_cstr:
4074 t1 = TOK_STR;
4075 add_cstr1:
4076 cstr_new(&cstr);
4077 cstr_cat(&cstr, cstrval);
4078 cstr_ccat(&cstr, '\0');
4079 cval.cstr = &cstr;
4080 tok_str_add2(tok_str, t1, &cval);
4081 cstr_free(&cstr);
4082 } else {
4083 mstr = (int *)s->c;
4084 mstr_allocated = 0;
4085 if (s->type.t == MACRO_FUNC) {
4086 /* NOTE: we do not use next_nomacro to avoid eating the
4087 next token. XXX: find better solution */
4088 redo:
4089 if (macro_ptr) {
4090 t = *macro_ptr;
4091 if (t == 0 && can_read_stream) {
4092 /* end of macro stream: we must look at the token
4093 after in the file */
4094 struct macro_level *ml = *can_read_stream;
4095 macro_ptr = NULL;
4096 if (ml)
4098 macro_ptr = ml->p;
4099 ml->p = NULL;
4100 *can_read_stream = ml -> prev;
4102 goto redo;
4104 } else {
4105 /* XXX: incorrect with comments */
4106 ch = file->buf_ptr[0];
4107 while (is_space(ch) || ch == '\n')
4108 cinp();
4109 t = ch;
4111 if (t != '(') /* no macro subst */
4112 return -1;
4114 /* argument macro */
4115 next_nomacro();
4116 next_nomacro();
4117 args = NULL;
4118 sa = s->next;
4119 /* NOTE: empty args are allowed, except if no args */
4120 for(;;) {
4121 /* handle '()' case */
4122 if (!args && !sa && tok == ')')
4123 break;
4124 if (!sa)
4125 error("macro '%s' used with too many args",
4126 get_tok_str(s->v, 0));
4127 tok_str_new(&str);
4128 parlevel = 0;
4129 /* NOTE: non zero sa->t indicates VA_ARGS */
4130 while ((parlevel > 0 ||
4131 (tok != ')' &&
4132 (tok != ',' || sa->type.t))) &&
4133 tok != -1) {
4134 if (tok == '(')
4135 parlevel++;
4136 else if (tok == ')')
4137 parlevel--;
4138 tok_str_add2(&str, tok, &tokc);
4139 next_nomacro();
4141 tok_str_add(&str, 0);
4142 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4143 sa = sa->next;
4144 if (tok == ')') {
4145 /* special case for gcc var args: add an empty
4146 var arg argument if it is omitted */
4147 if (sa && sa->type.t && gnu_ext)
4148 continue;
4149 else
4150 break;
4152 if (tok != ',')
4153 expect(",");
4154 next_nomacro();
4156 if (sa) {
4157 error("macro '%s' used with too few args",
4158 get_tok_str(s->v, 0));
4161 /* now subst each arg */
4162 mstr = macro_arg_subst(nested_list, mstr, args);
4163 /* free memory */
4164 sa = args;
4165 while (sa) {
4166 sa1 = sa->prev;
4167 tok_str_free((int *)sa->c);
4168 sym_free(sa);
4169 sa = sa1;
4171 mstr_allocated = 1;
4173 sym_push2(nested_list, s->v, 0, 0);
4174 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4175 /* pop nested defined symbol */
4176 sa1 = *nested_list;
4177 *nested_list = sa1->prev;
4178 sym_free(sa1);
4179 if (mstr_allocated)
4180 tok_str_free(mstr);
4182 return 0;
4185 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4186 return the resulting string (which must be freed). */
4187 static inline int *macro_twosharps(const int *macro_str)
4189 TokenSym *ts;
4190 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4191 int t;
4192 const char *p1, *p2;
4193 CValue cval;
4194 TokenString macro_str1;
4195 CString cstr;
4197 start_macro_ptr = macro_str;
4198 /* we search the first '##' */
4199 for(;;) {
4200 macro_ptr1 = macro_str;
4201 TOK_GET(t, macro_str, cval);
4202 /* nothing more to do if end of string */
4203 if (t == 0)
4204 return NULL;
4205 if (*macro_str == TOK_TWOSHARPS)
4206 break;
4209 /* we saw '##', so we need more processing to handle it */
4210 cstr_new(&cstr);
4211 tok_str_new(&macro_str1);
4212 tok = t;
4213 tokc = cval;
4215 /* add all tokens seen so far */
4216 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4217 TOK_GET(t, ptr, cval);
4218 tok_str_add2(&macro_str1, t, &cval);
4220 saved_macro_ptr = macro_ptr;
4221 /* XXX: get rid of the use of macro_ptr here */
4222 macro_ptr = (int *)macro_str;
4223 for(;;) {
4224 while (*macro_ptr == TOK_TWOSHARPS) {
4225 macro_ptr++;
4226 macro_ptr1 = macro_ptr;
4227 t = *macro_ptr;
4228 if (t) {
4229 TOK_GET(t, macro_ptr, cval);
4230 /* We concatenate the two tokens if we have an
4231 identifier or a preprocessing number */
4232 cstr_reset(&cstr);
4233 p1 = get_tok_str(tok, &tokc);
4234 cstr_cat(&cstr, p1);
4235 p2 = get_tok_str(t, &cval);
4236 cstr_cat(&cstr, p2);
4237 cstr_ccat(&cstr, '\0');
4239 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4240 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4241 if (tok == TOK_PPNUM) {
4242 /* if number, then create a number token */
4243 /* NOTE: no need to allocate because
4244 tok_str_add2() does it */
4245 cstr_reset(&tokcstr);
4246 tokcstr = cstr;
4247 cstr_new(&cstr);
4248 tokc.cstr = &tokcstr;
4249 } else {
4250 /* if identifier, we must do a test to
4251 validate we have a correct identifier */
4252 if (t == TOK_PPNUM) {
4253 const char *p;
4254 int c;
4256 p = p2;
4257 for(;;) {
4258 c = *p;
4259 if (c == '\0')
4260 break;
4261 p++;
4262 if (!isnum(c) && !isid(c))
4263 goto error_pasting;
4266 ts = tok_alloc(cstr.data, strlen(cstr.data));
4267 tok = ts->tok; /* modify current token */
4269 } else {
4270 const char *str = cstr.data;
4271 const unsigned char *q;
4273 /* we look for a valid token */
4274 /* XXX: do more extensive checks */
4275 if (!strcmp(str, ">>=")) {
4276 tok = TOK_A_SAR;
4277 } else if (!strcmp(str, "<<=")) {
4278 tok = TOK_A_SHL;
4279 } else if (strlen(str) == 2) {
4280 /* search in two bytes table */
4281 q = tok_two_chars;
4282 for(;;) {
4283 if (!*q)
4284 goto error_pasting;
4285 if (q[0] == str[0] && q[1] == str[1])
4286 break;
4287 q += 3;
4289 tok = q[2];
4290 } else {
4291 error_pasting:
4292 /* NOTE: because get_tok_str use a static buffer,
4293 we must save it */
4294 cstr_reset(&cstr);
4295 p1 = get_tok_str(tok, &tokc);
4296 cstr_cat(&cstr, p1);
4297 cstr_ccat(&cstr, '\0');
4298 p2 = get_tok_str(t, &cval);
4299 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4300 /* cannot merge tokens: just add them separately */
4301 tok_str_add2(&macro_str1, tok, &tokc);
4302 /* XXX: free associated memory ? */
4303 tok = t;
4304 tokc = cval;
4309 tok_str_add2(&macro_str1, tok, &tokc);
4310 next_nomacro();
4311 if (tok == 0)
4312 break;
4314 macro_ptr = (int *)saved_macro_ptr;
4315 cstr_free(&cstr);
4316 tok_str_add(&macro_str1, 0);
4317 return macro_str1.str;
4321 /* do macro substitution of macro_str and add result to
4322 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4323 inside to avoid recursing. */
4324 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4325 const int *macro_str, struct macro_level ** can_read_stream)
4327 Sym *s;
4328 int *macro_str1;
4329 const int *ptr;
4330 int t, ret;
4331 CValue cval;
4332 struct macro_level ml;
4334 /* first scan for '##' operator handling */
4335 ptr = macro_str;
4336 macro_str1 = macro_twosharps(ptr);
4337 if (macro_str1)
4338 ptr = macro_str1;
4339 while (1) {
4340 /* NOTE: ptr == NULL can only happen if tokens are read from
4341 file stream due to a macro function call */
4342 if (ptr == NULL)
4343 break;
4344 TOK_GET(t, ptr, cval);
4345 if (t == 0)
4346 break;
4347 s = define_find(t);
4348 if (s != NULL) {
4349 /* if nested substitution, do nothing */
4350 if (sym_find2(*nested_list, t))
4351 goto no_subst;
4352 ml.p = macro_ptr;
4353 if (can_read_stream)
4354 ml.prev = *can_read_stream, *can_read_stream = &ml;
4355 macro_ptr = (int *)ptr;
4356 tok = t;
4357 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4358 ptr = (int *)macro_ptr;
4359 macro_ptr = ml.p;
4360 if (can_read_stream && *can_read_stream == &ml)
4361 *can_read_stream = ml.prev;
4362 if (ret != 0)
4363 goto no_subst;
4364 } else {
4365 no_subst:
4366 tok_str_add2(tok_str, t, &cval);
4369 if (macro_str1)
4370 tok_str_free(macro_str1);
4373 /* return next token with macro substitution */
4374 static void next(void)
4376 Sym *nested_list, *s;
4377 TokenString str;
4378 struct macro_level *ml;
4380 redo:
4381 next_nomacro();
4382 if (!macro_ptr) {
4383 /* if not reading from macro substituted string, then try
4384 to substitute macros */
4385 if (tok >= TOK_IDENT &&
4386 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4387 s = define_find(tok);
4388 if (s) {
4389 /* we have a macro: we try to substitute */
4390 tok_str_new(&str);
4391 nested_list = NULL;
4392 ml = NULL;
4393 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4394 /* substitution done, NOTE: maybe empty */
4395 tok_str_add(&str, 0);
4396 macro_ptr = str.str;
4397 macro_ptr_allocated = str.str;
4398 goto redo;
4402 } else {
4403 if (tok == 0) {
4404 /* end of macro or end of unget buffer */
4405 if (unget_buffer_enabled) {
4406 macro_ptr = unget_saved_macro_ptr;
4407 unget_buffer_enabled = 0;
4408 } else {
4409 /* end of macro string: free it */
4410 tok_str_free(macro_ptr_allocated);
4411 macro_ptr = NULL;
4413 goto redo;
4417 /* convert preprocessor tokens into C tokens */
4418 if (tok == TOK_PPNUM &&
4419 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4420 parse_number((char *)tokc.cstr->data);
4424 /* push back current token and set current token to 'last_tok'. Only
4425 identifier case handled for labels. */
4426 static inline void unget_tok(int last_tok)
4428 int i, n;
4429 int *q;
4430 unget_saved_macro_ptr = macro_ptr;
4431 unget_buffer_enabled = 1;
4432 q = unget_saved_buffer;
4433 macro_ptr = q;
4434 *q++ = tok;
4435 n = tok_ext_size(tok) - 1;
4436 for(i=0;i<n;i++)
4437 *q++ = tokc.tab[i];
4438 *q = 0; /* end of token string */
4439 tok = last_tok;
4443 void swap(int *p, int *q)
4445 int t;
4446 t = *p;
4447 *p = *q;
4448 *q = t;
4451 void vsetc(CType *type, int r, CValue *vc)
4453 int v;
4455 if (vtop >= vstack + (VSTACK_SIZE - 1))
4456 error("memory full");
4457 /* cannot let cpu flags if other instruction are generated. Also
4458 avoid leaving VT_JMP anywhere except on the top of the stack
4459 because it would complicate the code generator. */
4460 if (vtop >= vstack) {
4461 v = vtop->r & VT_VALMASK;
4462 if (v == VT_CMP || (v & ~1) == VT_JMP)
4463 gv(RC_INT);
4465 vtop++;
4466 vtop->type = *type;
4467 vtop->r = r;
4468 vtop->r2 = VT_CONST;
4469 vtop->c = *vc;
4472 /* push integer constant */
4473 void vpushi(int v)
4475 CValue cval;
4476 cval.i = v;
4477 vsetc(&int_type, VT_CONST, &cval);
4480 /* Return a static symbol pointing to a section */
4481 static Sym *get_sym_ref(CType *type, Section *sec,
4482 unsigned long offset, unsigned long size)
4484 int v;
4485 Sym *sym;
4487 v = anon_sym++;
4488 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4489 sym->type.ref = type->ref;
4490 sym->r = VT_CONST | VT_SYM;
4491 put_extern_sym(sym, sec, offset, size);
4492 return sym;
4495 /* push a reference to a section offset by adding a dummy symbol */
4496 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4498 CValue cval;
4500 cval.ul = 0;
4501 vsetc(type, VT_CONST | VT_SYM, &cval);
4502 vtop->sym = get_sym_ref(type, sec, offset, size);
4505 /* define a new external reference to a symbol 'v' of type 'u' */
4506 static Sym *external_global_sym(int v, CType *type, int r)
4508 Sym *s;
4510 s = sym_find(v);
4511 if (!s) {
4512 /* push forward reference */
4513 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4514 s->type.ref = type->ref;
4515 s->r = r | VT_CONST | VT_SYM;
4517 return s;
4520 /* define a new external reference to a symbol 'v' of type 'u' */
4521 static Sym *external_sym(int v, CType *type, int r)
4523 Sym *s;
4525 s = sym_find(v);
4526 if (!s) {
4527 /* push forward reference */
4528 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4529 s->type.t |= VT_EXTERN;
4530 } else {
4531 if (!is_compatible_types(&s->type, type))
4532 error("incompatible types for redefinition of '%s'",
4533 get_tok_str(v, NULL));
4535 return s;
4538 /* push a reference to global symbol v */
4539 static void vpush_global_sym(CType *type, int v)
4541 Sym *sym;
4542 CValue cval;
4544 sym = external_global_sym(v, type, 0);
4545 cval.ul = 0;
4546 vsetc(type, VT_CONST | VT_SYM, &cval);
4547 vtop->sym = sym;
4550 void vset(CType *type, int r, int v)
4552 CValue cval;
4554 cval.i = v;
4555 vsetc(type, r, &cval);
4558 void vseti(int r, int v)
4560 CType type;
4561 type.t = VT_INT;
4562 vset(&type, r, v);
4565 void vswap(void)
4567 SValue tmp;
4569 tmp = vtop[0];
4570 vtop[0] = vtop[-1];
4571 vtop[-1] = tmp;
4574 void vpushv(SValue *v)
4576 if (vtop >= vstack + (VSTACK_SIZE - 1))
4577 error("memory full");
4578 vtop++;
4579 *vtop = *v;
4582 void vdup(void)
4584 vpushv(vtop);
4587 /* save r to the memory stack, and mark it as being free */
4588 void save_reg(int r)
4590 int l, saved, size, align;
4591 SValue *p, sv;
4592 CType *type;
4594 /* modify all stack values */
4595 saved = 0;
4596 l = 0;
4597 for(p=vstack;p<=vtop;p++) {
4598 if ((p->r & VT_VALMASK) == r ||
4599 (p->r2 & VT_VALMASK) == r) {
4600 /* must save value on stack if not already done */
4601 if (!saved) {
4602 /* NOTE: must reload 'r' because r might be equal to r2 */
4603 r = p->r & VT_VALMASK;
4604 /* store register in the stack */
4605 type = &p->type;
4606 if ((p->r & VT_LVAL) ||
4607 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4608 type = &int_type;
4609 size = type_size(type, &align);
4610 loc = (loc - size) & -align;
4611 sv.type.t = type->t;
4612 sv.r = VT_LOCAL | VT_LVAL;
4613 sv.c.ul = loc;
4614 store(r, &sv);
4615 #ifdef TCC_TARGET_I386
4616 /* x86 specific: need to pop fp register ST0 if saved */
4617 if (r == TREG_ST0) {
4618 o(0xd9dd); /* fstp %st(1) */
4620 #endif
4621 /* special long long case */
4622 if ((type->t & VT_BTYPE) == VT_LLONG) {
4623 sv.c.ul += 4;
4624 store(p->r2, &sv);
4626 l = loc;
4627 saved = 1;
4629 /* mark that stack entry as being saved on the stack */
4630 if (p->r & VT_LVAL) {
4631 /* also clear the bounded flag because the
4632 relocation address of the function was stored in
4633 p->c.ul */
4634 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4635 } else {
4636 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4638 p->r2 = VT_CONST;
4639 p->c.ul = l;
4644 /* find a register of class 'rc2' with at most one reference on stack.
4645 * If none, call get_reg(rc) */
4646 int get_reg_ex(int rc, int rc2)
4648 int r;
4649 SValue *p;
4651 for(r=0;r<NB_REGS;r++) {
4652 if (reg_classes[r] & rc2) {
4653 int n;
4654 n=0;
4655 for(p = vstack; p <= vtop; p++) {
4656 if ((p->r & VT_VALMASK) == r ||
4657 (p->r2 & VT_VALMASK) == r)
4658 n++;
4660 if (n <= 1)
4661 return r;
4664 return get_reg(rc);
4667 /* find a free register of class 'rc'. If none, save one register */
4668 int get_reg(int rc)
4670 int r;
4671 SValue *p;
4673 /* find a free register */
4674 for(r=0;r<NB_REGS;r++) {
4675 if (reg_classes[r] & rc) {
4676 for(p=vstack;p<=vtop;p++) {
4677 if ((p->r & VT_VALMASK) == r ||
4678 (p->r2 & VT_VALMASK) == r)
4679 goto notfound;
4681 return r;
4683 notfound: ;
4686 /* no register left : free the first one on the stack (VERY
4687 IMPORTANT to start from the bottom to ensure that we don't
4688 spill registers used in gen_opi()) */
4689 for(p=vstack;p<=vtop;p++) {
4690 r = p->r & VT_VALMASK;
4691 if (r < VT_CONST && (reg_classes[r] & rc))
4692 goto save_found;
4693 /* also look at second register (if long long) */
4694 r = p->r2 & VT_VALMASK;
4695 if (r < VT_CONST && (reg_classes[r] & rc)) {
4696 save_found:
4697 save_reg(r);
4698 return r;
4701 /* Should never comes here */
4702 return -1;
4705 /* save registers up to (vtop - n) stack entry */
4706 void save_regs(int n)
4708 int r;
4709 SValue *p, *p1;
4710 p1 = vtop - n;
4711 for(p = vstack;p <= p1; p++) {
4712 r = p->r & VT_VALMASK;
4713 if (r < VT_CONST) {
4714 save_reg(r);
4719 /* move register 's' to 'r', and flush previous value of r to memory
4720 if needed */
4721 void move_reg(int r, int s)
4723 SValue sv;
4725 if (r != s) {
4726 save_reg(r);
4727 sv.type.t = VT_INT;
4728 sv.r = s;
4729 sv.c.ul = 0;
4730 load(r, &sv);
4734 /* get address of vtop (vtop MUST BE an lvalue) */
4735 void gaddrof(void)
4737 vtop->r &= ~VT_LVAL;
4738 /* tricky: if saved lvalue, then we can go back to lvalue */
4739 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4740 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4743 #ifdef CONFIG_TCC_BCHECK
4744 /* generate lvalue bound code */
4745 void gbound(void)
4747 int lval_type;
4748 CType type1;
4750 vtop->r &= ~VT_MUSTBOUND;
4751 /* if lvalue, then use checking code before dereferencing */
4752 if (vtop->r & VT_LVAL) {
4753 /* if not VT_BOUNDED value, then make one */
4754 if (!(vtop->r & VT_BOUNDED)) {
4755 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4756 /* must save type because we must set it to int to get pointer */
4757 type1 = vtop->type;
4758 vtop->type.t = VT_INT;
4759 gaddrof();
4760 vpushi(0);
4761 gen_bounded_ptr_add();
4762 vtop->r |= lval_type;
4763 vtop->type = type1;
4765 /* then check for dereferencing */
4766 gen_bounded_ptr_deref();
4769 #endif
4771 /* store vtop a register belonging to class 'rc'. lvalues are
4772 converted to values. Cannot be used if cannot be converted to
4773 register value (such as structures). */
4774 int gv(int rc)
4776 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4777 unsigned long long ll;
4779 /* NOTE: get_reg can modify vstack[] */
4780 if (vtop->type.t & VT_BITFIELD) {
4781 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4782 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4783 /* remove bit field info to avoid loops */
4784 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4785 /* generate shifts */
4786 vpushi(32 - (bit_pos + bit_size));
4787 gen_op(TOK_SHL);
4788 vpushi(32 - bit_size);
4789 /* NOTE: transformed to SHR if unsigned */
4790 gen_op(TOK_SAR);
4791 r = gv(rc);
4792 } else {
4793 if (is_float(vtop->type.t) &&
4794 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4795 Sym *sym;
4796 int *ptr;
4797 unsigned long offset;
4799 /* XXX: unify with initializers handling ? */
4800 /* CPUs usually cannot use float constants, so we store them
4801 generically in data segment */
4802 size = type_size(&vtop->type, &align);
4803 offset = (data_section->data_offset + align - 1) & -align;
4804 data_section->data_offset = offset;
4805 /* XXX: not portable yet */
4806 ptr = section_ptr_add(data_section, size);
4807 size = size >> 2;
4808 for(i=0;i<size;i++)
4809 ptr[i] = vtop->c.tab[i];
4810 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4811 vtop->r |= VT_LVAL | VT_SYM;
4812 vtop->sym = sym;
4813 vtop->c.ul = 0;
4815 #ifdef CONFIG_TCC_BCHECK
4816 if (vtop->r & VT_MUSTBOUND)
4817 gbound();
4818 #endif
4820 r = vtop->r & VT_VALMASK;
4821 /* need to reload if:
4822 - constant
4823 - lvalue (need to dereference pointer)
4824 - already a register, but not in the right class */
4825 if (r >= VT_CONST ||
4826 (vtop->r & VT_LVAL) ||
4827 !(reg_classes[r] & rc) ||
4828 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4829 !(reg_classes[vtop->r2] & rc))) {
4830 r = get_reg(rc);
4831 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4832 /* two register type load : expand to two words
4833 temporarily */
4834 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4835 /* load constant */
4836 ll = vtop->c.ull;
4837 vtop->c.ui = ll; /* first word */
4838 load(r, vtop);
4839 vtop->r = r; /* save register value */
4840 vpushi(ll >> 32); /* second word */
4841 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4842 (vtop->r & VT_LVAL)) {
4843 /* We do not want to modifier the long long
4844 pointer here, so the safest (and less
4845 efficient) is to save all the other registers
4846 in the stack. XXX: totally inefficient. */
4847 save_regs(1);
4848 /* load from memory */
4849 load(r, vtop);
4850 vdup();
4851 vtop[-1].r = r; /* save register value */
4852 /* increment pointer to get second word */
4853 vtop->type.t = VT_INT;
4854 gaddrof();
4855 vpushi(4);
4856 gen_op('+');
4857 vtop->r |= VT_LVAL;
4858 } else {
4859 /* move registers */
4860 load(r, vtop);
4861 vdup();
4862 vtop[-1].r = r; /* save register value */
4863 vtop->r = vtop[-1].r2;
4865 /* allocate second register */
4866 rc2 = RC_INT;
4867 if (rc == RC_IRET)
4868 rc2 = RC_LRET;
4869 r2 = get_reg(rc2);
4870 load(r2, vtop);
4871 vpop();
4872 /* write second register */
4873 vtop->r2 = r2;
4874 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4875 int t1, t;
4876 /* lvalue of scalar type : need to use lvalue type
4877 because of possible cast */
4878 t = vtop->type.t;
4879 t1 = t;
4880 /* compute memory access type */
4881 if (vtop->r & VT_LVAL_BYTE)
4882 t = VT_BYTE;
4883 else if (vtop->r & VT_LVAL_SHORT)
4884 t = VT_SHORT;
4885 if (vtop->r & VT_LVAL_UNSIGNED)
4886 t |= VT_UNSIGNED;
4887 vtop->type.t = t;
4888 load(r, vtop);
4889 /* restore wanted type */
4890 vtop->type.t = t1;
4891 } else {
4892 /* one register type load */
4893 load(r, vtop);
4896 vtop->r = r;
4897 #ifdef TCC_TARGET_C67
4898 /* uses register pairs for doubles */
4899 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4900 vtop->r2 = r+1;
4901 #endif
4903 return r;
4906 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4907 void gv2(int rc1, int rc2)
4909 int v;
4911 /* generate more generic register first. But VT_JMP or VT_CMP
4912 values must be generated first in all cases to avoid possible
4913 reload errors */
4914 v = vtop[0].r & VT_VALMASK;
4915 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4916 vswap();
4917 gv(rc1);
4918 vswap();
4919 gv(rc2);
4920 /* test if reload is needed for first register */
4921 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4922 vswap();
4923 gv(rc1);
4924 vswap();
4926 } else {
4927 gv(rc2);
4928 vswap();
4929 gv(rc1);
4930 vswap();
4931 /* test if reload is needed for first register */
4932 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4933 gv(rc2);
4938 /* expand long long on stack in two int registers */
4939 void lexpand(void)
4941 int u;
4943 u = vtop->type.t & VT_UNSIGNED;
4944 gv(RC_INT);
4945 vdup();
4946 vtop[0].r = vtop[-1].r2;
4947 vtop[0].r2 = VT_CONST;
4948 vtop[-1].r2 = VT_CONST;
4949 vtop[0].type.t = VT_INT | u;
4950 vtop[-1].type.t = VT_INT | u;
4953 #ifdef TCC_TARGET_ARM
4954 /* expand long long on stack */
4955 void lexpand_nr(void)
4957 int u,v;
4959 u = vtop->type.t & VT_UNSIGNED;
4960 vdup();
4961 vtop->r2 = VT_CONST;
4962 vtop->type.t = VT_INT | u;
4963 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4964 if (v == VT_CONST) {
4965 vtop[-1].c.ui = vtop->c.ull;
4966 vtop->c.ui = vtop->c.ull >> 32;
4967 vtop->r = VT_CONST;
4968 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4969 vtop->c.ui += 4;
4970 vtop->r = vtop[-1].r;
4971 } else if (v > VT_CONST) {
4972 vtop--;
4973 lexpand();
4974 } else
4975 vtop->r = vtop[-1].r2;
4976 vtop[-1].r2 = VT_CONST;
4977 vtop[-1].type.t = VT_INT | u;
4979 #endif
4981 /* build a long long from two ints */
4982 void lbuild(int t)
4984 gv2(RC_INT, RC_INT);
4985 vtop[-1].r2 = vtop[0].r;
4986 vtop[-1].type.t = t;
4987 vpop();
4990 /* rotate n first stack elements to the bottom
4991 I1 ... In -> I2 ... In I1 [top is right]
4993 void vrotb(int n)
4995 int i;
4996 SValue tmp;
4998 tmp = vtop[-n + 1];
4999 for(i=-n+1;i!=0;i++)
5000 vtop[i] = vtop[i+1];
5001 vtop[0] = tmp;
5004 /* rotate n first stack elements to the top
5005 I1 ... In -> In I1 ... I(n-1) [top is right]
5007 void vrott(int n)
5009 int i;
5010 SValue tmp;
5012 tmp = vtop[0];
5013 for(i = 0;i < n - 1; i++)
5014 vtop[-i] = vtop[-i - 1];
5015 vtop[-n + 1] = tmp;
5018 #ifdef TCC_TARGET_ARM
5019 /* like vrott but in other direction
5020 In ... I1 -> I(n-1) ... I1 In [top is right]
5022 void vnrott(int n)
5024 int i;
5025 SValue tmp;
5027 tmp = vtop[-n + 1];
5028 for(i = n - 1; i > 0; i--)
5029 vtop[-i] = vtop[-i + 1];
5030 vtop[0] = tmp;
5032 #endif
5034 /* pop stack value */
5035 void vpop(void)
5037 int v;
5038 v = vtop->r & VT_VALMASK;
5039 #ifdef TCC_TARGET_I386
5040 /* for x86, we need to pop the FP stack */
5041 if (v == TREG_ST0 && !nocode_wanted) {
5042 o(0xd9dd); /* fstp %st(1) */
5043 } else
5044 #endif
5045 if (v == VT_JMP || v == VT_JMPI) {
5046 /* need to put correct jump if && or || without test */
5047 gsym(vtop->c.ul);
5049 vtop--;
5052 /* convert stack entry to register and duplicate its value in another
5053 register */
5054 void gv_dup(void)
5056 int rc, t, r, r1;
5057 SValue sv;
5059 t = vtop->type.t;
5060 if ((t & VT_BTYPE) == VT_LLONG) {
5061 lexpand();
5062 gv_dup();
5063 vswap();
5064 vrotb(3);
5065 gv_dup();
5066 vrotb(4);
5067 /* stack: H L L1 H1 */
5068 lbuild(t);
5069 vrotb(3);
5070 vrotb(3);
5071 vswap();
5072 lbuild(t);
5073 vswap();
5074 } else {
5075 /* duplicate value */
5076 rc = RC_INT;
5077 sv.type.t = VT_INT;
5078 if (is_float(t)) {
5079 rc = RC_FLOAT;
5080 sv.type.t = t;
5082 r = gv(rc);
5083 r1 = get_reg(rc);
5084 sv.r = r;
5085 sv.c.ul = 0;
5086 load(r1, &sv); /* move r to r1 */
5087 vdup();
5088 /* duplicates value */
5089 vtop->r = r1;
5093 /* generate CPU independent (unsigned) long long operations */
5094 void gen_opl(int op)
5096 int t, a, b, op1, c, i;
5097 int func;
5098 SValue tmp;
5100 switch(op) {
5101 case '/':
5102 case TOK_PDIV:
5103 func = TOK___divdi3;
5104 goto gen_func;
5105 case TOK_UDIV:
5106 func = TOK___udivdi3;
5107 goto gen_func;
5108 case '%':
5109 func = TOK___moddi3;
5110 goto gen_func;
5111 case TOK_UMOD:
5112 func = TOK___umoddi3;
5113 gen_func:
5114 /* call generic long long function */
5115 vpush_global_sym(&func_old_type, func);
5116 vrott(3);
5117 gfunc_call(2);
5118 vpushi(0);
5119 vtop->r = REG_IRET;
5120 vtop->r2 = REG_LRET;
5121 break;
5122 case '^':
5123 case '&':
5124 case '|':
5125 case '*':
5126 case '+':
5127 case '-':
5128 t = vtop->type.t;
5129 vswap();
5130 lexpand();
5131 vrotb(3);
5132 lexpand();
5133 /* stack: L1 H1 L2 H2 */
5134 tmp = vtop[0];
5135 vtop[0] = vtop[-3];
5136 vtop[-3] = tmp;
5137 tmp = vtop[-2];
5138 vtop[-2] = vtop[-3];
5139 vtop[-3] = tmp;
5140 vswap();
5141 /* stack: H1 H2 L1 L2 */
5142 if (op == '*') {
5143 vpushv(vtop - 1);
5144 vpushv(vtop - 1);
5145 gen_op(TOK_UMULL);
5146 lexpand();
5147 /* stack: H1 H2 L1 L2 ML MH */
5148 for(i=0;i<4;i++)
5149 vrotb(6);
5150 /* stack: ML MH H1 H2 L1 L2 */
5151 tmp = vtop[0];
5152 vtop[0] = vtop[-2];
5153 vtop[-2] = tmp;
5154 /* stack: ML MH H1 L2 H2 L1 */
5155 gen_op('*');
5156 vrotb(3);
5157 vrotb(3);
5158 gen_op('*');
5159 /* stack: ML MH M1 M2 */
5160 gen_op('+');
5161 gen_op('+');
5162 } else if (op == '+' || op == '-') {
5163 /* XXX: add non carry method too (for MIPS or alpha) */
5164 if (op == '+')
5165 op1 = TOK_ADDC1;
5166 else
5167 op1 = TOK_SUBC1;
5168 gen_op(op1);
5169 /* stack: H1 H2 (L1 op L2) */
5170 vrotb(3);
5171 vrotb(3);
5172 gen_op(op1 + 1); /* TOK_xxxC2 */
5173 } else {
5174 gen_op(op);
5175 /* stack: H1 H2 (L1 op L2) */
5176 vrotb(3);
5177 vrotb(3);
5178 /* stack: (L1 op L2) H1 H2 */
5179 gen_op(op);
5180 /* stack: (L1 op L2) (H1 op H2) */
5182 /* stack: L H */
5183 lbuild(t);
5184 break;
5185 case TOK_SAR:
5186 case TOK_SHR:
5187 case TOK_SHL:
5188 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5189 t = vtop[-1].type.t;
5190 vswap();
5191 lexpand();
5192 vrotb(3);
5193 /* stack: L H shift */
5194 c = (int)vtop->c.i;
5195 /* constant: simpler */
5196 /* NOTE: all comments are for SHL. the other cases are
5197 done by swaping words */
5198 vpop();
5199 if (op != TOK_SHL)
5200 vswap();
5201 if (c >= 32) {
5202 /* stack: L H */
5203 vpop();
5204 if (c > 32) {
5205 vpushi(c - 32);
5206 gen_op(op);
5208 if (op != TOK_SAR) {
5209 vpushi(0);
5210 } else {
5211 gv_dup();
5212 vpushi(31);
5213 gen_op(TOK_SAR);
5215 vswap();
5216 } else {
5217 vswap();
5218 gv_dup();
5219 /* stack: H L L */
5220 vpushi(c);
5221 gen_op(op);
5222 vswap();
5223 vpushi(32 - c);
5224 if (op == TOK_SHL)
5225 gen_op(TOK_SHR);
5226 else
5227 gen_op(TOK_SHL);
5228 vrotb(3);
5229 /* stack: L L H */
5230 vpushi(c);
5231 if (op == TOK_SHL)
5232 gen_op(TOK_SHL);
5233 else
5234 gen_op(TOK_SHR);
5235 gen_op('|');
5237 if (op != TOK_SHL)
5238 vswap();
5239 lbuild(t);
5240 } else {
5241 /* XXX: should provide a faster fallback on x86 ? */
5242 switch(op) {
5243 case TOK_SAR:
5244 func = TOK___sardi3;
5245 goto gen_func;
5246 case TOK_SHR:
5247 func = TOK___shrdi3;
5248 goto gen_func;
5249 case TOK_SHL:
5250 func = TOK___shldi3;
5251 goto gen_func;
5254 break;
5255 default:
5256 /* compare operations */
5257 t = vtop->type.t;
5258 vswap();
5259 lexpand();
5260 vrotb(3);
5261 lexpand();
5262 /* stack: L1 H1 L2 H2 */
5263 tmp = vtop[-1];
5264 vtop[-1] = vtop[-2];
5265 vtop[-2] = tmp;
5266 /* stack: L1 L2 H1 H2 */
5267 /* compare high */
5268 op1 = op;
5269 /* when values are equal, we need to compare low words. since
5270 the jump is inverted, we invert the test too. */
5271 if (op1 == TOK_LT)
5272 op1 = TOK_LE;
5273 else if (op1 == TOK_GT)
5274 op1 = TOK_GE;
5275 else if (op1 == TOK_ULT)
5276 op1 = TOK_ULE;
5277 else if (op1 == TOK_UGT)
5278 op1 = TOK_UGE;
5279 a = 0;
5280 b = 0;
5281 gen_op(op1);
5282 if (op1 != TOK_NE) {
5283 a = gtst(1, 0);
5285 if (op != TOK_EQ) {
5286 /* generate non equal test */
5287 /* XXX: NOT PORTABLE yet */
5288 if (a == 0) {
5289 b = gtst(0, 0);
5290 } else {
5291 #if defined(TCC_TARGET_I386)
5292 b = psym(0x850f, 0);
5293 #elif defined(TCC_TARGET_ARM)
5294 b = ind;
5295 o(0x1A000000 | encbranch(ind, 0, 1));
5296 #elif defined(TCC_TARGET_C67)
5297 error("not implemented");
5298 #else
5299 #error not supported
5300 #endif
5303 /* compare low. Always unsigned */
5304 op1 = op;
5305 if (op1 == TOK_LT)
5306 op1 = TOK_ULT;
5307 else if (op1 == TOK_LE)
5308 op1 = TOK_ULE;
5309 else if (op1 == TOK_GT)
5310 op1 = TOK_UGT;
5311 else if (op1 == TOK_GE)
5312 op1 = TOK_UGE;
5313 gen_op(op1);
5314 a = gtst(1, a);
5315 gsym(b);
5316 vseti(VT_JMPI, a);
5317 break;
5321 /* handle integer constant optimizations and various machine
5322 independent opt */
5323 void gen_opic(int op)
5325 int fc, c1, c2, n;
5326 SValue *v1, *v2;
5328 v1 = vtop - 1;
5329 v2 = vtop;
5330 /* currently, we cannot do computations with forward symbols */
5331 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5332 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5333 if (c1 && c2) {
5334 fc = v2->c.i;
5335 switch(op) {
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;
5340 case '|': v1->c.i |= fc; break;
5341 case '*': v1->c.i *= fc; break;
5343 case TOK_PDIV:
5344 case '/':
5345 case '%':
5346 case TOK_UDIV:
5347 case TOK_UMOD:
5348 /* if division by zero, generate explicit division */
5349 if (fc == 0) {
5350 if (const_wanted)
5351 error("division by zero in constant");
5352 goto general_case;
5354 switch(op) {
5355 default: v1->c.i /= fc; break;
5356 case '%': v1->c.i %= fc; break;
5357 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5358 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5360 break;
5361 case TOK_SHL: v1->c.i <<= fc; break;
5362 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5363 case TOK_SAR: v1->c.i >>= fc; break;
5364 /* tests */
5365 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5366 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5367 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5368 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5369 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5370 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5371 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5372 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5373 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5374 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5375 /* logical */
5376 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5377 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5378 default:
5379 goto general_case;
5381 vtop--;
5382 } else {
5383 /* if commutative ops, put c2 as constant */
5384 if (c1 && (op == '+' || op == '&' || op == '^' ||
5385 op == '|' || op == '*')) {
5386 vswap();
5387 swap(&c1, &c2);
5389 fc = vtop->c.i;
5390 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5391 op == TOK_PDIV) &&
5392 fc == 1) ||
5393 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5394 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5395 fc == 0) ||
5396 (op == '&' &&
5397 fc == -1))) {
5398 /* nothing to do */
5399 vtop--;
5400 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5401 /* try to use shifts instead of muls or divs */
5402 if (fc > 0 && (fc & (fc - 1)) == 0) {
5403 n = -1;
5404 while (fc) {
5405 fc >>= 1;
5406 n++;
5408 vtop->c.i = n;
5409 if (op == '*')
5410 op = TOK_SHL;
5411 else if (op == TOK_PDIV)
5412 op = TOK_SAR;
5413 else
5414 op = TOK_SHR;
5416 goto general_case;
5417 } else if (c2 && (op == '+' || op == '-') &&
5418 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5419 (VT_CONST | VT_SYM)) {
5420 /* symbol + constant case */
5421 if (op == '-')
5422 fc = -fc;
5423 vtop--;
5424 vtop->c.i += fc;
5425 } else {
5426 general_case:
5427 if (!nocode_wanted) {
5428 /* call low level op generator */
5429 gen_opi(op);
5430 } else {
5431 vtop--;
5437 /* generate a floating point operation with constant propagation */
5438 void gen_opif(int op)
5440 int c1, c2;
5441 SValue *v1, *v2;
5442 long double f1, f2;
5444 v1 = vtop - 1;
5445 v2 = vtop;
5446 /* currently, we cannot do computations with forward symbols */
5447 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5448 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5449 if (c1 && c2) {
5450 if (v1->type.t == VT_FLOAT) {
5451 f1 = v1->c.f;
5452 f2 = v2->c.f;
5453 } else if (v1->type.t == VT_DOUBLE) {
5454 f1 = v1->c.d;
5455 f2 = v2->c.d;
5456 } else {
5457 f1 = v1->c.ld;
5458 f2 = v2->c.ld;
5461 /* NOTE: we only do constant propagation if finite number (not
5462 NaN or infinity) (ANSI spec) */
5463 if (!ieee_finite(f1) || !ieee_finite(f2))
5464 goto general_case;
5466 switch(op) {
5467 case '+': f1 += f2; break;
5468 case '-': f1 -= f2; break;
5469 case '*': f1 *= f2; break;
5470 case '/':
5471 if (f2 == 0.0) {
5472 if (const_wanted)
5473 error("division by zero in constant");
5474 goto general_case;
5476 f1 /= f2;
5477 break;
5478 /* XXX: also handles tests ? */
5479 default:
5480 goto general_case;
5482 /* XXX: overflow test ? */
5483 if (v1->type.t == VT_FLOAT) {
5484 v1->c.f = f1;
5485 } else if (v1->type.t == VT_DOUBLE) {
5486 v1->c.d = f1;
5487 } else {
5488 v1->c.ld = f1;
5490 vtop--;
5491 } else {
5492 general_case:
5493 if (!nocode_wanted) {
5494 gen_opf(op);
5495 } else {
5496 vtop--;
5501 static int pointed_size(CType *type)
5503 int align;
5504 return type_size(pointed_type(type), &align);
5507 static inline int is_null_pointer(SValue *p)
5509 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5510 return 0;
5511 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5512 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5515 static inline int is_integer_btype(int bt)
5517 return (bt == VT_BYTE || bt == VT_SHORT ||
5518 bt == VT_INT || bt == VT_LLONG);
5521 /* check types for comparison or substraction of pointers */
5522 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5524 CType *type1, *type2, tmp_type1, tmp_type2;
5525 int bt1, bt2;
5527 /* null pointers are accepted for all comparisons as gcc */
5528 if (is_null_pointer(p1) || is_null_pointer(p2))
5529 return;
5530 type1 = &p1->type;
5531 type2 = &p2->type;
5532 bt1 = type1->t & VT_BTYPE;
5533 bt2 = type2->t & VT_BTYPE;
5534 /* accept comparison between pointer and integer with a warning */
5535 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5536 warning("comparison between pointer and integer");
5537 return;
5540 /* both must be pointers or implicit function pointers */
5541 if (bt1 == VT_PTR) {
5542 type1 = pointed_type(type1);
5543 } else if (bt1 != VT_FUNC)
5544 goto invalid_operands;
5546 if (bt2 == VT_PTR) {
5547 type2 = pointed_type(type2);
5548 } else if (bt2 != VT_FUNC) {
5549 invalid_operands:
5550 error("invalid operands to binary %s", get_tok_str(op, NULL));
5552 if ((type1->t & VT_BTYPE) == VT_VOID ||
5553 (type2->t & VT_BTYPE) == VT_VOID)
5554 return;
5555 tmp_type1 = *type1;
5556 tmp_type2 = *type2;
5557 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5558 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5559 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5560 /* gcc-like error if '-' is used */
5561 if (op == '-')
5562 goto invalid_operands;
5563 else
5564 warning("comparison of distinct pointer types lacks a cast");
5568 /* generic gen_op: handles types problems */
5569 void gen_op(int op)
5571 int u, t1, t2, bt1, bt2, t;
5572 CType type1;
5574 t1 = vtop[-1].type.t;
5575 t2 = vtop[0].type.t;
5576 bt1 = t1 & VT_BTYPE;
5577 bt2 = t2 & VT_BTYPE;
5579 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5580 /* at least one operand is a pointer */
5581 /* relationnal op: must be both pointers */
5582 if (op >= TOK_ULT && op <= TOK_GT) {
5583 check_comparison_pointer_types(vtop - 1, vtop, op);
5584 /* pointers are handled are unsigned */
5585 t = VT_INT | VT_UNSIGNED;
5586 goto std_op;
5588 /* if both pointers, then it must be the '-' op */
5589 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5590 if (op != '-')
5591 error("cannot use pointers here");
5592 check_comparison_pointer_types(vtop - 1, vtop, op);
5593 /* XXX: check that types are compatible */
5594 u = pointed_size(&vtop[-1].type);
5595 gen_opic(op);
5596 /* set to integer type */
5597 vtop->type.t = VT_INT;
5598 vpushi(u);
5599 gen_op(TOK_PDIV);
5600 } else {
5601 /* exactly one pointer : must be '+' or '-'. */
5602 if (op != '-' && op != '+')
5603 error("cannot use pointers here");
5604 /* Put pointer as first operand */
5605 if (bt2 == VT_PTR) {
5606 vswap();
5607 swap(&t1, &t2);
5609 type1 = vtop[-1].type;
5610 /* XXX: cast to int ? (long long case) */
5611 vpushi(pointed_size(&vtop[-1].type));
5612 gen_op('*');
5613 #ifdef CONFIG_TCC_BCHECK
5614 /* if evaluating constant expression, no code should be
5615 generated, so no bound check */
5616 if (do_bounds_check && !const_wanted) {
5617 /* if bounded pointers, we generate a special code to
5618 test bounds */
5619 if (op == '-') {
5620 vpushi(0);
5621 vswap();
5622 gen_op('-');
5624 gen_bounded_ptr_add();
5625 } else
5626 #endif
5628 gen_opic(op);
5630 /* put again type if gen_opic() swaped operands */
5631 vtop->type = type1;
5633 } else if (is_float(bt1) || is_float(bt2)) {
5634 /* compute bigger type and do implicit casts */
5635 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5636 t = VT_LDOUBLE;
5637 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5638 t = VT_DOUBLE;
5639 } else {
5640 t = VT_FLOAT;
5642 /* floats can only be used for a few operations */
5643 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5644 (op < TOK_ULT || op > TOK_GT))
5645 error("invalid operands for binary operation");
5646 goto std_op;
5647 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5648 /* cast to biggest op */
5649 t = VT_LLONG;
5650 /* convert to unsigned if it does not fit in a long long */
5651 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5652 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5653 t |= VT_UNSIGNED;
5654 goto std_op;
5655 } else {
5656 /* integer operations */
5657 t = VT_INT;
5658 /* convert to unsigned if it does not fit in an integer */
5659 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5660 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5661 t |= VT_UNSIGNED;
5662 std_op:
5663 /* XXX: currently, some unsigned operations are explicit, so
5664 we modify them here */
5665 if (t & VT_UNSIGNED) {
5666 if (op == TOK_SAR)
5667 op = TOK_SHR;
5668 else if (op == '/')
5669 op = TOK_UDIV;
5670 else if (op == '%')
5671 op = TOK_UMOD;
5672 else if (op == TOK_LT)
5673 op = TOK_ULT;
5674 else if (op == TOK_GT)
5675 op = TOK_UGT;
5676 else if (op == TOK_LE)
5677 op = TOK_ULE;
5678 else if (op == TOK_GE)
5679 op = TOK_UGE;
5681 vswap();
5682 type1.t = t;
5683 gen_cast(&type1);
5684 vswap();
5685 /* special case for shifts and long long: we keep the shift as
5686 an integer */
5687 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5688 type1.t = VT_INT;
5689 gen_cast(&type1);
5690 if (is_float(t))
5691 gen_opif(op);
5692 else if ((t & VT_BTYPE) == VT_LLONG)
5693 gen_opl(op);
5694 else
5695 gen_opic(op);
5696 if (op >= TOK_ULT && op <= TOK_GT) {
5697 /* relationnal op: the result is an int */
5698 vtop->type.t = VT_INT;
5699 } else {
5700 vtop->type.t = t;
5705 /* generic itof for unsigned long long case */
5706 void gen_cvt_itof1(int t)
5708 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5709 (VT_LLONG | VT_UNSIGNED)) {
5711 if (t == VT_FLOAT)
5712 vpush_global_sym(&func_old_type, TOK___ulltof);
5713 else if (t == VT_DOUBLE)
5714 vpush_global_sym(&func_old_type, TOK___ulltod);
5715 else
5716 vpush_global_sym(&func_old_type, TOK___ulltold);
5717 vrott(2);
5718 gfunc_call(1);
5719 vpushi(0);
5720 vtop->r = REG_FRET;
5721 } else {
5722 gen_cvt_itof(t);
5726 /* generic ftoi for unsigned long long case */
5727 void gen_cvt_ftoi1(int t)
5729 int st;
5731 if (t == (VT_LLONG | VT_UNSIGNED)) {
5732 /* not handled natively */
5733 st = vtop->type.t & VT_BTYPE;
5734 if (st == VT_FLOAT)
5735 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5736 else if (st == VT_DOUBLE)
5737 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5738 else
5739 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5740 vrott(2);
5741 gfunc_call(1);
5742 vpushi(0);
5743 vtop->r = REG_IRET;
5744 vtop->r2 = REG_LRET;
5745 } else {
5746 gen_cvt_ftoi(t);
5750 /* force char or short cast */
5751 void force_charshort_cast(int t)
5753 int bits, dbt;
5754 dbt = t & VT_BTYPE;
5755 /* XXX: add optimization if lvalue : just change type and offset */
5756 if (dbt == VT_BYTE)
5757 bits = 8;
5758 else
5759 bits = 16;
5760 if (t & VT_UNSIGNED) {
5761 vpushi((1 << bits) - 1);
5762 gen_op('&');
5763 } else {
5764 bits = 32 - bits;
5765 vpushi(bits);
5766 gen_op(TOK_SHL);
5767 /* result must be signed or the SAR is converted to an SHL
5768 This was not the case when "t" was a signed short
5769 and the last value on the stack was an unsigned int */
5770 vtop->type.t &= ~VT_UNSIGNED;
5771 vpushi(bits);
5772 gen_op(TOK_SAR);
5776 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5777 static void gen_cast(CType *type)
5779 int sbt, dbt, sf, df, c;
5781 /* special delayed cast for char/short */
5782 /* XXX: in some cases (multiple cascaded casts), it may still
5783 be incorrect */
5784 if (vtop->r & VT_MUSTCAST) {
5785 vtop->r &= ~VT_MUSTCAST;
5786 force_charshort_cast(vtop->type.t);
5789 /* bitfields first get cast to ints */
5790 if (vtop->type.t & VT_BITFIELD) {
5791 gv(RC_INT);
5794 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5795 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5797 if (sbt != dbt && !nocode_wanted) {
5798 sf = is_float(sbt);
5799 df = is_float(dbt);
5800 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5801 if (sf && df) {
5802 /* convert from fp to fp */
5803 if (c) {
5804 /* constant case: we can do it now */
5805 /* XXX: in ISOC, cannot do it if error in convert */
5806 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5807 vtop->c.f = (float)vtop->c.d;
5808 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5809 vtop->c.f = (float)vtop->c.ld;
5810 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5811 vtop->c.d = (double)vtop->c.f;
5812 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5813 vtop->c.d = (double)vtop->c.ld;
5814 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5815 vtop->c.ld = (long double)vtop->c.f;
5816 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5817 vtop->c.ld = (long double)vtop->c.d;
5818 } else {
5819 /* non constant case: generate code */
5820 gen_cvt_ftof(dbt);
5822 } else if (df) {
5823 /* convert int to fp */
5824 if (c) {
5825 switch(sbt) {
5826 case VT_LLONG | VT_UNSIGNED:
5827 case VT_LLONG:
5828 /* XXX: add const cases for long long */
5829 goto do_itof;
5830 case VT_INT | VT_UNSIGNED:
5831 switch(dbt) {
5832 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5833 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5834 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5836 break;
5837 default:
5838 switch(dbt) {
5839 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5840 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5841 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5843 break;
5845 } else {
5846 do_itof:
5847 #if !defined(TCC_TARGET_ARM)
5848 gen_cvt_itof1(dbt);
5849 #else
5850 gen_cvt_itof(dbt);
5851 #endif
5853 } else if (sf) {
5854 /* convert fp to int */
5855 /* we handle char/short/etc... with generic code */
5856 if (dbt != (VT_INT | VT_UNSIGNED) &&
5857 dbt != (VT_LLONG | VT_UNSIGNED) &&
5858 dbt != VT_LLONG)
5859 dbt = VT_INT;
5860 if (c) {
5861 switch(dbt) {
5862 case VT_LLONG | VT_UNSIGNED:
5863 case VT_LLONG:
5864 /* XXX: add const cases for long long */
5865 goto do_ftoi;
5866 case VT_INT | VT_UNSIGNED:
5867 switch(sbt) {
5868 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5869 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5870 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5872 break;
5873 default:
5874 /* int case */
5875 switch(sbt) {
5876 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5877 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5878 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5880 break;
5882 } else {
5883 do_ftoi:
5884 gen_cvt_ftoi1(dbt);
5886 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5887 /* additional cast for char/short/bool... */
5888 vtop->type.t = dbt;
5889 gen_cast(type);
5891 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5892 if ((sbt & VT_BTYPE) != VT_LLONG) {
5893 /* scalar to long long */
5894 if (c) {
5895 if (sbt == (VT_INT | VT_UNSIGNED))
5896 vtop->c.ll = vtop->c.ui;
5897 else
5898 vtop->c.ll = vtop->c.i;
5899 } else {
5900 /* machine independent conversion */
5901 gv(RC_INT);
5902 /* generate high word */
5903 if (sbt == (VT_INT | VT_UNSIGNED)) {
5904 vpushi(0);
5905 gv(RC_INT);
5906 } else {
5907 gv_dup();
5908 vpushi(31);
5909 gen_op(TOK_SAR);
5911 /* patch second register */
5912 vtop[-1].r2 = vtop->r;
5913 vpop();
5916 } else if (dbt == VT_BOOL) {
5917 /* scalar to bool */
5918 vpushi(0);
5919 gen_op(TOK_NE);
5920 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5921 (dbt & VT_BTYPE) == VT_SHORT) {
5922 force_charshort_cast(dbt);
5923 } else if ((dbt & VT_BTYPE) == VT_INT) {
5924 /* scalar to int */
5925 if (sbt == VT_LLONG) {
5926 /* from long long: just take low order word */
5927 lexpand();
5928 vpop();
5930 /* if lvalue and single word type, nothing to do because
5931 the lvalue already contains the real type size (see
5932 VT_LVAL_xxx constants) */
5935 vtop->type = *type;
5938 /* return type size. Put alignment at 'a' */
5939 static int type_size(CType *type, int *a)
5941 Sym *s;
5942 int bt;
5944 bt = type->t & VT_BTYPE;
5945 if (bt == VT_STRUCT) {
5946 /* struct/union */
5947 s = type->ref;
5948 *a = s->r;
5949 return s->c;
5950 } else if (bt == VT_PTR) {
5951 if (type->t & VT_ARRAY) {
5952 s = type->ref;
5953 return type_size(&s->type, a) * s->c;
5954 } else {
5955 *a = PTR_SIZE;
5956 return PTR_SIZE;
5958 } else if (bt == VT_LDOUBLE) {
5959 *a = LDOUBLE_ALIGN;
5960 return LDOUBLE_SIZE;
5961 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5962 #ifdef TCC_TARGET_I386
5963 *a = 4;
5964 #else
5965 *a = 8;
5966 #endif
5967 return 8;
5968 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5969 *a = 4;
5970 return 4;
5971 } else if (bt == VT_SHORT) {
5972 *a = 2;
5973 return 2;
5974 } else {
5975 /* char, void, function, _Bool */
5976 *a = 1;
5977 return 1;
5981 /* return the pointed type of t */
5982 static inline CType *pointed_type(CType *type)
5984 return &type->ref->type;
5987 /* modify type so that its it is a pointer to type. */
5988 static void mk_pointer(CType *type)
5990 Sym *s;
5991 s = sym_push(SYM_FIELD, type, 0, -1);
5992 type->t = VT_PTR | (type->t & ~VT_TYPE);
5993 type->ref = s;
5996 /* compare function types. OLD functions match any new functions */
5997 static int is_compatible_func(CType *type1, CType *type2)
5999 Sym *s1, *s2;
6001 s1 = type1->ref;
6002 s2 = type2->ref;
6003 if (!is_compatible_types(&s1->type, &s2->type))
6004 return 0;
6005 /* check func_call */
6006 if (s1->r != s2->r)
6007 return 0;
6008 /* XXX: not complete */
6009 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6010 return 1;
6011 if (s1->c != s2->c)
6012 return 0;
6013 while (s1 != NULL) {
6014 if (s2 == NULL)
6015 return 0;
6016 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6017 return 0;
6018 s1 = s1->next;
6019 s2 = s2->next;
6021 if (s2)
6022 return 0;
6023 return 1;
6026 /* return true if type1 and type2 are the same. If unqualified is
6027 true, qualifiers on the types are ignored.
6029 - enums are not checked as gcc __builtin_types_compatible_p ()
6031 static int compare_types(CType *type1, CType *type2, int unqualified)
6033 int bt1, t1, t2;
6035 t1 = type1->t & VT_TYPE;
6036 t2 = type2->t & VT_TYPE;
6037 if (unqualified) {
6038 /* strip qualifiers before comparing */
6039 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6040 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6042 /* XXX: bitfields ? */
6043 if (t1 != t2)
6044 return 0;
6045 /* test more complicated cases */
6046 bt1 = t1 & VT_BTYPE;
6047 if (bt1 == VT_PTR) {
6048 type1 = pointed_type(type1);
6049 type2 = pointed_type(type2);
6050 return is_compatible_types(type1, type2);
6051 } else if (bt1 == VT_STRUCT) {
6052 return (type1->ref == type2->ref);
6053 } else if (bt1 == VT_FUNC) {
6054 return is_compatible_func(type1, type2);
6055 } else {
6056 return 1;
6060 /* return true if type1 and type2 are exactly the same (including
6061 qualifiers).
6063 static int is_compatible_types(CType *type1, CType *type2)
6065 return compare_types(type1,type2,0);
6068 /* return true if type1 and type2 are the same (ignoring qualifiers).
6070 static int is_compatible_parameter_types(CType *type1, CType *type2)
6072 return compare_types(type1,type2,1);
6075 /* print a type. If 'varstr' is not NULL, then the variable is also
6076 printed in the type */
6077 /* XXX: union */
6078 /* XXX: add array and function pointers */
6079 void type_to_str(char *buf, int buf_size,
6080 CType *type, const char *varstr)
6082 int bt, v, t;
6083 Sym *s, *sa;
6084 char buf1[256];
6085 const char *tstr;
6087 t = type->t & VT_TYPE;
6088 bt = t & VT_BTYPE;
6089 buf[0] = '\0';
6090 if (t & VT_CONSTANT)
6091 pstrcat(buf, buf_size, "const ");
6092 if (t & VT_VOLATILE)
6093 pstrcat(buf, buf_size, "volatile ");
6094 if (t & VT_UNSIGNED)
6095 pstrcat(buf, buf_size, "unsigned ");
6096 switch(bt) {
6097 case VT_VOID:
6098 tstr = "void";
6099 goto add_tstr;
6100 case VT_BOOL:
6101 tstr = "_Bool";
6102 goto add_tstr;
6103 case VT_BYTE:
6104 tstr = "char";
6105 goto add_tstr;
6106 case VT_SHORT:
6107 tstr = "short";
6108 goto add_tstr;
6109 case VT_INT:
6110 tstr = "int";
6111 goto add_tstr;
6112 case VT_LONG:
6113 tstr = "long";
6114 goto add_tstr;
6115 case VT_LLONG:
6116 tstr = "long long";
6117 goto add_tstr;
6118 case VT_FLOAT:
6119 tstr = "float";
6120 goto add_tstr;
6121 case VT_DOUBLE:
6122 tstr = "double";
6123 goto add_tstr;
6124 case VT_LDOUBLE:
6125 tstr = "long double";
6126 add_tstr:
6127 pstrcat(buf, buf_size, tstr);
6128 break;
6129 case VT_ENUM:
6130 case VT_STRUCT:
6131 if (bt == VT_STRUCT)
6132 tstr = "struct ";
6133 else
6134 tstr = "enum ";
6135 pstrcat(buf, buf_size, tstr);
6136 v = type->ref->v & ~SYM_STRUCT;
6137 if (v >= SYM_FIRST_ANOM)
6138 pstrcat(buf, buf_size, "<anonymous>");
6139 else
6140 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6141 break;
6142 case VT_FUNC:
6143 s = type->ref;
6144 type_to_str(buf, buf_size, &s->type, varstr);
6145 pstrcat(buf, buf_size, "(");
6146 sa = s->next;
6147 while (sa != NULL) {
6148 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6149 pstrcat(buf, buf_size, buf1);
6150 sa = sa->next;
6151 if (sa)
6152 pstrcat(buf, buf_size, ", ");
6154 pstrcat(buf, buf_size, ")");
6155 goto no_var;
6156 case VT_PTR:
6157 s = type->ref;
6158 pstrcpy(buf1, sizeof(buf1), "*");
6159 if (varstr)
6160 pstrcat(buf1, sizeof(buf1), varstr);
6161 type_to_str(buf, buf_size, &s->type, buf1);
6162 goto no_var;
6164 if (varstr) {
6165 pstrcat(buf, buf_size, " ");
6166 pstrcat(buf, buf_size, varstr);
6168 no_var: ;
6171 /* verify type compatibility to store vtop in 'dt' type, and generate
6172 casts if needed. */
6173 static void gen_assign_cast(CType *dt)
6175 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6176 char buf1[256], buf2[256];
6177 int dbt, sbt;
6179 st = &vtop->type; /* source type */
6180 dbt = dt->t & VT_BTYPE;
6181 sbt = st->t & VT_BTYPE;
6182 if (dt->t & VT_CONSTANT)
6183 warning("assignment of read-only location");
6184 switch(dbt) {
6185 case VT_PTR:
6186 /* special cases for pointers */
6187 /* '0' can also be a pointer */
6188 if (is_null_pointer(vtop))
6189 goto type_ok;
6190 /* accept implicit pointer to integer cast with warning */
6191 if (is_integer_btype(sbt)) {
6192 warning("assignment makes pointer from integer without a cast");
6193 goto type_ok;
6195 type1 = pointed_type(dt);
6196 /* a function is implicitely a function pointer */
6197 if (sbt == VT_FUNC) {
6198 if ((type1->t & VT_BTYPE) != VT_VOID &&
6199 !is_compatible_types(pointed_type(dt), st))
6200 goto error;
6201 else
6202 goto type_ok;
6204 if (sbt != VT_PTR)
6205 goto error;
6206 type2 = pointed_type(st);
6207 if ((type1->t & VT_BTYPE) == VT_VOID ||
6208 (type2->t & VT_BTYPE) == VT_VOID) {
6209 /* void * can match anything */
6210 } else {
6211 /* exact type match, except for unsigned */
6212 tmp_type1 = *type1;
6213 tmp_type2 = *type2;
6214 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6215 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6216 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6217 goto error;
6219 /* check const and volatile */
6220 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6221 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6222 warning("assignment discards qualifiers from pointer target type");
6223 break;
6224 case VT_BYTE:
6225 case VT_SHORT:
6226 case VT_INT:
6227 case VT_LLONG:
6228 if (sbt == VT_PTR || sbt == VT_FUNC) {
6229 warning("assignment makes integer from pointer without a cast");
6231 /* XXX: more tests */
6232 break;
6233 case VT_STRUCT:
6234 tmp_type1 = *dt;
6235 tmp_type2 = *st;
6236 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6237 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6238 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6239 error:
6240 type_to_str(buf1, sizeof(buf1), st, NULL);
6241 type_to_str(buf2, sizeof(buf2), dt, NULL);
6242 error("cannot cast '%s' to '%s'", buf1, buf2);
6244 break;
6246 type_ok:
6247 gen_cast(dt);
6250 /* store vtop in lvalue pushed on stack */
6251 void vstore(void)
6253 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6255 ft = vtop[-1].type.t;
6256 sbt = vtop->type.t & VT_BTYPE;
6257 dbt = ft & VT_BTYPE;
6258 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6259 (sbt == VT_INT && dbt == VT_SHORT)) {
6260 /* optimize char/short casts */
6261 delayed_cast = VT_MUSTCAST;
6262 vtop->type.t = ft & VT_TYPE;
6263 /* XXX: factorize */
6264 if (ft & VT_CONSTANT)
6265 warning("assignment of read-only location");
6266 } else {
6267 delayed_cast = 0;
6268 if (!(ft & VT_BITFIELD))
6269 gen_assign_cast(&vtop[-1].type);
6272 if (sbt == VT_STRUCT) {
6273 /* if structure, only generate pointer */
6274 /* structure assignment : generate memcpy */
6275 /* XXX: optimize if small size */
6276 if (!nocode_wanted) {
6277 size = type_size(&vtop->type, &align);
6279 vpush_global_sym(&func_old_type, TOK_memcpy);
6281 /* destination */
6282 vpushv(vtop - 2);
6283 vtop->type.t = VT_INT;
6284 gaddrof();
6285 /* source */
6286 vpushv(vtop - 2);
6287 vtop->type.t = VT_INT;
6288 gaddrof();
6289 /* type size */
6290 vpushi(size);
6291 gfunc_call(3);
6293 vswap();
6294 vpop();
6295 } else {
6296 vswap();
6297 vpop();
6299 /* leave source on stack */
6300 } else if (ft & VT_BITFIELD) {
6301 /* bitfield store handling */
6302 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6303 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6304 /* remove bit field info to avoid loops */
6305 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6307 /* duplicate destination */
6308 vdup();
6309 vtop[-1] = vtop[-2];
6311 /* mask and shift source */
6312 vpushi((1 << bit_size) - 1);
6313 gen_op('&');
6314 vpushi(bit_pos);
6315 gen_op(TOK_SHL);
6316 /* load destination, mask and or with source */
6317 vswap();
6318 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6319 gen_op('&');
6320 gen_op('|');
6321 /* store result */
6322 vstore();
6323 } else {
6324 #ifdef CONFIG_TCC_BCHECK
6325 /* bound check case */
6326 if (vtop[-1].r & VT_MUSTBOUND) {
6327 vswap();
6328 gbound();
6329 vswap();
6331 #endif
6332 if (!nocode_wanted) {
6333 rc = RC_INT;
6334 if (is_float(ft))
6335 rc = RC_FLOAT;
6336 r = gv(rc); /* generate value */
6337 /* if lvalue was saved on stack, must read it */
6338 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6339 SValue sv;
6340 t = get_reg(RC_INT);
6341 sv.type.t = VT_INT;
6342 sv.r = VT_LOCAL | VT_LVAL;
6343 sv.c.ul = vtop[-1].c.ul;
6344 load(t, &sv);
6345 vtop[-1].r = t | VT_LVAL;
6347 store(r, vtop - 1);
6348 /* two word case handling : store second register at word + 4 */
6349 if ((ft & VT_BTYPE) == VT_LLONG) {
6350 vswap();
6351 /* convert to int to increment easily */
6352 vtop->type.t = VT_INT;
6353 gaddrof();
6354 vpushi(4);
6355 gen_op('+');
6356 vtop->r |= VT_LVAL;
6357 vswap();
6358 /* XXX: it works because r2 is spilled last ! */
6359 store(vtop->r2, vtop - 1);
6362 vswap();
6363 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6364 vtop->r |= delayed_cast;
6368 /* post defines POST/PRE add. c is the token ++ or -- */
6369 void inc(int post, int c)
6371 test_lvalue();
6372 vdup(); /* save lvalue */
6373 if (post) {
6374 gv_dup(); /* duplicate value */
6375 vrotb(3);
6376 vrotb(3);
6378 /* add constant */
6379 vpushi(c - TOK_MID);
6380 gen_op('+');
6381 vstore(); /* store value */
6382 if (post)
6383 vpop(); /* if post op, return saved value */
6386 /* Parse GNUC __attribute__ extension. Currently, the following
6387 extensions are recognized:
6388 - aligned(n) : set data/function alignment.
6389 - packed : force data alignment to 1
6390 - section(x) : generate data/code in this section.
6391 - unused : currently ignored, but may be used someday.
6392 - regparm(n) : pass function parameters in registers (i386 only)
6394 static void parse_attribute(AttributeDef *ad)
6396 int t, n;
6398 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6399 next();
6400 skip('(');
6401 skip('(');
6402 while (tok != ')') {
6403 if (tok < TOK_IDENT)
6404 expect("attribute name");
6405 t = tok;
6406 next();
6407 switch(t) {
6408 case TOK_SECTION1:
6409 case TOK_SECTION2:
6410 skip('(');
6411 if (tok != TOK_STR)
6412 expect("section name");
6413 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6414 next();
6415 skip(')');
6416 break;
6417 case TOK_ALIGNED1:
6418 case TOK_ALIGNED2:
6419 if (tok == '(') {
6420 next();
6421 n = expr_const();
6422 if (n <= 0 || (n & (n - 1)) != 0)
6423 error("alignment must be a positive power of two");
6424 skip(')');
6425 } else {
6426 n = MAX_ALIGN;
6428 ad->aligned = n;
6429 break;
6430 case TOK_PACKED1:
6431 case TOK_PACKED2:
6432 ad->packed = 1;
6433 break;
6434 case TOK_UNUSED1:
6435 case TOK_UNUSED2:
6436 /* currently, no need to handle it because tcc does not
6437 track unused objects */
6438 break;
6439 case TOK_NORETURN1:
6440 case TOK_NORETURN2:
6441 /* currently, no need to handle it because tcc does not
6442 track unused objects */
6443 break;
6444 case TOK_CDECL1:
6445 case TOK_CDECL2:
6446 case TOK_CDECL3:
6447 ad->func_call = FUNC_CDECL;
6448 break;
6449 case TOK_STDCALL1:
6450 case TOK_STDCALL2:
6451 case TOK_STDCALL3:
6452 ad->func_call = FUNC_STDCALL;
6453 break;
6454 #ifdef TCC_TARGET_I386
6455 case TOK_REGPARM1:
6456 case TOK_REGPARM2:
6457 skip('(');
6458 n = expr_const();
6459 if (n > 3)
6460 n = 3;
6461 else if (n < 0)
6462 n = 0;
6463 if (n > 0)
6464 ad->func_call = FUNC_FASTCALL1 + n - 1;
6465 skip(')');
6466 break;
6467 case TOK_FASTCALL1:
6468 case TOK_FASTCALL2:
6469 case TOK_FASTCALL3:
6470 ad->func_call = FUNC_FASTCALLW;
6471 break;
6472 #endif
6473 case TOK_DLLEXPORT:
6474 ad->dllexport = 1;
6475 break;
6476 default:
6477 if (tcc_state->warn_unsupported)
6478 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6479 /* skip parameters */
6480 /* XXX: skip parenthesis too */
6481 if (tok == '(') {
6482 next();
6483 while (tok != ')' && tok != -1)
6484 next();
6485 next();
6487 break;
6489 if (tok != ',')
6490 break;
6491 next();
6493 skip(')');
6494 skip(')');
6498 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6499 static void struct_decl(CType *type, int u)
6501 int a, v, size, align, maxalign, c, offset;
6502 int bit_size, bit_pos, bsize, bt, lbit_pos;
6503 Sym *s, *ss, *ass, **ps;
6504 AttributeDef ad;
6505 CType type1, btype;
6507 a = tok; /* save decl type */
6508 next();
6509 if (tok != '{') {
6510 v = tok;
6511 next();
6512 /* struct already defined ? return it */
6513 if (v < TOK_IDENT)
6514 expect("struct/union/enum name");
6515 s = struct_find(v);
6516 if (s) {
6517 if (s->type.t != a)
6518 error("invalid type");
6519 goto do_decl;
6521 } else {
6522 v = anon_sym++;
6524 type1.t = a;
6525 /* we put an undefined size for struct/union */
6526 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6527 s->r = 0; /* default alignment is zero as gcc */
6528 /* put struct/union/enum name in type */
6529 do_decl:
6530 type->t = u;
6531 type->ref = s;
6533 if (tok == '{') {
6534 next();
6535 if (s->c != -1)
6536 error("struct/union/enum already defined");
6537 /* cannot be empty */
6538 c = 0;
6539 /* non empty enums are not allowed */
6540 if (a == TOK_ENUM) {
6541 for(;;) {
6542 v = tok;
6543 if (v < TOK_UIDENT)
6544 expect("identifier");
6545 next();
6546 if (tok == '=') {
6547 next();
6548 c = expr_const();
6550 /* enum symbols have static storage */
6551 ss = sym_push(v, &int_type, VT_CONST, c);
6552 ss->type.t |= VT_STATIC;
6553 if (tok != ',')
6554 break;
6555 next();
6556 c++;
6557 /* NOTE: we accept a trailing comma */
6558 if (tok == '}')
6559 break;
6561 skip('}');
6562 } else {
6563 maxalign = 1;
6564 ps = &s->next;
6565 bit_pos = 0;
6566 offset = 0;
6567 while (tok != '}') {
6568 parse_btype(&btype, &ad);
6569 while (1) {
6570 bit_size = -1;
6571 v = 0;
6572 type1 = btype;
6573 if (tok != ':') {
6574 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6575 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6576 expect("identifier");
6577 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6578 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6579 error("invalid type for '%s'",
6580 get_tok_str(v, NULL));
6582 if (tok == ':') {
6583 next();
6584 bit_size = expr_const();
6585 /* XXX: handle v = 0 case for messages */
6586 if (bit_size < 0)
6587 error("negative width in bit-field '%s'",
6588 get_tok_str(v, NULL));
6589 if (v && bit_size == 0)
6590 error("zero width for bit-field '%s'",
6591 get_tok_str(v, NULL));
6593 size = type_size(&type1, &align);
6594 if (ad.aligned) {
6595 if (align < ad.aligned)
6596 align = ad.aligned;
6597 } else if (ad.packed) {
6598 align = 1;
6599 } else if (*tcc_state->pack_stack_ptr) {
6600 if (align > *tcc_state->pack_stack_ptr)
6601 align = *tcc_state->pack_stack_ptr;
6603 lbit_pos = 0;
6604 if (bit_size >= 0) {
6605 bt = type1.t & VT_BTYPE;
6606 if (bt != VT_INT &&
6607 bt != VT_BYTE &&
6608 bt != VT_SHORT &&
6609 bt != VT_BOOL &&
6610 bt != VT_ENUM)
6611 error("bitfields must have scalar type");
6612 bsize = size * 8;
6613 if (bit_size > bsize) {
6614 error("width of '%s' exceeds its type",
6615 get_tok_str(v, NULL));
6616 } else if (bit_size == bsize) {
6617 /* no need for bit fields */
6618 bit_pos = 0;
6619 } else if (bit_size == 0) {
6620 /* XXX: what to do if only padding in a
6621 structure ? */
6622 /* zero size: means to pad */
6623 if (bit_pos > 0)
6624 bit_pos = bsize;
6625 } else {
6626 /* we do not have enough room ? */
6627 if ((bit_pos + bit_size) > bsize)
6628 bit_pos = 0;
6629 lbit_pos = bit_pos;
6630 /* XXX: handle LSB first */
6631 type1.t |= VT_BITFIELD |
6632 (bit_pos << VT_STRUCT_SHIFT) |
6633 (bit_size << (VT_STRUCT_SHIFT + 6));
6634 bit_pos += bit_size;
6636 } else {
6637 bit_pos = 0;
6639 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
6640 /* add new memory data only if starting
6641 bit field */
6642 if (lbit_pos == 0) {
6643 if (a == TOK_STRUCT) {
6644 c = (c + align - 1) & -align;
6645 offset = c;
6646 c += size;
6647 } else {
6648 offset = 0;
6649 if (size > c)
6650 c = size;
6652 if (align > maxalign)
6653 maxalign = align;
6655 #if 0
6656 printf("add field %s offset=%d",
6657 get_tok_str(v, NULL), offset);
6658 if (type1.t & VT_BITFIELD) {
6659 printf(" pos=%d size=%d",
6660 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6661 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6663 printf("\n");
6664 #endif
6666 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
6667 ass = type1.ref;
6668 while ((ass = ass->next) != NULL) {
6669 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
6670 *ps = ss;
6671 ps = &ss->next;
6673 } else if (v) {
6674 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6675 *ps = ss;
6676 ps = &ss->next;
6678 if (tok == ';' || tok == TOK_EOF)
6679 break;
6680 skip(',');
6682 skip(';');
6684 skip('}');
6685 /* store size and alignment */
6686 s->c = (c + maxalign - 1) & -maxalign;
6687 s->r = maxalign;
6692 /* return 0 if no type declaration. otherwise, return the basic type
6693 and skip it.
6695 static int parse_btype(CType *type, AttributeDef *ad)
6697 int t, u, type_found, typespec_found;
6698 Sym *s;
6699 CType type1;
6701 memset(ad, 0, sizeof(AttributeDef));
6702 type_found = 0;
6703 typespec_found = 0;
6704 t = 0;
6705 while(1) {
6706 switch(tok) {
6707 case TOK_EXTENSION:
6708 /* currently, we really ignore extension */
6709 next();
6710 continue;
6712 /* basic types */
6713 case TOK_CHAR:
6714 u = VT_BYTE;
6715 basic_type:
6716 next();
6717 basic_type1:
6718 if ((t & VT_BTYPE) != 0)
6719 error("too many basic types");
6720 t |= u;
6721 typespec_found = 1;
6722 break;
6723 case TOK_VOID:
6724 u = VT_VOID;
6725 goto basic_type;
6726 case TOK_SHORT:
6727 u = VT_SHORT;
6728 goto basic_type;
6729 case TOK_INT:
6730 next();
6731 typespec_found = 1;
6732 break;
6733 case TOK_LONG:
6734 next();
6735 if ((t & VT_BTYPE) == VT_DOUBLE) {
6736 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6737 } else if ((t & VT_BTYPE) == VT_LONG) {
6738 t = (t & ~VT_BTYPE) | VT_LLONG;
6739 } else {
6740 u = VT_LONG;
6741 goto basic_type1;
6743 break;
6744 case TOK_BOOL:
6745 u = VT_BOOL;
6746 goto basic_type;
6747 case TOK_FLOAT:
6748 u = VT_FLOAT;
6749 goto basic_type;
6750 case TOK_DOUBLE:
6751 next();
6752 if ((t & VT_BTYPE) == VT_LONG) {
6753 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6754 } else {
6755 u = VT_DOUBLE;
6756 goto basic_type1;
6758 break;
6759 case TOK_ENUM:
6760 struct_decl(&type1, VT_ENUM);
6761 basic_type2:
6762 u = type1.t;
6763 type->ref = type1.ref;
6764 goto basic_type1;
6765 case TOK_STRUCT:
6766 case TOK_UNION:
6767 struct_decl(&type1, VT_STRUCT);
6768 goto basic_type2;
6770 /* type modifiers */
6771 case TOK_CONST1:
6772 case TOK_CONST2:
6773 case TOK_CONST3:
6774 t |= VT_CONSTANT;
6775 next();
6776 break;
6777 case TOK_VOLATILE1:
6778 case TOK_VOLATILE2:
6779 case TOK_VOLATILE3:
6780 t |= VT_VOLATILE;
6781 next();
6782 break;
6783 case TOK_SIGNED1:
6784 case TOK_SIGNED2:
6785 case TOK_SIGNED3:
6786 typespec_found = 1;
6787 t |= VT_SIGNED;
6788 next();
6789 break;
6790 case TOK_REGISTER:
6791 case TOK_AUTO:
6792 case TOK_RESTRICT1:
6793 case TOK_RESTRICT2:
6794 case TOK_RESTRICT3:
6795 next();
6796 break;
6797 case TOK_UNSIGNED:
6798 t |= VT_UNSIGNED;
6799 next();
6800 typespec_found = 1;
6801 break;
6803 /* storage */
6804 case TOK_EXTERN:
6805 t |= VT_EXTERN;
6806 next();
6807 break;
6808 case TOK_STATIC:
6809 t |= VT_STATIC;
6810 next();
6811 break;
6812 case TOK_TYPEDEF:
6813 t |= VT_TYPEDEF;
6814 next();
6815 break;
6816 case TOK_INLINE1:
6817 case TOK_INLINE2:
6818 case TOK_INLINE3:
6819 t |= VT_INLINE;
6820 next();
6821 break;
6823 /* GNUC attribute */
6824 case TOK_ATTRIBUTE1:
6825 case TOK_ATTRIBUTE2:
6826 parse_attribute(ad);
6827 break;
6828 /* GNUC typeof */
6829 case TOK_TYPEOF1:
6830 case TOK_TYPEOF2:
6831 case TOK_TYPEOF3:
6832 next();
6833 parse_expr_type(&type1);
6834 goto basic_type2;
6835 default:
6836 if (typespec_found)
6837 goto the_end;
6838 s = sym_find(tok);
6839 if (!s || !(s->type.t & VT_TYPEDEF))
6840 goto the_end;
6841 t |= (s->type.t & ~VT_TYPEDEF);
6842 type->ref = s->type.ref;
6843 next();
6844 typespec_found = 1;
6845 break;
6847 type_found = 1;
6849 the_end:
6850 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6851 error("signed and unsigned modifier");
6852 if (tcc_state->char_is_unsigned) {
6853 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6854 t |= VT_UNSIGNED;
6856 t &= ~VT_SIGNED;
6858 /* long is never used as type */
6859 if ((t & VT_BTYPE) == VT_LONG)
6860 t = (t & ~VT_BTYPE) | VT_INT;
6861 type->t = t;
6862 return type_found;
6865 /* convert a function parameter type (array to pointer and function to
6866 function pointer) */
6867 static inline void convert_parameter_type(CType *pt)
6869 /* remove const and volatile qualifiers (XXX: const could be used
6870 to indicate a const function parameter */
6871 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6872 /* array must be transformed to pointer according to ANSI C */
6873 pt->t &= ~VT_ARRAY;
6874 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6875 mk_pointer(pt);
6879 static void post_type(CType *type, AttributeDef *ad)
6881 int n, l, t1;
6882 Sym **plast, *s, *first;
6883 AttributeDef ad1;
6884 CType pt;
6886 if (tok == '(') {
6887 /* function declaration */
6888 next();
6889 l = 0;
6890 first = NULL;
6891 plast = &first;
6892 if (tok != ')') {
6893 for(;;) {
6894 /* read param name and compute offset */
6895 if (l != FUNC_OLD) {
6896 if (!parse_btype(&pt, &ad1)) {
6897 if (l) {
6898 error("invalid type");
6899 } else {
6900 l = FUNC_OLD;
6901 goto old_proto;
6904 l = FUNC_NEW;
6905 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6906 break;
6907 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6908 if ((pt.t & VT_BTYPE) == VT_VOID)
6909 error("parameter declared as void");
6910 } else {
6911 old_proto:
6912 n = tok;
6913 if (n < TOK_UIDENT)
6914 expect("identifier");
6915 pt.t = VT_INT;
6916 next();
6918 convert_parameter_type(&pt);
6919 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6920 *plast = s;
6921 plast = &s->next;
6922 if (tok == ')')
6923 break;
6924 skip(',');
6925 if (l == FUNC_NEW && tok == TOK_DOTS) {
6926 l = FUNC_ELLIPSIS;
6927 next();
6928 break;
6932 /* if no parameters, then old type prototype */
6933 if (l == 0)
6934 l = FUNC_OLD;
6935 skip(')');
6936 t1 = type->t & VT_STORAGE;
6937 /* NOTE: const is ignored in returned type as it has a special
6938 meaning in gcc / C++ */
6939 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6940 post_type(type, ad);
6941 /* we push a anonymous symbol which will contain the function prototype */
6942 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6943 s->next = first;
6944 type->t = t1 | VT_FUNC;
6945 type->ref = s;
6946 } else if (tok == '[') {
6947 /* array definition */
6948 next();
6949 n = -1;
6950 if (tok != ']') {
6951 n = expr_const();
6952 if (n < 0)
6953 error("invalid array size");
6955 skip(']');
6956 /* parse next post type */
6957 t1 = type->t & VT_STORAGE;
6958 type->t &= ~VT_STORAGE;
6959 post_type(type, ad);
6961 /* we push a anonymous symbol which will contain the array
6962 element type */
6963 s = sym_push(SYM_FIELD, type, 0, n);
6964 type->t = t1 | VT_ARRAY | VT_PTR;
6965 type->ref = s;
6969 /* Parse a type declaration (except basic type), and return the type
6970 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6971 expected. 'type' should contain the basic type. 'ad' is the
6972 attribute definition of the basic type. It can be modified by
6973 type_decl().
6975 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6977 Sym *s;
6978 CType type1, *type2;
6979 int qualifiers;
6981 while (tok == '*') {
6982 qualifiers = 0;
6983 redo:
6984 next();
6985 switch(tok) {
6986 case TOK_CONST1:
6987 case TOK_CONST2:
6988 case TOK_CONST3:
6989 qualifiers |= VT_CONSTANT;
6990 goto redo;
6991 case TOK_VOLATILE1:
6992 case TOK_VOLATILE2:
6993 case TOK_VOLATILE3:
6994 qualifiers |= VT_VOLATILE;
6995 goto redo;
6996 case TOK_RESTRICT1:
6997 case TOK_RESTRICT2:
6998 case TOK_RESTRICT3:
6999 goto redo;
7001 mk_pointer(type);
7002 type->t |= qualifiers;
7005 /* XXX: clarify attribute handling */
7006 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7007 parse_attribute(ad);
7009 /* recursive type */
7010 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7011 type1.t = 0; /* XXX: same as int */
7012 if (tok == '(') {
7013 next();
7014 /* XXX: this is not correct to modify 'ad' at this point, but
7015 the syntax is not clear */
7016 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7017 parse_attribute(ad);
7018 type_decl(&type1, ad, v, td);
7019 skip(')');
7020 } else {
7021 /* type identifier */
7022 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7023 *v = tok;
7024 next();
7025 } else {
7026 if (!(td & TYPE_ABSTRACT))
7027 expect("identifier");
7028 *v = 0;
7031 post_type(type, ad);
7032 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7033 parse_attribute(ad);
7034 if (!type1.t)
7035 return;
7036 /* append type at the end of type1 */
7037 type2 = &type1;
7038 for(;;) {
7039 s = type2->ref;
7040 type2 = &s->type;
7041 if (!type2->t) {
7042 *type2 = *type;
7043 break;
7046 *type = type1;
7049 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7050 static int lvalue_type(int t)
7052 int bt, r;
7053 r = VT_LVAL;
7054 bt = t & VT_BTYPE;
7055 if (bt == VT_BYTE || bt == VT_BOOL)
7056 r |= VT_LVAL_BYTE;
7057 else if (bt == VT_SHORT)
7058 r |= VT_LVAL_SHORT;
7059 else
7060 return r;
7061 if (t & VT_UNSIGNED)
7062 r |= VT_LVAL_UNSIGNED;
7063 return r;
7066 /* indirection with full error checking and bound check */
7067 static void indir(void)
7069 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7070 expect("pointer");
7071 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7072 gv(RC_INT);
7073 vtop->type = *pointed_type(&vtop->type);
7074 /* an array is never an lvalue */
7075 if (!(vtop->type.t & VT_ARRAY)) {
7076 vtop->r |= lvalue_type(vtop->type.t);
7077 /* if bound checking, the referenced pointer must be checked */
7078 if (do_bounds_check)
7079 vtop->r |= VT_MUSTBOUND;
7083 /* pass a parameter to a function and do type checking and casting */
7084 static void gfunc_param_typed(Sym *func, Sym *arg)
7086 int func_type;
7087 CType type;
7089 func_type = func->c;
7090 if (func_type == FUNC_OLD ||
7091 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7092 /* default casting : only need to convert float to double */
7093 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7094 type.t = VT_DOUBLE;
7095 gen_cast(&type);
7097 } else if (arg == NULL) {
7098 error("too many arguments to function");
7099 } else {
7100 type = arg->type;
7101 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7102 gen_assign_cast(&type);
7106 /* parse an expression of the form '(type)' or '(expr)' and return its
7107 type */
7108 static void parse_expr_type(CType *type)
7110 int n;
7111 AttributeDef ad;
7113 skip('(');
7114 if (parse_btype(type, &ad)) {
7115 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7116 } else {
7117 expr_type(type);
7119 skip(')');
7122 static void parse_type(CType *type)
7124 AttributeDef ad;
7125 int n;
7127 if (!parse_btype(type, &ad)) {
7128 expect("type");
7130 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7133 static void vpush_tokc(int t)
7135 CType type;
7136 type.t = t;
7137 vsetc(&type, VT_CONST, &tokc);
7140 static void unary(void)
7142 int n, t, align, size, r;
7143 CType type;
7144 Sym *s;
7145 AttributeDef ad;
7147 /* XXX: GCC 2.95.3 does not generate a table although it should be
7148 better here */
7149 tok_next:
7150 switch(tok) {
7151 case TOK_EXTENSION:
7152 next();
7153 goto tok_next;
7154 case TOK_CINT:
7155 case TOK_CCHAR:
7156 case TOK_LCHAR:
7157 vpushi(tokc.i);
7158 next();
7159 break;
7160 case TOK_CUINT:
7161 vpush_tokc(VT_INT | VT_UNSIGNED);
7162 next();
7163 break;
7164 case TOK_CLLONG:
7165 vpush_tokc(VT_LLONG);
7166 next();
7167 break;
7168 case TOK_CULLONG:
7169 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7170 next();
7171 break;
7172 case TOK_CFLOAT:
7173 vpush_tokc(VT_FLOAT);
7174 next();
7175 break;
7176 case TOK_CDOUBLE:
7177 vpush_tokc(VT_DOUBLE);
7178 next();
7179 break;
7180 case TOK_CLDOUBLE:
7181 vpush_tokc(VT_LDOUBLE);
7182 next();
7183 break;
7184 case TOK___FUNCTION__:
7185 if (!gnu_ext)
7186 goto tok_identifier;
7187 /* fall thru */
7188 case TOK___FUNC__:
7190 void *ptr;
7191 int len;
7192 /* special function name identifier */
7193 len = strlen(funcname) + 1;
7194 /* generate char[len] type */
7195 type.t = VT_BYTE;
7196 mk_pointer(&type);
7197 type.t |= VT_ARRAY;
7198 type.ref->c = len;
7199 vpush_ref(&type, data_section, data_section->data_offset, len);
7200 ptr = section_ptr_add(data_section, len);
7201 memcpy(ptr, funcname, len);
7202 next();
7204 break;
7205 case TOK_LSTR:
7206 #ifdef TCC_TARGET_PE
7207 t = VT_SHORT | VT_UNSIGNED;
7208 #else
7209 t = VT_INT;
7210 #endif
7211 goto str_init;
7212 case TOK_STR:
7213 /* string parsing */
7214 t = VT_BYTE;
7215 str_init:
7216 if (tcc_state->warn_write_strings)
7217 t |= VT_CONSTANT;
7218 type.t = t;
7219 mk_pointer(&type);
7220 type.t |= VT_ARRAY;
7221 memset(&ad, 0, sizeof(AttributeDef));
7222 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7223 break;
7224 case '(':
7225 next();
7226 /* cast ? */
7227 if (parse_btype(&type, &ad)) {
7228 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7229 skip(')');
7230 /* check ISOC99 compound literal */
7231 if (tok == '{') {
7232 /* data is allocated locally by default */
7233 if (global_expr)
7234 r = VT_CONST;
7235 else
7236 r = VT_LOCAL;
7237 /* all except arrays are lvalues */
7238 if (!(type.t & VT_ARRAY))
7239 r |= lvalue_type(type.t);
7240 memset(&ad, 0, sizeof(AttributeDef));
7241 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7242 } else {
7243 unary();
7244 gen_cast(&type);
7246 } else if (tok == '{') {
7247 /* save all registers */
7248 save_regs(0);
7249 /* statement expression : we do not accept break/continue
7250 inside as GCC does */
7251 block(NULL, NULL, NULL, NULL, 0, 1);
7252 skip(')');
7253 } else {
7254 gexpr();
7255 skip(')');
7257 break;
7258 case '*':
7259 next();
7260 unary();
7261 indir();
7262 break;
7263 case '&':
7264 next();
7265 unary();
7266 /* functions names must be treated as function pointers,
7267 except for unary '&' and sizeof. Since we consider that
7268 functions are not lvalues, we only have to handle it
7269 there and in function calls. */
7270 /* arrays can also be used although they are not lvalues */
7271 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7272 !(vtop->type.t & VT_ARRAY))
7273 test_lvalue();
7274 mk_pointer(&vtop->type);
7275 gaddrof();
7276 break;
7277 case '!':
7278 next();
7279 unary();
7280 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7281 vtop->c.i = !vtop->c.i;
7282 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7283 vtop->c.i = vtop->c.i ^ 1;
7284 else
7285 vseti(VT_JMP, gtst(1, 0));
7286 break;
7287 case '~':
7288 next();
7289 unary();
7290 vpushi(-1);
7291 gen_op('^');
7292 break;
7293 case '+':
7294 next();
7295 /* in order to force cast, we add zero */
7296 unary();
7297 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7298 error("pointer not accepted for unary plus");
7299 vpushi(0);
7300 gen_op('+');
7301 break;
7302 case TOK_SIZEOF:
7303 case TOK_ALIGNOF1:
7304 case TOK_ALIGNOF2:
7305 t = tok;
7306 next();
7307 if (tok == '(') {
7308 parse_expr_type(&type);
7309 } else {
7310 unary_type(&type);
7312 size = type_size(&type, &align);
7313 if (t == TOK_SIZEOF) {
7314 if (size < 0)
7315 error("sizeof applied to an incomplete type");
7316 vpushi(size);
7317 } else {
7318 vpushi(align);
7320 break;
7322 case TOK_builtin_types_compatible_p:
7324 CType type1, type2;
7325 next();
7326 skip('(');
7327 parse_type(&type1);
7328 skip(',');
7329 parse_type(&type2);
7330 skip(')');
7331 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7332 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7333 vpushi(is_compatible_types(&type1, &type2));
7335 break;
7336 case TOK_builtin_constant_p:
7338 int saved_nocode_wanted, res;
7339 next();
7340 skip('(');
7341 saved_nocode_wanted = nocode_wanted;
7342 nocode_wanted = 1;
7343 gexpr();
7344 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7345 vpop();
7346 nocode_wanted = saved_nocode_wanted;
7347 skip(')');
7348 vpushi(res);
7350 break;
7351 case TOK_INC:
7352 case TOK_DEC:
7353 t = tok;
7354 next();
7355 unary();
7356 inc(0, t);
7357 break;
7358 case '-':
7359 next();
7360 vpushi(0);
7361 unary();
7362 gen_op('-');
7363 break;
7364 case TOK_LAND:
7365 if (!gnu_ext)
7366 goto tok_identifier;
7367 next();
7368 /* allow to take the address of a label */
7369 if (tok < TOK_UIDENT)
7370 expect("label identifier");
7371 s = label_find(tok);
7372 if (!s) {
7373 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7374 } else {
7375 if (s->r == LABEL_DECLARED)
7376 s->r = LABEL_FORWARD;
7378 if (!s->type.t) {
7379 s->type.t = VT_VOID;
7380 mk_pointer(&s->type);
7381 s->type.t |= VT_STATIC;
7383 vset(&s->type, VT_CONST | VT_SYM, 0);
7384 vtop->sym = s;
7385 next();
7386 break;
7387 default:
7388 tok_identifier:
7389 t = tok;
7390 next();
7391 if (t < TOK_UIDENT)
7392 expect("identifier");
7393 s = sym_find(t);
7394 if (!s) {
7395 if (tok != '(')
7396 error("'%s' undeclared", get_tok_str(t, NULL));
7397 /* for simple function calls, we tolerate undeclared
7398 external reference to int() function */
7399 if (tcc_state->warn_implicit_function_declaration)
7400 warning("implicit declaration of function '%s'",
7401 get_tok_str(t, NULL));
7402 s = external_global_sym(t, &func_old_type, 0);
7404 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7405 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7406 /* if referencing an inline function, then we generate a
7407 symbol to it if not already done. It will have the
7408 effect to generate code for it at the end of the
7409 compilation unit. Inline function as always
7410 generated in the text section. */
7411 if (!s->c)
7412 put_extern_sym(s, text_section, 0, 0);
7413 r = VT_SYM | VT_CONST;
7414 } else {
7415 r = s->r;
7417 vset(&s->type, r, s->c);
7418 /* if forward reference, we must point to s */
7419 if (vtop->r & VT_SYM) {
7420 vtop->sym = s;
7421 vtop->c.ul = 0;
7423 break;
7426 /* post operations */
7427 while (1) {
7428 if (tok == TOK_INC || tok == TOK_DEC) {
7429 inc(1, tok);
7430 next();
7431 } else if (tok == '.' || tok == TOK_ARROW) {
7432 /* field */
7433 if (tok == TOK_ARROW)
7434 indir();
7435 test_lvalue();
7436 gaddrof();
7437 next();
7438 /* expect pointer on structure */
7439 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7440 expect("struct or union");
7441 s = vtop->type.ref;
7442 /* find field */
7443 tok |= SYM_FIELD;
7444 while ((s = s->next) != NULL) {
7445 if (s->v == tok)
7446 break;
7448 if (!s)
7449 error("field not found");
7450 /* add field offset to pointer */
7451 vtop->type = char_pointer_type; /* change type to 'char *' */
7452 vpushi(s->c);
7453 gen_op('+');
7454 /* change type to field type, and set to lvalue */
7455 vtop->type = s->type;
7456 /* an array is never an lvalue */
7457 if (!(vtop->type.t & VT_ARRAY)) {
7458 vtop->r |= lvalue_type(vtop->type.t);
7459 /* if bound checking, the referenced pointer must be checked */
7460 if (do_bounds_check)
7461 vtop->r |= VT_MUSTBOUND;
7463 next();
7464 } else if (tok == '[') {
7465 next();
7466 gexpr();
7467 gen_op('+');
7468 indir();
7469 skip(']');
7470 } else if (tok == '(') {
7471 SValue ret;
7472 Sym *sa;
7473 int nb_args;
7475 /* function call */
7476 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7477 /* pointer test (no array accepted) */
7478 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7479 vtop->type = *pointed_type(&vtop->type);
7480 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7481 goto error_func;
7482 } else {
7483 error_func:
7484 expect("function pointer");
7486 } else {
7487 vtop->r &= ~VT_LVAL; /* no lvalue */
7489 /* get return type */
7490 s = vtop->type.ref;
7491 next();
7492 sa = s->next; /* first parameter */
7493 nb_args = 0;
7494 /* compute first implicit argument if a structure is returned */
7495 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7496 /* get some space for the returned structure */
7497 size = type_size(&s->type, &align);
7498 loc = (loc - size) & -align;
7499 ret.type = s->type;
7500 ret.r = VT_LOCAL | VT_LVAL;
7501 /* pass it as 'int' to avoid structure arg passing
7502 problems */
7503 vseti(VT_LOCAL, loc);
7504 ret.c = vtop->c;
7505 nb_args++;
7506 } else {
7507 ret.type = s->type;
7508 ret.r2 = VT_CONST;
7509 /* return in register */
7510 if (is_float(ret.type.t)) {
7511 ret.r = REG_FRET;
7512 } else {
7513 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7514 ret.r2 = REG_LRET;
7515 ret.r = REG_IRET;
7517 ret.c.i = 0;
7519 if (tok != ')') {
7520 for(;;) {
7521 expr_eq();
7522 gfunc_param_typed(s, sa);
7523 nb_args++;
7524 if (sa)
7525 sa = sa->next;
7526 if (tok == ')')
7527 break;
7528 skip(',');
7531 if (sa)
7532 error("too few arguments to function");
7533 skip(')');
7534 if (!nocode_wanted) {
7535 gfunc_call(nb_args);
7536 } else {
7537 vtop -= (nb_args + 1);
7539 /* return value */
7540 vsetc(&ret.type, ret.r, &ret.c);
7541 vtop->r2 = ret.r2;
7542 } else {
7543 break;
7548 static void uneq(void)
7550 int t;
7552 unary();
7553 if (tok == '=' ||
7554 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7555 tok == TOK_A_XOR || tok == TOK_A_OR ||
7556 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7557 test_lvalue();
7558 t = tok;
7559 next();
7560 if (t == '=') {
7561 expr_eq();
7562 } else {
7563 vdup();
7564 expr_eq();
7565 gen_op(t & 0x7f);
7567 vstore();
7571 static void expr_prod(void)
7573 int t;
7575 uneq();
7576 while (tok == '*' || tok == '/' || tok == '%') {
7577 t = tok;
7578 next();
7579 uneq();
7580 gen_op(t);
7584 static void expr_sum(void)
7586 int t;
7588 expr_prod();
7589 while (tok == '+' || tok == '-') {
7590 t = tok;
7591 next();
7592 expr_prod();
7593 gen_op(t);
7597 static void expr_shift(void)
7599 int t;
7601 expr_sum();
7602 while (tok == TOK_SHL || tok == TOK_SAR) {
7603 t = tok;
7604 next();
7605 expr_sum();
7606 gen_op(t);
7610 static void expr_cmp(void)
7612 int t;
7614 expr_shift();
7615 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7616 tok == TOK_ULT || tok == TOK_UGE) {
7617 t = tok;
7618 next();
7619 expr_shift();
7620 gen_op(t);
7624 static void expr_cmpeq(void)
7626 int t;
7628 expr_cmp();
7629 while (tok == TOK_EQ || tok == TOK_NE) {
7630 t = tok;
7631 next();
7632 expr_cmp();
7633 gen_op(t);
7637 static void expr_and(void)
7639 expr_cmpeq();
7640 while (tok == '&') {
7641 next();
7642 expr_cmpeq();
7643 gen_op('&');
7647 static void expr_xor(void)
7649 expr_and();
7650 while (tok == '^') {
7651 next();
7652 expr_and();
7653 gen_op('^');
7657 static void expr_or(void)
7659 expr_xor();
7660 while (tok == '|') {
7661 next();
7662 expr_xor();
7663 gen_op('|');
7667 /* XXX: fix this mess */
7668 static void expr_land_const(void)
7670 expr_or();
7671 while (tok == TOK_LAND) {
7672 next();
7673 expr_or();
7674 gen_op(TOK_LAND);
7678 /* XXX: fix this mess */
7679 static void expr_lor_const(void)
7681 expr_land_const();
7682 while (tok == TOK_LOR) {
7683 next();
7684 expr_land_const();
7685 gen_op(TOK_LOR);
7689 /* only used if non constant */
7690 static void expr_land(void)
7692 int t;
7694 expr_or();
7695 if (tok == TOK_LAND) {
7696 t = 0;
7697 for(;;) {
7698 t = gtst(1, t);
7699 if (tok != TOK_LAND) {
7700 vseti(VT_JMPI, t);
7701 break;
7703 next();
7704 expr_or();
7709 static void expr_lor(void)
7711 int t;
7713 expr_land();
7714 if (tok == TOK_LOR) {
7715 t = 0;
7716 for(;;) {
7717 t = gtst(0, t);
7718 if (tok != TOK_LOR) {
7719 vseti(VT_JMP, t);
7720 break;
7722 next();
7723 expr_land();
7728 /* XXX: better constant handling */
7729 static void expr_eq(void)
7731 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7732 SValue sv;
7733 CType type, type1, type2;
7735 if (const_wanted) {
7736 int c1, c;
7737 expr_lor_const();
7738 if (tok == '?') {
7739 c = vtop->c.i;
7740 vpop();
7741 next();
7742 if (tok == ':' && gnu_ext) {
7743 c1 = c;
7744 } else {
7745 gexpr();
7746 c1 = vtop->c.i;
7747 vpop();
7749 skip(':');
7750 expr_eq();
7751 if (c)
7752 vtop->c.i = c1;
7754 } else {
7755 expr_lor();
7756 if (tok == '?') {
7757 next();
7758 if (vtop != vstack) {
7759 /* needed to avoid having different registers saved in
7760 each branch */
7761 if (is_float(vtop->type.t))
7762 rc = RC_FLOAT;
7763 else
7764 rc = RC_INT;
7765 gv(rc);
7766 save_regs(1);
7768 if (tok == ':' && gnu_ext) {
7769 gv_dup();
7770 tt = gtst(1, 0);
7771 } else {
7772 tt = gtst(1, 0);
7773 gexpr();
7775 type1 = vtop->type;
7776 sv = *vtop; /* save value to handle it later */
7777 vtop--; /* no vpop so that FP stack is not flushed */
7778 skip(':');
7779 u = gjmp(0);
7780 gsym(tt);
7781 expr_eq();
7782 type2 = vtop->type;
7784 t1 = type1.t;
7785 bt1 = t1 & VT_BTYPE;
7786 t2 = type2.t;
7787 bt2 = t2 & VT_BTYPE;
7788 /* cast operands to correct type according to ISOC rules */
7789 if (is_float(bt1) || is_float(bt2)) {
7790 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7791 type.t = VT_LDOUBLE;
7792 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7793 type.t = VT_DOUBLE;
7794 } else {
7795 type.t = VT_FLOAT;
7797 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7798 /* cast to biggest op */
7799 type.t = VT_LLONG;
7800 /* convert to unsigned if it does not fit in a long long */
7801 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7802 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7803 type.t |= VT_UNSIGNED;
7804 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7805 /* XXX: test pointer compatibility */
7806 type = type1;
7807 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
7808 /* XXX: test function pointer compatibility */
7809 type = type1;
7810 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7811 /* XXX: test structure compatibility */
7812 type = type1;
7813 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7814 /* NOTE: as an extension, we accept void on only one side */
7815 type.t = VT_VOID;
7816 } else {
7817 /* integer operations */
7818 type.t = VT_INT;
7819 /* convert to unsigned if it does not fit in an integer */
7820 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7821 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7822 type.t |= VT_UNSIGNED;
7825 /* now we convert second operand */
7826 gen_cast(&type);
7827 rc = RC_INT;
7828 if (is_float(type.t)) {
7829 rc = RC_FLOAT;
7830 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7831 /* for long longs, we use fixed registers to avoid having
7832 to handle a complicated move */
7833 rc = RC_IRET;
7836 r2 = gv(rc);
7837 /* this is horrible, but we must also convert first
7838 operand */
7839 tt = gjmp(0);
7840 gsym(u);
7841 /* put again first value and cast it */
7842 *vtop = sv;
7843 gen_cast(&type);
7844 r1 = gv(rc);
7845 move_reg(r2, r1);
7846 vtop->r = r2;
7847 gsym(tt);
7852 static void gexpr(void)
7854 while (1) {
7855 expr_eq();
7856 if (tok != ',')
7857 break;
7858 vpop();
7859 next();
7863 /* parse an expression and return its type without any side effect. */
7864 static void expr_type(CType *type)
7866 int saved_nocode_wanted;
7868 saved_nocode_wanted = nocode_wanted;
7869 nocode_wanted = 1;
7870 gexpr();
7871 *type = vtop->type;
7872 vpop();
7873 nocode_wanted = saved_nocode_wanted;
7876 /* parse a unary expression and return its type without any side
7877 effect. */
7878 static void unary_type(CType *type)
7880 int a;
7882 a = nocode_wanted;
7883 nocode_wanted = 1;
7884 unary();
7885 *type = vtop->type;
7886 vpop();
7887 nocode_wanted = a;
7890 /* parse a constant expression and return value in vtop. */
7891 static void expr_const1(void)
7893 int a;
7894 a = const_wanted;
7895 const_wanted = 1;
7896 expr_eq();
7897 const_wanted = a;
7900 /* parse an integer constant and return its value. */
7901 static int expr_const(void)
7903 int c;
7904 expr_const1();
7905 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7906 expect("constant expression");
7907 c = vtop->c.i;
7908 vpop();
7909 return c;
7912 /* return the label token if current token is a label, otherwise
7913 return zero */
7914 static int is_label(void)
7916 int last_tok;
7918 /* fast test first */
7919 if (tok < TOK_UIDENT)
7920 return 0;
7921 /* no need to save tokc because tok is an identifier */
7922 last_tok = tok;
7923 next();
7924 if (tok == ':') {
7925 next();
7926 return last_tok;
7927 } else {
7928 unget_tok(last_tok);
7929 return 0;
7933 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7934 int case_reg, int is_expr)
7936 int a, b, c, d;
7937 Sym *s;
7939 /* generate line number info */
7940 if (do_debug &&
7941 (last_line_num != file->line_num || last_ind != ind)) {
7942 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7943 last_ind = ind;
7944 last_line_num = file->line_num;
7947 if (is_expr) {
7948 /* default return value is (void) */
7949 vpushi(0);
7950 vtop->type.t = VT_VOID;
7953 if (tok == TOK_IF) {
7954 /* if test */
7955 next();
7956 skip('(');
7957 gexpr();
7958 skip(')');
7959 a = gtst(1, 0);
7960 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7961 c = tok;
7962 if (c == TOK_ELSE) {
7963 next();
7964 d = gjmp(0);
7965 gsym(a);
7966 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7967 gsym(d); /* patch else jmp */
7968 } else
7969 gsym(a);
7970 } else if (tok == TOK_WHILE) {
7971 next();
7972 d = ind;
7973 skip('(');
7974 gexpr();
7975 skip(')');
7976 a = gtst(1, 0);
7977 b = 0;
7978 block(&a, &b, case_sym, def_sym, case_reg, 0);
7979 gjmp_addr(d);
7980 gsym(a);
7981 gsym_addr(b, d);
7982 } else if (tok == '{') {
7983 Sym *llabel;
7985 next();
7986 /* record local declaration stack position */
7987 s = local_stack;
7988 llabel = local_label_stack;
7989 /* handle local labels declarations */
7990 if (tok == TOK_LABEL) {
7991 next();
7992 for(;;) {
7993 if (tok < TOK_UIDENT)
7994 expect("label identifier");
7995 label_push(&local_label_stack, tok, LABEL_DECLARED);
7996 next();
7997 if (tok == ',') {
7998 next();
7999 } else {
8000 skip(';');
8001 break;
8005 while (tok != '}') {
8006 decl(VT_LOCAL);
8007 if (tok != '}') {
8008 if (is_expr)
8009 vpop();
8010 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8013 /* pop locally defined labels */
8014 label_pop(&local_label_stack, llabel);
8015 /* pop locally defined symbols */
8016 sym_pop(&local_stack, s);
8017 next();
8018 } else if (tok == TOK_RETURN) {
8019 next();
8020 if (tok != ';') {
8021 gexpr();
8022 gen_assign_cast(&func_vt);
8023 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8024 CType type;
8025 /* if returning structure, must copy it to implicit
8026 first pointer arg location */
8027 type = func_vt;
8028 mk_pointer(&type);
8029 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8030 indir();
8031 vswap();
8032 /* copy structure value to pointer */
8033 vstore();
8034 } else if (is_float(func_vt.t)) {
8035 gv(RC_FRET);
8036 } else {
8037 gv(RC_IRET);
8039 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8041 skip(';');
8042 rsym = gjmp(rsym); /* jmp */
8043 } else if (tok == TOK_BREAK) {
8044 /* compute jump */
8045 if (!bsym)
8046 error("cannot break");
8047 *bsym = gjmp(*bsym);
8048 next();
8049 skip(';');
8050 } else if (tok == TOK_CONTINUE) {
8051 /* compute jump */
8052 if (!csym)
8053 error("cannot continue");
8054 *csym = gjmp(*csym);
8055 next();
8056 skip(';');
8057 } else if (tok == TOK_FOR) {
8058 int e;
8059 next();
8060 skip('(');
8061 if (tok != ';') {
8062 gexpr();
8063 vpop();
8065 skip(';');
8066 d = ind;
8067 c = ind;
8068 a = 0;
8069 b = 0;
8070 if (tok != ';') {
8071 gexpr();
8072 a = gtst(1, 0);
8074 skip(';');
8075 if (tok != ')') {
8076 e = gjmp(0);
8077 c = ind;
8078 gexpr();
8079 vpop();
8080 gjmp_addr(d);
8081 gsym(e);
8083 skip(')');
8084 block(&a, &b, case_sym, def_sym, case_reg, 0);
8085 gjmp_addr(c);
8086 gsym(a);
8087 gsym_addr(b, c);
8088 } else
8089 if (tok == TOK_DO) {
8090 next();
8091 a = 0;
8092 b = 0;
8093 d = ind;
8094 block(&a, &b, case_sym, def_sym, case_reg, 0);
8095 skip(TOK_WHILE);
8096 skip('(');
8097 gsym(b);
8098 gexpr();
8099 c = gtst(0, 0);
8100 gsym_addr(c, d);
8101 skip(')');
8102 gsym(a);
8103 skip(';');
8104 } else
8105 if (tok == TOK_SWITCH) {
8106 next();
8107 skip('(');
8108 gexpr();
8109 /* XXX: other types than integer */
8110 case_reg = gv(RC_INT);
8111 vpop();
8112 skip(')');
8113 a = 0;
8114 b = gjmp(0); /* jump to first case */
8115 c = 0;
8116 block(&a, csym, &b, &c, case_reg, 0);
8117 /* if no default, jmp after switch */
8118 if (c == 0)
8119 c = ind;
8120 /* default label */
8121 gsym_addr(b, c);
8122 /* break label */
8123 gsym(a);
8124 } else
8125 if (tok == TOK_CASE) {
8126 int v1, v2;
8127 if (!case_sym)
8128 expect("switch");
8129 next();
8130 v1 = expr_const();
8131 v2 = v1;
8132 if (gnu_ext && tok == TOK_DOTS) {
8133 next();
8134 v2 = expr_const();
8135 if (v2 < v1)
8136 warning("empty case range");
8138 /* since a case is like a label, we must skip it with a jmp */
8139 b = gjmp(0);
8140 gsym(*case_sym);
8141 vseti(case_reg, 0);
8142 vpushi(v1);
8143 if (v1 == v2) {
8144 gen_op(TOK_EQ);
8145 *case_sym = gtst(1, 0);
8146 } else {
8147 gen_op(TOK_GE);
8148 *case_sym = gtst(1, 0);
8149 vseti(case_reg, 0);
8150 vpushi(v2);
8151 gen_op(TOK_LE);
8152 *case_sym = gtst(1, *case_sym);
8154 gsym(b);
8155 skip(':');
8156 is_expr = 0;
8157 goto block_after_label;
8158 } else
8159 if (tok == TOK_DEFAULT) {
8160 next();
8161 skip(':');
8162 if (!def_sym)
8163 expect("switch");
8164 if (*def_sym)
8165 error("too many 'default'");
8166 *def_sym = ind;
8167 is_expr = 0;
8168 goto block_after_label;
8169 } else
8170 if (tok == TOK_GOTO) {
8171 next();
8172 if (tok == '*' && gnu_ext) {
8173 /* computed goto */
8174 next();
8175 gexpr();
8176 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8177 expect("pointer");
8178 ggoto();
8179 } else if (tok >= TOK_UIDENT) {
8180 s = label_find(tok);
8181 /* put forward definition if needed */
8182 if (!s) {
8183 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8184 } else {
8185 if (s->r == LABEL_DECLARED)
8186 s->r = LABEL_FORWARD;
8188 /* label already defined */
8189 if (s->r & LABEL_FORWARD)
8190 s->next = (void *)gjmp((long)s->next);
8191 else
8192 gjmp_addr((long)s->next);
8193 next();
8194 } else {
8195 expect("label identifier");
8197 skip(';');
8198 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8199 asm_instr();
8200 } else {
8201 b = is_label();
8202 if (b) {
8203 /* label case */
8204 s = label_find(b);
8205 if (s) {
8206 if (s->r == LABEL_DEFINED)
8207 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8208 gsym((long)s->next);
8209 s->r = LABEL_DEFINED;
8210 } else {
8211 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8213 s->next = (void *)ind;
8214 /* we accept this, but it is a mistake */
8215 block_after_label:
8216 if (tok == '}') {
8217 warning("deprecated use of label at end of compound statement");
8218 } else {
8219 if (is_expr)
8220 vpop();
8221 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8223 } else {
8224 /* expression case */
8225 if (tok != ';') {
8226 if (is_expr) {
8227 vpop();
8228 gexpr();
8229 } else {
8230 gexpr();
8231 vpop();
8234 skip(';');
8239 /* t is the array or struct type. c is the array or struct
8240 address. cur_index/cur_field is the pointer to the current
8241 value. 'size_only' is true if only size info is needed (only used
8242 in arrays) */
8243 static void decl_designator(CType *type, Section *sec, unsigned long c,
8244 int *cur_index, Sym **cur_field,
8245 int size_only)
8247 Sym *s, *f;
8248 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8249 CType type1;
8251 notfirst = 0;
8252 elem_size = 0;
8253 nb_elems = 1;
8254 if (gnu_ext && (l = is_label()) != 0)
8255 goto struct_field;
8256 while (tok == '[' || tok == '.') {
8257 if (tok == '[') {
8258 if (!(type->t & VT_ARRAY))
8259 expect("array type");
8260 s = type->ref;
8261 next();
8262 index = expr_const();
8263 if (index < 0 || (s->c >= 0 && index >= s->c))
8264 expect("invalid index");
8265 if (tok == TOK_DOTS && gnu_ext) {
8266 next();
8267 index_last = expr_const();
8268 if (index_last < 0 ||
8269 (s->c >= 0 && index_last >= s->c) ||
8270 index_last < index)
8271 expect("invalid index");
8272 } else {
8273 index_last = index;
8275 skip(']');
8276 if (!notfirst)
8277 *cur_index = index_last;
8278 type = pointed_type(type);
8279 elem_size = type_size(type, &align);
8280 c += index * elem_size;
8281 /* NOTE: we only support ranges for last designator */
8282 nb_elems = index_last - index + 1;
8283 if (nb_elems != 1) {
8284 notfirst = 1;
8285 break;
8287 } else {
8288 next();
8289 l = tok;
8290 next();
8291 struct_field:
8292 if ((type->t & VT_BTYPE) != VT_STRUCT)
8293 expect("struct/union type");
8294 s = type->ref;
8295 l |= SYM_FIELD;
8296 f = s->next;
8297 while (f) {
8298 if (f->v == l)
8299 break;
8300 f = f->next;
8302 if (!f)
8303 expect("field");
8304 if (!notfirst)
8305 *cur_field = f;
8306 /* XXX: fix this mess by using explicit storage field */
8307 type1 = f->type;
8308 type1.t |= (type->t & ~VT_TYPE);
8309 type = &type1;
8310 c += f->c;
8312 notfirst = 1;
8314 if (notfirst) {
8315 if (tok == '=') {
8316 next();
8317 } else {
8318 if (!gnu_ext)
8319 expect("=");
8321 } else {
8322 if (type->t & VT_ARRAY) {
8323 index = *cur_index;
8324 type = pointed_type(type);
8325 c += index * type_size(type, &align);
8326 } else {
8327 f = *cur_field;
8328 if (!f)
8329 error("too many field init");
8330 /* XXX: fix this mess by using explicit storage field */
8331 type1 = f->type;
8332 type1.t |= (type->t & ~VT_TYPE);
8333 type = &type1;
8334 c += f->c;
8337 decl_initializer(type, sec, c, 0, size_only);
8339 /* XXX: make it more general */
8340 if (!size_only && nb_elems > 1) {
8341 unsigned long c_end;
8342 uint8_t *src, *dst;
8343 int i;
8345 if (!sec)
8346 error("range init not supported yet for dynamic storage");
8347 c_end = c + nb_elems * elem_size;
8348 if (c_end > sec->data_allocated)
8349 section_realloc(sec, c_end);
8350 src = sec->data + c;
8351 dst = src;
8352 for(i = 1; i < nb_elems; i++) {
8353 dst += elem_size;
8354 memcpy(dst, src, elem_size);
8359 #define EXPR_VAL 0
8360 #define EXPR_CONST 1
8361 #define EXPR_ANY 2
8363 /* store a value or an expression directly in global data or in local array */
8364 static void init_putv(CType *type, Section *sec, unsigned long c,
8365 int v, int expr_type)
8367 int saved_global_expr, bt, bit_pos, bit_size;
8368 void *ptr;
8369 unsigned long long bit_mask;
8370 CType dtype;
8372 switch(expr_type) {
8373 case EXPR_VAL:
8374 vpushi(v);
8375 break;
8376 case EXPR_CONST:
8377 /* compound literals must be allocated globally in this case */
8378 saved_global_expr = global_expr;
8379 global_expr = 1;
8380 expr_const1();
8381 global_expr = saved_global_expr;
8382 /* NOTE: symbols are accepted */
8383 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8384 error("initializer element is not constant");
8385 break;
8386 case EXPR_ANY:
8387 expr_eq();
8388 break;
8391 dtype = *type;
8392 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8394 if (sec) {
8395 /* XXX: not portable */
8396 /* XXX: generate error if incorrect relocation */
8397 gen_assign_cast(&dtype);
8398 bt = type->t & VT_BTYPE;
8399 ptr = sec->data + c;
8400 /* XXX: make code faster ? */
8401 if (!(type->t & VT_BITFIELD)) {
8402 bit_pos = 0;
8403 bit_size = 32;
8404 bit_mask = -1LL;
8405 } else {
8406 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8407 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8408 bit_mask = (1LL << bit_size) - 1;
8410 if ((vtop->r & VT_SYM) &&
8411 (bt == VT_BYTE ||
8412 bt == VT_SHORT ||
8413 bt == VT_DOUBLE ||
8414 bt == VT_LDOUBLE ||
8415 bt == VT_LLONG ||
8416 (bt == VT_INT && bit_size != 32)))
8417 error("initializer element is not computable at load time");
8418 switch(bt) {
8419 case VT_BYTE:
8420 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8421 break;
8422 case VT_SHORT:
8423 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8424 break;
8425 case VT_DOUBLE:
8426 *(double *)ptr = vtop->c.d;
8427 break;
8428 case VT_LDOUBLE:
8429 *(long double *)ptr = vtop->c.ld;
8430 break;
8431 case VT_LLONG:
8432 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8433 break;
8434 default:
8435 if (vtop->r & VT_SYM) {
8436 greloc(sec, vtop->sym, c, R_DATA_32);
8438 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8439 break;
8441 vtop--;
8442 } else {
8443 vset(&dtype, VT_LOCAL, c);
8444 vswap();
8445 vstore();
8446 vpop();
8450 /* put zeros for variable based init */
8451 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8453 if (sec) {
8454 /* nothing to do because globals are already set to zero */
8455 } else {
8456 vpush_global_sym(&func_old_type, TOK_memset);
8457 vseti(VT_LOCAL, c);
8458 vpushi(0);
8459 vpushi(size);
8460 gfunc_call(3);
8464 /* 't' contains the type and storage info. 'c' is the offset of the
8465 object in section 'sec'. If 'sec' is NULL, it means stack based
8466 allocation. 'first' is true if array '{' must be read (multi
8467 dimension implicit array init handling). 'size_only' is true if
8468 size only evaluation is wanted (only for arrays). */
8469 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8470 int first, int size_only)
8472 int index, array_length, n, no_oblock, nb, parlevel, i;
8473 int size1, align1, expr_type;
8474 Sym *s, *f;
8475 CType *t1;
8477 if (type->t & VT_ARRAY) {
8478 s = type->ref;
8479 n = s->c;
8480 array_length = 0;
8481 t1 = pointed_type(type);
8482 size1 = type_size(t1, &align1);
8484 no_oblock = 1;
8485 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8486 tok == '{') {
8487 skip('{');
8488 no_oblock = 0;
8491 /* only parse strings here if correct type (otherwise: handle
8492 them as ((w)char *) expressions */
8493 if ((tok == TOK_LSTR &&
8494 #ifdef TCC_TARGET_PE
8495 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)) ||
8496 #else
8497 (t1->t & VT_BTYPE) == VT_INT) ||
8498 #endif
8499 (tok == TOK_STR &&
8500 (t1->t & VT_BTYPE) == VT_BYTE)) {
8501 while (tok == TOK_STR || tok == TOK_LSTR) {
8502 int cstr_len, ch;
8503 CString *cstr;
8505 cstr = tokc.cstr;
8506 /* compute maximum number of chars wanted */
8507 if (tok == TOK_STR)
8508 cstr_len = cstr->size;
8509 else
8510 cstr_len = cstr->size / sizeof(nwchar_t);
8511 cstr_len--;
8512 nb = cstr_len;
8513 if (n >= 0 && nb > (n - array_length))
8514 nb = n - array_length;
8515 if (!size_only) {
8516 if (cstr_len > nb)
8517 warning("initializer-string for array is too long");
8518 /* in order to go faster for common case (char
8519 string in global variable, we handle it
8520 specifically */
8521 if (sec && tok == TOK_STR && size1 == 1) {
8522 memcpy(sec->data + c + array_length, cstr->data, nb);
8523 } else {
8524 for(i=0;i<nb;i++) {
8525 if (tok == TOK_STR)
8526 ch = ((unsigned char *)cstr->data)[i];
8527 else
8528 ch = ((nwchar_t *)cstr->data)[i];
8529 init_putv(t1, sec, c + (array_length + i) * size1,
8530 ch, EXPR_VAL);
8534 array_length += nb;
8535 next();
8537 /* only add trailing zero if enough storage (no
8538 warning in this case since it is standard) */
8539 if (n < 0 || array_length < n) {
8540 if (!size_only) {
8541 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8543 array_length++;
8545 } else {
8546 index = 0;
8547 while (tok != '}') {
8548 decl_designator(type, sec, c, &index, NULL, size_only);
8549 if (n >= 0 && index >= n)
8550 error("index too large");
8551 /* must put zero in holes (note that doing it that way
8552 ensures that it even works with designators) */
8553 if (!size_only && array_length < index) {
8554 init_putz(t1, sec, c + array_length * size1,
8555 (index - array_length) * size1);
8557 index++;
8558 if (index > array_length)
8559 array_length = index;
8560 /* special test for multi dimensional arrays (may not
8561 be strictly correct if designators are used at the
8562 same time) */
8563 if (index >= n && no_oblock)
8564 break;
8565 if (tok == '}')
8566 break;
8567 skip(',');
8570 if (!no_oblock)
8571 skip('}');
8572 /* put zeros at the end */
8573 if (!size_only && n >= 0 && array_length < n) {
8574 init_putz(t1, sec, c + array_length * size1,
8575 (n - array_length) * size1);
8577 /* patch type size if needed */
8578 if (n < 0)
8579 s->c = array_length;
8580 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8581 (sec || !first || tok == '{')) {
8582 int par_count;
8584 /* NOTE: the previous test is a specific case for automatic
8585 struct/union init */
8586 /* XXX: union needs only one init */
8588 /* XXX: this test is incorrect for local initializers
8589 beginning with ( without {. It would be much more difficult
8590 to do it correctly (ideally, the expression parser should
8591 be used in all cases) */
8592 par_count = 0;
8593 if (tok == '(') {
8594 AttributeDef ad1;
8595 CType type1;
8596 next();
8597 while (tok == '(') {
8598 par_count++;
8599 next();
8601 if (!parse_btype(&type1, &ad1))
8602 expect("cast");
8603 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8604 #if 0
8605 if (!is_assignable_types(type, &type1))
8606 error("invalid type for cast");
8607 #endif
8608 skip(')');
8610 no_oblock = 1;
8611 if (first || tok == '{') {
8612 skip('{');
8613 no_oblock = 0;
8615 s = type->ref;
8616 f = s->next;
8617 array_length = 0;
8618 index = 0;
8619 n = s->c;
8620 while (tok != '}') {
8621 decl_designator(type, sec, c, NULL, &f, size_only);
8622 index = f->c;
8623 if (!size_only && array_length < index) {
8624 init_putz(type, sec, c + array_length,
8625 index - array_length);
8627 index = index + type_size(&f->type, &align1);
8628 if (index > array_length)
8629 array_length = index;
8630 f = f->next;
8631 if (no_oblock && f == NULL)
8632 break;
8633 if (tok == '}')
8634 break;
8635 skip(',');
8637 /* put zeros at the end */
8638 if (!size_only && array_length < n) {
8639 init_putz(type, sec, c + array_length,
8640 n - array_length);
8642 if (!no_oblock)
8643 skip('}');
8644 while (par_count) {
8645 skip(')');
8646 par_count--;
8648 } else if (tok == '{') {
8649 next();
8650 decl_initializer(type, sec, c, first, size_only);
8651 skip('}');
8652 } else if (size_only) {
8653 /* just skip expression */
8654 parlevel = 0;
8655 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8656 tok != -1) {
8657 if (tok == '(')
8658 parlevel++;
8659 else if (tok == ')')
8660 parlevel--;
8661 next();
8663 } else {
8664 /* currently, we always use constant expression for globals
8665 (may change for scripting case) */
8666 expr_type = EXPR_CONST;
8667 if (!sec)
8668 expr_type = EXPR_ANY;
8669 init_putv(type, sec, c, 0, expr_type);
8673 /* parse an initializer for type 't' if 'has_init' is non zero, and
8674 allocate space in local or global data space ('r' is either
8675 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8676 variable 'v' of scope 'scope' is declared before initializers are
8677 parsed. If 'v' is zero, then a reference to the new object is put
8678 in the value stack. If 'has_init' is 2, a special parsing is done
8679 to handle string constants. */
8680 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8681 int has_init, int v, int scope)
8683 int size, align, addr, data_offset;
8684 int level;
8685 ParseState saved_parse_state;
8686 TokenString init_str;
8687 Section *sec;
8689 size = type_size(type, &align);
8690 /* If unknown size, we must evaluate it before
8691 evaluating initializers because
8692 initializers can generate global data too
8693 (e.g. string pointers or ISOC99 compound
8694 literals). It also simplifies local
8695 initializers handling */
8696 tok_str_new(&init_str);
8697 if (size < 0) {
8698 if (!has_init)
8699 error("unknown type size");
8700 /* get all init string */
8701 if (has_init == 2) {
8702 /* only get strings */
8703 while (tok == TOK_STR || tok == TOK_LSTR) {
8704 tok_str_add_tok(&init_str);
8705 next();
8707 } else {
8708 level = 0;
8709 while (level > 0 || (tok != ',' && tok != ';')) {
8710 if (tok < 0)
8711 error("unexpected end of file in initializer");
8712 tok_str_add_tok(&init_str);
8713 if (tok == '{')
8714 level++;
8715 else if (tok == '}') {
8716 if (level == 0)
8717 break;
8718 level--;
8720 next();
8723 tok_str_add(&init_str, -1);
8724 tok_str_add(&init_str, 0);
8726 /* compute size */
8727 save_parse_state(&saved_parse_state);
8729 macro_ptr = init_str.str;
8730 next();
8731 decl_initializer(type, NULL, 0, 1, 1);
8732 /* prepare second initializer parsing */
8733 macro_ptr = init_str.str;
8734 next();
8736 /* if still unknown size, error */
8737 size = type_size(type, &align);
8738 if (size < 0)
8739 error("unknown type size");
8741 /* take into account specified alignment if bigger */
8742 if (ad->aligned) {
8743 if (ad->aligned > align)
8744 align = ad->aligned;
8745 } else if (ad->packed) {
8746 align = 1;
8748 if ((r & VT_VALMASK) == VT_LOCAL) {
8749 sec = NULL;
8750 if (do_bounds_check && (type->t & VT_ARRAY))
8751 loc--;
8752 loc = (loc - size) & -align;
8753 addr = loc;
8754 /* handles bounds */
8755 /* XXX: currently, since we do only one pass, we cannot track
8756 '&' operators, so we add only arrays */
8757 if (do_bounds_check && (type->t & VT_ARRAY)) {
8758 unsigned long *bounds_ptr;
8759 /* add padding between regions */
8760 loc--;
8761 /* then add local bound info */
8762 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8763 bounds_ptr[0] = addr;
8764 bounds_ptr[1] = size;
8766 if (v) {
8767 /* local variable */
8768 sym_push(v, type, r, addr);
8769 } else {
8770 /* push local reference */
8771 vset(type, r, addr);
8773 } else {
8774 Sym *sym;
8776 sym = NULL;
8777 if (v && scope == VT_CONST) {
8778 /* see if the symbol was already defined */
8779 sym = sym_find(v);
8780 if (sym) {
8781 if (!is_compatible_types(&sym->type, type))
8782 error("incompatible types for redefinition of '%s'",
8783 get_tok_str(v, NULL));
8784 if (sym->type.t & VT_EXTERN) {
8785 /* if the variable is extern, it was not allocated */
8786 sym->type.t &= ~VT_EXTERN;
8787 /* set array size if it was ommited in extern
8788 declaration */
8789 if ((sym->type.t & VT_ARRAY) &&
8790 sym->type.ref->c < 0 &&
8791 type->ref->c >= 0)
8792 sym->type.ref->c = type->ref->c;
8793 } else {
8794 /* we accept several definitions of the same
8795 global variable. this is tricky, because we
8796 must play with the SHN_COMMON type of the symbol */
8797 /* XXX: should check if the variable was already
8798 initialized. It is incorrect to initialized it
8799 twice */
8800 /* no init data, we won't add more to the symbol */
8801 if (!has_init)
8802 goto no_alloc;
8807 /* allocate symbol in corresponding section */
8808 sec = ad->section;
8809 if (!sec) {
8810 if (has_init)
8811 sec = data_section;
8812 else if (tcc_state->nocommon)
8813 sec = bss_section;
8815 if (sec) {
8816 data_offset = sec->data_offset;
8817 data_offset = (data_offset + align - 1) & -align;
8818 addr = data_offset;
8819 /* very important to increment global pointer at this time
8820 because initializers themselves can create new initializers */
8821 data_offset += size;
8822 /* add padding if bound check */
8823 if (do_bounds_check)
8824 data_offset++;
8825 sec->data_offset = data_offset;
8826 /* allocate section space to put the data */
8827 if (sec->sh_type != SHT_NOBITS &&
8828 data_offset > sec->data_allocated)
8829 section_realloc(sec, data_offset);
8830 /* align section if needed */
8831 if (align > sec->sh_addralign)
8832 sec->sh_addralign = align;
8833 } else {
8834 addr = 0; /* avoid warning */
8837 if (v) {
8838 if (scope == VT_CONST) {
8839 if (!sym)
8840 goto do_def;
8841 } else {
8842 do_def:
8843 sym = sym_push(v, type, r | VT_SYM, 0);
8845 /* update symbol definition */
8846 if (sec) {
8847 put_extern_sym(sym, sec, addr, size);
8848 } else {
8849 Elf32_Sym *esym;
8850 /* put a common area */
8851 put_extern_sym(sym, NULL, align, size);
8852 /* XXX: find a nicer way */
8853 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8854 esym->st_shndx = SHN_COMMON;
8856 } else {
8857 CValue cval;
8859 /* push global reference */
8860 sym = get_sym_ref(type, sec, addr, size);
8861 cval.ul = 0;
8862 vsetc(type, VT_CONST | VT_SYM, &cval);
8863 vtop->sym = sym;
8866 /* handles bounds now because the symbol must be defined
8867 before for the relocation */
8868 if (do_bounds_check) {
8869 unsigned long *bounds_ptr;
8871 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8872 /* then add global bound info */
8873 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8874 bounds_ptr[0] = 0; /* relocated */
8875 bounds_ptr[1] = size;
8878 if (has_init) {
8879 decl_initializer(type, sec, addr, 1, 0);
8880 /* restore parse state if needed */
8881 if (init_str.str) {
8882 tok_str_free(init_str.str);
8883 restore_parse_state(&saved_parse_state);
8886 no_alloc: ;
8889 void put_func_debug(Sym *sym)
8891 char buf[512];
8893 /* stabs info */
8894 /* XXX: we put here a dummy type */
8895 snprintf(buf, sizeof(buf), "%s:%c1",
8896 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8897 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8898 cur_text_section, sym->c);
8899 last_ind = 0;
8900 last_line_num = 0;
8903 /* parse an old style function declaration list */
8904 /* XXX: check multiple parameter */
8905 static void func_decl_list(Sym *func_sym)
8907 AttributeDef ad;
8908 int v;
8909 Sym *s;
8910 CType btype, type;
8912 /* parse each declaration */
8913 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8914 if (!parse_btype(&btype, &ad))
8915 expect("declaration list");
8916 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8917 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8918 tok == ';') {
8919 /* we accept no variable after */
8920 } else {
8921 for(;;) {
8922 type = btype;
8923 type_decl(&type, &ad, &v, TYPE_DIRECT);
8924 /* find parameter in function parameter list */
8925 s = func_sym->next;
8926 while (s != NULL) {
8927 if ((s->v & ~SYM_FIELD) == v)
8928 goto found;
8929 s = s->next;
8931 error("declaration for parameter '%s' but no such parameter",
8932 get_tok_str(v, NULL));
8933 found:
8934 /* check that no storage specifier except 'register' was given */
8935 if (type.t & VT_STORAGE)
8936 error("storage class specified for '%s'", get_tok_str(v, NULL));
8937 convert_parameter_type(&type);
8938 /* we can add the type (NOTE: it could be local to the function) */
8939 s->type = type;
8940 /* accept other parameters */
8941 if (tok == ',')
8942 next();
8943 else
8944 break;
8947 skip(';');
8951 /* parse a function defined by symbol 'sym' and generate its code in
8952 'cur_text_section' */
8953 static void gen_function(Sym *sym)
8955 ind = cur_text_section->data_offset;
8956 /* NOTE: we patch the symbol size later */
8957 put_extern_sym(sym, cur_text_section, ind, 0);
8958 funcname = get_tok_str(sym->v, NULL);
8959 func_ind = ind;
8960 /* put debug symbol */
8961 if (do_debug)
8962 put_func_debug(sym);
8963 /* push a dummy symbol to enable local sym storage */
8964 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8965 gfunc_prolog(&sym->type);
8966 rsym = 0;
8967 block(NULL, NULL, NULL, NULL, 0, 0);
8968 gsym(rsym);
8969 gfunc_epilog();
8970 cur_text_section->data_offset = ind;
8971 label_pop(&global_label_stack, NULL);
8972 sym_pop(&local_stack, NULL); /* reset local stack */
8973 /* end of function */
8974 /* patch symbol size */
8975 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8976 ind - func_ind;
8977 if (do_debug) {
8978 put_stabn(N_FUN, 0, 0, ind - func_ind);
8980 funcname = ""; /* for safety */
8981 func_vt.t = VT_VOID; /* for safety */
8982 ind = 0; /* for safety */
8985 static void gen_inline_functions(void)
8987 Sym *sym;
8988 CType *type;
8989 int *str, inline_generated;
8991 /* iterate while inline function are referenced */
8992 for(;;) {
8993 inline_generated = 0;
8994 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8995 type = &sym->type;
8996 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8997 (type->t & (VT_STATIC | VT_INLINE)) ==
8998 (VT_STATIC | VT_INLINE) &&
8999 sym->c != 0) {
9000 /* the function was used: generate its code and
9001 convert it to a normal function */
9002 str = (int *)sym->r;
9003 sym->r = VT_SYM | VT_CONST;
9004 type->t &= ~VT_INLINE;
9006 macro_ptr = str;
9007 next();
9008 cur_text_section = text_section;
9009 gen_function(sym);
9010 macro_ptr = NULL; /* fail safe */
9012 tok_str_free(str);
9013 inline_generated = 1;
9016 if (!inline_generated)
9017 break;
9020 /* free all remaining inline function tokens */
9021 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9022 type = &sym->type;
9023 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9024 (type->t & (VT_STATIC | VT_INLINE)) ==
9025 (VT_STATIC | VT_INLINE)) {
9026 str = (int *)sym->r;
9027 tok_str_free(str);
9028 sym->r = 0; /* fail safe */
9033 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9034 static void decl(int l)
9036 int v, has_init, r;
9037 CType type, btype;
9038 Sym *sym;
9039 AttributeDef ad;
9041 while (1) {
9042 if (!parse_btype(&btype, &ad)) {
9043 /* skip redundant ';' */
9044 /* XXX: find more elegant solution */
9045 if (tok == ';') {
9046 next();
9047 continue;
9049 if (l == VT_CONST &&
9050 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9051 /* global asm block */
9052 asm_global_instr();
9053 continue;
9055 /* special test for old K&R protos without explicit int
9056 type. Only accepted when defining global data */
9057 if (l == VT_LOCAL || tok < TOK_DEFINE)
9058 break;
9059 btype.t = VT_INT;
9061 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9062 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9063 tok == ';') {
9064 /* we accept no variable after */
9065 next();
9066 continue;
9068 while (1) { /* iterate thru each declaration */
9069 type = btype;
9070 type_decl(&type, &ad, &v, TYPE_DIRECT);
9071 #if 0
9073 char buf[500];
9074 type_to_str(buf, sizeof(buf), &type, get_tok_str(v, NULL));
9075 printf("type = '%s'\n", buf);
9077 #endif
9078 if ((type.t & VT_BTYPE) == VT_FUNC) {
9079 /* if old style function prototype, we accept a
9080 declaration list */
9081 sym = type.ref;
9082 if (sym->c == FUNC_OLD)
9083 func_decl_list(sym);
9086 if (tok == '{') {
9087 if (l == VT_LOCAL)
9088 error("cannot use local functions");
9089 if ((type.t & VT_BTYPE) != VT_FUNC)
9090 expect("function definition");
9092 /* reject abstract declarators in function definition */
9093 sym = type.ref;
9094 while ((sym = sym->next) != NULL)
9095 if (!(sym->v & ~SYM_FIELD))
9096 expect("identifier");
9098 /* XXX: cannot do better now: convert extern line to static inline */
9099 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9100 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9102 sym = sym_find(v);
9103 if (sym) {
9104 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9105 goto func_error1;
9106 /* specific case: if not func_call defined, we put
9107 the one of the prototype */
9108 /* XXX: should have default value */
9109 if (sym->type.ref->r != FUNC_CDECL &&
9110 type.ref->r == FUNC_CDECL)
9111 type.ref->r = sym->type.ref->r;
9112 if (!is_compatible_types(&sym->type, &type)) {
9113 func_error1:
9114 error("incompatible types for redefinition of '%s'",
9115 get_tok_str(v, NULL));
9117 /* if symbol is already defined, then put complete type */
9118 sym->type = type;
9119 } else {
9120 /* put function symbol */
9121 sym = global_identifier_push(v, type.t, 0);
9122 sym->type.ref = type.ref;
9125 /* static inline functions are just recorded as a kind
9126 of macro. Their code will be emitted at the end of
9127 the compilation unit only if they are used */
9128 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9129 (VT_INLINE | VT_STATIC)) {
9130 TokenString func_str;
9131 int block_level;
9133 tok_str_new(&func_str);
9135 block_level = 0;
9136 for(;;) {
9137 int t;
9138 if (tok == TOK_EOF)
9139 error("unexpected end of file");
9140 tok_str_add_tok(&func_str);
9141 t = tok;
9142 next();
9143 if (t == '{') {
9144 block_level++;
9145 } else if (t == '}') {
9146 block_level--;
9147 if (block_level == 0)
9148 break;
9151 tok_str_add(&func_str, -1);
9152 tok_str_add(&func_str, 0);
9153 sym->r = (int)func_str.str;
9154 } else {
9155 /* compute text section */
9156 cur_text_section = ad.section;
9157 if (!cur_text_section)
9158 cur_text_section = text_section;
9159 sym->r = VT_SYM | VT_CONST;
9160 gen_function(sym);
9161 #ifdef TCC_TARGET_PE
9162 if (ad.dllexport) {
9163 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
9165 #endif
9167 break;
9168 } else {
9169 if (btype.t & VT_TYPEDEF) {
9170 /* save typedefed type */
9171 /* XXX: test storage specifiers ? */
9172 sym = sym_push(v, &type, 0, 0);
9173 sym->type.t |= VT_TYPEDEF;
9174 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9175 /* external function definition */
9176 /* specific case for func_call attribute */
9177 if (ad.func_call)
9178 type.ref->r = ad.func_call;
9179 external_sym(v, &type, 0);
9180 } else {
9181 /* not lvalue if array */
9182 r = 0;
9183 if (!(type.t & VT_ARRAY))
9184 r |= lvalue_type(type.t);
9185 has_init = (tok == '=');
9186 if ((btype.t & VT_EXTERN) ||
9187 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9188 !has_init && l == VT_CONST && type.ref->c < 0)) {
9189 /* external variable */
9190 /* NOTE: as GCC, uninitialized global static
9191 arrays of null size are considered as
9192 extern */
9193 external_sym(v, &type, r);
9194 } else {
9195 if (type.t & VT_STATIC)
9196 r |= VT_CONST;
9197 else
9198 r |= l;
9199 if (has_init)
9200 next();
9201 decl_initializer_alloc(&type, &ad, r,
9202 has_init, v, l);
9205 if (tok != ',') {
9206 skip(';');
9207 break;
9209 next();
9215 /* better than nothing, but needs extension to handle '-E' option
9216 correctly too */
9217 static void preprocess_init(TCCState *s1)
9219 s1->include_stack_ptr = s1->include_stack;
9220 /* XXX: move that before to avoid having to initialize
9221 file->ifdef_stack_ptr ? */
9222 s1->ifdef_stack_ptr = s1->ifdef_stack;
9223 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9225 /* XXX: not ANSI compliant: bound checking says error */
9226 vtop = vstack - 1;
9227 s1->pack_stack[0] = 0;
9228 s1->pack_stack_ptr = s1->pack_stack;
9231 /* compile the C file opened in 'file'. Return non zero if errors. */
9232 static int tcc_compile(TCCState *s1)
9234 Sym *define_start;
9235 char buf[512];
9236 volatile int section_sym;
9238 #ifdef INC_DEBUG
9239 printf("%s: **** new file\n", file->filename);
9240 #endif
9241 preprocess_init(s1);
9243 funcname = "";
9244 anon_sym = SYM_FIRST_ANOM;
9246 /* file info: full path + filename */
9247 section_sym = 0; /* avoid warning */
9248 if (do_debug) {
9249 section_sym = put_elf_sym(symtab_section, 0, 0,
9250 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9251 text_section->sh_num, NULL);
9252 getcwd(buf, sizeof(buf));
9253 pstrcat(buf, sizeof(buf), "/");
9254 put_stabs_r(buf, N_SO, 0, 0,
9255 text_section->data_offset, text_section, section_sym);
9256 put_stabs_r(file->filename, N_SO, 0, 0,
9257 text_section->data_offset, text_section, section_sym);
9259 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9260 symbols can be safely used */
9261 put_elf_sym(symtab_section, 0, 0,
9262 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9263 SHN_ABS, file->filename);
9265 /* define some often used types */
9266 int_type.t = VT_INT;
9268 char_pointer_type.t = VT_BYTE;
9269 mk_pointer(&char_pointer_type);
9271 func_old_type.t = VT_FUNC;
9272 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9274 #if 0
9275 /* define 'void *alloca(unsigned int)' builtin function */
9277 Sym *s1;
9279 p = anon_sym++;
9280 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9281 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9282 s1->next = NULL;
9283 sym->next = s1;
9284 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9286 #endif
9288 define_start = define_stack;
9290 if (setjmp(s1->error_jmp_buf) == 0) {
9291 s1->nb_errors = 0;
9292 s1->error_set_jmp_enabled = 1;
9294 ch = file->buf_ptr[0];
9295 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9296 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9297 next();
9298 decl(VT_CONST);
9299 if (tok != TOK_EOF)
9300 expect("declaration");
9302 /* end of translation unit info */
9303 if (do_debug) {
9304 put_stabs_r(NULL, N_SO, 0, 0,
9305 text_section->data_offset, text_section, section_sym);
9308 s1->error_set_jmp_enabled = 0;
9310 /* reset define stack, but leave -Dsymbols (may be incorrect if
9311 they are undefined) */
9312 free_defines(define_start);
9314 gen_inline_functions();
9316 sym_pop(&global_stack, NULL);
9318 return s1->nb_errors != 0 ? -1 : 0;
9321 /* Preprocess the current file */
9322 /* XXX: add line and file infos, add options to preserve spaces */
9323 static int tcc_preprocess(TCCState *s1)
9325 Sym *define_start;
9326 int last_is_space;
9328 preprocess_init(s1);
9330 define_start = define_stack;
9332 ch = file->buf_ptr[0];
9333 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9334 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9335 PARSE_FLAG_LINEFEED;
9336 last_is_space = 1;
9337 next();
9338 for(;;) {
9339 if (tok == TOK_EOF)
9340 break;
9341 if (!last_is_space) {
9342 fputc(' ', s1->outfile);
9344 fputs(get_tok_str(tok, &tokc), s1->outfile);
9345 if (tok == TOK_LINEFEED) {
9346 last_is_space = 1;
9347 /* XXX: suppress that hack */
9348 parse_flags &= ~PARSE_FLAG_LINEFEED;
9349 next();
9350 parse_flags |= PARSE_FLAG_LINEFEED;
9351 } else {
9352 last_is_space = 0;
9353 next();
9357 free_defines(define_start);
9359 return 0;
9362 #ifdef LIBTCC
9363 int tcc_compile_string(TCCState *s, const char *str)
9365 BufferedFile bf1, *bf = &bf1;
9366 int ret, len;
9367 char *buf;
9369 /* init file structure */
9370 bf->fd = -1;
9371 /* XXX: avoid copying */
9372 len = strlen(str);
9373 buf = tcc_malloc(len + 1);
9374 if (!buf)
9375 return -1;
9376 memcpy(buf, str, len);
9377 buf[len] = CH_EOB;
9378 bf->buf_ptr = buf;
9379 bf->buf_end = buf + len;
9380 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9381 bf->line_num = 1;
9382 file = bf;
9384 ret = tcc_compile(s);
9386 tcc_free(buf);
9388 /* currently, no need to close */
9389 return ret;
9391 #endif
9393 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9394 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9396 BufferedFile bf1, *bf = &bf1;
9398 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9399 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9400 /* default value */
9401 if (!value)
9402 value = "1";
9403 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9405 /* init file structure */
9406 bf->fd = -1;
9407 bf->buf_ptr = bf->buffer;
9408 bf->buf_end = bf->buffer + strlen(bf->buffer);
9409 *bf->buf_end = CH_EOB;
9410 bf->filename[0] = '\0';
9411 bf->line_num = 1;
9412 file = bf;
9414 s1->include_stack_ptr = s1->include_stack;
9416 /* parse with define parser */
9417 ch = file->buf_ptr[0];
9418 next_nomacro();
9419 parse_define();
9420 file = NULL;
9423 /* undefine a preprocessor symbol */
9424 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9426 TokenSym *ts;
9427 Sym *s;
9428 ts = tok_alloc(sym, strlen(sym));
9429 s = define_find(ts->tok);
9430 /* undefine symbol by putting an invalid name */
9431 if (s)
9432 define_undef(s);
9435 #ifdef CONFIG_TCC_ASM
9437 #ifdef TCC_TARGET_I386
9438 #include "i386-asm.c"
9439 #endif
9440 #include "tccasm.c"
9442 #else
9443 static void asm_instr(void)
9445 error("inline asm() not supported");
9447 static void asm_global_instr(void)
9449 error("inline asm() not supported");
9451 #endif
9453 #include "tccelf.c"
9455 #ifdef TCC_TARGET_COFF
9456 #include "tcccoff.c"
9457 #endif
9459 #ifdef TCC_TARGET_PE
9460 #include "tccpe.c"
9461 #endif
9463 /* print the position in the source file of PC value 'pc' by reading
9464 the stabs debug information */
9465 static void rt_printline(unsigned long wanted_pc)
9467 Stab_Sym *sym, *sym_end;
9468 char func_name[128], last_func_name[128];
9469 unsigned long func_addr, last_pc, pc;
9470 const char *incl_files[INCLUDE_STACK_SIZE];
9471 int incl_index, len, last_line_num, i;
9472 const char *str, *p;
9474 fprintf(stderr, "0x%08lx:", wanted_pc);
9476 func_name[0] = '\0';
9477 func_addr = 0;
9478 incl_index = 0;
9479 last_func_name[0] = '\0';
9480 last_pc = 0xffffffff;
9481 last_line_num = 1;
9482 sym = (Stab_Sym *)stab_section->data + 1;
9483 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9484 while (sym < sym_end) {
9485 switch(sym->n_type) {
9486 /* function start or end */
9487 case N_FUN:
9488 if (sym->n_strx == 0) {
9489 /* we test if between last line and end of function */
9490 pc = sym->n_value + func_addr;
9491 if (wanted_pc >= last_pc && wanted_pc < pc)
9492 goto found;
9493 func_name[0] = '\0';
9494 func_addr = 0;
9495 } else {
9496 str = stabstr_section->data + sym->n_strx;
9497 p = strchr(str, ':');
9498 if (!p) {
9499 pstrcpy(func_name, sizeof(func_name), str);
9500 } else {
9501 len = p - str;
9502 if (len > sizeof(func_name) - 1)
9503 len = sizeof(func_name) - 1;
9504 memcpy(func_name, str, len);
9505 func_name[len] = '\0';
9507 func_addr = sym->n_value;
9509 break;
9510 /* line number info */
9511 case N_SLINE:
9512 pc = sym->n_value + func_addr;
9513 if (wanted_pc >= last_pc && wanted_pc < pc)
9514 goto found;
9515 last_pc = pc;
9516 last_line_num = sym->n_desc;
9517 /* XXX: slow! */
9518 strcpy(last_func_name, func_name);
9519 break;
9520 /* include files */
9521 case N_BINCL:
9522 str = stabstr_section->data + sym->n_strx;
9523 add_incl:
9524 if (incl_index < INCLUDE_STACK_SIZE) {
9525 incl_files[incl_index++] = str;
9527 break;
9528 case N_EINCL:
9529 if (incl_index > 1)
9530 incl_index--;
9531 break;
9532 case N_SO:
9533 if (sym->n_strx == 0) {
9534 incl_index = 0; /* end of translation unit */
9535 } else {
9536 str = stabstr_section->data + sym->n_strx;
9537 /* do not add path */
9538 len = strlen(str);
9539 if (len > 0 && str[len - 1] != '/')
9540 goto add_incl;
9542 break;
9544 sym++;
9547 /* second pass: we try symtab symbols (no line number info) */
9548 incl_index = 0;
9550 Elf32_Sym *sym, *sym_end;
9551 int type;
9553 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9554 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9555 sym < sym_end;
9556 sym++) {
9557 type = ELF32_ST_TYPE(sym->st_info);
9558 if (type == STT_FUNC) {
9559 if (wanted_pc >= sym->st_value &&
9560 wanted_pc < sym->st_value + sym->st_size) {
9561 pstrcpy(last_func_name, sizeof(last_func_name),
9562 strtab_section->data + sym->st_name);
9563 goto found;
9568 /* did not find any info: */
9569 fprintf(stderr, " ???\n");
9570 return;
9571 found:
9572 if (last_func_name[0] != '\0') {
9573 fprintf(stderr, " %s()", last_func_name);
9575 if (incl_index > 0) {
9576 fprintf(stderr, " (%s:%d",
9577 incl_files[incl_index - 1], last_line_num);
9578 for(i = incl_index - 2; i >= 0; i--)
9579 fprintf(stderr, ", included from %s", incl_files[i]);
9580 fprintf(stderr, ")");
9582 fprintf(stderr, "\n");
9585 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9587 #ifdef __i386__
9589 /* fix for glibc 2.1 */
9590 #ifndef REG_EIP
9591 #define REG_EIP EIP
9592 #define REG_EBP EBP
9593 #endif
9595 /* return the PC at frame level 'level'. Return non zero if not found */
9596 static int rt_get_caller_pc(unsigned long *paddr,
9597 ucontext_t *uc, int level)
9599 unsigned long fp;
9600 int i;
9602 if (level == 0) {
9603 #if defined(__FreeBSD__)
9604 *paddr = uc->uc_mcontext.mc_eip;
9605 #elif defined(__dietlibc__)
9606 *paddr = uc->uc_mcontext.eip;
9607 #else
9608 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9609 #endif
9610 return 0;
9611 } else {
9612 #if defined(__FreeBSD__)
9613 fp = uc->uc_mcontext.mc_ebp;
9614 #elif defined(__dietlibc__)
9615 fp = uc->uc_mcontext.ebp;
9616 #else
9617 fp = uc->uc_mcontext.gregs[REG_EBP];
9618 #endif
9619 for(i=1;i<level;i++) {
9620 /* XXX: check address validity with program info */
9621 if (fp <= 0x1000 || fp >= 0xc0000000)
9622 return -1;
9623 fp = ((unsigned long *)fp)[0];
9625 *paddr = ((unsigned long *)fp)[1];
9626 return 0;
9629 #else
9631 #warning add arch specific rt_get_caller_pc()
9633 static int rt_get_caller_pc(unsigned long *paddr,
9634 ucontext_t *uc, int level)
9636 return -1;
9638 #endif
9640 /* emit a run time error at position 'pc' */
9641 void rt_error(ucontext_t *uc, const char *fmt, ...)
9643 va_list ap;
9644 unsigned long pc;
9645 int i;
9647 va_start(ap, fmt);
9648 fprintf(stderr, "Runtime error: ");
9649 vfprintf(stderr, fmt, ap);
9650 fprintf(stderr, "\n");
9651 for(i=0;i<num_callers;i++) {
9652 if (rt_get_caller_pc(&pc, uc, i) < 0)
9653 break;
9654 if (i == 0)
9655 fprintf(stderr, "at ");
9656 else
9657 fprintf(stderr, "by ");
9658 rt_printline(pc);
9660 exit(255);
9661 va_end(ap);
9664 /* signal handler for fatal errors */
9665 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9667 ucontext_t *uc = puc;
9669 switch(signum) {
9670 case SIGFPE:
9671 switch(siginf->si_code) {
9672 case FPE_INTDIV:
9673 case FPE_FLTDIV:
9674 rt_error(uc, "division by zero");
9675 break;
9676 default:
9677 rt_error(uc, "floating point exception");
9678 break;
9680 break;
9681 case SIGBUS:
9682 case SIGSEGV:
9683 if (rt_bound_error_msg && *rt_bound_error_msg)
9684 rt_error(uc, *rt_bound_error_msg);
9685 else
9686 rt_error(uc, "dereferencing invalid pointer");
9687 break;
9688 case SIGILL:
9689 rt_error(uc, "illegal instruction");
9690 break;
9691 case SIGABRT:
9692 rt_error(uc, "abort() called");
9693 break;
9694 default:
9695 rt_error(uc, "caught signal %d", signum);
9696 break;
9698 exit(255);
9700 #endif
9702 /* do all relocations (needed before using tcc_get_symbol()) */
9703 int tcc_relocate(TCCState *s1)
9705 Section *s;
9706 int i;
9708 s1->nb_errors = 0;
9710 #ifdef TCC_TARGET_PE
9711 pe_add_runtime(s1);
9712 #else
9713 tcc_add_runtime(s1);
9714 #endif
9716 relocate_common_syms();
9718 tcc_add_linker_symbols(s1);
9720 build_got_entries(s1);
9722 /* compute relocation address : section are relocated in place. We
9723 also alloc the bss space */
9724 for(i = 1; i < s1->nb_sections; i++) {
9725 s = s1->sections[i];
9726 if (s->sh_flags & SHF_ALLOC) {
9727 if (s->sh_type == SHT_NOBITS)
9728 s->data = tcc_mallocz(s->data_offset);
9729 s->sh_addr = (unsigned long)s->data;
9733 relocate_syms(s1, 1);
9735 if (s1->nb_errors != 0)
9736 return -1;
9738 /* relocate each section */
9739 for(i = 1; i < s1->nb_sections; i++) {
9740 s = s1->sections[i];
9741 if (s->reloc)
9742 relocate_section(s1, s);
9745 /* mark executable sections as executable in memory */
9746 for(i = 1; i < s1->nb_sections; i++) {
9747 s = s1->sections[i];
9748 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
9749 (SHF_ALLOC | SHF_EXECINSTR)) {
9750 #ifdef WIN32
9752 DWORD old_protect;
9753 VirtualProtect(s->data, s->data_offset,
9754 PAGE_EXECUTE_READWRITE, &old_protect);
9756 #else
9758 unsigned long start, end;
9759 start = (unsigned long)(s->data) & ~(PAGESIZE - 1);
9760 end = (unsigned long)(s->data + s->data_offset);
9761 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
9762 mprotect((void *)start, end - start,
9763 PROT_READ | PROT_WRITE | PROT_EXEC);
9765 #endif
9768 return 0;
9771 /* launch the compiled program with the given arguments */
9772 int tcc_run(TCCState *s1, int argc, char **argv)
9774 int (*prog_main)(int, char **);
9776 if (tcc_relocate(s1) < 0)
9777 return -1;
9779 prog_main = tcc_get_symbol_err(s1, "main");
9781 if (do_debug) {
9782 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9783 error("debug mode currently not available for Windows");
9784 #else
9785 struct sigaction sigact;
9786 /* install TCC signal handlers to print debug info on fatal
9787 runtime errors */
9788 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9789 sigact.sa_sigaction = sig_error;
9790 sigemptyset(&sigact.sa_mask);
9791 sigaction(SIGFPE, &sigact, NULL);
9792 sigaction(SIGILL, &sigact, NULL);
9793 sigaction(SIGSEGV, &sigact, NULL);
9794 sigaction(SIGBUS, &sigact, NULL);
9795 sigaction(SIGABRT, &sigact, NULL);
9796 #endif
9799 #ifdef CONFIG_TCC_BCHECK
9800 if (do_bounds_check) {
9801 void (*bound_init)(void);
9803 /* set error function */
9804 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9805 "__bound_error_msg");
9807 /* XXX: use .init section so that it also work in binary ? */
9808 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9809 bound_init();
9811 #endif
9812 return (*prog_main)(argc, argv);
9815 TCCState *tcc_new(void)
9817 const char *p, *r;
9818 TCCState *s;
9819 TokenSym *ts;
9820 int i, c;
9822 s = tcc_mallocz(sizeof(TCCState));
9823 if (!s)
9824 return NULL;
9825 tcc_state = s;
9826 s->output_type = TCC_OUTPUT_MEMORY;
9828 /* init isid table */
9829 for(i=0;i<256;i++)
9830 isidnum_table[i] = isid(i) || isnum(i);
9832 /* add all tokens */
9833 table_ident = NULL;
9834 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9836 tok_ident = TOK_IDENT;
9837 p = tcc_keywords;
9838 while (*p) {
9839 r = p;
9840 for(;;) {
9841 c = *r++;
9842 if (c == '\0')
9843 break;
9845 ts = tok_alloc(p, r - p - 1);
9846 p = r;
9849 /* we add dummy defines for some special macros to speed up tests
9850 and to have working defined() */
9851 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9852 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9853 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9854 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9856 /* standard defines */
9857 tcc_define_symbol(s, "__STDC__", NULL);
9858 #if defined(TCC_TARGET_I386)
9859 tcc_define_symbol(s, "__i386__", NULL);
9860 #endif
9861 #if defined(TCC_TARGET_ARM)
9862 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9863 tcc_define_symbol(s, "__arm_elf__", NULL);
9864 tcc_define_symbol(s, "__arm_elf", NULL);
9865 tcc_define_symbol(s, "arm_elf", NULL);
9866 tcc_define_symbol(s, "__arm__", NULL);
9867 tcc_define_symbol(s, "__arm", NULL);
9868 tcc_define_symbol(s, "arm", NULL);
9869 tcc_define_symbol(s, "__APCS_32__", NULL);
9870 #endif
9871 #if defined(linux)
9872 tcc_define_symbol(s, "__linux__", NULL);
9873 tcc_define_symbol(s, "linux", NULL);
9874 #endif
9875 /* tiny C specific defines */
9876 tcc_define_symbol(s, "__TINYC__", NULL);
9878 /* tiny C & gcc defines */
9879 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9880 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9881 #ifdef TCC_TARGET_PE
9882 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
9883 #else
9884 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9885 #endif
9887 /* default library paths */
9888 #ifdef TCC_TARGET_PE
9890 char buf[1024];
9891 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
9892 tcc_add_library_path(s, buf);
9894 #else
9895 tcc_add_library_path(s, "/usr/local/lib");
9896 tcc_add_library_path(s, "/usr/lib");
9897 tcc_add_library_path(s, "/lib");
9898 #endif
9900 /* no section zero */
9901 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9903 /* create standard sections */
9904 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9905 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9906 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9908 /* symbols are always generated for linking stage */
9909 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9910 ".strtab",
9911 ".hashtab", SHF_PRIVATE);
9912 strtab_section = symtab_section->link;
9914 /* private symbol table for dynamic symbols */
9915 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9916 ".dynstrtab",
9917 ".dynhashtab", SHF_PRIVATE);
9918 s->alacarte_link = 1;
9920 #ifdef CHAR_IS_UNSIGNED
9921 s->char_is_unsigned = 1;
9922 #endif
9923 #if defined(TCC_TARGET_PE) && 0
9924 /* XXX: currently the PE linker is not ready to support that */
9925 s->leading_underscore = 1;
9926 #endif
9927 return s;
9930 void tcc_delete(TCCState *s1)
9932 int i, n;
9934 /* free -D defines */
9935 free_defines(NULL);
9937 /* free tokens */
9938 n = tok_ident - TOK_IDENT;
9939 for(i = 0; i < n; i++)
9940 tcc_free(table_ident[i]);
9941 tcc_free(table_ident);
9943 /* free all sections */
9945 free_section(symtab_section->hash);
9947 free_section(s1->dynsymtab_section->hash);
9948 free_section(s1->dynsymtab_section->link);
9949 free_section(s1->dynsymtab_section);
9951 for(i = 1; i < s1->nb_sections; i++)
9952 free_section(s1->sections[i]);
9953 tcc_free(s1->sections);
9955 /* free loaded dlls array */
9956 for(i = 0; i < s1->nb_loaded_dlls; i++)
9957 tcc_free(s1->loaded_dlls[i]);
9958 tcc_free(s1->loaded_dlls);
9960 /* library paths */
9961 for(i = 0; i < s1->nb_library_paths; i++)
9962 tcc_free(s1->library_paths[i]);
9963 tcc_free(s1->library_paths);
9965 /* cached includes */
9966 for(i = 0; i < s1->nb_cached_includes; i++)
9967 tcc_free(s1->cached_includes[i]);
9968 tcc_free(s1->cached_includes);
9970 for(i = 0; i < s1->nb_include_paths; i++)
9971 tcc_free(s1->include_paths[i]);
9972 tcc_free(s1->include_paths);
9974 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9975 tcc_free(s1->sysinclude_paths[i]);
9976 tcc_free(s1->sysinclude_paths);
9978 tcc_free(s1);
9981 int tcc_add_include_path(TCCState *s1, const char *pathname)
9983 char *pathname1;
9985 pathname1 = tcc_strdup(pathname);
9986 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9987 return 0;
9990 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9992 char *pathname1;
9994 pathname1 = tcc_strdup(pathname);
9995 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9996 return 0;
9999 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10001 const char *ext, *filename1;
10002 Elf32_Ehdr ehdr;
10003 int fd, ret;
10004 BufferedFile *saved_file;
10006 /* find source file type with extension */
10007 filename1 = strrchr(filename, '/');
10008 if (filename1)
10009 filename1++;
10010 else
10011 filename1 = filename;
10012 ext = strrchr(filename1, '.');
10013 if (ext)
10014 ext++;
10016 /* open the file */
10017 saved_file = file;
10018 file = tcc_open(s1, filename);
10019 if (!file) {
10020 if (flags & AFF_PRINT_ERROR) {
10021 error_noabort("file '%s' not found", filename);
10023 ret = -1;
10024 goto fail1;
10027 if (flags & AFF_PREPROCESS) {
10028 ret = tcc_preprocess(s1);
10029 } else if (!ext || !strcmp(ext, "c")) {
10030 /* C file assumed */
10031 ret = tcc_compile(s1);
10032 } else
10033 #ifdef CONFIG_TCC_ASM
10034 if (!strcmp(ext, "S")) {
10035 /* preprocessed assembler */
10036 ret = tcc_assemble(s1, 1);
10037 } else if (!strcmp(ext, "s")) {
10038 /* non preprocessed assembler */
10039 ret = tcc_assemble(s1, 0);
10040 } else
10041 #endif
10042 #ifdef TCC_TARGET_PE
10043 if (!strcmp(ext, "def")) {
10044 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
10045 } else
10046 #endif
10048 fd = file->fd;
10049 /* assume executable format: auto guess file type */
10050 ret = read(fd, &ehdr, sizeof(ehdr));
10051 lseek(fd, 0, SEEK_SET);
10052 if (ret <= 0) {
10053 error_noabort("could not read header");
10054 goto fail;
10055 } else if (ret != sizeof(ehdr)) {
10056 goto try_load_script;
10059 if (ehdr.e_ident[0] == ELFMAG0 &&
10060 ehdr.e_ident[1] == ELFMAG1 &&
10061 ehdr.e_ident[2] == ELFMAG2 &&
10062 ehdr.e_ident[3] == ELFMAG3) {
10063 file->line_num = 0; /* do not display line number if error */
10064 if (ehdr.e_type == ET_REL) {
10065 ret = tcc_load_object_file(s1, fd, 0);
10066 } else if (ehdr.e_type == ET_DYN) {
10067 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10068 #ifdef TCC_TARGET_PE
10069 ret = -1;
10070 #else
10071 void *h;
10072 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10073 if (h)
10074 ret = 0;
10075 else
10076 ret = -1;
10077 #endif
10078 } else {
10079 ret = tcc_load_dll(s1, fd, filename,
10080 (flags & AFF_REFERENCED_DLL) != 0);
10082 } else {
10083 error_noabort("unrecognized ELF file");
10084 goto fail;
10086 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10087 file->line_num = 0; /* do not display line number if error */
10088 ret = tcc_load_archive(s1, fd);
10089 } else
10090 #ifdef TCC_TARGET_COFF
10091 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10092 ret = tcc_load_coff(s1, fd);
10093 } else
10094 #endif
10096 /* as GNU ld, consider it is an ld script if not recognized */
10097 try_load_script:
10098 ret = tcc_load_ldscript(s1);
10099 if (ret < 0) {
10100 error_noabort("unrecognized file type");
10101 goto fail;
10105 the_end:
10106 tcc_close(file);
10107 fail1:
10108 file = saved_file;
10109 return ret;
10110 fail:
10111 ret = -1;
10112 goto the_end;
10115 int tcc_add_file(TCCState *s, const char *filename)
10117 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10120 int tcc_add_library_path(TCCState *s, const char *pathname)
10122 char *pathname1;
10124 pathname1 = tcc_strdup(pathname);
10125 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10126 return 0;
10129 /* find and load a dll. Return non zero if not found */
10130 /* XXX: add '-rpath' option support ? */
10131 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10133 char buf[1024];
10134 int i;
10136 for(i = 0; i < s->nb_library_paths; i++) {
10137 snprintf(buf, sizeof(buf), "%s/%s",
10138 s->library_paths[i], filename);
10139 if (tcc_add_file_internal(s, buf, flags) == 0)
10140 return 0;
10142 return -1;
10145 /* the library name is the same as the argument of the '-l' option */
10146 int tcc_add_library(TCCState *s, const char *libraryname)
10148 char buf[1024];
10149 int i;
10151 /* first we look for the dynamic library if not static linking */
10152 if (!s->static_link) {
10153 #ifdef TCC_TARGET_PE
10154 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10155 #else
10156 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10157 #endif
10158 if (tcc_add_dll(s, buf, 0) == 0)
10159 return 0;
10162 /* then we look for the static library */
10163 for(i = 0; i < s->nb_library_paths; i++) {
10164 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10165 s->library_paths[i], libraryname);
10166 if (tcc_add_file_internal(s, buf, 0) == 0)
10167 return 0;
10169 return -1;
10172 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10174 add_elf_sym(symtab_section, val, 0,
10175 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10176 SHN_ABS, name);
10177 return 0;
10180 int tcc_set_output_type(TCCState *s, int output_type)
10182 s->output_type = output_type;
10184 if (!s->nostdinc) {
10185 char buf[1024];
10187 /* default include paths */
10188 /* XXX: reverse order needed if -isystem support */
10189 #ifndef TCC_TARGET_PE
10190 tcc_add_sysinclude_path(s, "/usr/local/include");
10191 tcc_add_sysinclude_path(s, "/usr/include");
10192 #endif
10193 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10194 tcc_add_sysinclude_path(s, buf);
10195 #ifdef TCC_TARGET_PE
10196 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10197 tcc_add_sysinclude_path(s, buf);
10198 #endif
10201 /* if bound checking, then add corresponding sections */
10202 #ifdef CONFIG_TCC_BCHECK
10203 if (do_bounds_check) {
10204 /* define symbol */
10205 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10206 /* create bounds sections */
10207 bounds_section = new_section(s, ".bounds",
10208 SHT_PROGBITS, SHF_ALLOC);
10209 lbounds_section = new_section(s, ".lbounds",
10210 SHT_PROGBITS, SHF_ALLOC);
10212 #endif
10214 if (s->char_is_unsigned) {
10215 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10218 /* add debug sections */
10219 if (do_debug) {
10220 /* stab symbols */
10221 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10222 stab_section->sh_entsize = sizeof(Stab_Sym);
10223 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10224 put_elf_str(stabstr_section, "");
10225 stab_section->link = stabstr_section;
10226 /* put first entry */
10227 put_stabs("", 0, 0, 0, 0);
10230 /* add libc crt1/crti objects */
10231 #ifndef TCC_TARGET_PE
10232 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10233 !s->nostdlib) {
10234 if (output_type != TCC_OUTPUT_DLL)
10235 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10236 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10238 #endif
10239 return 0;
10242 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10243 #define FD_INVERT 0x0002 /* invert value before storing */
10245 typedef struct FlagDef {
10246 uint16_t offset;
10247 uint16_t flags;
10248 const char *name;
10249 } FlagDef;
10251 static const FlagDef warning_defs[] = {
10252 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10253 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10254 { offsetof(TCCState, warn_error), 0, "error" },
10255 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10256 "implicit-function-declaration" },
10259 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10260 const char *name, int value)
10262 int i;
10263 const FlagDef *p;
10264 const char *r;
10266 r = name;
10267 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10268 r += 3;
10269 value = !value;
10271 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10272 if (!strcmp(r, p->name))
10273 goto found;
10275 return -1;
10276 found:
10277 if (p->flags & FD_INVERT)
10278 value = !value;
10279 *(int *)((uint8_t *)s + p->offset) = value;
10280 return 0;
10284 /* set/reset a warning */
10285 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10287 int i;
10288 const FlagDef *p;
10290 if (!strcmp(warning_name, "all")) {
10291 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10292 if (p->flags & WD_ALL)
10293 *(int *)((uint8_t *)s + p->offset) = 1;
10295 return 0;
10296 } else {
10297 return set_flag(s, warning_defs, countof(warning_defs),
10298 warning_name, value);
10302 static const FlagDef flag_defs[] = {
10303 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10304 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10305 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10306 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10309 /* set/reset a flag */
10310 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10312 return set_flag(s, flag_defs, countof(flag_defs),
10313 flag_name, value);
10316 #if !defined(LIBTCC)
10318 /* extract the basename of a file */
10319 static const char *tcc_basename(const char *name)
10321 const char *p;
10322 p = strrchr(name, '/');
10323 #ifdef WIN32
10324 if (!p)
10325 p = strrchr(name, '\\');
10326 #endif
10327 if (!p)
10328 p = name;
10329 else
10330 p++;
10331 return p;
10334 static int64_t getclock_us(void)
10336 #ifdef WIN32
10337 struct _timeb tb;
10338 _ftime(&tb);
10339 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10340 #else
10341 struct timeval tv;
10342 gettimeofday(&tv, NULL);
10343 return tv.tv_sec * 1000000LL + tv.tv_usec;
10344 #endif
10347 void help(void)
10349 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10350 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10351 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10352 " [infile1 infile2...] [-run infile args...]\n"
10353 "\n"
10354 "General options:\n"
10355 " -v display current version\n"
10356 " -c compile only - generate an object file\n"
10357 " -o outfile set output filename\n"
10358 " -Bdir set tcc internal library path\n"
10359 " -bench output compilation statistics\n"
10360 " -run run compiled source\n"
10361 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10362 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10363 " -w disable all warnings\n"
10364 "Preprocessor options:\n"
10365 " -E preprocess only\n"
10366 " -Idir add include path 'dir'\n"
10367 " -Dsym[=val] define 'sym' with value 'val'\n"
10368 " -Usym undefine 'sym'\n"
10369 "Linker options:\n"
10370 " -Ldir add library path 'dir'\n"
10371 " -llib link with dynamic or static library 'lib'\n"
10372 " -shared generate a shared library\n"
10373 " -static static linking\n"
10374 " -rdynamic export all global symbols to dynamic linker\n"
10375 " -r relocatable output\n"
10376 "Debugger options:\n"
10377 " -g generate runtime debug info\n"
10378 #ifdef CONFIG_TCC_BCHECK
10379 " -b compile with built-in memory and bounds checker (implies -g)\n"
10380 #endif
10381 " -bt N show N callers in stack traces\n"
10385 #define TCC_OPTION_HAS_ARG 0x0001
10386 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10388 typedef struct TCCOption {
10389 const char *name;
10390 uint16_t index;
10391 uint16_t flags;
10392 } TCCOption;
10394 enum {
10395 TCC_OPTION_HELP,
10396 TCC_OPTION_I,
10397 TCC_OPTION_D,
10398 TCC_OPTION_U,
10399 TCC_OPTION_L,
10400 TCC_OPTION_B,
10401 TCC_OPTION_l,
10402 TCC_OPTION_bench,
10403 TCC_OPTION_bt,
10404 TCC_OPTION_b,
10405 TCC_OPTION_g,
10406 TCC_OPTION_c,
10407 TCC_OPTION_static,
10408 TCC_OPTION_shared,
10409 TCC_OPTION_o,
10410 TCC_OPTION_r,
10411 TCC_OPTION_Wl,
10412 TCC_OPTION_W,
10413 TCC_OPTION_O,
10414 TCC_OPTION_m,
10415 TCC_OPTION_f,
10416 TCC_OPTION_nostdinc,
10417 TCC_OPTION_nostdlib,
10418 TCC_OPTION_print_search_dirs,
10419 TCC_OPTION_rdynamic,
10420 TCC_OPTION_run,
10421 TCC_OPTION_v,
10422 TCC_OPTION_w,
10423 TCC_OPTION_pipe,
10424 TCC_OPTION_E,
10427 static const TCCOption tcc_options[] = {
10428 { "h", TCC_OPTION_HELP, 0 },
10429 { "?", TCC_OPTION_HELP, 0 },
10430 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10431 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10432 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10433 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10434 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10435 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10436 { "bench", TCC_OPTION_bench, 0 },
10437 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10438 #ifdef CONFIG_TCC_BCHECK
10439 { "b", TCC_OPTION_b, 0 },
10440 #endif
10441 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10442 { "c", TCC_OPTION_c, 0 },
10443 { "static", TCC_OPTION_static, 0 },
10444 { "shared", TCC_OPTION_shared, 0 },
10445 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10446 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10447 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10448 { "r", TCC_OPTION_r, 0 },
10449 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10450 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10451 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10452 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10453 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10454 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10455 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10456 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10457 { "v", TCC_OPTION_v, 0 },
10458 { "w", TCC_OPTION_w, 0 },
10459 { "pipe", TCC_OPTION_pipe, 0},
10460 { "E", TCC_OPTION_E, 0},
10461 { NULL },
10464 /* convert 'str' into an array of space separated strings */
10465 static int expand_args(char ***pargv, const char *str)
10467 const char *s1;
10468 char **argv, *arg;
10469 int argc, len;
10471 argc = 0;
10472 argv = NULL;
10473 for(;;) {
10474 while (is_space(*str))
10475 str++;
10476 if (*str == '\0')
10477 break;
10478 s1 = str;
10479 while (*str != '\0' && !is_space(*str))
10480 str++;
10481 len = str - s1;
10482 arg = tcc_malloc(len + 1);
10483 memcpy(arg, s1, len);
10484 arg[len] = '\0';
10485 dynarray_add((void ***)&argv, &argc, arg);
10487 *pargv = argv;
10488 return argc;
10491 static char **files;
10492 static int nb_files, nb_libraries;
10493 static int multiple_files;
10494 static int print_search_dirs;
10495 static int output_type;
10496 static int reloc_output;
10497 static const char *outfile;
10499 int parse_args(TCCState *s, int argc, char **argv)
10501 int optind;
10502 const TCCOption *popt;
10503 const char *optarg, *p1, *r1;
10504 char *r;
10506 optind = 0;
10507 while (1) {
10508 if (optind >= argc) {
10509 if (nb_files == 0 && !print_search_dirs)
10510 goto show_help;
10511 else
10512 break;
10514 r = argv[optind++];
10515 if (r[0] != '-') {
10516 /* add a new file */
10517 dynarray_add((void ***)&files, &nb_files, r);
10518 if (!multiple_files) {
10519 optind--;
10520 /* argv[0] will be this file */
10521 break;
10523 } else {
10524 /* find option in table (match only the first chars */
10525 popt = tcc_options;
10526 for(;;) {
10527 p1 = popt->name;
10528 if (p1 == NULL)
10529 error("invalid option -- '%s'", r);
10530 r1 = r + 1;
10531 for(;;) {
10532 if (*p1 == '\0')
10533 goto option_found;
10534 if (*r1 != *p1)
10535 break;
10536 p1++;
10537 r1++;
10539 popt++;
10541 option_found:
10542 if (popt->flags & TCC_OPTION_HAS_ARG) {
10543 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10544 optarg = r1;
10545 } else {
10546 if (optind >= argc)
10547 error("argument to '%s' is missing", r);
10548 optarg = argv[optind++];
10550 } else {
10551 if (*r1 != '\0')
10552 goto show_help;
10553 optarg = NULL;
10556 switch(popt->index) {
10557 case TCC_OPTION_HELP:
10558 show_help:
10559 help();
10560 exit(1);
10561 case TCC_OPTION_I:
10562 if (tcc_add_include_path(s, optarg) < 0)
10563 error("too many include paths");
10564 break;
10565 case TCC_OPTION_D:
10567 char *sym, *value;
10568 sym = (char *)optarg;
10569 value = strchr(sym, '=');
10570 if (value) {
10571 *value = '\0';
10572 value++;
10574 tcc_define_symbol(s, sym, value);
10576 break;
10577 case TCC_OPTION_U:
10578 tcc_undefine_symbol(s, optarg);
10579 break;
10580 case TCC_OPTION_L:
10581 tcc_add_library_path(s, optarg);
10582 break;
10583 case TCC_OPTION_B:
10584 /* set tcc utilities path (mainly for tcc development) */
10585 tcc_lib_path = optarg;
10586 break;
10587 case TCC_OPTION_l:
10588 dynarray_add((void ***)&files, &nb_files, r);
10589 nb_libraries++;
10590 break;
10591 case TCC_OPTION_bench:
10592 do_bench = 1;
10593 break;
10594 case TCC_OPTION_bt:
10595 num_callers = atoi(optarg);
10596 break;
10597 #ifdef CONFIG_TCC_BCHECK
10598 case TCC_OPTION_b:
10599 do_bounds_check = 1;
10600 do_debug = 1;
10601 break;
10602 #endif
10603 case TCC_OPTION_g:
10604 do_debug = 1;
10605 break;
10606 case TCC_OPTION_c:
10607 multiple_files = 1;
10608 output_type = TCC_OUTPUT_OBJ;
10609 break;
10610 case TCC_OPTION_static:
10611 s->static_link = 1;
10612 break;
10613 case TCC_OPTION_shared:
10614 output_type = TCC_OUTPUT_DLL;
10615 break;
10616 case TCC_OPTION_o:
10617 multiple_files = 1;
10618 outfile = optarg;
10619 break;
10620 case TCC_OPTION_r:
10621 /* generate a .o merging several output files */
10622 reloc_output = 1;
10623 output_type = TCC_OUTPUT_OBJ;
10624 break;
10625 case TCC_OPTION_nostdinc:
10626 s->nostdinc = 1;
10627 break;
10628 case TCC_OPTION_nostdlib:
10629 s->nostdlib = 1;
10630 break;
10631 case TCC_OPTION_print_search_dirs:
10632 print_search_dirs = 1;
10633 break;
10634 case TCC_OPTION_run:
10636 int argc1;
10637 char **argv1;
10638 argc1 = expand_args(&argv1, optarg);
10639 if (argc1 > 0) {
10640 parse_args(s, argc1, argv1);
10642 multiple_files = 0;
10643 output_type = TCC_OUTPUT_MEMORY;
10645 break;
10646 case TCC_OPTION_v:
10647 printf("tcc version %s\n", TCC_VERSION);
10648 exit(0);
10649 case TCC_OPTION_f:
10650 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10651 goto unsupported_option;
10652 break;
10653 case TCC_OPTION_W:
10654 if (tcc_set_warning(s, optarg, 1) < 0 &&
10655 s->warn_unsupported)
10656 goto unsupported_option;
10657 break;
10658 case TCC_OPTION_w:
10659 s->warn_none = 1;
10660 break;
10661 case TCC_OPTION_rdynamic:
10662 s->rdynamic = 1;
10663 break;
10664 case TCC_OPTION_Wl:
10666 const char *p;
10667 if (strstart(optarg, "-Ttext,", &p)) {
10668 s->text_addr = strtoul(p, NULL, 16);
10669 s->has_text_addr = 1;
10670 } else if (strstart(optarg, "--oformat,", &p)) {
10671 if (strstart(p, "elf32-", NULL)) {
10672 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10673 } else if (!strcmp(p, "binary")) {
10674 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10675 } else
10676 #ifdef TCC_TARGET_COFF
10677 if (!strcmp(p, "coff")) {
10678 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10679 } else
10680 #endif
10682 error("target %s not found", p);
10684 } else {
10685 error("unsupported linker option '%s'", optarg);
10688 break;
10689 case TCC_OPTION_E:
10690 output_type = TCC_OUTPUT_PREPROCESS;
10691 break;
10692 default:
10693 if (s->warn_unsupported) {
10694 unsupported_option:
10695 warning("unsupported option '%s'", r);
10697 break;
10701 return optind;
10704 int main(int argc, char **argv)
10706 int i;
10707 TCCState *s;
10708 int nb_objfiles, ret, optind;
10709 char objfilename[1024];
10710 int64_t start_time = 0;
10712 #ifdef WIN32
10713 /* on win32, we suppose the lib and includes are at the location
10714 of 'tcc.exe' */
10716 static char path[1024];
10717 char *p, *d;
10719 GetModuleFileNameA(NULL, path, sizeof path);
10720 p = d = strlwr(path);
10721 while (*d)
10723 if (*d == '\\') *d = '/', p = d;
10724 ++d;
10726 *p = '\0';
10727 tcc_lib_path = path;
10729 #endif
10731 s = tcc_new();
10732 output_type = TCC_OUTPUT_EXE;
10733 outfile = NULL;
10734 multiple_files = 1;
10735 files = NULL;
10736 nb_files = 0;
10737 nb_libraries = 0;
10738 reloc_output = 0;
10739 print_search_dirs = 0;
10741 optind = parse_args(s, argc - 1, argv + 1) + 1;
10743 if (print_search_dirs) {
10744 /* enough for Linux kernel */
10745 printf("install: %s/\n", tcc_lib_path);
10746 return 0;
10749 nb_objfiles = nb_files - nb_libraries;
10751 /* if outfile provided without other options, we output an
10752 executable */
10753 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10754 output_type = TCC_OUTPUT_EXE;
10756 /* check -c consistency : only single file handled. XXX: checks file type */
10757 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10758 /* accepts only a single input file */
10759 if (nb_objfiles != 1)
10760 error("cannot specify multiple files with -c");
10761 if (nb_libraries != 0)
10762 error("cannot specify libraries with -c");
10766 if (output_type == TCC_OUTPUT_PREPROCESS) {
10767 if (!outfile) {
10768 s->outfile = stdout;
10769 } else {
10770 s->outfile = fopen(outfile, "wb");
10771 if (!s->outfile)
10772 error("could not open '%s", outfile);
10774 } else if (output_type != TCC_OUTPUT_MEMORY) {
10775 if (!outfile) {
10776 /* compute default outfile name */
10777 pstrcpy(objfilename, sizeof(objfilename) - 1,
10778 /* strip path */
10779 tcc_basename(files[0]));
10780 #ifdef TCC_TARGET_PE
10781 pe_guess_outfile(objfilename, output_type);
10782 #else
10783 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10784 char *ext = strrchr(objfilename, '.');
10785 if (!ext)
10786 goto default_outfile;
10787 /* add .o extension */
10788 strcpy(ext + 1, "o");
10789 } else {
10790 default_outfile:
10791 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10793 #endif
10794 outfile = objfilename;
10798 if (do_bench) {
10799 start_time = getclock_us();
10802 tcc_set_output_type(s, output_type);
10804 /* compile or add each files or library */
10805 for(i = 0;i < nb_files; i++) {
10806 const char *filename;
10808 filename = files[i];
10809 if (output_type == TCC_OUTPUT_PREPROCESS) {
10810 tcc_add_file_internal(s, filename,
10811 AFF_PRINT_ERROR | AFF_PREPROCESS);
10812 } else {
10813 if (filename[0] == '-') {
10814 if (tcc_add_library(s, filename + 2) < 0)
10815 error("cannot find %s", filename);
10816 } else {
10817 if (tcc_add_file(s, filename) < 0) {
10818 ret = 1;
10819 goto the_end;
10825 /* free all files */
10826 tcc_free(files);
10828 if (do_bench) {
10829 double total_time;
10830 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10831 if (total_time < 0.001)
10832 total_time = 0.001;
10833 if (total_bytes < 1)
10834 total_bytes = 1;
10835 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10836 tok_ident - TOK_IDENT, total_lines, total_bytes,
10837 total_time, (int)(total_lines / total_time),
10838 total_bytes / total_time / 1000000.0);
10841 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
10842 if (outfile)
10843 fclose(s->outfile);
10844 ret = 0;
10845 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
10846 ret = tcc_run(s, argc - optind, argv + optind);
10847 } else
10848 #ifdef TCC_TARGET_PE
10849 if (s->output_type != TCC_OUTPUT_OBJ) {
10850 ret = tcc_output_pe(s, outfile);
10851 } else
10852 #endif
10854 tcc_output_file(s, outfile);
10855 ret = 0;
10857 the_end:
10858 /* XXX: cannot do it with bound checking because of the malloc hooks */
10859 if (!do_bounds_check)
10860 tcc_delete(s);
10862 #ifdef MEM_DEBUG
10863 if (do_bench) {
10864 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10866 #endif
10867 return ret;
10870 #endif