Import more changesets from Rob Landley's fork (part 2)
[tinycc/miki.git] / tcc.c
blob3d80a3155a28cb2c5d58f027d95344b99442ad35
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);
728 int __stdcall VirtualProtect(void*,unsigned long,unsigned long,unsigned long*);
729 #define PAGE_EXECUTE_READWRITE 0x0040
731 #define snprintf _snprintf
732 #define vsnprintf _vsnprintf
733 #ifndef __GNUC__
734 #define strtold (long double)strtod
735 #define strtof (float)strtod
736 #define strtoll (long long)strtol
737 #endif
738 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
739 /* currently incorrect */
740 long double strtold(const char *nptr, char **endptr)
742 return (long double)strtod(nptr, endptr);
744 float strtof(const char *nptr, char **endptr)
746 return (float)strtod(nptr, endptr);
748 #else
749 /* XXX: need to define this to use them in non ISOC99 context */
750 extern float strtof (const char *__nptr, char **__endptr);
751 extern long double strtold (const char *__nptr, char **__endptr);
752 #endif
754 static char *pstrcpy(char *buf, int buf_size, const char *s);
755 static char *pstrcat(char *buf, int buf_size, const char *s);
756 static char *tcc_basename(const char *name);
758 static void next(void);
759 static void next_nomacro(void);
760 static void parse_expr_type(CType *type);
761 static void expr_type(CType *type);
762 static void unary_type(CType *type);
763 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
764 int case_reg, int is_expr);
765 static int expr_const(void);
766 static void expr_eq(void);
767 static void gexpr(void);
768 static void gen_inline_functions(void);
769 static void decl(int l);
770 static void decl_initializer(CType *type, Section *sec, unsigned long c,
771 int first, int size_only);
772 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
773 int has_init, int v, int scope);
774 int gv(int rc);
775 void gv2(int rc1, int rc2);
776 void move_reg(int r, int s);
777 void save_regs(int n);
778 void save_reg(int r);
779 void vpop(void);
780 void vswap(void);
781 void vdup(void);
782 int get_reg(int rc);
783 int get_reg_ex(int rc,int rc2);
785 struct macro_level {
786 struct macro_level *prev;
787 int *p;
790 static void macro_subst(TokenString *tok_str, Sym **nested_list,
791 const int *macro_str, struct macro_level **can_read_stream);
792 void gen_op(int op);
793 void force_charshort_cast(int t);
794 static void gen_cast(CType *type);
795 void vstore(void);
796 static Sym *sym_find(int v);
797 static Sym *sym_push(int v, CType *type, int r, int c);
799 /* type handling */
800 static int type_size(CType *type, int *a);
801 static inline CType *pointed_type(CType *type);
802 static int pointed_size(CType *type);
803 static int lvalue_type(int t);
804 static int parse_btype(CType *type, AttributeDef *ad);
805 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
806 static int compare_types(CType *type1, CType *type2, int unqualified);
807 static int is_compatible_types(CType *type1, CType *type2);
808 static int is_compatible_parameter_types(CType *type1, CType *type2);
810 int ieee_finite(double d);
811 void error(const char *fmt, ...);
812 void vpushi(int v);
813 void vrott(int n);
814 void vnrott(int n);
815 void lexpand_nr(void);
816 static void vpush_global_sym(CType *type, int v);
817 void vset(CType *type, int r, int v);
818 void type_to_str(char *buf, int buf_size,
819 CType *type, const char *varstr);
820 char *get_tok_str(int v, CValue *cv);
821 static Sym *get_sym_ref(CType *type, Section *sec,
822 unsigned long offset, unsigned long size);
823 static Sym *external_global_sym(int v, CType *type, int r);
825 /* section generation */
826 static void section_realloc(Section *sec, unsigned long new_size);
827 static void *section_ptr_add(Section *sec, unsigned long size);
828 static void put_extern_sym(Sym *sym, Section *section,
829 unsigned long value, unsigned long size);
830 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
831 static int put_elf_str(Section *s, const char *sym);
832 static int put_elf_sym(Section *s,
833 unsigned long value, unsigned long size,
834 int info, int other, int shndx, const char *name);
835 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
836 int info, int other, int sh_num, const char *name);
837 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
838 int type, int symbol);
839 static void put_stabs(const char *str, int type, int other, int desc,
840 unsigned long value);
841 static void put_stabs_r(const char *str, int type, int other, int desc,
842 unsigned long value, Section *sec, int sym_index);
843 static void put_stabn(int type, int other, int desc, int value);
844 static void put_stabd(int type, int other, int desc);
845 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
847 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
848 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
849 #define AFF_PREPROCESS 0x0004 /* preprocess file */
850 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
852 /* tcccoff.c */
853 int tcc_output_coff(TCCState *s1, FILE *f);
855 /* tccpe.c */
856 void *resolve_sym(TCCState *s1, const char *sym, int type);
857 int pe_load_def_file(struct TCCState *s1, FILE *fp);
858 void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
859 unsigned long pe_add_runtime(struct TCCState *s1);
860 int tcc_output_pe(struct TCCState *s1, const char *filename);
862 /* tccasm.c */
864 #ifdef CONFIG_TCC_ASM
866 typedef struct ExprValue {
867 uint32_t v;
868 Sym *sym;
869 } ExprValue;
871 #define MAX_ASM_OPERANDS 30
873 typedef struct ASMOperand {
874 int id; /* GCC 3 optionnal identifier (0 if number only supported */
875 char *constraint;
876 char asm_str[16]; /* computed asm string for operand */
877 SValue *vt; /* C value of the expression */
878 int ref_index; /* if >= 0, gives reference to a output constraint */
879 int input_index; /* if >= 0, gives reference to an input constraint */
880 int priority; /* priority, used to assign registers */
881 int reg; /* if >= 0, register number used for this operand */
882 int is_llong; /* true if double register value */
883 int is_memory; /* true if memory operand */
884 int is_rw; /* for '+' modifier */
885 } ASMOperand;
887 static void asm_expr(TCCState *s1, ExprValue *pe);
888 static int asm_int_expr(TCCState *s1);
889 static int find_constraint(ASMOperand *operands, int nb_operands,
890 const char *name, const char **pp);
892 static int tcc_assemble(TCCState *s1, int do_preprocess);
894 #endif
896 static void asm_instr(void);
897 static void asm_global_instr(void);
899 /* true if float/double/long double type */
900 static inline int is_float(int t)
902 int bt;
903 bt = t & VT_BTYPE;
904 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
907 #ifdef TCC_TARGET_I386
908 #include "i386-gen.c"
909 #endif
911 #ifdef TCC_TARGET_ARM
912 #include "arm-gen.c"
913 #endif
915 #ifdef TCC_TARGET_C67
916 #include "c67-gen.c"
917 #endif
919 #ifdef CONFIG_TCC_STATIC
921 #define RTLD_LAZY 0x001
922 #define RTLD_NOW 0x002
923 #define RTLD_GLOBAL 0x100
924 #define RTLD_DEFAULT NULL
926 /* dummy function for profiling */
927 void *dlopen(const char *filename, int flag)
929 return NULL;
932 const char *dlerror(void)
934 return "error";
937 typedef struct TCCSyms {
938 char *str;
939 void *ptr;
940 } TCCSyms;
942 #define TCCSYM(a) { #a, &a, },
944 /* add the symbol you want here if no dynamic linking is done */
945 static TCCSyms tcc_syms[] = {
946 #if !defined(CONFIG_TCCBOOT)
947 TCCSYM(printf)
948 TCCSYM(fprintf)
949 TCCSYM(fopen)
950 TCCSYM(fclose)
951 #endif
952 { NULL, NULL },
955 void *resolve_sym(TCCState *s1, const char *symbol, int type)
957 TCCSyms *p;
958 p = tcc_syms;
959 while (p->str != NULL) {
960 if (!strcmp(p->str, symbol))
961 return p->ptr;
962 p++;
964 return NULL;
967 #elif !defined(WIN32)
969 #include <dlfcn.h>
971 void *resolve_sym(TCCState *s1, const char *sym, int type)
973 return dlsym(RTLD_DEFAULT, sym);
976 #endif
978 /********************************************************/
980 /* we use our own 'finite' function to avoid potential problems with
981 non standard math libs */
982 /* XXX: endianness dependent */
983 int ieee_finite(double d)
985 int *p = (int *)&d;
986 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
989 /* copy a string and truncate it. */
990 static char *pstrcpy(char *buf, int buf_size, const char *s)
992 char *q, *q_end;
993 int c;
995 if (buf_size > 0) {
996 q = buf;
997 q_end = buf + buf_size - 1;
998 while (q < q_end) {
999 c = *s++;
1000 if (c == '\0')
1001 break;
1002 *q++ = c;
1004 *q = '\0';
1006 return buf;
1009 /* strcat and truncate. */
1010 static char *pstrcat(char *buf, int buf_size, const char *s)
1012 int len;
1013 len = strlen(buf);
1014 if (len < buf_size)
1015 pstrcpy(buf + len, buf_size - len, s);
1016 return buf;
1019 static int strstart(const char *str, const char *val, const char **ptr)
1021 const char *p, *q;
1022 p = str;
1023 q = val;
1024 while (*q != '\0') {
1025 if (*p != *q)
1026 return 0;
1027 p++;
1028 q++;
1030 if (ptr)
1031 *ptr = p;
1032 return 1;
1035 /* memory management */
1036 #ifdef MEM_DEBUG
1037 int mem_cur_size;
1038 int mem_max_size;
1039 #endif
1041 static inline void tcc_free(void *ptr)
1043 #ifdef MEM_DEBUG
1044 mem_cur_size -= malloc_usable_size(ptr);
1045 #endif
1046 free(ptr);
1049 static void *tcc_malloc(unsigned long size)
1051 void *ptr;
1052 ptr = malloc(size);
1053 if (!ptr && size)
1054 error("memory full");
1055 #ifdef MEM_DEBUG
1056 mem_cur_size += malloc_usable_size(ptr);
1057 if (mem_cur_size > mem_max_size)
1058 mem_max_size = mem_cur_size;
1059 #endif
1060 return ptr;
1063 static void *tcc_mallocz(unsigned long size)
1065 void *ptr;
1066 ptr = tcc_malloc(size);
1067 memset(ptr, 0, size);
1068 return ptr;
1071 static inline void *tcc_realloc(void *ptr, unsigned long size)
1073 void *ptr1;
1074 #ifdef MEM_DEBUG
1075 mem_cur_size -= malloc_usable_size(ptr);
1076 #endif
1077 ptr1 = realloc(ptr, size);
1078 #ifdef MEM_DEBUG
1079 /* NOTE: count not correct if alloc error, but not critical */
1080 mem_cur_size += malloc_usable_size(ptr1);
1081 if (mem_cur_size > mem_max_size)
1082 mem_max_size = mem_cur_size;
1083 #endif
1084 return ptr1;
1087 static char *tcc_strdup(const char *str)
1089 char *ptr;
1090 ptr = tcc_malloc(strlen(str) + 1);
1091 strcpy(ptr, str);
1092 return ptr;
1095 #define free(p) use_tcc_free(p)
1096 #define malloc(s) use_tcc_malloc(s)
1097 #define realloc(p, s) use_tcc_realloc(p, s)
1099 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1101 int nb, nb_alloc;
1102 void **pp;
1104 nb = *nb_ptr;
1105 pp = *ptab;
1106 /* every power of two we double array size */
1107 if ((nb & (nb - 1)) == 0) {
1108 if (!nb)
1109 nb_alloc = 1;
1110 else
1111 nb_alloc = nb * 2;
1112 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1113 if (!pp)
1114 error("memory full");
1115 *ptab = pp;
1117 pp[nb++] = data;
1118 *nb_ptr = nb;
1121 /* symbol allocator */
1122 static Sym *__sym_malloc(void)
1124 Sym *sym_pool, *sym, *last_sym;
1125 int i;
1127 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1129 last_sym = sym_free_first;
1130 sym = sym_pool;
1131 for(i = 0; i < SYM_POOL_NB; i++) {
1132 sym->next = last_sym;
1133 last_sym = sym;
1134 sym++;
1136 sym_free_first = last_sym;
1137 return last_sym;
1140 static inline Sym *sym_malloc(void)
1142 Sym *sym;
1143 sym = sym_free_first;
1144 if (!sym)
1145 sym = __sym_malloc();
1146 sym_free_first = sym->next;
1147 return sym;
1150 static inline void sym_free(Sym *sym)
1152 sym->next = sym_free_first;
1153 sym_free_first = sym;
1156 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1158 Section *sec;
1160 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1161 strcpy(sec->name, name);
1162 sec->sh_type = sh_type;
1163 sec->sh_flags = sh_flags;
1164 switch(sh_type) {
1165 case SHT_HASH:
1166 case SHT_REL:
1167 case SHT_DYNSYM:
1168 case SHT_SYMTAB:
1169 case SHT_DYNAMIC:
1170 sec->sh_addralign = 4;
1171 break;
1172 case SHT_STRTAB:
1173 sec->sh_addralign = 1;
1174 break;
1175 default:
1176 sec->sh_addralign = 32; /* default conservative alignment */
1177 break;
1180 /* only add section if not private */
1181 if (!(sh_flags & SHF_PRIVATE)) {
1182 sec->sh_num = s1->nb_sections;
1183 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1185 return sec;
1188 static void free_section(Section *s)
1190 tcc_free(s->data);
1191 tcc_free(s);
1194 /* realloc section and set its content to zero */
1195 static void section_realloc(Section *sec, unsigned long new_size)
1197 unsigned long size;
1198 unsigned char *data;
1200 size = sec->data_allocated;
1201 if (size == 0)
1202 size = 1;
1203 while (size < new_size)
1204 size = size * 2;
1205 data = tcc_realloc(sec->data, size);
1206 if (!data)
1207 error("memory full");
1208 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1209 sec->data = data;
1210 sec->data_allocated = size;
1213 /* reserve at least 'size' bytes in section 'sec' from
1214 sec->data_offset. */
1215 static void *section_ptr_add(Section *sec, unsigned long size)
1217 unsigned long offset, offset1;
1219 offset = sec->data_offset;
1220 offset1 = offset + size;
1221 if (offset1 > sec->data_allocated)
1222 section_realloc(sec, offset1);
1223 sec->data_offset = offset1;
1224 return sec->data + offset;
1227 /* return a reference to a section, and create it if it does not
1228 exists */
1229 Section *find_section(TCCState *s1, const char *name)
1231 Section *sec;
1232 int i;
1233 for(i = 1; i < s1->nb_sections; i++) {
1234 sec = s1->sections[i];
1235 if (!strcmp(name, sec->name))
1236 return sec;
1238 /* sections are created as PROGBITS */
1239 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1242 #define SECTION_ABS ((void *)1)
1244 /* update sym->c so that it points to an external symbol in section
1245 'section' with value 'value' */
1246 static void put_extern_sym2(Sym *sym, Section *section,
1247 unsigned long value, unsigned long size,
1248 int can_add_underscore)
1250 int sym_type, sym_bind, sh_num, info;
1251 Elf32_Sym *esym;
1252 const char *name;
1253 char buf1[256];
1255 if (section == NULL)
1256 sh_num = SHN_UNDEF;
1257 else if (section == SECTION_ABS)
1258 sh_num = SHN_ABS;
1259 else
1260 sh_num = section->sh_num;
1261 if (!sym->c) {
1262 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1263 sym_type = STT_FUNC;
1264 else
1265 sym_type = STT_OBJECT;
1266 if (sym->type.t & VT_STATIC)
1267 sym_bind = STB_LOCAL;
1268 else
1269 sym_bind = STB_GLOBAL;
1271 name = get_tok_str(sym->v, NULL);
1272 #ifdef CONFIG_TCC_BCHECK
1273 if (do_bounds_check) {
1274 char buf[32];
1276 /* XXX: avoid doing that for statics ? */
1277 /* if bound checking is activated, we change some function
1278 names by adding the "__bound" prefix */
1279 switch(sym->v) {
1280 #if 0
1281 /* XXX: we rely only on malloc hooks */
1282 case TOK_malloc:
1283 case TOK_free:
1284 case TOK_realloc:
1285 case TOK_memalign:
1286 case TOK_calloc:
1287 #endif
1288 case TOK_memcpy:
1289 case TOK_memmove:
1290 case TOK_memset:
1291 case TOK_strlen:
1292 case TOK_strcpy:
1293 case TOK__alloca:
1294 strcpy(buf, "__bound_");
1295 strcat(buf, name);
1296 name = buf;
1297 break;
1300 #endif
1301 if (tcc_state->leading_underscore && can_add_underscore) {
1302 buf1[0] = '_';
1303 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1304 name = buf1;
1306 info = ELF32_ST_INFO(sym_bind, sym_type);
1307 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
1308 } else {
1309 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1310 esym->st_value = value;
1311 esym->st_size = size;
1312 esym->st_shndx = sh_num;
1316 static void put_extern_sym(Sym *sym, Section *section,
1317 unsigned long value, unsigned long size)
1319 put_extern_sym2(sym, section, value, size, 1);
1322 /* add a new relocation entry to symbol 'sym' in section 's' */
1323 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1325 if (!sym->c)
1326 put_extern_sym(sym, NULL, 0, 0);
1327 /* now we can add ELF relocation info */
1328 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1331 static inline int isid(int c)
1333 return (c >= 'a' && c <= 'z') ||
1334 (c >= 'A' && c <= 'Z') ||
1335 c == '_';
1338 static inline int isnum(int c)
1340 return c >= '0' && c <= '9';
1343 static inline int isoct(int c)
1345 return c >= '0' && c <= '7';
1348 static inline int toup(int c)
1350 if (c >= 'a' && c <= 'z')
1351 return c - 'a' + 'A';
1352 else
1353 return c;
1356 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1358 int len;
1359 len = strlen(buf);
1360 vsnprintf(buf + len, buf_size - len, fmt, ap);
1363 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1365 va_list ap;
1366 va_start(ap, fmt);
1367 strcat_vprintf(buf, buf_size, fmt, ap);
1368 va_end(ap);
1371 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1373 char buf[2048];
1374 BufferedFile **f;
1376 buf[0] = '\0';
1377 if (file) {
1378 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1379 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1380 (*f)->filename, (*f)->line_num);
1381 if (file->line_num > 0) {
1382 strcat_printf(buf, sizeof(buf),
1383 "%s:%d: ", file->filename, file->line_num);
1384 } else {
1385 strcat_printf(buf, sizeof(buf),
1386 "%s: ", file->filename);
1388 } else {
1389 strcat_printf(buf, sizeof(buf),
1390 "tcc: ");
1392 if (is_warning)
1393 strcat_printf(buf, sizeof(buf), "warning: ");
1394 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1396 if (!s1->error_func) {
1397 /* default case: stderr */
1398 fprintf(stderr, "%s\n", buf);
1399 } else {
1400 s1->error_func(s1->error_opaque, buf);
1402 if (!is_warning || s1->warn_error)
1403 s1->nb_errors++;
1406 #ifdef LIBTCC
1407 void tcc_set_error_func(TCCState *s, void *error_opaque,
1408 void (*error_func)(void *opaque, const char *msg))
1410 s->error_opaque = error_opaque;
1411 s->error_func = error_func;
1413 #endif
1415 /* error without aborting current compilation */
1416 void error_noabort(const char *fmt, ...)
1418 TCCState *s1 = tcc_state;
1419 va_list ap;
1421 va_start(ap, fmt);
1422 error1(s1, 0, fmt, ap);
1423 va_end(ap);
1426 void error(const char *fmt, ...)
1428 TCCState *s1 = tcc_state;
1429 va_list ap;
1431 va_start(ap, fmt);
1432 error1(s1, 0, fmt, ap);
1433 va_end(ap);
1434 /* better than nothing: in some cases, we accept to handle errors */
1435 if (s1->error_set_jmp_enabled) {
1436 longjmp(s1->error_jmp_buf, 1);
1437 } else {
1438 /* XXX: eliminate this someday */
1439 exit(1);
1443 void expect(const char *msg)
1445 error("%s expected", msg);
1448 void warning(const char *fmt, ...)
1450 TCCState *s1 = tcc_state;
1451 va_list ap;
1453 if (s1->warn_none)
1454 return;
1456 va_start(ap, fmt);
1457 error1(s1, 1, fmt, ap);
1458 va_end(ap);
1461 void skip(int c)
1463 if (tok != c)
1464 error("'%c' expected", c);
1465 next();
1468 static void test_lvalue(void)
1470 if (!(vtop->r & VT_LVAL))
1471 expect("lvalue");
1474 /* allocate a new token */
1475 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1477 TokenSym *ts, **ptable;
1478 int i;
1480 if (tok_ident >= SYM_FIRST_ANOM)
1481 error("memory full");
1483 /* expand token table if needed */
1484 i = tok_ident - TOK_IDENT;
1485 if ((i % TOK_ALLOC_INCR) == 0) {
1486 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1487 if (!ptable)
1488 error("memory full");
1489 table_ident = ptable;
1492 ts = tcc_malloc(sizeof(TokenSym) + len);
1493 table_ident[i] = ts;
1494 ts->tok = tok_ident++;
1495 ts->sym_define = NULL;
1496 ts->sym_label = NULL;
1497 ts->sym_struct = NULL;
1498 ts->sym_identifier = NULL;
1499 ts->len = len;
1500 ts->hash_next = NULL;
1501 memcpy(ts->str, str, len);
1502 ts->str[len] = '\0';
1503 *pts = ts;
1504 return ts;
1507 #define TOK_HASH_INIT 1
1508 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1510 /* find a token and add it if not found */
1511 static TokenSym *tok_alloc(const char *str, int len)
1513 TokenSym *ts, **pts;
1514 int i;
1515 unsigned int h;
1517 h = TOK_HASH_INIT;
1518 for(i=0;i<len;i++)
1519 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1520 h &= (TOK_HASH_SIZE - 1);
1522 pts = &hash_ident[h];
1523 for(;;) {
1524 ts = *pts;
1525 if (!ts)
1526 break;
1527 if (ts->len == len && !memcmp(ts->str, str, len))
1528 return ts;
1529 pts = &(ts->hash_next);
1531 return tok_alloc_new(pts, str, len);
1534 /* CString handling */
1536 static void cstr_realloc(CString *cstr, int new_size)
1538 int size;
1539 void *data;
1541 size = cstr->size_allocated;
1542 if (size == 0)
1543 size = 8; /* no need to allocate a too small first string */
1544 while (size < new_size)
1545 size = size * 2;
1546 data = tcc_realloc(cstr->data_allocated, size);
1547 if (!data)
1548 error("memory full");
1549 cstr->data_allocated = data;
1550 cstr->size_allocated = size;
1551 cstr->data = data;
1554 /* add a byte */
1555 static inline void cstr_ccat(CString *cstr, int ch)
1557 int size;
1558 size = cstr->size + 1;
1559 if (size > cstr->size_allocated)
1560 cstr_realloc(cstr, size);
1561 ((unsigned char *)cstr->data)[size - 1] = ch;
1562 cstr->size = size;
1565 static void cstr_cat(CString *cstr, const char *str)
1567 int c;
1568 for(;;) {
1569 c = *str;
1570 if (c == '\0')
1571 break;
1572 cstr_ccat(cstr, c);
1573 str++;
1577 /* add a wide char */
1578 static void cstr_wccat(CString *cstr, int ch)
1580 int size;
1581 size = cstr->size + sizeof(nwchar_t);
1582 if (size > cstr->size_allocated)
1583 cstr_realloc(cstr, size);
1584 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1585 cstr->size = size;
1588 static void cstr_new(CString *cstr)
1590 memset(cstr, 0, sizeof(CString));
1593 /* free string and reset it to NULL */
1594 static void cstr_free(CString *cstr)
1596 tcc_free(cstr->data_allocated);
1597 cstr_new(cstr);
1600 #define cstr_reset(cstr) cstr_free(cstr)
1602 /* XXX: unicode ? */
1603 static void add_char(CString *cstr, int c)
1605 if (c == '\'' || c == '\"' || c == '\\') {
1606 /* XXX: could be more precise if char or string */
1607 cstr_ccat(cstr, '\\');
1609 if (c >= 32 && c <= 126) {
1610 cstr_ccat(cstr, c);
1611 } else {
1612 cstr_ccat(cstr, '\\');
1613 if (c == '\n') {
1614 cstr_ccat(cstr, 'n');
1615 } else {
1616 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1617 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1618 cstr_ccat(cstr, '0' + (c & 7));
1623 /* XXX: buffer overflow */
1624 /* XXX: float tokens */
1625 char *get_tok_str(int v, CValue *cv)
1627 static char buf[STRING_MAX_SIZE + 1];
1628 static CString cstr_buf;
1629 CString *cstr;
1630 unsigned char *q;
1631 char *p;
1632 int i, len;
1634 /* NOTE: to go faster, we give a fixed buffer for small strings */
1635 cstr_reset(&cstr_buf);
1636 cstr_buf.data = buf;
1637 cstr_buf.size_allocated = sizeof(buf);
1638 p = buf;
1640 switch(v) {
1641 case TOK_CINT:
1642 case TOK_CUINT:
1643 /* XXX: not quite exact, but only useful for testing */
1644 sprintf(p, "%u", cv->ui);
1645 break;
1646 case TOK_CLLONG:
1647 case TOK_CULLONG:
1648 /* XXX: not quite exact, but only useful for testing */
1649 sprintf(p, "%Lu", cv->ull);
1650 break;
1651 case TOK_CCHAR:
1652 case TOK_LCHAR:
1653 cstr_ccat(&cstr_buf, '\'');
1654 add_char(&cstr_buf, cv->i);
1655 cstr_ccat(&cstr_buf, '\'');
1656 cstr_ccat(&cstr_buf, '\0');
1657 break;
1658 case TOK_PPNUM:
1659 cstr = cv->cstr;
1660 len = cstr->size - 1;
1661 for(i=0;i<len;i++)
1662 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1663 cstr_ccat(&cstr_buf, '\0');
1664 break;
1665 case TOK_STR:
1666 case TOK_LSTR:
1667 cstr = cv->cstr;
1668 cstr_ccat(&cstr_buf, '\"');
1669 if (v == TOK_STR) {
1670 len = cstr->size - 1;
1671 for(i=0;i<len;i++)
1672 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1673 } else {
1674 len = (cstr->size / sizeof(nwchar_t)) - 1;
1675 for(i=0;i<len;i++)
1676 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1678 cstr_ccat(&cstr_buf, '\"');
1679 cstr_ccat(&cstr_buf, '\0');
1680 break;
1681 case TOK_LT:
1682 v = '<';
1683 goto addv;
1684 case TOK_GT:
1685 v = '>';
1686 goto addv;
1687 case TOK_DOTS:
1688 return strcpy(p, "...");
1689 case TOK_A_SHL:
1690 return strcpy(p, "<<=");
1691 case TOK_A_SAR:
1692 return strcpy(p, ">>=");
1693 default:
1694 if (v < TOK_IDENT) {
1695 /* search in two bytes table */
1696 q = tok_two_chars;
1697 while (*q) {
1698 if (q[2] == v) {
1699 *p++ = q[0];
1700 *p++ = q[1];
1701 *p = '\0';
1702 return buf;
1704 q += 3;
1706 addv:
1707 *p++ = v;
1708 *p = '\0';
1709 } else if (v < tok_ident) {
1710 return table_ident[v - TOK_IDENT]->str;
1711 } else if (v >= SYM_FIRST_ANOM) {
1712 /* special name for anonymous symbol */
1713 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1714 } else {
1715 /* should never happen */
1716 return NULL;
1718 break;
1720 return cstr_buf.data;
1723 /* push, without hashing */
1724 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1726 Sym *s;
1727 s = sym_malloc();
1728 s->v = v;
1729 s->type.t = t;
1730 s->c = c;
1731 s->next = NULL;
1732 /* add in stack */
1733 s->prev = *ps;
1734 *ps = s;
1735 return s;
1738 /* find a symbol and return its associated structure. 's' is the top
1739 of the symbol stack */
1740 static Sym *sym_find2(Sym *s, int v)
1742 while (s) {
1743 if (s->v == v)
1744 return s;
1745 s = s->prev;
1747 return NULL;
1750 /* structure lookup */
1751 static inline Sym *struct_find(int v)
1753 v -= TOK_IDENT;
1754 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1755 return NULL;
1756 return table_ident[v]->sym_struct;
1759 /* find an identifier */
1760 static inline Sym *sym_find(int v)
1762 v -= TOK_IDENT;
1763 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1764 return NULL;
1765 return table_ident[v]->sym_identifier;
1768 /* push a given symbol on the symbol stack */
1769 static Sym *sym_push(int v, CType *type, int r, int c)
1771 Sym *s, **ps;
1772 TokenSym *ts;
1774 if (local_stack)
1775 ps = &local_stack;
1776 else
1777 ps = &global_stack;
1778 s = sym_push2(ps, v, type->t, c);
1779 s->type.ref = type->ref;
1780 s->r = r;
1781 /* don't record fields or anonymous symbols */
1782 /* XXX: simplify */
1783 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1784 /* record symbol in token array */
1785 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1786 if (v & SYM_STRUCT)
1787 ps = &ts->sym_struct;
1788 else
1789 ps = &ts->sym_identifier;
1790 s->prev_tok = *ps;
1791 *ps = s;
1793 return s;
1796 /* push a global identifier */
1797 static Sym *global_identifier_push(int v, int t, int c)
1799 Sym *s, **ps;
1800 s = sym_push2(&global_stack, v, t, c);
1801 /* don't record anonymous symbol */
1802 if (v < SYM_FIRST_ANOM) {
1803 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1804 /* modify the top most local identifier, so that
1805 sym_identifier will point to 's' when popped */
1806 while (*ps != NULL)
1807 ps = &(*ps)->prev_tok;
1808 s->prev_tok = NULL;
1809 *ps = s;
1811 return s;
1814 /* pop symbols until top reaches 'b' */
1815 static void sym_pop(Sym **ptop, Sym *b)
1817 Sym *s, *ss, **ps;
1818 TokenSym *ts;
1819 int v;
1821 s = *ptop;
1822 while(s != b) {
1823 ss = s->prev;
1824 v = s->v;
1825 /* remove symbol in token array */
1826 /* XXX: simplify */
1827 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1828 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1829 if (v & SYM_STRUCT)
1830 ps = &ts->sym_struct;
1831 else
1832 ps = &ts->sym_identifier;
1833 *ps = s->prev_tok;
1835 sym_free(s);
1836 s = ss;
1838 *ptop = b;
1841 /* I/O layer */
1843 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1845 int fd;
1846 BufferedFile *bf;
1847 int i, len;
1849 fd = open(filename, O_RDONLY | O_BINARY);
1850 if (fd < 0)
1851 return NULL;
1852 bf = tcc_malloc(sizeof(BufferedFile));
1853 if (!bf) {
1854 close(fd);
1855 return NULL;
1857 bf->fd = fd;
1858 bf->buf_ptr = bf->buffer;
1859 bf->buf_end = bf->buffer;
1860 bf->buffer[0] = CH_EOB; /* put eob symbol */
1861 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1862 len = strlen(bf->filename);
1863 for (i = 0; i < len; i++)
1864 if (bf->filename[i] == '\\')
1865 bf->filename[i] = '/';
1866 bf->line_num = 1;
1867 bf->ifndef_macro = 0;
1868 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1869 // printf("opening '%s'\n", filename);
1870 return bf;
1873 void tcc_close(BufferedFile *bf)
1875 total_lines += bf->line_num;
1876 close(bf->fd);
1877 tcc_free(bf);
1880 /* fill input buffer and peek next char */
1881 static int tcc_peekc_slow(BufferedFile *bf)
1883 int len;
1884 /* only tries to read if really end of buffer */
1885 if (bf->buf_ptr >= bf->buf_end) {
1886 if (bf->fd != -1) {
1887 #if defined(PARSE_DEBUG)
1888 len = 8;
1889 #else
1890 len = IO_BUF_SIZE;
1891 #endif
1892 len = read(bf->fd, bf->buffer, len);
1893 if (len < 0)
1894 len = 0;
1895 } else {
1896 len = 0;
1898 total_bytes += len;
1899 bf->buf_ptr = bf->buffer;
1900 bf->buf_end = bf->buffer + len;
1901 *bf->buf_end = CH_EOB;
1903 if (bf->buf_ptr < bf->buf_end) {
1904 return bf->buf_ptr[0];
1905 } else {
1906 bf->buf_ptr = bf->buf_end;
1907 return CH_EOF;
1911 /* return the current character, handling end of block if necessary
1912 (but not stray) */
1913 static int handle_eob(void)
1915 return tcc_peekc_slow(file);
1918 /* read next char from current input file and handle end of input buffer */
1919 static inline void inp(void)
1921 ch = *(++(file->buf_ptr));
1922 /* end of buffer/file handling */
1923 if (ch == CH_EOB)
1924 ch = handle_eob();
1927 /* handle '\[\r]\n' */
1928 static void handle_stray(void)
1930 while (ch == '\\') {
1931 inp();
1932 if (ch == '\n') {
1933 file->line_num++;
1934 inp();
1935 } else if (ch == '\r') {
1936 inp();
1937 if (ch != '\n')
1938 goto fail;
1939 file->line_num++;
1940 inp();
1941 } else {
1942 fail:
1943 error("stray '\\' in program");
1948 /* skip the stray and handle the \\n case. Output an error if
1949 incorrect char after the stray */
1950 static int handle_stray1(uint8_t *p)
1952 int c;
1954 if (p >= file->buf_end) {
1955 file->buf_ptr = p;
1956 c = handle_eob();
1957 p = file->buf_ptr;
1958 if (c == '\\')
1959 goto parse_stray;
1960 } else {
1961 parse_stray:
1962 file->buf_ptr = p;
1963 ch = *p;
1964 handle_stray();
1965 p = file->buf_ptr;
1966 c = *p;
1968 return c;
1971 /* handle just the EOB case, but not stray */
1972 #define PEEKC_EOB(c, p)\
1974 p++;\
1975 c = *p;\
1976 if (c == '\\') {\
1977 file->buf_ptr = p;\
1978 c = handle_eob();\
1979 p = file->buf_ptr;\
1983 /* handle the complicated stray case */
1984 #define PEEKC(c, p)\
1986 p++;\
1987 c = *p;\
1988 if (c == '\\') {\
1989 c = handle_stray1(p);\
1990 p = file->buf_ptr;\
1994 /* input with '\[\r]\n' handling. Note that this function cannot
1995 handle other characters after '\', so you cannot call it inside
1996 strings or comments */
1997 static void minp(void)
1999 inp();
2000 if (ch == '\\')
2001 handle_stray();
2005 /* single line C++ comments */
2006 static uint8_t *parse_line_comment(uint8_t *p)
2008 int c;
2010 p++;
2011 for(;;) {
2012 c = *p;
2013 redo:
2014 if (c == '\n' || c == CH_EOF) {
2015 break;
2016 } else if (c == '\\') {
2017 file->buf_ptr = p;
2018 c = handle_eob();
2019 p = file->buf_ptr;
2020 if (c == '\\') {
2021 PEEKC_EOB(c, p);
2022 if (c == '\n') {
2023 file->line_num++;
2024 PEEKC_EOB(c, p);
2025 } else if (c == '\r') {
2026 PEEKC_EOB(c, p);
2027 if (c == '\n') {
2028 file->line_num++;
2029 PEEKC_EOB(c, p);
2032 } else {
2033 goto redo;
2035 } else {
2036 p++;
2039 return p;
2042 /* C comments */
2043 static uint8_t *parse_comment(uint8_t *p)
2045 int c;
2047 p++;
2048 for(;;) {
2049 /* fast skip loop */
2050 for(;;) {
2051 c = *p;
2052 if (c == '\n' || c == '*' || c == '\\')
2053 break;
2054 p++;
2055 c = *p;
2056 if (c == '\n' || c == '*' || c == '\\')
2057 break;
2058 p++;
2060 /* now we can handle all the cases */
2061 if (c == '\n') {
2062 file->line_num++;
2063 p++;
2064 } else if (c == '*') {
2065 p++;
2066 for(;;) {
2067 c = *p;
2068 if (c == '*') {
2069 p++;
2070 } else if (c == '/') {
2071 goto end_of_comment;
2072 } else if (c == '\\') {
2073 file->buf_ptr = p;
2074 c = handle_eob();
2075 p = file->buf_ptr;
2076 if (c == '\\') {
2077 /* skip '\[\r]\n', otherwise just skip the stray */
2078 while (c == '\\') {
2079 PEEKC_EOB(c, p);
2080 if (c == '\n') {
2081 file->line_num++;
2082 PEEKC_EOB(c, p);
2083 } else if (c == '\r') {
2084 PEEKC_EOB(c, p);
2085 if (c == '\n') {
2086 file->line_num++;
2087 PEEKC_EOB(c, p);
2089 } else {
2090 goto after_star;
2094 } else {
2095 break;
2098 after_star: ;
2099 } else {
2100 /* stray, eob or eof */
2101 file->buf_ptr = p;
2102 c = handle_eob();
2103 p = file->buf_ptr;
2104 if (c == CH_EOF) {
2105 error("unexpected end of file in comment");
2106 } else if (c == '\\') {
2107 p++;
2111 end_of_comment:
2112 p++;
2113 return p;
2116 #define cinp minp
2118 /* space exlcuding newline */
2119 static inline int is_space(int ch)
2121 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2124 static inline void skip_spaces(void)
2126 while (is_space(ch))
2127 cinp();
2130 /* parse a string without interpreting escapes */
2131 static uint8_t *parse_pp_string(uint8_t *p,
2132 int sep, CString *str)
2134 int c;
2135 p++;
2136 for(;;) {
2137 c = *p;
2138 if (c == sep) {
2139 break;
2140 } else if (c == '\\') {
2141 file->buf_ptr = p;
2142 c = handle_eob();
2143 p = file->buf_ptr;
2144 if (c == CH_EOF) {
2145 unterminated_string:
2146 /* XXX: indicate line number of start of string */
2147 error("missing terminating %c character", sep);
2148 } else if (c == '\\') {
2149 /* escape : just skip \[\r]\n */
2150 PEEKC_EOB(c, p);
2151 if (c == '\n') {
2152 file->line_num++;
2153 p++;
2154 } else if (c == '\r') {
2155 PEEKC_EOB(c, p);
2156 if (c != '\n')
2157 expect("'\n' after '\r'");
2158 file->line_num++;
2159 p++;
2160 } else if (c == CH_EOF) {
2161 goto unterminated_string;
2162 } else {
2163 if (str) {
2164 cstr_ccat(str, '\\');
2165 cstr_ccat(str, c);
2167 p++;
2170 } else if (c == '\n') {
2171 file->line_num++;
2172 goto add_char;
2173 } else if (c == '\r') {
2174 PEEKC_EOB(c, p);
2175 if (c != '\n') {
2176 if (str)
2177 cstr_ccat(str, '\r');
2178 } else {
2179 file->line_num++;
2180 goto add_char;
2182 } else {
2183 add_char:
2184 if (str)
2185 cstr_ccat(str, c);
2186 p++;
2189 p++;
2190 return p;
2193 /* skip block of text until #else, #elif or #endif. skip also pairs of
2194 #if/#endif */
2195 void preprocess_skip(void)
2197 int a, start_of_line, c;
2198 uint8_t *p;
2200 p = file->buf_ptr;
2201 start_of_line = 1;
2202 a = 0;
2203 for(;;) {
2204 redo_no_start:
2205 c = *p;
2206 switch(c) {
2207 case ' ':
2208 case '\t':
2209 case '\f':
2210 case '\v':
2211 case '\r':
2212 p++;
2213 goto redo_no_start;
2214 case '\n':
2215 start_of_line = 1;
2216 file->line_num++;
2217 p++;
2218 goto redo_no_start;
2219 case '\\':
2220 file->buf_ptr = p;
2221 c = handle_eob();
2222 if (c == CH_EOF) {
2223 expect("#endif");
2224 } else if (c == '\\') {
2225 /* XXX: incorrect: should not give an error */
2226 ch = file->buf_ptr[0];
2227 handle_stray();
2229 p = file->buf_ptr;
2230 goto redo_no_start;
2231 /* skip strings */
2232 case '\"':
2233 case '\'':
2234 p = parse_pp_string(p, c, NULL);
2235 break;
2236 /* skip comments */
2237 case '/':
2238 file->buf_ptr = p;
2239 ch = *p;
2240 minp();
2241 p = file->buf_ptr;
2242 if (ch == '*') {
2243 p = parse_comment(p);
2244 } else if (ch == '/') {
2245 p = parse_line_comment(p);
2247 break;
2249 case '#':
2250 p++;
2251 if (start_of_line) {
2252 file->buf_ptr = p;
2253 next_nomacro();
2254 p = file->buf_ptr;
2255 if (a == 0 &&
2256 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2257 goto the_end;
2258 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2259 a++;
2260 else if (tok == TOK_ENDIF)
2261 a--;
2263 break;
2264 default:
2265 p++;
2266 break;
2268 start_of_line = 0;
2270 the_end: ;
2271 file->buf_ptr = p;
2274 /* ParseState handling */
2276 /* XXX: currently, no include file info is stored. Thus, we cannot display
2277 accurate messages if the function or data definition spans multiple
2278 files */
2280 /* save current parse state in 's' */
2281 void save_parse_state(ParseState *s)
2283 s->line_num = file->line_num;
2284 s->macro_ptr = macro_ptr;
2285 s->tok = tok;
2286 s->tokc = tokc;
2289 /* restore parse state from 's' */
2290 void restore_parse_state(ParseState *s)
2292 file->line_num = s->line_num;
2293 macro_ptr = s->macro_ptr;
2294 tok = s->tok;
2295 tokc = s->tokc;
2298 /* return the number of additional 'ints' necessary to store the
2299 token */
2300 static inline int tok_ext_size(int t)
2302 switch(t) {
2303 /* 4 bytes */
2304 case TOK_CINT:
2305 case TOK_CUINT:
2306 case TOK_CCHAR:
2307 case TOK_LCHAR:
2308 case TOK_CFLOAT:
2309 case TOK_LINENUM:
2310 return 1;
2311 case TOK_STR:
2312 case TOK_LSTR:
2313 case TOK_PPNUM:
2314 error("unsupported token");
2315 return 1;
2316 case TOK_CDOUBLE:
2317 case TOK_CLLONG:
2318 case TOK_CULLONG:
2319 return 2;
2320 case TOK_CLDOUBLE:
2321 return LDOUBLE_SIZE / 4;
2322 default:
2323 return 0;
2327 /* token string handling */
2329 static inline void tok_str_new(TokenString *s)
2331 s->str = NULL;
2332 s->len = 0;
2333 s->allocated_len = 0;
2334 s->last_line_num = -1;
2337 static void tok_str_free(int *str)
2339 tcc_free(str);
2342 static int *tok_str_realloc(TokenString *s)
2344 int *str, len;
2346 if (s->allocated_len == 0) {
2347 len = 8;
2348 } else {
2349 len = s->allocated_len * 2;
2351 str = tcc_realloc(s->str, len * sizeof(int));
2352 if (!str)
2353 error("memory full");
2354 s->allocated_len = len;
2355 s->str = str;
2356 return str;
2359 static void tok_str_add(TokenString *s, int t)
2361 int len, *str;
2363 len = s->len;
2364 str = s->str;
2365 if (len >= s->allocated_len)
2366 str = tok_str_realloc(s);
2367 str[len++] = t;
2368 s->len = len;
2371 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2373 int len, *str;
2375 len = s->len;
2376 str = s->str;
2378 /* allocate space for worst case */
2379 if (len + TOK_MAX_SIZE > s->allocated_len)
2380 str = tok_str_realloc(s);
2381 str[len++] = t;
2382 switch(t) {
2383 case TOK_CINT:
2384 case TOK_CUINT:
2385 case TOK_CCHAR:
2386 case TOK_LCHAR:
2387 case TOK_CFLOAT:
2388 case TOK_LINENUM:
2389 str[len++] = cv->tab[0];
2390 break;
2391 case TOK_PPNUM:
2392 case TOK_STR:
2393 case TOK_LSTR:
2395 int nb_words;
2396 CString *cstr;
2398 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2399 while ((len + nb_words) > s->allocated_len)
2400 str = tok_str_realloc(s);
2401 cstr = (CString *)(str + len);
2402 cstr->data = NULL;
2403 cstr->size = cv->cstr->size;
2404 cstr->data_allocated = NULL;
2405 cstr->size_allocated = cstr->size;
2406 memcpy((char *)cstr + sizeof(CString),
2407 cv->cstr->data, cstr->size);
2408 len += nb_words;
2410 break;
2411 case TOK_CDOUBLE:
2412 case TOK_CLLONG:
2413 case TOK_CULLONG:
2414 #if LDOUBLE_SIZE == 8
2415 case TOK_CLDOUBLE:
2416 #endif
2417 str[len++] = cv->tab[0];
2418 str[len++] = cv->tab[1];
2419 break;
2420 #if LDOUBLE_SIZE == 12
2421 case TOK_CLDOUBLE:
2422 str[len++] = cv->tab[0];
2423 str[len++] = cv->tab[1];
2424 str[len++] = cv->tab[2];
2425 #elif LDOUBLE_SIZE != 8
2426 #error add long double size support
2427 #endif
2428 break;
2429 default:
2430 break;
2432 s->len = len;
2435 /* add the current parse token in token string 's' */
2436 static void tok_str_add_tok(TokenString *s)
2438 CValue cval;
2440 /* save line number info */
2441 if (file->line_num != s->last_line_num) {
2442 s->last_line_num = file->line_num;
2443 cval.i = s->last_line_num;
2444 tok_str_add2(s, TOK_LINENUM, &cval);
2446 tok_str_add2(s, tok, &tokc);
2449 #if LDOUBLE_SIZE == 12
2450 #define LDOUBLE_GET(p, cv) \
2451 cv.tab[0] = p[0]; \
2452 cv.tab[1] = p[1]; \
2453 cv.tab[2] = p[2];
2454 #elif LDOUBLE_SIZE == 8
2455 #define LDOUBLE_GET(p, cv) \
2456 cv.tab[0] = p[0]; \
2457 cv.tab[1] = p[1];
2458 #else
2459 #error add long double size support
2460 #endif
2463 /* get a token from an integer array and increment pointer
2464 accordingly. we code it as a macro to avoid pointer aliasing. */
2465 #define TOK_GET(t, p, cv) \
2467 t = *p++; \
2468 switch(t) { \
2469 case TOK_CINT: \
2470 case TOK_CUINT: \
2471 case TOK_CCHAR: \
2472 case TOK_LCHAR: \
2473 case TOK_CFLOAT: \
2474 case TOK_LINENUM: \
2475 cv.tab[0] = *p++; \
2476 break; \
2477 case TOK_STR: \
2478 case TOK_LSTR: \
2479 case TOK_PPNUM: \
2480 cv.cstr = (CString *)p; \
2481 cv.cstr->data = (char *)p + sizeof(CString);\
2482 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2483 break; \
2484 case TOK_CDOUBLE: \
2485 case TOK_CLLONG: \
2486 case TOK_CULLONG: \
2487 cv.tab[0] = p[0]; \
2488 cv.tab[1] = p[1]; \
2489 p += 2; \
2490 break; \
2491 case TOK_CLDOUBLE: \
2492 LDOUBLE_GET(p, cv); \
2493 p += LDOUBLE_SIZE / 4; \
2494 break; \
2495 default: \
2496 break; \
2500 /* defines handling */
2501 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2503 Sym *s;
2505 s = sym_push2(&define_stack, v, macro_type, (int)str);
2506 s->next = first_arg;
2507 table_ident[v - TOK_IDENT]->sym_define = s;
2510 /* undefined a define symbol. Its name is just set to zero */
2511 static void define_undef(Sym *s)
2513 int v;
2514 v = s->v;
2515 if (v >= TOK_IDENT && v < tok_ident)
2516 table_ident[v - TOK_IDENT]->sym_define = NULL;
2517 s->v = 0;
2520 static inline Sym *define_find(int v)
2522 v -= TOK_IDENT;
2523 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2524 return NULL;
2525 return table_ident[v]->sym_define;
2528 /* free define stack until top reaches 'b' */
2529 static void free_defines(Sym *b)
2531 Sym *top, *top1;
2532 int v;
2534 top = define_stack;
2535 while (top != b) {
2536 top1 = top->prev;
2537 /* do not free args or predefined defines */
2538 if (top->c)
2539 tok_str_free((int *)top->c);
2540 v = top->v;
2541 if (v >= TOK_IDENT && v < tok_ident)
2542 table_ident[v - TOK_IDENT]->sym_define = NULL;
2543 sym_free(top);
2544 top = top1;
2546 define_stack = b;
2549 /* label lookup */
2550 static Sym *label_find(int v)
2552 v -= TOK_IDENT;
2553 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2554 return NULL;
2555 return table_ident[v]->sym_label;
2558 static Sym *label_push(Sym **ptop, int v, int flags)
2560 Sym *s, **ps;
2561 s = sym_push2(ptop, v, 0, 0);
2562 s->r = flags;
2563 ps = &table_ident[v - TOK_IDENT]->sym_label;
2564 if (ptop == &global_label_stack) {
2565 /* modify the top most local identifier, so that
2566 sym_identifier will point to 's' when popped */
2567 while (*ps != NULL)
2568 ps = &(*ps)->prev_tok;
2570 s->prev_tok = *ps;
2571 *ps = s;
2572 return s;
2575 /* pop labels until element last is reached. Look if any labels are
2576 undefined. Define symbols if '&&label' was used. */
2577 static void label_pop(Sym **ptop, Sym *slast)
2579 Sym *s, *s1;
2580 for(s = *ptop; s != slast; s = s1) {
2581 s1 = s->prev;
2582 if (s->r == LABEL_DECLARED) {
2583 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2584 } else if (s->r == LABEL_FORWARD) {
2585 error("label '%s' used but not defined",
2586 get_tok_str(s->v, NULL));
2587 } else {
2588 if (s->c) {
2589 /* define corresponding symbol. A size of
2590 1 is put. */
2591 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2594 /* remove label */
2595 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2596 sym_free(s);
2598 *ptop = slast;
2601 /* eval an expression for #if/#elif */
2602 static int expr_preprocess(void)
2604 int c, t;
2605 TokenString str;
2607 tok_str_new(&str);
2608 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2609 next(); /* do macro subst */
2610 if (tok == TOK_DEFINED) {
2611 next_nomacro();
2612 t = tok;
2613 if (t == '(')
2614 next_nomacro();
2615 c = define_find(tok) != 0;
2616 if (t == '(')
2617 next_nomacro();
2618 tok = TOK_CINT;
2619 tokc.i = c;
2620 } else if (tok >= TOK_IDENT) {
2621 /* if undefined macro */
2622 tok = TOK_CINT;
2623 tokc.i = 0;
2625 tok_str_add_tok(&str);
2627 tok_str_add(&str, -1); /* simulate end of file */
2628 tok_str_add(&str, 0);
2629 /* now evaluate C constant expression */
2630 macro_ptr = str.str;
2631 next();
2632 c = expr_const();
2633 macro_ptr = NULL;
2634 tok_str_free(str.str);
2635 return c != 0;
2638 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2639 static void tok_print(int *str)
2641 int t;
2642 CValue cval;
2644 while (1) {
2645 TOK_GET(t, str, cval);
2646 if (!t)
2647 break;
2648 printf(" %s", get_tok_str(t, &cval));
2650 printf("\n");
2652 #endif
2654 /* parse after #define */
2655 static void parse_define(void)
2657 Sym *s, *first, **ps;
2658 int v, t, varg, is_vaargs, c;
2659 TokenString str;
2661 v = tok;
2662 if (v < TOK_IDENT)
2663 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2664 /* XXX: should check if same macro (ANSI) */
2665 first = NULL;
2666 t = MACRO_OBJ;
2667 /* '(' must be just after macro definition for MACRO_FUNC */
2668 c = file->buf_ptr[0];
2669 if (c == '\\')
2670 c = handle_stray1(file->buf_ptr);
2671 if (c == '(') {
2672 next_nomacro();
2673 next_nomacro();
2674 ps = &first;
2675 while (tok != ')') {
2676 varg = tok;
2677 next_nomacro();
2678 is_vaargs = 0;
2679 if (varg == TOK_DOTS) {
2680 varg = TOK___VA_ARGS__;
2681 is_vaargs = 1;
2682 } else if (tok == TOK_DOTS && gnu_ext) {
2683 is_vaargs = 1;
2684 next_nomacro();
2686 if (varg < TOK_IDENT)
2687 error("badly punctuated parameter list");
2688 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2689 *ps = s;
2690 ps = &s->next;
2691 if (tok != ',')
2692 break;
2693 next_nomacro();
2695 t = MACRO_FUNC;
2697 tok_str_new(&str);
2698 next_nomacro();
2699 /* EOF testing necessary for '-D' handling */
2700 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2701 tok_str_add2(&str, tok, &tokc);
2702 next_nomacro();
2704 tok_str_add(&str, 0);
2705 #ifdef PP_DEBUG
2706 printf("define %s %d: ", get_tok_str(v, NULL), t);
2707 tok_print(str.str);
2708 #endif
2709 define_push(v, t, str.str, first);
2712 static inline int hash_cached_include(int type, const char *filename)
2714 const unsigned char *s;
2715 unsigned int h;
2717 h = TOK_HASH_INIT;
2718 h = TOK_HASH_FUNC(h, type);
2719 s = filename;
2720 while (*s) {
2721 h = TOK_HASH_FUNC(h, *s);
2722 s++;
2724 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2725 return h;
2728 /* XXX: use a token or a hash table to accelerate matching ? */
2729 static CachedInclude *search_cached_include(TCCState *s1,
2730 int type, const char *filename)
2732 CachedInclude *e;
2733 int i, h;
2734 h = hash_cached_include(type, filename);
2735 i = s1->cached_includes_hash[h];
2736 for(;;) {
2737 if (i == 0)
2738 break;
2739 e = s1->cached_includes[i - 1];
2740 if (e->type == type && !strcmp(e->filename, filename))
2741 return e;
2742 i = e->hash_next;
2744 return NULL;
2747 static inline void add_cached_include(TCCState *s1, int type,
2748 const char *filename, int ifndef_macro)
2750 CachedInclude *e;
2751 int h;
2753 if (search_cached_include(s1, type, filename))
2754 return;
2755 #ifdef INC_DEBUG
2756 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2757 #endif
2758 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2759 if (!e)
2760 return;
2761 e->type = type;
2762 strcpy(e->filename, filename);
2763 e->ifndef_macro = ifndef_macro;
2764 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2765 /* add in hash table */
2766 h = hash_cached_include(type, filename);
2767 e->hash_next = s1->cached_includes_hash[h];
2768 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2771 static void pragma_parse(TCCState *s1)
2773 int val;
2775 next();
2776 if (tok == TOK_pack) {
2778 This may be:
2779 #pragma pack(1) // set
2780 #pragma pack() // reset to default
2781 #pragma pack(push,1) // push & set
2782 #pragma pack(pop) // restore previous
2784 next();
2785 skip('(');
2786 if (tok == TOK_ASM_pop) {
2787 next();
2788 if (s1->pack_stack_ptr <= s1->pack_stack) {
2789 stk_error:
2790 error("out of pack stack");
2792 s1->pack_stack_ptr--;
2793 } else {
2794 val = 0;
2795 if (tok != ')') {
2796 if (tok == TOK_ASM_push) {
2797 next();
2798 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2799 goto stk_error;
2800 s1->pack_stack_ptr++;
2801 skip(',');
2803 if (tok != TOK_CINT) {
2804 pack_error:
2805 error("invalid pack pragma");
2807 val = tokc.i;
2808 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2809 goto pack_error;
2810 next();
2812 *s1->pack_stack_ptr = val;
2813 skip(')');
2818 /* is_bof is true if first non space token at beginning of file */
2819 static void preprocess(int is_bof)
2821 TCCState *s1 = tcc_state;
2822 int size, i, c, n, saved_parse_flags;
2823 char buf[1024], *q, *p;
2824 char buf1[1024];
2825 BufferedFile *f;
2826 Sym *s;
2827 CachedInclude *e;
2829 saved_parse_flags = parse_flags;
2830 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2831 PARSE_FLAG_LINEFEED;
2832 next_nomacro();
2833 redo:
2834 switch(tok) {
2835 case TOK_DEFINE:
2836 next_nomacro();
2837 parse_define();
2838 break;
2839 case TOK_UNDEF:
2840 next_nomacro();
2841 s = define_find(tok);
2842 /* undefine symbol by putting an invalid name */
2843 if (s)
2844 define_undef(s);
2845 break;
2846 case TOK_INCLUDE:
2847 case TOK_INCLUDE_NEXT:
2848 ch = file->buf_ptr[0];
2849 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2850 skip_spaces();
2851 if (ch == '<') {
2852 c = '>';
2853 goto read_name;
2854 } else if (ch == '\"') {
2855 c = ch;
2856 read_name:
2857 /* XXX: better stray handling */
2858 minp();
2859 q = buf;
2860 while (ch != c && ch != '\n' && ch != CH_EOF) {
2861 if ((q - buf) < sizeof(buf) - 1)
2862 *q++ = ch;
2863 minp();
2865 *q = '\0';
2866 minp();
2867 #if 0
2868 /* eat all spaces and comments after include */
2869 /* XXX: slightly incorrect */
2870 while (ch1 != '\n' && ch1 != CH_EOF)
2871 inp();
2872 #endif
2873 } else {
2874 /* computed #include : either we have only strings or
2875 we have anything enclosed in '<>' */
2876 next();
2877 buf[0] = '\0';
2878 if (tok == TOK_STR) {
2879 while (tok != TOK_LINEFEED) {
2880 if (tok != TOK_STR) {
2881 include_syntax:
2882 error("'#include' expects \"FILENAME\" or <FILENAME>");
2884 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2885 next();
2887 c = '\"';
2888 } else {
2889 int len;
2890 while (tok != TOK_LINEFEED) {
2891 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2892 next();
2894 len = strlen(buf);
2895 /* check syntax and remove '<>' */
2896 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2897 goto include_syntax;
2898 memmove(buf, buf + 1, len - 2);
2899 buf[len - 2] = '\0';
2900 c = '>';
2904 e = search_cached_include(s1, c, buf);
2905 if (e && define_find(e->ifndef_macro)) {
2906 /* no need to parse the include because the 'ifndef macro'
2907 is defined */
2908 #ifdef INC_DEBUG
2909 printf("%s: skipping %s\n", file->filename, buf);
2910 #endif
2911 } else {
2912 if (c == '\"') {
2913 /* first search in current dir if "header.h" */
2914 size = 0;
2915 p = strrchr(file->filename, '/');
2916 if (p)
2917 size = p + 1 - file->filename;
2918 if (size > sizeof(buf1) - 1)
2919 size = sizeof(buf1) - 1;
2920 memcpy(buf1, file->filename, size);
2921 buf1[size] = '\0';
2922 pstrcat(buf1, sizeof(buf1), buf);
2923 f = tcc_open(s1, buf1);
2924 if (f) {
2925 if (tok == TOK_INCLUDE_NEXT)
2926 tok = TOK_INCLUDE;
2927 else
2928 goto found;
2931 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2932 error("#include recursion too deep");
2933 /* now search in all the include paths */
2934 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2935 for(i = 0; i < n; i++) {
2936 const char *path;
2937 if (i < s1->nb_include_paths)
2938 path = s1->include_paths[i];
2939 else
2940 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2941 pstrcpy(buf1, sizeof(buf1), path);
2942 pstrcat(buf1, sizeof(buf1), "/");
2943 pstrcat(buf1, sizeof(buf1), buf);
2944 f = tcc_open(s1, buf1);
2945 if (f) {
2946 if (tok == TOK_INCLUDE_NEXT)
2947 tok = TOK_INCLUDE;
2948 else
2949 goto found;
2952 error("include file '%s' not found", buf);
2953 f = NULL;
2954 found:
2955 #ifdef INC_DEBUG
2956 printf("%s: including %s\n", file->filename, buf1);
2957 #endif
2958 f->inc_type = c;
2959 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2960 /* push current file in stack */
2961 /* XXX: fix current line init */
2962 *s1->include_stack_ptr++ = file;
2963 file = f;
2964 /* add include file debug info */
2965 if (do_debug) {
2966 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2968 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2969 ch = file->buf_ptr[0];
2970 goto the_end;
2972 break;
2973 case TOK_IFNDEF:
2974 c = 1;
2975 goto do_ifdef;
2976 case TOK_IF:
2977 c = expr_preprocess();
2978 goto do_if;
2979 case TOK_IFDEF:
2980 c = 0;
2981 do_ifdef:
2982 next_nomacro();
2983 if (tok < TOK_IDENT)
2984 error("invalid argument for '#if%sdef'", c ? "n" : "");
2985 if (is_bof) {
2986 if (c) {
2987 #ifdef INC_DEBUG
2988 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2989 #endif
2990 file->ifndef_macro = tok;
2993 c = (define_find(tok) != 0) ^ c;
2994 do_if:
2995 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2996 error("memory full");
2997 *s1->ifdef_stack_ptr++ = c;
2998 goto test_skip;
2999 case TOK_ELSE:
3000 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3001 error("#else without matching #if");
3002 if (s1->ifdef_stack_ptr[-1] & 2)
3003 error("#else after #else");
3004 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3005 goto test_skip;
3006 case TOK_ELIF:
3007 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3008 error("#elif without matching #if");
3009 c = s1->ifdef_stack_ptr[-1];
3010 if (c > 1)
3011 error("#elif after #else");
3012 /* last #if/#elif expression was true: we skip */
3013 if (c == 1)
3014 goto skip;
3015 c = expr_preprocess();
3016 s1->ifdef_stack_ptr[-1] = c;
3017 test_skip:
3018 if (!(c & 1)) {
3019 skip:
3020 preprocess_skip();
3021 is_bof = 0;
3022 goto redo;
3024 break;
3025 case TOK_ENDIF:
3026 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3027 error("#endif without matching #if");
3028 s1->ifdef_stack_ptr--;
3029 /* '#ifndef macro' was at the start of file. Now we check if
3030 an '#endif' is exactly at the end of file */
3031 if (file->ifndef_macro &&
3032 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3033 file->ifndef_macro_saved = file->ifndef_macro;
3034 /* need to set to zero to avoid false matches if another
3035 #ifndef at middle of file */
3036 file->ifndef_macro = 0;
3037 while (tok != TOK_LINEFEED)
3038 next_nomacro();
3039 tok_flags |= TOK_FLAG_ENDIF;
3040 goto the_end;
3042 break;
3043 case TOK_LINE:
3044 next();
3045 if (tok != TOK_CINT)
3046 error("#line");
3047 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3048 next();
3049 if (tok != TOK_LINEFEED) {
3050 if (tok != TOK_STR)
3051 error("#line");
3052 pstrcpy(file->filename, sizeof(file->filename),
3053 (char *)tokc.cstr->data);
3055 break;
3056 case TOK_ERROR:
3057 case TOK_WARNING:
3058 c = tok;
3059 ch = file->buf_ptr[0];
3060 skip_spaces();
3061 q = buf;
3062 while (ch != '\n' && ch != CH_EOF) {
3063 if ((q - buf) < sizeof(buf) - 1)
3064 *q++ = ch;
3065 minp();
3067 *q = '\0';
3068 if (c == TOK_ERROR)
3069 error("#error %s", buf);
3070 else
3071 warning("#warning %s", buf);
3072 break;
3073 case TOK_PRAGMA:
3074 pragma_parse(s1);
3075 break;
3076 default:
3077 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3078 /* '!' is ignored to allow C scripts. numbers are ignored
3079 to emulate cpp behaviour */
3080 } else {
3081 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3082 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
3084 break;
3086 /* ignore other preprocess commands or #! for C scripts */
3087 while (tok != TOK_LINEFEED)
3088 next_nomacro();
3089 the_end:
3090 parse_flags = saved_parse_flags;
3093 /* evaluate escape codes in a string. */
3094 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3096 int c, n;
3097 const uint8_t *p;
3099 p = buf;
3100 for(;;) {
3101 c = *p;
3102 if (c == '\0')
3103 break;
3104 if (c == '\\') {
3105 p++;
3106 /* escape */
3107 c = *p;
3108 switch(c) {
3109 case '0': case '1': case '2': case '3':
3110 case '4': case '5': case '6': case '7':
3111 /* at most three octal digits */
3112 n = c - '0';
3113 p++;
3114 c = *p;
3115 if (isoct(c)) {
3116 n = n * 8 + c - '0';
3117 p++;
3118 c = *p;
3119 if (isoct(c)) {
3120 n = n * 8 + c - '0';
3121 p++;
3124 c = n;
3125 goto add_char_nonext;
3126 case 'x':
3127 case 'u':
3128 case 'U':
3129 p++;
3130 n = 0;
3131 for(;;) {
3132 c = *p;
3133 if (c >= 'a' && c <= 'f')
3134 c = c - 'a' + 10;
3135 else if (c >= 'A' && c <= 'F')
3136 c = c - 'A' + 10;
3137 else if (isnum(c))
3138 c = c - '0';
3139 else
3140 break;
3141 n = n * 16 + c;
3142 p++;
3144 c = n;
3145 goto add_char_nonext;
3146 case 'a':
3147 c = '\a';
3148 break;
3149 case 'b':
3150 c = '\b';
3151 break;
3152 case 'f':
3153 c = '\f';
3154 break;
3155 case 'n':
3156 c = '\n';
3157 break;
3158 case 'r':
3159 c = '\r';
3160 break;
3161 case 't':
3162 c = '\t';
3163 break;
3164 case 'v':
3165 c = '\v';
3166 break;
3167 case 'e':
3168 if (!gnu_ext)
3169 goto invalid_escape;
3170 c = 27;
3171 break;
3172 case '\'':
3173 case '\"':
3174 case '\\':
3175 case '?':
3176 break;
3177 default:
3178 invalid_escape:
3179 if (c >= '!' && c <= '~')
3180 warning("unknown escape sequence: \'\\%c\'", c);
3181 else
3182 warning("unknown escape sequence: \'\\x%x\'", c);
3183 break;
3186 p++;
3187 add_char_nonext:
3188 if (!is_long)
3189 cstr_ccat(outstr, c);
3190 else
3191 cstr_wccat(outstr, c);
3193 /* add a trailing '\0' */
3194 if (!is_long)
3195 cstr_ccat(outstr, '\0');
3196 else
3197 cstr_wccat(outstr, '\0');
3200 /* we use 64 bit numbers */
3201 #define BN_SIZE 2
3203 /* bn = (bn << shift) | or_val */
3204 void bn_lshift(unsigned int *bn, int shift, int or_val)
3206 int i;
3207 unsigned int v;
3208 for(i=0;i<BN_SIZE;i++) {
3209 v = bn[i];
3210 bn[i] = (v << shift) | or_val;
3211 or_val = v >> (32 - shift);
3215 void bn_zero(unsigned int *bn)
3217 int i;
3218 for(i=0;i<BN_SIZE;i++) {
3219 bn[i] = 0;
3223 /* parse number in null terminated string 'p' and return it in the
3224 current token */
3225 void parse_number(const char *p)
3227 int b, t, shift, frac_bits, s, exp_val, ch;
3228 char *q;
3229 unsigned int bn[BN_SIZE];
3230 double d;
3232 /* number */
3233 q = token_buf;
3234 ch = *p++;
3235 t = ch;
3236 ch = *p++;
3237 *q++ = t;
3238 b = 10;
3239 if (t == '.') {
3240 goto float_frac_parse;
3241 } else if (t == '0') {
3242 if (ch == 'x' || ch == 'X') {
3243 q--;
3244 ch = *p++;
3245 b = 16;
3246 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3247 q--;
3248 ch = *p++;
3249 b = 2;
3252 /* parse all digits. cannot check octal numbers at this stage
3253 because of floating point constants */
3254 while (1) {
3255 if (ch >= 'a' && ch <= 'f')
3256 t = ch - 'a' + 10;
3257 else if (ch >= 'A' && ch <= 'F')
3258 t = ch - 'A' + 10;
3259 else if (isnum(ch))
3260 t = ch - '0';
3261 else
3262 break;
3263 if (t >= b)
3264 break;
3265 if (q >= token_buf + STRING_MAX_SIZE) {
3266 num_too_long:
3267 error("number too long");
3269 *q++ = ch;
3270 ch = *p++;
3272 if (ch == '.' ||
3273 ((ch == 'e' || ch == 'E') && b == 10) ||
3274 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3275 if (b != 10) {
3276 /* NOTE: strtox should support that for hexa numbers, but
3277 non ISOC99 libcs do not support it, so we prefer to do
3278 it by hand */
3279 /* hexadecimal or binary floats */
3280 /* XXX: handle overflows */
3281 *q = '\0';
3282 if (b == 16)
3283 shift = 4;
3284 else
3285 shift = 2;
3286 bn_zero(bn);
3287 q = token_buf;
3288 while (1) {
3289 t = *q++;
3290 if (t == '\0') {
3291 break;
3292 } else if (t >= 'a') {
3293 t = t - 'a' + 10;
3294 } else if (t >= 'A') {
3295 t = t - 'A' + 10;
3296 } else {
3297 t = t - '0';
3299 bn_lshift(bn, shift, t);
3301 frac_bits = 0;
3302 if (ch == '.') {
3303 ch = *p++;
3304 while (1) {
3305 t = ch;
3306 if (t >= 'a' && t <= 'f') {
3307 t = t - 'a' + 10;
3308 } else if (t >= 'A' && t <= 'F') {
3309 t = t - 'A' + 10;
3310 } else if (t >= '0' && t <= '9') {
3311 t = t - '0';
3312 } else {
3313 break;
3315 if (t >= b)
3316 error("invalid digit");
3317 bn_lshift(bn, shift, t);
3318 frac_bits += shift;
3319 ch = *p++;
3322 if (ch != 'p' && ch != 'P')
3323 expect("exponent");
3324 ch = *p++;
3325 s = 1;
3326 exp_val = 0;
3327 if (ch == '+') {
3328 ch = *p++;
3329 } else if (ch == '-') {
3330 s = -1;
3331 ch = *p++;
3333 if (ch < '0' || ch > '9')
3334 expect("exponent digits");
3335 while (ch >= '0' && ch <= '9') {
3336 exp_val = exp_val * 10 + ch - '0';
3337 ch = *p++;
3339 exp_val = exp_val * s;
3341 /* now we can generate the number */
3342 /* XXX: should patch directly float number */
3343 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3344 d = ldexp(d, exp_val - frac_bits);
3345 t = toup(ch);
3346 if (t == 'F') {
3347 ch = *p++;
3348 tok = TOK_CFLOAT;
3349 /* float : should handle overflow */
3350 tokc.f = (float)d;
3351 } else if (t == 'L') {
3352 ch = *p++;
3353 tok = TOK_CLDOUBLE;
3354 /* XXX: not large enough */
3355 tokc.ld = (long double)d;
3356 } else {
3357 tok = TOK_CDOUBLE;
3358 tokc.d = d;
3360 } else {
3361 /* decimal floats */
3362 if (ch == '.') {
3363 if (q >= token_buf + STRING_MAX_SIZE)
3364 goto num_too_long;
3365 *q++ = ch;
3366 ch = *p++;
3367 float_frac_parse:
3368 while (ch >= '0' && ch <= '9') {
3369 if (q >= token_buf + STRING_MAX_SIZE)
3370 goto num_too_long;
3371 *q++ = ch;
3372 ch = *p++;
3375 if (ch == 'e' || ch == 'E') {
3376 if (q >= token_buf + STRING_MAX_SIZE)
3377 goto num_too_long;
3378 *q++ = ch;
3379 ch = *p++;
3380 if (ch == '-' || ch == '+') {
3381 if (q >= token_buf + STRING_MAX_SIZE)
3382 goto num_too_long;
3383 *q++ = ch;
3384 ch = *p++;
3386 if (ch < '0' || ch > '9')
3387 expect("exponent digits");
3388 while (ch >= '0' && ch <= '9') {
3389 if (q >= token_buf + STRING_MAX_SIZE)
3390 goto num_too_long;
3391 *q++ = ch;
3392 ch = *p++;
3395 *q = '\0';
3396 t = toup(ch);
3397 errno = 0;
3398 if (t == 'F') {
3399 ch = *p++;
3400 tok = TOK_CFLOAT;
3401 tokc.f = strtof(token_buf, NULL);
3402 } else if (t == 'L') {
3403 ch = *p++;
3404 tok = TOK_CLDOUBLE;
3405 tokc.ld = strtold(token_buf, NULL);
3406 } else {
3407 tok = TOK_CDOUBLE;
3408 tokc.d = strtod(token_buf, NULL);
3411 } else {
3412 unsigned long long n, n1;
3413 int lcount, ucount;
3415 /* integer number */
3416 *q = '\0';
3417 q = token_buf;
3418 if (b == 10 && *q == '0') {
3419 b = 8;
3420 q++;
3422 n = 0;
3423 while(1) {
3424 t = *q++;
3425 /* no need for checks except for base 10 / 8 errors */
3426 if (t == '\0') {
3427 break;
3428 } else if (t >= 'a') {
3429 t = t - 'a' + 10;
3430 } else if (t >= 'A') {
3431 t = t - 'A' + 10;
3432 } else {
3433 t = t - '0';
3434 if (t >= b)
3435 error("invalid digit");
3437 n1 = n;
3438 n = n * b + t;
3439 /* detect overflow */
3440 /* XXX: this test is not reliable */
3441 if (n < n1)
3442 error("integer constant overflow");
3445 /* XXX: not exactly ANSI compliant */
3446 if ((n & 0xffffffff00000000LL) != 0) {
3447 if ((n >> 63) != 0)
3448 tok = TOK_CULLONG;
3449 else
3450 tok = TOK_CLLONG;
3451 } else if (n > 0x7fffffff) {
3452 tok = TOK_CUINT;
3453 } else {
3454 tok = TOK_CINT;
3456 lcount = 0;
3457 ucount = 0;
3458 for(;;) {
3459 t = toup(ch);
3460 if (t == 'L') {
3461 if (lcount >= 2)
3462 error("three 'l's in integer constant");
3463 lcount++;
3464 if (lcount == 2) {
3465 if (tok == TOK_CINT)
3466 tok = TOK_CLLONG;
3467 else if (tok == TOK_CUINT)
3468 tok = TOK_CULLONG;
3470 ch = *p++;
3471 } else if (t == 'U') {
3472 if (ucount >= 1)
3473 error("two 'u's in integer constant");
3474 ucount++;
3475 if (tok == TOK_CINT)
3476 tok = TOK_CUINT;
3477 else if (tok == TOK_CLLONG)
3478 tok = TOK_CULLONG;
3479 ch = *p++;
3480 } else {
3481 break;
3484 if (tok == TOK_CINT || tok == TOK_CUINT)
3485 tokc.ui = n;
3486 else
3487 tokc.ull = n;
3492 #define PARSE2(c1, tok1, c2, tok2) \
3493 case c1: \
3494 PEEKC(c, p); \
3495 if (c == c2) { \
3496 p++; \
3497 tok = tok2; \
3498 } else { \
3499 tok = tok1; \
3501 break;
3503 /* return next token without macro substitution */
3504 static inline void next_nomacro1(void)
3506 int t, c, is_long;
3507 TokenSym *ts;
3508 uint8_t *p, *p1;
3509 unsigned int h;
3511 p = file->buf_ptr;
3512 redo_no_start:
3513 c = *p;
3514 switch(c) {
3515 case ' ':
3516 case '\t':
3517 case '\f':
3518 case '\v':
3519 case '\r':
3520 p++;
3521 goto redo_no_start;
3523 case '\\':
3524 /* first look if it is in fact an end of buffer */
3525 if (p >= file->buf_end) {
3526 file->buf_ptr = p;
3527 handle_eob();
3528 p = file->buf_ptr;
3529 if (p >= file->buf_end)
3530 goto parse_eof;
3531 else
3532 goto redo_no_start;
3533 } else {
3534 file->buf_ptr = p;
3535 ch = *p;
3536 handle_stray();
3537 p = file->buf_ptr;
3538 goto redo_no_start;
3540 parse_eof:
3542 TCCState *s1 = tcc_state;
3543 if (parse_flags & PARSE_FLAG_LINEFEED) {
3544 tok = TOK_LINEFEED;
3545 } else if (s1->include_stack_ptr == s1->include_stack ||
3546 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3547 /* no include left : end of file. */
3548 tok = TOK_EOF;
3549 } else {
3550 /* pop include file */
3552 /* test if previous '#endif' was after a #ifdef at
3553 start of file */
3554 if (tok_flags & TOK_FLAG_ENDIF) {
3555 #ifdef INC_DEBUG
3556 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3557 #endif
3558 add_cached_include(s1, file->inc_type, file->inc_filename,
3559 file->ifndef_macro_saved);
3562 /* add end of include file debug info */
3563 if (do_debug) {
3564 put_stabd(N_EINCL, 0, 0);
3566 /* pop include stack */
3567 tcc_close(file);
3568 s1->include_stack_ptr--;
3569 file = *s1->include_stack_ptr;
3570 p = file->buf_ptr;
3571 goto redo_no_start;
3574 break;
3576 case '\n':
3577 if (parse_flags & PARSE_FLAG_LINEFEED) {
3578 tok = TOK_LINEFEED;
3579 } else {
3580 file->line_num++;
3581 tok_flags |= TOK_FLAG_BOL;
3582 p++;
3583 goto redo_no_start;
3585 break;
3587 case '#':
3588 /* XXX: simplify */
3589 PEEKC(c, p);
3590 if ((tok_flags & TOK_FLAG_BOL) &&
3591 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3592 file->buf_ptr = p;
3593 preprocess(tok_flags & TOK_FLAG_BOF);
3594 p = file->buf_ptr;
3595 goto redo_no_start;
3596 } else {
3597 if (c == '#') {
3598 p++;
3599 tok = TOK_TWOSHARPS;
3600 } else {
3601 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3602 p = parse_line_comment(p - 1);
3603 goto redo_no_start;
3604 } else {
3605 tok = '#';
3609 break;
3611 case 'a': case 'b': case 'c': case 'd':
3612 case 'e': case 'f': case 'g': case 'h':
3613 case 'i': case 'j': case 'k': case 'l':
3614 case 'm': case 'n': case 'o': case 'p':
3615 case 'q': case 'r': case 's': case 't':
3616 case 'u': case 'v': case 'w': case 'x':
3617 case 'y': case 'z':
3618 case 'A': case 'B': case 'C': case 'D':
3619 case 'E': case 'F': case 'G': case 'H':
3620 case 'I': case 'J': case 'K':
3621 case 'M': case 'N': case 'O': case 'P':
3622 case 'Q': case 'R': case 'S': case 'T':
3623 case 'U': case 'V': case 'W': case 'X':
3624 case 'Y': case 'Z':
3625 case '_':
3626 parse_ident_fast:
3627 p1 = p;
3628 h = TOK_HASH_INIT;
3629 h = TOK_HASH_FUNC(h, c);
3630 p++;
3631 for(;;) {
3632 c = *p;
3633 if (!isidnum_table[c])
3634 break;
3635 h = TOK_HASH_FUNC(h, c);
3636 p++;
3638 if (c != '\\') {
3639 TokenSym **pts;
3640 int len;
3642 /* fast case : no stray found, so we have the full token
3643 and we have already hashed it */
3644 len = p - p1;
3645 h &= (TOK_HASH_SIZE - 1);
3646 pts = &hash_ident[h];
3647 for(;;) {
3648 ts = *pts;
3649 if (!ts)
3650 break;
3651 if (ts->len == len && !memcmp(ts->str, p1, len))
3652 goto token_found;
3653 pts = &(ts->hash_next);
3655 ts = tok_alloc_new(pts, p1, len);
3656 token_found: ;
3657 } else {
3658 /* slower case */
3659 cstr_reset(&tokcstr);
3661 while (p1 < p) {
3662 cstr_ccat(&tokcstr, *p1);
3663 p1++;
3665 p--;
3666 PEEKC(c, p);
3667 parse_ident_slow:
3668 while (isidnum_table[c]) {
3669 cstr_ccat(&tokcstr, c);
3670 PEEKC(c, p);
3672 ts = tok_alloc(tokcstr.data, tokcstr.size);
3674 tok = ts->tok;
3675 break;
3676 case 'L':
3677 t = p[1];
3678 if (t != '\\' && t != '\'' && t != '\"') {
3679 /* fast case */
3680 goto parse_ident_fast;
3681 } else {
3682 PEEKC(c, p);
3683 if (c == '\'' || c == '\"') {
3684 is_long = 1;
3685 goto str_const;
3686 } else {
3687 cstr_reset(&tokcstr);
3688 cstr_ccat(&tokcstr, 'L');
3689 goto parse_ident_slow;
3692 break;
3693 case '0': case '1': case '2': case '3':
3694 case '4': case '5': case '6': case '7':
3695 case '8': case '9':
3697 cstr_reset(&tokcstr);
3698 /* after the first digit, accept digits, alpha, '.' or sign if
3699 prefixed by 'eEpP' */
3700 parse_num:
3701 for(;;) {
3702 t = c;
3703 cstr_ccat(&tokcstr, c);
3704 PEEKC(c, p);
3705 if (!(isnum(c) || isid(c) || c == '.' ||
3706 ((c == '+' || c == '-') &&
3707 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3708 break;
3710 /* We add a trailing '\0' to ease parsing */
3711 cstr_ccat(&tokcstr, '\0');
3712 tokc.cstr = &tokcstr;
3713 tok = TOK_PPNUM;
3714 break;
3715 case '.':
3716 /* special dot handling because it can also start a number */
3717 PEEKC(c, p);
3718 if (isnum(c)) {
3719 cstr_reset(&tokcstr);
3720 cstr_ccat(&tokcstr, '.');
3721 goto parse_num;
3722 } else if (c == '.') {
3723 PEEKC(c, p);
3724 if (c != '.')
3725 expect("'.'");
3726 PEEKC(c, p);
3727 tok = TOK_DOTS;
3728 } else {
3729 tok = '.';
3731 break;
3732 case '\'':
3733 case '\"':
3734 is_long = 0;
3735 str_const:
3737 CString str;
3738 int sep;
3740 sep = c;
3742 /* parse the string */
3743 cstr_new(&str);
3744 p = parse_pp_string(p, sep, &str);
3745 cstr_ccat(&str, '\0');
3747 /* eval the escape (should be done as TOK_PPNUM) */
3748 cstr_reset(&tokcstr);
3749 parse_escape_string(&tokcstr, str.data, is_long);
3750 cstr_free(&str);
3752 if (sep == '\'') {
3753 int char_size;
3754 /* XXX: make it portable */
3755 if (!is_long)
3756 char_size = 1;
3757 else
3758 char_size = sizeof(nwchar_t);
3759 if (tokcstr.size <= char_size)
3760 error("empty character constant");
3761 if (tokcstr.size > 2 * char_size)
3762 warning("multi-character character constant");
3763 if (!is_long) {
3764 tokc.i = *(int8_t *)tokcstr.data;
3765 tok = TOK_CCHAR;
3766 } else {
3767 tokc.i = *(nwchar_t *)tokcstr.data;
3768 tok = TOK_LCHAR;
3770 } else {
3771 tokc.cstr = &tokcstr;
3772 if (!is_long)
3773 tok = TOK_STR;
3774 else
3775 tok = TOK_LSTR;
3778 break;
3780 case '<':
3781 PEEKC(c, p);
3782 if (c == '=') {
3783 p++;
3784 tok = TOK_LE;
3785 } else if (c == '<') {
3786 PEEKC(c, p);
3787 if (c == '=') {
3788 p++;
3789 tok = TOK_A_SHL;
3790 } else {
3791 tok = TOK_SHL;
3793 } else {
3794 tok = TOK_LT;
3796 break;
3798 case '>':
3799 PEEKC(c, p);
3800 if (c == '=') {
3801 p++;
3802 tok = TOK_GE;
3803 } else if (c == '>') {
3804 PEEKC(c, p);
3805 if (c == '=') {
3806 p++;
3807 tok = TOK_A_SAR;
3808 } else {
3809 tok = TOK_SAR;
3811 } else {
3812 tok = TOK_GT;
3814 break;
3816 case '&':
3817 PEEKC(c, p);
3818 if (c == '&') {
3819 p++;
3820 tok = TOK_LAND;
3821 } else if (c == '=') {
3822 p++;
3823 tok = TOK_A_AND;
3824 } else {
3825 tok = '&';
3827 break;
3829 case '|':
3830 PEEKC(c, p);
3831 if (c == '|') {
3832 p++;
3833 tok = TOK_LOR;
3834 } else if (c == '=') {
3835 p++;
3836 tok = TOK_A_OR;
3837 } else {
3838 tok = '|';
3840 break;
3842 case '+':
3843 PEEKC(c, p);
3844 if (c == '+') {
3845 p++;
3846 tok = TOK_INC;
3847 } else if (c == '=') {
3848 p++;
3849 tok = TOK_A_ADD;
3850 } else {
3851 tok = '+';
3853 break;
3855 case '-':
3856 PEEKC(c, p);
3857 if (c == '-') {
3858 p++;
3859 tok = TOK_DEC;
3860 } else if (c == '=') {
3861 p++;
3862 tok = TOK_A_SUB;
3863 } else if (c == '>') {
3864 p++;
3865 tok = TOK_ARROW;
3866 } else {
3867 tok = '-';
3869 break;
3871 PARSE2('!', '!', '=', TOK_NE)
3872 PARSE2('=', '=', '=', TOK_EQ)
3873 PARSE2('*', '*', '=', TOK_A_MUL)
3874 PARSE2('%', '%', '=', TOK_A_MOD)
3875 PARSE2('^', '^', '=', TOK_A_XOR)
3877 /* comments or operator */
3878 case '/':
3879 PEEKC(c, p);
3880 if (c == '*') {
3881 p = parse_comment(p);
3882 goto redo_no_start;
3883 } else if (c == '/') {
3884 p = parse_line_comment(p);
3885 goto redo_no_start;
3886 } else if (c == '=') {
3887 p++;
3888 tok = TOK_A_DIV;
3889 } else {
3890 tok = '/';
3892 break;
3894 /* simple tokens */
3895 case '(':
3896 case ')':
3897 case '[':
3898 case ']':
3899 case '{':
3900 case '}':
3901 case ',':
3902 case ';':
3903 case ':':
3904 case '?':
3905 case '~':
3906 case '$': /* only used in assembler */
3907 case '@': /* dito */
3908 tok = c;
3909 p++;
3910 break;
3911 default:
3912 error("unrecognized character \\x%02x", c);
3913 break;
3915 file->buf_ptr = p;
3916 tok_flags = 0;
3917 #if defined(PARSE_DEBUG)
3918 printf("token = %s\n", get_tok_str(tok, &tokc));
3919 #endif
3922 /* return next token without macro substitution. Can read input from
3923 macro_ptr buffer */
3924 static void next_nomacro(void)
3926 if (macro_ptr) {
3927 redo:
3928 tok = *macro_ptr;
3929 if (tok) {
3930 TOK_GET(tok, macro_ptr, tokc);
3931 if (tok == TOK_LINENUM) {
3932 file->line_num = tokc.i;
3933 goto redo;
3936 } else {
3937 next_nomacro1();
3941 /* substitute args in macro_str and return allocated string */
3942 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3944 int *st, last_tok, t, notfirst;
3945 Sym *s;
3946 CValue cval;
3947 TokenString str;
3948 CString cstr;
3950 tok_str_new(&str);
3951 last_tok = 0;
3952 while(1) {
3953 TOK_GET(t, macro_str, cval);
3954 if (!t)
3955 break;
3956 if (t == '#') {
3957 /* stringize */
3958 TOK_GET(t, macro_str, cval);
3959 if (!t)
3960 break;
3961 s = sym_find2(args, t);
3962 if (s) {
3963 cstr_new(&cstr);
3964 st = (int *)s->c;
3965 notfirst = 0;
3966 while (*st) {
3967 if (notfirst)
3968 cstr_ccat(&cstr, ' ');
3969 TOK_GET(t, st, cval);
3970 cstr_cat(&cstr, get_tok_str(t, &cval));
3971 notfirst = 1;
3973 cstr_ccat(&cstr, '\0');
3974 #ifdef PP_DEBUG
3975 printf("stringize: %s\n", (char *)cstr.data);
3976 #endif
3977 /* add string */
3978 cval.cstr = &cstr;
3979 tok_str_add2(&str, TOK_STR, &cval);
3980 cstr_free(&cstr);
3981 } else {
3982 tok_str_add2(&str, t, &cval);
3984 } else if (t >= TOK_IDENT) {
3985 s = sym_find2(args, t);
3986 if (s) {
3987 st = (int *)s->c;
3988 /* if '##' is present before or after, no arg substitution */
3989 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3990 /* special case for var arg macros : ## eats the
3991 ',' if empty VA_ARGS variable. */
3992 /* XXX: test of the ',' is not 100%
3993 reliable. should fix it to avoid security
3994 problems */
3995 if (gnu_ext && s->type.t &&
3996 last_tok == TOK_TWOSHARPS &&
3997 str.len >= 2 && str.str[str.len - 2] == ',') {
3998 if (*st == 0) {
3999 /* suppress ',' '##' */
4000 str.len -= 2;
4001 } else {
4002 /* suppress '##' and add variable */
4003 str.len--;
4004 goto add_var;
4006 } else {
4007 int t1;
4008 add_var:
4009 for(;;) {
4010 TOK_GET(t1, st, cval);
4011 if (!t1)
4012 break;
4013 tok_str_add2(&str, t1, &cval);
4016 } else {
4017 /* NOTE: the stream cannot be read when macro
4018 substituing an argument */
4019 macro_subst(&str, nested_list, st, NULL);
4021 } else {
4022 tok_str_add(&str, t);
4024 } else {
4025 tok_str_add2(&str, t, &cval);
4027 last_tok = t;
4029 tok_str_add(&str, 0);
4030 return str.str;
4033 static char const ab_month_name[12][4] =
4035 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4036 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4039 /* do macro substitution of current token with macro 's' and add
4040 result to (tok_str,tok_len). 'nested_list' is the list of all
4041 macros we got inside to avoid recursing. Return non zero if no
4042 substitution needs to be done */
4043 static int macro_subst_tok(TokenString *tok_str,
4044 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4046 Sym *args, *sa, *sa1;
4047 int mstr_allocated, parlevel, *mstr, t, t1;
4048 TokenString str;
4049 char *cstrval;
4050 CValue cval;
4051 CString cstr;
4052 char buf[32];
4054 /* if symbol is a macro, prepare substitution */
4055 /* special macros */
4056 if (tok == TOK___LINE__) {
4057 snprintf(buf, sizeof(buf), "%d", file->line_num);
4058 cstrval = buf;
4059 t1 = TOK_PPNUM;
4060 goto add_cstr1;
4061 } else if (tok == TOK___FILE__) {
4062 cstrval = file->filename;
4063 goto add_cstr;
4064 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4065 time_t ti;
4066 struct tm *tm;
4068 time(&ti);
4069 tm = localtime(&ti);
4070 if (tok == TOK___DATE__) {
4071 snprintf(buf, sizeof(buf), "%s %2d %d",
4072 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4073 } else {
4074 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4075 tm->tm_hour, tm->tm_min, tm->tm_sec);
4077 cstrval = buf;
4078 add_cstr:
4079 t1 = TOK_STR;
4080 add_cstr1:
4081 cstr_new(&cstr);
4082 cstr_cat(&cstr, cstrval);
4083 cstr_ccat(&cstr, '\0');
4084 cval.cstr = &cstr;
4085 tok_str_add2(tok_str, t1, &cval);
4086 cstr_free(&cstr);
4087 } else {
4088 mstr = (int *)s->c;
4089 mstr_allocated = 0;
4090 if (s->type.t == MACRO_FUNC) {
4091 /* NOTE: we do not use next_nomacro to avoid eating the
4092 next token. XXX: find better solution */
4093 redo:
4094 if (macro_ptr) {
4095 t = *macro_ptr;
4096 if (t == 0 && can_read_stream) {
4097 /* end of macro stream: we must look at the token
4098 after in the file */
4099 struct macro_level *ml = *can_read_stream;
4100 macro_ptr = NULL;
4101 if (ml)
4103 macro_ptr = ml->p;
4104 ml->p = NULL;
4105 *can_read_stream = ml -> prev;
4107 goto redo;
4109 } else {
4110 /* XXX: incorrect with comments */
4111 ch = file->buf_ptr[0];
4112 while (is_space(ch) || ch == '\n')
4113 cinp();
4114 t = ch;
4116 if (t != '(') /* no macro subst */
4117 return -1;
4119 /* argument macro */
4120 next_nomacro();
4121 next_nomacro();
4122 args = NULL;
4123 sa = s->next;
4124 /* NOTE: empty args are allowed, except if no args */
4125 for(;;) {
4126 /* handle '()' case */
4127 if (!args && !sa && tok == ')')
4128 break;
4129 if (!sa)
4130 error("macro '%s' used with too many args",
4131 get_tok_str(s->v, 0));
4132 tok_str_new(&str);
4133 parlevel = 0;
4134 /* NOTE: non zero sa->t indicates VA_ARGS */
4135 while ((parlevel > 0 ||
4136 (tok != ')' &&
4137 (tok != ',' || sa->type.t))) &&
4138 tok != -1) {
4139 if (tok == '(')
4140 parlevel++;
4141 else if (tok == ')')
4142 parlevel--;
4143 tok_str_add2(&str, tok, &tokc);
4144 next_nomacro();
4146 tok_str_add(&str, 0);
4147 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4148 sa = sa->next;
4149 if (tok == ')') {
4150 /* special case for gcc var args: add an empty
4151 var arg argument if it is omitted */
4152 if (sa && sa->type.t && gnu_ext)
4153 continue;
4154 else
4155 break;
4157 if (tok != ',')
4158 expect(",");
4159 next_nomacro();
4161 if (sa) {
4162 error("macro '%s' used with too few args",
4163 get_tok_str(s->v, 0));
4166 /* now subst each arg */
4167 mstr = macro_arg_subst(nested_list, mstr, args);
4168 /* free memory */
4169 sa = args;
4170 while (sa) {
4171 sa1 = sa->prev;
4172 tok_str_free((int *)sa->c);
4173 sym_free(sa);
4174 sa = sa1;
4176 mstr_allocated = 1;
4178 sym_push2(nested_list, s->v, 0, 0);
4179 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4180 /* pop nested defined symbol */
4181 sa1 = *nested_list;
4182 *nested_list = sa1->prev;
4183 sym_free(sa1);
4184 if (mstr_allocated)
4185 tok_str_free(mstr);
4187 return 0;
4190 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4191 return the resulting string (which must be freed). */
4192 static inline int *macro_twosharps(const int *macro_str)
4194 TokenSym *ts;
4195 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4196 int t;
4197 const char *p1, *p2;
4198 CValue cval;
4199 TokenString macro_str1;
4200 CString cstr;
4202 start_macro_ptr = macro_str;
4203 /* we search the first '##' */
4204 for(;;) {
4205 macro_ptr1 = macro_str;
4206 TOK_GET(t, macro_str, cval);
4207 /* nothing more to do if end of string */
4208 if (t == 0)
4209 return NULL;
4210 if (*macro_str == TOK_TWOSHARPS)
4211 break;
4214 /* we saw '##', so we need more processing to handle it */
4215 cstr_new(&cstr);
4216 tok_str_new(&macro_str1);
4217 tok = t;
4218 tokc = cval;
4220 /* add all tokens seen so far */
4221 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4222 TOK_GET(t, ptr, cval);
4223 tok_str_add2(&macro_str1, t, &cval);
4225 saved_macro_ptr = macro_ptr;
4226 /* XXX: get rid of the use of macro_ptr here */
4227 macro_ptr = (int *)macro_str;
4228 for(;;) {
4229 while (*macro_ptr == TOK_TWOSHARPS) {
4230 macro_ptr++;
4231 macro_ptr1 = macro_ptr;
4232 t = *macro_ptr;
4233 if (t) {
4234 TOK_GET(t, macro_ptr, cval);
4235 /* We concatenate the two tokens if we have an
4236 identifier or a preprocessing number */
4237 cstr_reset(&cstr);
4238 p1 = get_tok_str(tok, &tokc);
4239 cstr_cat(&cstr, p1);
4240 p2 = get_tok_str(t, &cval);
4241 cstr_cat(&cstr, p2);
4242 cstr_ccat(&cstr, '\0');
4244 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4245 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4246 if (tok == TOK_PPNUM) {
4247 /* if number, then create a number token */
4248 /* NOTE: no need to allocate because
4249 tok_str_add2() does it */
4250 cstr_reset(&tokcstr);
4251 tokcstr = cstr;
4252 cstr_new(&cstr);
4253 tokc.cstr = &tokcstr;
4254 } else {
4255 /* if identifier, we must do a test to
4256 validate we have a correct identifier */
4257 if (t == TOK_PPNUM) {
4258 const char *p;
4259 int c;
4261 p = p2;
4262 for(;;) {
4263 c = *p;
4264 if (c == '\0')
4265 break;
4266 p++;
4267 if (!isnum(c) && !isid(c))
4268 goto error_pasting;
4271 ts = tok_alloc(cstr.data, strlen(cstr.data));
4272 tok = ts->tok; /* modify current token */
4274 } else {
4275 const char *str = cstr.data;
4276 const unsigned char *q;
4278 /* we look for a valid token */
4279 /* XXX: do more extensive checks */
4280 if (!strcmp(str, ">>=")) {
4281 tok = TOK_A_SAR;
4282 } else if (!strcmp(str, "<<=")) {
4283 tok = TOK_A_SHL;
4284 } else if (strlen(str) == 2) {
4285 /* search in two bytes table */
4286 q = tok_two_chars;
4287 for(;;) {
4288 if (!*q)
4289 goto error_pasting;
4290 if (q[0] == str[0] && q[1] == str[1])
4291 break;
4292 q += 3;
4294 tok = q[2];
4295 } else {
4296 error_pasting:
4297 /* NOTE: because get_tok_str use a static buffer,
4298 we must save it */
4299 cstr_reset(&cstr);
4300 p1 = get_tok_str(tok, &tokc);
4301 cstr_cat(&cstr, p1);
4302 cstr_ccat(&cstr, '\0');
4303 p2 = get_tok_str(t, &cval);
4304 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4305 /* cannot merge tokens: just add them separately */
4306 tok_str_add2(&macro_str1, tok, &tokc);
4307 /* XXX: free associated memory ? */
4308 tok = t;
4309 tokc = cval;
4314 tok_str_add2(&macro_str1, tok, &tokc);
4315 next_nomacro();
4316 if (tok == 0)
4317 break;
4319 macro_ptr = (int *)saved_macro_ptr;
4320 cstr_free(&cstr);
4321 tok_str_add(&macro_str1, 0);
4322 return macro_str1.str;
4326 /* do macro substitution of macro_str and add result to
4327 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4328 inside to avoid recursing. */
4329 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4330 const int *macro_str, struct macro_level ** can_read_stream)
4332 Sym *s;
4333 int *macro_str1;
4334 const int *ptr;
4335 int t, ret;
4336 CValue cval;
4337 struct macro_level ml;
4339 /* first scan for '##' operator handling */
4340 ptr = macro_str;
4341 macro_str1 = macro_twosharps(ptr);
4342 if (macro_str1)
4343 ptr = macro_str1;
4344 while (1) {
4345 /* NOTE: ptr == NULL can only happen if tokens are read from
4346 file stream due to a macro function call */
4347 if (ptr == NULL)
4348 break;
4349 TOK_GET(t, ptr, cval);
4350 if (t == 0)
4351 break;
4352 s = define_find(t);
4353 if (s != NULL) {
4354 /* if nested substitution, do nothing */
4355 if (sym_find2(*nested_list, t))
4356 goto no_subst;
4357 ml.p = macro_ptr;
4358 if (can_read_stream)
4359 ml.prev = *can_read_stream, *can_read_stream = &ml;
4360 macro_ptr = (int *)ptr;
4361 tok = t;
4362 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4363 ptr = (int *)macro_ptr;
4364 macro_ptr = ml.p;
4365 if (can_read_stream && *can_read_stream == &ml)
4366 *can_read_stream = ml.prev;
4367 if (ret != 0)
4368 goto no_subst;
4369 } else {
4370 no_subst:
4371 tok_str_add2(tok_str, t, &cval);
4374 if (macro_str1)
4375 tok_str_free(macro_str1);
4378 /* return next token with macro substitution */
4379 static void next(void)
4381 Sym *nested_list, *s;
4382 TokenString str;
4383 struct macro_level *ml;
4385 redo:
4386 next_nomacro();
4387 if (!macro_ptr) {
4388 /* if not reading from macro substituted string, then try
4389 to substitute macros */
4390 if (tok >= TOK_IDENT &&
4391 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4392 s = define_find(tok);
4393 if (s) {
4394 /* we have a macro: we try to substitute */
4395 tok_str_new(&str);
4396 nested_list = NULL;
4397 ml = NULL;
4398 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4399 /* substitution done, NOTE: maybe empty */
4400 tok_str_add(&str, 0);
4401 macro_ptr = str.str;
4402 macro_ptr_allocated = str.str;
4403 goto redo;
4407 } else {
4408 if (tok == 0) {
4409 /* end of macro or end of unget buffer */
4410 if (unget_buffer_enabled) {
4411 macro_ptr = unget_saved_macro_ptr;
4412 unget_buffer_enabled = 0;
4413 } else {
4414 /* end of macro string: free it */
4415 tok_str_free(macro_ptr_allocated);
4416 macro_ptr = NULL;
4418 goto redo;
4422 /* convert preprocessor tokens into C tokens */
4423 if (tok == TOK_PPNUM &&
4424 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4425 parse_number((char *)tokc.cstr->data);
4429 /* push back current token and set current token to 'last_tok'. Only
4430 identifier case handled for labels. */
4431 static inline void unget_tok(int last_tok)
4433 int i, n;
4434 int *q;
4435 unget_saved_macro_ptr = macro_ptr;
4436 unget_buffer_enabled = 1;
4437 q = unget_saved_buffer;
4438 macro_ptr = q;
4439 *q++ = tok;
4440 n = tok_ext_size(tok) - 1;
4441 for(i=0;i<n;i++)
4442 *q++ = tokc.tab[i];
4443 *q = 0; /* end of token string */
4444 tok = last_tok;
4448 void swap(int *p, int *q)
4450 int t;
4451 t = *p;
4452 *p = *q;
4453 *q = t;
4456 void vsetc(CType *type, int r, CValue *vc)
4458 int v;
4460 if (vtop >= vstack + (VSTACK_SIZE - 1))
4461 error("memory full");
4462 /* cannot let cpu flags if other instruction are generated. Also
4463 avoid leaving VT_JMP anywhere except on the top of the stack
4464 because it would complicate the code generator. */
4465 if (vtop >= vstack) {
4466 v = vtop->r & VT_VALMASK;
4467 if (v == VT_CMP || (v & ~1) == VT_JMP)
4468 gv(RC_INT);
4470 vtop++;
4471 vtop->type = *type;
4472 vtop->r = r;
4473 vtop->r2 = VT_CONST;
4474 vtop->c = *vc;
4477 /* push integer constant */
4478 void vpushi(int v)
4480 CValue cval;
4481 cval.i = v;
4482 vsetc(&int_type, VT_CONST, &cval);
4485 /* Return a static symbol pointing to a section */
4486 static Sym *get_sym_ref(CType *type, Section *sec,
4487 unsigned long offset, unsigned long size)
4489 int v;
4490 Sym *sym;
4492 v = anon_sym++;
4493 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4494 sym->type.ref = type->ref;
4495 sym->r = VT_CONST | VT_SYM;
4496 put_extern_sym(sym, sec, offset, size);
4497 return sym;
4500 /* push a reference to a section offset by adding a dummy symbol */
4501 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4503 CValue cval;
4505 cval.ul = 0;
4506 vsetc(type, VT_CONST | VT_SYM, &cval);
4507 vtop->sym = get_sym_ref(type, sec, offset, size);
4510 /* define a new external reference to a symbol 'v' of type 'u' */
4511 static Sym *external_global_sym(int v, CType *type, int r)
4513 Sym *s;
4515 s = sym_find(v);
4516 if (!s) {
4517 /* push forward reference */
4518 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4519 s->type.ref = type->ref;
4520 s->r = r | VT_CONST | VT_SYM;
4522 return s;
4525 /* define a new external reference to a symbol 'v' of type 'u' */
4526 static Sym *external_sym(int v, CType *type, int r)
4528 Sym *s;
4530 s = sym_find(v);
4531 if (!s) {
4532 /* push forward reference */
4533 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4534 s->type.t |= VT_EXTERN;
4535 } else {
4536 if (!is_compatible_types(&s->type, type))
4537 error("incompatible types for redefinition of '%s'",
4538 get_tok_str(v, NULL));
4540 return s;
4543 /* push a reference to global symbol v */
4544 static void vpush_global_sym(CType *type, int v)
4546 Sym *sym;
4547 CValue cval;
4549 sym = external_global_sym(v, type, 0);
4550 cval.ul = 0;
4551 vsetc(type, VT_CONST | VT_SYM, &cval);
4552 vtop->sym = sym;
4555 void vset(CType *type, int r, int v)
4557 CValue cval;
4559 cval.i = v;
4560 vsetc(type, r, &cval);
4563 void vseti(int r, int v)
4565 CType type;
4566 type.t = VT_INT;
4567 vset(&type, r, v);
4570 void vswap(void)
4572 SValue tmp;
4574 tmp = vtop[0];
4575 vtop[0] = vtop[-1];
4576 vtop[-1] = tmp;
4579 void vpushv(SValue *v)
4581 if (vtop >= vstack + (VSTACK_SIZE - 1))
4582 error("memory full");
4583 vtop++;
4584 *vtop = *v;
4587 void vdup(void)
4589 vpushv(vtop);
4592 /* save r to the memory stack, and mark it as being free */
4593 void save_reg(int r)
4595 int l, saved, size, align;
4596 SValue *p, sv;
4597 CType *type;
4599 /* modify all stack values */
4600 saved = 0;
4601 l = 0;
4602 for(p=vstack;p<=vtop;p++) {
4603 if ((p->r & VT_VALMASK) == r ||
4604 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4605 /* must save value on stack if not already done */
4606 if (!saved) {
4607 /* NOTE: must reload 'r' because r might be equal to r2 */
4608 r = p->r & VT_VALMASK;
4609 /* store register in the stack */
4610 type = &p->type;
4611 if ((p->r & VT_LVAL) ||
4612 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4613 type = &int_type;
4614 size = type_size(type, &align);
4615 loc = (loc - size) & -align;
4616 sv.type.t = type->t;
4617 sv.r = VT_LOCAL | VT_LVAL;
4618 sv.c.ul = loc;
4619 store(r, &sv);
4620 #ifdef TCC_TARGET_I386
4621 /* x86 specific: need to pop fp register ST0 if saved */
4622 if (r == TREG_ST0) {
4623 o(0xd9dd); /* fstp %st(1) */
4625 #endif
4626 /* special long long case */
4627 if ((type->t & VT_BTYPE) == VT_LLONG) {
4628 sv.c.ul += 4;
4629 store(p->r2, &sv);
4631 l = loc;
4632 saved = 1;
4634 /* mark that stack entry as being saved on the stack */
4635 if (p->r & VT_LVAL) {
4636 /* also clear the bounded flag because the
4637 relocation address of the function was stored in
4638 p->c.ul */
4639 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4640 } else {
4641 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4643 p->r2 = VT_CONST;
4644 p->c.ul = l;
4649 /* find a register of class 'rc2' with at most one reference on stack.
4650 * If none, call get_reg(rc) */
4651 int get_reg_ex(int rc, int rc2)
4653 int r;
4654 SValue *p;
4656 for(r=0;r<NB_REGS;r++) {
4657 if (reg_classes[r] & rc2) {
4658 int n;
4659 n=0;
4660 for(p = vstack; p <= vtop; p++) {
4661 if ((p->r & VT_VALMASK) == r ||
4662 (p->r2 & VT_VALMASK) == r)
4663 n++;
4665 if (n <= 1)
4666 return r;
4669 return get_reg(rc);
4672 /* find a free register of class 'rc'. If none, save one register */
4673 int get_reg(int rc)
4675 int r;
4676 SValue *p;
4678 /* find a free register */
4679 for(r=0;r<NB_REGS;r++) {
4680 if (reg_classes[r] & rc) {
4681 for(p=vstack;p<=vtop;p++) {
4682 if ((p->r & VT_VALMASK) == r ||
4683 (p->r2 & VT_VALMASK) == r)
4684 goto notfound;
4686 return r;
4688 notfound: ;
4691 /* no register left : free the first one on the stack (VERY
4692 IMPORTANT to start from the bottom to ensure that we don't
4693 spill registers used in gen_opi()) */
4694 for(p=vstack;p<=vtop;p++) {
4695 r = p->r & VT_VALMASK;
4696 if (r < VT_CONST && (reg_classes[r] & rc))
4697 goto save_found;
4698 /* also look at second register (if long long) */
4699 r = p->r2 & VT_VALMASK;
4700 if (r < VT_CONST && (reg_classes[r] & rc)) {
4701 save_found:
4702 save_reg(r);
4703 return r;
4706 /* Should never comes here */
4707 return -1;
4710 /* save registers up to (vtop - n) stack entry */
4711 void save_regs(int n)
4713 int r;
4714 SValue *p, *p1;
4715 p1 = vtop - n;
4716 for(p = vstack;p <= p1; p++) {
4717 r = p->r & VT_VALMASK;
4718 if (r < VT_CONST) {
4719 save_reg(r);
4724 /* move register 's' to 'r', and flush previous value of r to memory
4725 if needed */
4726 void move_reg(int r, int s)
4728 SValue sv;
4730 if (r != s) {
4731 save_reg(r);
4732 sv.type.t = VT_INT;
4733 sv.r = s;
4734 sv.c.ul = 0;
4735 load(r, &sv);
4739 /* get address of vtop (vtop MUST BE an lvalue) */
4740 void gaddrof(void)
4742 vtop->r &= ~VT_LVAL;
4743 /* tricky: if saved lvalue, then we can go back to lvalue */
4744 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4745 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4748 #ifdef CONFIG_TCC_BCHECK
4749 /* generate lvalue bound code */
4750 void gbound(void)
4752 int lval_type;
4753 CType type1;
4755 vtop->r &= ~VT_MUSTBOUND;
4756 /* if lvalue, then use checking code before dereferencing */
4757 if (vtop->r & VT_LVAL) {
4758 /* if not VT_BOUNDED value, then make one */
4759 if (!(vtop->r & VT_BOUNDED)) {
4760 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4761 /* must save type because we must set it to int to get pointer */
4762 type1 = vtop->type;
4763 vtop->type.t = VT_INT;
4764 gaddrof();
4765 vpushi(0);
4766 gen_bounded_ptr_add();
4767 vtop->r |= lval_type;
4768 vtop->type = type1;
4770 /* then check for dereferencing */
4771 gen_bounded_ptr_deref();
4774 #endif
4776 /* store vtop a register belonging to class 'rc'. lvalues are
4777 converted to values. Cannot be used if cannot be converted to
4778 register value (such as structures). */
4779 int gv(int rc)
4781 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4782 unsigned long long ll;
4784 /* NOTE: get_reg can modify vstack[] */
4785 if (vtop->type.t & VT_BITFIELD) {
4786 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4787 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4788 /* remove bit field info to avoid loops */
4789 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4790 /* generate shifts */
4791 vpushi(32 - (bit_pos + bit_size));
4792 gen_op(TOK_SHL);
4793 vpushi(32 - bit_size);
4794 /* NOTE: transformed to SHR if unsigned */
4795 gen_op(TOK_SAR);
4796 r = gv(rc);
4797 } else {
4798 if (is_float(vtop->type.t) &&
4799 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4800 Sym *sym;
4801 int *ptr;
4802 unsigned long offset;
4804 /* XXX: unify with initializers handling ? */
4805 /* CPUs usually cannot use float constants, so we store them
4806 generically in data segment */
4807 size = type_size(&vtop->type, &align);
4808 offset = (data_section->data_offset + align - 1) & -align;
4809 data_section->data_offset = offset;
4810 /* XXX: not portable yet */
4811 #ifdef __i386__
4812 /* Zero pad x87 tenbyte long doubles */
4813 if (size == 12)
4814 vtop->c.tab[2] &= 0xffff;
4815 #endif
4816 ptr = section_ptr_add(data_section, size);
4817 size = size >> 2;
4818 for(i=0;i<size;i++)
4819 ptr[i] = vtop->c.tab[i];
4820 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4821 vtop->r |= VT_LVAL | VT_SYM;
4822 vtop->sym = sym;
4823 vtop->c.ul = 0;
4825 #ifdef CONFIG_TCC_BCHECK
4826 if (vtop->r & VT_MUSTBOUND)
4827 gbound();
4828 #endif
4830 r = vtop->r & VT_VALMASK;
4831 /* need to reload if:
4832 - constant
4833 - lvalue (need to dereference pointer)
4834 - already a register, but not in the right class */
4835 if (r >= VT_CONST ||
4836 (vtop->r & VT_LVAL) ||
4837 !(reg_classes[r] & rc) ||
4838 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4839 !(reg_classes[vtop->r2] & rc))) {
4840 r = get_reg(rc);
4841 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4842 /* two register type load : expand to two words
4843 temporarily */
4844 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4845 /* load constant */
4846 ll = vtop->c.ull;
4847 vtop->c.ui = ll; /* first word */
4848 load(r, vtop);
4849 vtop->r = r; /* save register value */
4850 vpushi(ll >> 32); /* second word */
4851 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4852 (vtop->r & VT_LVAL)) {
4853 /* We do not want to modifier the long long
4854 pointer here, so the safest (and less
4855 efficient) is to save all the other registers
4856 in the stack. XXX: totally inefficient. */
4857 save_regs(1);
4858 /* load from memory */
4859 load(r, vtop);
4860 vdup();
4861 vtop[-1].r = r; /* save register value */
4862 /* increment pointer to get second word */
4863 vtop->type.t = VT_INT;
4864 gaddrof();
4865 vpushi(4);
4866 gen_op('+');
4867 vtop->r |= VT_LVAL;
4868 } else {
4869 /* move registers */
4870 load(r, vtop);
4871 vdup();
4872 vtop[-1].r = r; /* save register value */
4873 vtop->r = vtop[-1].r2;
4875 /* allocate second register */
4876 rc2 = RC_INT;
4877 if (rc == RC_IRET)
4878 rc2 = RC_LRET;
4879 r2 = get_reg(rc2);
4880 load(r2, vtop);
4881 vpop();
4882 /* write second register */
4883 vtop->r2 = r2;
4884 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4885 int t1, t;
4886 /* lvalue of scalar type : need to use lvalue type
4887 because of possible cast */
4888 t = vtop->type.t;
4889 t1 = t;
4890 /* compute memory access type */
4891 if (vtop->r & VT_LVAL_BYTE)
4892 t = VT_BYTE;
4893 else if (vtop->r & VT_LVAL_SHORT)
4894 t = VT_SHORT;
4895 if (vtop->r & VT_LVAL_UNSIGNED)
4896 t |= VT_UNSIGNED;
4897 vtop->type.t = t;
4898 load(r, vtop);
4899 /* restore wanted type */
4900 vtop->type.t = t1;
4901 } else {
4902 /* one register type load */
4903 load(r, vtop);
4906 vtop->r = r;
4907 #ifdef TCC_TARGET_C67
4908 /* uses register pairs for doubles */
4909 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4910 vtop->r2 = r+1;
4911 #endif
4913 return r;
4916 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4917 void gv2(int rc1, int rc2)
4919 int v;
4921 /* generate more generic register first. But VT_JMP or VT_CMP
4922 values must be generated first in all cases to avoid possible
4923 reload errors */
4924 v = vtop[0].r & VT_VALMASK;
4925 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4926 vswap();
4927 gv(rc1);
4928 vswap();
4929 gv(rc2);
4930 /* test if reload is needed for first register */
4931 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4932 vswap();
4933 gv(rc1);
4934 vswap();
4936 } else {
4937 gv(rc2);
4938 vswap();
4939 gv(rc1);
4940 vswap();
4941 /* test if reload is needed for first register */
4942 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4943 gv(rc2);
4948 /* expand long long on stack in two int registers */
4949 void lexpand(void)
4951 int u;
4953 u = vtop->type.t & VT_UNSIGNED;
4954 gv(RC_INT);
4955 vdup();
4956 vtop[0].r = vtop[-1].r2;
4957 vtop[0].r2 = VT_CONST;
4958 vtop[-1].r2 = VT_CONST;
4959 vtop[0].type.t = VT_INT | u;
4960 vtop[-1].type.t = VT_INT | u;
4963 #ifdef TCC_TARGET_ARM
4964 /* expand long long on stack */
4965 void lexpand_nr(void)
4967 int u,v;
4969 u = vtop->type.t & VT_UNSIGNED;
4970 vdup();
4971 vtop->r2 = VT_CONST;
4972 vtop->type.t = VT_INT | u;
4973 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4974 if (v == VT_CONST) {
4975 vtop[-1].c.ui = vtop->c.ull;
4976 vtop->c.ui = vtop->c.ull >> 32;
4977 vtop->r = VT_CONST;
4978 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4979 vtop->c.ui += 4;
4980 vtop->r = vtop[-1].r;
4981 } else if (v > VT_CONST) {
4982 vtop--;
4983 lexpand();
4984 } else
4985 vtop->r = vtop[-1].r2;
4986 vtop[-1].r2 = VT_CONST;
4987 vtop[-1].type.t = VT_INT | u;
4989 #endif
4991 /* build a long long from two ints */
4992 void lbuild(int t)
4994 gv2(RC_INT, RC_INT);
4995 vtop[-1].r2 = vtop[0].r;
4996 vtop[-1].type.t = t;
4997 vpop();
5000 /* rotate n first stack elements to the bottom
5001 I1 ... In -> I2 ... In I1 [top is right]
5003 void vrotb(int n)
5005 int i;
5006 SValue tmp;
5008 tmp = vtop[-n + 1];
5009 for(i=-n+1;i!=0;i++)
5010 vtop[i] = vtop[i+1];
5011 vtop[0] = tmp;
5014 /* rotate n first stack elements to the top
5015 I1 ... In -> In I1 ... I(n-1) [top is right]
5017 void vrott(int n)
5019 int i;
5020 SValue tmp;
5022 tmp = vtop[0];
5023 for(i = 0;i < n - 1; i++)
5024 vtop[-i] = vtop[-i - 1];
5025 vtop[-n + 1] = tmp;
5028 #ifdef TCC_TARGET_ARM
5029 /* like vrott but in other direction
5030 In ... I1 -> I(n-1) ... I1 In [top is right]
5032 void vnrott(int n)
5034 int i;
5035 SValue tmp;
5037 tmp = vtop[-n + 1];
5038 for(i = n - 1; i > 0; i--)
5039 vtop[-i] = vtop[-i + 1];
5040 vtop[0] = tmp;
5042 #endif
5044 /* pop stack value */
5045 void vpop(void)
5047 int v;
5048 v = vtop->r & VT_VALMASK;
5049 #ifdef TCC_TARGET_I386
5050 /* for x86, we need to pop the FP stack */
5051 if (v == TREG_ST0 && !nocode_wanted) {
5052 o(0xd9dd); /* fstp %st(1) */
5053 } else
5054 #endif
5055 if (v == VT_JMP || v == VT_JMPI) {
5056 /* need to put correct jump if && or || without test */
5057 gsym(vtop->c.ul);
5059 vtop--;
5062 /* convert stack entry to register and duplicate its value in another
5063 register */
5064 void gv_dup(void)
5066 int rc, t, r, r1;
5067 SValue sv;
5069 t = vtop->type.t;
5070 if ((t & VT_BTYPE) == VT_LLONG) {
5071 lexpand();
5072 gv_dup();
5073 vswap();
5074 vrotb(3);
5075 gv_dup();
5076 vrotb(4);
5077 /* stack: H L L1 H1 */
5078 lbuild(t);
5079 vrotb(3);
5080 vrotb(3);
5081 vswap();
5082 lbuild(t);
5083 vswap();
5084 } else {
5085 /* duplicate value */
5086 rc = RC_INT;
5087 sv.type.t = VT_INT;
5088 if (is_float(t)) {
5089 rc = RC_FLOAT;
5090 sv.type.t = t;
5092 r = gv(rc);
5093 r1 = get_reg(rc);
5094 sv.r = r;
5095 sv.c.ul = 0;
5096 load(r1, &sv); /* move r to r1 */
5097 vdup();
5098 /* duplicates value */
5099 vtop->r = r1;
5103 /* generate CPU independent (unsigned) long long operations */
5104 void gen_opl(int op)
5106 int t, a, b, op1, c, i;
5107 int func;
5108 SValue tmp;
5110 switch(op) {
5111 case '/':
5112 case TOK_PDIV:
5113 func = TOK___divdi3;
5114 goto gen_func;
5115 case TOK_UDIV:
5116 func = TOK___udivdi3;
5117 goto gen_func;
5118 case '%':
5119 func = TOK___moddi3;
5120 goto gen_func;
5121 case TOK_UMOD:
5122 func = TOK___umoddi3;
5123 gen_func:
5124 /* call generic long long function */
5125 vpush_global_sym(&func_old_type, func);
5126 vrott(3);
5127 gfunc_call(2);
5128 vpushi(0);
5129 vtop->r = REG_IRET;
5130 vtop->r2 = REG_LRET;
5131 break;
5132 case '^':
5133 case '&':
5134 case '|':
5135 case '*':
5136 case '+':
5137 case '-':
5138 t = vtop->type.t;
5139 vswap();
5140 lexpand();
5141 vrotb(3);
5142 lexpand();
5143 /* stack: L1 H1 L2 H2 */
5144 tmp = vtop[0];
5145 vtop[0] = vtop[-3];
5146 vtop[-3] = tmp;
5147 tmp = vtop[-2];
5148 vtop[-2] = vtop[-3];
5149 vtop[-3] = tmp;
5150 vswap();
5151 /* stack: H1 H2 L1 L2 */
5152 if (op == '*') {
5153 vpushv(vtop - 1);
5154 vpushv(vtop - 1);
5155 gen_op(TOK_UMULL);
5156 lexpand();
5157 /* stack: H1 H2 L1 L2 ML MH */
5158 for(i=0;i<4;i++)
5159 vrotb(6);
5160 /* stack: ML MH H1 H2 L1 L2 */
5161 tmp = vtop[0];
5162 vtop[0] = vtop[-2];
5163 vtop[-2] = tmp;
5164 /* stack: ML MH H1 L2 H2 L1 */
5165 gen_op('*');
5166 vrotb(3);
5167 vrotb(3);
5168 gen_op('*');
5169 /* stack: ML MH M1 M2 */
5170 gen_op('+');
5171 gen_op('+');
5172 } else if (op == '+' || op == '-') {
5173 /* XXX: add non carry method too (for MIPS or alpha) */
5174 if (op == '+')
5175 op1 = TOK_ADDC1;
5176 else
5177 op1 = TOK_SUBC1;
5178 gen_op(op1);
5179 /* stack: H1 H2 (L1 op L2) */
5180 vrotb(3);
5181 vrotb(3);
5182 gen_op(op1 + 1); /* TOK_xxxC2 */
5183 } else {
5184 gen_op(op);
5185 /* stack: H1 H2 (L1 op L2) */
5186 vrotb(3);
5187 vrotb(3);
5188 /* stack: (L1 op L2) H1 H2 */
5189 gen_op(op);
5190 /* stack: (L1 op L2) (H1 op H2) */
5192 /* stack: L H */
5193 lbuild(t);
5194 break;
5195 case TOK_SAR:
5196 case TOK_SHR:
5197 case TOK_SHL:
5198 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5199 t = vtop[-1].type.t;
5200 vswap();
5201 lexpand();
5202 vrotb(3);
5203 /* stack: L H shift */
5204 c = (int)vtop->c.i;
5205 /* constant: simpler */
5206 /* NOTE: all comments are for SHL. the other cases are
5207 done by swaping words */
5208 vpop();
5209 if (op != TOK_SHL)
5210 vswap();
5211 if (c >= 32) {
5212 /* stack: L H */
5213 vpop();
5214 if (c > 32) {
5215 vpushi(c - 32);
5216 gen_op(op);
5218 if (op != TOK_SAR) {
5219 vpushi(0);
5220 } else {
5221 gv_dup();
5222 vpushi(31);
5223 gen_op(TOK_SAR);
5225 vswap();
5226 } else {
5227 vswap();
5228 gv_dup();
5229 /* stack: H L L */
5230 vpushi(c);
5231 gen_op(op);
5232 vswap();
5233 vpushi(32 - c);
5234 if (op == TOK_SHL)
5235 gen_op(TOK_SHR);
5236 else
5237 gen_op(TOK_SHL);
5238 vrotb(3);
5239 /* stack: L L H */
5240 vpushi(c);
5241 if (op == TOK_SHL)
5242 gen_op(TOK_SHL);
5243 else
5244 gen_op(TOK_SHR);
5245 gen_op('|');
5247 if (op != TOK_SHL)
5248 vswap();
5249 lbuild(t);
5250 } else {
5251 /* XXX: should provide a faster fallback on x86 ? */
5252 switch(op) {
5253 case TOK_SAR:
5254 func = TOK___sardi3;
5255 goto gen_func;
5256 case TOK_SHR:
5257 func = TOK___shrdi3;
5258 goto gen_func;
5259 case TOK_SHL:
5260 func = TOK___shldi3;
5261 goto gen_func;
5264 break;
5265 default:
5266 /* compare operations */
5267 t = vtop->type.t;
5268 vswap();
5269 lexpand();
5270 vrotb(3);
5271 lexpand();
5272 /* stack: L1 H1 L2 H2 */
5273 tmp = vtop[-1];
5274 vtop[-1] = vtop[-2];
5275 vtop[-2] = tmp;
5276 /* stack: L1 L2 H1 H2 */
5277 /* compare high */
5278 op1 = op;
5279 /* when values are equal, we need to compare low words. since
5280 the jump is inverted, we invert the test too. */
5281 if (op1 == TOK_LT)
5282 op1 = TOK_LE;
5283 else if (op1 == TOK_GT)
5284 op1 = TOK_GE;
5285 else if (op1 == TOK_ULT)
5286 op1 = TOK_ULE;
5287 else if (op1 == TOK_UGT)
5288 op1 = TOK_UGE;
5289 a = 0;
5290 b = 0;
5291 gen_op(op1);
5292 if (op1 != TOK_NE) {
5293 a = gtst(1, 0);
5295 if (op != TOK_EQ) {
5296 /* generate non equal test */
5297 /* XXX: NOT PORTABLE yet */
5298 if (a == 0) {
5299 b = gtst(0, 0);
5300 } else {
5301 #if defined(TCC_TARGET_I386)
5302 b = psym(0x850f, 0);
5303 #elif defined(TCC_TARGET_ARM)
5304 b = ind;
5305 o(0x1A000000 | encbranch(ind, 0, 1));
5306 #elif defined(TCC_TARGET_C67)
5307 error("not implemented");
5308 #else
5309 #error not supported
5310 #endif
5313 /* compare low. Always unsigned */
5314 op1 = op;
5315 if (op1 == TOK_LT)
5316 op1 = TOK_ULT;
5317 else if (op1 == TOK_LE)
5318 op1 = TOK_ULE;
5319 else if (op1 == TOK_GT)
5320 op1 = TOK_UGT;
5321 else if (op1 == TOK_GE)
5322 op1 = TOK_UGE;
5323 gen_op(op1);
5324 a = gtst(1, a);
5325 gsym(b);
5326 vseti(VT_JMPI, a);
5327 break;
5331 /* handle integer constant optimizations and various machine
5332 independent opt */
5333 void gen_opic(int op)
5335 int c1, c2, t1, t2, n, c;
5336 SValue *v1, *v2;
5337 long long l1, l2, l;
5338 typedef unsigned long long U;
5340 v1 = vtop - 1;
5341 v2 = vtop;
5342 t1 = v1->type.t & VT_BTYPE;
5343 t2 = v2->type.t & VT_BTYPE;
5344 l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i;
5345 l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i;
5347 /* currently, we cannot do computations with forward symbols */
5348 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5349 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5350 if (c1 && c2) {
5351 switch(op) {
5352 case '+': l1 += l2; break;
5353 case '-': l1 -= l2; break;
5354 case '&': l1 &= l2; break;
5355 case '^': l1 ^= l2; break;
5356 case '|': l1 |= l2; break;
5357 case '*': l1 *= l2; break;
5359 case TOK_PDIV:
5360 case '/':
5361 case '%':
5362 case TOK_UDIV:
5363 case TOK_UMOD:
5364 /* if division by zero, generate explicit division */
5365 if (l2 == 0) {
5366 if (const_wanted)
5367 error("division by zero in constant");
5368 goto general_case;
5370 switch(op) {
5371 default: l1 /= l2; break;
5372 case '%': l1 %= l2; break;
5373 case TOK_UDIV: l1 = (U)l1 / l2; break;
5374 case TOK_UMOD: l1 = (U)l1 % l2; break;
5376 break;
5377 case TOK_SHL: l1 <<= l2; break;
5378 case TOK_SHR: l1 = (U)l1 >> l2; break;
5379 case TOK_SAR: l1 >>= l2; break;
5380 /* tests */
5381 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5382 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5383 case TOK_EQ: l1 = l1 == l2; break;
5384 case TOK_NE: l1 = l1 != l2; break;
5385 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5386 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5387 case TOK_LT: l1 = l1 < l2; break;
5388 case TOK_GE: l1 = l1 >= l2; break;
5389 case TOK_LE: l1 = l1 <= l2; break;
5390 case TOK_GT: l1 = l1 > l2; break;
5391 /* logical */
5392 case TOK_LAND: l1 = l1 && l2; break;
5393 case TOK_LOR: l1 = l1 || l2; break;
5394 default:
5395 goto general_case;
5397 v1->c.ll = l1;
5398 vtop--;
5399 } else {
5400 /* if commutative ops, put c2 as constant */
5401 if (c1 && (op == '+' || op == '&' || op == '^' ||
5402 op == '|' || op == '*')) {
5403 vswap();
5404 c = c1, c1 = c2, c2 = c;
5405 l = l1, l1 = l2, l2 = l;
5407 /* Filter out NOP operations like x*1, x-0, x&-1... */
5408 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5409 op == TOK_PDIV) &&
5410 l2 == 1) ||
5411 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5412 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5413 l2 == 0) ||
5414 (op == '&' &&
5415 l2 == -1))) {
5416 /* nothing to do */
5417 vtop--;
5418 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5419 /* try to use shifts instead of muls or divs */
5420 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5421 n = -1;
5422 while (l2) {
5423 l2 >>= 1;
5424 n++;
5426 vtop->c.ll = n;
5427 if (op == '*')
5428 op = TOK_SHL;
5429 else if (op == TOK_PDIV)
5430 op = TOK_SAR;
5431 else
5432 op = TOK_SHR;
5434 goto general_case;
5435 } else if (c2 && (op == '+' || op == '-') &&
5436 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5437 (VT_CONST | VT_SYM)) {
5438 /* symbol + constant case */
5439 if (op == '-')
5440 l2 = -l2;
5441 vtop--;
5442 vtop->c.ll += l2;
5443 } else {
5444 general_case:
5445 if (!nocode_wanted) {
5446 /* call low level op generator */
5447 if (t1 == VT_LLONG || t2 == VT_LLONG)
5448 gen_opl(op);
5449 else
5450 gen_opi(op);
5451 } else {
5452 vtop--;
5458 /* generate a floating point operation with constant propagation */
5459 void gen_opif(int op)
5461 int c1, c2;
5462 SValue *v1, *v2;
5463 long double f1, f2;
5465 v1 = vtop - 1;
5466 v2 = vtop;
5467 /* currently, we cannot do computations with forward symbols */
5468 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5469 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5470 if (c1 && c2) {
5471 if (v1->type.t == VT_FLOAT) {
5472 f1 = v1->c.f;
5473 f2 = v2->c.f;
5474 } else if (v1->type.t == VT_DOUBLE) {
5475 f1 = v1->c.d;
5476 f2 = v2->c.d;
5477 } else {
5478 f1 = v1->c.ld;
5479 f2 = v2->c.ld;
5482 /* NOTE: we only do constant propagation if finite number (not
5483 NaN or infinity) (ANSI spec) */
5484 if (!ieee_finite(f1) || !ieee_finite(f2))
5485 goto general_case;
5487 switch(op) {
5488 case '+': f1 += f2; break;
5489 case '-': f1 -= f2; break;
5490 case '*': f1 *= f2; break;
5491 case '/':
5492 if (f2 == 0.0) {
5493 if (const_wanted)
5494 error("division by zero in constant");
5495 goto general_case;
5497 f1 /= f2;
5498 break;
5499 /* XXX: also handles tests ? */
5500 default:
5501 goto general_case;
5503 /* XXX: overflow test ? */
5504 if (v1->type.t == VT_FLOAT) {
5505 v1->c.f = f1;
5506 } else if (v1->type.t == VT_DOUBLE) {
5507 v1->c.d = f1;
5508 } else {
5509 v1->c.ld = f1;
5511 vtop--;
5512 } else {
5513 general_case:
5514 if (!nocode_wanted) {
5515 gen_opf(op);
5516 } else {
5517 vtop--;
5522 static int pointed_size(CType *type)
5524 int align;
5525 return type_size(pointed_type(type), &align);
5528 static inline int is_null_pointer(SValue *p)
5530 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5531 return 0;
5532 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5533 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5536 static inline int is_integer_btype(int bt)
5538 return (bt == VT_BYTE || bt == VT_SHORT ||
5539 bt == VT_INT || bt == VT_LLONG);
5542 /* check types for comparison or substraction of pointers */
5543 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5545 CType *type1, *type2, tmp_type1, tmp_type2;
5546 int bt1, bt2;
5548 /* null pointers are accepted for all comparisons as gcc */
5549 if (is_null_pointer(p1) || is_null_pointer(p2))
5550 return;
5551 type1 = &p1->type;
5552 type2 = &p2->type;
5553 bt1 = type1->t & VT_BTYPE;
5554 bt2 = type2->t & VT_BTYPE;
5555 /* accept comparison between pointer and integer with a warning */
5556 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5557 if (op != TOK_LOR && op != TOK_LAND )
5558 warning("comparison between pointer and integer");
5559 return;
5562 /* both must be pointers or implicit function pointers */
5563 if (bt1 == VT_PTR) {
5564 type1 = pointed_type(type1);
5565 } else if (bt1 != VT_FUNC)
5566 goto invalid_operands;
5568 if (bt2 == VT_PTR) {
5569 type2 = pointed_type(type2);
5570 } else if (bt2 != VT_FUNC) {
5571 invalid_operands:
5572 error("invalid operands to binary %s", get_tok_str(op, NULL));
5574 if ((type1->t & VT_BTYPE) == VT_VOID ||
5575 (type2->t & VT_BTYPE) == VT_VOID)
5576 return;
5577 tmp_type1 = *type1;
5578 tmp_type2 = *type2;
5579 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5580 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5581 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5582 /* gcc-like error if '-' is used */
5583 if (op == '-')
5584 goto invalid_operands;
5585 else
5586 warning("comparison of distinct pointer types lacks a cast");
5590 /* generic gen_op: handles types problems */
5591 void gen_op(int op)
5593 int u, t1, t2, bt1, bt2, t;
5594 CType type1;
5596 t1 = vtop[-1].type.t;
5597 t2 = vtop[0].type.t;
5598 bt1 = t1 & VT_BTYPE;
5599 bt2 = t2 & VT_BTYPE;
5601 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5602 /* at least one operand is a pointer */
5603 /* relationnal op: must be both pointers */
5604 if (op >= TOK_ULT && op <= TOK_LOR) {
5605 check_comparison_pointer_types(vtop - 1, vtop, op);
5606 /* pointers are handled are unsigned */
5607 t = VT_INT | VT_UNSIGNED;
5608 goto std_op;
5610 /* if both pointers, then it must be the '-' op */
5611 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5612 if (op != '-')
5613 error("cannot use pointers here");
5614 check_comparison_pointer_types(vtop - 1, vtop, op);
5615 /* XXX: check that types are compatible */
5616 u = pointed_size(&vtop[-1].type);
5617 gen_opic(op);
5618 /* set to integer type */
5619 vtop->type.t = VT_INT;
5620 vpushi(u);
5621 gen_op(TOK_PDIV);
5622 } else {
5623 /* exactly one pointer : must be '+' or '-'. */
5624 if (op != '-' && op != '+')
5625 error("cannot use pointers here");
5626 /* Put pointer as first operand */
5627 if (bt2 == VT_PTR) {
5628 vswap();
5629 swap(&t1, &t2);
5631 type1 = vtop[-1].type;
5632 /* XXX: cast to int ? (long long case) */
5633 vpushi(pointed_size(&vtop[-1].type));
5634 gen_op('*');
5635 #ifdef CONFIG_TCC_BCHECK
5636 /* if evaluating constant expression, no code should be
5637 generated, so no bound check */
5638 if (do_bounds_check && !const_wanted) {
5639 /* if bounded pointers, we generate a special code to
5640 test bounds */
5641 if (op == '-') {
5642 vpushi(0);
5643 vswap();
5644 gen_op('-');
5646 gen_bounded_ptr_add();
5647 } else
5648 #endif
5650 gen_opic(op);
5652 /* put again type if gen_opic() swaped operands */
5653 vtop->type = type1;
5655 } else if (is_float(bt1) || is_float(bt2)) {
5656 /* compute bigger type and do implicit casts */
5657 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5658 t = VT_LDOUBLE;
5659 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5660 t = VT_DOUBLE;
5661 } else {
5662 t = VT_FLOAT;
5664 /* floats can only be used for a few operations */
5665 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5666 (op < TOK_ULT || op > TOK_GT))
5667 error("invalid operands for binary operation");
5668 goto std_op;
5669 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5670 /* cast to biggest op */
5671 t = VT_LLONG;
5672 /* convert to unsigned if it does not fit in a long long */
5673 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5674 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5675 t |= VT_UNSIGNED;
5676 goto std_op;
5677 } else {
5678 /* integer operations */
5679 t = VT_INT;
5680 /* convert to unsigned if it does not fit in an integer */
5681 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5682 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5683 t |= VT_UNSIGNED;
5684 std_op:
5685 /* XXX: currently, some unsigned operations are explicit, so
5686 we modify them here */
5687 if (t & VT_UNSIGNED) {
5688 if (op == TOK_SAR)
5689 op = TOK_SHR;
5690 else if (op == '/')
5691 op = TOK_UDIV;
5692 else if (op == '%')
5693 op = TOK_UMOD;
5694 else if (op == TOK_LT)
5695 op = TOK_ULT;
5696 else if (op == TOK_GT)
5697 op = TOK_UGT;
5698 else if (op == TOK_LE)
5699 op = TOK_ULE;
5700 else if (op == TOK_GE)
5701 op = TOK_UGE;
5703 vswap();
5704 type1.t = t;
5705 gen_cast(&type1);
5706 vswap();
5707 /* special case for shifts and long long: we keep the shift as
5708 an integer */
5709 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5710 type1.t = VT_INT;
5711 gen_cast(&type1);
5712 if (is_float(t))
5713 gen_opif(op);
5714 else
5715 gen_opic(op);
5716 if (op >= TOK_ULT && op <= TOK_GT) {
5717 /* relationnal op: the result is an int */
5718 vtop->type.t = VT_INT;
5719 } else {
5720 vtop->type.t = t;
5725 /* generic itof for unsigned long long case */
5726 void gen_cvt_itof1(int t)
5728 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5729 (VT_LLONG | VT_UNSIGNED)) {
5731 if (t == VT_FLOAT)
5732 vpush_global_sym(&func_old_type, TOK___ulltof);
5733 else if (t == VT_DOUBLE)
5734 vpush_global_sym(&func_old_type, TOK___ulltod);
5735 else
5736 vpush_global_sym(&func_old_type, TOK___ulltold);
5737 vrott(2);
5738 gfunc_call(1);
5739 vpushi(0);
5740 vtop->r = REG_FRET;
5741 } else {
5742 gen_cvt_itof(t);
5746 /* generic ftoi for unsigned long long case */
5747 void gen_cvt_ftoi1(int t)
5749 int st;
5751 if (t == (VT_LLONG | VT_UNSIGNED)) {
5752 /* not handled natively */
5753 st = vtop->type.t & VT_BTYPE;
5754 if (st == VT_FLOAT)
5755 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5756 else if (st == VT_DOUBLE)
5757 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5758 else
5759 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5760 vrott(2);
5761 gfunc_call(1);
5762 vpushi(0);
5763 vtop->r = REG_IRET;
5764 vtop->r2 = REG_LRET;
5765 } else {
5766 gen_cvt_ftoi(t);
5770 /* force char or short cast */
5771 void force_charshort_cast(int t)
5773 int bits, dbt;
5774 dbt = t & VT_BTYPE;
5775 /* XXX: add optimization if lvalue : just change type and offset */
5776 if (dbt == VT_BYTE)
5777 bits = 8;
5778 else
5779 bits = 16;
5780 if (t & VT_UNSIGNED) {
5781 vpushi((1 << bits) - 1);
5782 gen_op('&');
5783 } else {
5784 bits = 32 - bits;
5785 vpushi(bits);
5786 gen_op(TOK_SHL);
5787 /* result must be signed or the SAR is converted to an SHL
5788 This was not the case when "t" was a signed short
5789 and the last value on the stack was an unsigned int */
5790 vtop->type.t &= ~VT_UNSIGNED;
5791 vpushi(bits);
5792 gen_op(TOK_SAR);
5796 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5797 static void gen_cast(CType *type)
5799 int sbt, dbt, sf, df, c;
5801 /* special delayed cast for char/short */
5802 /* XXX: in some cases (multiple cascaded casts), it may still
5803 be incorrect */
5804 if (vtop->r & VT_MUSTCAST) {
5805 vtop->r &= ~VT_MUSTCAST;
5806 force_charshort_cast(vtop->type.t);
5809 /* bitfields first get cast to ints */
5810 if (vtop->type.t & VT_BITFIELD) {
5811 gv(RC_INT);
5814 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5815 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5817 if (sbt != dbt && !nocode_wanted) {
5818 sf = is_float(sbt);
5819 df = is_float(dbt);
5820 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5821 if (sf && df) {
5822 /* convert from fp to fp */
5823 if (c) {
5824 /* constant case: we can do it now */
5825 /* XXX: in ISOC, cannot do it if error in convert */
5826 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5827 vtop->c.f = (float)vtop->c.d;
5828 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5829 vtop->c.f = (float)vtop->c.ld;
5830 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5831 vtop->c.d = (double)vtop->c.f;
5832 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5833 vtop->c.d = (double)vtop->c.ld;
5834 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5835 vtop->c.ld = (long double)vtop->c.f;
5836 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5837 vtop->c.ld = (long double)vtop->c.d;
5838 } else {
5839 /* non constant case: generate code */
5840 gen_cvt_ftof(dbt);
5842 } else if (df) {
5843 /* convert int to fp */
5844 if (c) {
5845 switch(sbt) {
5846 case VT_LLONG | VT_UNSIGNED:
5847 case VT_LLONG:
5848 /* XXX: add const cases for long long */
5849 goto do_itof;
5850 case VT_INT | VT_UNSIGNED:
5851 switch(dbt) {
5852 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5853 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5854 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5856 break;
5857 default:
5858 switch(dbt) {
5859 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5860 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5861 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5863 break;
5865 } else {
5866 do_itof:
5867 #if !defined(TCC_TARGET_ARM)
5868 gen_cvt_itof1(dbt);
5869 #else
5870 gen_cvt_itof(dbt);
5871 #endif
5873 } else if (sf) {
5874 /* convert fp to int */
5875 if (dbt == VT_BOOL) {
5876 vpushi(0);
5877 gen_op(TOK_NE);
5878 } else {
5879 /* we handle char/short/etc... with generic code */
5880 if (dbt != (VT_INT | VT_UNSIGNED) &&
5881 dbt != (VT_LLONG | VT_UNSIGNED) &&
5882 dbt != VT_LLONG)
5883 dbt = VT_INT;
5884 if (c) {
5885 switch(dbt) {
5886 case VT_LLONG | VT_UNSIGNED:
5887 case VT_LLONG:
5888 /* XXX: add const cases for long long */
5889 goto do_ftoi;
5890 case VT_INT | VT_UNSIGNED:
5891 switch(sbt) {
5892 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5893 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5894 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5896 break;
5897 default:
5898 /* int case */
5899 switch(sbt) {
5900 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5901 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5902 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5904 break;
5906 } else {
5907 do_ftoi:
5908 gen_cvt_ftoi1(dbt);
5910 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5911 /* additional cast for char/short... */
5912 vtop->type.t = dbt;
5913 gen_cast(type);
5916 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5917 if ((sbt & VT_BTYPE) != VT_LLONG) {
5918 /* scalar to long long */
5919 if (c) {
5920 if (sbt == (VT_INT | VT_UNSIGNED))
5921 vtop->c.ll = vtop->c.ui;
5922 else
5923 vtop->c.ll = vtop->c.i;
5924 } else {
5925 /* machine independent conversion */
5926 gv(RC_INT);
5927 /* generate high word */
5928 if (sbt == (VT_INT | VT_UNSIGNED)) {
5929 vpushi(0);
5930 gv(RC_INT);
5931 } else {
5932 gv_dup();
5933 vpushi(31);
5934 gen_op(TOK_SAR);
5936 /* patch second register */
5937 vtop[-1].r2 = vtop->r;
5938 vpop();
5941 } else if (dbt == VT_BOOL) {
5942 /* scalar to bool */
5943 vpushi(0);
5944 gen_op(TOK_NE);
5945 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5946 (dbt & VT_BTYPE) == VT_SHORT) {
5947 if (sbt == VT_PTR) {
5948 vtop->type.t = VT_INT;
5949 warning("nonportable conversion from pointer to char/short");
5951 force_charshort_cast(dbt);
5952 } else if ((dbt & VT_BTYPE) == VT_INT) {
5953 /* scalar to int */
5954 if (sbt == VT_LLONG) {
5955 /* from long long: just take low order word */
5956 lexpand();
5957 vpop();
5959 /* if lvalue and single word type, nothing to do because
5960 the lvalue already contains the real type size (see
5961 VT_LVAL_xxx constants) */
5963 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
5964 /* if we are casting between pointer types,
5965 we must update the VT_LVAL_xxx size */
5966 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
5967 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
5969 vtop->type = *type;
5972 /* return type size. Put alignment at 'a' */
5973 static int type_size(CType *type, int *a)
5975 Sym *s;
5976 int bt;
5978 bt = type->t & VT_BTYPE;
5979 if (bt == VT_STRUCT) {
5980 /* struct/union */
5981 s = type->ref;
5982 *a = s->r;
5983 return s->c;
5984 } else if (bt == VT_PTR) {
5985 if (type->t & VT_ARRAY) {
5986 s = type->ref;
5987 return type_size(&s->type, a) * s->c;
5988 } else {
5989 *a = PTR_SIZE;
5990 return PTR_SIZE;
5992 } else if (bt == VT_LDOUBLE) {
5993 *a = LDOUBLE_ALIGN;
5994 return LDOUBLE_SIZE;
5995 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5996 #ifdef TCC_TARGET_I386
5997 *a = 4;
5998 #else
5999 *a = 8;
6000 #endif
6001 return 8;
6002 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6003 *a = 4;
6004 return 4;
6005 } else if (bt == VT_SHORT) {
6006 *a = 2;
6007 return 2;
6008 } else {
6009 /* char, void, function, _Bool */
6010 *a = 1;
6011 return 1;
6015 /* return the pointed type of t */
6016 static inline CType *pointed_type(CType *type)
6018 return &type->ref->type;
6021 /* modify type so that its it is a pointer to type. */
6022 static void mk_pointer(CType *type)
6024 Sym *s;
6025 s = sym_push(SYM_FIELD, type, 0, -1);
6026 type->t = VT_PTR | (type->t & ~VT_TYPE);
6027 type->ref = s;
6030 /* compare function types. OLD functions match any new functions */
6031 static int is_compatible_func(CType *type1, CType *type2)
6033 Sym *s1, *s2;
6035 s1 = type1->ref;
6036 s2 = type2->ref;
6037 if (!is_compatible_types(&s1->type, &s2->type))
6038 return 0;
6039 /* check func_call */
6040 if (s1->r != s2->r)
6041 return 0;
6042 /* XXX: not complete */
6043 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6044 return 1;
6045 if (s1->c != s2->c)
6046 return 0;
6047 while (s1 != NULL) {
6048 if (s2 == NULL)
6049 return 0;
6050 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6051 return 0;
6052 s1 = s1->next;
6053 s2 = s2->next;
6055 if (s2)
6056 return 0;
6057 return 1;
6060 /* return true if type1 and type2 are the same. If unqualified is
6061 true, qualifiers on the types are ignored.
6063 - enums are not checked as gcc __builtin_types_compatible_p ()
6065 static int compare_types(CType *type1, CType *type2, int unqualified)
6067 int bt1, t1, t2;
6069 t1 = type1->t & VT_TYPE;
6070 t2 = type2->t & VT_TYPE;
6071 if (unqualified) {
6072 /* strip qualifiers before comparing */
6073 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6074 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6076 /* XXX: bitfields ? */
6077 if (t1 != t2)
6078 return 0;
6079 /* test more complicated cases */
6080 bt1 = t1 & VT_BTYPE;
6081 if (bt1 == VT_PTR) {
6082 type1 = pointed_type(type1);
6083 type2 = pointed_type(type2);
6084 return is_compatible_types(type1, type2);
6085 } else if (bt1 == VT_STRUCT) {
6086 return (type1->ref == type2->ref);
6087 } else if (bt1 == VT_FUNC) {
6088 return is_compatible_func(type1, type2);
6089 } else {
6090 return 1;
6094 /* return true if type1 and type2 are exactly the same (including
6095 qualifiers).
6097 static int is_compatible_types(CType *type1, CType *type2)
6099 return compare_types(type1,type2,0);
6102 /* return true if type1 and type2 are the same (ignoring qualifiers).
6104 static int is_compatible_parameter_types(CType *type1, CType *type2)
6106 return compare_types(type1,type2,1);
6109 /* print a type. If 'varstr' is not NULL, then the variable is also
6110 printed in the type */
6111 /* XXX: union */
6112 /* XXX: add array and function pointers */
6113 void type_to_str(char *buf, int buf_size,
6114 CType *type, const char *varstr)
6116 int bt, v, t;
6117 Sym *s, *sa;
6118 char buf1[256];
6119 const char *tstr;
6121 t = type->t & VT_TYPE;
6122 bt = t & VT_BTYPE;
6123 buf[0] = '\0';
6124 if (t & VT_CONSTANT)
6125 pstrcat(buf, buf_size, "const ");
6126 if (t & VT_VOLATILE)
6127 pstrcat(buf, buf_size, "volatile ");
6128 if (t & VT_UNSIGNED)
6129 pstrcat(buf, buf_size, "unsigned ");
6130 switch(bt) {
6131 case VT_VOID:
6132 tstr = "void";
6133 goto add_tstr;
6134 case VT_BOOL:
6135 tstr = "_Bool";
6136 goto add_tstr;
6137 case VT_BYTE:
6138 tstr = "char";
6139 goto add_tstr;
6140 case VT_SHORT:
6141 tstr = "short";
6142 goto add_tstr;
6143 case VT_INT:
6144 tstr = "int";
6145 goto add_tstr;
6146 case VT_LONG:
6147 tstr = "long";
6148 goto add_tstr;
6149 case VT_LLONG:
6150 tstr = "long long";
6151 goto add_tstr;
6152 case VT_FLOAT:
6153 tstr = "float";
6154 goto add_tstr;
6155 case VT_DOUBLE:
6156 tstr = "double";
6157 goto add_tstr;
6158 case VT_LDOUBLE:
6159 tstr = "long double";
6160 add_tstr:
6161 pstrcat(buf, buf_size, tstr);
6162 break;
6163 case VT_ENUM:
6164 case VT_STRUCT:
6165 if (bt == VT_STRUCT)
6166 tstr = "struct ";
6167 else
6168 tstr = "enum ";
6169 pstrcat(buf, buf_size, tstr);
6170 v = type->ref->v & ~SYM_STRUCT;
6171 if (v >= SYM_FIRST_ANOM)
6172 pstrcat(buf, buf_size, "<anonymous>");
6173 else
6174 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6175 break;
6176 case VT_FUNC:
6177 s = type->ref;
6178 type_to_str(buf, buf_size, &s->type, varstr);
6179 pstrcat(buf, buf_size, "(");
6180 sa = s->next;
6181 while (sa != NULL) {
6182 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6183 pstrcat(buf, buf_size, buf1);
6184 sa = sa->next;
6185 if (sa)
6186 pstrcat(buf, buf_size, ", ");
6188 pstrcat(buf, buf_size, ")");
6189 goto no_var;
6190 case VT_PTR:
6191 s = type->ref;
6192 pstrcpy(buf1, sizeof(buf1), "*");
6193 if (varstr)
6194 pstrcat(buf1, sizeof(buf1), varstr);
6195 type_to_str(buf, buf_size, &s->type, buf1);
6196 goto no_var;
6198 if (varstr) {
6199 pstrcat(buf, buf_size, " ");
6200 pstrcat(buf, buf_size, varstr);
6202 no_var: ;
6205 /* verify type compatibility to store vtop in 'dt' type, and generate
6206 casts if needed. */
6207 static void gen_assign_cast(CType *dt)
6209 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6210 char buf1[256], buf2[256];
6211 int dbt, sbt;
6213 st = &vtop->type; /* source type */
6214 dbt = dt->t & VT_BTYPE;
6215 sbt = st->t & VT_BTYPE;
6216 if (dt->t & VT_CONSTANT)
6217 warning("assignment of read-only location");
6218 switch(dbt) {
6219 case VT_PTR:
6220 /* special cases for pointers */
6221 /* '0' can also be a pointer */
6222 if (is_null_pointer(vtop))
6223 goto type_ok;
6224 /* accept implicit pointer to integer cast with warning */
6225 if (is_integer_btype(sbt)) {
6226 warning("assignment makes pointer from integer without a cast");
6227 goto type_ok;
6229 type1 = pointed_type(dt);
6230 /* a function is implicitely a function pointer */
6231 if (sbt == VT_FUNC) {
6232 if ((type1->t & VT_BTYPE) != VT_VOID &&
6233 !is_compatible_types(pointed_type(dt), st))
6234 goto error;
6235 else
6236 goto type_ok;
6238 if (sbt != VT_PTR)
6239 goto error;
6240 type2 = pointed_type(st);
6241 if ((type1->t & VT_BTYPE) == VT_VOID ||
6242 (type2->t & VT_BTYPE) == VT_VOID) {
6243 /* void * can match anything */
6244 } else {
6245 /* exact type match, except for unsigned */
6246 tmp_type1 = *type1;
6247 tmp_type2 = *type2;
6248 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6249 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6250 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6251 warning("assignment from incompatible pointer type");
6253 /* check const and volatile */
6254 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6255 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6256 warning("assignment discards qualifiers from pointer target type");
6257 break;
6258 case VT_BYTE:
6259 case VT_SHORT:
6260 case VT_INT:
6261 case VT_LLONG:
6262 if (sbt == VT_PTR || sbt == VT_FUNC) {
6263 warning("assignment makes integer from pointer without a cast");
6265 /* XXX: more tests */
6266 break;
6267 case VT_STRUCT:
6268 tmp_type1 = *dt;
6269 tmp_type2 = *st;
6270 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6271 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6272 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6273 error:
6274 type_to_str(buf1, sizeof(buf1), st, NULL);
6275 type_to_str(buf2, sizeof(buf2), dt, NULL);
6276 error("cannot cast '%s' to '%s'", buf1, buf2);
6278 break;
6280 type_ok:
6281 gen_cast(dt);
6284 /* store vtop in lvalue pushed on stack */
6285 void vstore(void)
6287 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6289 ft = vtop[-1].type.t;
6290 sbt = vtop->type.t & VT_BTYPE;
6291 dbt = ft & VT_BTYPE;
6292 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6293 (sbt == VT_INT && dbt == VT_SHORT)) {
6294 /* optimize char/short casts */
6295 delayed_cast = VT_MUSTCAST;
6296 vtop->type.t = ft & VT_TYPE;
6297 /* XXX: factorize */
6298 if (ft & VT_CONSTANT)
6299 warning("assignment of read-only location");
6300 } else {
6301 delayed_cast = 0;
6302 if (!(ft & VT_BITFIELD))
6303 gen_assign_cast(&vtop[-1].type);
6306 if (sbt == VT_STRUCT) {
6307 /* if structure, only generate pointer */
6308 /* structure assignment : generate memcpy */
6309 /* XXX: optimize if small size */
6310 if (!nocode_wanted) {
6311 size = type_size(&vtop->type, &align);
6313 vpush_global_sym(&func_old_type, TOK_memcpy);
6315 /* destination */
6316 vpushv(vtop - 2);
6317 vtop->type.t = VT_INT;
6318 gaddrof();
6319 /* source */
6320 vpushv(vtop - 2);
6321 vtop->type.t = VT_INT;
6322 gaddrof();
6323 /* type size */
6324 vpushi(size);
6325 gfunc_call(3);
6327 vswap();
6328 vpop();
6329 } else {
6330 vswap();
6331 vpop();
6333 /* leave source on stack */
6334 } else if (ft & VT_BITFIELD) {
6335 /* bitfield store handling */
6336 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6337 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6338 /* remove bit field info to avoid loops */
6339 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6341 /* duplicate source into other register */
6342 gv_dup();
6343 vswap();
6344 vrott(3);
6346 /* duplicate destination */
6347 vdup();
6348 vtop[-1] = vtop[-2];
6350 /* mask and shift source */
6351 vpushi((1 << bit_size) - 1);
6352 gen_op('&');
6353 vpushi(bit_pos);
6354 gen_op(TOK_SHL);
6355 /* load destination, mask and or with source */
6356 vswap();
6357 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6358 gen_op('&');
6359 gen_op('|');
6360 /* store result */
6361 vstore();
6363 /* pop off shifted source from "duplicate source..." above */
6364 vpop();
6366 } else {
6367 #ifdef CONFIG_TCC_BCHECK
6368 /* bound check case */
6369 if (vtop[-1].r & VT_MUSTBOUND) {
6370 vswap();
6371 gbound();
6372 vswap();
6374 #endif
6375 if (!nocode_wanted) {
6376 rc = RC_INT;
6377 if (is_float(ft))
6378 rc = RC_FLOAT;
6379 r = gv(rc); /* generate value */
6380 /* if lvalue was saved on stack, must read it */
6381 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6382 SValue sv;
6383 t = get_reg(RC_INT);
6384 sv.type.t = VT_INT;
6385 sv.r = VT_LOCAL | VT_LVAL;
6386 sv.c.ul = vtop[-1].c.ul;
6387 load(t, &sv);
6388 vtop[-1].r = t | VT_LVAL;
6390 store(r, vtop - 1);
6391 /* two word case handling : store second register at word + 4 */
6392 if ((ft & VT_BTYPE) == VT_LLONG) {
6393 vswap();
6394 /* convert to int to increment easily */
6395 vtop->type.t = VT_INT;
6396 gaddrof();
6397 vpushi(4);
6398 gen_op('+');
6399 vtop->r |= VT_LVAL;
6400 vswap();
6401 /* XXX: it works because r2 is spilled last ! */
6402 store(vtop->r2, vtop - 1);
6405 vswap();
6406 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6407 vtop->r |= delayed_cast;
6411 /* post defines POST/PRE add. c is the token ++ or -- */
6412 void inc(int post, int c)
6414 test_lvalue();
6415 vdup(); /* save lvalue */
6416 if (post) {
6417 gv_dup(); /* duplicate value */
6418 vrotb(3);
6419 vrotb(3);
6421 /* add constant */
6422 vpushi(c - TOK_MID);
6423 gen_op('+');
6424 vstore(); /* store value */
6425 if (post)
6426 vpop(); /* if post op, return saved value */
6429 /* Parse GNUC __attribute__ extension. Currently, the following
6430 extensions are recognized:
6431 - aligned(n) : set data/function alignment.
6432 - packed : force data alignment to 1
6433 - section(x) : generate data/code in this section.
6434 - unused : currently ignored, but may be used someday.
6435 - regparm(n) : pass function parameters in registers (i386 only)
6437 static void parse_attribute(AttributeDef *ad)
6439 int t, n;
6441 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6442 next();
6443 skip('(');
6444 skip('(');
6445 while (tok != ')') {
6446 if (tok < TOK_IDENT)
6447 expect("attribute name");
6448 t = tok;
6449 next();
6450 switch(t) {
6451 case TOK_SECTION1:
6452 case TOK_SECTION2:
6453 skip('(');
6454 if (tok != TOK_STR)
6455 expect("section name");
6456 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6457 next();
6458 skip(')');
6459 break;
6460 case TOK_ALIGNED1:
6461 case TOK_ALIGNED2:
6462 if (tok == '(') {
6463 next();
6464 n = expr_const();
6465 if (n <= 0 || (n & (n - 1)) != 0)
6466 error("alignment must be a positive power of two");
6467 skip(')');
6468 } else {
6469 n = MAX_ALIGN;
6471 ad->aligned = n;
6472 break;
6473 case TOK_PACKED1:
6474 case TOK_PACKED2:
6475 ad->packed = 1;
6476 break;
6477 case TOK_UNUSED1:
6478 case TOK_UNUSED2:
6479 /* currently, no need to handle it because tcc does not
6480 track unused objects */
6481 break;
6482 case TOK_NORETURN1:
6483 case TOK_NORETURN2:
6484 /* currently, no need to handle it because tcc does not
6485 track unused objects */
6486 break;
6487 case TOK_CDECL1:
6488 case TOK_CDECL2:
6489 case TOK_CDECL3:
6490 ad->func_call = FUNC_CDECL;
6491 break;
6492 case TOK_STDCALL1:
6493 case TOK_STDCALL2:
6494 case TOK_STDCALL3:
6495 ad->func_call = FUNC_STDCALL;
6496 break;
6497 #ifdef TCC_TARGET_I386
6498 case TOK_REGPARM1:
6499 case TOK_REGPARM2:
6500 skip('(');
6501 n = expr_const();
6502 if (n > 3)
6503 n = 3;
6504 else if (n < 0)
6505 n = 0;
6506 if (n > 0)
6507 ad->func_call = FUNC_FASTCALL1 + n - 1;
6508 skip(')');
6509 break;
6510 case TOK_FASTCALL1:
6511 case TOK_FASTCALL2:
6512 case TOK_FASTCALL3:
6513 ad->func_call = FUNC_FASTCALLW;
6514 break;
6515 #endif
6516 case TOK_DLLEXPORT:
6517 ad->dllexport = 1;
6518 break;
6519 default:
6520 if (tcc_state->warn_unsupported)
6521 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6522 /* skip parameters */
6523 if (tok == '(') {
6524 int parenthesis = 0;
6525 do {
6526 if (tok == '(')
6527 parenthesis++;
6528 else if (tok == ')')
6529 parenthesis--;
6530 next();
6531 } while (parenthesis && tok != -1);
6533 break;
6535 if (tok != ',')
6536 break;
6537 next();
6539 skip(')');
6540 skip(')');
6544 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6545 static void struct_decl(CType *type, int u)
6547 int a, v, size, align, maxalign, c, offset;
6548 int bit_size, bit_pos, bsize, bt, lbit_pos;
6549 Sym *s, *ss, *ass, **ps;
6550 AttributeDef ad;
6551 CType type1, btype;
6553 a = tok; /* save decl type */
6554 next();
6555 if (tok != '{') {
6556 v = tok;
6557 next();
6558 /* struct already defined ? return it */
6559 if (v < TOK_IDENT)
6560 expect("struct/union/enum name");
6561 s = struct_find(v);
6562 if (s) {
6563 if (s->type.t != a)
6564 error("invalid type");
6565 goto do_decl;
6567 } else {
6568 v = anon_sym++;
6570 type1.t = a;
6571 /* we put an undefined size for struct/union */
6572 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6573 s->r = 0; /* default alignment is zero as gcc */
6574 /* put struct/union/enum name in type */
6575 do_decl:
6576 type->t = u;
6577 type->ref = s;
6579 if (tok == '{') {
6580 next();
6581 if (s->c != -1)
6582 error("struct/union/enum already defined");
6583 /* cannot be empty */
6584 c = 0;
6585 /* non empty enums are not allowed */
6586 if (a == TOK_ENUM) {
6587 for(;;) {
6588 v = tok;
6589 if (v < TOK_UIDENT)
6590 expect("identifier");
6591 next();
6592 if (tok == '=') {
6593 next();
6594 c = expr_const();
6596 /* enum symbols have static storage */
6597 ss = sym_push(v, &int_type, VT_CONST, c);
6598 ss->type.t |= VT_STATIC;
6599 if (tok != ',')
6600 break;
6601 next();
6602 c++;
6603 /* NOTE: we accept a trailing comma */
6604 if (tok == '}')
6605 break;
6607 skip('}');
6608 } else {
6609 maxalign = 1;
6610 ps = &s->next;
6611 bit_pos = 0;
6612 offset = 0;
6613 while (tok != '}') {
6614 parse_btype(&btype, &ad);
6615 while (1) {
6616 bit_size = -1;
6617 v = 0;
6618 type1 = btype;
6619 if (tok != ':') {
6620 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6621 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6622 expect("identifier");
6623 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6624 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6625 error("invalid type for '%s'",
6626 get_tok_str(v, NULL));
6628 if (tok == ':') {
6629 next();
6630 bit_size = expr_const();
6631 /* XXX: handle v = 0 case for messages */
6632 if (bit_size < 0)
6633 error("negative width in bit-field '%s'",
6634 get_tok_str(v, NULL));
6635 if (v && bit_size == 0)
6636 error("zero width for bit-field '%s'",
6637 get_tok_str(v, NULL));
6639 size = type_size(&type1, &align);
6640 if (ad.aligned) {
6641 if (align < ad.aligned)
6642 align = ad.aligned;
6643 } else if (ad.packed) {
6644 align = 1;
6645 } else if (*tcc_state->pack_stack_ptr) {
6646 if (align > *tcc_state->pack_stack_ptr)
6647 align = *tcc_state->pack_stack_ptr;
6649 lbit_pos = 0;
6650 if (bit_size >= 0) {
6651 bt = type1.t & VT_BTYPE;
6652 if (bt != VT_INT &&
6653 bt != VT_BYTE &&
6654 bt != VT_SHORT &&
6655 bt != VT_BOOL &&
6656 bt != VT_ENUM)
6657 error("bitfields must have scalar type");
6658 bsize = size * 8;
6659 if (bit_size > bsize) {
6660 error("width of '%s' exceeds its type",
6661 get_tok_str(v, NULL));
6662 } else if (bit_size == bsize) {
6663 /* no need for bit fields */
6664 bit_pos = 0;
6665 } else if (bit_size == 0) {
6666 /* XXX: what to do if only padding in a
6667 structure ? */
6668 /* zero size: means to pad */
6669 if (bit_pos > 0)
6670 bit_pos = bsize;
6671 } else {
6672 /* we do not have enough room ? */
6673 if ((bit_pos + bit_size) > bsize)
6674 bit_pos = 0;
6675 lbit_pos = bit_pos;
6676 /* XXX: handle LSB first */
6677 type1.t |= VT_BITFIELD |
6678 (bit_pos << VT_STRUCT_SHIFT) |
6679 (bit_size << (VT_STRUCT_SHIFT + 6));
6680 bit_pos += bit_size;
6682 } else {
6683 bit_pos = 0;
6685 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
6686 /* add new memory data only if starting
6687 bit field */
6688 if (lbit_pos == 0) {
6689 if (a == TOK_STRUCT) {
6690 c = (c + align - 1) & -align;
6691 offset = c;
6692 if (size > 0)
6693 c += size;
6694 } else {
6695 offset = 0;
6696 if (size > c)
6697 c = size;
6699 if (align > maxalign)
6700 maxalign = align;
6702 #if 0
6703 printf("add field %s offset=%d",
6704 get_tok_str(v, NULL), offset);
6705 if (type1.t & VT_BITFIELD) {
6706 printf(" pos=%d size=%d",
6707 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6708 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6710 printf("\n");
6711 #endif
6713 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
6714 ass = type1.ref;
6715 while ((ass = ass->next) != NULL) {
6716 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
6717 *ps = ss;
6718 ps = &ss->next;
6720 } else if (v) {
6721 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6722 *ps = ss;
6723 ps = &ss->next;
6725 if (tok == ';' || tok == TOK_EOF)
6726 break;
6727 skip(',');
6729 skip(';');
6731 skip('}');
6732 /* store size and alignment */
6733 s->c = (c + maxalign - 1) & -maxalign;
6734 s->r = maxalign;
6739 /* return 0 if no type declaration. otherwise, return the basic type
6740 and skip it.
6742 static int parse_btype(CType *type, AttributeDef *ad)
6744 int t, u, type_found, typespec_found, typedef_found;
6745 Sym *s;
6746 CType type1;
6748 memset(ad, 0, sizeof(AttributeDef));
6749 type_found = 0;
6750 typespec_found = 0;
6751 typedef_found = 0;
6752 t = 0;
6753 while(1) {
6754 switch(tok) {
6755 case TOK_EXTENSION:
6756 /* currently, we really ignore extension */
6757 next();
6758 continue;
6760 /* basic types */
6761 case TOK_CHAR:
6762 u = VT_BYTE;
6763 basic_type:
6764 next();
6765 basic_type1:
6766 if ((t & VT_BTYPE) != 0)
6767 error("too many basic types");
6768 t |= u;
6769 typespec_found = 1;
6770 break;
6771 case TOK_VOID:
6772 u = VT_VOID;
6773 goto basic_type;
6774 case TOK_SHORT:
6775 u = VT_SHORT;
6776 goto basic_type;
6777 case TOK_INT:
6778 next();
6779 typespec_found = 1;
6780 break;
6781 case TOK_LONG:
6782 next();
6783 if ((t & VT_BTYPE) == VT_DOUBLE) {
6784 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6785 } else if ((t & VT_BTYPE) == VT_LONG) {
6786 t = (t & ~VT_BTYPE) | VT_LLONG;
6787 } else {
6788 u = VT_LONG;
6789 goto basic_type1;
6791 break;
6792 case TOK_BOOL:
6793 u = VT_BOOL;
6794 goto basic_type;
6795 case TOK_FLOAT:
6796 u = VT_FLOAT;
6797 goto basic_type;
6798 case TOK_DOUBLE:
6799 next();
6800 if ((t & VT_BTYPE) == VT_LONG) {
6801 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6802 } else {
6803 u = VT_DOUBLE;
6804 goto basic_type1;
6806 break;
6807 case TOK_ENUM:
6808 struct_decl(&type1, VT_ENUM);
6809 basic_type2:
6810 u = type1.t;
6811 type->ref = type1.ref;
6812 goto basic_type1;
6813 case TOK_STRUCT:
6814 case TOK_UNION:
6815 struct_decl(&type1, VT_STRUCT);
6816 goto basic_type2;
6818 /* type modifiers */
6819 case TOK_CONST1:
6820 case TOK_CONST2:
6821 case TOK_CONST3:
6822 t |= VT_CONSTANT;
6823 next();
6824 break;
6825 case TOK_VOLATILE1:
6826 case TOK_VOLATILE2:
6827 case TOK_VOLATILE3:
6828 t |= VT_VOLATILE;
6829 next();
6830 break;
6831 case TOK_SIGNED1:
6832 case TOK_SIGNED2:
6833 case TOK_SIGNED3:
6834 typespec_found = 1;
6835 t |= VT_SIGNED;
6836 next();
6837 break;
6838 case TOK_REGISTER:
6839 case TOK_AUTO:
6840 case TOK_RESTRICT1:
6841 case TOK_RESTRICT2:
6842 case TOK_RESTRICT3:
6843 next();
6844 break;
6845 case TOK_UNSIGNED:
6846 t |= VT_UNSIGNED;
6847 next();
6848 typespec_found = 1;
6849 break;
6851 /* storage */
6852 case TOK_EXTERN:
6853 t |= VT_EXTERN;
6854 next();
6855 break;
6856 case TOK_STATIC:
6857 t |= VT_STATIC;
6858 next();
6859 break;
6860 case TOK_TYPEDEF:
6861 t |= VT_TYPEDEF;
6862 next();
6863 break;
6864 case TOK_INLINE1:
6865 case TOK_INLINE2:
6866 case TOK_INLINE3:
6867 t |= VT_INLINE;
6868 next();
6869 break;
6871 /* GNUC attribute */
6872 case TOK_ATTRIBUTE1:
6873 case TOK_ATTRIBUTE2:
6874 parse_attribute(ad);
6875 break;
6876 /* GNUC typeof */
6877 case TOK_TYPEOF1:
6878 case TOK_TYPEOF2:
6879 case TOK_TYPEOF3:
6880 next();
6881 parse_expr_type(&type1);
6882 goto basic_type2;
6883 default:
6884 if (typespec_found || typedef_found)
6885 goto the_end;
6886 s = sym_find(tok);
6887 if (!s || !(s->type.t & VT_TYPEDEF))
6888 goto the_end;
6889 typedef_found = 1;
6890 t |= (s->type.t & ~VT_TYPEDEF);
6891 type->ref = s->type.ref;
6892 next();
6893 typespec_found = 1;
6894 break;
6896 type_found = 1;
6898 the_end:
6899 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6900 error("signed and unsigned modifier");
6901 if (tcc_state->char_is_unsigned) {
6902 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6903 t |= VT_UNSIGNED;
6905 t &= ~VT_SIGNED;
6907 /* long is never used as type */
6908 if ((t & VT_BTYPE) == VT_LONG)
6909 t = (t & ~VT_BTYPE) | VT_INT;
6910 type->t = t;
6911 return type_found;
6914 /* convert a function parameter type (array to pointer and function to
6915 function pointer) */
6916 static inline void convert_parameter_type(CType *pt)
6918 /* remove const and volatile qualifiers (XXX: const could be used
6919 to indicate a const function parameter */
6920 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6921 /* array must be transformed to pointer according to ANSI C */
6922 pt->t &= ~VT_ARRAY;
6923 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6924 mk_pointer(pt);
6928 static void post_type(CType *type, AttributeDef *ad)
6930 int n, l, t1;
6931 Sym **plast, *s, *first;
6932 AttributeDef ad1;
6933 CType pt;
6935 if (tok == '(') {
6936 /* function declaration */
6937 next();
6938 l = 0;
6939 first = NULL;
6940 plast = &first;
6941 if (tok != ')') {
6942 for(;;) {
6943 /* read param name and compute offset */
6944 if (l != FUNC_OLD) {
6945 if (!parse_btype(&pt, &ad1)) {
6946 if (l) {
6947 error("invalid type");
6948 } else {
6949 l = FUNC_OLD;
6950 goto old_proto;
6953 l = FUNC_NEW;
6954 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6955 break;
6956 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6957 if ((pt.t & VT_BTYPE) == VT_VOID)
6958 error("parameter declared as void");
6959 } else {
6960 old_proto:
6961 n = tok;
6962 if (n < TOK_UIDENT)
6963 expect("identifier");
6964 pt.t = VT_INT;
6965 next();
6967 convert_parameter_type(&pt);
6968 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6969 *plast = s;
6970 plast = &s->next;
6971 if (tok == ')')
6972 break;
6973 skip(',');
6974 if (l == FUNC_NEW && tok == TOK_DOTS) {
6975 l = FUNC_ELLIPSIS;
6976 next();
6977 break;
6981 /* if no parameters, then old type prototype */
6982 if (l == 0)
6983 l = FUNC_OLD;
6984 skip(')');
6985 t1 = type->t & VT_STORAGE;
6986 /* NOTE: const is ignored in returned type as it has a special
6987 meaning in gcc / C++ */
6988 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6989 post_type(type, ad);
6990 /* we push a anonymous symbol which will contain the function prototype */
6991 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6992 s->next = first;
6993 type->t = t1 | VT_FUNC;
6994 type->ref = s;
6995 } else if (tok == '[') {
6996 /* array definition */
6997 next();
6998 n = -1;
6999 if (tok != ']') {
7000 n = expr_const();
7001 if (n < 0)
7002 error("invalid array size");
7004 skip(']');
7005 /* parse next post type */
7006 t1 = type->t & VT_STORAGE;
7007 type->t &= ~VT_STORAGE;
7008 post_type(type, ad);
7010 /* we push a anonymous symbol which will contain the array
7011 element type */
7012 s = sym_push(SYM_FIELD, type, 0, n);
7013 type->t = t1 | VT_ARRAY | VT_PTR;
7014 type->ref = s;
7018 /* Parse a type declaration (except basic type), and return the type
7019 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7020 expected. 'type' should contain the basic type. 'ad' is the
7021 attribute definition of the basic type. It can be modified by
7022 type_decl().
7024 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7026 Sym *s;
7027 CType type1, *type2;
7028 int qualifiers;
7030 while (tok == '*') {
7031 qualifiers = 0;
7032 redo:
7033 next();
7034 switch(tok) {
7035 case TOK_CONST1:
7036 case TOK_CONST2:
7037 case TOK_CONST3:
7038 qualifiers |= VT_CONSTANT;
7039 goto redo;
7040 case TOK_VOLATILE1:
7041 case TOK_VOLATILE2:
7042 case TOK_VOLATILE3:
7043 qualifiers |= VT_VOLATILE;
7044 goto redo;
7045 case TOK_RESTRICT1:
7046 case TOK_RESTRICT2:
7047 case TOK_RESTRICT3:
7048 goto redo;
7050 mk_pointer(type);
7051 type->t |= qualifiers;
7054 /* XXX: clarify attribute handling */
7055 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7056 parse_attribute(ad);
7058 /* recursive type */
7059 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7060 type1.t = 0; /* XXX: same as int */
7061 if (tok == '(') {
7062 next();
7063 /* XXX: this is not correct to modify 'ad' at this point, but
7064 the syntax is not clear */
7065 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7066 parse_attribute(ad);
7067 type_decl(&type1, ad, v, td);
7068 skip(')');
7069 } else {
7070 /* type identifier */
7071 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7072 *v = tok;
7073 next();
7074 } else {
7075 if (!(td & TYPE_ABSTRACT))
7076 expect("identifier");
7077 *v = 0;
7080 post_type(type, ad);
7081 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7082 parse_attribute(ad);
7083 if (!type1.t)
7084 return;
7085 /* append type at the end of type1 */
7086 type2 = &type1;
7087 for(;;) {
7088 s = type2->ref;
7089 type2 = &s->type;
7090 if (!type2->t) {
7091 *type2 = *type;
7092 break;
7095 *type = type1;
7098 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7099 static int lvalue_type(int t)
7101 int bt, r;
7102 r = VT_LVAL;
7103 bt = t & VT_BTYPE;
7104 if (bt == VT_BYTE || bt == VT_BOOL)
7105 r |= VT_LVAL_BYTE;
7106 else if (bt == VT_SHORT)
7107 r |= VT_LVAL_SHORT;
7108 else
7109 return r;
7110 if (t & VT_UNSIGNED)
7111 r |= VT_LVAL_UNSIGNED;
7112 return r;
7115 /* indirection with full error checking and bound check */
7116 static void indir(void)
7118 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7119 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7120 return;
7121 expect("pointer");
7123 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7124 gv(RC_INT);
7125 vtop->type = *pointed_type(&vtop->type);
7126 /* Arrays and functions are never lvalues */
7127 if (!(vtop->type.t & VT_ARRAY)
7128 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7129 vtop->r |= lvalue_type(vtop->type.t);
7130 /* if bound checking, the referenced pointer must be checked */
7131 if (do_bounds_check)
7132 vtop->r |= VT_MUSTBOUND;
7136 /* pass a parameter to a function and do type checking and casting */
7137 static void gfunc_param_typed(Sym *func, Sym *arg)
7139 int func_type;
7140 CType type;
7142 func_type = func->c;
7143 if (func_type == FUNC_OLD ||
7144 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7145 /* default casting : only need to convert float to double */
7146 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7147 type.t = VT_DOUBLE;
7148 gen_cast(&type);
7150 } else if (arg == NULL) {
7151 error("too many arguments to function");
7152 } else {
7153 type = arg->type;
7154 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7155 gen_assign_cast(&type);
7159 /* parse an expression of the form '(type)' or '(expr)' and return its
7160 type */
7161 static void parse_expr_type(CType *type)
7163 int n;
7164 AttributeDef ad;
7166 skip('(');
7167 if (parse_btype(type, &ad)) {
7168 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7169 } else {
7170 expr_type(type);
7172 skip(')');
7175 static void parse_type(CType *type)
7177 AttributeDef ad;
7178 int n;
7180 if (!parse_btype(type, &ad)) {
7181 expect("type");
7183 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7186 static void vpush_tokc(int t)
7188 CType type;
7189 type.t = t;
7190 vsetc(&type, VT_CONST, &tokc);
7193 static void unary(void)
7195 int n, t, align, size, r;
7196 CType type;
7197 Sym *s;
7198 AttributeDef ad;
7200 /* XXX: GCC 2.95.3 does not generate a table although it should be
7201 better here */
7202 tok_next:
7203 switch(tok) {
7204 case TOK_EXTENSION:
7205 next();
7206 goto tok_next;
7207 case TOK_CINT:
7208 case TOK_CCHAR:
7209 case TOK_LCHAR:
7210 vpushi(tokc.i);
7211 next();
7212 break;
7213 case TOK_CUINT:
7214 vpush_tokc(VT_INT | VT_UNSIGNED);
7215 next();
7216 break;
7217 case TOK_CLLONG:
7218 vpush_tokc(VT_LLONG);
7219 next();
7220 break;
7221 case TOK_CULLONG:
7222 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7223 next();
7224 break;
7225 case TOK_CFLOAT:
7226 vpush_tokc(VT_FLOAT);
7227 next();
7228 break;
7229 case TOK_CDOUBLE:
7230 vpush_tokc(VT_DOUBLE);
7231 next();
7232 break;
7233 case TOK_CLDOUBLE:
7234 vpush_tokc(VT_LDOUBLE);
7235 next();
7236 break;
7237 case TOK___FUNCTION__:
7238 if (!gnu_ext)
7239 goto tok_identifier;
7240 /* fall thru */
7241 case TOK___FUNC__:
7243 void *ptr;
7244 int len;
7245 /* special function name identifier */
7246 len = strlen(funcname) + 1;
7247 /* generate char[len] type */
7248 type.t = VT_BYTE;
7249 mk_pointer(&type);
7250 type.t |= VT_ARRAY;
7251 type.ref->c = len;
7252 vpush_ref(&type, data_section, data_section->data_offset, len);
7253 ptr = section_ptr_add(data_section, len);
7254 memcpy(ptr, funcname, len);
7255 next();
7257 break;
7258 case TOK_LSTR:
7259 #ifdef TCC_TARGET_PE
7260 t = VT_SHORT | VT_UNSIGNED;
7261 #else
7262 t = VT_INT;
7263 #endif
7264 goto str_init;
7265 case TOK_STR:
7266 /* string parsing */
7267 t = VT_BYTE;
7268 str_init:
7269 if (tcc_state->warn_write_strings)
7270 t |= VT_CONSTANT;
7271 type.t = t;
7272 mk_pointer(&type);
7273 type.t |= VT_ARRAY;
7274 memset(&ad, 0, sizeof(AttributeDef));
7275 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7276 break;
7277 case '(':
7278 next();
7279 /* cast ? */
7280 if (parse_btype(&type, &ad)) {
7281 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7282 skip(')');
7283 /* check ISOC99 compound literal */
7284 if (tok == '{') {
7285 /* data is allocated locally by default */
7286 if (global_expr)
7287 r = VT_CONST;
7288 else
7289 r = VT_LOCAL;
7290 /* all except arrays are lvalues */
7291 if (!(type.t & VT_ARRAY))
7292 r |= lvalue_type(type.t);
7293 memset(&ad, 0, sizeof(AttributeDef));
7294 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7295 } else {
7296 unary();
7297 gen_cast(&type);
7299 } else if (tok == '{') {
7300 /* save all registers */
7301 save_regs(0);
7302 /* statement expression : we do not accept break/continue
7303 inside as GCC does */
7304 block(NULL, NULL, NULL, NULL, 0, 1);
7305 skip(')');
7306 } else {
7307 gexpr();
7308 skip(')');
7310 break;
7311 case '*':
7312 next();
7313 unary();
7314 indir();
7315 break;
7316 case '&':
7317 next();
7318 unary();
7319 /* functions names must be treated as function pointers,
7320 except for unary '&' and sizeof. Since we consider that
7321 functions are not lvalues, we only have to handle it
7322 there and in function calls. */
7323 /* arrays can also be used although they are not lvalues */
7324 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7325 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7326 test_lvalue();
7327 mk_pointer(&vtop->type);
7328 gaddrof();
7329 break;
7330 case '!':
7331 next();
7332 unary();
7333 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7334 vtop->c.i = !vtop->c.i;
7335 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7336 vtop->c.i = vtop->c.i ^ 1;
7337 else {
7338 save_regs(1);
7339 vseti(VT_JMP, gtst(1, 0));
7341 break;
7342 case '~':
7343 next();
7344 unary();
7345 vpushi(-1);
7346 gen_op('^');
7347 break;
7348 case '+':
7349 next();
7350 /* in order to force cast, we add zero */
7351 unary();
7352 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7353 error("pointer not accepted for unary plus");
7354 vpushi(0);
7355 gen_op('+');
7356 break;
7357 case TOK_SIZEOF:
7358 case TOK_ALIGNOF1:
7359 case TOK_ALIGNOF2:
7360 t = tok;
7361 next();
7362 if (tok == '(') {
7363 parse_expr_type(&type);
7364 } else {
7365 unary_type(&type);
7367 size = type_size(&type, &align);
7368 if (t == TOK_SIZEOF) {
7369 if (size < 0)
7370 error("sizeof applied to an incomplete type");
7371 vpushi(size);
7372 } else {
7373 vpushi(align);
7375 vtop->type.t |= VT_UNSIGNED;
7376 break;
7378 case TOK_builtin_types_compatible_p:
7380 CType type1, type2;
7381 next();
7382 skip('(');
7383 parse_type(&type1);
7384 skip(',');
7385 parse_type(&type2);
7386 skip(')');
7387 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7388 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7389 vpushi(is_compatible_types(&type1, &type2));
7391 break;
7392 case TOK_builtin_constant_p:
7394 int saved_nocode_wanted, res;
7395 next();
7396 skip('(');
7397 saved_nocode_wanted = nocode_wanted;
7398 nocode_wanted = 1;
7399 gexpr();
7400 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7401 vpop();
7402 nocode_wanted = saved_nocode_wanted;
7403 skip(')');
7404 vpushi(res);
7406 break;
7407 case TOK_INC:
7408 case TOK_DEC:
7409 t = tok;
7410 next();
7411 unary();
7412 inc(0, t);
7413 break;
7414 case '-':
7415 next();
7416 vpushi(0);
7417 unary();
7418 gen_op('-');
7419 break;
7420 case TOK_LAND:
7421 if (!gnu_ext)
7422 goto tok_identifier;
7423 next();
7424 /* allow to take the address of a label */
7425 if (tok < TOK_UIDENT)
7426 expect("label identifier");
7427 s = label_find(tok);
7428 if (!s) {
7429 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7430 } else {
7431 if (s->r == LABEL_DECLARED)
7432 s->r = LABEL_FORWARD;
7434 if (!s->type.t) {
7435 s->type.t = VT_VOID;
7436 mk_pointer(&s->type);
7437 s->type.t |= VT_STATIC;
7439 vset(&s->type, VT_CONST | VT_SYM, 0);
7440 vtop->sym = s;
7441 next();
7442 break;
7443 default:
7444 tok_identifier:
7445 t = tok;
7446 next();
7447 if (t < TOK_UIDENT)
7448 expect("identifier");
7449 s = sym_find(t);
7450 if (!s) {
7451 if (tok != '(')
7452 error("'%s' undeclared", get_tok_str(t, NULL));
7453 /* for simple function calls, we tolerate undeclared
7454 external reference to int() function */
7455 if (tcc_state->warn_implicit_function_declaration)
7456 warning("implicit declaration of function '%s'",
7457 get_tok_str(t, NULL));
7458 s = external_global_sym(t, &func_old_type, 0);
7460 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7461 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7462 /* if referencing an inline function, then we generate a
7463 symbol to it if not already done. It will have the
7464 effect to generate code for it at the end of the
7465 compilation unit. Inline function as always
7466 generated in the text section. */
7467 if (!s->c)
7468 put_extern_sym(s, text_section, 0, 0);
7469 r = VT_SYM | VT_CONST;
7470 } else {
7471 r = s->r;
7473 vset(&s->type, r, s->c);
7474 /* if forward reference, we must point to s */
7475 if (vtop->r & VT_SYM) {
7476 vtop->sym = s;
7477 vtop->c.ul = 0;
7479 break;
7482 /* post operations */
7483 while (1) {
7484 if (tok == TOK_INC || tok == TOK_DEC) {
7485 inc(1, tok);
7486 next();
7487 } else if (tok == '.' || tok == TOK_ARROW) {
7488 /* field */
7489 if (tok == TOK_ARROW)
7490 indir();
7491 test_lvalue();
7492 gaddrof();
7493 next();
7494 /* expect pointer on structure */
7495 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7496 expect("struct or union");
7497 s = vtop->type.ref;
7498 /* find field */
7499 tok |= SYM_FIELD;
7500 while ((s = s->next) != NULL) {
7501 if (s->v == tok)
7502 break;
7504 if (!s)
7505 error("field not found");
7506 /* add field offset to pointer */
7507 vtop->type = char_pointer_type; /* change type to 'char *' */
7508 vpushi(s->c);
7509 gen_op('+');
7510 /* change type to field type, and set to lvalue */
7511 vtop->type = s->type;
7512 /* an array is never an lvalue */
7513 if (!(vtop->type.t & VT_ARRAY)) {
7514 vtop->r |= lvalue_type(vtop->type.t);
7515 /* if bound checking, the referenced pointer must be checked */
7516 if (do_bounds_check)
7517 vtop->r |= VT_MUSTBOUND;
7519 next();
7520 } else if (tok == '[') {
7521 next();
7522 gexpr();
7523 gen_op('+');
7524 indir();
7525 skip(']');
7526 } else if (tok == '(') {
7527 SValue ret;
7528 Sym *sa;
7529 int nb_args;
7531 /* function call */
7532 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7533 /* pointer test (no array accepted) */
7534 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7535 vtop->type = *pointed_type(&vtop->type);
7536 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7537 goto error_func;
7538 } else {
7539 error_func:
7540 expect("function pointer");
7542 } else {
7543 vtop->r &= ~VT_LVAL; /* no lvalue */
7545 /* get return type */
7546 s = vtop->type.ref;
7547 next();
7548 sa = s->next; /* first parameter */
7549 nb_args = 0;
7550 /* compute first implicit argument if a structure is returned */
7551 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7552 /* get some space for the returned structure */
7553 size = type_size(&s->type, &align);
7554 loc = (loc - size) & -align;
7555 ret.type = s->type;
7556 ret.r = VT_LOCAL | VT_LVAL;
7557 /* pass it as 'int' to avoid structure arg passing
7558 problems */
7559 vseti(VT_LOCAL, loc);
7560 ret.c = vtop->c;
7561 nb_args++;
7562 } else {
7563 ret.type = s->type;
7564 ret.r2 = VT_CONST;
7565 /* return in register */
7566 if (is_float(ret.type.t)) {
7567 ret.r = REG_FRET;
7568 } else {
7569 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7570 ret.r2 = REG_LRET;
7571 ret.r = REG_IRET;
7573 ret.c.i = 0;
7575 if (tok != ')') {
7576 for(;;) {
7577 expr_eq();
7578 gfunc_param_typed(s, sa);
7579 nb_args++;
7580 if (sa)
7581 sa = sa->next;
7582 if (tok == ')')
7583 break;
7584 skip(',');
7587 if (sa)
7588 error("too few arguments to function");
7589 skip(')');
7590 if (!nocode_wanted) {
7591 gfunc_call(nb_args);
7592 } else {
7593 vtop -= (nb_args + 1);
7595 /* return value */
7596 vsetc(&ret.type, ret.r, &ret.c);
7597 vtop->r2 = ret.r2;
7598 } else {
7599 break;
7604 static void uneq(void)
7606 int t;
7608 unary();
7609 if (tok == '=' ||
7610 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7611 tok == TOK_A_XOR || tok == TOK_A_OR ||
7612 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7613 test_lvalue();
7614 t = tok;
7615 next();
7616 if (t == '=') {
7617 expr_eq();
7618 } else {
7619 vdup();
7620 expr_eq();
7621 gen_op(t & 0x7f);
7623 vstore();
7627 static void expr_prod(void)
7629 int t;
7631 uneq();
7632 while (tok == '*' || tok == '/' || tok == '%') {
7633 t = tok;
7634 next();
7635 uneq();
7636 gen_op(t);
7640 static void expr_sum(void)
7642 int t;
7644 expr_prod();
7645 while (tok == '+' || tok == '-') {
7646 t = tok;
7647 next();
7648 expr_prod();
7649 gen_op(t);
7653 static void expr_shift(void)
7655 int t;
7657 expr_sum();
7658 while (tok == TOK_SHL || tok == TOK_SAR) {
7659 t = tok;
7660 next();
7661 expr_sum();
7662 gen_op(t);
7666 static void expr_cmp(void)
7668 int t;
7670 expr_shift();
7671 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7672 tok == TOK_ULT || tok == TOK_UGE) {
7673 t = tok;
7674 next();
7675 expr_shift();
7676 gen_op(t);
7680 static void expr_cmpeq(void)
7682 int t;
7684 expr_cmp();
7685 while (tok == TOK_EQ || tok == TOK_NE) {
7686 t = tok;
7687 next();
7688 expr_cmp();
7689 gen_op(t);
7693 static void expr_and(void)
7695 expr_cmpeq();
7696 while (tok == '&') {
7697 next();
7698 expr_cmpeq();
7699 gen_op('&');
7703 static void expr_xor(void)
7705 expr_and();
7706 while (tok == '^') {
7707 next();
7708 expr_and();
7709 gen_op('^');
7713 static void expr_or(void)
7715 expr_xor();
7716 while (tok == '|') {
7717 next();
7718 expr_xor();
7719 gen_op('|');
7723 /* XXX: fix this mess */
7724 static void expr_land_const(void)
7726 expr_or();
7727 while (tok == TOK_LAND) {
7728 next();
7729 expr_or();
7730 gen_op(TOK_LAND);
7734 /* XXX: fix this mess */
7735 static void expr_lor_const(void)
7737 expr_land_const();
7738 while (tok == TOK_LOR) {
7739 next();
7740 expr_land_const();
7741 gen_op(TOK_LOR);
7745 /* only used if non constant */
7746 static void expr_land(void)
7748 int t;
7750 expr_or();
7751 if (tok == TOK_LAND) {
7752 t = 0;
7753 save_regs(1);
7754 for(;;) {
7755 t = gtst(1, t);
7756 if (tok != TOK_LAND) {
7757 vseti(VT_JMPI, t);
7758 break;
7760 next();
7761 expr_or();
7766 static void expr_lor(void)
7768 int t;
7770 expr_land();
7771 if (tok == TOK_LOR) {
7772 t = 0;
7773 save_regs(1);
7774 for(;;) {
7775 t = gtst(0, t);
7776 if (tok != TOK_LOR) {
7777 vseti(VT_JMP, t);
7778 break;
7780 next();
7781 expr_land();
7786 /* XXX: better constant handling */
7787 static void expr_eq(void)
7789 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7790 SValue sv;
7791 CType type, type1, type2;
7793 if (const_wanted) {
7794 int c1, c;
7795 expr_lor_const();
7796 if (tok == '?') {
7797 c = vtop->c.i;
7798 vpop();
7799 next();
7800 if (tok == ':' && gnu_ext) {
7801 c1 = c;
7802 } else {
7803 gexpr();
7804 c1 = vtop->c.i;
7805 vpop();
7807 skip(':');
7808 expr_eq();
7809 if (c)
7810 vtop->c.i = c1;
7812 } else {
7813 expr_lor();
7814 if (tok == '?') {
7815 next();
7816 if (vtop != vstack) {
7817 /* needed to avoid having different registers saved in
7818 each branch */
7819 if (is_float(vtop->type.t))
7820 rc = RC_FLOAT;
7821 else
7822 rc = RC_INT;
7823 gv(rc);
7824 save_regs(1);
7826 if (tok == ':' && gnu_ext) {
7827 gv_dup();
7828 tt = gtst(1, 0);
7829 } else {
7830 tt = gtst(1, 0);
7831 gexpr();
7833 type1 = vtop->type;
7834 sv = *vtop; /* save value to handle it later */
7835 vtop--; /* no vpop so that FP stack is not flushed */
7836 skip(':');
7837 u = gjmp(0);
7838 gsym(tt);
7839 expr_eq();
7840 type2 = vtop->type;
7842 t1 = type1.t;
7843 bt1 = t1 & VT_BTYPE;
7844 t2 = type2.t;
7845 bt2 = t2 & VT_BTYPE;
7846 /* cast operands to correct type according to ISOC rules */
7847 if (is_float(bt1) || is_float(bt2)) {
7848 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7849 type.t = VT_LDOUBLE;
7850 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7851 type.t = VT_DOUBLE;
7852 } else {
7853 type.t = VT_FLOAT;
7855 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7856 /* cast to biggest op */
7857 type.t = VT_LLONG;
7858 /* convert to unsigned if it does not fit in a long long */
7859 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7860 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7861 type.t |= VT_UNSIGNED;
7862 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7863 /* XXX: test pointer compatibility */
7864 type = type1;
7865 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
7866 /* XXX: test function pointer compatibility */
7867 type = type1;
7868 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7869 /* XXX: test structure compatibility */
7870 type = type1;
7871 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7872 /* NOTE: as an extension, we accept void on only one side */
7873 type.t = VT_VOID;
7874 } else {
7875 /* integer operations */
7876 type.t = VT_INT;
7877 /* convert to unsigned if it does not fit in an integer */
7878 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7879 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7880 type.t |= VT_UNSIGNED;
7883 /* now we convert second operand */
7884 gen_cast(&type);
7885 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
7886 gaddrof();
7887 rc = RC_INT;
7888 if (is_float(type.t)) {
7889 rc = RC_FLOAT;
7890 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7891 /* for long longs, we use fixed registers to avoid having
7892 to handle a complicated move */
7893 rc = RC_IRET;
7896 r2 = gv(rc);
7897 /* this is horrible, but we must also convert first
7898 operand */
7899 tt = gjmp(0);
7900 gsym(u);
7901 /* put again first value and cast it */
7902 *vtop = sv;
7903 gen_cast(&type);
7904 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
7905 gaddrof();
7906 r1 = gv(rc);
7907 move_reg(r2, r1);
7908 vtop->r = r2;
7909 gsym(tt);
7914 static void gexpr(void)
7916 while (1) {
7917 expr_eq();
7918 if (tok != ',')
7919 break;
7920 vpop();
7921 next();
7925 /* parse an expression and return its type without any side effect. */
7926 static void expr_type(CType *type)
7928 int saved_nocode_wanted;
7930 saved_nocode_wanted = nocode_wanted;
7931 nocode_wanted = 1;
7932 gexpr();
7933 *type = vtop->type;
7934 vpop();
7935 nocode_wanted = saved_nocode_wanted;
7938 /* parse a unary expression and return its type without any side
7939 effect. */
7940 static void unary_type(CType *type)
7942 int a;
7944 a = nocode_wanted;
7945 nocode_wanted = 1;
7946 unary();
7947 *type = vtop->type;
7948 vpop();
7949 nocode_wanted = a;
7952 /* parse a constant expression and return value in vtop. */
7953 static void expr_const1(void)
7955 int a;
7956 a = const_wanted;
7957 const_wanted = 1;
7958 expr_eq();
7959 const_wanted = a;
7962 /* parse an integer constant and return its value. */
7963 static int expr_const(void)
7965 int c;
7966 expr_const1();
7967 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7968 expect("constant expression");
7969 c = vtop->c.i;
7970 vpop();
7971 return c;
7974 /* return the label token if current token is a label, otherwise
7975 return zero */
7976 static int is_label(void)
7978 int last_tok;
7980 /* fast test first */
7981 if (tok < TOK_UIDENT)
7982 return 0;
7983 /* no need to save tokc because tok is an identifier */
7984 last_tok = tok;
7985 next();
7986 if (tok == ':') {
7987 next();
7988 return last_tok;
7989 } else {
7990 unget_tok(last_tok);
7991 return 0;
7995 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7996 int case_reg, int is_expr)
7998 int a, b, c, d;
7999 Sym *s;
8001 /* generate line number info */
8002 if (do_debug &&
8003 (last_line_num != file->line_num || last_ind != ind)) {
8004 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8005 last_ind = ind;
8006 last_line_num = file->line_num;
8009 if (is_expr) {
8010 /* default return value is (void) */
8011 vpushi(0);
8012 vtop->type.t = VT_VOID;
8015 if (tok == TOK_IF) {
8016 /* if test */
8017 next();
8018 skip('(');
8019 gexpr();
8020 skip(')');
8021 a = gtst(1, 0);
8022 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8023 c = tok;
8024 if (c == TOK_ELSE) {
8025 next();
8026 d = gjmp(0);
8027 gsym(a);
8028 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8029 gsym(d); /* patch else jmp */
8030 } else
8031 gsym(a);
8032 } else if (tok == TOK_WHILE) {
8033 next();
8034 d = ind;
8035 skip('(');
8036 gexpr();
8037 skip(')');
8038 a = gtst(1, 0);
8039 b = 0;
8040 block(&a, &b, case_sym, def_sym, case_reg, 0);
8041 gjmp_addr(d);
8042 gsym(a);
8043 gsym_addr(b, d);
8044 } else if (tok == '{') {
8045 Sym *llabel;
8047 next();
8048 /* record local declaration stack position */
8049 s = local_stack;
8050 llabel = local_label_stack;
8051 /* handle local labels declarations */
8052 if (tok == TOK_LABEL) {
8053 next();
8054 for(;;) {
8055 if (tok < TOK_UIDENT)
8056 expect("label identifier");
8057 label_push(&local_label_stack, tok, LABEL_DECLARED);
8058 next();
8059 if (tok == ',') {
8060 next();
8061 } else {
8062 skip(';');
8063 break;
8067 while (tok != '}') {
8068 decl(VT_LOCAL);
8069 if (tok != '}') {
8070 if (is_expr)
8071 vpop();
8072 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8075 /* pop locally defined labels */
8076 label_pop(&local_label_stack, llabel);
8077 /* pop locally defined symbols */
8078 sym_pop(&local_stack, s);
8079 next();
8080 } else if (tok == TOK_RETURN) {
8081 next();
8082 if (tok != ';') {
8083 gexpr();
8084 gen_assign_cast(&func_vt);
8085 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8086 CType type;
8087 /* if returning structure, must copy it to implicit
8088 first pointer arg location */
8089 type = func_vt;
8090 mk_pointer(&type);
8091 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8092 indir();
8093 vswap();
8094 /* copy structure value to pointer */
8095 vstore();
8096 } else if (is_float(func_vt.t)) {
8097 gv(RC_FRET);
8098 } else {
8099 gv(RC_IRET);
8101 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8103 skip(';');
8104 rsym = gjmp(rsym); /* jmp */
8105 } else if (tok == TOK_BREAK) {
8106 /* compute jump */
8107 if (!bsym)
8108 error("cannot break");
8109 *bsym = gjmp(*bsym);
8110 next();
8111 skip(';');
8112 } else if (tok == TOK_CONTINUE) {
8113 /* compute jump */
8114 if (!csym)
8115 error("cannot continue");
8116 *csym = gjmp(*csym);
8117 next();
8118 skip(';');
8119 } else if (tok == TOK_FOR) {
8120 int e;
8121 next();
8122 skip('(');
8123 if (tok != ';') {
8124 gexpr();
8125 vpop();
8127 skip(';');
8128 d = ind;
8129 c = ind;
8130 a = 0;
8131 b = 0;
8132 if (tok != ';') {
8133 gexpr();
8134 a = gtst(1, 0);
8136 skip(';');
8137 if (tok != ')') {
8138 e = gjmp(0);
8139 c = ind;
8140 gexpr();
8141 vpop();
8142 gjmp_addr(d);
8143 gsym(e);
8145 skip(')');
8146 block(&a, &b, case_sym, def_sym, case_reg, 0);
8147 gjmp_addr(c);
8148 gsym(a);
8149 gsym_addr(b, c);
8150 } else
8151 if (tok == TOK_DO) {
8152 next();
8153 a = 0;
8154 b = 0;
8155 d = ind;
8156 block(&a, &b, case_sym, def_sym, case_reg, 0);
8157 skip(TOK_WHILE);
8158 skip('(');
8159 gsym(b);
8160 gexpr();
8161 c = gtst(0, 0);
8162 gsym_addr(c, d);
8163 skip(')');
8164 gsym(a);
8165 skip(';');
8166 } else
8167 if (tok == TOK_SWITCH) {
8168 next();
8169 skip('(');
8170 gexpr();
8171 /* XXX: other types than integer */
8172 case_reg = gv(RC_INT);
8173 vpop();
8174 skip(')');
8175 a = 0;
8176 b = gjmp(0); /* jump to first case */
8177 c = 0;
8178 block(&a, csym, &b, &c, case_reg, 0);
8179 /* if no default, jmp after switch */
8180 if (c == 0)
8181 c = ind;
8182 /* default label */
8183 gsym_addr(b, c);
8184 /* break label */
8185 gsym(a);
8186 } else
8187 if (tok == TOK_CASE) {
8188 int v1, v2;
8189 if (!case_sym)
8190 expect("switch");
8191 /* since a case is like a label, we must skip it with a jmp */
8192 b = gjmp(0);
8193 next_case:
8194 next();
8195 v1 = expr_const();
8196 v2 = v1;
8197 if (gnu_ext && tok == TOK_DOTS) {
8198 next();
8199 v2 = expr_const();
8200 if (v2 < v1)
8201 warning("empty case range");
8203 gsym(*case_sym);
8204 vseti(case_reg, 0);
8205 vpushi(v1);
8206 if (v1 == v2) {
8207 gen_op(TOK_EQ);
8208 *case_sym = 0;
8209 } else {
8210 gen_op(TOK_GE);
8211 *case_sym = gtst(1, 0);
8212 vseti(case_reg, 0);
8213 vpushi(v2);
8214 gen_op(TOK_LE);
8216 skip(':');
8217 if (tok == TOK_CASE) {
8218 b = gtst(0, b);
8219 goto next_case;
8221 *case_sym = gtst(1, *case_sym);
8222 gsym(b);
8223 is_expr = 0;
8224 goto block_after_label;
8225 } else
8226 if (tok == TOK_DEFAULT) {
8227 next();
8228 skip(':');
8229 if (!def_sym)
8230 expect("switch");
8231 if (*def_sym)
8232 error("too many 'default'");
8233 *def_sym = ind;
8234 is_expr = 0;
8235 goto block_after_label;
8236 } else
8237 if (tok == TOK_GOTO) {
8238 next();
8239 if (tok == '*' && gnu_ext) {
8240 /* computed goto */
8241 next();
8242 gexpr();
8243 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8244 expect("pointer");
8245 ggoto();
8246 } else if (tok >= TOK_UIDENT) {
8247 s = label_find(tok);
8248 /* put forward definition if needed */
8249 if (!s) {
8250 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8251 } else {
8252 if (s->r == LABEL_DECLARED)
8253 s->r = LABEL_FORWARD;
8255 /* label already defined */
8256 if (s->r & LABEL_FORWARD)
8257 s->next = (void *)gjmp((long)s->next);
8258 else
8259 gjmp_addr((long)s->next);
8260 next();
8261 } else {
8262 expect("label identifier");
8264 skip(';');
8265 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8266 asm_instr();
8267 } else {
8268 b = is_label();
8269 if (b) {
8270 /* label case */
8271 s = label_find(b);
8272 if (s) {
8273 if (s->r == LABEL_DEFINED)
8274 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8275 gsym((long)s->next);
8276 s->r = LABEL_DEFINED;
8277 } else {
8278 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8280 s->next = (void *)ind;
8281 /* we accept this, but it is a mistake */
8282 block_after_label:
8283 if (tok == '}') {
8284 warning("deprecated use of label at end of compound statement");
8285 } else {
8286 if (is_expr)
8287 vpop();
8288 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8290 } else {
8291 /* expression case */
8292 if (tok != ';') {
8293 if (is_expr) {
8294 vpop();
8295 gexpr();
8296 } else {
8297 gexpr();
8298 vpop();
8301 skip(';');
8306 /* t is the array or struct type. c is the array or struct
8307 address. cur_index/cur_field is the pointer to the current
8308 value. 'size_only' is true if only size info is needed (only used
8309 in arrays) */
8310 static void decl_designator(CType *type, Section *sec, unsigned long c,
8311 int *cur_index, Sym **cur_field,
8312 int size_only)
8314 Sym *s, *f;
8315 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8316 CType type1;
8318 notfirst = 0;
8319 elem_size = 0;
8320 nb_elems = 1;
8321 if (gnu_ext && (l = is_label()) != 0)
8322 goto struct_field;
8323 while (tok == '[' || tok == '.') {
8324 if (tok == '[') {
8325 if (!(type->t & VT_ARRAY))
8326 expect("array type");
8327 s = type->ref;
8328 next();
8329 index = expr_const();
8330 if (index < 0 || (s->c >= 0 && index >= s->c))
8331 expect("invalid index");
8332 if (tok == TOK_DOTS && gnu_ext) {
8333 next();
8334 index_last = expr_const();
8335 if (index_last < 0 ||
8336 (s->c >= 0 && index_last >= s->c) ||
8337 index_last < index)
8338 expect("invalid index");
8339 } else {
8340 index_last = index;
8342 skip(']');
8343 if (!notfirst)
8344 *cur_index = index_last;
8345 type = pointed_type(type);
8346 elem_size = type_size(type, &align);
8347 c += index * elem_size;
8348 /* NOTE: we only support ranges for last designator */
8349 nb_elems = index_last - index + 1;
8350 if (nb_elems != 1) {
8351 notfirst = 1;
8352 break;
8354 } else {
8355 next();
8356 l = tok;
8357 next();
8358 struct_field:
8359 if ((type->t & VT_BTYPE) != VT_STRUCT)
8360 expect("struct/union type");
8361 s = type->ref;
8362 l |= SYM_FIELD;
8363 f = s->next;
8364 while (f) {
8365 if (f->v == l)
8366 break;
8367 f = f->next;
8369 if (!f)
8370 expect("field");
8371 if (!notfirst)
8372 *cur_field = f;
8373 /* XXX: fix this mess by using explicit storage field */
8374 type1 = f->type;
8375 type1.t |= (type->t & ~VT_TYPE);
8376 type = &type1;
8377 c += f->c;
8379 notfirst = 1;
8381 if (notfirst) {
8382 if (tok == '=') {
8383 next();
8384 } else {
8385 if (!gnu_ext)
8386 expect("=");
8388 } else {
8389 if (type->t & VT_ARRAY) {
8390 index = *cur_index;
8391 type = pointed_type(type);
8392 c += index * type_size(type, &align);
8393 } else {
8394 f = *cur_field;
8395 if (!f)
8396 error("too many field init");
8397 /* XXX: fix this mess by using explicit storage field */
8398 type1 = f->type;
8399 type1.t |= (type->t & ~VT_TYPE);
8400 type = &type1;
8401 c += f->c;
8404 decl_initializer(type, sec, c, 0, size_only);
8406 /* XXX: make it more general */
8407 if (!size_only && nb_elems > 1) {
8408 unsigned long c_end;
8409 uint8_t *src, *dst;
8410 int i;
8412 if (!sec)
8413 error("range init not supported yet for dynamic storage");
8414 c_end = c + nb_elems * elem_size;
8415 if (c_end > sec->data_allocated)
8416 section_realloc(sec, c_end);
8417 src = sec->data + c;
8418 dst = src;
8419 for(i = 1; i < nb_elems; i++) {
8420 dst += elem_size;
8421 memcpy(dst, src, elem_size);
8426 #define EXPR_VAL 0
8427 #define EXPR_CONST 1
8428 #define EXPR_ANY 2
8430 /* store a value or an expression directly in global data or in local array */
8431 static void init_putv(CType *type, Section *sec, unsigned long c,
8432 int v, int expr_type)
8434 int saved_global_expr, bt, bit_pos, bit_size;
8435 void *ptr;
8436 unsigned long long bit_mask;
8437 CType dtype;
8439 switch(expr_type) {
8440 case EXPR_VAL:
8441 vpushi(v);
8442 break;
8443 case EXPR_CONST:
8444 /* compound literals must be allocated globally in this case */
8445 saved_global_expr = global_expr;
8446 global_expr = 1;
8447 expr_const1();
8448 global_expr = saved_global_expr;
8449 /* NOTE: symbols are accepted */
8450 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8451 error("initializer element is not constant");
8452 break;
8453 case EXPR_ANY:
8454 expr_eq();
8455 break;
8458 dtype = *type;
8459 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8461 if (sec) {
8462 /* XXX: not portable */
8463 /* XXX: generate error if incorrect relocation */
8464 gen_assign_cast(&dtype);
8465 bt = type->t & VT_BTYPE;
8466 ptr = sec->data + c;
8467 /* XXX: make code faster ? */
8468 if (!(type->t & VT_BITFIELD)) {
8469 bit_pos = 0;
8470 bit_size = 32;
8471 bit_mask = -1LL;
8472 } else {
8473 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8474 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8475 bit_mask = (1LL << bit_size) - 1;
8477 if ((vtop->r & VT_SYM) &&
8478 (bt == VT_BYTE ||
8479 bt == VT_SHORT ||
8480 bt == VT_DOUBLE ||
8481 bt == VT_LDOUBLE ||
8482 bt == VT_LLONG ||
8483 (bt == VT_INT && bit_size != 32)))
8484 error("initializer element is not computable at load time");
8485 switch(bt) {
8486 case VT_BYTE:
8487 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8488 break;
8489 case VT_SHORT:
8490 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8491 break;
8492 case VT_DOUBLE:
8493 *(double *)ptr = vtop->c.d;
8494 break;
8495 case VT_LDOUBLE:
8496 *(long double *)ptr = vtop->c.ld;
8497 break;
8498 case VT_LLONG:
8499 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8500 break;
8501 default:
8502 if (vtop->r & VT_SYM) {
8503 greloc(sec, vtop->sym, c, R_DATA_32);
8505 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8506 break;
8508 vtop--;
8509 } else {
8510 vset(&dtype, VT_LOCAL|VT_LVAL, c);
8511 vswap();
8512 vstore();
8513 vpop();
8517 /* put zeros for variable based init */
8518 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8520 if (sec) {
8521 /* nothing to do because globals are already set to zero */
8522 } else {
8523 vpush_global_sym(&func_old_type, TOK_memset);
8524 vseti(VT_LOCAL, c);
8525 vpushi(0);
8526 vpushi(size);
8527 gfunc_call(3);
8531 /* 't' contains the type and storage info. 'c' is the offset of the
8532 object in section 'sec'. If 'sec' is NULL, it means stack based
8533 allocation. 'first' is true if array '{' must be read (multi
8534 dimension implicit array init handling). 'size_only' is true if
8535 size only evaluation is wanted (only for arrays). */
8536 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8537 int first, int size_only)
8539 int index, array_length, n, no_oblock, nb, parlevel, i;
8540 int size1, align1, expr_type;
8541 Sym *s, *f;
8542 CType *t1;
8544 if (type->t & VT_ARRAY) {
8545 s = type->ref;
8546 n = s->c;
8547 array_length = 0;
8548 t1 = pointed_type(type);
8549 size1 = type_size(t1, &align1);
8551 no_oblock = 1;
8552 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8553 tok == '{') {
8554 skip('{');
8555 no_oblock = 0;
8558 /* only parse strings here if correct type (otherwise: handle
8559 them as ((w)char *) expressions */
8560 if ((tok == TOK_LSTR &&
8561 #ifdef TCC_TARGET_PE
8562 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)) ||
8563 #else
8564 (t1->t & VT_BTYPE) == VT_INT) ||
8565 #endif
8566 (tok == TOK_STR &&
8567 (t1->t & VT_BTYPE) == VT_BYTE)) {
8568 while (tok == TOK_STR || tok == TOK_LSTR) {
8569 int cstr_len, ch;
8570 CString *cstr;
8572 cstr = tokc.cstr;
8573 /* compute maximum number of chars wanted */
8574 if (tok == TOK_STR)
8575 cstr_len = cstr->size;
8576 else
8577 cstr_len = cstr->size / sizeof(nwchar_t);
8578 cstr_len--;
8579 nb = cstr_len;
8580 if (n >= 0 && nb > (n - array_length))
8581 nb = n - array_length;
8582 if (!size_only) {
8583 if (cstr_len > nb)
8584 warning("initializer-string for array is too long");
8585 /* in order to go faster for common case (char
8586 string in global variable, we handle it
8587 specifically */
8588 if (sec && tok == TOK_STR && size1 == 1) {
8589 memcpy(sec->data + c + array_length, cstr->data, nb);
8590 } else {
8591 for(i=0;i<nb;i++) {
8592 if (tok == TOK_STR)
8593 ch = ((unsigned char *)cstr->data)[i];
8594 else
8595 ch = ((nwchar_t *)cstr->data)[i];
8596 init_putv(t1, sec, c + (array_length + i) * size1,
8597 ch, EXPR_VAL);
8601 array_length += nb;
8602 next();
8604 /* only add trailing zero if enough storage (no
8605 warning in this case since it is standard) */
8606 if (n < 0 || array_length < n) {
8607 if (!size_only) {
8608 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8610 array_length++;
8612 } else {
8613 index = 0;
8614 while (tok != '}') {
8615 decl_designator(type, sec, c, &index, NULL, size_only);
8616 if (n >= 0 && index >= n)
8617 error("index too large");
8618 /* must put zero in holes (note that doing it that way
8619 ensures that it even works with designators) */
8620 if (!size_only && array_length < index) {
8621 init_putz(t1, sec, c + array_length * size1,
8622 (index - array_length) * size1);
8624 index++;
8625 if (index > array_length)
8626 array_length = index;
8627 /* special test for multi dimensional arrays (may not
8628 be strictly correct if designators are used at the
8629 same time) */
8630 if (index >= n && no_oblock)
8631 break;
8632 if (tok == '}')
8633 break;
8634 skip(',');
8637 if (!no_oblock)
8638 skip('}');
8639 /* put zeros at the end */
8640 if (!size_only && n >= 0 && array_length < n) {
8641 init_putz(t1, sec, c + array_length * size1,
8642 (n - array_length) * size1);
8644 /* patch type size if needed */
8645 if (n < 0)
8646 s->c = array_length;
8647 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8648 (sec || !first || tok == '{')) {
8649 int par_count;
8651 /* NOTE: the previous test is a specific case for automatic
8652 struct/union init */
8653 /* XXX: union needs only one init */
8655 /* XXX: this test is incorrect for local initializers
8656 beginning with ( without {. It would be much more difficult
8657 to do it correctly (ideally, the expression parser should
8658 be used in all cases) */
8659 par_count = 0;
8660 if (tok == '(') {
8661 AttributeDef ad1;
8662 CType type1;
8663 next();
8664 while (tok == '(') {
8665 par_count++;
8666 next();
8668 if (!parse_btype(&type1, &ad1))
8669 expect("cast");
8670 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8671 #if 0
8672 if (!is_assignable_types(type, &type1))
8673 error("invalid type for cast");
8674 #endif
8675 skip(')');
8677 no_oblock = 1;
8678 if (first || tok == '{') {
8679 skip('{');
8680 no_oblock = 0;
8682 s = type->ref;
8683 f = s->next;
8684 array_length = 0;
8685 index = 0;
8686 n = s->c;
8687 while (tok != '}') {
8688 decl_designator(type, sec, c, NULL, &f, size_only);
8689 index = f->c;
8690 if (!size_only && array_length < index) {
8691 init_putz(type, sec, c + array_length,
8692 index - array_length);
8694 index = index + type_size(&f->type, &align1);
8695 if (index > array_length)
8696 array_length = index;
8697 f = f->next;
8698 if (no_oblock && f == NULL)
8699 break;
8700 if (tok == '}')
8701 break;
8702 skip(',');
8704 /* put zeros at the end */
8705 if (!size_only && array_length < n) {
8706 init_putz(type, sec, c + array_length,
8707 n - array_length);
8709 if (!no_oblock)
8710 skip('}');
8711 while (par_count) {
8712 skip(')');
8713 par_count--;
8715 } else if (tok == '{') {
8716 next();
8717 decl_initializer(type, sec, c, first, size_only);
8718 skip('}');
8719 } else if (size_only) {
8720 /* just skip expression */
8721 parlevel = 0;
8722 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8723 tok != -1) {
8724 if (tok == '(')
8725 parlevel++;
8726 else if (tok == ')')
8727 parlevel--;
8728 next();
8730 } else {
8731 /* currently, we always use constant expression for globals
8732 (may change for scripting case) */
8733 expr_type = EXPR_CONST;
8734 if (!sec)
8735 expr_type = EXPR_ANY;
8736 init_putv(type, sec, c, 0, expr_type);
8740 /* parse an initializer for type 't' if 'has_init' is non zero, and
8741 allocate space in local or global data space ('r' is either
8742 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8743 variable 'v' of scope 'scope' is declared before initializers are
8744 parsed. If 'v' is zero, then a reference to the new object is put
8745 in the value stack. If 'has_init' is 2, a special parsing is done
8746 to handle string constants. */
8747 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8748 int has_init, int v, int scope)
8750 int size, align, addr, data_offset;
8751 int level;
8752 ParseState saved_parse_state;
8753 TokenString init_str;
8754 Section *sec;
8756 size = type_size(type, &align);
8757 /* If unknown size, we must evaluate it before
8758 evaluating initializers because
8759 initializers can generate global data too
8760 (e.g. string pointers or ISOC99 compound
8761 literals). It also simplifies local
8762 initializers handling */
8763 tok_str_new(&init_str);
8764 if (size < 0) {
8765 if (!has_init)
8766 error("unknown type size");
8767 /* get all init string */
8768 if (has_init == 2) {
8769 /* only get strings */
8770 while (tok == TOK_STR || tok == TOK_LSTR) {
8771 tok_str_add_tok(&init_str);
8772 next();
8774 } else {
8775 level = 0;
8776 while (level > 0 || (tok != ',' && tok != ';')) {
8777 if (tok < 0)
8778 error("unexpected end of file in initializer");
8779 tok_str_add_tok(&init_str);
8780 if (tok == '{')
8781 level++;
8782 else if (tok == '}') {
8783 if (level == 0)
8784 break;
8785 level--;
8787 next();
8790 tok_str_add(&init_str, -1);
8791 tok_str_add(&init_str, 0);
8793 /* compute size */
8794 save_parse_state(&saved_parse_state);
8796 macro_ptr = init_str.str;
8797 next();
8798 decl_initializer(type, NULL, 0, 1, 1);
8799 /* prepare second initializer parsing */
8800 macro_ptr = init_str.str;
8801 next();
8803 /* if still unknown size, error */
8804 size = type_size(type, &align);
8805 if (size < 0)
8806 error("unknown type size");
8808 /* take into account specified alignment if bigger */
8809 if (ad->aligned) {
8810 if (ad->aligned > align)
8811 align = ad->aligned;
8812 } else if (ad->packed) {
8813 align = 1;
8815 if ((r & VT_VALMASK) == VT_LOCAL) {
8816 sec = NULL;
8817 if (do_bounds_check && (type->t & VT_ARRAY))
8818 loc--;
8819 loc = (loc - size) & -align;
8820 addr = loc;
8821 /* handles bounds */
8822 /* XXX: currently, since we do only one pass, we cannot track
8823 '&' operators, so we add only arrays */
8824 if (do_bounds_check && (type->t & VT_ARRAY)) {
8825 unsigned long *bounds_ptr;
8826 /* add padding between regions */
8827 loc--;
8828 /* then add local bound info */
8829 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8830 bounds_ptr[0] = addr;
8831 bounds_ptr[1] = size;
8833 if (v) {
8834 /* local variable */
8835 sym_push(v, type, r, addr);
8836 } else {
8837 /* push local reference */
8838 vset(type, r, addr);
8840 } else {
8841 Sym *sym;
8843 sym = NULL;
8844 if (v && scope == VT_CONST) {
8845 /* see if the symbol was already defined */
8846 sym = sym_find(v);
8847 if (sym) {
8848 if (!is_compatible_types(&sym->type, type))
8849 error("incompatible types for redefinition of '%s'",
8850 get_tok_str(v, NULL));
8851 if (sym->type.t & VT_EXTERN) {
8852 /* if the variable is extern, it was not allocated */
8853 sym->type.t &= ~VT_EXTERN;
8854 /* set array size if it was ommited in extern
8855 declaration */
8856 if ((sym->type.t & VT_ARRAY) &&
8857 sym->type.ref->c < 0 &&
8858 type->ref->c >= 0)
8859 sym->type.ref->c = type->ref->c;
8860 } else {
8861 /* we accept several definitions of the same
8862 global variable. this is tricky, because we
8863 must play with the SHN_COMMON type of the symbol */
8864 /* XXX: should check if the variable was already
8865 initialized. It is incorrect to initialized it
8866 twice */
8867 /* no init data, we won't add more to the symbol */
8868 if (!has_init)
8869 goto no_alloc;
8874 /* allocate symbol in corresponding section */
8875 sec = ad->section;
8876 if (!sec) {
8877 if (has_init)
8878 sec = data_section;
8879 else if (tcc_state->nocommon)
8880 sec = bss_section;
8882 if (sec) {
8883 data_offset = sec->data_offset;
8884 data_offset = (data_offset + align - 1) & -align;
8885 addr = data_offset;
8886 /* very important to increment global pointer at this time
8887 because initializers themselves can create new initializers */
8888 data_offset += size;
8889 /* add padding if bound check */
8890 if (do_bounds_check)
8891 data_offset++;
8892 sec->data_offset = data_offset;
8893 /* allocate section space to put the data */
8894 if (sec->sh_type != SHT_NOBITS &&
8895 data_offset > sec->data_allocated)
8896 section_realloc(sec, data_offset);
8897 /* align section if needed */
8898 if (align > sec->sh_addralign)
8899 sec->sh_addralign = align;
8900 } else {
8901 addr = 0; /* avoid warning */
8904 if (v) {
8905 if (scope != VT_CONST || !sym) {
8906 sym = sym_push(v, type, r | VT_SYM, 0);
8908 /* update symbol definition */
8909 if (sec) {
8910 put_extern_sym(sym, sec, addr, size);
8911 } else {
8912 Elf32_Sym *esym;
8913 /* put a common area */
8914 put_extern_sym(sym, NULL, align, size);
8915 /* XXX: find a nicer way */
8916 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8917 esym->st_shndx = SHN_COMMON;
8919 } else {
8920 CValue cval;
8922 /* push global reference */
8923 sym = get_sym_ref(type, sec, addr, size);
8924 cval.ul = 0;
8925 vsetc(type, VT_CONST | VT_SYM, &cval);
8926 vtop->sym = sym;
8929 /* handles bounds now because the symbol must be defined
8930 before for the relocation */
8931 if (do_bounds_check) {
8932 unsigned long *bounds_ptr;
8934 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8935 /* then add global bound info */
8936 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8937 bounds_ptr[0] = 0; /* relocated */
8938 bounds_ptr[1] = size;
8941 if (has_init) {
8942 decl_initializer(type, sec, addr, 1, 0);
8943 /* restore parse state if needed */
8944 if (init_str.str) {
8945 tok_str_free(init_str.str);
8946 restore_parse_state(&saved_parse_state);
8949 no_alloc: ;
8952 void put_func_debug(Sym *sym)
8954 char buf[512];
8956 /* stabs info */
8957 /* XXX: we put here a dummy type */
8958 snprintf(buf, sizeof(buf), "%s:%c1",
8959 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8960 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8961 cur_text_section, sym->c);
8962 last_ind = 0;
8963 last_line_num = 0;
8966 /* parse an old style function declaration list */
8967 /* XXX: check multiple parameter */
8968 static void func_decl_list(Sym *func_sym)
8970 AttributeDef ad;
8971 int v;
8972 Sym *s;
8973 CType btype, type;
8975 /* parse each declaration */
8976 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8977 if (!parse_btype(&btype, &ad))
8978 expect("declaration list");
8979 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8980 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8981 tok == ';') {
8982 /* we accept no variable after */
8983 } else {
8984 for(;;) {
8985 type = btype;
8986 type_decl(&type, &ad, &v, TYPE_DIRECT);
8987 /* find parameter in function parameter list */
8988 s = func_sym->next;
8989 while (s != NULL) {
8990 if ((s->v & ~SYM_FIELD) == v)
8991 goto found;
8992 s = s->next;
8994 error("declaration for parameter '%s' but no such parameter",
8995 get_tok_str(v, NULL));
8996 found:
8997 /* check that no storage specifier except 'register' was given */
8998 if (type.t & VT_STORAGE)
8999 error("storage class specified for '%s'", get_tok_str(v, NULL));
9000 convert_parameter_type(&type);
9001 /* we can add the type (NOTE: it could be local to the function) */
9002 s->type = type;
9003 /* accept other parameters */
9004 if (tok == ',')
9005 next();
9006 else
9007 break;
9010 skip(';');
9014 /* parse a function defined by symbol 'sym' and generate its code in
9015 'cur_text_section' */
9016 static void gen_function(Sym *sym)
9018 ind = cur_text_section->data_offset;
9019 /* NOTE: we patch the symbol size later */
9020 put_extern_sym(sym, cur_text_section, ind, 0);
9021 funcname = get_tok_str(sym->v, NULL);
9022 func_ind = ind;
9023 /* put debug symbol */
9024 if (do_debug)
9025 put_func_debug(sym);
9026 /* push a dummy symbol to enable local sym storage */
9027 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9028 gfunc_prolog(&sym->type);
9029 rsym = 0;
9030 block(NULL, NULL, NULL, NULL, 0, 0);
9031 gsym(rsym);
9032 gfunc_epilog();
9033 cur_text_section->data_offset = ind;
9034 label_pop(&global_label_stack, NULL);
9035 sym_pop(&local_stack, NULL); /* reset local stack */
9036 /* end of function */
9037 /* patch symbol size */
9038 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
9039 ind - func_ind;
9040 if (do_debug) {
9041 put_stabn(N_FUN, 0, 0, ind - func_ind);
9043 funcname = ""; /* for safety */
9044 func_vt.t = VT_VOID; /* for safety */
9045 ind = 0; /* for safety */
9048 static void gen_inline_functions(void)
9050 Sym *sym;
9051 CType *type;
9052 int *str, inline_generated;
9054 /* iterate while inline function are referenced */
9055 for(;;) {
9056 inline_generated = 0;
9057 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9058 type = &sym->type;
9059 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9060 (type->t & (VT_STATIC | VT_INLINE)) ==
9061 (VT_STATIC | VT_INLINE) &&
9062 sym->c != 0) {
9063 /* the function was used: generate its code and
9064 convert it to a normal function */
9065 str = (int *)sym->r;
9066 sym->r = VT_SYM | VT_CONST;
9067 type->t &= ~VT_INLINE;
9069 macro_ptr = str;
9070 next();
9071 cur_text_section = text_section;
9072 gen_function(sym);
9073 macro_ptr = NULL; /* fail safe */
9075 tok_str_free(str);
9076 inline_generated = 1;
9079 if (!inline_generated)
9080 break;
9083 /* free all remaining inline function tokens */
9084 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9085 type = &sym->type;
9086 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9087 (type->t & (VT_STATIC | VT_INLINE)) ==
9088 (VT_STATIC | VT_INLINE)) {
9089 str = (int *)sym->r;
9090 tok_str_free(str);
9091 sym->r = 0; /* fail safe */
9096 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9097 static void decl(int l)
9099 int v, has_init, r;
9100 CType type, btype;
9101 Sym *sym;
9102 AttributeDef ad;
9104 while (1) {
9105 if (!parse_btype(&btype, &ad)) {
9106 /* skip redundant ';' */
9107 /* XXX: find more elegant solution */
9108 if (tok == ';') {
9109 next();
9110 continue;
9112 if (l == VT_CONST &&
9113 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9114 /* global asm block */
9115 asm_global_instr();
9116 continue;
9118 /* special test for old K&R protos without explicit int
9119 type. Only accepted when defining global data */
9120 if (l == VT_LOCAL || tok < TOK_DEFINE)
9121 break;
9122 btype.t = VT_INT;
9124 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9125 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9126 tok == ';') {
9127 /* we accept no variable after */
9128 next();
9129 continue;
9131 while (1) { /* iterate thru each declaration */
9132 type = btype;
9133 type_decl(&type, &ad, &v, TYPE_DIRECT);
9134 #if 0
9136 char buf[500];
9137 type_to_str(buf, sizeof(buf), &type, get_tok_str(v, NULL));
9138 printf("type = '%s'\n", buf);
9140 #endif
9141 if ((type.t & VT_BTYPE) == VT_FUNC) {
9142 /* if old style function prototype, we accept a
9143 declaration list */
9144 sym = type.ref;
9145 if (sym->c == FUNC_OLD)
9146 func_decl_list(sym);
9149 if (tok == '{') {
9150 if (l == VT_LOCAL)
9151 error("cannot use local functions");
9152 if ((type.t & VT_BTYPE) != VT_FUNC)
9153 expect("function definition");
9155 /* reject abstract declarators in function definition */
9156 sym = type.ref;
9157 while ((sym = sym->next) != NULL)
9158 if (!(sym->v & ~SYM_FIELD))
9159 expect("identifier");
9161 /* XXX: cannot do better now: convert extern line to static inline */
9162 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9163 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9165 sym = sym_find(v);
9166 if (sym) {
9167 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9168 goto func_error1;
9169 /* specific case: if not func_call defined, we put
9170 the one of the prototype */
9171 /* XXX: should have default value */
9172 if (sym->type.ref->r != FUNC_CDECL &&
9173 type.ref->r == FUNC_CDECL)
9174 type.ref->r = sym->type.ref->r;
9175 if (!is_compatible_types(&sym->type, &type)) {
9176 func_error1:
9177 error("incompatible types for redefinition of '%s'",
9178 get_tok_str(v, NULL));
9180 /* if symbol is already defined, then put complete type */
9181 sym->type = type;
9182 } else {
9183 /* put function symbol */
9184 sym = global_identifier_push(v, type.t, 0);
9185 sym->type.ref = type.ref;
9188 /* static inline functions are just recorded as a kind
9189 of macro. Their code will be emitted at the end of
9190 the compilation unit only if they are used */
9191 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9192 (VT_INLINE | VT_STATIC)) {
9193 TokenString func_str;
9194 int block_level;
9196 tok_str_new(&func_str);
9198 block_level = 0;
9199 for(;;) {
9200 int t;
9201 if (tok == TOK_EOF)
9202 error("unexpected end of file");
9203 tok_str_add_tok(&func_str);
9204 t = tok;
9205 next();
9206 if (t == '{') {
9207 block_level++;
9208 } else if (t == '}') {
9209 block_level--;
9210 if (block_level == 0)
9211 break;
9214 tok_str_add(&func_str, -1);
9215 tok_str_add(&func_str, 0);
9216 sym->r = (int)func_str.str;
9217 } else {
9218 /* compute text section */
9219 cur_text_section = ad.section;
9220 if (!cur_text_section)
9221 cur_text_section = text_section;
9222 sym->r = VT_SYM | VT_CONST;
9223 gen_function(sym);
9224 #ifdef TCC_TARGET_PE
9225 if (ad.dllexport) {
9226 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
9228 #endif
9230 break;
9231 } else {
9232 if (btype.t & VT_TYPEDEF) {
9233 /* save typedefed type */
9234 /* XXX: test storage specifiers ? */
9235 sym = sym_push(v, &type, 0, 0);
9236 sym->type.t |= VT_TYPEDEF;
9237 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9238 /* external function definition */
9239 /* specific case for func_call attribute */
9240 if (ad.func_call)
9241 type.ref->r = ad.func_call;
9242 external_sym(v, &type, 0);
9243 } else {
9244 /* not lvalue if array */
9245 r = 0;
9246 if (!(type.t & VT_ARRAY))
9247 r |= lvalue_type(type.t);
9248 has_init = (tok == '=');
9249 if ((btype.t & VT_EXTERN) ||
9250 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9251 !has_init && l == VT_CONST && type.ref->c < 0)) {
9252 /* external variable */
9253 /* NOTE: as GCC, uninitialized global static
9254 arrays of null size are considered as
9255 extern */
9256 external_sym(v, &type, r);
9257 } else {
9258 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9259 if (type.t & VT_STATIC)
9260 r |= VT_CONST;
9261 else
9262 r |= l;
9263 if (has_init)
9264 next();
9265 decl_initializer_alloc(&type, &ad, r,
9266 has_init, v, l);
9269 if (tok != ',') {
9270 skip(';');
9271 break;
9273 next();
9279 /* better than nothing, but needs extension to handle '-E' option
9280 correctly too */
9281 static void preprocess_init(TCCState *s1)
9283 s1->include_stack_ptr = s1->include_stack;
9284 /* XXX: move that before to avoid having to initialize
9285 file->ifdef_stack_ptr ? */
9286 s1->ifdef_stack_ptr = s1->ifdef_stack;
9287 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9289 /* XXX: not ANSI compliant: bound checking says error */
9290 vtop = vstack - 1;
9291 s1->pack_stack[0] = 0;
9292 s1->pack_stack_ptr = s1->pack_stack;
9295 /* compile the C file opened in 'file'. Return non zero if errors. */
9296 static int tcc_compile(TCCState *s1)
9298 Sym *define_start;
9299 char buf[512];
9300 volatile int section_sym;
9302 #ifdef INC_DEBUG
9303 printf("%s: **** new file\n", file->filename);
9304 #endif
9305 preprocess_init(s1);
9307 funcname = "";
9308 anon_sym = SYM_FIRST_ANOM;
9310 /* file info: full path + filename */
9311 section_sym = 0; /* avoid warning */
9312 if (do_debug) {
9313 section_sym = put_elf_sym(symtab_section, 0, 0,
9314 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9315 text_section->sh_num, NULL);
9316 getcwd(buf, sizeof(buf));
9317 pstrcat(buf, sizeof(buf), "/");
9318 put_stabs_r(buf, N_SO, 0, 0,
9319 text_section->data_offset, text_section, section_sym);
9320 put_stabs_r(file->filename, N_SO, 0, 0,
9321 text_section->data_offset, text_section, section_sym);
9323 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9324 symbols can be safely used */
9325 put_elf_sym(symtab_section, 0, 0,
9326 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9327 SHN_ABS, file->filename);
9329 /* define some often used types */
9330 int_type.t = VT_INT;
9332 char_pointer_type.t = VT_BYTE;
9333 mk_pointer(&char_pointer_type);
9335 func_old_type.t = VT_FUNC;
9336 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9338 #if 0
9339 /* define 'void *alloca(unsigned int)' builtin function */
9341 Sym *s1;
9343 p = anon_sym++;
9344 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9345 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9346 s1->next = NULL;
9347 sym->next = s1;
9348 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9350 #endif
9352 define_start = define_stack;
9354 if (setjmp(s1->error_jmp_buf) == 0) {
9355 s1->nb_errors = 0;
9356 s1->error_set_jmp_enabled = 1;
9358 ch = file->buf_ptr[0];
9359 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9360 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9361 next();
9362 decl(VT_CONST);
9363 if (tok != TOK_EOF)
9364 expect("declaration");
9366 /* end of translation unit info */
9367 if (do_debug) {
9368 put_stabs_r(NULL, N_SO, 0, 0,
9369 text_section->data_offset, text_section, section_sym);
9372 s1->error_set_jmp_enabled = 0;
9374 /* reset define stack, but leave -Dsymbols (may be incorrect if
9375 they are undefined) */
9376 free_defines(define_start);
9378 gen_inline_functions();
9380 sym_pop(&global_stack, NULL);
9382 return s1->nb_errors != 0 ? -1 : 0;
9385 /* Preprocess the current file */
9386 /* XXX: add line and file infos, add options to preserve spaces */
9387 static int tcc_preprocess(TCCState *s1)
9389 Sym *define_start;
9390 int last_is_space;
9392 preprocess_init(s1);
9394 define_start = define_stack;
9396 ch = file->buf_ptr[0];
9397 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9398 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9399 PARSE_FLAG_LINEFEED;
9400 last_is_space = 1;
9401 next();
9402 for(;;) {
9403 if (tok == TOK_EOF)
9404 break;
9405 if (!last_is_space) {
9406 fputc(' ', s1->outfile);
9408 fputs(get_tok_str(tok, &tokc), s1->outfile);
9409 if (tok == TOK_LINEFEED) {
9410 last_is_space = 1;
9411 /* XXX: suppress that hack */
9412 parse_flags &= ~PARSE_FLAG_LINEFEED;
9413 next();
9414 parse_flags |= PARSE_FLAG_LINEFEED;
9415 } else {
9416 last_is_space = 0;
9417 next();
9421 free_defines(define_start);
9423 return 0;
9426 #ifdef LIBTCC
9427 int tcc_compile_string(TCCState *s, const char *str)
9429 BufferedFile bf1, *bf = &bf1;
9430 int ret, len;
9431 char *buf;
9433 /* init file structure */
9434 bf->fd = -1;
9435 /* XXX: avoid copying */
9436 len = strlen(str);
9437 buf = tcc_malloc(len + 1);
9438 if (!buf)
9439 return -1;
9440 memcpy(buf, str, len);
9441 buf[len] = CH_EOB;
9442 bf->buf_ptr = buf;
9443 bf->buf_end = buf + len;
9444 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9445 bf->line_num = 1;
9446 file = bf;
9448 ret = tcc_compile(s);
9450 tcc_free(buf);
9452 /* currently, no need to close */
9453 return ret;
9455 #endif
9457 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9458 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9460 BufferedFile bf1, *bf = &bf1;
9462 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9463 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9464 /* default value */
9465 if (!value)
9466 value = "1";
9467 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9469 /* init file structure */
9470 bf->fd = -1;
9471 bf->buf_ptr = bf->buffer;
9472 bf->buf_end = bf->buffer + strlen(bf->buffer);
9473 *bf->buf_end = CH_EOB;
9474 bf->filename[0] = '\0';
9475 bf->line_num = 1;
9476 file = bf;
9478 s1->include_stack_ptr = s1->include_stack;
9480 /* parse with define parser */
9481 ch = file->buf_ptr[0];
9482 next_nomacro();
9483 parse_define();
9484 file = NULL;
9487 /* undefine a preprocessor symbol */
9488 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9490 TokenSym *ts;
9491 Sym *s;
9492 ts = tok_alloc(sym, strlen(sym));
9493 s = define_find(ts->tok);
9494 /* undefine symbol by putting an invalid name */
9495 if (s)
9496 define_undef(s);
9499 #ifdef CONFIG_TCC_ASM
9501 #ifdef TCC_TARGET_I386
9502 #include "i386-asm.c"
9503 #endif
9504 #include "tccasm.c"
9506 #else
9507 static void asm_instr(void)
9509 error("inline asm() not supported");
9511 static void asm_global_instr(void)
9513 error("inline asm() not supported");
9515 #endif
9517 #include "tccelf.c"
9519 #ifdef TCC_TARGET_COFF
9520 #include "tcccoff.c"
9521 #endif
9523 #ifdef TCC_TARGET_PE
9524 #include "tccpe.c"
9525 #endif
9527 /* print the position in the source file of PC value 'pc' by reading
9528 the stabs debug information */
9529 static void rt_printline(unsigned long wanted_pc)
9531 Stab_Sym *sym, *sym_end;
9532 char func_name[128], last_func_name[128];
9533 unsigned long func_addr, last_pc, pc;
9534 const char *incl_files[INCLUDE_STACK_SIZE];
9535 int incl_index, len, last_line_num, i;
9536 const char *str, *p;
9538 fprintf(stderr, "0x%08lx:", wanted_pc);
9540 func_name[0] = '\0';
9541 func_addr = 0;
9542 incl_index = 0;
9543 last_func_name[0] = '\0';
9544 last_pc = 0xffffffff;
9545 last_line_num = 1;
9546 sym = (Stab_Sym *)stab_section->data + 1;
9547 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9548 while (sym < sym_end) {
9549 switch(sym->n_type) {
9550 /* function start or end */
9551 case N_FUN:
9552 if (sym->n_strx == 0) {
9553 /* we test if between last line and end of function */
9554 pc = sym->n_value + func_addr;
9555 if (wanted_pc >= last_pc && wanted_pc < pc)
9556 goto found;
9557 func_name[0] = '\0';
9558 func_addr = 0;
9559 } else {
9560 str = stabstr_section->data + sym->n_strx;
9561 p = strchr(str, ':');
9562 if (!p) {
9563 pstrcpy(func_name, sizeof(func_name), str);
9564 } else {
9565 len = p - str;
9566 if (len > sizeof(func_name) - 1)
9567 len = sizeof(func_name) - 1;
9568 memcpy(func_name, str, len);
9569 func_name[len] = '\0';
9571 func_addr = sym->n_value;
9573 break;
9574 /* line number info */
9575 case N_SLINE:
9576 pc = sym->n_value + func_addr;
9577 if (wanted_pc >= last_pc && wanted_pc < pc)
9578 goto found;
9579 last_pc = pc;
9580 last_line_num = sym->n_desc;
9581 /* XXX: slow! */
9582 strcpy(last_func_name, func_name);
9583 break;
9584 /* include files */
9585 case N_BINCL:
9586 str = stabstr_section->data + sym->n_strx;
9587 add_incl:
9588 if (incl_index < INCLUDE_STACK_SIZE) {
9589 incl_files[incl_index++] = str;
9591 break;
9592 case N_EINCL:
9593 if (incl_index > 1)
9594 incl_index--;
9595 break;
9596 case N_SO:
9597 if (sym->n_strx == 0) {
9598 incl_index = 0; /* end of translation unit */
9599 } else {
9600 str = stabstr_section->data + sym->n_strx;
9601 /* do not add path */
9602 len = strlen(str);
9603 if (len > 0 && str[len - 1] != '/')
9604 goto add_incl;
9606 break;
9608 sym++;
9611 /* second pass: we try symtab symbols (no line number info) */
9612 incl_index = 0;
9614 Elf32_Sym *sym, *sym_end;
9615 int type;
9617 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9618 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9619 sym < sym_end;
9620 sym++) {
9621 type = ELF32_ST_TYPE(sym->st_info);
9622 if (type == STT_FUNC) {
9623 if (wanted_pc >= sym->st_value &&
9624 wanted_pc < sym->st_value + sym->st_size) {
9625 pstrcpy(last_func_name, sizeof(last_func_name),
9626 strtab_section->data + sym->st_name);
9627 goto found;
9632 /* did not find any info: */
9633 fprintf(stderr, " ???\n");
9634 return;
9635 found:
9636 if (last_func_name[0] != '\0') {
9637 fprintf(stderr, " %s()", last_func_name);
9639 if (incl_index > 0) {
9640 fprintf(stderr, " (%s:%d",
9641 incl_files[incl_index - 1], last_line_num);
9642 for(i = incl_index - 2; i >= 0; i--)
9643 fprintf(stderr, ", included from %s", incl_files[i]);
9644 fprintf(stderr, ")");
9646 fprintf(stderr, "\n");
9649 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9651 #ifdef __i386__
9653 /* fix for glibc 2.1 */
9654 #ifndef REG_EIP
9655 #define REG_EIP EIP
9656 #define REG_EBP EBP
9657 #endif
9659 /* return the PC at frame level 'level'. Return non zero if not found */
9660 static int rt_get_caller_pc(unsigned long *paddr,
9661 ucontext_t *uc, int level)
9663 unsigned long fp;
9664 int i;
9666 if (level == 0) {
9667 #if defined(__FreeBSD__)
9668 *paddr = uc->uc_mcontext.mc_eip;
9669 #elif defined(__dietlibc__)
9670 *paddr = uc->uc_mcontext.eip;
9671 #else
9672 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9673 #endif
9674 return 0;
9675 } else {
9676 #if defined(__FreeBSD__)
9677 fp = uc->uc_mcontext.mc_ebp;
9678 #elif defined(__dietlibc__)
9679 fp = uc->uc_mcontext.ebp;
9680 #else
9681 fp = uc->uc_mcontext.gregs[REG_EBP];
9682 #endif
9683 for(i=1;i<level;i++) {
9684 /* XXX: check address validity with program info */
9685 if (fp <= 0x1000 || fp >= 0xc0000000)
9686 return -1;
9687 fp = ((unsigned long *)fp)[0];
9689 *paddr = ((unsigned long *)fp)[1];
9690 return 0;
9693 #else
9695 #warning add arch specific rt_get_caller_pc()
9697 static int rt_get_caller_pc(unsigned long *paddr,
9698 ucontext_t *uc, int level)
9700 return -1;
9702 #endif
9704 /* emit a run time error at position 'pc' */
9705 void rt_error(ucontext_t *uc, const char *fmt, ...)
9707 va_list ap;
9708 unsigned long pc;
9709 int i;
9711 va_start(ap, fmt);
9712 fprintf(stderr, "Runtime error: ");
9713 vfprintf(stderr, fmt, ap);
9714 fprintf(stderr, "\n");
9715 for(i=0;i<num_callers;i++) {
9716 if (rt_get_caller_pc(&pc, uc, i) < 0)
9717 break;
9718 if (i == 0)
9719 fprintf(stderr, "at ");
9720 else
9721 fprintf(stderr, "by ");
9722 rt_printline(pc);
9724 exit(255);
9725 va_end(ap);
9728 /* signal handler for fatal errors */
9729 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9731 ucontext_t *uc = puc;
9733 switch(signum) {
9734 case SIGFPE:
9735 switch(siginf->si_code) {
9736 case FPE_INTDIV:
9737 case FPE_FLTDIV:
9738 rt_error(uc, "division by zero");
9739 break;
9740 default:
9741 rt_error(uc, "floating point exception");
9742 break;
9744 break;
9745 case SIGBUS:
9746 case SIGSEGV:
9747 if (rt_bound_error_msg && *rt_bound_error_msg)
9748 rt_error(uc, *rt_bound_error_msg);
9749 else
9750 rt_error(uc, "dereferencing invalid pointer");
9751 break;
9752 case SIGILL:
9753 rt_error(uc, "illegal instruction");
9754 break;
9755 case SIGABRT:
9756 rt_error(uc, "abort() called");
9757 break;
9758 default:
9759 rt_error(uc, "caught signal %d", signum);
9760 break;
9762 exit(255);
9764 #endif
9766 /* do all relocations (needed before using tcc_get_symbol()) */
9767 int tcc_relocate(TCCState *s1)
9769 Section *s;
9770 int i;
9772 s1->nb_errors = 0;
9774 #ifdef TCC_TARGET_PE
9775 pe_add_runtime(s1);
9776 #else
9777 tcc_add_runtime(s1);
9778 #endif
9780 relocate_common_syms();
9782 tcc_add_linker_symbols(s1);
9784 build_got_entries(s1);
9786 /* compute relocation address : section are relocated in place. We
9787 also alloc the bss space */
9788 for(i = 1; i < s1->nb_sections; i++) {
9789 s = s1->sections[i];
9790 if (s->sh_flags & SHF_ALLOC) {
9791 if (s->sh_type == SHT_NOBITS)
9792 s->data = tcc_mallocz(s->data_offset);
9793 s->sh_addr = (unsigned long)s->data;
9797 relocate_syms(s1, 1);
9799 if (s1->nb_errors != 0)
9800 return -1;
9802 /* relocate each section */
9803 for(i = 1; i < s1->nb_sections; i++) {
9804 s = s1->sections[i];
9805 if (s->reloc)
9806 relocate_section(s1, s);
9809 /* mark executable sections as executable in memory */
9810 for(i = 1; i < s1->nb_sections; i++) {
9811 s = s1->sections[i];
9812 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
9813 (SHF_ALLOC | SHF_EXECINSTR)) {
9814 #ifdef WIN32
9816 unsigned long old_protect;
9817 VirtualProtect(s->data, s->data_offset,
9818 PAGE_EXECUTE_READWRITE, &old_protect);
9820 #else
9822 unsigned long start, end;
9823 start = (unsigned long)(s->data) & ~(PAGESIZE - 1);
9824 end = (unsigned long)(s->data + s->data_offset);
9825 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
9826 mprotect((void *)start, end - start,
9827 PROT_READ | PROT_WRITE | PROT_EXEC);
9829 #endif
9832 return 0;
9835 /* launch the compiled program with the given arguments */
9836 int tcc_run(TCCState *s1, int argc, char **argv)
9838 int (*prog_main)(int, char **);
9840 if (tcc_relocate(s1) < 0)
9841 return -1;
9843 prog_main = tcc_get_symbol_err(s1, "main");
9845 if (do_debug) {
9846 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9847 error("debug mode currently not available for Windows");
9848 #else
9849 struct sigaction sigact;
9850 /* install TCC signal handlers to print debug info on fatal
9851 runtime errors */
9852 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9853 sigact.sa_sigaction = sig_error;
9854 sigemptyset(&sigact.sa_mask);
9855 sigaction(SIGFPE, &sigact, NULL);
9856 sigaction(SIGILL, &sigact, NULL);
9857 sigaction(SIGSEGV, &sigact, NULL);
9858 sigaction(SIGBUS, &sigact, NULL);
9859 sigaction(SIGABRT, &sigact, NULL);
9860 #endif
9863 #ifdef CONFIG_TCC_BCHECK
9864 if (do_bounds_check) {
9865 void (*bound_init)(void);
9867 /* set error function */
9868 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9869 "__bound_error_msg");
9871 /* XXX: use .init section so that it also work in binary ? */
9872 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9873 bound_init();
9875 #endif
9876 return (*prog_main)(argc, argv);
9879 TCCState *tcc_new(void)
9881 const char *p, *r;
9882 TCCState *s;
9883 TokenSym *ts;
9884 int i, c;
9886 s = tcc_mallocz(sizeof(TCCState));
9887 if (!s)
9888 return NULL;
9889 tcc_state = s;
9890 s->output_type = TCC_OUTPUT_MEMORY;
9892 /* init isid table */
9893 for(i=0;i<256;i++)
9894 isidnum_table[i] = isid(i) || isnum(i);
9896 /* add all tokens */
9897 table_ident = NULL;
9898 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9900 tok_ident = TOK_IDENT;
9901 p = tcc_keywords;
9902 while (*p) {
9903 r = p;
9904 for(;;) {
9905 c = *r++;
9906 if (c == '\0')
9907 break;
9909 ts = tok_alloc(p, r - p - 1);
9910 p = r;
9913 /* we add dummy defines for some special macros to speed up tests
9914 and to have working defined() */
9915 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9916 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9917 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9918 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9920 /* standard defines */
9921 tcc_define_symbol(s, "__STDC__", NULL);
9922 #if defined(TCC_TARGET_I386)
9923 tcc_define_symbol(s, "__i386__", NULL);
9924 #endif
9925 #if defined(TCC_TARGET_ARM)
9926 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9927 tcc_define_symbol(s, "__arm_elf__", NULL);
9928 tcc_define_symbol(s, "__arm_elf", NULL);
9929 tcc_define_symbol(s, "arm_elf", NULL);
9930 tcc_define_symbol(s, "__arm__", NULL);
9931 tcc_define_symbol(s, "__arm", NULL);
9932 tcc_define_symbol(s, "arm", NULL);
9933 tcc_define_symbol(s, "__APCS_32__", NULL);
9934 #endif
9935 #if defined(linux)
9936 tcc_define_symbol(s, "__linux__", NULL);
9937 tcc_define_symbol(s, "linux", NULL);
9938 #endif
9939 /* tiny C specific defines */
9940 tcc_define_symbol(s, "__TINYC__", NULL);
9942 /* tiny C & gcc defines */
9943 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9944 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9945 #ifdef TCC_TARGET_PE
9946 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
9947 #else
9948 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9949 #endif
9951 /* default library paths */
9952 #ifdef TCC_TARGET_PE
9954 char buf[1024];
9955 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
9956 tcc_add_library_path(s, buf);
9958 #else
9959 tcc_add_library_path(s, "/usr/local/lib");
9960 tcc_add_library_path(s, "/usr/lib");
9961 tcc_add_library_path(s, "/lib");
9962 #endif
9964 /* no section zero */
9965 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9967 /* create standard sections */
9968 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9969 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9970 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9972 /* symbols are always generated for linking stage */
9973 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9974 ".strtab",
9975 ".hashtab", SHF_PRIVATE);
9976 strtab_section = symtab_section->link;
9978 /* private symbol table for dynamic symbols */
9979 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9980 ".dynstrtab",
9981 ".dynhashtab", SHF_PRIVATE);
9982 s->alacarte_link = 1;
9984 #ifdef CHAR_IS_UNSIGNED
9985 s->char_is_unsigned = 1;
9986 #endif
9987 #if defined(TCC_TARGET_PE) && 0
9988 /* XXX: currently the PE linker is not ready to support that */
9989 s->leading_underscore = 1;
9990 #endif
9991 return s;
9994 void tcc_delete(TCCState *s1)
9996 int i, n;
9998 /* free -D defines */
9999 free_defines(NULL);
10001 /* free tokens */
10002 n = tok_ident - TOK_IDENT;
10003 for(i = 0; i < n; i++)
10004 tcc_free(table_ident[i]);
10005 tcc_free(table_ident);
10007 /* free all sections */
10009 free_section(symtab_section->hash);
10011 free_section(s1->dynsymtab_section->hash);
10012 free_section(s1->dynsymtab_section->link);
10013 free_section(s1->dynsymtab_section);
10015 for(i = 1; i < s1->nb_sections; i++)
10016 free_section(s1->sections[i]);
10017 tcc_free(s1->sections);
10019 /* free loaded dlls array */
10020 for(i = 0; i < s1->nb_loaded_dlls; i++)
10021 tcc_free(s1->loaded_dlls[i]);
10022 tcc_free(s1->loaded_dlls);
10024 /* library paths */
10025 for(i = 0; i < s1->nb_library_paths; i++)
10026 tcc_free(s1->library_paths[i]);
10027 tcc_free(s1->library_paths);
10029 /* cached includes */
10030 for(i = 0; i < s1->nb_cached_includes; i++)
10031 tcc_free(s1->cached_includes[i]);
10032 tcc_free(s1->cached_includes);
10034 for(i = 0; i < s1->nb_include_paths; i++)
10035 tcc_free(s1->include_paths[i]);
10036 tcc_free(s1->include_paths);
10038 for(i = 0; i < s1->nb_sysinclude_paths; i++)
10039 tcc_free(s1->sysinclude_paths[i]);
10040 tcc_free(s1->sysinclude_paths);
10042 tcc_free(s1);
10045 int tcc_add_include_path(TCCState *s1, const char *pathname)
10047 char *pathname1;
10049 pathname1 = tcc_strdup(pathname);
10050 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10051 return 0;
10054 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10056 char *pathname1;
10058 pathname1 = tcc_strdup(pathname);
10059 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10060 return 0;
10063 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10065 const char *ext, *filename1;
10066 Elf32_Ehdr ehdr;
10067 int fd, ret;
10068 BufferedFile *saved_file;
10070 /* find source file type with extension */
10071 filename1 = strrchr(filename, '/');
10072 if (filename1)
10073 filename1++;
10074 else
10075 filename1 = filename;
10076 ext = strrchr(filename1, '.');
10077 if (ext)
10078 ext++;
10080 /* open the file */
10081 saved_file = file;
10082 file = tcc_open(s1, filename);
10083 if (!file) {
10084 if (flags & AFF_PRINT_ERROR) {
10085 error_noabort("file '%s' not found", filename);
10087 ret = -1;
10088 goto fail1;
10091 if (flags & AFF_PREPROCESS) {
10092 ret = tcc_preprocess(s1);
10093 } else if (!ext || !strcmp(ext, "c")) {
10094 /* C file assumed */
10095 ret = tcc_compile(s1);
10096 } else
10097 #ifdef CONFIG_TCC_ASM
10098 if (!strcmp(ext, "S")) {
10099 /* preprocessed assembler */
10100 ret = tcc_assemble(s1, 1);
10101 } else if (!strcmp(ext, "s")) {
10102 /* non preprocessed assembler */
10103 ret = tcc_assemble(s1, 0);
10104 } else
10105 #endif
10106 #ifdef TCC_TARGET_PE
10107 if (!strcmp(ext, "def")) {
10108 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
10109 } else
10110 #endif
10112 fd = file->fd;
10113 /* assume executable format: auto guess file type */
10114 ret = read(fd, &ehdr, sizeof(ehdr));
10115 lseek(fd, 0, SEEK_SET);
10116 if (ret <= 0) {
10117 error_noabort("could not read header");
10118 goto fail;
10119 } else if (ret != sizeof(ehdr)) {
10120 goto try_load_script;
10123 if (ehdr.e_ident[0] == ELFMAG0 &&
10124 ehdr.e_ident[1] == ELFMAG1 &&
10125 ehdr.e_ident[2] == ELFMAG2 &&
10126 ehdr.e_ident[3] == ELFMAG3) {
10127 file->line_num = 0; /* do not display line number if error */
10128 if (ehdr.e_type == ET_REL) {
10129 ret = tcc_load_object_file(s1, fd, 0);
10130 } else if (ehdr.e_type == ET_DYN) {
10131 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10132 #ifdef TCC_TARGET_PE
10133 ret = -1;
10134 #else
10135 void *h;
10136 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10137 if (h)
10138 ret = 0;
10139 else
10140 ret = -1;
10141 #endif
10142 } else {
10143 ret = tcc_load_dll(s1, fd, filename,
10144 (flags & AFF_REFERENCED_DLL) != 0);
10146 } else {
10147 error_noabort("unrecognized ELF file");
10148 goto fail;
10150 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10151 file->line_num = 0; /* do not display line number if error */
10152 ret = tcc_load_archive(s1, fd);
10153 } else
10154 #ifdef TCC_TARGET_COFF
10155 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10156 ret = tcc_load_coff(s1, fd);
10157 } else
10158 #endif
10160 /* as GNU ld, consider it is an ld script if not recognized */
10161 try_load_script:
10162 ret = tcc_load_ldscript(s1);
10163 if (ret < 0) {
10164 error_noabort("unrecognized file type");
10165 goto fail;
10169 the_end:
10170 tcc_close(file);
10171 fail1:
10172 file = saved_file;
10173 return ret;
10174 fail:
10175 ret = -1;
10176 goto the_end;
10179 int tcc_add_file(TCCState *s, const char *filename)
10181 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10184 int tcc_add_library_path(TCCState *s, const char *pathname)
10186 char *pathname1;
10188 pathname1 = tcc_strdup(pathname);
10189 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10190 return 0;
10193 /* find and load a dll. Return non zero if not found */
10194 /* XXX: add '-rpath' option support ? */
10195 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10197 char buf[1024];
10198 int i;
10200 for(i = 0; i < s->nb_library_paths; i++) {
10201 snprintf(buf, sizeof(buf), "%s/%s",
10202 s->library_paths[i], filename);
10203 if (tcc_add_file_internal(s, buf, flags) == 0)
10204 return 0;
10206 return -1;
10209 /* the library name is the same as the argument of the '-l' option */
10210 int tcc_add_library(TCCState *s, const char *libraryname)
10212 char buf[1024];
10213 int i;
10215 /* first we look for the dynamic library if not static linking */
10216 if (!s->static_link) {
10217 #ifdef TCC_TARGET_PE
10218 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10219 #else
10220 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10221 #endif
10222 if (tcc_add_dll(s, buf, 0) == 0)
10223 return 0;
10226 /* then we look for the static library */
10227 for(i = 0; i < s->nb_library_paths; i++) {
10228 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10229 s->library_paths[i], libraryname);
10230 if (tcc_add_file_internal(s, buf, 0) == 0)
10231 return 0;
10233 return -1;
10236 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10238 add_elf_sym(symtab_section, val, 0,
10239 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10240 SHN_ABS, name);
10241 return 0;
10244 int tcc_set_output_type(TCCState *s, int output_type)
10246 s->output_type = output_type;
10248 if (!s->nostdinc) {
10249 char buf[1024];
10251 /* default include paths */
10252 /* XXX: reverse order needed if -isystem support */
10253 #ifndef TCC_TARGET_PE
10254 tcc_add_sysinclude_path(s, "/usr/local/include");
10255 tcc_add_sysinclude_path(s, "/usr/include");
10256 #endif
10257 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10258 tcc_add_sysinclude_path(s, buf);
10259 #ifdef TCC_TARGET_PE
10260 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10261 tcc_add_sysinclude_path(s, buf);
10262 #endif
10265 /* if bound checking, then add corresponding sections */
10266 #ifdef CONFIG_TCC_BCHECK
10267 if (do_bounds_check) {
10268 /* define symbol */
10269 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10270 /* create bounds sections */
10271 bounds_section = new_section(s, ".bounds",
10272 SHT_PROGBITS, SHF_ALLOC);
10273 lbounds_section = new_section(s, ".lbounds",
10274 SHT_PROGBITS, SHF_ALLOC);
10276 #endif
10278 if (s->char_is_unsigned) {
10279 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10282 /* add debug sections */
10283 if (do_debug) {
10284 /* stab symbols */
10285 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10286 stab_section->sh_entsize = sizeof(Stab_Sym);
10287 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10288 put_elf_str(stabstr_section, "");
10289 stab_section->link = stabstr_section;
10290 /* put first entry */
10291 put_stabs("", 0, 0, 0, 0);
10294 /* add libc crt1/crti objects */
10295 #ifndef TCC_TARGET_PE
10296 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10297 !s->nostdlib) {
10298 if (output_type != TCC_OUTPUT_DLL)
10299 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10300 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10302 #endif
10303 return 0;
10306 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10307 #define FD_INVERT 0x0002 /* invert value before storing */
10309 typedef struct FlagDef {
10310 uint16_t offset;
10311 uint16_t flags;
10312 const char *name;
10313 } FlagDef;
10315 static const FlagDef warning_defs[] = {
10316 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10317 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10318 { offsetof(TCCState, warn_error), 0, "error" },
10319 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10320 "implicit-function-declaration" },
10323 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10324 const char *name, int value)
10326 int i;
10327 const FlagDef *p;
10328 const char *r;
10330 r = name;
10331 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10332 r += 3;
10333 value = !value;
10335 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10336 if (!strcmp(r, p->name))
10337 goto found;
10339 return -1;
10340 found:
10341 if (p->flags & FD_INVERT)
10342 value = !value;
10343 *(int *)((uint8_t *)s + p->offset) = value;
10344 return 0;
10348 /* set/reset a warning */
10349 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10351 int i;
10352 const FlagDef *p;
10354 if (!strcmp(warning_name, "all")) {
10355 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10356 if (p->flags & WD_ALL)
10357 *(int *)((uint8_t *)s + p->offset) = 1;
10359 return 0;
10360 } else {
10361 return set_flag(s, warning_defs, countof(warning_defs),
10362 warning_name, value);
10366 static const FlagDef flag_defs[] = {
10367 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10368 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10369 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10370 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10373 /* set/reset a flag */
10374 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10376 return set_flag(s, flag_defs, countof(flag_defs),
10377 flag_name, value);
10380 /* extract the basename of a file */
10381 static char *tcc_basename(const char *name)
10383 const char *p;
10384 p = strrchr(name, '/');
10385 #ifdef WIN32
10386 if (!p)
10387 p = strrchr(name, '\\');
10388 #endif
10389 if (!p)
10390 p = name;
10391 else
10392 p++;
10393 return (char*)p;
10396 #if !defined(LIBTCC)
10398 static int64_t getclock_us(void)
10400 #ifdef WIN32
10401 struct _timeb tb;
10402 _ftime(&tb);
10403 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10404 #else
10405 struct timeval tv;
10406 gettimeofday(&tv, NULL);
10407 return tv.tv_sec * 1000000LL + tv.tv_usec;
10408 #endif
10411 void help(void)
10413 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10414 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10415 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10416 " [infile1 infile2...] [-run infile args...]\n"
10417 "\n"
10418 "General options:\n"
10419 " -v display current version\n"
10420 " -c compile only - generate an object file\n"
10421 " -o outfile set output filename\n"
10422 " -Bdir set tcc internal library path\n"
10423 " -bench output compilation statistics\n"
10424 " -run run compiled source\n"
10425 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10426 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10427 " -w disable all warnings\n"
10428 "Preprocessor options:\n"
10429 " -E preprocess only\n"
10430 " -Idir add include path 'dir'\n"
10431 " -Dsym[=val] define 'sym' with value 'val'\n"
10432 " -Usym undefine 'sym'\n"
10433 "Linker options:\n"
10434 " -Ldir add library path 'dir'\n"
10435 " -llib link with dynamic or static library 'lib'\n"
10436 " -shared generate a shared library\n"
10437 " -static static linking\n"
10438 " -rdynamic export all global symbols to dynamic linker\n"
10439 " -r relocatable output\n"
10440 "Debugger options:\n"
10441 " -g generate runtime debug info\n"
10442 #ifdef CONFIG_TCC_BCHECK
10443 " -b compile with built-in memory and bounds checker (implies -g)\n"
10444 #endif
10445 " -bt N show N callers in stack traces\n"
10449 #define TCC_OPTION_HAS_ARG 0x0001
10450 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10452 typedef struct TCCOption {
10453 const char *name;
10454 uint16_t index;
10455 uint16_t flags;
10456 } TCCOption;
10458 enum {
10459 TCC_OPTION_HELP,
10460 TCC_OPTION_I,
10461 TCC_OPTION_D,
10462 TCC_OPTION_U,
10463 TCC_OPTION_L,
10464 TCC_OPTION_B,
10465 TCC_OPTION_l,
10466 TCC_OPTION_bench,
10467 TCC_OPTION_bt,
10468 TCC_OPTION_b,
10469 TCC_OPTION_g,
10470 TCC_OPTION_c,
10471 TCC_OPTION_static,
10472 TCC_OPTION_shared,
10473 TCC_OPTION_o,
10474 TCC_OPTION_r,
10475 TCC_OPTION_Wl,
10476 TCC_OPTION_W,
10477 TCC_OPTION_O,
10478 TCC_OPTION_m,
10479 TCC_OPTION_f,
10480 TCC_OPTION_nostdinc,
10481 TCC_OPTION_nostdlib,
10482 TCC_OPTION_print_search_dirs,
10483 TCC_OPTION_rdynamic,
10484 TCC_OPTION_run,
10485 TCC_OPTION_v,
10486 TCC_OPTION_w,
10487 TCC_OPTION_pipe,
10488 TCC_OPTION_E,
10491 static const TCCOption tcc_options[] = {
10492 { "h", TCC_OPTION_HELP, 0 },
10493 { "?", TCC_OPTION_HELP, 0 },
10494 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10495 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10496 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10497 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10498 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10499 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10500 { "bench", TCC_OPTION_bench, 0 },
10501 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10502 #ifdef CONFIG_TCC_BCHECK
10503 { "b", TCC_OPTION_b, 0 },
10504 #endif
10505 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10506 { "c", TCC_OPTION_c, 0 },
10507 { "static", TCC_OPTION_static, 0 },
10508 { "shared", TCC_OPTION_shared, 0 },
10509 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10510 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10511 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10512 { "r", TCC_OPTION_r, 0 },
10513 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10514 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10515 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10516 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10517 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10518 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10519 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10520 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10521 { "v", TCC_OPTION_v, 0 },
10522 { "w", TCC_OPTION_w, 0 },
10523 { "pipe", TCC_OPTION_pipe, 0},
10524 { "E", TCC_OPTION_E, 0},
10525 { NULL },
10528 /* convert 'str' into an array of space separated strings */
10529 static int expand_args(char ***pargv, const char *str)
10531 const char *s1;
10532 char **argv, *arg;
10533 int argc, len;
10535 argc = 0;
10536 argv = NULL;
10537 for(;;) {
10538 while (is_space(*str))
10539 str++;
10540 if (*str == '\0')
10541 break;
10542 s1 = str;
10543 while (*str != '\0' && !is_space(*str))
10544 str++;
10545 len = str - s1;
10546 arg = tcc_malloc(len + 1);
10547 memcpy(arg, s1, len);
10548 arg[len] = '\0';
10549 dynarray_add((void ***)&argv, &argc, arg);
10551 *pargv = argv;
10552 return argc;
10555 static char **files;
10556 static int nb_files, nb_libraries;
10557 static int multiple_files;
10558 static int print_search_dirs;
10559 static int output_type;
10560 static int reloc_output;
10561 static const char *outfile;
10563 int parse_args(TCCState *s, int argc, char **argv)
10565 int optind;
10566 const TCCOption *popt;
10567 const char *optarg, *p1, *r1;
10568 char *r;
10570 optind = 0;
10571 while (1) {
10572 if (optind >= argc) {
10573 if (nb_files == 0 && !print_search_dirs)
10574 goto show_help;
10575 else
10576 break;
10578 r = argv[optind++];
10579 if (r[0] != '-') {
10580 /* add a new file */
10581 dynarray_add((void ***)&files, &nb_files, r);
10582 if (!multiple_files) {
10583 optind--;
10584 /* argv[0] will be this file */
10585 break;
10587 } else {
10588 /* find option in table (match only the first chars */
10589 popt = tcc_options;
10590 for(;;) {
10591 p1 = popt->name;
10592 if (p1 == NULL)
10593 error("invalid option -- '%s'", r);
10594 r1 = r + 1;
10595 for(;;) {
10596 if (*p1 == '\0')
10597 goto option_found;
10598 if (*r1 != *p1)
10599 break;
10600 p1++;
10601 r1++;
10603 popt++;
10605 option_found:
10606 if (popt->flags & TCC_OPTION_HAS_ARG) {
10607 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10608 optarg = r1;
10609 } else {
10610 if (optind >= argc)
10611 error("argument to '%s' is missing", r);
10612 optarg = argv[optind++];
10614 } else {
10615 if (*r1 != '\0')
10616 goto show_help;
10617 optarg = NULL;
10620 switch(popt->index) {
10621 case TCC_OPTION_HELP:
10622 show_help:
10623 help();
10624 exit(1);
10625 case TCC_OPTION_I:
10626 if (tcc_add_include_path(s, optarg) < 0)
10627 error("too many include paths");
10628 break;
10629 case TCC_OPTION_D:
10631 char *sym, *value;
10632 sym = (char *)optarg;
10633 value = strchr(sym, '=');
10634 if (value) {
10635 *value = '\0';
10636 value++;
10638 tcc_define_symbol(s, sym, value);
10640 break;
10641 case TCC_OPTION_U:
10642 tcc_undefine_symbol(s, optarg);
10643 break;
10644 case TCC_OPTION_L:
10645 tcc_add_library_path(s, optarg);
10646 break;
10647 case TCC_OPTION_B:
10648 /* set tcc utilities path (mainly for tcc development) */
10649 tcc_lib_path = optarg;
10650 break;
10651 case TCC_OPTION_l:
10652 dynarray_add((void ***)&files, &nb_files, r);
10653 nb_libraries++;
10654 break;
10655 case TCC_OPTION_bench:
10656 do_bench = 1;
10657 break;
10658 case TCC_OPTION_bt:
10659 num_callers = atoi(optarg);
10660 break;
10661 #ifdef CONFIG_TCC_BCHECK
10662 case TCC_OPTION_b:
10663 do_bounds_check = 1;
10664 do_debug = 1;
10665 break;
10666 #endif
10667 case TCC_OPTION_g:
10668 do_debug = 1;
10669 break;
10670 case TCC_OPTION_c:
10671 multiple_files = 1;
10672 output_type = TCC_OUTPUT_OBJ;
10673 break;
10674 case TCC_OPTION_static:
10675 s->static_link = 1;
10676 break;
10677 case TCC_OPTION_shared:
10678 output_type = TCC_OUTPUT_DLL;
10679 break;
10680 case TCC_OPTION_o:
10681 multiple_files = 1;
10682 outfile = optarg;
10683 break;
10684 case TCC_OPTION_r:
10685 /* generate a .o merging several output files */
10686 reloc_output = 1;
10687 output_type = TCC_OUTPUT_OBJ;
10688 break;
10689 case TCC_OPTION_nostdinc:
10690 s->nostdinc = 1;
10691 break;
10692 case TCC_OPTION_nostdlib:
10693 s->nostdlib = 1;
10694 break;
10695 case TCC_OPTION_print_search_dirs:
10696 print_search_dirs = 1;
10697 break;
10698 case TCC_OPTION_run:
10700 int argc1;
10701 char **argv1;
10702 argc1 = expand_args(&argv1, optarg);
10703 if (argc1 > 0) {
10704 parse_args(s, argc1, argv1);
10706 multiple_files = 0;
10707 output_type = TCC_OUTPUT_MEMORY;
10709 break;
10710 case TCC_OPTION_v:
10711 printf("tcc version %s\n", TCC_VERSION);
10712 exit(0);
10713 case TCC_OPTION_f:
10714 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10715 goto unsupported_option;
10716 break;
10717 case TCC_OPTION_W:
10718 if (tcc_set_warning(s, optarg, 1) < 0 &&
10719 s->warn_unsupported)
10720 goto unsupported_option;
10721 break;
10722 case TCC_OPTION_w:
10723 s->warn_none = 1;
10724 break;
10725 case TCC_OPTION_rdynamic:
10726 s->rdynamic = 1;
10727 break;
10728 case TCC_OPTION_Wl:
10730 const char *p;
10731 if (strstart(optarg, "-Ttext,", &p)) {
10732 s->text_addr = strtoul(p, NULL, 16);
10733 s->has_text_addr = 1;
10734 } else if (strstart(optarg, "--oformat,", &p)) {
10735 if (strstart(p, "elf32-", NULL)) {
10736 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10737 } else if (!strcmp(p, "binary")) {
10738 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10739 } else
10740 #ifdef TCC_TARGET_COFF
10741 if (!strcmp(p, "coff")) {
10742 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10743 } else
10744 #endif
10746 error("target %s not found", p);
10748 } else {
10749 error("unsupported linker option '%s'", optarg);
10752 break;
10753 case TCC_OPTION_E:
10754 output_type = TCC_OUTPUT_PREPROCESS;
10755 break;
10756 default:
10757 if (s->warn_unsupported) {
10758 unsupported_option:
10759 warning("unsupported option '%s'", r);
10761 break;
10765 return optind;
10768 int main(int argc, char **argv)
10770 int i;
10771 TCCState *s;
10772 int nb_objfiles, ret, optind;
10773 char objfilename[1024];
10774 int64_t start_time = 0;
10776 #ifdef WIN32
10777 /* on win32, we suppose the lib and includes are at the location
10778 of 'tcc.exe' */
10780 static char path[1024];
10781 char *p, *d;
10783 GetModuleFileNameA(NULL, path, sizeof path);
10784 p = d = strlwr(path);
10785 while (*d)
10787 if (*d == '\\') *d = '/', p = d;
10788 ++d;
10790 *p = '\0';
10791 tcc_lib_path = path;
10793 #endif
10795 s = tcc_new();
10796 output_type = TCC_OUTPUT_EXE;
10797 outfile = NULL;
10798 multiple_files = 1;
10799 files = NULL;
10800 nb_files = 0;
10801 nb_libraries = 0;
10802 reloc_output = 0;
10803 print_search_dirs = 0;
10805 optind = parse_args(s, argc - 1, argv + 1) + 1;
10807 if (print_search_dirs) {
10808 /* enough for Linux kernel */
10809 printf("install: %s/\n", tcc_lib_path);
10810 return 0;
10813 nb_objfiles = nb_files - nb_libraries;
10815 /* if outfile provided without other options, we output an
10816 executable */
10817 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10818 output_type = TCC_OUTPUT_EXE;
10820 /* check -c consistency : only single file handled. XXX: checks file type */
10821 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10822 /* accepts only a single input file */
10823 if (nb_objfiles != 1)
10824 error("cannot specify multiple files with -c");
10825 if (nb_libraries != 0)
10826 error("cannot specify libraries with -c");
10830 if (output_type == TCC_OUTPUT_PREPROCESS) {
10831 if (!outfile) {
10832 s->outfile = stdout;
10833 } else {
10834 s->outfile = fopen(outfile, "wb");
10835 if (!s->outfile)
10836 error("could not open '%s", outfile);
10838 } else if (output_type != TCC_OUTPUT_MEMORY) {
10839 if (!outfile) {
10840 /* compute default outfile name */
10841 pstrcpy(objfilename, sizeof(objfilename) - 1,
10842 /* strip path */
10843 tcc_basename(files[0]));
10844 #ifdef TCC_TARGET_PE
10845 pe_guess_outfile(objfilename, output_type);
10846 #else
10847 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10848 char *ext = strrchr(objfilename, '.');
10849 if (!ext)
10850 goto default_outfile;
10851 /* add .o extension */
10852 strcpy(ext + 1, "o");
10853 } else {
10854 default_outfile:
10855 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10857 #endif
10858 outfile = objfilename;
10862 if (do_bench) {
10863 start_time = getclock_us();
10866 tcc_set_output_type(s, output_type);
10868 /* compile or add each files or library */
10869 for(i = 0;i < nb_files; i++) {
10870 const char *filename;
10872 filename = files[i];
10873 if (output_type == TCC_OUTPUT_PREPROCESS) {
10874 tcc_add_file_internal(s, filename,
10875 AFF_PRINT_ERROR | AFF_PREPROCESS);
10876 } else {
10877 if (filename[0] == '-') {
10878 if (tcc_add_library(s, filename + 2) < 0)
10879 error("cannot find %s", filename);
10880 } else {
10881 if (tcc_add_file(s, filename) < 0) {
10882 ret = 1;
10883 goto the_end;
10889 /* free all files */
10890 tcc_free(files);
10892 if (do_bench) {
10893 double total_time;
10894 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10895 if (total_time < 0.001)
10896 total_time = 0.001;
10897 if (total_bytes < 1)
10898 total_bytes = 1;
10899 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10900 tok_ident - TOK_IDENT, total_lines, total_bytes,
10901 total_time, (int)(total_lines / total_time),
10902 total_bytes / total_time / 1000000.0);
10905 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
10906 if (outfile)
10907 fclose(s->outfile);
10908 ret = 0;
10909 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
10910 ret = tcc_run(s, argc - optind, argv + optind);
10911 } else
10912 #ifdef TCC_TARGET_PE
10913 if (s->output_type != TCC_OUTPUT_OBJ) {
10914 ret = tcc_output_pe(s, outfile);
10915 } else
10916 #endif
10918 ret = tcc_output_file(s, outfile) ? 1 : 0;
10920 the_end:
10921 /* XXX: cannot do it with bound checking because of the malloc hooks */
10922 if (!do_bounds_check)
10923 tcc_delete(s);
10925 #ifdef MEM_DEBUG
10926 if (do_bench) {
10927 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10929 #endif
10930 return ret;
10933 #endif