Import 409,410: ARM EABI by Daniel Glöckner
[tinycc/kirr.git] / tcc.c
blob36195d1d449a69b304fdc415a94c1fc1fd4d21e3
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 */
324 #define TOK_FLAG_EOF 0x0008 /* end of file */
326 static int *macro_ptr, *macro_ptr_allocated;
327 static int *unget_saved_macro_ptr;
328 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
329 static int unget_buffer_enabled;
330 static int parse_flags;
331 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
332 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
333 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
334 token. line feed is also
335 returned at eof */
336 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
338 static Section *text_section, *data_section, *bss_section; /* predefined sections */
339 static Section *cur_text_section; /* current section where function code is
340 generated */
341 #ifdef CONFIG_TCC_ASM
342 static Section *last_text_section; /* to handle .previous asm directive */
343 #endif
344 /* bound check related sections */
345 static Section *bounds_section; /* contains global data bound description */
346 static Section *lbounds_section; /* contains local data bound description */
347 /* symbol sections */
348 static Section *symtab_section, *strtab_section;
350 /* debug sections */
351 static Section *stab_section, *stabstr_section;
353 /* loc : local variable index
354 ind : output code index
355 rsym: return symbol
356 anon_sym: anonymous symbol index
358 static int rsym, anon_sym, ind, loc;
359 /* expression generation modifiers */
360 static int const_wanted; /* true if constant wanted */
361 static int nocode_wanted; /* true if no code generation wanted for an expression */
362 static int global_expr; /* true if compound literals must be allocated
363 globally (used during initializers parsing */
364 static CType func_vt; /* current function return type (used by return
365 instruction) */
366 static int func_vc;
367 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
368 static int tok_ident;
369 static TokenSym **table_ident;
370 static TokenSym *hash_ident[TOK_HASH_SIZE];
371 static char token_buf[STRING_MAX_SIZE + 1];
372 static char *funcname;
373 static Sym *global_stack, *local_stack;
374 static Sym *define_stack;
375 static Sym *global_label_stack, *local_label_stack;
376 /* symbol allocator */
377 #define SYM_POOL_NB (8192 / sizeof(Sym))
378 static Sym *sym_free_first;
380 static SValue vstack[VSTACK_SIZE], *vtop;
381 /* some predefined types */
382 static CType char_pointer_type, func_old_type, int_type;
383 /* true if isid(c) || isnum(c) */
384 static unsigned char isidnum_table[256];
386 /* compile with debug symbol (and use them if error during execution) */
387 static int do_debug = 0;
389 /* compile with built-in memory and bounds checker */
390 static int do_bounds_check = 0;
392 /* display benchmark infos */
393 #if !defined(LIBTCC)
394 static int do_bench = 0;
395 #endif
396 static int total_lines;
397 static int total_bytes;
399 /* use GNU C extensions */
400 static int gnu_ext = 1;
402 /* use Tiny C extensions */
403 static int tcc_ext = 1;
405 /* max number of callers shown if error */
406 static int num_callers = 6;
407 static const char **rt_bound_error_msg;
409 /* XXX: get rid of this ASAP */
410 static struct TCCState *tcc_state;
412 /* give the path of the tcc libraries */
413 static const char *tcc_lib_path = CONFIG_TCCDIR;
415 struct TCCState {
416 int output_type;
418 BufferedFile **include_stack_ptr;
419 int *ifdef_stack_ptr;
421 /* include file handling */
422 char **include_paths;
423 int nb_include_paths;
424 char **sysinclude_paths;
425 int nb_sysinclude_paths;
426 CachedInclude **cached_includes;
427 int nb_cached_includes;
429 char **library_paths;
430 int nb_library_paths;
432 /* array of all loaded dlls (including those referenced by loaded
433 dlls) */
434 DLLReference **loaded_dlls;
435 int nb_loaded_dlls;
437 /* sections */
438 Section **sections;
439 int nb_sections; /* number of sections, including first dummy section */
441 /* got handling */
442 Section *got;
443 Section *plt;
444 unsigned long *got_offsets;
445 int nb_got_offsets;
446 /* give the correspondance from symtab indexes to dynsym indexes */
447 int *symtab_to_dynsym;
449 /* temporary dynamic symbol sections (for dll loading) */
450 Section *dynsymtab_section;
451 /* exported dynamic symbol section */
452 Section *dynsym;
454 int nostdinc; /* if true, no standard headers are added */
455 int nostdlib; /* if true, no standard libraries are added */
457 int nocommon; /* if true, do not use common symbols for .bss data */
459 /* if true, static linking is performed */
460 int static_link;
462 /* if true, all symbols are exported */
463 int rdynamic;
465 /* if true, only link in referenced objects from archive */
466 int alacarte_link;
468 /* address of text section */
469 unsigned long text_addr;
470 int has_text_addr;
472 /* output format, see TCC_OUTPUT_FORMAT_xxx */
473 int output_format;
475 /* C language options */
476 int char_is_unsigned;
477 int leading_underscore;
479 /* warning switches */
480 int warn_write_strings;
481 int warn_unsupported;
482 int warn_error;
483 int warn_none;
484 int warn_implicit_function_declaration;
486 /* error handling */
487 void *error_opaque;
488 void (*error_func)(void *opaque, const char *msg);
489 int error_set_jmp_enabled;
490 jmp_buf error_jmp_buf;
491 int nb_errors;
493 /* tiny assembler state */
494 Sym *asm_labels;
496 /* see include_stack_ptr */
497 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
499 /* see ifdef_stack_ptr */
500 int ifdef_stack[IFDEF_STACK_SIZE];
502 /* see cached_includes */
503 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
505 /* pack stack */
506 int pack_stack[PACK_STACK_SIZE];
507 int *pack_stack_ptr;
509 /* output file for preprocessing */
510 FILE *outfile;
513 /* The current value can be: */
514 #define VT_VALMASK 0x00ff
515 #define VT_CONST 0x00f0 /* constant in vc
516 (must be first non register value) */
517 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
518 #define VT_LOCAL 0x00f2 /* offset on stack */
519 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
520 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
521 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
522 #define VT_LVAL 0x0100 /* var is an lvalue */
523 #define VT_SYM 0x0200 /* a symbol value is added */
524 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
525 char/short stored in integer registers) */
526 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
527 dereferencing value */
528 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
529 bounding function call point is in vc */
530 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
531 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
532 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
533 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
535 /* types */
536 #define VT_INT 0 /* integer type */
537 #define VT_BYTE 1 /* signed byte type */
538 #define VT_SHORT 2 /* short type */
539 #define VT_VOID 3 /* void type */
540 #define VT_PTR 4 /* pointer */
541 #define VT_ENUM 5 /* enum definition */
542 #define VT_FUNC 6 /* function type */
543 #define VT_STRUCT 7 /* struct/union definition */
544 #define VT_FLOAT 8 /* IEEE float */
545 #define VT_DOUBLE 9 /* IEEE double */
546 #define VT_LDOUBLE 10 /* IEEE long double */
547 #define VT_BOOL 11 /* ISOC99 boolean type */
548 #define VT_LLONG 12 /* 64 bit integer */
549 #define VT_LONG 13 /* long integer (NEVER USED as type, only
550 during parsing) */
551 #define VT_BTYPE 0x000f /* mask for basic type */
552 #define VT_UNSIGNED 0x0010 /* unsigned type */
553 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
554 #define VT_BITFIELD 0x0040 /* bitfield modifier */
555 #define VT_CONSTANT 0x0800 /* const modifier */
556 #define VT_VOLATILE 0x1000 /* volatile modifier */
557 #define VT_SIGNED 0x2000 /* signed type */
559 /* storage */
560 #define VT_EXTERN 0x00000080 /* extern definition */
561 #define VT_STATIC 0x00000100 /* static variable */
562 #define VT_TYPEDEF 0x00000200 /* typedef definition */
563 #define VT_INLINE 0x00000400 /* inline definition */
565 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
567 /* type mask (except storage) */
568 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
569 #define VT_TYPE (~(VT_STORAGE))
571 /* token values */
573 /* warning: the following compare tokens depend on i386 asm code */
574 #define TOK_ULT 0x92
575 #define TOK_UGE 0x93
576 #define TOK_EQ 0x94
577 #define TOK_NE 0x95
578 #define TOK_ULE 0x96
579 #define TOK_UGT 0x97
580 #define TOK_Nset 0x98
581 #define TOK_Nclear 0x99
582 #define TOK_LT 0x9c
583 #define TOK_GE 0x9d
584 #define TOK_LE 0x9e
585 #define TOK_GT 0x9f
587 #define TOK_LAND 0xa0
588 #define TOK_LOR 0xa1
590 #define TOK_DEC 0xa2
591 #define TOK_MID 0xa3 /* inc/dec, to void constant */
592 #define TOK_INC 0xa4
593 #define TOK_UDIV 0xb0 /* unsigned division */
594 #define TOK_UMOD 0xb1 /* unsigned modulo */
595 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
596 #define TOK_CINT 0xb3 /* number in tokc */
597 #define TOK_CCHAR 0xb4 /* char constant in tokc */
598 #define TOK_STR 0xb5 /* pointer to string in tokc */
599 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
600 #define TOK_LCHAR 0xb7
601 #define TOK_LSTR 0xb8
602 #define TOK_CFLOAT 0xb9 /* float constant */
603 #define TOK_LINENUM 0xba /* line number info */
604 #define TOK_CDOUBLE 0xc0 /* double constant */
605 #define TOK_CLDOUBLE 0xc1 /* long double constant */
606 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
607 #define TOK_ADDC1 0xc3 /* add with carry generation */
608 #define TOK_ADDC2 0xc4 /* add with carry use */
609 #define TOK_SUBC1 0xc5 /* add with carry generation */
610 #define TOK_SUBC2 0xc6 /* add with carry use */
611 #define TOK_CUINT 0xc8 /* unsigned int constant */
612 #define TOK_CLLONG 0xc9 /* long long constant */
613 #define TOK_CULLONG 0xca /* unsigned long long constant */
614 #define TOK_ARROW 0xcb
615 #define TOK_DOTS 0xcc /* three dots */
616 #define TOK_SHR 0xcd /* unsigned shift right */
617 #define TOK_PPNUM 0xce /* preprocessor number */
619 #define TOK_SHL 0x01 /* shift left */
620 #define TOK_SAR 0x02 /* signed shift right */
622 /* assignement operators : normal operator or 0x80 */
623 #define TOK_A_MOD 0xa5
624 #define TOK_A_AND 0xa6
625 #define TOK_A_MUL 0xaa
626 #define TOK_A_ADD 0xab
627 #define TOK_A_SUB 0xad
628 #define TOK_A_DIV 0xaf
629 #define TOK_A_XOR 0xde
630 #define TOK_A_OR 0xfc
631 #define TOK_A_SHL 0x81
632 #define TOK_A_SAR 0x82
634 #ifndef offsetof
635 #define offsetof(type, field) ((size_t) &((type *)0)->field)
636 #endif
638 #ifndef countof
639 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
640 #endif
642 /* WARNING: the content of this string encodes token numbers */
643 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";
645 #define TOK_EOF (-1) /* end of file */
646 #define TOK_LINEFEED 10 /* line feed */
648 /* all identificators and strings have token above that */
649 #define TOK_IDENT 256
651 /* only used for i386 asm opcodes definitions */
652 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
654 #define DEF_BWL(x) \
655 DEF(TOK_ASM_ ## x ## b, #x "b") \
656 DEF(TOK_ASM_ ## x ## w, #x "w") \
657 DEF(TOK_ASM_ ## x ## l, #x "l") \
658 DEF(TOK_ASM_ ## x, #x)
660 #define DEF_WL(x) \
661 DEF(TOK_ASM_ ## x ## w, #x "w") \
662 DEF(TOK_ASM_ ## x ## l, #x "l") \
663 DEF(TOK_ASM_ ## x, #x)
665 #define DEF_FP1(x) \
666 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
667 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
668 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
669 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
671 #define DEF_FP(x) \
672 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
673 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
674 DEF_FP1(x)
676 #define DEF_ASMTEST(x) \
677 DEF_ASM(x ## o) \
678 DEF_ASM(x ## no) \
679 DEF_ASM(x ## b) \
680 DEF_ASM(x ## c) \
681 DEF_ASM(x ## nae) \
682 DEF_ASM(x ## nb) \
683 DEF_ASM(x ## nc) \
684 DEF_ASM(x ## ae) \
685 DEF_ASM(x ## e) \
686 DEF_ASM(x ## z) \
687 DEF_ASM(x ## ne) \
688 DEF_ASM(x ## nz) \
689 DEF_ASM(x ## be) \
690 DEF_ASM(x ## na) \
691 DEF_ASM(x ## nbe) \
692 DEF_ASM(x ## a) \
693 DEF_ASM(x ## s) \
694 DEF_ASM(x ## ns) \
695 DEF_ASM(x ## p) \
696 DEF_ASM(x ## pe) \
697 DEF_ASM(x ## np) \
698 DEF_ASM(x ## po) \
699 DEF_ASM(x ## l) \
700 DEF_ASM(x ## nge) \
701 DEF_ASM(x ## nl) \
702 DEF_ASM(x ## ge) \
703 DEF_ASM(x ## le) \
704 DEF_ASM(x ## ng) \
705 DEF_ASM(x ## nle) \
706 DEF_ASM(x ## g)
708 #define TOK_ASM_int TOK_INT
710 enum tcc_token {
711 TOK_LAST = TOK_IDENT - 1,
712 #define DEF(id, str) id,
713 #include "tcctok.h"
714 #undef DEF
717 static const char tcc_keywords[] =
718 #define DEF(id, str) str "\0"
719 #include "tcctok.h"
720 #undef DEF
723 #define TOK_UIDENT TOK_DEFINE
725 #ifdef WIN32
726 int __stdcall GetModuleFileNameA(void *, char *, int);
727 void *__stdcall GetProcAddress(void *, const char *);
728 void *__stdcall GetModuleHandleA(const char *);
729 void *__stdcall LoadLibraryA(const char *);
730 int __stdcall FreeConsole(void);
731 int __stdcall VirtualProtect(void*,unsigned long,unsigned long,unsigned long*);
732 #define PAGE_EXECUTE_READWRITE 0x0040
734 #define snprintf _snprintf
735 #define vsnprintf _vsnprintf
736 #ifndef __GNUC__
737 #define strtold (long double)strtod
738 #define strtof (float)strtod
739 #define strtoll (long long)strtol
740 #endif
741 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
742 /* currently incorrect */
743 long double strtold(const char *nptr, char **endptr)
745 return (long double)strtod(nptr, endptr);
747 float strtof(const char *nptr, char **endptr)
749 return (float)strtod(nptr, endptr);
751 #else
752 /* XXX: need to define this to use them in non ISOC99 context */
753 extern float strtof (const char *__nptr, char **__endptr);
754 extern long double strtold (const char *__nptr, char **__endptr);
755 #endif
757 static char *pstrcpy(char *buf, int buf_size, const char *s);
758 static char *pstrcat(char *buf, int buf_size, const char *s);
759 static char *tcc_basename(const char *name);
761 static void next(void);
762 static void next_nomacro(void);
763 static void parse_expr_type(CType *type);
764 static void expr_type(CType *type);
765 static void unary_type(CType *type);
766 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
767 int case_reg, int is_expr);
768 static int expr_const(void);
769 static void expr_eq(void);
770 static void gexpr(void);
771 static void gen_inline_functions(void);
772 static void decl(int l);
773 static void decl_initializer(CType *type, Section *sec, unsigned long c,
774 int first, int size_only);
775 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
776 int has_init, int v, int scope);
777 int gv(int rc);
778 void gv2(int rc1, int rc2);
779 void move_reg(int r, int s);
780 void save_regs(int n);
781 void save_reg(int r);
782 void vpop(void);
783 void vswap(void);
784 void vdup(void);
785 int get_reg(int rc);
786 int get_reg_ex(int rc,int rc2);
788 struct macro_level {
789 struct macro_level *prev;
790 int *p;
793 static void macro_subst(TokenString *tok_str, Sym **nested_list,
794 const int *macro_str, struct macro_level **can_read_stream);
795 void gen_op(int op);
796 void force_charshort_cast(int t);
797 static void gen_cast(CType *type);
798 void vstore(void);
799 static Sym *sym_find(int v);
800 static Sym *sym_push(int v, CType *type, int r, int c);
802 /* type handling */
803 static int type_size(CType *type, int *a);
804 static inline CType *pointed_type(CType *type);
805 static int pointed_size(CType *type);
806 static int lvalue_type(int t);
807 static int parse_btype(CType *type, AttributeDef *ad);
808 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
809 static int compare_types(CType *type1, CType *type2, int unqualified);
810 static int is_compatible_types(CType *type1, CType *type2);
811 static int is_compatible_parameter_types(CType *type1, CType *type2);
813 int ieee_finite(double d);
814 void error(const char *fmt, ...);
815 void vpushi(int v);
816 void vrott(int n);
817 void vnrott(int n);
818 void lexpand_nr(void);
819 static void vpush_global_sym(CType *type, int v);
820 void vset(CType *type, int r, int v);
821 void type_to_str(char *buf, int buf_size,
822 CType *type, const char *varstr);
823 char *get_tok_str(int v, CValue *cv);
824 static Sym *get_sym_ref(CType *type, Section *sec,
825 unsigned long offset, unsigned long size);
826 static Sym *external_global_sym(int v, CType *type, int r);
828 /* section generation */
829 static void section_realloc(Section *sec, unsigned long new_size);
830 static void *section_ptr_add(Section *sec, unsigned long size);
831 static void put_extern_sym(Sym *sym, Section *section,
832 unsigned long value, unsigned long size);
833 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
834 static int put_elf_str(Section *s, const char *sym);
835 static int put_elf_sym(Section *s,
836 unsigned long value, unsigned long size,
837 int info, int other, int shndx, const char *name);
838 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
839 int info, int other, int sh_num, const char *name);
840 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
841 int type, int symbol);
842 static void put_stabs(const char *str, int type, int other, int desc,
843 unsigned long value);
844 static void put_stabs_r(const char *str, int type, int other, int desc,
845 unsigned long value, Section *sec, int sym_index);
846 static void put_stabn(int type, int other, int desc, int value);
847 static void put_stabd(int type, int other, int desc);
848 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
850 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
851 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
852 #define AFF_PREPROCESS 0x0004 /* preprocess file */
853 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
855 /* tcccoff.c */
856 int tcc_output_coff(TCCState *s1, FILE *f);
858 /* tccpe.c */
859 void *resolve_sym(TCCState *s1, const char *sym, int type);
860 int pe_load_def_file(struct TCCState *s1, FILE *fp);
861 void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
862 unsigned long pe_add_runtime(struct TCCState *s1);
863 int tcc_output_pe(struct TCCState *s1, const char *filename);
865 /* tccasm.c */
867 #ifdef CONFIG_TCC_ASM
869 typedef struct ExprValue {
870 uint32_t v;
871 Sym *sym;
872 } ExprValue;
874 #define MAX_ASM_OPERANDS 30
876 typedef struct ASMOperand {
877 int id; /* GCC 3 optionnal identifier (0 if number only supported */
878 char *constraint;
879 char asm_str[16]; /* computed asm string for operand */
880 SValue *vt; /* C value of the expression */
881 int ref_index; /* if >= 0, gives reference to a output constraint */
882 int input_index; /* if >= 0, gives reference to an input constraint */
883 int priority; /* priority, used to assign registers */
884 int reg; /* if >= 0, register number used for this operand */
885 int is_llong; /* true if double register value */
886 int is_memory; /* true if memory operand */
887 int is_rw; /* for '+' modifier */
888 } ASMOperand;
890 static void asm_expr(TCCState *s1, ExprValue *pe);
891 static int asm_int_expr(TCCState *s1);
892 static int find_constraint(ASMOperand *operands, int nb_operands,
893 const char *name, const char **pp);
895 static int tcc_assemble(TCCState *s1, int do_preprocess);
897 #endif
899 static void asm_instr(void);
900 static void asm_global_instr(void);
902 /* true if float/double/long double type */
903 static inline int is_float(int t)
905 int bt;
906 bt = t & VT_BTYPE;
907 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
910 #ifdef TCC_TARGET_I386
911 #include "i386-gen.c"
912 #endif
914 #ifdef TCC_TARGET_ARM
915 #include "arm-gen.c"
916 #endif
918 #ifdef TCC_TARGET_C67
919 #include "c67-gen.c"
920 #endif
922 #ifdef CONFIG_TCC_STATIC
924 #define RTLD_LAZY 0x001
925 #define RTLD_NOW 0x002
926 #define RTLD_GLOBAL 0x100
927 #define RTLD_DEFAULT NULL
929 /* dummy function for profiling */
930 void *dlopen(const char *filename, int flag)
932 return NULL;
935 const char *dlerror(void)
937 return "error";
940 typedef struct TCCSyms {
941 char *str;
942 void *ptr;
943 } TCCSyms;
945 #define TCCSYM(a) { #a, &a, },
947 /* add the symbol you want here if no dynamic linking is done */
948 static TCCSyms tcc_syms[] = {
949 #if !defined(CONFIG_TCCBOOT)
950 TCCSYM(printf)
951 TCCSYM(fprintf)
952 TCCSYM(fopen)
953 TCCSYM(fclose)
954 #endif
955 { NULL, NULL },
958 void *resolve_sym(TCCState *s1, const char *symbol, int type)
960 TCCSyms *p;
961 p = tcc_syms;
962 while (p->str != NULL) {
963 if (!strcmp(p->str, symbol))
964 return p->ptr;
965 p++;
967 return NULL;
970 #elif !defined(WIN32)
972 #include <dlfcn.h>
974 void *resolve_sym(TCCState *s1, const char *sym, int type)
976 return dlsym(RTLD_DEFAULT, sym);
979 #endif
981 /********************************************************/
983 /* we use our own 'finite' function to avoid potential problems with
984 non standard math libs */
985 /* XXX: endianness dependent */
986 int ieee_finite(double d)
988 int *p = (int *)&d;
989 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
992 /* copy a string and truncate it. */
993 static char *pstrcpy(char *buf, int buf_size, const char *s)
995 char *q, *q_end;
996 int c;
998 if (buf_size > 0) {
999 q = buf;
1000 q_end = buf + buf_size - 1;
1001 while (q < q_end) {
1002 c = *s++;
1003 if (c == '\0')
1004 break;
1005 *q++ = c;
1007 *q = '\0';
1009 return buf;
1012 /* strcat and truncate. */
1013 static char *pstrcat(char *buf, int buf_size, const char *s)
1015 int len;
1016 len = strlen(buf);
1017 if (len < buf_size)
1018 pstrcpy(buf + len, buf_size - len, s);
1019 return buf;
1022 static int strstart(const char *str, const char *val, const char **ptr)
1024 const char *p, *q;
1025 p = str;
1026 q = val;
1027 while (*q != '\0') {
1028 if (*p != *q)
1029 return 0;
1030 p++;
1031 q++;
1033 if (ptr)
1034 *ptr = p;
1035 return 1;
1038 #ifdef WIN32
1039 char *normalize_slashes(char *path)
1041 char *p;
1042 for (p = path; *p; ++p)
1043 if (*p == '\\')
1044 *p = '/';
1045 return path;
1048 char *w32_tcc_lib_path(void)
1050 /* on win32, we suppose the lib and includes are at the location
1051 of 'tcc.exe' */
1052 char path[1024], *p;
1053 GetModuleFileNameA(NULL, path, sizeof path);
1054 p = tcc_basename(normalize_slashes(strlwr(path)));
1055 if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
1056 p -= 5;
1057 else if (p > path)
1058 p--;
1059 *p = 0;
1060 return strdup(path);
1062 #endif
1064 /* memory management */
1065 #ifdef MEM_DEBUG
1066 int mem_cur_size;
1067 int mem_max_size;
1068 #endif
1070 static inline void tcc_free(void *ptr)
1072 #ifdef MEM_DEBUG
1073 mem_cur_size -= malloc_usable_size(ptr);
1074 #endif
1075 free(ptr);
1078 static void *tcc_malloc(unsigned long size)
1080 void *ptr;
1081 ptr = malloc(size);
1082 if (!ptr && size)
1083 error("memory full");
1084 #ifdef MEM_DEBUG
1085 mem_cur_size += malloc_usable_size(ptr);
1086 if (mem_cur_size > mem_max_size)
1087 mem_max_size = mem_cur_size;
1088 #endif
1089 return ptr;
1092 static void *tcc_mallocz(unsigned long size)
1094 void *ptr;
1095 ptr = tcc_malloc(size);
1096 memset(ptr, 0, size);
1097 return ptr;
1100 static inline void *tcc_realloc(void *ptr, unsigned long size)
1102 void *ptr1;
1103 #ifdef MEM_DEBUG
1104 mem_cur_size -= malloc_usable_size(ptr);
1105 #endif
1106 ptr1 = realloc(ptr, size);
1107 #ifdef MEM_DEBUG
1108 /* NOTE: count not correct if alloc error, but not critical */
1109 mem_cur_size += malloc_usable_size(ptr1);
1110 if (mem_cur_size > mem_max_size)
1111 mem_max_size = mem_cur_size;
1112 #endif
1113 return ptr1;
1116 static char *tcc_strdup(const char *str)
1118 char *ptr;
1119 ptr = tcc_malloc(strlen(str) + 1);
1120 strcpy(ptr, str);
1121 return ptr;
1124 #define free(p) use_tcc_free(p)
1125 #define malloc(s) use_tcc_malloc(s)
1126 #define realloc(p, s) use_tcc_realloc(p, s)
1128 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1130 int nb, nb_alloc;
1131 void **pp;
1133 nb = *nb_ptr;
1134 pp = *ptab;
1135 /* every power of two we double array size */
1136 if ((nb & (nb - 1)) == 0) {
1137 if (!nb)
1138 nb_alloc = 1;
1139 else
1140 nb_alloc = nb * 2;
1141 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1142 if (!pp)
1143 error("memory full");
1144 *ptab = pp;
1146 pp[nb++] = data;
1147 *nb_ptr = nb;
1150 /* symbol allocator */
1151 static Sym *__sym_malloc(void)
1153 Sym *sym_pool, *sym, *last_sym;
1154 int i;
1156 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1158 last_sym = sym_free_first;
1159 sym = sym_pool;
1160 for(i = 0; i < SYM_POOL_NB; i++) {
1161 sym->next = last_sym;
1162 last_sym = sym;
1163 sym++;
1165 sym_free_first = last_sym;
1166 return last_sym;
1169 static inline Sym *sym_malloc(void)
1171 Sym *sym;
1172 sym = sym_free_first;
1173 if (!sym)
1174 sym = __sym_malloc();
1175 sym_free_first = sym->next;
1176 return sym;
1179 static inline void sym_free(Sym *sym)
1181 sym->next = sym_free_first;
1182 sym_free_first = sym;
1185 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1187 Section *sec;
1189 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1190 strcpy(sec->name, name);
1191 sec->sh_type = sh_type;
1192 sec->sh_flags = sh_flags;
1193 switch(sh_type) {
1194 case SHT_HASH:
1195 case SHT_REL:
1196 case SHT_DYNSYM:
1197 case SHT_SYMTAB:
1198 case SHT_DYNAMIC:
1199 sec->sh_addralign = 4;
1200 break;
1201 case SHT_STRTAB:
1202 sec->sh_addralign = 1;
1203 break;
1204 default:
1205 sec->sh_addralign = 32; /* default conservative alignment */
1206 break;
1209 /* only add section if not private */
1210 if (!(sh_flags & SHF_PRIVATE)) {
1211 sec->sh_num = s1->nb_sections;
1212 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1214 return sec;
1217 static void free_section(Section *s)
1219 tcc_free(s->data);
1220 tcc_free(s);
1223 /* realloc section and set its content to zero */
1224 static void section_realloc(Section *sec, unsigned long new_size)
1226 unsigned long size;
1227 unsigned char *data;
1229 size = sec->data_allocated;
1230 if (size == 0)
1231 size = 1;
1232 while (size < new_size)
1233 size = size * 2;
1234 data = tcc_realloc(sec->data, size);
1235 if (!data)
1236 error("memory full");
1237 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1238 sec->data = data;
1239 sec->data_allocated = size;
1242 /* reserve at least 'size' bytes in section 'sec' from
1243 sec->data_offset. */
1244 static void *section_ptr_add(Section *sec, unsigned long size)
1246 unsigned long offset, offset1;
1248 offset = sec->data_offset;
1249 offset1 = offset + size;
1250 if (offset1 > sec->data_allocated)
1251 section_realloc(sec, offset1);
1252 sec->data_offset = offset1;
1253 return sec->data + offset;
1256 /* return a reference to a section, and create it if it does not
1257 exists */
1258 Section *find_section(TCCState *s1, const char *name)
1260 Section *sec;
1261 int i;
1262 for(i = 1; i < s1->nb_sections; i++) {
1263 sec = s1->sections[i];
1264 if (!strcmp(name, sec->name))
1265 return sec;
1267 /* sections are created as PROGBITS */
1268 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1271 #define SECTION_ABS ((void *)1)
1273 /* update sym->c so that it points to an external symbol in section
1274 'section' with value 'value' */
1275 static void put_extern_sym2(Sym *sym, Section *section,
1276 unsigned long value, unsigned long size,
1277 int can_add_underscore)
1279 int sym_type, sym_bind, sh_num, info;
1280 Elf32_Sym *esym;
1281 const char *name;
1282 char buf1[256];
1284 if (section == NULL)
1285 sh_num = SHN_UNDEF;
1286 else if (section == SECTION_ABS)
1287 sh_num = SHN_ABS;
1288 else
1289 sh_num = section->sh_num;
1290 if (!sym->c) {
1291 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1292 sym_type = STT_FUNC;
1293 else
1294 sym_type = STT_OBJECT;
1295 if (sym->type.t & VT_STATIC)
1296 sym_bind = STB_LOCAL;
1297 else
1298 sym_bind = STB_GLOBAL;
1300 name = get_tok_str(sym->v, NULL);
1301 #ifdef CONFIG_TCC_BCHECK
1302 if (do_bounds_check) {
1303 char buf[32];
1305 /* XXX: avoid doing that for statics ? */
1306 /* if bound checking is activated, we change some function
1307 names by adding the "__bound" prefix */
1308 switch(sym->v) {
1309 #if 0
1310 /* XXX: we rely only on malloc hooks */
1311 case TOK_malloc:
1312 case TOK_free:
1313 case TOK_realloc:
1314 case TOK_memalign:
1315 case TOK_calloc:
1316 #endif
1317 case TOK_memcpy:
1318 case TOK_memmove:
1319 case TOK_memset:
1320 case TOK_strlen:
1321 case TOK_strcpy:
1322 case TOK__alloca:
1323 strcpy(buf, "__bound_");
1324 strcat(buf, name);
1325 name = buf;
1326 break;
1329 #endif
1330 if (tcc_state->leading_underscore && can_add_underscore) {
1331 buf1[0] = '_';
1332 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1333 name = buf1;
1335 info = ELF32_ST_INFO(sym_bind, sym_type);
1336 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
1337 } else {
1338 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1339 esym->st_value = value;
1340 esym->st_size = size;
1341 esym->st_shndx = sh_num;
1345 static void put_extern_sym(Sym *sym, Section *section,
1346 unsigned long value, unsigned long size)
1348 put_extern_sym2(sym, section, value, size, 1);
1351 /* add a new relocation entry to symbol 'sym' in section 's' */
1352 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1354 if (!sym->c)
1355 put_extern_sym(sym, NULL, 0, 0);
1356 /* now we can add ELF relocation info */
1357 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1360 static inline int isid(int c)
1362 return (c >= 'a' && c <= 'z') ||
1363 (c >= 'A' && c <= 'Z') ||
1364 c == '_';
1367 static inline int isnum(int c)
1369 return c >= '0' && c <= '9';
1372 static inline int isoct(int c)
1374 return c >= '0' && c <= '7';
1377 static inline int toup(int c)
1379 if (c >= 'a' && c <= 'z')
1380 return c - 'a' + 'A';
1381 else
1382 return c;
1385 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1387 int len;
1388 len = strlen(buf);
1389 vsnprintf(buf + len, buf_size - len, fmt, ap);
1392 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1394 va_list ap;
1395 va_start(ap, fmt);
1396 strcat_vprintf(buf, buf_size, fmt, ap);
1397 va_end(ap);
1400 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1402 char buf[2048];
1403 BufferedFile **f;
1405 buf[0] = '\0';
1406 if (file) {
1407 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1408 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1409 (*f)->filename, (*f)->line_num);
1410 if (file->line_num > 0) {
1411 strcat_printf(buf, sizeof(buf),
1412 "%s:%d: ", file->filename, file->line_num);
1413 } else {
1414 strcat_printf(buf, sizeof(buf),
1415 "%s: ", file->filename);
1417 } else {
1418 strcat_printf(buf, sizeof(buf),
1419 "tcc: ");
1421 if (is_warning)
1422 strcat_printf(buf, sizeof(buf), "warning: ");
1423 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1425 if (!s1->error_func) {
1426 /* default case: stderr */
1427 fprintf(stderr, "%s\n", buf);
1428 } else {
1429 s1->error_func(s1->error_opaque, buf);
1431 if (!is_warning || s1->warn_error)
1432 s1->nb_errors++;
1435 #ifdef LIBTCC
1436 void tcc_set_error_func(TCCState *s, void *error_opaque,
1437 void (*error_func)(void *opaque, const char *msg))
1439 s->error_opaque = error_opaque;
1440 s->error_func = error_func;
1442 #endif
1444 /* error without aborting current compilation */
1445 void error_noabort(const char *fmt, ...)
1447 TCCState *s1 = tcc_state;
1448 va_list ap;
1450 va_start(ap, fmt);
1451 error1(s1, 0, fmt, ap);
1452 va_end(ap);
1455 void error(const char *fmt, ...)
1457 TCCState *s1 = tcc_state;
1458 va_list ap;
1460 va_start(ap, fmt);
1461 error1(s1, 0, fmt, ap);
1462 va_end(ap);
1463 /* better than nothing: in some cases, we accept to handle errors */
1464 if (s1->error_set_jmp_enabled) {
1465 longjmp(s1->error_jmp_buf, 1);
1466 } else {
1467 /* XXX: eliminate this someday */
1468 exit(1);
1472 void expect(const char *msg)
1474 error("%s expected", msg);
1477 void warning(const char *fmt, ...)
1479 TCCState *s1 = tcc_state;
1480 va_list ap;
1482 if (s1->warn_none)
1483 return;
1485 va_start(ap, fmt);
1486 error1(s1, 1, fmt, ap);
1487 va_end(ap);
1490 void skip(int c)
1492 if (tok != c)
1493 error("'%c' expected", c);
1494 next();
1497 static void test_lvalue(void)
1499 if (!(vtop->r & VT_LVAL))
1500 expect("lvalue");
1503 /* allocate a new token */
1504 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1506 TokenSym *ts, **ptable;
1507 int i;
1509 if (tok_ident >= SYM_FIRST_ANOM)
1510 error("memory full");
1512 /* expand token table if needed */
1513 i = tok_ident - TOK_IDENT;
1514 if ((i % TOK_ALLOC_INCR) == 0) {
1515 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1516 if (!ptable)
1517 error("memory full");
1518 table_ident = ptable;
1521 ts = tcc_malloc(sizeof(TokenSym) + len);
1522 table_ident[i] = ts;
1523 ts->tok = tok_ident++;
1524 ts->sym_define = NULL;
1525 ts->sym_label = NULL;
1526 ts->sym_struct = NULL;
1527 ts->sym_identifier = NULL;
1528 ts->len = len;
1529 ts->hash_next = NULL;
1530 memcpy(ts->str, str, len);
1531 ts->str[len] = '\0';
1532 *pts = ts;
1533 return ts;
1536 #define TOK_HASH_INIT 1
1537 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1539 /* find a token and add it if not found */
1540 static TokenSym *tok_alloc(const char *str, int len)
1542 TokenSym *ts, **pts;
1543 int i;
1544 unsigned int h;
1546 h = TOK_HASH_INIT;
1547 for(i=0;i<len;i++)
1548 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1549 h &= (TOK_HASH_SIZE - 1);
1551 pts = &hash_ident[h];
1552 for(;;) {
1553 ts = *pts;
1554 if (!ts)
1555 break;
1556 if (ts->len == len && !memcmp(ts->str, str, len))
1557 return ts;
1558 pts = &(ts->hash_next);
1560 return tok_alloc_new(pts, str, len);
1563 /* CString handling */
1565 static void cstr_realloc(CString *cstr, int new_size)
1567 int size;
1568 void *data;
1570 size = cstr->size_allocated;
1571 if (size == 0)
1572 size = 8; /* no need to allocate a too small first string */
1573 while (size < new_size)
1574 size = size * 2;
1575 data = tcc_realloc(cstr->data_allocated, size);
1576 if (!data)
1577 error("memory full");
1578 cstr->data_allocated = data;
1579 cstr->size_allocated = size;
1580 cstr->data = data;
1583 /* add a byte */
1584 static inline void cstr_ccat(CString *cstr, int ch)
1586 int size;
1587 size = cstr->size + 1;
1588 if (size > cstr->size_allocated)
1589 cstr_realloc(cstr, size);
1590 ((unsigned char *)cstr->data)[size - 1] = ch;
1591 cstr->size = size;
1594 static void cstr_cat(CString *cstr, const char *str)
1596 int c;
1597 for(;;) {
1598 c = *str;
1599 if (c == '\0')
1600 break;
1601 cstr_ccat(cstr, c);
1602 str++;
1606 /* add a wide char */
1607 static void cstr_wccat(CString *cstr, int ch)
1609 int size;
1610 size = cstr->size + sizeof(nwchar_t);
1611 if (size > cstr->size_allocated)
1612 cstr_realloc(cstr, size);
1613 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1614 cstr->size = size;
1617 static void cstr_new(CString *cstr)
1619 memset(cstr, 0, sizeof(CString));
1622 /* free string and reset it to NULL */
1623 static void cstr_free(CString *cstr)
1625 tcc_free(cstr->data_allocated);
1626 cstr_new(cstr);
1629 #define cstr_reset(cstr) cstr_free(cstr)
1631 /* XXX: unicode ? */
1632 static void add_char(CString *cstr, int c)
1634 if (c == '\'' || c == '\"' || c == '\\') {
1635 /* XXX: could be more precise if char or string */
1636 cstr_ccat(cstr, '\\');
1638 if (c >= 32 && c <= 126) {
1639 cstr_ccat(cstr, c);
1640 } else {
1641 cstr_ccat(cstr, '\\');
1642 if (c == '\n') {
1643 cstr_ccat(cstr, 'n');
1644 } else {
1645 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1646 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1647 cstr_ccat(cstr, '0' + (c & 7));
1652 /* XXX: buffer overflow */
1653 /* XXX: float tokens */
1654 char *get_tok_str(int v, CValue *cv)
1656 static char buf[STRING_MAX_SIZE + 1];
1657 static CString cstr_buf;
1658 CString *cstr;
1659 unsigned char *q;
1660 char *p;
1661 int i, len;
1663 /* NOTE: to go faster, we give a fixed buffer for small strings */
1664 cstr_reset(&cstr_buf);
1665 cstr_buf.data = buf;
1666 cstr_buf.size_allocated = sizeof(buf);
1667 p = buf;
1669 switch(v) {
1670 case TOK_CINT:
1671 case TOK_CUINT:
1672 /* XXX: not quite exact, but only useful for testing */
1673 sprintf(p, "%u", cv->ui);
1674 break;
1675 case TOK_CLLONG:
1676 case TOK_CULLONG:
1677 /* XXX: not quite exact, but only useful for testing */
1678 sprintf(p, "%Lu", cv->ull);
1679 break;
1680 case TOK_CCHAR:
1681 case TOK_LCHAR:
1682 cstr_ccat(&cstr_buf, '\'');
1683 add_char(&cstr_buf, cv->i);
1684 cstr_ccat(&cstr_buf, '\'');
1685 cstr_ccat(&cstr_buf, '\0');
1686 break;
1687 case TOK_PPNUM:
1688 cstr = cv->cstr;
1689 len = cstr->size - 1;
1690 for(i=0;i<len;i++)
1691 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1692 cstr_ccat(&cstr_buf, '\0');
1693 break;
1694 case TOK_STR:
1695 case TOK_LSTR:
1696 cstr = cv->cstr;
1697 cstr_ccat(&cstr_buf, '\"');
1698 if (v == TOK_STR) {
1699 len = cstr->size - 1;
1700 for(i=0;i<len;i++)
1701 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1702 } else {
1703 len = (cstr->size / sizeof(nwchar_t)) - 1;
1704 for(i=0;i<len;i++)
1705 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1707 cstr_ccat(&cstr_buf, '\"');
1708 cstr_ccat(&cstr_buf, '\0');
1709 break;
1710 case TOK_LT:
1711 v = '<';
1712 goto addv;
1713 case TOK_GT:
1714 v = '>';
1715 goto addv;
1716 case TOK_DOTS:
1717 return strcpy(p, "...");
1718 case TOK_A_SHL:
1719 return strcpy(p, "<<=");
1720 case TOK_A_SAR:
1721 return strcpy(p, ">>=");
1722 default:
1723 if (v < TOK_IDENT) {
1724 /* search in two bytes table */
1725 q = tok_two_chars;
1726 while (*q) {
1727 if (q[2] == v) {
1728 *p++ = q[0];
1729 *p++ = q[1];
1730 *p = '\0';
1731 return buf;
1733 q += 3;
1735 addv:
1736 *p++ = v;
1737 *p = '\0';
1738 } else if (v < tok_ident) {
1739 return table_ident[v - TOK_IDENT]->str;
1740 } else if (v >= SYM_FIRST_ANOM) {
1741 /* special name for anonymous symbol */
1742 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1743 } else {
1744 /* should never happen */
1745 return NULL;
1747 break;
1749 return cstr_buf.data;
1752 /* push, without hashing */
1753 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1755 Sym *s;
1756 s = sym_malloc();
1757 s->v = v;
1758 s->type.t = t;
1759 s->c = c;
1760 s->next = NULL;
1761 /* add in stack */
1762 s->prev = *ps;
1763 *ps = s;
1764 return s;
1767 /* find a symbol and return its associated structure. 's' is the top
1768 of the symbol stack */
1769 static Sym *sym_find2(Sym *s, int v)
1771 while (s) {
1772 if (s->v == v)
1773 return s;
1774 s = s->prev;
1776 return NULL;
1779 /* structure lookup */
1780 static inline Sym *struct_find(int v)
1782 v -= TOK_IDENT;
1783 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1784 return NULL;
1785 return table_ident[v]->sym_struct;
1788 /* find an identifier */
1789 static inline Sym *sym_find(int v)
1791 v -= TOK_IDENT;
1792 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1793 return NULL;
1794 return table_ident[v]->sym_identifier;
1797 /* push a given symbol on the symbol stack */
1798 static Sym *sym_push(int v, CType *type, int r, int c)
1800 Sym *s, **ps;
1801 TokenSym *ts;
1803 if (local_stack)
1804 ps = &local_stack;
1805 else
1806 ps = &global_stack;
1807 s = sym_push2(ps, v, type->t, c);
1808 s->type.ref = type->ref;
1809 s->r = r;
1810 /* don't record fields or anonymous symbols */
1811 /* XXX: simplify */
1812 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1813 /* record symbol in token array */
1814 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1815 if (v & SYM_STRUCT)
1816 ps = &ts->sym_struct;
1817 else
1818 ps = &ts->sym_identifier;
1819 s->prev_tok = *ps;
1820 *ps = s;
1822 return s;
1825 /* push a global identifier */
1826 static Sym *global_identifier_push(int v, int t, int c)
1828 Sym *s, **ps;
1829 s = sym_push2(&global_stack, v, t, c);
1830 /* don't record anonymous symbol */
1831 if (v < SYM_FIRST_ANOM) {
1832 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1833 /* modify the top most local identifier, so that
1834 sym_identifier will point to 's' when popped */
1835 while (*ps != NULL)
1836 ps = &(*ps)->prev_tok;
1837 s->prev_tok = NULL;
1838 *ps = s;
1840 return s;
1843 /* pop symbols until top reaches 'b' */
1844 static void sym_pop(Sym **ptop, Sym *b)
1846 Sym *s, *ss, **ps;
1847 TokenSym *ts;
1848 int v;
1850 s = *ptop;
1851 while(s != b) {
1852 ss = s->prev;
1853 v = s->v;
1854 /* remove symbol in token array */
1855 /* XXX: simplify */
1856 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1857 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1858 if (v & SYM_STRUCT)
1859 ps = &ts->sym_struct;
1860 else
1861 ps = &ts->sym_identifier;
1862 *ps = s->prev_tok;
1864 sym_free(s);
1865 s = ss;
1867 *ptop = b;
1870 /* I/O layer */
1872 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1874 int fd;
1875 BufferedFile *bf;
1877 fd = open(filename, O_RDONLY | O_BINARY);
1878 if (fd < 0)
1879 return NULL;
1880 bf = tcc_malloc(sizeof(BufferedFile));
1881 if (!bf) {
1882 close(fd);
1883 return NULL;
1885 bf->fd = fd;
1886 bf->buf_ptr = bf->buffer;
1887 bf->buf_end = bf->buffer;
1888 bf->buffer[0] = CH_EOB; /* put eob symbol */
1889 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1890 normalize_slashes(bf->filename);
1891 bf->line_num = 1;
1892 bf->ifndef_macro = 0;
1893 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1894 // printf("opening '%s'\n", filename);
1895 return bf;
1898 void tcc_close(BufferedFile *bf)
1900 total_lines += bf->line_num;
1901 close(bf->fd);
1902 tcc_free(bf);
1905 /* fill input buffer and peek next char */
1906 static int tcc_peekc_slow(BufferedFile *bf)
1908 int len;
1909 /* only tries to read if really end of buffer */
1910 if (bf->buf_ptr >= bf->buf_end) {
1911 if (bf->fd != -1) {
1912 #if defined(PARSE_DEBUG)
1913 len = 8;
1914 #else
1915 len = IO_BUF_SIZE;
1916 #endif
1917 len = read(bf->fd, bf->buffer, len);
1918 if (len < 0)
1919 len = 0;
1920 } else {
1921 len = 0;
1923 total_bytes += len;
1924 bf->buf_ptr = bf->buffer;
1925 bf->buf_end = bf->buffer + len;
1926 *bf->buf_end = CH_EOB;
1928 if (bf->buf_ptr < bf->buf_end) {
1929 return bf->buf_ptr[0];
1930 } else {
1931 bf->buf_ptr = bf->buf_end;
1932 return CH_EOF;
1936 /* return the current character, handling end of block if necessary
1937 (but not stray) */
1938 static int handle_eob(void)
1940 return tcc_peekc_slow(file);
1943 /* read next char from current input file and handle end of input buffer */
1944 static inline void inp(void)
1946 ch = *(++(file->buf_ptr));
1947 /* end of buffer/file handling */
1948 if (ch == CH_EOB)
1949 ch = handle_eob();
1952 /* handle '\[\r]\n' */
1953 static void handle_stray(void)
1955 while (ch == '\\') {
1956 inp();
1957 if (ch == '\n') {
1958 file->line_num++;
1959 inp();
1960 } else if (ch == '\r') {
1961 inp();
1962 if (ch != '\n')
1963 goto fail;
1964 file->line_num++;
1965 inp();
1966 } else {
1967 fail:
1968 error("stray '\\' in program");
1973 /* skip the stray and handle the \\n case. Output an error if
1974 incorrect char after the stray */
1975 static int handle_stray1(uint8_t *p)
1977 int c;
1979 if (p >= file->buf_end) {
1980 file->buf_ptr = p;
1981 c = handle_eob();
1982 p = file->buf_ptr;
1983 if (c == '\\')
1984 goto parse_stray;
1985 } else {
1986 parse_stray:
1987 file->buf_ptr = p;
1988 ch = *p;
1989 handle_stray();
1990 p = file->buf_ptr;
1991 c = *p;
1993 return c;
1996 /* handle just the EOB case, but not stray */
1997 #define PEEKC_EOB(c, p)\
1999 p++;\
2000 c = *p;\
2001 if (c == '\\') {\
2002 file->buf_ptr = p;\
2003 c = handle_eob();\
2004 p = file->buf_ptr;\
2008 /* handle the complicated stray case */
2009 #define PEEKC(c, p)\
2011 p++;\
2012 c = *p;\
2013 if (c == '\\') {\
2014 c = handle_stray1(p);\
2015 p = file->buf_ptr;\
2019 /* input with '\[\r]\n' handling. Note that this function cannot
2020 handle other characters after '\', so you cannot call it inside
2021 strings or comments */
2022 static void minp(void)
2024 inp();
2025 if (ch == '\\')
2026 handle_stray();
2030 /* single line C++ comments */
2031 static uint8_t *parse_line_comment(uint8_t *p)
2033 int c;
2035 p++;
2036 for(;;) {
2037 c = *p;
2038 redo:
2039 if (c == '\n' || c == CH_EOF) {
2040 break;
2041 } else if (c == '\\') {
2042 file->buf_ptr = p;
2043 c = handle_eob();
2044 p = file->buf_ptr;
2045 if (c == '\\') {
2046 PEEKC_EOB(c, p);
2047 if (c == '\n') {
2048 file->line_num++;
2049 PEEKC_EOB(c, p);
2050 } else if (c == '\r') {
2051 PEEKC_EOB(c, p);
2052 if (c == '\n') {
2053 file->line_num++;
2054 PEEKC_EOB(c, p);
2057 } else {
2058 goto redo;
2060 } else {
2061 p++;
2064 return p;
2067 /* C comments */
2068 static uint8_t *parse_comment(uint8_t *p)
2070 int c;
2072 p++;
2073 for(;;) {
2074 /* fast skip loop */
2075 for(;;) {
2076 c = *p;
2077 if (c == '\n' || c == '*' || c == '\\')
2078 break;
2079 p++;
2080 c = *p;
2081 if (c == '\n' || c == '*' || c == '\\')
2082 break;
2083 p++;
2085 /* now we can handle all the cases */
2086 if (c == '\n') {
2087 file->line_num++;
2088 p++;
2089 } else if (c == '*') {
2090 p++;
2091 for(;;) {
2092 c = *p;
2093 if (c == '*') {
2094 p++;
2095 } else if (c == '/') {
2096 goto end_of_comment;
2097 } else if (c == '\\') {
2098 file->buf_ptr = p;
2099 c = handle_eob();
2100 p = file->buf_ptr;
2101 if (c == '\\') {
2102 /* skip '\[\r]\n', otherwise just skip the stray */
2103 while (c == '\\') {
2104 PEEKC_EOB(c, p);
2105 if (c == '\n') {
2106 file->line_num++;
2107 PEEKC_EOB(c, p);
2108 } else if (c == '\r') {
2109 PEEKC_EOB(c, p);
2110 if (c == '\n') {
2111 file->line_num++;
2112 PEEKC_EOB(c, p);
2114 } else {
2115 goto after_star;
2119 } else {
2120 break;
2123 after_star: ;
2124 } else {
2125 /* stray, eob or eof */
2126 file->buf_ptr = p;
2127 c = handle_eob();
2128 p = file->buf_ptr;
2129 if (c == CH_EOF) {
2130 error("unexpected end of file in comment");
2131 } else if (c == '\\') {
2132 p++;
2136 end_of_comment:
2137 p++;
2138 return p;
2141 #define cinp minp
2143 /* space exlcuding newline */
2144 static inline int is_space(int ch)
2146 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2149 static inline void skip_spaces(void)
2151 while (is_space(ch))
2152 cinp();
2155 /* parse a string without interpreting escapes */
2156 static uint8_t *parse_pp_string(uint8_t *p,
2157 int sep, CString *str)
2159 int c;
2160 p++;
2161 for(;;) {
2162 c = *p;
2163 if (c == sep) {
2164 break;
2165 } else if (c == '\\') {
2166 file->buf_ptr = p;
2167 c = handle_eob();
2168 p = file->buf_ptr;
2169 if (c == CH_EOF) {
2170 unterminated_string:
2171 /* XXX: indicate line number of start of string */
2172 error("missing terminating %c character", sep);
2173 } else if (c == '\\') {
2174 /* escape : just skip \[\r]\n */
2175 PEEKC_EOB(c, p);
2176 if (c == '\n') {
2177 file->line_num++;
2178 p++;
2179 } else if (c == '\r') {
2180 PEEKC_EOB(c, p);
2181 if (c != '\n')
2182 expect("'\n' after '\r'");
2183 file->line_num++;
2184 p++;
2185 } else if (c == CH_EOF) {
2186 goto unterminated_string;
2187 } else {
2188 if (str) {
2189 cstr_ccat(str, '\\');
2190 cstr_ccat(str, c);
2192 p++;
2195 } else if (c == '\n') {
2196 file->line_num++;
2197 goto add_char;
2198 } else if (c == '\r') {
2199 PEEKC_EOB(c, p);
2200 if (c != '\n') {
2201 if (str)
2202 cstr_ccat(str, '\r');
2203 } else {
2204 file->line_num++;
2205 goto add_char;
2207 } else {
2208 add_char:
2209 if (str)
2210 cstr_ccat(str, c);
2211 p++;
2214 p++;
2215 return p;
2218 /* skip block of text until #else, #elif or #endif. skip also pairs of
2219 #if/#endif */
2220 void preprocess_skip(void)
2222 int a, start_of_line, c;
2223 uint8_t *p;
2225 p = file->buf_ptr;
2226 start_of_line = 1;
2227 a = 0;
2228 for(;;) {
2229 redo_no_start:
2230 c = *p;
2231 switch(c) {
2232 case ' ':
2233 case '\t':
2234 case '\f':
2235 case '\v':
2236 case '\r':
2237 p++;
2238 goto redo_no_start;
2239 case '\n':
2240 start_of_line = 1;
2241 file->line_num++;
2242 p++;
2243 goto redo_no_start;
2244 case '\\':
2245 file->buf_ptr = p;
2246 c = handle_eob();
2247 if (c == CH_EOF) {
2248 expect("#endif");
2249 } else if (c == '\\') {
2250 /* XXX: incorrect: should not give an error */
2251 ch = file->buf_ptr[0];
2252 handle_stray();
2254 p = file->buf_ptr;
2255 goto redo_no_start;
2256 /* skip strings */
2257 case '\"':
2258 case '\'':
2259 p = parse_pp_string(p, c, NULL);
2260 break;
2261 /* skip comments */
2262 case '/':
2263 file->buf_ptr = p;
2264 ch = *p;
2265 minp();
2266 p = file->buf_ptr;
2267 if (ch == '*') {
2268 p = parse_comment(p);
2269 } else if (ch == '/') {
2270 p = parse_line_comment(p);
2272 break;
2274 case '#':
2275 p++;
2276 if (start_of_line) {
2277 file->buf_ptr = p;
2278 next_nomacro();
2279 p = file->buf_ptr;
2280 if (a == 0 &&
2281 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2282 goto the_end;
2283 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2284 a++;
2285 else if (tok == TOK_ENDIF)
2286 a--;
2288 break;
2289 default:
2290 p++;
2291 break;
2293 start_of_line = 0;
2295 the_end: ;
2296 file->buf_ptr = p;
2299 /* ParseState handling */
2301 /* XXX: currently, no include file info is stored. Thus, we cannot display
2302 accurate messages if the function or data definition spans multiple
2303 files */
2305 /* save current parse state in 's' */
2306 void save_parse_state(ParseState *s)
2308 s->line_num = file->line_num;
2309 s->macro_ptr = macro_ptr;
2310 s->tok = tok;
2311 s->tokc = tokc;
2314 /* restore parse state from 's' */
2315 void restore_parse_state(ParseState *s)
2317 file->line_num = s->line_num;
2318 macro_ptr = s->macro_ptr;
2319 tok = s->tok;
2320 tokc = s->tokc;
2323 /* return the number of additional 'ints' necessary to store the
2324 token */
2325 static inline int tok_ext_size(int t)
2327 switch(t) {
2328 /* 4 bytes */
2329 case TOK_CINT:
2330 case TOK_CUINT:
2331 case TOK_CCHAR:
2332 case TOK_LCHAR:
2333 case TOK_CFLOAT:
2334 case TOK_LINENUM:
2335 return 1;
2336 case TOK_STR:
2337 case TOK_LSTR:
2338 case TOK_PPNUM:
2339 error("unsupported token");
2340 return 1;
2341 case TOK_CDOUBLE:
2342 case TOK_CLLONG:
2343 case TOK_CULLONG:
2344 return 2;
2345 case TOK_CLDOUBLE:
2346 return LDOUBLE_SIZE / 4;
2347 default:
2348 return 0;
2352 /* token string handling */
2354 static inline void tok_str_new(TokenString *s)
2356 s->str = NULL;
2357 s->len = 0;
2358 s->allocated_len = 0;
2359 s->last_line_num = -1;
2362 static void tok_str_free(int *str)
2364 tcc_free(str);
2367 static int *tok_str_realloc(TokenString *s)
2369 int *str, len;
2371 if (s->allocated_len == 0) {
2372 len = 8;
2373 } else {
2374 len = s->allocated_len * 2;
2376 str = tcc_realloc(s->str, len * sizeof(int));
2377 if (!str)
2378 error("memory full");
2379 s->allocated_len = len;
2380 s->str = str;
2381 return str;
2384 static void tok_str_add(TokenString *s, int t)
2386 int len, *str;
2388 len = s->len;
2389 str = s->str;
2390 if (len >= s->allocated_len)
2391 str = tok_str_realloc(s);
2392 str[len++] = t;
2393 s->len = len;
2396 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2398 int len, *str;
2400 len = s->len;
2401 str = s->str;
2403 /* allocate space for worst case */
2404 if (len + TOK_MAX_SIZE > s->allocated_len)
2405 str = tok_str_realloc(s);
2406 str[len++] = t;
2407 switch(t) {
2408 case TOK_CINT:
2409 case TOK_CUINT:
2410 case TOK_CCHAR:
2411 case TOK_LCHAR:
2412 case TOK_CFLOAT:
2413 case TOK_LINENUM:
2414 str[len++] = cv->tab[0];
2415 break;
2416 case TOK_PPNUM:
2417 case TOK_STR:
2418 case TOK_LSTR:
2420 int nb_words;
2421 CString *cstr;
2423 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2424 while ((len + nb_words) > s->allocated_len)
2425 str = tok_str_realloc(s);
2426 cstr = (CString *)(str + len);
2427 cstr->data = NULL;
2428 cstr->size = cv->cstr->size;
2429 cstr->data_allocated = NULL;
2430 cstr->size_allocated = cstr->size;
2431 memcpy((char *)cstr + sizeof(CString),
2432 cv->cstr->data, cstr->size);
2433 len += nb_words;
2435 break;
2436 case TOK_CDOUBLE:
2437 case TOK_CLLONG:
2438 case TOK_CULLONG:
2439 #if LDOUBLE_SIZE == 8
2440 case TOK_CLDOUBLE:
2441 #endif
2442 str[len++] = cv->tab[0];
2443 str[len++] = cv->tab[1];
2444 break;
2445 #if LDOUBLE_SIZE == 12
2446 case TOK_CLDOUBLE:
2447 str[len++] = cv->tab[0];
2448 str[len++] = cv->tab[1];
2449 str[len++] = cv->tab[2];
2450 #elif LDOUBLE_SIZE != 8
2451 #error add long double size support
2452 #endif
2453 break;
2454 default:
2455 break;
2457 s->len = len;
2460 /* add the current parse token in token string 's' */
2461 static void tok_str_add_tok(TokenString *s)
2463 CValue cval;
2465 /* save line number info */
2466 if (file->line_num != s->last_line_num) {
2467 s->last_line_num = file->line_num;
2468 cval.i = s->last_line_num;
2469 tok_str_add2(s, TOK_LINENUM, &cval);
2471 tok_str_add2(s, tok, &tokc);
2474 #if LDOUBLE_SIZE == 12
2475 #define LDOUBLE_GET(p, cv) \
2476 cv.tab[0] = p[0]; \
2477 cv.tab[1] = p[1]; \
2478 cv.tab[2] = p[2];
2479 #elif LDOUBLE_SIZE == 8
2480 #define LDOUBLE_GET(p, cv) \
2481 cv.tab[0] = p[0]; \
2482 cv.tab[1] = p[1];
2483 #else
2484 #error add long double size support
2485 #endif
2488 /* get a token from an integer array and increment pointer
2489 accordingly. we code it as a macro to avoid pointer aliasing. */
2490 #define TOK_GET(t, p, cv) \
2492 t = *p++; \
2493 switch(t) { \
2494 case TOK_CINT: \
2495 case TOK_CUINT: \
2496 case TOK_CCHAR: \
2497 case TOK_LCHAR: \
2498 case TOK_CFLOAT: \
2499 case TOK_LINENUM: \
2500 cv.tab[0] = *p++; \
2501 break; \
2502 case TOK_STR: \
2503 case TOK_LSTR: \
2504 case TOK_PPNUM: \
2505 cv.cstr = (CString *)p; \
2506 cv.cstr->data = (char *)p + sizeof(CString);\
2507 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2508 break; \
2509 case TOK_CDOUBLE: \
2510 case TOK_CLLONG: \
2511 case TOK_CULLONG: \
2512 cv.tab[0] = p[0]; \
2513 cv.tab[1] = p[1]; \
2514 p += 2; \
2515 break; \
2516 case TOK_CLDOUBLE: \
2517 LDOUBLE_GET(p, cv); \
2518 p += LDOUBLE_SIZE / 4; \
2519 break; \
2520 default: \
2521 break; \
2525 /* defines handling */
2526 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2528 Sym *s;
2530 s = sym_push2(&define_stack, v, macro_type, (int)str);
2531 s->next = first_arg;
2532 table_ident[v - TOK_IDENT]->sym_define = s;
2535 /* undefined a define symbol. Its name is just set to zero */
2536 static void define_undef(Sym *s)
2538 int v;
2539 v = s->v;
2540 if (v >= TOK_IDENT && v < tok_ident)
2541 table_ident[v - TOK_IDENT]->sym_define = NULL;
2542 s->v = 0;
2545 static inline Sym *define_find(int v)
2547 v -= TOK_IDENT;
2548 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2549 return NULL;
2550 return table_ident[v]->sym_define;
2553 /* free define stack until top reaches 'b' */
2554 static void free_defines(Sym *b)
2556 Sym *top, *top1;
2557 int v;
2559 top = define_stack;
2560 while (top != b) {
2561 top1 = top->prev;
2562 /* do not free args or predefined defines */
2563 if (top->c)
2564 tok_str_free((int *)top->c);
2565 v = top->v;
2566 if (v >= TOK_IDENT && v < tok_ident)
2567 table_ident[v - TOK_IDENT]->sym_define = NULL;
2568 sym_free(top);
2569 top = top1;
2571 define_stack = b;
2574 /* label lookup */
2575 static Sym *label_find(int v)
2577 v -= TOK_IDENT;
2578 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2579 return NULL;
2580 return table_ident[v]->sym_label;
2583 static Sym *label_push(Sym **ptop, int v, int flags)
2585 Sym *s, **ps;
2586 s = sym_push2(ptop, v, 0, 0);
2587 s->r = flags;
2588 ps = &table_ident[v - TOK_IDENT]->sym_label;
2589 if (ptop == &global_label_stack) {
2590 /* modify the top most local identifier, so that
2591 sym_identifier will point to 's' when popped */
2592 while (*ps != NULL)
2593 ps = &(*ps)->prev_tok;
2595 s->prev_tok = *ps;
2596 *ps = s;
2597 return s;
2600 /* pop labels until element last is reached. Look if any labels are
2601 undefined. Define symbols if '&&label' was used. */
2602 static void label_pop(Sym **ptop, Sym *slast)
2604 Sym *s, *s1;
2605 for(s = *ptop; s != slast; s = s1) {
2606 s1 = s->prev;
2607 if (s->r == LABEL_DECLARED) {
2608 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2609 } else if (s->r == LABEL_FORWARD) {
2610 error("label '%s' used but not defined",
2611 get_tok_str(s->v, NULL));
2612 } else {
2613 if (s->c) {
2614 /* define corresponding symbol. A size of
2615 1 is put. */
2616 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2619 /* remove label */
2620 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2621 sym_free(s);
2623 *ptop = slast;
2626 /* eval an expression for #if/#elif */
2627 static int expr_preprocess(void)
2629 int c, t;
2630 TokenString str;
2632 tok_str_new(&str);
2633 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2634 next(); /* do macro subst */
2635 if (tok == TOK_DEFINED) {
2636 next_nomacro();
2637 t = tok;
2638 if (t == '(')
2639 next_nomacro();
2640 c = define_find(tok) != 0;
2641 if (t == '(')
2642 next_nomacro();
2643 tok = TOK_CINT;
2644 tokc.i = c;
2645 } else if (tok >= TOK_IDENT) {
2646 /* if undefined macro */
2647 tok = TOK_CINT;
2648 tokc.i = 0;
2650 tok_str_add_tok(&str);
2652 tok_str_add(&str, -1); /* simulate end of file */
2653 tok_str_add(&str, 0);
2654 /* now evaluate C constant expression */
2655 macro_ptr = str.str;
2656 next();
2657 c = expr_const();
2658 macro_ptr = NULL;
2659 tok_str_free(str.str);
2660 return c != 0;
2663 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2664 static void tok_print(int *str)
2666 int t;
2667 CValue cval;
2669 while (1) {
2670 TOK_GET(t, str, cval);
2671 if (!t)
2672 break;
2673 printf(" %s", get_tok_str(t, &cval));
2675 printf("\n");
2677 #endif
2679 /* parse after #define */
2680 static void parse_define(void)
2682 Sym *s, *first, **ps;
2683 int v, t, varg, is_vaargs, c;
2684 TokenString str;
2686 v = tok;
2687 if (v < TOK_IDENT)
2688 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2689 /* XXX: should check if same macro (ANSI) */
2690 first = NULL;
2691 t = MACRO_OBJ;
2692 /* '(' must be just after macro definition for MACRO_FUNC */
2693 c = file->buf_ptr[0];
2694 if (c == '\\')
2695 c = handle_stray1(file->buf_ptr);
2696 if (c == '(') {
2697 next_nomacro();
2698 next_nomacro();
2699 ps = &first;
2700 while (tok != ')') {
2701 varg = tok;
2702 next_nomacro();
2703 is_vaargs = 0;
2704 if (varg == TOK_DOTS) {
2705 varg = TOK___VA_ARGS__;
2706 is_vaargs = 1;
2707 } else if (tok == TOK_DOTS && gnu_ext) {
2708 is_vaargs = 1;
2709 next_nomacro();
2711 if (varg < TOK_IDENT)
2712 error("badly punctuated parameter list");
2713 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2714 *ps = s;
2715 ps = &s->next;
2716 if (tok != ',')
2717 break;
2718 next_nomacro();
2720 t = MACRO_FUNC;
2722 tok_str_new(&str);
2723 next_nomacro();
2724 /* EOF testing necessary for '-D' handling */
2725 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2726 tok_str_add2(&str, tok, &tokc);
2727 next_nomacro();
2729 tok_str_add(&str, 0);
2730 #ifdef PP_DEBUG
2731 printf("define %s %d: ", get_tok_str(v, NULL), t);
2732 tok_print(str.str);
2733 #endif
2734 define_push(v, t, str.str, first);
2737 static inline int hash_cached_include(int type, const char *filename)
2739 const unsigned char *s;
2740 unsigned int h;
2742 h = TOK_HASH_INIT;
2743 h = TOK_HASH_FUNC(h, type);
2744 s = filename;
2745 while (*s) {
2746 h = TOK_HASH_FUNC(h, *s);
2747 s++;
2749 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2750 return h;
2753 /* XXX: use a token or a hash table to accelerate matching ? */
2754 static CachedInclude *search_cached_include(TCCState *s1,
2755 int type, const char *filename)
2757 CachedInclude *e;
2758 int i, h;
2759 h = hash_cached_include(type, filename);
2760 i = s1->cached_includes_hash[h];
2761 for(;;) {
2762 if (i == 0)
2763 break;
2764 e = s1->cached_includes[i - 1];
2765 if (e->type == type && !strcmp(e->filename, filename))
2766 return e;
2767 i = e->hash_next;
2769 return NULL;
2772 static inline void add_cached_include(TCCState *s1, int type,
2773 const char *filename, int ifndef_macro)
2775 CachedInclude *e;
2776 int h;
2778 if (search_cached_include(s1, type, filename))
2779 return;
2780 #ifdef INC_DEBUG
2781 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2782 #endif
2783 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2784 if (!e)
2785 return;
2786 e->type = type;
2787 strcpy(e->filename, filename);
2788 e->ifndef_macro = ifndef_macro;
2789 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2790 /* add in hash table */
2791 h = hash_cached_include(type, filename);
2792 e->hash_next = s1->cached_includes_hash[h];
2793 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2796 static void pragma_parse(TCCState *s1)
2798 int val;
2800 next();
2801 if (tok == TOK_pack) {
2803 This may be:
2804 #pragma pack(1) // set
2805 #pragma pack() // reset to default
2806 #pragma pack(push,1) // push & set
2807 #pragma pack(pop) // restore previous
2809 next();
2810 skip('(');
2811 if (tok == TOK_ASM_pop) {
2812 next();
2813 if (s1->pack_stack_ptr <= s1->pack_stack) {
2814 stk_error:
2815 error("out of pack stack");
2817 s1->pack_stack_ptr--;
2818 } else {
2819 val = 0;
2820 if (tok != ')') {
2821 if (tok == TOK_ASM_push) {
2822 next();
2823 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2824 goto stk_error;
2825 s1->pack_stack_ptr++;
2826 skip(',');
2828 if (tok != TOK_CINT) {
2829 pack_error:
2830 error("invalid pack pragma");
2832 val = tokc.i;
2833 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2834 goto pack_error;
2835 next();
2837 *s1->pack_stack_ptr = val;
2838 skip(')');
2843 /* is_bof is true if first non space token at beginning of file */
2844 static void preprocess(int is_bof)
2846 TCCState *s1 = tcc_state;
2847 int size, i, c, n, saved_parse_flags;
2848 char buf[1024], *q, *p;
2849 char buf1[1024];
2850 BufferedFile *f;
2851 Sym *s;
2852 CachedInclude *e;
2854 saved_parse_flags = parse_flags;
2855 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2856 PARSE_FLAG_LINEFEED;
2857 next_nomacro();
2858 redo:
2859 switch(tok) {
2860 case TOK_DEFINE:
2861 next_nomacro();
2862 parse_define();
2863 break;
2864 case TOK_UNDEF:
2865 next_nomacro();
2866 s = define_find(tok);
2867 /* undefine symbol by putting an invalid name */
2868 if (s)
2869 define_undef(s);
2870 break;
2871 case TOK_INCLUDE:
2872 case TOK_INCLUDE_NEXT:
2873 ch = file->buf_ptr[0];
2874 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2875 skip_spaces();
2876 if (ch == '<') {
2877 c = '>';
2878 goto read_name;
2879 } else if (ch == '\"') {
2880 c = ch;
2881 read_name:
2882 /* XXX: better stray handling */
2883 minp();
2884 q = buf;
2885 while (ch != c && ch != '\n' && ch != CH_EOF) {
2886 if ((q - buf) < sizeof(buf) - 1)
2887 *q++ = ch;
2888 minp();
2890 *q = '\0';
2891 minp();
2892 #if 0
2893 /* eat all spaces and comments after include */
2894 /* XXX: slightly incorrect */
2895 while (ch1 != '\n' && ch1 != CH_EOF)
2896 inp();
2897 #endif
2898 } else {
2899 /* computed #include : either we have only strings or
2900 we have anything enclosed in '<>' */
2901 next();
2902 buf[0] = '\0';
2903 if (tok == TOK_STR) {
2904 while (tok != TOK_LINEFEED) {
2905 if (tok != TOK_STR) {
2906 include_syntax:
2907 error("'#include' expects \"FILENAME\" or <FILENAME>");
2909 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2910 next();
2912 c = '\"';
2913 } else {
2914 int len;
2915 while (tok != TOK_LINEFEED) {
2916 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2917 next();
2919 len = strlen(buf);
2920 /* check syntax and remove '<>' */
2921 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2922 goto include_syntax;
2923 memmove(buf, buf + 1, len - 2);
2924 buf[len - 2] = '\0';
2925 c = '>';
2929 e = search_cached_include(s1, c, buf);
2930 if (e && define_find(e->ifndef_macro)) {
2931 /* no need to parse the include because the 'ifndef macro'
2932 is defined */
2933 #ifdef INC_DEBUG
2934 printf("%s: skipping %s\n", file->filename, buf);
2935 #endif
2936 } else {
2937 if (c == '\"') {
2938 /* first search in current dir if "header.h" */
2939 size = 0;
2940 p = strrchr(file->filename, '/');
2941 if (p)
2942 size = p + 1 - file->filename;
2943 if (size > sizeof(buf1) - 1)
2944 size = sizeof(buf1) - 1;
2945 memcpy(buf1, file->filename, size);
2946 buf1[size] = '\0';
2947 pstrcat(buf1, sizeof(buf1), buf);
2948 f = tcc_open(s1, buf1);
2949 if (f) {
2950 if (tok == TOK_INCLUDE_NEXT)
2951 tok = TOK_INCLUDE;
2952 else
2953 goto found;
2956 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2957 error("#include recursion too deep");
2958 /* now search in all the include paths */
2959 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2960 for(i = 0; i < n; i++) {
2961 const char *path;
2962 if (i < s1->nb_include_paths)
2963 path = s1->include_paths[i];
2964 else
2965 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2966 pstrcpy(buf1, sizeof(buf1), path);
2967 pstrcat(buf1, sizeof(buf1), "/");
2968 pstrcat(buf1, sizeof(buf1), buf);
2969 f = tcc_open(s1, buf1);
2970 if (f) {
2971 if (tok == TOK_INCLUDE_NEXT)
2972 tok = TOK_INCLUDE;
2973 else
2974 goto found;
2977 error("include file '%s' not found", buf);
2978 f = NULL;
2979 found:
2980 #ifdef INC_DEBUG
2981 printf("%s: including %s\n", file->filename, buf1);
2982 #endif
2983 f->inc_type = c;
2984 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2985 /* push current file in stack */
2986 /* XXX: fix current line init */
2987 *s1->include_stack_ptr++ = file;
2988 file = f;
2989 /* add include file debug info */
2990 if (do_debug) {
2991 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2993 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2994 ch = file->buf_ptr[0];
2995 goto the_end;
2997 break;
2998 case TOK_IFNDEF:
2999 c = 1;
3000 goto do_ifdef;
3001 case TOK_IF:
3002 c = expr_preprocess();
3003 goto do_if;
3004 case TOK_IFDEF:
3005 c = 0;
3006 do_ifdef:
3007 next_nomacro();
3008 if (tok < TOK_IDENT)
3009 error("invalid argument for '#if%sdef'", c ? "n" : "");
3010 if (is_bof) {
3011 if (c) {
3012 #ifdef INC_DEBUG
3013 printf("#ifndef %s\n", get_tok_str(tok, NULL));
3014 #endif
3015 file->ifndef_macro = tok;
3018 c = (define_find(tok) != 0) ^ c;
3019 do_if:
3020 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
3021 error("memory full");
3022 *s1->ifdef_stack_ptr++ = c;
3023 goto test_skip;
3024 case TOK_ELSE:
3025 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3026 error("#else without matching #if");
3027 if (s1->ifdef_stack_ptr[-1] & 2)
3028 error("#else after #else");
3029 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3030 goto test_skip;
3031 case TOK_ELIF:
3032 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3033 error("#elif without matching #if");
3034 c = s1->ifdef_stack_ptr[-1];
3035 if (c > 1)
3036 error("#elif after #else");
3037 /* last #if/#elif expression was true: we skip */
3038 if (c == 1)
3039 goto skip;
3040 c = expr_preprocess();
3041 s1->ifdef_stack_ptr[-1] = c;
3042 test_skip:
3043 if (!(c & 1)) {
3044 skip:
3045 preprocess_skip();
3046 is_bof = 0;
3047 goto redo;
3049 break;
3050 case TOK_ENDIF:
3051 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3052 error("#endif without matching #if");
3053 s1->ifdef_stack_ptr--;
3054 /* '#ifndef macro' was at the start of file. Now we check if
3055 an '#endif' is exactly at the end of file */
3056 if (file->ifndef_macro &&
3057 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3058 file->ifndef_macro_saved = file->ifndef_macro;
3059 /* need to set to zero to avoid false matches if another
3060 #ifndef at middle of file */
3061 file->ifndef_macro = 0;
3062 while (tok != TOK_LINEFEED)
3063 next_nomacro();
3064 tok_flags |= TOK_FLAG_ENDIF;
3065 goto the_end;
3067 break;
3068 case TOK_LINE:
3069 next();
3070 if (tok != TOK_CINT)
3071 error("#line");
3072 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3073 next();
3074 if (tok != TOK_LINEFEED) {
3075 if (tok != TOK_STR)
3076 error("#line");
3077 pstrcpy(file->filename, sizeof(file->filename),
3078 (char *)tokc.cstr->data);
3080 break;
3081 case TOK_ERROR:
3082 case TOK_WARNING:
3083 c = tok;
3084 ch = file->buf_ptr[0];
3085 skip_spaces();
3086 q = buf;
3087 while (ch != '\n' && ch != CH_EOF) {
3088 if ((q - buf) < sizeof(buf) - 1)
3089 *q++ = ch;
3090 minp();
3092 *q = '\0';
3093 if (c == TOK_ERROR)
3094 error("#error %s", buf);
3095 else
3096 warning("#warning %s", buf);
3097 break;
3098 case TOK_PRAGMA:
3099 pragma_parse(s1);
3100 break;
3101 default:
3102 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3103 /* '!' is ignored to allow C scripts. numbers are ignored
3104 to emulate cpp behaviour */
3105 } else {
3106 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3107 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
3109 break;
3111 /* ignore other preprocess commands or #! for C scripts */
3112 while (tok != TOK_LINEFEED)
3113 next_nomacro();
3114 the_end:
3115 parse_flags = saved_parse_flags;
3118 /* evaluate escape codes in a string. */
3119 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3121 int c, n;
3122 const uint8_t *p;
3124 p = buf;
3125 for(;;) {
3126 c = *p;
3127 if (c == '\0')
3128 break;
3129 if (c == '\\') {
3130 p++;
3131 /* escape */
3132 c = *p;
3133 switch(c) {
3134 case '0': case '1': case '2': case '3':
3135 case '4': case '5': case '6': case '7':
3136 /* at most three octal digits */
3137 n = c - '0';
3138 p++;
3139 c = *p;
3140 if (isoct(c)) {
3141 n = n * 8 + c - '0';
3142 p++;
3143 c = *p;
3144 if (isoct(c)) {
3145 n = n * 8 + c - '0';
3146 p++;
3149 c = n;
3150 goto add_char_nonext;
3151 case 'x':
3152 case 'u':
3153 case 'U':
3154 p++;
3155 n = 0;
3156 for(;;) {
3157 c = *p;
3158 if (c >= 'a' && c <= 'f')
3159 c = c - 'a' + 10;
3160 else if (c >= 'A' && c <= 'F')
3161 c = c - 'A' + 10;
3162 else if (isnum(c))
3163 c = c - '0';
3164 else
3165 break;
3166 n = n * 16 + c;
3167 p++;
3169 c = n;
3170 goto add_char_nonext;
3171 case 'a':
3172 c = '\a';
3173 break;
3174 case 'b':
3175 c = '\b';
3176 break;
3177 case 'f':
3178 c = '\f';
3179 break;
3180 case 'n':
3181 c = '\n';
3182 break;
3183 case 'r':
3184 c = '\r';
3185 break;
3186 case 't':
3187 c = '\t';
3188 break;
3189 case 'v':
3190 c = '\v';
3191 break;
3192 case 'e':
3193 if (!gnu_ext)
3194 goto invalid_escape;
3195 c = 27;
3196 break;
3197 case '\'':
3198 case '\"':
3199 case '\\':
3200 case '?':
3201 break;
3202 default:
3203 invalid_escape:
3204 if (c >= '!' && c <= '~')
3205 warning("unknown escape sequence: \'\\%c\'", c);
3206 else
3207 warning("unknown escape sequence: \'\\x%x\'", c);
3208 break;
3211 p++;
3212 add_char_nonext:
3213 if (!is_long)
3214 cstr_ccat(outstr, c);
3215 else
3216 cstr_wccat(outstr, c);
3218 /* add a trailing '\0' */
3219 if (!is_long)
3220 cstr_ccat(outstr, '\0');
3221 else
3222 cstr_wccat(outstr, '\0');
3225 /* we use 64 bit numbers */
3226 #define BN_SIZE 2
3228 /* bn = (bn << shift) | or_val */
3229 void bn_lshift(unsigned int *bn, int shift, int or_val)
3231 int i;
3232 unsigned int v;
3233 for(i=0;i<BN_SIZE;i++) {
3234 v = bn[i];
3235 bn[i] = (v << shift) | or_val;
3236 or_val = v >> (32 - shift);
3240 void bn_zero(unsigned int *bn)
3242 int i;
3243 for(i=0;i<BN_SIZE;i++) {
3244 bn[i] = 0;
3248 /* parse number in null terminated string 'p' and return it in the
3249 current token */
3250 void parse_number(const char *p)
3252 int b, t, shift, frac_bits, s, exp_val, ch;
3253 char *q;
3254 unsigned int bn[BN_SIZE];
3255 double d;
3257 /* number */
3258 q = token_buf;
3259 ch = *p++;
3260 t = ch;
3261 ch = *p++;
3262 *q++ = t;
3263 b = 10;
3264 if (t == '.') {
3265 goto float_frac_parse;
3266 } else if (t == '0') {
3267 if (ch == 'x' || ch == 'X') {
3268 q--;
3269 ch = *p++;
3270 b = 16;
3271 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3272 q--;
3273 ch = *p++;
3274 b = 2;
3277 /* parse all digits. cannot check octal numbers at this stage
3278 because of floating point constants */
3279 while (1) {
3280 if (ch >= 'a' && ch <= 'f')
3281 t = ch - 'a' + 10;
3282 else if (ch >= 'A' && ch <= 'F')
3283 t = ch - 'A' + 10;
3284 else if (isnum(ch))
3285 t = ch - '0';
3286 else
3287 break;
3288 if (t >= b)
3289 break;
3290 if (q >= token_buf + STRING_MAX_SIZE) {
3291 num_too_long:
3292 error("number too long");
3294 *q++ = ch;
3295 ch = *p++;
3297 if (ch == '.' ||
3298 ((ch == 'e' || ch == 'E') && b == 10) ||
3299 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3300 if (b != 10) {
3301 /* NOTE: strtox should support that for hexa numbers, but
3302 non ISOC99 libcs do not support it, so we prefer to do
3303 it by hand */
3304 /* hexadecimal or binary floats */
3305 /* XXX: handle overflows */
3306 *q = '\0';
3307 if (b == 16)
3308 shift = 4;
3309 else
3310 shift = 2;
3311 bn_zero(bn);
3312 q = token_buf;
3313 while (1) {
3314 t = *q++;
3315 if (t == '\0') {
3316 break;
3317 } else if (t >= 'a') {
3318 t = t - 'a' + 10;
3319 } else if (t >= 'A') {
3320 t = t - 'A' + 10;
3321 } else {
3322 t = t - '0';
3324 bn_lshift(bn, shift, t);
3326 frac_bits = 0;
3327 if (ch == '.') {
3328 ch = *p++;
3329 while (1) {
3330 t = ch;
3331 if (t >= 'a' && t <= 'f') {
3332 t = t - 'a' + 10;
3333 } else if (t >= 'A' && t <= 'F') {
3334 t = t - 'A' + 10;
3335 } else if (t >= '0' && t <= '9') {
3336 t = t - '0';
3337 } else {
3338 break;
3340 if (t >= b)
3341 error("invalid digit");
3342 bn_lshift(bn, shift, t);
3343 frac_bits += shift;
3344 ch = *p++;
3347 if (ch != 'p' && ch != 'P')
3348 expect("exponent");
3349 ch = *p++;
3350 s = 1;
3351 exp_val = 0;
3352 if (ch == '+') {
3353 ch = *p++;
3354 } else if (ch == '-') {
3355 s = -1;
3356 ch = *p++;
3358 if (ch < '0' || ch > '9')
3359 expect("exponent digits");
3360 while (ch >= '0' && ch <= '9') {
3361 exp_val = exp_val * 10 + ch - '0';
3362 ch = *p++;
3364 exp_val = exp_val * s;
3366 /* now we can generate the number */
3367 /* XXX: should patch directly float number */
3368 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3369 d = ldexp(d, exp_val - frac_bits);
3370 t = toup(ch);
3371 if (t == 'F') {
3372 ch = *p++;
3373 tok = TOK_CFLOAT;
3374 /* float : should handle overflow */
3375 tokc.f = (float)d;
3376 } else if (t == 'L') {
3377 ch = *p++;
3378 tok = TOK_CLDOUBLE;
3379 /* XXX: not large enough */
3380 tokc.ld = (long double)d;
3381 } else {
3382 tok = TOK_CDOUBLE;
3383 tokc.d = d;
3385 } else {
3386 /* decimal floats */
3387 if (ch == '.') {
3388 if (q >= token_buf + STRING_MAX_SIZE)
3389 goto num_too_long;
3390 *q++ = ch;
3391 ch = *p++;
3392 float_frac_parse:
3393 while (ch >= '0' && ch <= '9') {
3394 if (q >= token_buf + STRING_MAX_SIZE)
3395 goto num_too_long;
3396 *q++ = ch;
3397 ch = *p++;
3400 if (ch == 'e' || ch == 'E') {
3401 if (q >= token_buf + STRING_MAX_SIZE)
3402 goto num_too_long;
3403 *q++ = ch;
3404 ch = *p++;
3405 if (ch == '-' || ch == '+') {
3406 if (q >= token_buf + STRING_MAX_SIZE)
3407 goto num_too_long;
3408 *q++ = ch;
3409 ch = *p++;
3411 if (ch < '0' || ch > '9')
3412 expect("exponent digits");
3413 while (ch >= '0' && ch <= '9') {
3414 if (q >= token_buf + STRING_MAX_SIZE)
3415 goto num_too_long;
3416 *q++ = ch;
3417 ch = *p++;
3420 *q = '\0';
3421 t = toup(ch);
3422 errno = 0;
3423 if (t == 'F') {
3424 ch = *p++;
3425 tok = TOK_CFLOAT;
3426 tokc.f = strtof(token_buf, NULL);
3427 } else if (t == 'L') {
3428 ch = *p++;
3429 tok = TOK_CLDOUBLE;
3430 tokc.ld = strtold(token_buf, NULL);
3431 } else {
3432 tok = TOK_CDOUBLE;
3433 tokc.d = strtod(token_buf, NULL);
3436 } else {
3437 unsigned long long n, n1;
3438 int lcount, ucount;
3440 /* integer number */
3441 *q = '\0';
3442 q = token_buf;
3443 if (b == 10 && *q == '0') {
3444 b = 8;
3445 q++;
3447 n = 0;
3448 while(1) {
3449 t = *q++;
3450 /* no need for checks except for base 10 / 8 errors */
3451 if (t == '\0') {
3452 break;
3453 } else if (t >= 'a') {
3454 t = t - 'a' + 10;
3455 } else if (t >= 'A') {
3456 t = t - 'A' + 10;
3457 } else {
3458 t = t - '0';
3459 if (t >= b)
3460 error("invalid digit");
3462 n1 = n;
3463 n = n * b + t;
3464 /* detect overflow */
3465 /* XXX: this test is not reliable */
3466 if (n < n1)
3467 error("integer constant overflow");
3470 /* XXX: not exactly ANSI compliant */
3471 if ((n & 0xffffffff00000000LL) != 0) {
3472 if ((n >> 63) != 0)
3473 tok = TOK_CULLONG;
3474 else
3475 tok = TOK_CLLONG;
3476 } else if (n > 0x7fffffff) {
3477 tok = TOK_CUINT;
3478 } else {
3479 tok = TOK_CINT;
3481 lcount = 0;
3482 ucount = 0;
3483 for(;;) {
3484 t = toup(ch);
3485 if (t == 'L') {
3486 if (lcount >= 2)
3487 error("three 'l's in integer constant");
3488 lcount++;
3489 if (lcount == 2) {
3490 if (tok == TOK_CINT)
3491 tok = TOK_CLLONG;
3492 else if (tok == TOK_CUINT)
3493 tok = TOK_CULLONG;
3495 ch = *p++;
3496 } else if (t == 'U') {
3497 if (ucount >= 1)
3498 error("two 'u's in integer constant");
3499 ucount++;
3500 if (tok == TOK_CINT)
3501 tok = TOK_CUINT;
3502 else if (tok == TOK_CLLONG)
3503 tok = TOK_CULLONG;
3504 ch = *p++;
3505 } else {
3506 break;
3509 if (tok == TOK_CINT || tok == TOK_CUINT)
3510 tokc.ui = n;
3511 else
3512 tokc.ull = n;
3517 #define PARSE2(c1, tok1, c2, tok2) \
3518 case c1: \
3519 PEEKC(c, p); \
3520 if (c == c2) { \
3521 p++; \
3522 tok = tok2; \
3523 } else { \
3524 tok = tok1; \
3526 break;
3528 /* return next token without macro substitution */
3529 static inline void next_nomacro1(void)
3531 int t, c, is_long;
3532 TokenSym *ts;
3533 uint8_t *p, *p1;
3534 unsigned int h;
3536 p = file->buf_ptr;
3537 redo_no_start:
3538 c = *p;
3539 switch(c) {
3540 case ' ':
3541 case '\t':
3542 case '\f':
3543 case '\v':
3544 case '\r':
3545 p++;
3546 goto redo_no_start;
3548 case '\\':
3549 /* first look if it is in fact an end of buffer */
3550 if (p >= file->buf_end) {
3551 file->buf_ptr = p;
3552 handle_eob();
3553 p = file->buf_ptr;
3554 if (p >= file->buf_end)
3555 goto parse_eof;
3556 else
3557 goto redo_no_start;
3558 } else {
3559 file->buf_ptr = p;
3560 ch = *p;
3561 handle_stray();
3562 p = file->buf_ptr;
3563 goto redo_no_start;
3565 parse_eof:
3567 TCCState *s1 = tcc_state;
3568 if ((parse_flags & PARSE_FLAG_LINEFEED)
3569 && !(tok_flags & TOK_FLAG_EOF)) {
3570 tok_flags |= TOK_FLAG_EOF;
3571 tok = TOK_LINEFEED;
3572 goto keep_tok_flags;
3573 } else if (s1->include_stack_ptr == s1->include_stack ||
3574 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3575 /* no include left : end of file. */
3576 tok = TOK_EOF;
3577 } else {
3578 tok_flags &= ~TOK_FLAG_EOF;
3579 /* pop include file */
3581 /* test if previous '#endif' was after a #ifdef at
3582 start of file */
3583 if (tok_flags & TOK_FLAG_ENDIF) {
3584 #ifdef INC_DEBUG
3585 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3586 #endif
3587 add_cached_include(s1, file->inc_type, file->inc_filename,
3588 file->ifndef_macro_saved);
3591 /* add end of include file debug info */
3592 if (do_debug) {
3593 put_stabd(N_EINCL, 0, 0);
3595 /* pop include stack */
3596 tcc_close(file);
3597 s1->include_stack_ptr--;
3598 file = *s1->include_stack_ptr;
3599 p = file->buf_ptr;
3600 goto redo_no_start;
3603 break;
3605 case '\n':
3606 file->line_num++;
3607 tok_flags |= TOK_FLAG_BOL;
3608 p++;
3609 if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
3610 goto redo_no_start;
3611 tok = TOK_LINEFEED;
3612 goto keep_tok_flags;
3614 case '#':
3615 /* XXX: simplify */
3616 PEEKC(c, p);
3617 if ((tok_flags & TOK_FLAG_BOL) &&
3618 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3619 file->buf_ptr = p;
3620 preprocess(tok_flags & TOK_FLAG_BOF);
3621 p = file->buf_ptr;
3622 goto redo_no_start;
3623 } else {
3624 if (c == '#') {
3625 p++;
3626 tok = TOK_TWOSHARPS;
3627 } else {
3628 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3629 p = parse_line_comment(p - 1);
3630 goto redo_no_start;
3631 } else {
3632 tok = '#';
3636 break;
3638 case 'a': case 'b': case 'c': case 'd':
3639 case 'e': case 'f': case 'g': case 'h':
3640 case 'i': case 'j': case 'k': case 'l':
3641 case 'm': case 'n': case 'o': case 'p':
3642 case 'q': case 'r': case 's': case 't':
3643 case 'u': case 'v': case 'w': case 'x':
3644 case 'y': case 'z':
3645 case 'A': case 'B': case 'C': case 'D':
3646 case 'E': case 'F': case 'G': case 'H':
3647 case 'I': case 'J': case 'K':
3648 case 'M': case 'N': case 'O': case 'P':
3649 case 'Q': case 'R': case 'S': case 'T':
3650 case 'U': case 'V': case 'W': case 'X':
3651 case 'Y': case 'Z':
3652 case '_':
3653 parse_ident_fast:
3654 p1 = p;
3655 h = TOK_HASH_INIT;
3656 h = TOK_HASH_FUNC(h, c);
3657 p++;
3658 for(;;) {
3659 c = *p;
3660 if (!isidnum_table[c])
3661 break;
3662 h = TOK_HASH_FUNC(h, c);
3663 p++;
3665 if (c != '\\') {
3666 TokenSym **pts;
3667 int len;
3669 /* fast case : no stray found, so we have the full token
3670 and we have already hashed it */
3671 len = p - p1;
3672 h &= (TOK_HASH_SIZE - 1);
3673 pts = &hash_ident[h];
3674 for(;;) {
3675 ts = *pts;
3676 if (!ts)
3677 break;
3678 if (ts->len == len && !memcmp(ts->str, p1, len))
3679 goto token_found;
3680 pts = &(ts->hash_next);
3682 ts = tok_alloc_new(pts, p1, len);
3683 token_found: ;
3684 } else {
3685 /* slower case */
3686 cstr_reset(&tokcstr);
3688 while (p1 < p) {
3689 cstr_ccat(&tokcstr, *p1);
3690 p1++;
3692 p--;
3693 PEEKC(c, p);
3694 parse_ident_slow:
3695 while (isidnum_table[c]) {
3696 cstr_ccat(&tokcstr, c);
3697 PEEKC(c, p);
3699 ts = tok_alloc(tokcstr.data, tokcstr.size);
3701 tok = ts->tok;
3702 break;
3703 case 'L':
3704 t = p[1];
3705 if (t != '\\' && t != '\'' && t != '\"') {
3706 /* fast case */
3707 goto parse_ident_fast;
3708 } else {
3709 PEEKC(c, p);
3710 if (c == '\'' || c == '\"') {
3711 is_long = 1;
3712 goto str_const;
3713 } else {
3714 cstr_reset(&tokcstr);
3715 cstr_ccat(&tokcstr, 'L');
3716 goto parse_ident_slow;
3719 break;
3720 case '0': case '1': case '2': case '3':
3721 case '4': case '5': case '6': case '7':
3722 case '8': case '9':
3724 cstr_reset(&tokcstr);
3725 /* after the first digit, accept digits, alpha, '.' or sign if
3726 prefixed by 'eEpP' */
3727 parse_num:
3728 for(;;) {
3729 t = c;
3730 cstr_ccat(&tokcstr, c);
3731 PEEKC(c, p);
3732 if (!(isnum(c) || isid(c) || c == '.' ||
3733 ((c == '+' || c == '-') &&
3734 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3735 break;
3737 /* We add a trailing '\0' to ease parsing */
3738 cstr_ccat(&tokcstr, '\0');
3739 tokc.cstr = &tokcstr;
3740 tok = TOK_PPNUM;
3741 break;
3742 case '.':
3743 /* special dot handling because it can also start a number */
3744 PEEKC(c, p);
3745 if (isnum(c)) {
3746 cstr_reset(&tokcstr);
3747 cstr_ccat(&tokcstr, '.');
3748 goto parse_num;
3749 } else if (c == '.') {
3750 PEEKC(c, p);
3751 if (c != '.')
3752 expect("'.'");
3753 PEEKC(c, p);
3754 tok = TOK_DOTS;
3755 } else {
3756 tok = '.';
3758 break;
3759 case '\'':
3760 case '\"':
3761 is_long = 0;
3762 str_const:
3764 CString str;
3765 int sep;
3767 sep = c;
3769 /* parse the string */
3770 cstr_new(&str);
3771 p = parse_pp_string(p, sep, &str);
3772 cstr_ccat(&str, '\0');
3774 /* eval the escape (should be done as TOK_PPNUM) */
3775 cstr_reset(&tokcstr);
3776 parse_escape_string(&tokcstr, str.data, is_long);
3777 cstr_free(&str);
3779 if (sep == '\'') {
3780 int char_size;
3781 /* XXX: make it portable */
3782 if (!is_long)
3783 char_size = 1;
3784 else
3785 char_size = sizeof(nwchar_t);
3786 if (tokcstr.size <= char_size)
3787 error("empty character constant");
3788 if (tokcstr.size > 2 * char_size)
3789 warning("multi-character character constant");
3790 if (!is_long) {
3791 tokc.i = *(int8_t *)tokcstr.data;
3792 tok = TOK_CCHAR;
3793 } else {
3794 tokc.i = *(nwchar_t *)tokcstr.data;
3795 tok = TOK_LCHAR;
3797 } else {
3798 tokc.cstr = &tokcstr;
3799 if (!is_long)
3800 tok = TOK_STR;
3801 else
3802 tok = TOK_LSTR;
3805 break;
3807 case '<':
3808 PEEKC(c, p);
3809 if (c == '=') {
3810 p++;
3811 tok = TOK_LE;
3812 } else if (c == '<') {
3813 PEEKC(c, p);
3814 if (c == '=') {
3815 p++;
3816 tok = TOK_A_SHL;
3817 } else {
3818 tok = TOK_SHL;
3820 } else {
3821 tok = TOK_LT;
3823 break;
3825 case '>':
3826 PEEKC(c, p);
3827 if (c == '=') {
3828 p++;
3829 tok = TOK_GE;
3830 } else if (c == '>') {
3831 PEEKC(c, p);
3832 if (c == '=') {
3833 p++;
3834 tok = TOK_A_SAR;
3835 } else {
3836 tok = TOK_SAR;
3838 } else {
3839 tok = TOK_GT;
3841 break;
3843 case '&':
3844 PEEKC(c, p);
3845 if (c == '&') {
3846 p++;
3847 tok = TOK_LAND;
3848 } else if (c == '=') {
3849 p++;
3850 tok = TOK_A_AND;
3851 } else {
3852 tok = '&';
3854 break;
3856 case '|':
3857 PEEKC(c, p);
3858 if (c == '|') {
3859 p++;
3860 tok = TOK_LOR;
3861 } else if (c == '=') {
3862 p++;
3863 tok = TOK_A_OR;
3864 } else {
3865 tok = '|';
3867 break;
3869 case '+':
3870 PEEKC(c, p);
3871 if (c == '+') {
3872 p++;
3873 tok = TOK_INC;
3874 } else if (c == '=') {
3875 p++;
3876 tok = TOK_A_ADD;
3877 } else {
3878 tok = '+';
3880 break;
3882 case '-':
3883 PEEKC(c, p);
3884 if (c == '-') {
3885 p++;
3886 tok = TOK_DEC;
3887 } else if (c == '=') {
3888 p++;
3889 tok = TOK_A_SUB;
3890 } else if (c == '>') {
3891 p++;
3892 tok = TOK_ARROW;
3893 } else {
3894 tok = '-';
3896 break;
3898 PARSE2('!', '!', '=', TOK_NE)
3899 PARSE2('=', '=', '=', TOK_EQ)
3900 PARSE2('*', '*', '=', TOK_A_MUL)
3901 PARSE2('%', '%', '=', TOK_A_MOD)
3902 PARSE2('^', '^', '=', TOK_A_XOR)
3904 /* comments or operator */
3905 case '/':
3906 PEEKC(c, p);
3907 if (c == '*') {
3908 p = parse_comment(p);
3909 goto redo_no_start;
3910 } else if (c == '/') {
3911 p = parse_line_comment(p);
3912 goto redo_no_start;
3913 } else if (c == '=') {
3914 p++;
3915 tok = TOK_A_DIV;
3916 } else {
3917 tok = '/';
3919 break;
3921 /* simple tokens */
3922 case '(':
3923 case ')':
3924 case '[':
3925 case ']':
3926 case '{':
3927 case '}':
3928 case ',':
3929 case ';':
3930 case ':':
3931 case '?':
3932 case '~':
3933 case '$': /* only used in assembler */
3934 case '@': /* dito */
3935 tok = c;
3936 p++;
3937 break;
3938 default:
3939 error("unrecognized character \\x%02x", c);
3940 break;
3942 tok_flags = 0;
3943 keep_tok_flags:
3944 file->buf_ptr = p;
3945 #if defined(PARSE_DEBUG)
3946 printf("token = %s\n", get_tok_str(tok, &tokc));
3947 #endif
3950 /* return next token without macro substitution. Can read input from
3951 macro_ptr buffer */
3952 static void next_nomacro(void)
3954 if (macro_ptr) {
3955 redo:
3956 tok = *macro_ptr;
3957 if (tok) {
3958 TOK_GET(tok, macro_ptr, tokc);
3959 if (tok == TOK_LINENUM) {
3960 file->line_num = tokc.i;
3961 goto redo;
3964 } else {
3965 next_nomacro1();
3969 /* substitute args in macro_str and return allocated string */
3970 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3972 int *st, last_tok, t, notfirst;
3973 Sym *s;
3974 CValue cval;
3975 TokenString str;
3976 CString cstr;
3978 tok_str_new(&str);
3979 last_tok = 0;
3980 while(1) {
3981 TOK_GET(t, macro_str, cval);
3982 if (!t)
3983 break;
3984 if (t == '#') {
3985 /* stringize */
3986 TOK_GET(t, macro_str, cval);
3987 if (!t)
3988 break;
3989 s = sym_find2(args, t);
3990 if (s) {
3991 cstr_new(&cstr);
3992 st = (int *)s->c;
3993 notfirst = 0;
3994 while (*st) {
3995 if (notfirst)
3996 cstr_ccat(&cstr, ' ');
3997 TOK_GET(t, st, cval);
3998 cstr_cat(&cstr, get_tok_str(t, &cval));
3999 notfirst = 1;
4001 cstr_ccat(&cstr, '\0');
4002 #ifdef PP_DEBUG
4003 printf("stringize: %s\n", (char *)cstr.data);
4004 #endif
4005 /* add string */
4006 cval.cstr = &cstr;
4007 tok_str_add2(&str, TOK_STR, &cval);
4008 cstr_free(&cstr);
4009 } else {
4010 tok_str_add2(&str, t, &cval);
4012 } else if (t >= TOK_IDENT) {
4013 s = sym_find2(args, t);
4014 if (s) {
4015 st = (int *)s->c;
4016 /* if '##' is present before or after, no arg substitution */
4017 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
4018 /* special case for var arg macros : ## eats the
4019 ',' if empty VA_ARGS variable. */
4020 /* XXX: test of the ',' is not 100%
4021 reliable. should fix it to avoid security
4022 problems */
4023 if (gnu_ext && s->type.t &&
4024 last_tok == TOK_TWOSHARPS &&
4025 str.len >= 2 && str.str[str.len - 2] == ',') {
4026 if (*st == 0) {
4027 /* suppress ',' '##' */
4028 str.len -= 2;
4029 } else {
4030 /* suppress '##' and add variable */
4031 str.len--;
4032 goto add_var;
4034 } else {
4035 int t1;
4036 add_var:
4037 for(;;) {
4038 TOK_GET(t1, st, cval);
4039 if (!t1)
4040 break;
4041 tok_str_add2(&str, t1, &cval);
4044 } else {
4045 /* NOTE: the stream cannot be read when macro
4046 substituing an argument */
4047 macro_subst(&str, nested_list, st, NULL);
4049 } else {
4050 tok_str_add(&str, t);
4052 } else {
4053 tok_str_add2(&str, t, &cval);
4055 last_tok = t;
4057 tok_str_add(&str, 0);
4058 return str.str;
4061 static char const ab_month_name[12][4] =
4063 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4064 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4067 /* do macro substitution of current token with macro 's' and add
4068 result to (tok_str,tok_len). 'nested_list' is the list of all
4069 macros we got inside to avoid recursing. Return non zero if no
4070 substitution needs to be done */
4071 static int macro_subst_tok(TokenString *tok_str,
4072 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4074 Sym *args, *sa, *sa1;
4075 int mstr_allocated, parlevel, *mstr, t, t1;
4076 TokenString str;
4077 char *cstrval;
4078 CValue cval;
4079 CString cstr;
4080 char buf[32];
4082 /* if symbol is a macro, prepare substitution */
4083 /* special macros */
4084 if (tok == TOK___LINE__) {
4085 snprintf(buf, sizeof(buf), "%d", file->line_num);
4086 cstrval = buf;
4087 t1 = TOK_PPNUM;
4088 goto add_cstr1;
4089 } else if (tok == TOK___FILE__) {
4090 cstrval = file->filename;
4091 goto add_cstr;
4092 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4093 time_t ti;
4094 struct tm *tm;
4096 time(&ti);
4097 tm = localtime(&ti);
4098 if (tok == TOK___DATE__) {
4099 snprintf(buf, sizeof(buf), "%s %2d %d",
4100 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4101 } else {
4102 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4103 tm->tm_hour, tm->tm_min, tm->tm_sec);
4105 cstrval = buf;
4106 add_cstr:
4107 t1 = TOK_STR;
4108 add_cstr1:
4109 cstr_new(&cstr);
4110 cstr_cat(&cstr, cstrval);
4111 cstr_ccat(&cstr, '\0');
4112 cval.cstr = &cstr;
4113 tok_str_add2(tok_str, t1, &cval);
4114 cstr_free(&cstr);
4115 } else {
4116 mstr = (int *)s->c;
4117 mstr_allocated = 0;
4118 if (s->type.t == MACRO_FUNC) {
4119 /* NOTE: we do not use next_nomacro to avoid eating the
4120 next token. XXX: find better solution */
4121 redo:
4122 if (macro_ptr) {
4123 t = *macro_ptr;
4124 if (t == 0 && can_read_stream) {
4125 /* end of macro stream: we must look at the token
4126 after in the file */
4127 struct macro_level *ml = *can_read_stream;
4128 macro_ptr = NULL;
4129 if (ml)
4131 macro_ptr = ml->p;
4132 ml->p = NULL;
4133 *can_read_stream = ml -> prev;
4135 goto redo;
4137 } else {
4138 /* XXX: incorrect with comments */
4139 ch = file->buf_ptr[0];
4140 while (is_space(ch) || ch == '\n')
4141 cinp();
4142 t = ch;
4144 if (t != '(') /* no macro subst */
4145 return -1;
4147 /* argument macro */
4148 next_nomacro();
4149 next_nomacro();
4150 args = NULL;
4151 sa = s->next;
4152 /* NOTE: empty args are allowed, except if no args */
4153 for(;;) {
4154 /* handle '()' case */
4155 if (!args && !sa && tok == ')')
4156 break;
4157 if (!sa)
4158 error("macro '%s' used with too many args",
4159 get_tok_str(s->v, 0));
4160 tok_str_new(&str);
4161 parlevel = 0;
4162 /* NOTE: non zero sa->t indicates VA_ARGS */
4163 while ((parlevel > 0 ||
4164 (tok != ')' &&
4165 (tok != ',' || sa->type.t))) &&
4166 tok != -1) {
4167 if (tok == '(')
4168 parlevel++;
4169 else if (tok == ')')
4170 parlevel--;
4171 if (tok != TOK_LINEFEED)
4172 tok_str_add2(&str, tok, &tokc);
4173 next_nomacro();
4175 tok_str_add(&str, 0);
4176 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4177 sa = sa->next;
4178 if (tok == ')') {
4179 /* special case for gcc var args: add an empty
4180 var arg argument if it is omitted */
4181 if (sa && sa->type.t && gnu_ext)
4182 continue;
4183 else
4184 break;
4186 if (tok != ',')
4187 expect(",");
4188 next_nomacro();
4190 if (sa) {
4191 error("macro '%s' used with too few args",
4192 get_tok_str(s->v, 0));
4195 /* now subst each arg */
4196 mstr = macro_arg_subst(nested_list, mstr, args);
4197 /* free memory */
4198 sa = args;
4199 while (sa) {
4200 sa1 = sa->prev;
4201 tok_str_free((int *)sa->c);
4202 sym_free(sa);
4203 sa = sa1;
4205 mstr_allocated = 1;
4207 sym_push2(nested_list, s->v, 0, 0);
4208 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4209 /* pop nested defined symbol */
4210 sa1 = *nested_list;
4211 *nested_list = sa1->prev;
4212 sym_free(sa1);
4213 if (mstr_allocated)
4214 tok_str_free(mstr);
4216 return 0;
4219 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4220 return the resulting string (which must be freed). */
4221 static inline int *macro_twosharps(const int *macro_str)
4223 TokenSym *ts;
4224 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4225 int t;
4226 const char *p1, *p2;
4227 CValue cval;
4228 TokenString macro_str1;
4229 CString cstr;
4231 start_macro_ptr = macro_str;
4232 /* we search the first '##' */
4233 for(;;) {
4234 macro_ptr1 = macro_str;
4235 TOK_GET(t, macro_str, cval);
4236 /* nothing more to do if end of string */
4237 if (t == 0)
4238 return NULL;
4239 if (*macro_str == TOK_TWOSHARPS)
4240 break;
4243 /* we saw '##', so we need more processing to handle it */
4244 cstr_new(&cstr);
4245 tok_str_new(&macro_str1);
4246 tok = t;
4247 tokc = cval;
4249 /* add all tokens seen so far */
4250 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4251 TOK_GET(t, ptr, cval);
4252 tok_str_add2(&macro_str1, t, &cval);
4254 saved_macro_ptr = macro_ptr;
4255 /* XXX: get rid of the use of macro_ptr here */
4256 macro_ptr = (int *)macro_str;
4257 for(;;) {
4258 while (*macro_ptr == TOK_TWOSHARPS) {
4259 macro_ptr++;
4260 macro_ptr1 = macro_ptr;
4261 t = *macro_ptr;
4262 if (t) {
4263 TOK_GET(t, macro_ptr, cval);
4264 /* We concatenate the two tokens if we have an
4265 identifier or a preprocessing number */
4266 cstr_reset(&cstr);
4267 p1 = get_tok_str(tok, &tokc);
4268 cstr_cat(&cstr, p1);
4269 p2 = get_tok_str(t, &cval);
4270 cstr_cat(&cstr, p2);
4271 cstr_ccat(&cstr, '\0');
4273 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4274 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4275 if (tok == TOK_PPNUM) {
4276 /* if number, then create a number token */
4277 /* NOTE: no need to allocate because
4278 tok_str_add2() does it */
4279 cstr_reset(&tokcstr);
4280 tokcstr = cstr;
4281 cstr_new(&cstr);
4282 tokc.cstr = &tokcstr;
4283 } else {
4284 /* if identifier, we must do a test to
4285 validate we have a correct identifier */
4286 if (t == TOK_PPNUM) {
4287 const char *p;
4288 int c;
4290 p = p2;
4291 for(;;) {
4292 c = *p;
4293 if (c == '\0')
4294 break;
4295 p++;
4296 if (!isnum(c) && !isid(c))
4297 goto error_pasting;
4300 ts = tok_alloc(cstr.data, strlen(cstr.data));
4301 tok = ts->tok; /* modify current token */
4303 } else {
4304 const char *str = cstr.data;
4305 const unsigned char *q;
4307 /* we look for a valid token */
4308 /* XXX: do more extensive checks */
4309 if (!strcmp(str, ">>=")) {
4310 tok = TOK_A_SAR;
4311 } else if (!strcmp(str, "<<=")) {
4312 tok = TOK_A_SHL;
4313 } else if (strlen(str) == 2) {
4314 /* search in two bytes table */
4315 q = tok_two_chars;
4316 for(;;) {
4317 if (!*q)
4318 goto error_pasting;
4319 if (q[0] == str[0] && q[1] == str[1])
4320 break;
4321 q += 3;
4323 tok = q[2];
4324 } else {
4325 error_pasting:
4326 /* NOTE: because get_tok_str use a static buffer,
4327 we must save it */
4328 cstr_reset(&cstr);
4329 p1 = get_tok_str(tok, &tokc);
4330 cstr_cat(&cstr, p1);
4331 cstr_ccat(&cstr, '\0');
4332 p2 = get_tok_str(t, &cval);
4333 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4334 /* cannot merge tokens: just add them separately */
4335 tok_str_add2(&macro_str1, tok, &tokc);
4336 /* XXX: free associated memory ? */
4337 tok = t;
4338 tokc = cval;
4343 tok_str_add2(&macro_str1, tok, &tokc);
4344 next_nomacro();
4345 if (tok == 0)
4346 break;
4348 macro_ptr = (int *)saved_macro_ptr;
4349 cstr_free(&cstr);
4350 tok_str_add(&macro_str1, 0);
4351 return macro_str1.str;
4355 /* do macro substitution of macro_str and add result to
4356 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4357 inside to avoid recursing. */
4358 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4359 const int *macro_str, struct macro_level ** can_read_stream)
4361 Sym *s;
4362 int *macro_str1;
4363 const int *ptr;
4364 int t, ret;
4365 CValue cval;
4366 struct macro_level ml;
4368 /* first scan for '##' operator handling */
4369 ptr = macro_str;
4370 macro_str1 = macro_twosharps(ptr);
4371 if (macro_str1)
4372 ptr = macro_str1;
4373 while (1) {
4374 /* NOTE: ptr == NULL can only happen if tokens are read from
4375 file stream due to a macro function call */
4376 if (ptr == NULL)
4377 break;
4378 TOK_GET(t, ptr, cval);
4379 if (t == 0)
4380 break;
4381 s = define_find(t);
4382 if (s != NULL) {
4383 /* if nested substitution, do nothing */
4384 if (sym_find2(*nested_list, t))
4385 goto no_subst;
4386 ml.p = macro_ptr;
4387 if (can_read_stream)
4388 ml.prev = *can_read_stream, *can_read_stream = &ml;
4389 macro_ptr = (int *)ptr;
4390 tok = t;
4391 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4392 ptr = (int *)macro_ptr;
4393 macro_ptr = ml.p;
4394 if (can_read_stream && *can_read_stream == &ml)
4395 *can_read_stream = ml.prev;
4396 if (ret != 0)
4397 goto no_subst;
4398 } else {
4399 no_subst:
4400 tok_str_add2(tok_str, t, &cval);
4403 if (macro_str1)
4404 tok_str_free(macro_str1);
4407 /* return next token with macro substitution */
4408 static void next(void)
4410 Sym *nested_list, *s;
4411 TokenString str;
4412 struct macro_level *ml;
4414 redo:
4415 next_nomacro();
4416 if (!macro_ptr) {
4417 /* if not reading from macro substituted string, then try
4418 to substitute macros */
4419 if (tok >= TOK_IDENT &&
4420 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4421 s = define_find(tok);
4422 if (s) {
4423 /* we have a macro: we try to substitute */
4424 tok_str_new(&str);
4425 nested_list = NULL;
4426 ml = NULL;
4427 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4428 /* substitution done, NOTE: maybe empty */
4429 tok_str_add(&str, 0);
4430 macro_ptr = str.str;
4431 macro_ptr_allocated = str.str;
4432 goto redo;
4436 } else {
4437 if (tok == 0) {
4438 /* end of macro or end of unget buffer */
4439 if (unget_buffer_enabled) {
4440 macro_ptr = unget_saved_macro_ptr;
4441 unget_buffer_enabled = 0;
4442 } else {
4443 /* end of macro string: free it */
4444 tok_str_free(macro_ptr_allocated);
4445 macro_ptr = NULL;
4447 goto redo;
4451 /* convert preprocessor tokens into C tokens */
4452 if (tok == TOK_PPNUM &&
4453 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4454 parse_number((char *)tokc.cstr->data);
4458 /* push back current token and set current token to 'last_tok'. Only
4459 identifier case handled for labels. */
4460 static inline void unget_tok(int last_tok)
4462 int i, n;
4463 int *q;
4464 unget_saved_macro_ptr = macro_ptr;
4465 unget_buffer_enabled = 1;
4466 q = unget_saved_buffer;
4467 macro_ptr = q;
4468 *q++ = tok;
4469 n = tok_ext_size(tok) - 1;
4470 for(i=0;i<n;i++)
4471 *q++ = tokc.tab[i];
4472 *q = 0; /* end of token string */
4473 tok = last_tok;
4477 void swap(int *p, int *q)
4479 int t;
4480 t = *p;
4481 *p = *q;
4482 *q = t;
4485 void vsetc(CType *type, int r, CValue *vc)
4487 int v;
4489 if (vtop >= vstack + (VSTACK_SIZE - 1))
4490 error("memory full");
4491 /* cannot let cpu flags if other instruction are generated. Also
4492 avoid leaving VT_JMP anywhere except on the top of the stack
4493 because it would complicate the code generator. */
4494 if (vtop >= vstack) {
4495 v = vtop->r & VT_VALMASK;
4496 if (v == VT_CMP || (v & ~1) == VT_JMP)
4497 gv(RC_INT);
4499 vtop++;
4500 vtop->type = *type;
4501 vtop->r = r;
4502 vtop->r2 = VT_CONST;
4503 vtop->c = *vc;
4506 /* push integer constant */
4507 void vpushi(int v)
4509 CValue cval;
4510 cval.i = v;
4511 vsetc(&int_type, VT_CONST, &cval);
4514 /* Return a static symbol pointing to a section */
4515 static Sym *get_sym_ref(CType *type, Section *sec,
4516 unsigned long offset, unsigned long size)
4518 int v;
4519 Sym *sym;
4521 v = anon_sym++;
4522 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4523 sym->type.ref = type->ref;
4524 sym->r = VT_CONST | VT_SYM;
4525 put_extern_sym(sym, sec, offset, size);
4526 return sym;
4529 /* push a reference to a section offset by adding a dummy symbol */
4530 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4532 CValue cval;
4534 cval.ul = 0;
4535 vsetc(type, VT_CONST | VT_SYM, &cval);
4536 vtop->sym = get_sym_ref(type, sec, offset, size);
4539 /* define a new external reference to a symbol 'v' of type 'u' */
4540 static Sym *external_global_sym(int v, CType *type, int r)
4542 Sym *s;
4544 s = sym_find(v);
4545 if (!s) {
4546 /* push forward reference */
4547 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4548 s->type.ref = type->ref;
4549 s->r = r | VT_CONST | VT_SYM;
4551 return s;
4554 /* define a new external reference to a symbol 'v' of type 'u' */
4555 static Sym *external_sym(int v, CType *type, int r)
4557 Sym *s;
4559 s = sym_find(v);
4560 if (!s) {
4561 /* push forward reference */
4562 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4563 s->type.t |= VT_EXTERN;
4564 } else {
4565 if (!is_compatible_types(&s->type, type))
4566 error("incompatible types for redefinition of '%s'",
4567 get_tok_str(v, NULL));
4569 return s;
4572 /* push a reference to global symbol v */
4573 static void vpush_global_sym(CType *type, int v)
4575 Sym *sym;
4576 CValue cval;
4578 sym = external_global_sym(v, type, 0);
4579 cval.ul = 0;
4580 vsetc(type, VT_CONST | VT_SYM, &cval);
4581 vtop->sym = sym;
4584 void vset(CType *type, int r, int v)
4586 CValue cval;
4588 cval.i = v;
4589 vsetc(type, r, &cval);
4592 void vseti(int r, int v)
4594 CType type;
4595 type.t = VT_INT;
4596 vset(&type, r, v);
4599 void vswap(void)
4601 SValue tmp;
4603 tmp = vtop[0];
4604 vtop[0] = vtop[-1];
4605 vtop[-1] = tmp;
4608 void vpushv(SValue *v)
4610 if (vtop >= vstack + (VSTACK_SIZE - 1))
4611 error("memory full");
4612 vtop++;
4613 *vtop = *v;
4616 void vdup(void)
4618 vpushv(vtop);
4621 /* save r to the memory stack, and mark it as being free */
4622 void save_reg(int r)
4624 int l, saved, size, align;
4625 SValue *p, sv;
4626 CType *type;
4628 /* modify all stack values */
4629 saved = 0;
4630 l = 0;
4631 for(p=vstack;p<=vtop;p++) {
4632 if ((p->r & VT_VALMASK) == r ||
4633 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4634 /* must save value on stack if not already done */
4635 if (!saved) {
4636 /* NOTE: must reload 'r' because r might be equal to r2 */
4637 r = p->r & VT_VALMASK;
4638 /* store register in the stack */
4639 type = &p->type;
4640 if ((p->r & VT_LVAL) ||
4641 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4642 type = &int_type;
4643 size = type_size(type, &align);
4644 loc = (loc - size) & -align;
4645 sv.type.t = type->t;
4646 sv.r = VT_LOCAL | VT_LVAL;
4647 sv.c.ul = loc;
4648 store(r, &sv);
4649 #ifdef TCC_TARGET_I386
4650 /* x86 specific: need to pop fp register ST0 if saved */
4651 if (r == TREG_ST0) {
4652 o(0xd9dd); /* fstp %st(1) */
4654 #endif
4655 /* special long long case */
4656 if ((type->t & VT_BTYPE) == VT_LLONG) {
4657 sv.c.ul += 4;
4658 store(p->r2, &sv);
4660 l = loc;
4661 saved = 1;
4663 /* mark that stack entry as being saved on the stack */
4664 if (p->r & VT_LVAL) {
4665 /* also clear the bounded flag because the
4666 relocation address of the function was stored in
4667 p->c.ul */
4668 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4669 } else {
4670 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4672 p->r2 = VT_CONST;
4673 p->c.ul = l;
4678 /* find a register of class 'rc2' with at most one reference on stack.
4679 * If none, call get_reg(rc) */
4680 int get_reg_ex(int rc, int rc2)
4682 int r;
4683 SValue *p;
4685 for(r=0;r<NB_REGS;r++) {
4686 if (reg_classes[r] & rc2) {
4687 int n;
4688 n=0;
4689 for(p = vstack; p <= vtop; p++) {
4690 if ((p->r & VT_VALMASK) == r ||
4691 (p->r2 & VT_VALMASK) == r)
4692 n++;
4694 if (n <= 1)
4695 return r;
4698 return get_reg(rc);
4701 /* find a free register of class 'rc'. If none, save one register */
4702 int get_reg(int rc)
4704 int r;
4705 SValue *p;
4707 /* find a free register */
4708 for(r=0;r<NB_REGS;r++) {
4709 if (reg_classes[r] & rc) {
4710 for(p=vstack;p<=vtop;p++) {
4711 if ((p->r & VT_VALMASK) == r ||
4712 (p->r2 & VT_VALMASK) == r)
4713 goto notfound;
4715 return r;
4717 notfound: ;
4720 /* no register left : free the first one on the stack (VERY
4721 IMPORTANT to start from the bottom to ensure that we don't
4722 spill registers used in gen_opi()) */
4723 for(p=vstack;p<=vtop;p++) {
4724 r = p->r & VT_VALMASK;
4725 if (r < VT_CONST && (reg_classes[r] & rc))
4726 goto save_found;
4727 /* also look at second register (if long long) */
4728 r = p->r2 & VT_VALMASK;
4729 if (r < VT_CONST && (reg_classes[r] & rc)) {
4730 save_found:
4731 save_reg(r);
4732 return r;
4735 /* Should never comes here */
4736 return -1;
4739 /* save registers up to (vtop - n) stack entry */
4740 void save_regs(int n)
4742 int r;
4743 SValue *p, *p1;
4744 p1 = vtop - n;
4745 for(p = vstack;p <= p1; p++) {
4746 r = p->r & VT_VALMASK;
4747 if (r < VT_CONST) {
4748 save_reg(r);
4753 /* move register 's' to 'r', and flush previous value of r to memory
4754 if needed */
4755 void move_reg(int r, int s)
4757 SValue sv;
4759 if (r != s) {
4760 save_reg(r);
4761 sv.type.t = VT_INT;
4762 sv.r = s;
4763 sv.c.ul = 0;
4764 load(r, &sv);
4768 /* get address of vtop (vtop MUST BE an lvalue) */
4769 void gaddrof(void)
4771 vtop->r &= ~VT_LVAL;
4772 /* tricky: if saved lvalue, then we can go back to lvalue */
4773 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4774 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4777 #ifdef CONFIG_TCC_BCHECK
4778 /* generate lvalue bound code */
4779 void gbound(void)
4781 int lval_type;
4782 CType type1;
4784 vtop->r &= ~VT_MUSTBOUND;
4785 /* if lvalue, then use checking code before dereferencing */
4786 if (vtop->r & VT_LVAL) {
4787 /* if not VT_BOUNDED value, then make one */
4788 if (!(vtop->r & VT_BOUNDED)) {
4789 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4790 /* must save type because we must set it to int to get pointer */
4791 type1 = vtop->type;
4792 vtop->type.t = VT_INT;
4793 gaddrof();
4794 vpushi(0);
4795 gen_bounded_ptr_add();
4796 vtop->r |= lval_type;
4797 vtop->type = type1;
4799 /* then check for dereferencing */
4800 gen_bounded_ptr_deref();
4803 #endif
4805 /* store vtop a register belonging to class 'rc'. lvalues are
4806 converted to values. Cannot be used if cannot be converted to
4807 register value (such as structures). */
4808 int gv(int rc)
4810 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4811 unsigned long long ll;
4813 /* NOTE: get_reg can modify vstack[] */
4814 if (vtop->type.t & VT_BITFIELD) {
4815 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4816 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4817 /* remove bit field info to avoid loops */
4818 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4819 /* generate shifts */
4820 vpushi(32 - (bit_pos + bit_size));
4821 gen_op(TOK_SHL);
4822 vpushi(32 - bit_size);
4823 /* NOTE: transformed to SHR if unsigned */
4824 gen_op(TOK_SAR);
4825 r = gv(rc);
4826 } else {
4827 if (is_float(vtop->type.t) &&
4828 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4829 Sym *sym;
4830 int *ptr;
4831 unsigned long offset;
4832 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4833 CValue check;
4834 #endif
4836 /* XXX: unify with initializers handling ? */
4837 /* CPUs usually cannot use float constants, so we store them
4838 generically in data segment */
4839 size = type_size(&vtop->type, &align);
4840 offset = (data_section->data_offset + align - 1) & -align;
4841 data_section->data_offset = offset;
4842 /* XXX: not portable yet */
4843 #ifdef __i386__
4844 /* Zero pad x87 tenbyte long doubles */
4845 if (size == 12)
4846 vtop->c.tab[2] &= 0xffff;
4847 #endif
4848 ptr = section_ptr_add(data_section, size);
4849 size = size >> 2;
4850 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4851 check.d = 1;
4852 if(check.tab[0])
4853 for(i=0;i<size;i++)
4854 ptr[i] = vtop->c.tab[size-1-i];
4855 else
4856 #endif
4857 for(i=0;i<size;i++)
4858 ptr[i] = vtop->c.tab[i];
4859 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4860 vtop->r |= VT_LVAL | VT_SYM;
4861 vtop->sym = sym;
4862 vtop->c.ul = 0;
4864 #ifdef CONFIG_TCC_BCHECK
4865 if (vtop->r & VT_MUSTBOUND)
4866 gbound();
4867 #endif
4869 r = vtop->r & VT_VALMASK;
4870 /* need to reload if:
4871 - constant
4872 - lvalue (need to dereference pointer)
4873 - already a register, but not in the right class */
4874 if (r >= VT_CONST ||
4875 (vtop->r & VT_LVAL) ||
4876 !(reg_classes[r] & rc) ||
4877 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4878 !(reg_classes[vtop->r2] & rc))) {
4879 r = get_reg(rc);
4880 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4881 /* two register type load : expand to two words
4882 temporarily */
4883 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4884 /* load constant */
4885 ll = vtop->c.ull;
4886 vtop->c.ui = ll; /* first word */
4887 load(r, vtop);
4888 vtop->r = r; /* save register value */
4889 vpushi(ll >> 32); /* second word */
4890 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4891 (vtop->r & VT_LVAL)) {
4892 /* We do not want to modifier the long long
4893 pointer here, so the safest (and less
4894 efficient) is to save all the other registers
4895 in the stack. XXX: totally inefficient. */
4896 save_regs(1);
4897 /* load from memory */
4898 load(r, vtop);
4899 vdup();
4900 vtop[-1].r = r; /* save register value */
4901 /* increment pointer to get second word */
4902 vtop->type.t = VT_INT;
4903 gaddrof();
4904 vpushi(4);
4905 gen_op('+');
4906 vtop->r |= VT_LVAL;
4907 } else {
4908 /* move registers */
4909 load(r, vtop);
4910 vdup();
4911 vtop[-1].r = r; /* save register value */
4912 vtop->r = vtop[-1].r2;
4914 /* allocate second register */
4915 rc2 = RC_INT;
4916 if (rc == RC_IRET)
4917 rc2 = RC_LRET;
4918 r2 = get_reg(rc2);
4919 load(r2, vtop);
4920 vpop();
4921 /* write second register */
4922 vtop->r2 = r2;
4923 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4924 int t1, t;
4925 /* lvalue of scalar type : need to use lvalue type
4926 because of possible cast */
4927 t = vtop->type.t;
4928 t1 = t;
4929 /* compute memory access type */
4930 if (vtop->r & VT_LVAL_BYTE)
4931 t = VT_BYTE;
4932 else if (vtop->r & VT_LVAL_SHORT)
4933 t = VT_SHORT;
4934 if (vtop->r & VT_LVAL_UNSIGNED)
4935 t |= VT_UNSIGNED;
4936 vtop->type.t = t;
4937 load(r, vtop);
4938 /* restore wanted type */
4939 vtop->type.t = t1;
4940 } else {
4941 /* one register type load */
4942 load(r, vtop);
4945 vtop->r = r;
4946 #ifdef TCC_TARGET_C67
4947 /* uses register pairs for doubles */
4948 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4949 vtop->r2 = r+1;
4950 #endif
4952 return r;
4955 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4956 void gv2(int rc1, int rc2)
4958 int v;
4960 /* generate more generic register first. But VT_JMP or VT_CMP
4961 values must be generated first in all cases to avoid possible
4962 reload errors */
4963 v = vtop[0].r & VT_VALMASK;
4964 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4965 vswap();
4966 gv(rc1);
4967 vswap();
4968 gv(rc2);
4969 /* test if reload is needed for first register */
4970 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4971 vswap();
4972 gv(rc1);
4973 vswap();
4975 } else {
4976 gv(rc2);
4977 vswap();
4978 gv(rc1);
4979 vswap();
4980 /* test if reload is needed for first register */
4981 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4982 gv(rc2);
4987 /* expand long long on stack in two int registers */
4988 void lexpand(void)
4990 int u;
4992 u = vtop->type.t & VT_UNSIGNED;
4993 gv(RC_INT);
4994 vdup();
4995 vtop[0].r = vtop[-1].r2;
4996 vtop[0].r2 = VT_CONST;
4997 vtop[-1].r2 = VT_CONST;
4998 vtop[0].type.t = VT_INT | u;
4999 vtop[-1].type.t = VT_INT | u;
5002 #ifdef TCC_TARGET_ARM
5003 /* expand long long on stack */
5004 void lexpand_nr(void)
5006 int u,v;
5008 u = vtop->type.t & VT_UNSIGNED;
5009 vdup();
5010 vtop->r2 = VT_CONST;
5011 vtop->type.t = VT_INT | u;
5012 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
5013 if (v == VT_CONST) {
5014 vtop[-1].c.ui = vtop->c.ull;
5015 vtop->c.ui = vtop->c.ull >> 32;
5016 vtop->r = VT_CONST;
5017 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
5018 vtop->c.ui += 4;
5019 vtop->r = vtop[-1].r;
5020 } else if (v > VT_CONST) {
5021 vtop--;
5022 lexpand();
5023 } else
5024 vtop->r = vtop[-1].r2;
5025 vtop[-1].r2 = VT_CONST;
5026 vtop[-1].type.t = VT_INT | u;
5028 #endif
5030 /* build a long long from two ints */
5031 void lbuild(int t)
5033 gv2(RC_INT, RC_INT);
5034 vtop[-1].r2 = vtop[0].r;
5035 vtop[-1].type.t = t;
5036 vpop();
5039 /* rotate n first stack elements to the bottom
5040 I1 ... In -> I2 ... In I1 [top is right]
5042 void vrotb(int n)
5044 int i;
5045 SValue tmp;
5047 tmp = vtop[-n + 1];
5048 for(i=-n+1;i!=0;i++)
5049 vtop[i] = vtop[i+1];
5050 vtop[0] = tmp;
5053 /* rotate n first stack elements to the top
5054 I1 ... In -> In I1 ... I(n-1) [top is right]
5056 void vrott(int n)
5058 int i;
5059 SValue tmp;
5061 tmp = vtop[0];
5062 for(i = 0;i < n - 1; i++)
5063 vtop[-i] = vtop[-i - 1];
5064 vtop[-n + 1] = tmp;
5067 #ifdef TCC_TARGET_ARM
5068 /* like vrott but in other direction
5069 In ... I1 -> I(n-1) ... I1 In [top is right]
5071 void vnrott(int n)
5073 int i;
5074 SValue tmp;
5076 tmp = vtop[-n + 1];
5077 for(i = n - 1; i > 0; i--)
5078 vtop[-i] = vtop[-i + 1];
5079 vtop[0] = tmp;
5081 #endif
5083 /* pop stack value */
5084 void vpop(void)
5086 int v;
5087 v = vtop->r & VT_VALMASK;
5088 #ifdef TCC_TARGET_I386
5089 /* for x86, we need to pop the FP stack */
5090 if (v == TREG_ST0 && !nocode_wanted) {
5091 o(0xd9dd); /* fstp %st(1) */
5092 } else
5093 #endif
5094 if (v == VT_JMP || v == VT_JMPI) {
5095 /* need to put correct jump if && or || without test */
5096 gsym(vtop->c.ul);
5098 vtop--;
5101 /* convert stack entry to register and duplicate its value in another
5102 register */
5103 void gv_dup(void)
5105 int rc, t, r, r1;
5106 SValue sv;
5108 t = vtop->type.t;
5109 if ((t & VT_BTYPE) == VT_LLONG) {
5110 lexpand();
5111 gv_dup();
5112 vswap();
5113 vrotb(3);
5114 gv_dup();
5115 vrotb(4);
5116 /* stack: H L L1 H1 */
5117 lbuild(t);
5118 vrotb(3);
5119 vrotb(3);
5120 vswap();
5121 lbuild(t);
5122 vswap();
5123 } else {
5124 /* duplicate value */
5125 rc = RC_INT;
5126 sv.type.t = VT_INT;
5127 if (is_float(t)) {
5128 rc = RC_FLOAT;
5129 sv.type.t = t;
5131 r = gv(rc);
5132 r1 = get_reg(rc);
5133 sv.r = r;
5134 sv.c.ul = 0;
5135 load(r1, &sv); /* move r to r1 */
5136 vdup();
5137 /* duplicates value */
5138 vtop->r = r1;
5142 /* generate CPU independent (unsigned) long long operations */
5143 void gen_opl(int op)
5145 int t, a, b, op1, c, i;
5146 int func;
5147 SValue tmp;
5149 switch(op) {
5150 case '/':
5151 case TOK_PDIV:
5152 func = TOK___divdi3;
5153 goto gen_func;
5154 case TOK_UDIV:
5155 func = TOK___udivdi3;
5156 goto gen_func;
5157 case '%':
5158 func = TOK___moddi3;
5159 goto gen_func;
5160 case TOK_UMOD:
5161 func = TOK___umoddi3;
5162 gen_func:
5163 /* call generic long long function */
5164 vpush_global_sym(&func_old_type, func);
5165 vrott(3);
5166 gfunc_call(2);
5167 vpushi(0);
5168 vtop->r = REG_IRET;
5169 vtop->r2 = REG_LRET;
5170 break;
5171 case '^':
5172 case '&':
5173 case '|':
5174 case '*':
5175 case '+':
5176 case '-':
5177 t = vtop->type.t;
5178 vswap();
5179 lexpand();
5180 vrotb(3);
5181 lexpand();
5182 /* stack: L1 H1 L2 H2 */
5183 tmp = vtop[0];
5184 vtop[0] = vtop[-3];
5185 vtop[-3] = tmp;
5186 tmp = vtop[-2];
5187 vtop[-2] = vtop[-3];
5188 vtop[-3] = tmp;
5189 vswap();
5190 /* stack: H1 H2 L1 L2 */
5191 if (op == '*') {
5192 vpushv(vtop - 1);
5193 vpushv(vtop - 1);
5194 gen_op(TOK_UMULL);
5195 lexpand();
5196 /* stack: H1 H2 L1 L2 ML MH */
5197 for(i=0;i<4;i++)
5198 vrotb(6);
5199 /* stack: ML MH H1 H2 L1 L2 */
5200 tmp = vtop[0];
5201 vtop[0] = vtop[-2];
5202 vtop[-2] = tmp;
5203 /* stack: ML MH H1 L2 H2 L1 */
5204 gen_op('*');
5205 vrotb(3);
5206 vrotb(3);
5207 gen_op('*');
5208 /* stack: ML MH M1 M2 */
5209 gen_op('+');
5210 gen_op('+');
5211 } else if (op == '+' || op == '-') {
5212 /* XXX: add non carry method too (for MIPS or alpha) */
5213 if (op == '+')
5214 op1 = TOK_ADDC1;
5215 else
5216 op1 = TOK_SUBC1;
5217 gen_op(op1);
5218 /* stack: H1 H2 (L1 op L2) */
5219 vrotb(3);
5220 vrotb(3);
5221 gen_op(op1 + 1); /* TOK_xxxC2 */
5222 } else {
5223 gen_op(op);
5224 /* stack: H1 H2 (L1 op L2) */
5225 vrotb(3);
5226 vrotb(3);
5227 /* stack: (L1 op L2) H1 H2 */
5228 gen_op(op);
5229 /* stack: (L1 op L2) (H1 op H2) */
5231 /* stack: L H */
5232 lbuild(t);
5233 break;
5234 case TOK_SAR:
5235 case TOK_SHR:
5236 case TOK_SHL:
5237 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5238 t = vtop[-1].type.t;
5239 vswap();
5240 lexpand();
5241 vrotb(3);
5242 /* stack: L H shift */
5243 c = (int)vtop->c.i;
5244 /* constant: simpler */
5245 /* NOTE: all comments are for SHL. the other cases are
5246 done by swaping words */
5247 vpop();
5248 if (op != TOK_SHL)
5249 vswap();
5250 if (c >= 32) {
5251 /* stack: L H */
5252 vpop();
5253 if (c > 32) {
5254 vpushi(c - 32);
5255 gen_op(op);
5257 if (op != TOK_SAR) {
5258 vpushi(0);
5259 } else {
5260 gv_dup();
5261 vpushi(31);
5262 gen_op(TOK_SAR);
5264 vswap();
5265 } else {
5266 vswap();
5267 gv_dup();
5268 /* stack: H L L */
5269 vpushi(c);
5270 gen_op(op);
5271 vswap();
5272 vpushi(32 - c);
5273 if (op == TOK_SHL)
5274 gen_op(TOK_SHR);
5275 else
5276 gen_op(TOK_SHL);
5277 vrotb(3);
5278 /* stack: L L H */
5279 vpushi(c);
5280 if (op == TOK_SHL)
5281 gen_op(TOK_SHL);
5282 else
5283 gen_op(TOK_SHR);
5284 gen_op('|');
5286 if (op != TOK_SHL)
5287 vswap();
5288 lbuild(t);
5289 } else {
5290 /* XXX: should provide a faster fallback on x86 ? */
5291 switch(op) {
5292 case TOK_SAR:
5293 func = TOK___sardi3;
5294 goto gen_func;
5295 case TOK_SHR:
5296 func = TOK___shrdi3;
5297 goto gen_func;
5298 case TOK_SHL:
5299 func = TOK___shldi3;
5300 goto gen_func;
5303 break;
5304 default:
5305 /* compare operations */
5306 t = vtop->type.t;
5307 vswap();
5308 lexpand();
5309 vrotb(3);
5310 lexpand();
5311 /* stack: L1 H1 L2 H2 */
5312 tmp = vtop[-1];
5313 vtop[-1] = vtop[-2];
5314 vtop[-2] = tmp;
5315 /* stack: L1 L2 H1 H2 */
5316 /* compare high */
5317 op1 = op;
5318 /* when values are equal, we need to compare low words. since
5319 the jump is inverted, we invert the test too. */
5320 if (op1 == TOK_LT)
5321 op1 = TOK_LE;
5322 else if (op1 == TOK_GT)
5323 op1 = TOK_GE;
5324 else if (op1 == TOK_ULT)
5325 op1 = TOK_ULE;
5326 else if (op1 == TOK_UGT)
5327 op1 = TOK_UGE;
5328 a = 0;
5329 b = 0;
5330 gen_op(op1);
5331 if (op1 != TOK_NE) {
5332 a = gtst(1, 0);
5334 if (op != TOK_EQ) {
5335 /* generate non equal test */
5336 /* XXX: NOT PORTABLE yet */
5337 if (a == 0) {
5338 b = gtst(0, 0);
5339 } else {
5340 #if defined(TCC_TARGET_I386)
5341 b = psym(0x850f, 0);
5342 #elif defined(TCC_TARGET_ARM)
5343 b = ind;
5344 o(0x1A000000 | encbranch(ind, 0, 1));
5345 #elif defined(TCC_TARGET_C67)
5346 error("not implemented");
5347 #else
5348 #error not supported
5349 #endif
5352 /* compare low. Always unsigned */
5353 op1 = op;
5354 if (op1 == TOK_LT)
5355 op1 = TOK_ULT;
5356 else if (op1 == TOK_LE)
5357 op1 = TOK_ULE;
5358 else if (op1 == TOK_GT)
5359 op1 = TOK_UGT;
5360 else if (op1 == TOK_GE)
5361 op1 = TOK_UGE;
5362 gen_op(op1);
5363 a = gtst(1, a);
5364 gsym(b);
5365 vseti(VT_JMPI, a);
5366 break;
5370 /* handle integer constant optimizations and various machine
5371 independent opt */
5372 void gen_opic(int op)
5374 int c1, c2, t1, t2, n, c;
5375 SValue *v1, *v2;
5376 long long l1, l2, l;
5377 typedef unsigned long long U;
5379 v1 = vtop - 1;
5380 v2 = vtop;
5381 t1 = v1->type.t & VT_BTYPE;
5382 t2 = v2->type.t & VT_BTYPE;
5383 l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i;
5384 l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i;
5386 /* currently, we cannot do computations with forward symbols */
5387 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5388 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5389 if (c1 && c2) {
5390 switch(op) {
5391 case '+': l1 += l2; break;
5392 case '-': l1 -= l2; break;
5393 case '&': l1 &= l2; break;
5394 case '^': l1 ^= l2; break;
5395 case '|': l1 |= l2; break;
5396 case '*': l1 *= l2; break;
5398 case TOK_PDIV:
5399 case '/':
5400 case '%':
5401 case TOK_UDIV:
5402 case TOK_UMOD:
5403 /* if division by zero, generate explicit division */
5404 if (l2 == 0) {
5405 if (const_wanted)
5406 error("division by zero in constant");
5407 goto general_case;
5409 switch(op) {
5410 default: l1 /= l2; break;
5411 case '%': l1 %= l2; break;
5412 case TOK_UDIV: l1 = (U)l1 / l2; break;
5413 case TOK_UMOD: l1 = (U)l1 % l2; break;
5415 break;
5416 case TOK_SHL: l1 <<= l2; break;
5417 case TOK_SHR: l1 = (U)l1 >> l2; break;
5418 case TOK_SAR: l1 >>= l2; break;
5419 /* tests */
5420 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5421 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5422 case TOK_EQ: l1 = l1 == l2; break;
5423 case TOK_NE: l1 = l1 != l2; break;
5424 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5425 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5426 case TOK_LT: l1 = l1 < l2; break;
5427 case TOK_GE: l1 = l1 >= l2; break;
5428 case TOK_LE: l1 = l1 <= l2; break;
5429 case TOK_GT: l1 = l1 > l2; break;
5430 /* logical */
5431 case TOK_LAND: l1 = l1 && l2; break;
5432 case TOK_LOR: l1 = l1 || l2; break;
5433 default:
5434 goto general_case;
5436 v1->c.ll = l1;
5437 vtop--;
5438 } else {
5439 /* if commutative ops, put c2 as constant */
5440 if (c1 && (op == '+' || op == '&' || op == '^' ||
5441 op == '|' || op == '*')) {
5442 vswap();
5443 c = c1, c1 = c2, c2 = c;
5444 l = l1, l1 = l2, l2 = l;
5446 /* Filter out NOP operations like x*1, x-0, x&-1... */
5447 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5448 op == TOK_PDIV) &&
5449 l2 == 1) ||
5450 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5451 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5452 l2 == 0) ||
5453 (op == '&' &&
5454 l2 == -1))) {
5455 /* nothing to do */
5456 vtop--;
5457 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5458 /* try to use shifts instead of muls or divs */
5459 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5460 n = -1;
5461 while (l2) {
5462 l2 >>= 1;
5463 n++;
5465 vtop->c.ll = n;
5466 if (op == '*')
5467 op = TOK_SHL;
5468 else if (op == TOK_PDIV)
5469 op = TOK_SAR;
5470 else
5471 op = TOK_SHR;
5473 goto general_case;
5474 } else if (c2 && (op == '+' || op == '-') &&
5475 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5476 (VT_CONST | VT_SYM)) {
5477 /* symbol + constant case */
5478 if (op == '-')
5479 l2 = -l2;
5480 vtop--;
5481 vtop->c.ll += l2;
5482 } else {
5483 general_case:
5484 if (!nocode_wanted) {
5485 /* call low level op generator */
5486 if (t1 == VT_LLONG || t2 == VT_LLONG)
5487 gen_opl(op);
5488 else
5489 gen_opi(op);
5490 } else {
5491 vtop--;
5497 /* generate a floating point operation with constant propagation */
5498 void gen_opif(int op)
5500 int c1, c2;
5501 SValue *v1, *v2;
5502 long double f1, f2;
5504 v1 = vtop - 1;
5505 v2 = vtop;
5506 /* currently, we cannot do computations with forward symbols */
5507 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5508 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5509 if (c1 && c2) {
5510 if (v1->type.t == VT_FLOAT) {
5511 f1 = v1->c.f;
5512 f2 = v2->c.f;
5513 } else if (v1->type.t == VT_DOUBLE) {
5514 f1 = v1->c.d;
5515 f2 = v2->c.d;
5516 } else {
5517 f1 = v1->c.ld;
5518 f2 = v2->c.ld;
5521 /* NOTE: we only do constant propagation if finite number (not
5522 NaN or infinity) (ANSI spec) */
5523 if (!ieee_finite(f1) || !ieee_finite(f2))
5524 goto general_case;
5526 switch(op) {
5527 case '+': f1 += f2; break;
5528 case '-': f1 -= f2; break;
5529 case '*': f1 *= f2; break;
5530 case '/':
5531 if (f2 == 0.0) {
5532 if (const_wanted)
5533 error("division by zero in constant");
5534 goto general_case;
5536 f1 /= f2;
5537 break;
5538 /* XXX: also handles tests ? */
5539 default:
5540 goto general_case;
5542 /* XXX: overflow test ? */
5543 if (v1->type.t == VT_FLOAT) {
5544 v1->c.f = f1;
5545 } else if (v1->type.t == VT_DOUBLE) {
5546 v1->c.d = f1;
5547 } else {
5548 v1->c.ld = f1;
5550 vtop--;
5551 } else {
5552 general_case:
5553 if (!nocode_wanted) {
5554 gen_opf(op);
5555 } else {
5556 vtop--;
5561 static int pointed_size(CType *type)
5563 int align;
5564 return type_size(pointed_type(type), &align);
5567 static inline int is_null_pointer(SValue *p)
5569 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5570 return 0;
5571 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5572 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5575 static inline int is_integer_btype(int bt)
5577 return (bt == VT_BYTE || bt == VT_SHORT ||
5578 bt == VT_INT || bt == VT_LLONG);
5581 /* check types for comparison or substraction of pointers */
5582 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5584 CType *type1, *type2, tmp_type1, tmp_type2;
5585 int bt1, bt2;
5587 /* null pointers are accepted for all comparisons as gcc */
5588 if (is_null_pointer(p1) || is_null_pointer(p2))
5589 return;
5590 type1 = &p1->type;
5591 type2 = &p2->type;
5592 bt1 = type1->t & VT_BTYPE;
5593 bt2 = type2->t & VT_BTYPE;
5594 /* accept comparison between pointer and integer with a warning */
5595 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5596 if (op != TOK_LOR && op != TOK_LAND )
5597 warning("comparison between pointer and integer");
5598 return;
5601 /* both must be pointers or implicit function pointers */
5602 if (bt1 == VT_PTR) {
5603 type1 = pointed_type(type1);
5604 } else if (bt1 != VT_FUNC)
5605 goto invalid_operands;
5607 if (bt2 == VT_PTR) {
5608 type2 = pointed_type(type2);
5609 } else if (bt2 != VT_FUNC) {
5610 invalid_operands:
5611 error("invalid operands to binary %s", get_tok_str(op, NULL));
5613 if ((type1->t & VT_BTYPE) == VT_VOID ||
5614 (type2->t & VT_BTYPE) == VT_VOID)
5615 return;
5616 tmp_type1 = *type1;
5617 tmp_type2 = *type2;
5618 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5619 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5620 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5621 /* gcc-like error if '-' is used */
5622 if (op == '-')
5623 goto invalid_operands;
5624 else
5625 warning("comparison of distinct pointer types lacks a cast");
5629 /* generic gen_op: handles types problems */
5630 void gen_op(int op)
5632 int u, t1, t2, bt1, bt2, t;
5633 CType type1;
5635 t1 = vtop[-1].type.t;
5636 t2 = vtop[0].type.t;
5637 bt1 = t1 & VT_BTYPE;
5638 bt2 = t2 & VT_BTYPE;
5640 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5641 /* at least one operand is a pointer */
5642 /* relationnal op: must be both pointers */
5643 if (op >= TOK_ULT && op <= TOK_LOR) {
5644 check_comparison_pointer_types(vtop - 1, vtop, op);
5645 /* pointers are handled are unsigned */
5646 t = VT_INT | VT_UNSIGNED;
5647 goto std_op;
5649 /* if both pointers, then it must be the '-' op */
5650 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5651 if (op != '-')
5652 error("cannot use pointers here");
5653 check_comparison_pointer_types(vtop - 1, vtop, op);
5654 /* XXX: check that types are compatible */
5655 u = pointed_size(&vtop[-1].type);
5656 gen_opic(op);
5657 /* set to integer type */
5658 vtop->type.t = VT_INT;
5659 vpushi(u);
5660 gen_op(TOK_PDIV);
5661 } else {
5662 /* exactly one pointer : must be '+' or '-'. */
5663 if (op != '-' && op != '+')
5664 error("cannot use pointers here");
5665 /* Put pointer as first operand */
5666 if (bt2 == VT_PTR) {
5667 vswap();
5668 swap(&t1, &t2);
5670 type1 = vtop[-1].type;
5671 /* XXX: cast to int ? (long long case) */
5672 vpushi(pointed_size(&vtop[-1].type));
5673 gen_op('*');
5674 #ifdef CONFIG_TCC_BCHECK
5675 /* if evaluating constant expression, no code should be
5676 generated, so no bound check */
5677 if (do_bounds_check && !const_wanted) {
5678 /* if bounded pointers, we generate a special code to
5679 test bounds */
5680 if (op == '-') {
5681 vpushi(0);
5682 vswap();
5683 gen_op('-');
5685 gen_bounded_ptr_add();
5686 } else
5687 #endif
5689 gen_opic(op);
5691 /* put again type if gen_opic() swaped operands */
5692 vtop->type = type1;
5694 } else if (is_float(bt1) || is_float(bt2)) {
5695 /* compute bigger type and do implicit casts */
5696 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5697 t = VT_LDOUBLE;
5698 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5699 t = VT_DOUBLE;
5700 } else {
5701 t = VT_FLOAT;
5703 /* floats can only be used for a few operations */
5704 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5705 (op < TOK_ULT || op > TOK_GT))
5706 error("invalid operands for binary operation");
5707 goto std_op;
5708 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5709 /* cast to biggest op */
5710 t = VT_LLONG;
5711 /* convert to unsigned if it does not fit in a long long */
5712 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5713 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5714 t |= VT_UNSIGNED;
5715 goto std_op;
5716 } else {
5717 /* integer operations */
5718 t = VT_INT;
5719 /* convert to unsigned if it does not fit in an integer */
5720 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5721 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5722 t |= VT_UNSIGNED;
5723 std_op:
5724 /* XXX: currently, some unsigned operations are explicit, so
5725 we modify them here */
5726 if (t & VT_UNSIGNED) {
5727 if (op == TOK_SAR)
5728 op = TOK_SHR;
5729 else if (op == '/')
5730 op = TOK_UDIV;
5731 else if (op == '%')
5732 op = TOK_UMOD;
5733 else if (op == TOK_LT)
5734 op = TOK_ULT;
5735 else if (op == TOK_GT)
5736 op = TOK_UGT;
5737 else if (op == TOK_LE)
5738 op = TOK_ULE;
5739 else if (op == TOK_GE)
5740 op = TOK_UGE;
5742 vswap();
5743 type1.t = t;
5744 gen_cast(&type1);
5745 vswap();
5746 /* special case for shifts and long long: we keep the shift as
5747 an integer */
5748 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5749 type1.t = VT_INT;
5750 gen_cast(&type1);
5751 if (is_float(t))
5752 gen_opif(op);
5753 else
5754 gen_opic(op);
5755 if (op >= TOK_ULT && op <= TOK_GT) {
5756 /* relationnal op: the result is an int */
5757 vtop->type.t = VT_INT;
5758 } else {
5759 vtop->type.t = t;
5764 /* generic itof for unsigned long long case */
5765 void gen_cvt_itof1(int t)
5767 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5768 (VT_LLONG | VT_UNSIGNED)) {
5770 if (t == VT_FLOAT)
5771 vpush_global_sym(&func_old_type, TOK___ulltof);
5772 else if (t == VT_DOUBLE)
5773 vpush_global_sym(&func_old_type, TOK___ulltod);
5774 else
5775 vpush_global_sym(&func_old_type, TOK___ulltold);
5776 vrott(2);
5777 gfunc_call(1);
5778 vpushi(0);
5779 vtop->r = REG_FRET;
5780 } else {
5781 gen_cvt_itof(t);
5785 /* generic ftoi for unsigned long long case */
5786 void gen_cvt_ftoi1(int t)
5788 int st;
5790 if (t == (VT_LLONG | VT_UNSIGNED)) {
5791 /* not handled natively */
5792 st = vtop->type.t & VT_BTYPE;
5793 if (st == VT_FLOAT)
5794 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5795 else if (st == VT_DOUBLE)
5796 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5797 else
5798 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5799 vrott(2);
5800 gfunc_call(1);
5801 vpushi(0);
5802 vtop->r = REG_IRET;
5803 vtop->r2 = REG_LRET;
5804 } else {
5805 gen_cvt_ftoi(t);
5809 /* force char or short cast */
5810 void force_charshort_cast(int t)
5812 int bits, dbt;
5813 dbt = t & VT_BTYPE;
5814 /* XXX: add optimization if lvalue : just change type and offset */
5815 if (dbt == VT_BYTE)
5816 bits = 8;
5817 else
5818 bits = 16;
5819 if (t & VT_UNSIGNED) {
5820 vpushi((1 << bits) - 1);
5821 gen_op('&');
5822 } else {
5823 bits = 32 - bits;
5824 vpushi(bits);
5825 gen_op(TOK_SHL);
5826 /* result must be signed or the SAR is converted to an SHL
5827 This was not the case when "t" was a signed short
5828 and the last value on the stack was an unsigned int */
5829 vtop->type.t &= ~VT_UNSIGNED;
5830 vpushi(bits);
5831 gen_op(TOK_SAR);
5835 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5836 static void gen_cast(CType *type)
5838 int sbt, dbt, sf, df, c;
5840 /* special delayed cast for char/short */
5841 /* XXX: in some cases (multiple cascaded casts), it may still
5842 be incorrect */
5843 if (vtop->r & VT_MUSTCAST) {
5844 vtop->r &= ~VT_MUSTCAST;
5845 force_charshort_cast(vtop->type.t);
5848 /* bitfields first get cast to ints */
5849 if (vtop->type.t & VT_BITFIELD) {
5850 gv(RC_INT);
5853 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5854 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5856 if (sbt != dbt && !nocode_wanted) {
5857 sf = is_float(sbt);
5858 df = is_float(dbt);
5859 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5860 if (sf && df) {
5861 /* convert from fp to fp */
5862 if (c) {
5863 /* constant case: we can do it now */
5864 /* XXX: in ISOC, cannot do it if error in convert */
5865 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5866 vtop->c.f = (float)vtop->c.d;
5867 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5868 vtop->c.f = (float)vtop->c.ld;
5869 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5870 vtop->c.d = (double)vtop->c.f;
5871 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5872 vtop->c.d = (double)vtop->c.ld;
5873 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5874 vtop->c.ld = (long double)vtop->c.f;
5875 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5876 vtop->c.ld = (long double)vtop->c.d;
5877 } else {
5878 /* non constant case: generate code */
5879 gen_cvt_ftof(dbt);
5881 } else if (df) {
5882 /* convert int to fp */
5883 if (c) {
5884 switch(sbt) {
5885 case VT_LLONG | VT_UNSIGNED:
5886 case VT_LLONG:
5887 /* XXX: add const cases for long long */
5888 goto do_itof;
5889 case VT_INT | VT_UNSIGNED:
5890 switch(dbt) {
5891 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5892 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5893 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5895 break;
5896 default:
5897 switch(dbt) {
5898 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5899 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5900 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5902 break;
5904 } else {
5905 do_itof:
5906 #if !defined(TCC_TARGET_ARM)
5907 gen_cvt_itof1(dbt);
5908 #else
5909 gen_cvt_itof(dbt);
5910 #endif
5912 } else if (sf) {
5913 /* convert fp to int */
5914 if (dbt == VT_BOOL) {
5915 vpushi(0);
5916 gen_op(TOK_NE);
5917 } else {
5918 /* we handle char/short/etc... with generic code */
5919 if (dbt != (VT_INT | VT_UNSIGNED) &&
5920 dbt != (VT_LLONG | VT_UNSIGNED) &&
5921 dbt != VT_LLONG)
5922 dbt = VT_INT;
5923 if (c) {
5924 switch(dbt) {
5925 case VT_LLONG | VT_UNSIGNED:
5926 case VT_LLONG:
5927 /* XXX: add const cases for long long */
5928 goto do_ftoi;
5929 case VT_INT | VT_UNSIGNED:
5930 switch(sbt) {
5931 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5932 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5933 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5935 break;
5936 default:
5937 /* int case */
5938 switch(sbt) {
5939 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5940 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5941 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5943 break;
5945 } else {
5946 do_ftoi:
5947 gen_cvt_ftoi1(dbt);
5949 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5950 /* additional cast for char/short... */
5951 vtop->type.t = dbt;
5952 gen_cast(type);
5955 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5956 if ((sbt & VT_BTYPE) != VT_LLONG) {
5957 /* scalar to long long */
5958 if (c) {
5959 if (sbt == (VT_INT | VT_UNSIGNED))
5960 vtop->c.ll = vtop->c.ui;
5961 else
5962 vtop->c.ll = vtop->c.i;
5963 } else {
5964 /* machine independent conversion */
5965 gv(RC_INT);
5966 /* generate high word */
5967 if (sbt == (VT_INT | VT_UNSIGNED)) {
5968 vpushi(0);
5969 gv(RC_INT);
5970 } else {
5971 gv_dup();
5972 vpushi(31);
5973 gen_op(TOK_SAR);
5975 /* patch second register */
5976 vtop[-1].r2 = vtop->r;
5977 vpop();
5980 } else if (dbt == VT_BOOL) {
5981 /* scalar to bool */
5982 vpushi(0);
5983 gen_op(TOK_NE);
5984 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5985 (dbt & VT_BTYPE) == VT_SHORT) {
5986 if (sbt == VT_PTR) {
5987 vtop->type.t = VT_INT;
5988 warning("nonportable conversion from pointer to char/short");
5990 force_charshort_cast(dbt);
5991 } else if ((dbt & VT_BTYPE) == VT_INT) {
5992 /* scalar to int */
5993 if (sbt == VT_LLONG) {
5994 /* from long long: just take low order word */
5995 lexpand();
5996 vpop();
5998 /* if lvalue and single word type, nothing to do because
5999 the lvalue already contains the real type size (see
6000 VT_LVAL_xxx constants) */
6002 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
6003 /* if we are casting between pointer types,
6004 we must update the VT_LVAL_xxx size */
6005 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
6006 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
6008 vtop->type = *type;
6011 /* return type size. Put alignment at 'a' */
6012 static int type_size(CType *type, int *a)
6014 Sym *s;
6015 int bt;
6017 bt = type->t & VT_BTYPE;
6018 if (bt == VT_STRUCT) {
6019 /* struct/union */
6020 s = type->ref;
6021 *a = s->r;
6022 return s->c;
6023 } else if (bt == VT_PTR) {
6024 if (type->t & VT_ARRAY) {
6025 s = type->ref;
6026 return type_size(&s->type, a) * s->c;
6027 } else {
6028 *a = PTR_SIZE;
6029 return PTR_SIZE;
6031 } else if (bt == VT_LDOUBLE) {
6032 *a = LDOUBLE_ALIGN;
6033 return LDOUBLE_SIZE;
6034 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
6035 #ifdef TCC_TARGET_I386
6036 *a = 4;
6037 #elif defined(TCC_TARGET_ARM)
6038 #ifdef TCC_ARM_EABI
6039 *a = 8;
6040 #else
6041 *a = 4;
6042 #endif
6043 #else
6044 *a = 8;
6045 #endif
6046 return 8;
6047 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6048 *a = 4;
6049 return 4;
6050 } else if (bt == VT_SHORT) {
6051 *a = 2;
6052 return 2;
6053 } else {
6054 /* char, void, function, _Bool */
6055 *a = 1;
6056 return 1;
6060 /* return the pointed type of t */
6061 static inline CType *pointed_type(CType *type)
6063 return &type->ref->type;
6066 /* modify type so that its it is a pointer to type. */
6067 static void mk_pointer(CType *type)
6069 Sym *s;
6070 s = sym_push(SYM_FIELD, type, 0, -1);
6071 type->t = VT_PTR | (type->t & ~VT_TYPE);
6072 type->ref = s;
6075 /* compare function types. OLD functions match any new functions */
6076 static int is_compatible_func(CType *type1, CType *type2)
6078 Sym *s1, *s2;
6080 s1 = type1->ref;
6081 s2 = type2->ref;
6082 if (!is_compatible_types(&s1->type, &s2->type))
6083 return 0;
6084 /* check func_call */
6085 if (s1->r != s2->r)
6086 return 0;
6087 /* XXX: not complete */
6088 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6089 return 1;
6090 if (s1->c != s2->c)
6091 return 0;
6092 while (s1 != NULL) {
6093 if (s2 == NULL)
6094 return 0;
6095 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6096 return 0;
6097 s1 = s1->next;
6098 s2 = s2->next;
6100 if (s2)
6101 return 0;
6102 return 1;
6105 /* return true if type1 and type2 are the same. If unqualified is
6106 true, qualifiers on the types are ignored.
6108 - enums are not checked as gcc __builtin_types_compatible_p ()
6110 static int compare_types(CType *type1, CType *type2, int unqualified)
6112 int bt1, t1, t2;
6114 t1 = type1->t & VT_TYPE;
6115 t2 = type2->t & VT_TYPE;
6116 if (unqualified) {
6117 /* strip qualifiers before comparing */
6118 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6119 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6121 /* XXX: bitfields ? */
6122 if (t1 != t2)
6123 return 0;
6124 /* test more complicated cases */
6125 bt1 = t1 & VT_BTYPE;
6126 if (bt1 == VT_PTR) {
6127 type1 = pointed_type(type1);
6128 type2 = pointed_type(type2);
6129 return is_compatible_types(type1, type2);
6130 } else if (bt1 == VT_STRUCT) {
6131 return (type1->ref == type2->ref);
6132 } else if (bt1 == VT_FUNC) {
6133 return is_compatible_func(type1, type2);
6134 } else {
6135 return 1;
6139 /* return true if type1 and type2 are exactly the same (including
6140 qualifiers).
6142 static int is_compatible_types(CType *type1, CType *type2)
6144 return compare_types(type1,type2,0);
6147 /* return true if type1 and type2 are the same (ignoring qualifiers).
6149 static int is_compatible_parameter_types(CType *type1, CType *type2)
6151 return compare_types(type1,type2,1);
6154 /* print a type. If 'varstr' is not NULL, then the variable is also
6155 printed in the type */
6156 /* XXX: union */
6157 /* XXX: add array and function pointers */
6158 void type_to_str(char *buf, int buf_size,
6159 CType *type, const char *varstr)
6161 int bt, v, t;
6162 Sym *s, *sa;
6163 char buf1[256];
6164 const char *tstr;
6166 t = type->t & VT_TYPE;
6167 bt = t & VT_BTYPE;
6168 buf[0] = '\0';
6169 if (t & VT_CONSTANT)
6170 pstrcat(buf, buf_size, "const ");
6171 if (t & VT_VOLATILE)
6172 pstrcat(buf, buf_size, "volatile ");
6173 if (t & VT_UNSIGNED)
6174 pstrcat(buf, buf_size, "unsigned ");
6175 switch(bt) {
6176 case VT_VOID:
6177 tstr = "void";
6178 goto add_tstr;
6179 case VT_BOOL:
6180 tstr = "_Bool";
6181 goto add_tstr;
6182 case VT_BYTE:
6183 tstr = "char";
6184 goto add_tstr;
6185 case VT_SHORT:
6186 tstr = "short";
6187 goto add_tstr;
6188 case VT_INT:
6189 tstr = "int";
6190 goto add_tstr;
6191 case VT_LONG:
6192 tstr = "long";
6193 goto add_tstr;
6194 case VT_LLONG:
6195 tstr = "long long";
6196 goto add_tstr;
6197 case VT_FLOAT:
6198 tstr = "float";
6199 goto add_tstr;
6200 case VT_DOUBLE:
6201 tstr = "double";
6202 goto add_tstr;
6203 case VT_LDOUBLE:
6204 tstr = "long double";
6205 add_tstr:
6206 pstrcat(buf, buf_size, tstr);
6207 break;
6208 case VT_ENUM:
6209 case VT_STRUCT:
6210 if (bt == VT_STRUCT)
6211 tstr = "struct ";
6212 else
6213 tstr = "enum ";
6214 pstrcat(buf, buf_size, tstr);
6215 v = type->ref->v & ~SYM_STRUCT;
6216 if (v >= SYM_FIRST_ANOM)
6217 pstrcat(buf, buf_size, "<anonymous>");
6218 else
6219 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6220 break;
6221 case VT_FUNC:
6222 s = type->ref;
6223 type_to_str(buf, buf_size, &s->type, varstr);
6224 pstrcat(buf, buf_size, "(");
6225 sa = s->next;
6226 while (sa != NULL) {
6227 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6228 pstrcat(buf, buf_size, buf1);
6229 sa = sa->next;
6230 if (sa)
6231 pstrcat(buf, buf_size, ", ");
6233 pstrcat(buf, buf_size, ")");
6234 goto no_var;
6235 case VT_PTR:
6236 s = type->ref;
6237 pstrcpy(buf1, sizeof(buf1), "*");
6238 if (varstr)
6239 pstrcat(buf1, sizeof(buf1), varstr);
6240 type_to_str(buf, buf_size, &s->type, buf1);
6241 goto no_var;
6243 if (varstr) {
6244 pstrcat(buf, buf_size, " ");
6245 pstrcat(buf, buf_size, varstr);
6247 no_var: ;
6250 /* verify type compatibility to store vtop in 'dt' type, and generate
6251 casts if needed. */
6252 static void gen_assign_cast(CType *dt)
6254 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6255 char buf1[256], buf2[256];
6256 int dbt, sbt;
6258 st = &vtop->type; /* source type */
6259 dbt = dt->t & VT_BTYPE;
6260 sbt = st->t & VT_BTYPE;
6261 if (dt->t & VT_CONSTANT)
6262 warning("assignment of read-only location");
6263 switch(dbt) {
6264 case VT_PTR:
6265 /* special cases for pointers */
6266 /* '0' can also be a pointer */
6267 if (is_null_pointer(vtop))
6268 goto type_ok;
6269 /* accept implicit pointer to integer cast with warning */
6270 if (is_integer_btype(sbt)) {
6271 warning("assignment makes pointer from integer without a cast");
6272 goto type_ok;
6274 type1 = pointed_type(dt);
6275 /* a function is implicitely a function pointer */
6276 if (sbt == VT_FUNC) {
6277 if ((type1->t & VT_BTYPE) != VT_VOID &&
6278 !is_compatible_types(pointed_type(dt), st))
6279 goto error;
6280 else
6281 goto type_ok;
6283 if (sbt != VT_PTR)
6284 goto error;
6285 type2 = pointed_type(st);
6286 if ((type1->t & VT_BTYPE) == VT_VOID ||
6287 (type2->t & VT_BTYPE) == VT_VOID) {
6288 /* void * can match anything */
6289 } else {
6290 /* exact type match, except for unsigned */
6291 tmp_type1 = *type1;
6292 tmp_type2 = *type2;
6293 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6294 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6295 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6296 warning("assignment from incompatible pointer type");
6298 /* check const and volatile */
6299 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6300 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6301 warning("assignment discards qualifiers from pointer target type");
6302 break;
6303 case VT_BYTE:
6304 case VT_SHORT:
6305 case VT_INT:
6306 case VT_LLONG:
6307 if (sbt == VT_PTR || sbt == VT_FUNC) {
6308 warning("assignment makes integer from pointer without a cast");
6310 /* XXX: more tests */
6311 break;
6312 case VT_STRUCT:
6313 tmp_type1 = *dt;
6314 tmp_type2 = *st;
6315 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6316 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6317 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6318 error:
6319 type_to_str(buf1, sizeof(buf1), st, NULL);
6320 type_to_str(buf2, sizeof(buf2), dt, NULL);
6321 error("cannot cast '%s' to '%s'", buf1, buf2);
6323 break;
6325 type_ok:
6326 gen_cast(dt);
6329 /* store vtop in lvalue pushed on stack */
6330 void vstore(void)
6332 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6334 ft = vtop[-1].type.t;
6335 sbt = vtop->type.t & VT_BTYPE;
6336 dbt = ft & VT_BTYPE;
6337 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6338 (sbt == VT_INT && dbt == VT_SHORT)) {
6339 /* optimize char/short casts */
6340 delayed_cast = VT_MUSTCAST;
6341 vtop->type.t = ft & VT_TYPE;
6342 /* XXX: factorize */
6343 if (ft & VT_CONSTANT)
6344 warning("assignment of read-only location");
6345 } else {
6346 delayed_cast = 0;
6347 if (!(ft & VT_BITFIELD))
6348 gen_assign_cast(&vtop[-1].type);
6351 if (sbt == VT_STRUCT) {
6352 /* if structure, only generate pointer */
6353 /* structure assignment : generate memcpy */
6354 /* XXX: optimize if small size */
6355 if (!nocode_wanted) {
6356 size = type_size(&vtop->type, &align);
6358 #ifdef TCC_ARM_EABI
6359 if(!(align & 7))
6360 vpush_global_sym(&func_old_type, TOK_memcpy8);
6361 else if(!(align & 3))
6362 vpush_global_sym(&func_old_type, TOK_memcpy4);
6363 else
6364 #endif
6365 vpush_global_sym(&func_old_type, TOK_memcpy);
6367 /* destination */
6368 vpushv(vtop - 2);
6369 vtop->type.t = VT_INT;
6370 gaddrof();
6371 /* source */
6372 vpushv(vtop - 2);
6373 vtop->type.t = VT_INT;
6374 gaddrof();
6375 /* type size */
6376 vpushi(size);
6377 gfunc_call(3);
6379 vswap();
6380 vpop();
6381 } else {
6382 vswap();
6383 vpop();
6385 /* leave source on stack */
6386 } else if (ft & VT_BITFIELD) {
6387 /* bitfield store handling */
6388 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6389 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6390 /* remove bit field info to avoid loops */
6391 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6393 /* duplicate source into other register */
6394 gv_dup();
6395 vswap();
6396 vrott(3);
6398 /* duplicate destination */
6399 vdup();
6400 vtop[-1] = vtop[-2];
6402 /* mask and shift source */
6403 vpushi((1 << bit_size) - 1);
6404 gen_op('&');
6405 vpushi(bit_pos);
6406 gen_op(TOK_SHL);
6407 /* load destination, mask and or with source */
6408 vswap();
6409 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6410 gen_op('&');
6411 gen_op('|');
6412 /* store result */
6413 vstore();
6415 /* pop off shifted source from "duplicate source..." above */
6416 vpop();
6418 } else {
6419 #ifdef CONFIG_TCC_BCHECK
6420 /* bound check case */
6421 if (vtop[-1].r & VT_MUSTBOUND) {
6422 vswap();
6423 gbound();
6424 vswap();
6426 #endif
6427 if (!nocode_wanted) {
6428 rc = RC_INT;
6429 if (is_float(ft))
6430 rc = RC_FLOAT;
6431 r = gv(rc); /* generate value */
6432 /* if lvalue was saved on stack, must read it */
6433 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6434 SValue sv;
6435 t = get_reg(RC_INT);
6436 sv.type.t = VT_INT;
6437 sv.r = VT_LOCAL | VT_LVAL;
6438 sv.c.ul = vtop[-1].c.ul;
6439 load(t, &sv);
6440 vtop[-1].r = t | VT_LVAL;
6442 store(r, vtop - 1);
6443 /* two word case handling : store second register at word + 4 */
6444 if ((ft & VT_BTYPE) == VT_LLONG) {
6445 vswap();
6446 /* convert to int to increment easily */
6447 vtop->type.t = VT_INT;
6448 gaddrof();
6449 vpushi(4);
6450 gen_op('+');
6451 vtop->r |= VT_LVAL;
6452 vswap();
6453 /* XXX: it works because r2 is spilled last ! */
6454 store(vtop->r2, vtop - 1);
6457 vswap();
6458 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6459 vtop->r |= delayed_cast;
6463 /* post defines POST/PRE add. c is the token ++ or -- */
6464 void inc(int post, int c)
6466 test_lvalue();
6467 vdup(); /* save lvalue */
6468 if (post) {
6469 gv_dup(); /* duplicate value */
6470 vrotb(3);
6471 vrotb(3);
6473 /* add constant */
6474 vpushi(c - TOK_MID);
6475 gen_op('+');
6476 vstore(); /* store value */
6477 if (post)
6478 vpop(); /* if post op, return saved value */
6481 /* Parse GNUC __attribute__ extension. Currently, the following
6482 extensions are recognized:
6483 - aligned(n) : set data/function alignment.
6484 - packed : force data alignment to 1
6485 - section(x) : generate data/code in this section.
6486 - unused : currently ignored, but may be used someday.
6487 - regparm(n) : pass function parameters in registers (i386 only)
6489 static void parse_attribute(AttributeDef *ad)
6491 int t, n;
6493 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6494 next();
6495 skip('(');
6496 skip('(');
6497 while (tok != ')') {
6498 if (tok < TOK_IDENT)
6499 expect("attribute name");
6500 t = tok;
6501 next();
6502 switch(t) {
6503 case TOK_SECTION1:
6504 case TOK_SECTION2:
6505 skip('(');
6506 if (tok != TOK_STR)
6507 expect("section name");
6508 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6509 next();
6510 skip(')');
6511 break;
6512 case TOK_ALIGNED1:
6513 case TOK_ALIGNED2:
6514 if (tok == '(') {
6515 next();
6516 n = expr_const();
6517 if (n <= 0 || (n & (n - 1)) != 0)
6518 error("alignment must be a positive power of two");
6519 skip(')');
6520 } else {
6521 n = MAX_ALIGN;
6523 ad->aligned = n;
6524 break;
6525 case TOK_PACKED1:
6526 case TOK_PACKED2:
6527 ad->packed = 1;
6528 break;
6529 case TOK_UNUSED1:
6530 case TOK_UNUSED2:
6531 /* currently, no need to handle it because tcc does not
6532 track unused objects */
6533 break;
6534 case TOK_NORETURN1:
6535 case TOK_NORETURN2:
6536 /* currently, no need to handle it because tcc does not
6537 track unused objects */
6538 break;
6539 case TOK_CDECL1:
6540 case TOK_CDECL2:
6541 case TOK_CDECL3:
6542 ad->func_call = FUNC_CDECL;
6543 break;
6544 case TOK_STDCALL1:
6545 case TOK_STDCALL2:
6546 case TOK_STDCALL3:
6547 ad->func_call = FUNC_STDCALL;
6548 break;
6549 #ifdef TCC_TARGET_I386
6550 case TOK_REGPARM1:
6551 case TOK_REGPARM2:
6552 skip('(');
6553 n = expr_const();
6554 if (n > 3)
6555 n = 3;
6556 else if (n < 0)
6557 n = 0;
6558 if (n > 0)
6559 ad->func_call = FUNC_FASTCALL1 + n - 1;
6560 skip(')');
6561 break;
6562 case TOK_FASTCALL1:
6563 case TOK_FASTCALL2:
6564 case TOK_FASTCALL3:
6565 ad->func_call = FUNC_FASTCALLW;
6566 break;
6567 #endif
6568 case TOK_DLLEXPORT:
6569 ad->dllexport = 1;
6570 break;
6571 default:
6572 if (tcc_state->warn_unsupported)
6573 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6574 /* skip parameters */
6575 if (tok == '(') {
6576 int parenthesis = 0;
6577 do {
6578 if (tok == '(')
6579 parenthesis++;
6580 else if (tok == ')')
6581 parenthesis--;
6582 next();
6583 } while (parenthesis && tok != -1);
6585 break;
6587 if (tok != ',')
6588 break;
6589 next();
6591 skip(')');
6592 skip(')');
6596 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6597 static void struct_decl(CType *type, int u)
6599 int a, v, size, align, maxalign, c, offset;
6600 int bit_size, bit_pos, bsize, bt, lbit_pos;
6601 Sym *s, *ss, *ass, **ps;
6602 AttributeDef ad;
6603 CType type1, btype;
6605 a = tok; /* save decl type */
6606 next();
6607 if (tok != '{') {
6608 v = tok;
6609 next();
6610 /* struct already defined ? return it */
6611 if (v < TOK_IDENT)
6612 expect("struct/union/enum name");
6613 s = struct_find(v);
6614 if (s) {
6615 if (s->type.t != a)
6616 error("invalid type");
6617 goto do_decl;
6619 } else {
6620 v = anon_sym++;
6622 type1.t = a;
6623 /* we put an undefined size for struct/union */
6624 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6625 s->r = 0; /* default alignment is zero as gcc */
6626 /* put struct/union/enum name in type */
6627 do_decl:
6628 type->t = u;
6629 type->ref = s;
6631 if (tok == '{') {
6632 next();
6633 if (s->c != -1)
6634 error("struct/union/enum already defined");
6635 /* cannot be empty */
6636 c = 0;
6637 /* non empty enums are not allowed */
6638 if (a == TOK_ENUM) {
6639 for(;;) {
6640 v = tok;
6641 if (v < TOK_UIDENT)
6642 expect("identifier");
6643 next();
6644 if (tok == '=') {
6645 next();
6646 c = expr_const();
6648 /* enum symbols have static storage */
6649 ss = sym_push(v, &int_type, VT_CONST, c);
6650 ss->type.t |= VT_STATIC;
6651 if (tok != ',')
6652 break;
6653 next();
6654 c++;
6655 /* NOTE: we accept a trailing comma */
6656 if (tok == '}')
6657 break;
6659 skip('}');
6660 } else {
6661 maxalign = 1;
6662 ps = &s->next;
6663 bit_pos = 0;
6664 offset = 0;
6665 while (tok != '}') {
6666 parse_btype(&btype, &ad);
6667 while (1) {
6668 bit_size = -1;
6669 v = 0;
6670 type1 = btype;
6671 if (tok != ':') {
6672 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6673 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6674 expect("identifier");
6675 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6676 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6677 error("invalid type for '%s'",
6678 get_tok_str(v, NULL));
6680 if (tok == ':') {
6681 next();
6682 bit_size = expr_const();
6683 /* XXX: handle v = 0 case for messages */
6684 if (bit_size < 0)
6685 error("negative width in bit-field '%s'",
6686 get_tok_str(v, NULL));
6687 if (v && bit_size == 0)
6688 error("zero width for bit-field '%s'",
6689 get_tok_str(v, NULL));
6691 size = type_size(&type1, &align);
6692 if (ad.aligned) {
6693 if (align < ad.aligned)
6694 align = ad.aligned;
6695 } else if (ad.packed) {
6696 align = 1;
6697 } else if (*tcc_state->pack_stack_ptr) {
6698 if (align > *tcc_state->pack_stack_ptr)
6699 align = *tcc_state->pack_stack_ptr;
6701 lbit_pos = 0;
6702 if (bit_size >= 0) {
6703 bt = type1.t & VT_BTYPE;
6704 if (bt != VT_INT &&
6705 bt != VT_BYTE &&
6706 bt != VT_SHORT &&
6707 bt != VT_BOOL &&
6708 bt != VT_ENUM)
6709 error("bitfields must have scalar type");
6710 bsize = size * 8;
6711 if (bit_size > bsize) {
6712 error("width of '%s' exceeds its type",
6713 get_tok_str(v, NULL));
6714 } else if (bit_size == bsize) {
6715 /* no need for bit fields */
6716 bit_pos = 0;
6717 } else if (bit_size == 0) {
6718 /* XXX: what to do if only padding in a
6719 structure ? */
6720 /* zero size: means to pad */
6721 if (bit_pos > 0)
6722 bit_pos = bsize;
6723 } else {
6724 /* we do not have enough room ? */
6725 if ((bit_pos + bit_size) > bsize)
6726 bit_pos = 0;
6727 lbit_pos = bit_pos;
6728 /* XXX: handle LSB first */
6729 type1.t |= VT_BITFIELD |
6730 (bit_pos << VT_STRUCT_SHIFT) |
6731 (bit_size << (VT_STRUCT_SHIFT + 6));
6732 bit_pos += bit_size;
6734 } else {
6735 bit_pos = 0;
6737 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
6738 /* add new memory data only if starting
6739 bit field */
6740 if (lbit_pos == 0) {
6741 if (a == TOK_STRUCT) {
6742 c = (c + align - 1) & -align;
6743 offset = c;
6744 if (size > 0)
6745 c += size;
6746 } else {
6747 offset = 0;
6748 if (size > c)
6749 c = size;
6751 if (align > maxalign)
6752 maxalign = align;
6754 #if 0
6755 printf("add field %s offset=%d",
6756 get_tok_str(v, NULL), offset);
6757 if (type1.t & VT_BITFIELD) {
6758 printf(" pos=%d size=%d",
6759 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6760 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6762 printf("\n");
6763 #endif
6765 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
6766 ass = type1.ref;
6767 while ((ass = ass->next) != NULL) {
6768 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
6769 *ps = ss;
6770 ps = &ss->next;
6772 } else if (v) {
6773 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6774 *ps = ss;
6775 ps = &ss->next;
6777 if (tok == ';' || tok == TOK_EOF)
6778 break;
6779 skip(',');
6781 skip(';');
6783 skip('}');
6784 /* store size and alignment */
6785 s->c = (c + maxalign - 1) & -maxalign;
6786 s->r = maxalign;
6791 /* return 0 if no type declaration. otherwise, return the basic type
6792 and skip it.
6794 static int parse_btype(CType *type, AttributeDef *ad)
6796 int t, u, type_found, typespec_found, typedef_found;
6797 Sym *s;
6798 CType type1;
6800 memset(ad, 0, sizeof(AttributeDef));
6801 type_found = 0;
6802 typespec_found = 0;
6803 typedef_found = 0;
6804 t = 0;
6805 while(1) {
6806 switch(tok) {
6807 case TOK_EXTENSION:
6808 /* currently, we really ignore extension */
6809 next();
6810 continue;
6812 /* basic types */
6813 case TOK_CHAR:
6814 u = VT_BYTE;
6815 basic_type:
6816 next();
6817 basic_type1:
6818 if ((t & VT_BTYPE) != 0)
6819 error("too many basic types");
6820 t |= u;
6821 typespec_found = 1;
6822 break;
6823 case TOK_VOID:
6824 u = VT_VOID;
6825 goto basic_type;
6826 case TOK_SHORT:
6827 u = VT_SHORT;
6828 goto basic_type;
6829 case TOK_INT:
6830 next();
6831 typespec_found = 1;
6832 break;
6833 case TOK_LONG:
6834 next();
6835 if ((t & VT_BTYPE) == VT_DOUBLE) {
6836 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6837 } else if ((t & VT_BTYPE) == VT_LONG) {
6838 t = (t & ~VT_BTYPE) | VT_LLONG;
6839 } else {
6840 u = VT_LONG;
6841 goto basic_type1;
6843 break;
6844 case TOK_BOOL:
6845 u = VT_BOOL;
6846 goto basic_type;
6847 case TOK_FLOAT:
6848 u = VT_FLOAT;
6849 goto basic_type;
6850 case TOK_DOUBLE:
6851 next();
6852 if ((t & VT_BTYPE) == VT_LONG) {
6853 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6854 } else {
6855 u = VT_DOUBLE;
6856 goto basic_type1;
6858 break;
6859 case TOK_ENUM:
6860 struct_decl(&type1, VT_ENUM);
6861 basic_type2:
6862 u = type1.t;
6863 type->ref = type1.ref;
6864 goto basic_type1;
6865 case TOK_STRUCT:
6866 case TOK_UNION:
6867 struct_decl(&type1, VT_STRUCT);
6868 goto basic_type2;
6870 /* type modifiers */
6871 case TOK_CONST1:
6872 case TOK_CONST2:
6873 case TOK_CONST3:
6874 t |= VT_CONSTANT;
6875 next();
6876 break;
6877 case TOK_VOLATILE1:
6878 case TOK_VOLATILE2:
6879 case TOK_VOLATILE3:
6880 t |= VT_VOLATILE;
6881 next();
6882 break;
6883 case TOK_SIGNED1:
6884 case TOK_SIGNED2:
6885 case TOK_SIGNED3:
6886 typespec_found = 1;
6887 t |= VT_SIGNED;
6888 next();
6889 break;
6890 case TOK_REGISTER:
6891 case TOK_AUTO:
6892 case TOK_RESTRICT1:
6893 case TOK_RESTRICT2:
6894 case TOK_RESTRICT3:
6895 next();
6896 break;
6897 case TOK_UNSIGNED:
6898 t |= VT_UNSIGNED;
6899 next();
6900 typespec_found = 1;
6901 break;
6903 /* storage */
6904 case TOK_EXTERN:
6905 t |= VT_EXTERN;
6906 next();
6907 break;
6908 case TOK_STATIC:
6909 t |= VT_STATIC;
6910 next();
6911 break;
6912 case TOK_TYPEDEF:
6913 t |= VT_TYPEDEF;
6914 next();
6915 break;
6916 case TOK_INLINE1:
6917 case TOK_INLINE2:
6918 case TOK_INLINE3:
6919 t |= VT_INLINE;
6920 next();
6921 break;
6923 /* GNUC attribute */
6924 case TOK_ATTRIBUTE1:
6925 case TOK_ATTRIBUTE2:
6926 parse_attribute(ad);
6927 break;
6928 /* GNUC typeof */
6929 case TOK_TYPEOF1:
6930 case TOK_TYPEOF2:
6931 case TOK_TYPEOF3:
6932 next();
6933 parse_expr_type(&type1);
6934 goto basic_type2;
6935 default:
6936 if (typespec_found || typedef_found)
6937 goto the_end;
6938 s = sym_find(tok);
6939 if (!s || !(s->type.t & VT_TYPEDEF))
6940 goto the_end;
6941 typedef_found = 1;
6942 t |= (s->type.t & ~VT_TYPEDEF);
6943 type->ref = s->type.ref;
6944 next();
6945 typespec_found = 1;
6946 break;
6948 type_found = 1;
6950 the_end:
6951 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6952 error("signed and unsigned modifier");
6953 if (tcc_state->char_is_unsigned) {
6954 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6955 t |= VT_UNSIGNED;
6957 t &= ~VT_SIGNED;
6959 /* long is never used as type */
6960 if ((t & VT_BTYPE) == VT_LONG)
6961 t = (t & ~VT_BTYPE) | VT_INT;
6962 type->t = t;
6963 return type_found;
6966 /* convert a function parameter type (array to pointer and function to
6967 function pointer) */
6968 static inline void convert_parameter_type(CType *pt)
6970 /* remove const and volatile qualifiers (XXX: const could be used
6971 to indicate a const function parameter */
6972 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6973 /* array must be transformed to pointer according to ANSI C */
6974 pt->t &= ~VT_ARRAY;
6975 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6976 mk_pointer(pt);
6980 static void post_type(CType *type, AttributeDef *ad)
6982 int n, l, t1;
6983 Sym **plast, *s, *first;
6984 AttributeDef ad1;
6985 CType pt;
6987 if (tok == '(') {
6988 /* function declaration */
6989 next();
6990 l = 0;
6991 first = NULL;
6992 plast = &first;
6993 if (tok != ')') {
6994 for(;;) {
6995 /* read param name and compute offset */
6996 if (l != FUNC_OLD) {
6997 if (!parse_btype(&pt, &ad1)) {
6998 if (l) {
6999 error("invalid type");
7000 } else {
7001 l = FUNC_OLD;
7002 goto old_proto;
7005 l = FUNC_NEW;
7006 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
7007 break;
7008 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
7009 if ((pt.t & VT_BTYPE) == VT_VOID)
7010 error("parameter declared as void");
7011 } else {
7012 old_proto:
7013 n = tok;
7014 if (n < TOK_UIDENT)
7015 expect("identifier");
7016 pt.t = VT_INT;
7017 next();
7019 convert_parameter_type(&pt);
7020 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
7021 *plast = s;
7022 plast = &s->next;
7023 if (tok == ')')
7024 break;
7025 skip(',');
7026 if (l == FUNC_NEW && tok == TOK_DOTS) {
7027 l = FUNC_ELLIPSIS;
7028 next();
7029 break;
7033 /* if no parameters, then old type prototype */
7034 if (l == 0)
7035 l = FUNC_OLD;
7036 skip(')');
7037 t1 = type->t & VT_STORAGE;
7038 /* NOTE: const is ignored in returned type as it has a special
7039 meaning in gcc / C++ */
7040 type->t &= ~(VT_STORAGE | VT_CONSTANT);
7041 post_type(type, ad);
7042 /* we push a anonymous symbol which will contain the function prototype */
7043 s = sym_push(SYM_FIELD, type, ad->func_call, l);
7044 s->next = first;
7045 type->t = t1 | VT_FUNC;
7046 type->ref = s;
7047 } else if (tok == '[') {
7048 /* array definition */
7049 next();
7050 n = -1;
7051 if (tok != ']') {
7052 n = expr_const();
7053 if (n < 0)
7054 error("invalid array size");
7056 skip(']');
7057 /* parse next post type */
7058 t1 = type->t & VT_STORAGE;
7059 type->t &= ~VT_STORAGE;
7060 post_type(type, ad);
7062 /* we push a anonymous symbol which will contain the array
7063 element type */
7064 s = sym_push(SYM_FIELD, type, 0, n);
7065 type->t = t1 | VT_ARRAY | VT_PTR;
7066 type->ref = s;
7070 /* Parse a type declaration (except basic type), and return the type
7071 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7072 expected. 'type' should contain the basic type. 'ad' is the
7073 attribute definition of the basic type. It can be modified by
7074 type_decl().
7076 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7078 Sym *s;
7079 CType type1, *type2;
7080 int qualifiers;
7082 while (tok == '*') {
7083 qualifiers = 0;
7084 redo:
7085 next();
7086 switch(tok) {
7087 case TOK_CONST1:
7088 case TOK_CONST2:
7089 case TOK_CONST3:
7090 qualifiers |= VT_CONSTANT;
7091 goto redo;
7092 case TOK_VOLATILE1:
7093 case TOK_VOLATILE2:
7094 case TOK_VOLATILE3:
7095 qualifiers |= VT_VOLATILE;
7096 goto redo;
7097 case TOK_RESTRICT1:
7098 case TOK_RESTRICT2:
7099 case TOK_RESTRICT3:
7100 goto redo;
7102 mk_pointer(type);
7103 type->t |= qualifiers;
7106 /* XXX: clarify attribute handling */
7107 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7108 parse_attribute(ad);
7110 /* recursive type */
7111 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7112 type1.t = 0; /* XXX: same as int */
7113 if (tok == '(') {
7114 next();
7115 /* XXX: this is not correct to modify 'ad' at this point, but
7116 the syntax is not clear */
7117 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7118 parse_attribute(ad);
7119 type_decl(&type1, ad, v, td);
7120 skip(')');
7121 } else {
7122 /* type identifier */
7123 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7124 *v = tok;
7125 next();
7126 } else {
7127 if (!(td & TYPE_ABSTRACT))
7128 expect("identifier");
7129 *v = 0;
7132 post_type(type, ad);
7133 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7134 parse_attribute(ad);
7135 if (!type1.t)
7136 return;
7137 /* append type at the end of type1 */
7138 type2 = &type1;
7139 for(;;) {
7140 s = type2->ref;
7141 type2 = &s->type;
7142 if (!type2->t) {
7143 *type2 = *type;
7144 break;
7147 *type = type1;
7150 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7151 static int lvalue_type(int t)
7153 int bt, r;
7154 r = VT_LVAL;
7155 bt = t & VT_BTYPE;
7156 if (bt == VT_BYTE || bt == VT_BOOL)
7157 r |= VT_LVAL_BYTE;
7158 else if (bt == VT_SHORT)
7159 r |= VT_LVAL_SHORT;
7160 else
7161 return r;
7162 if (t & VT_UNSIGNED)
7163 r |= VT_LVAL_UNSIGNED;
7164 return r;
7167 /* indirection with full error checking and bound check */
7168 static void indir(void)
7170 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7171 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7172 return;
7173 expect("pointer");
7175 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7176 gv(RC_INT);
7177 vtop->type = *pointed_type(&vtop->type);
7178 /* Arrays and functions are never lvalues */
7179 if (!(vtop->type.t & VT_ARRAY)
7180 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7181 vtop->r |= lvalue_type(vtop->type.t);
7182 /* if bound checking, the referenced pointer must be checked */
7183 if (do_bounds_check)
7184 vtop->r |= VT_MUSTBOUND;
7188 /* pass a parameter to a function and do type checking and casting */
7189 static void gfunc_param_typed(Sym *func, Sym *arg)
7191 int func_type;
7192 CType type;
7194 func_type = func->c;
7195 if (func_type == FUNC_OLD ||
7196 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7197 /* default casting : only need to convert float to double */
7198 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7199 type.t = VT_DOUBLE;
7200 gen_cast(&type);
7202 } else if (arg == NULL) {
7203 error("too many arguments to function");
7204 } else {
7205 type = arg->type;
7206 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7207 gen_assign_cast(&type);
7211 /* parse an expression of the form '(type)' or '(expr)' and return its
7212 type */
7213 static void parse_expr_type(CType *type)
7215 int n;
7216 AttributeDef ad;
7218 skip('(');
7219 if (parse_btype(type, &ad)) {
7220 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7221 } else {
7222 expr_type(type);
7224 skip(')');
7227 static void parse_type(CType *type)
7229 AttributeDef ad;
7230 int n;
7232 if (!parse_btype(type, &ad)) {
7233 expect("type");
7235 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7238 static void vpush_tokc(int t)
7240 CType type;
7241 type.t = t;
7242 vsetc(&type, VT_CONST, &tokc);
7245 static void unary(void)
7247 int n, t, align, size, r;
7248 CType type;
7249 Sym *s;
7250 AttributeDef ad;
7252 /* XXX: GCC 2.95.3 does not generate a table although it should be
7253 better here */
7254 tok_next:
7255 switch(tok) {
7256 case TOK_EXTENSION:
7257 next();
7258 goto tok_next;
7259 case TOK_CINT:
7260 case TOK_CCHAR:
7261 case TOK_LCHAR:
7262 vpushi(tokc.i);
7263 next();
7264 break;
7265 case TOK_CUINT:
7266 vpush_tokc(VT_INT | VT_UNSIGNED);
7267 next();
7268 break;
7269 case TOK_CLLONG:
7270 vpush_tokc(VT_LLONG);
7271 next();
7272 break;
7273 case TOK_CULLONG:
7274 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7275 next();
7276 break;
7277 case TOK_CFLOAT:
7278 vpush_tokc(VT_FLOAT);
7279 next();
7280 break;
7281 case TOK_CDOUBLE:
7282 vpush_tokc(VT_DOUBLE);
7283 next();
7284 break;
7285 case TOK_CLDOUBLE:
7286 vpush_tokc(VT_LDOUBLE);
7287 next();
7288 break;
7289 case TOK___FUNCTION__:
7290 if (!gnu_ext)
7291 goto tok_identifier;
7292 /* fall thru */
7293 case TOK___FUNC__:
7295 void *ptr;
7296 int len;
7297 /* special function name identifier */
7298 len = strlen(funcname) + 1;
7299 /* generate char[len] type */
7300 type.t = VT_BYTE;
7301 mk_pointer(&type);
7302 type.t |= VT_ARRAY;
7303 type.ref->c = len;
7304 vpush_ref(&type, data_section, data_section->data_offset, len);
7305 ptr = section_ptr_add(data_section, len);
7306 memcpy(ptr, funcname, len);
7307 next();
7309 break;
7310 case TOK_LSTR:
7311 #ifdef TCC_TARGET_PE
7312 t = VT_SHORT | VT_UNSIGNED;
7313 #else
7314 t = VT_INT;
7315 #endif
7316 goto str_init;
7317 case TOK_STR:
7318 /* string parsing */
7319 t = VT_BYTE;
7320 str_init:
7321 if (tcc_state->warn_write_strings)
7322 t |= VT_CONSTANT;
7323 type.t = t;
7324 mk_pointer(&type);
7325 type.t |= VT_ARRAY;
7326 memset(&ad, 0, sizeof(AttributeDef));
7327 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7328 break;
7329 case '(':
7330 next();
7331 /* cast ? */
7332 if (parse_btype(&type, &ad)) {
7333 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7334 skip(')');
7335 /* check ISOC99 compound literal */
7336 if (tok == '{') {
7337 /* data is allocated locally by default */
7338 if (global_expr)
7339 r = VT_CONST;
7340 else
7341 r = VT_LOCAL;
7342 /* all except arrays are lvalues */
7343 if (!(type.t & VT_ARRAY))
7344 r |= lvalue_type(type.t);
7345 memset(&ad, 0, sizeof(AttributeDef));
7346 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7347 } else {
7348 unary();
7349 gen_cast(&type);
7351 } else if (tok == '{') {
7352 /* save all registers */
7353 save_regs(0);
7354 /* statement expression : we do not accept break/continue
7355 inside as GCC does */
7356 block(NULL, NULL, NULL, NULL, 0, 1);
7357 skip(')');
7358 } else {
7359 gexpr();
7360 skip(')');
7362 break;
7363 case '*':
7364 next();
7365 unary();
7366 indir();
7367 break;
7368 case '&':
7369 next();
7370 unary();
7371 /* functions names must be treated as function pointers,
7372 except for unary '&' and sizeof. Since we consider that
7373 functions are not lvalues, we only have to handle it
7374 there and in function calls. */
7375 /* arrays can also be used although they are not lvalues */
7376 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7377 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7378 test_lvalue();
7379 mk_pointer(&vtop->type);
7380 gaddrof();
7381 break;
7382 case '!':
7383 next();
7384 unary();
7385 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7386 vtop->c.i = !vtop->c.i;
7387 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7388 vtop->c.i = vtop->c.i ^ 1;
7389 else {
7390 save_regs(1);
7391 vseti(VT_JMP, gtst(1, 0));
7393 break;
7394 case '~':
7395 next();
7396 unary();
7397 vpushi(-1);
7398 gen_op('^');
7399 break;
7400 case '+':
7401 next();
7402 /* in order to force cast, we add zero */
7403 unary();
7404 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7405 error("pointer not accepted for unary plus");
7406 vpushi(0);
7407 gen_op('+');
7408 break;
7409 case TOK_SIZEOF:
7410 case TOK_ALIGNOF1:
7411 case TOK_ALIGNOF2:
7412 t = tok;
7413 next();
7414 if (tok == '(') {
7415 parse_expr_type(&type);
7416 } else {
7417 unary_type(&type);
7419 size = type_size(&type, &align);
7420 if (t == TOK_SIZEOF) {
7421 if (size < 0)
7422 error("sizeof applied to an incomplete type");
7423 vpushi(size);
7424 } else {
7425 vpushi(align);
7427 vtop->type.t |= VT_UNSIGNED;
7428 break;
7430 case TOK_builtin_types_compatible_p:
7432 CType type1, type2;
7433 next();
7434 skip('(');
7435 parse_type(&type1);
7436 skip(',');
7437 parse_type(&type2);
7438 skip(')');
7439 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7440 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7441 vpushi(is_compatible_types(&type1, &type2));
7443 break;
7444 case TOK_builtin_constant_p:
7446 int saved_nocode_wanted, res;
7447 next();
7448 skip('(');
7449 saved_nocode_wanted = nocode_wanted;
7450 nocode_wanted = 1;
7451 gexpr();
7452 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7453 vpop();
7454 nocode_wanted = saved_nocode_wanted;
7455 skip(')');
7456 vpushi(res);
7458 break;
7459 case TOK_INC:
7460 case TOK_DEC:
7461 t = tok;
7462 next();
7463 unary();
7464 inc(0, t);
7465 break;
7466 case '-':
7467 next();
7468 vpushi(0);
7469 unary();
7470 gen_op('-');
7471 break;
7472 case TOK_LAND:
7473 if (!gnu_ext)
7474 goto tok_identifier;
7475 next();
7476 /* allow to take the address of a label */
7477 if (tok < TOK_UIDENT)
7478 expect("label identifier");
7479 s = label_find(tok);
7480 if (!s) {
7481 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7482 } else {
7483 if (s->r == LABEL_DECLARED)
7484 s->r = LABEL_FORWARD;
7486 if (!s->type.t) {
7487 s->type.t = VT_VOID;
7488 mk_pointer(&s->type);
7489 s->type.t |= VT_STATIC;
7491 vset(&s->type, VT_CONST | VT_SYM, 0);
7492 vtop->sym = s;
7493 next();
7494 break;
7495 default:
7496 tok_identifier:
7497 t = tok;
7498 next();
7499 if (t < TOK_UIDENT)
7500 expect("identifier");
7501 s = sym_find(t);
7502 if (!s) {
7503 if (tok != '(')
7504 error("'%s' undeclared", get_tok_str(t, NULL));
7505 /* for simple function calls, we tolerate undeclared
7506 external reference to int() function */
7507 if (tcc_state->warn_implicit_function_declaration)
7508 warning("implicit declaration of function '%s'",
7509 get_tok_str(t, NULL));
7510 s = external_global_sym(t, &func_old_type, 0);
7512 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7513 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7514 /* if referencing an inline function, then we generate a
7515 symbol to it if not already done. It will have the
7516 effect to generate code for it at the end of the
7517 compilation unit. Inline function as always
7518 generated in the text section. */
7519 if (!s->c)
7520 put_extern_sym(s, text_section, 0, 0);
7521 r = VT_SYM | VT_CONST;
7522 } else {
7523 r = s->r;
7525 vset(&s->type, r, s->c);
7526 /* if forward reference, we must point to s */
7527 if (vtop->r & VT_SYM) {
7528 vtop->sym = s;
7529 vtop->c.ul = 0;
7531 break;
7534 /* post operations */
7535 while (1) {
7536 if (tok == TOK_INC || tok == TOK_DEC) {
7537 inc(1, tok);
7538 next();
7539 } else if (tok == '.' || tok == TOK_ARROW) {
7540 /* field */
7541 if (tok == TOK_ARROW)
7542 indir();
7543 test_lvalue();
7544 gaddrof();
7545 next();
7546 /* expect pointer on structure */
7547 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7548 expect("struct or union");
7549 s = vtop->type.ref;
7550 /* find field */
7551 tok |= SYM_FIELD;
7552 while ((s = s->next) != NULL) {
7553 if (s->v == tok)
7554 break;
7556 if (!s)
7557 error("field not found");
7558 /* add field offset to pointer */
7559 vtop->type = char_pointer_type; /* change type to 'char *' */
7560 vpushi(s->c);
7561 gen_op('+');
7562 /* change type to field type, and set to lvalue */
7563 vtop->type = s->type;
7564 /* an array is never an lvalue */
7565 if (!(vtop->type.t & VT_ARRAY)) {
7566 vtop->r |= lvalue_type(vtop->type.t);
7567 /* if bound checking, the referenced pointer must be checked */
7568 if (do_bounds_check)
7569 vtop->r |= VT_MUSTBOUND;
7571 next();
7572 } else if (tok == '[') {
7573 next();
7574 gexpr();
7575 gen_op('+');
7576 indir();
7577 skip(']');
7578 } else if (tok == '(') {
7579 SValue ret;
7580 Sym *sa;
7581 int nb_args;
7583 /* function call */
7584 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7585 /* pointer test (no array accepted) */
7586 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7587 vtop->type = *pointed_type(&vtop->type);
7588 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7589 goto error_func;
7590 } else {
7591 error_func:
7592 expect("function pointer");
7594 } else {
7595 vtop->r &= ~VT_LVAL; /* no lvalue */
7597 /* get return type */
7598 s = vtop->type.ref;
7599 next();
7600 sa = s->next; /* first parameter */
7601 nb_args = 0;
7602 /* compute first implicit argument if a structure is returned */
7603 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7604 /* get some space for the returned structure */
7605 size = type_size(&s->type, &align);
7606 loc = (loc - size) & -align;
7607 ret.type = s->type;
7608 ret.r = VT_LOCAL | VT_LVAL;
7609 /* pass it as 'int' to avoid structure arg passing
7610 problems */
7611 vseti(VT_LOCAL, loc);
7612 ret.c = vtop->c;
7613 nb_args++;
7614 } else {
7615 ret.type = s->type;
7616 ret.r2 = VT_CONST;
7617 /* return in register */
7618 if (is_float(ret.type.t)) {
7619 ret.r = REG_FRET;
7620 } else {
7621 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7622 ret.r2 = REG_LRET;
7623 ret.r = REG_IRET;
7625 ret.c.i = 0;
7627 if (tok != ')') {
7628 for(;;) {
7629 expr_eq();
7630 gfunc_param_typed(s, sa);
7631 nb_args++;
7632 if (sa)
7633 sa = sa->next;
7634 if (tok == ')')
7635 break;
7636 skip(',');
7639 if (sa)
7640 error("too few arguments to function");
7641 skip(')');
7642 if (!nocode_wanted) {
7643 gfunc_call(nb_args);
7644 } else {
7645 vtop -= (nb_args + 1);
7647 /* return value */
7648 vsetc(&ret.type, ret.r, &ret.c);
7649 vtop->r2 = ret.r2;
7650 } else {
7651 break;
7656 static void uneq(void)
7658 int t;
7660 unary();
7661 if (tok == '=' ||
7662 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7663 tok == TOK_A_XOR || tok == TOK_A_OR ||
7664 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7665 test_lvalue();
7666 t = tok;
7667 next();
7668 if (t == '=') {
7669 expr_eq();
7670 } else {
7671 vdup();
7672 expr_eq();
7673 gen_op(t & 0x7f);
7675 vstore();
7679 static void expr_prod(void)
7681 int t;
7683 uneq();
7684 while (tok == '*' || tok == '/' || tok == '%') {
7685 t = tok;
7686 next();
7687 uneq();
7688 gen_op(t);
7692 static void expr_sum(void)
7694 int t;
7696 expr_prod();
7697 while (tok == '+' || tok == '-') {
7698 t = tok;
7699 next();
7700 expr_prod();
7701 gen_op(t);
7705 static void expr_shift(void)
7707 int t;
7709 expr_sum();
7710 while (tok == TOK_SHL || tok == TOK_SAR) {
7711 t = tok;
7712 next();
7713 expr_sum();
7714 gen_op(t);
7718 static void expr_cmp(void)
7720 int t;
7722 expr_shift();
7723 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7724 tok == TOK_ULT || tok == TOK_UGE) {
7725 t = tok;
7726 next();
7727 expr_shift();
7728 gen_op(t);
7732 static void expr_cmpeq(void)
7734 int t;
7736 expr_cmp();
7737 while (tok == TOK_EQ || tok == TOK_NE) {
7738 t = tok;
7739 next();
7740 expr_cmp();
7741 gen_op(t);
7745 static void expr_and(void)
7747 expr_cmpeq();
7748 while (tok == '&') {
7749 next();
7750 expr_cmpeq();
7751 gen_op('&');
7755 static void expr_xor(void)
7757 expr_and();
7758 while (tok == '^') {
7759 next();
7760 expr_and();
7761 gen_op('^');
7765 static void expr_or(void)
7767 expr_xor();
7768 while (tok == '|') {
7769 next();
7770 expr_xor();
7771 gen_op('|');
7775 /* XXX: fix this mess */
7776 static void expr_land_const(void)
7778 expr_or();
7779 while (tok == TOK_LAND) {
7780 next();
7781 expr_or();
7782 gen_op(TOK_LAND);
7786 /* XXX: fix this mess */
7787 static void expr_lor_const(void)
7789 expr_land_const();
7790 while (tok == TOK_LOR) {
7791 next();
7792 expr_land_const();
7793 gen_op(TOK_LOR);
7797 /* only used if non constant */
7798 static void expr_land(void)
7800 int t;
7802 expr_or();
7803 if (tok == TOK_LAND) {
7804 t = 0;
7805 save_regs(1);
7806 for(;;) {
7807 t = gtst(1, t);
7808 if (tok != TOK_LAND) {
7809 vseti(VT_JMPI, t);
7810 break;
7812 next();
7813 expr_or();
7818 static void expr_lor(void)
7820 int t;
7822 expr_land();
7823 if (tok == TOK_LOR) {
7824 t = 0;
7825 save_regs(1);
7826 for(;;) {
7827 t = gtst(0, t);
7828 if (tok != TOK_LOR) {
7829 vseti(VT_JMP, t);
7830 break;
7832 next();
7833 expr_land();
7838 /* XXX: better constant handling */
7839 static void expr_eq(void)
7841 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7842 SValue sv;
7843 CType type, type1, type2;
7845 if (const_wanted) {
7846 int c1, c;
7847 expr_lor_const();
7848 if (tok == '?') {
7849 c = vtop->c.i;
7850 vpop();
7851 next();
7852 if (tok == ':' && gnu_ext) {
7853 c1 = c;
7854 } else {
7855 gexpr();
7856 c1 = vtop->c.i;
7857 vpop();
7859 skip(':');
7860 expr_eq();
7861 if (c)
7862 vtop->c.i = c1;
7864 } else {
7865 expr_lor();
7866 if (tok == '?') {
7867 next();
7868 if (vtop != vstack) {
7869 /* needed to avoid having different registers saved in
7870 each branch */
7871 if (is_float(vtop->type.t))
7872 rc = RC_FLOAT;
7873 else
7874 rc = RC_INT;
7875 gv(rc);
7876 save_regs(1);
7878 if (tok == ':' && gnu_ext) {
7879 gv_dup();
7880 tt = gtst(1, 0);
7881 } else {
7882 tt = gtst(1, 0);
7883 gexpr();
7885 type1 = vtop->type;
7886 sv = *vtop; /* save value to handle it later */
7887 vtop--; /* no vpop so that FP stack is not flushed */
7888 skip(':');
7889 u = gjmp(0);
7890 gsym(tt);
7891 expr_eq();
7892 type2 = vtop->type;
7894 t1 = type1.t;
7895 bt1 = t1 & VT_BTYPE;
7896 t2 = type2.t;
7897 bt2 = t2 & VT_BTYPE;
7898 /* cast operands to correct type according to ISOC rules */
7899 if (is_float(bt1) || is_float(bt2)) {
7900 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7901 type.t = VT_LDOUBLE;
7902 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7903 type.t = VT_DOUBLE;
7904 } else {
7905 type.t = VT_FLOAT;
7907 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7908 /* cast to biggest op */
7909 type.t = VT_LLONG;
7910 /* convert to unsigned if it does not fit in a long long */
7911 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7912 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7913 type.t |= VT_UNSIGNED;
7914 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7915 /* XXX: test pointer compatibility */
7916 type = type1;
7917 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
7918 /* XXX: test function pointer compatibility */
7919 type = type1;
7920 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7921 /* XXX: test structure compatibility */
7922 type = type1;
7923 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7924 /* NOTE: as an extension, we accept void on only one side */
7925 type.t = VT_VOID;
7926 } else {
7927 /* integer operations */
7928 type.t = VT_INT;
7929 /* convert to unsigned if it does not fit in an integer */
7930 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7931 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7932 type.t |= VT_UNSIGNED;
7935 /* now we convert second operand */
7936 gen_cast(&type);
7937 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
7938 gaddrof();
7939 rc = RC_INT;
7940 if (is_float(type.t)) {
7941 rc = RC_FLOAT;
7942 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7943 /* for long longs, we use fixed registers to avoid having
7944 to handle a complicated move */
7945 rc = RC_IRET;
7948 r2 = gv(rc);
7949 /* this is horrible, but we must also convert first
7950 operand */
7951 tt = gjmp(0);
7952 gsym(u);
7953 /* put again first value and cast it */
7954 *vtop = sv;
7955 gen_cast(&type);
7956 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
7957 gaddrof();
7958 r1 = gv(rc);
7959 move_reg(r2, r1);
7960 vtop->r = r2;
7961 gsym(tt);
7966 static void gexpr(void)
7968 while (1) {
7969 expr_eq();
7970 if (tok != ',')
7971 break;
7972 vpop();
7973 next();
7977 /* parse an expression and return its type without any side effect. */
7978 static void expr_type(CType *type)
7980 int saved_nocode_wanted;
7982 saved_nocode_wanted = nocode_wanted;
7983 nocode_wanted = 1;
7984 gexpr();
7985 *type = vtop->type;
7986 vpop();
7987 nocode_wanted = saved_nocode_wanted;
7990 /* parse a unary expression and return its type without any side
7991 effect. */
7992 static void unary_type(CType *type)
7994 int a;
7996 a = nocode_wanted;
7997 nocode_wanted = 1;
7998 unary();
7999 *type = vtop->type;
8000 vpop();
8001 nocode_wanted = a;
8004 /* parse a constant expression and return value in vtop. */
8005 static void expr_const1(void)
8007 int a;
8008 a = const_wanted;
8009 const_wanted = 1;
8010 expr_eq();
8011 const_wanted = a;
8014 /* parse an integer constant and return its value. */
8015 static int expr_const(void)
8017 int c;
8018 expr_const1();
8019 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8020 expect("constant expression");
8021 c = vtop->c.i;
8022 vpop();
8023 return c;
8026 /* return the label token if current token is a label, otherwise
8027 return zero */
8028 static int is_label(void)
8030 int last_tok;
8032 /* fast test first */
8033 if (tok < TOK_UIDENT)
8034 return 0;
8035 /* no need to save tokc because tok is an identifier */
8036 last_tok = tok;
8037 next();
8038 if (tok == ':') {
8039 next();
8040 return last_tok;
8041 } else {
8042 unget_tok(last_tok);
8043 return 0;
8047 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8048 int case_reg, int is_expr)
8050 int a, b, c, d;
8051 Sym *s;
8053 /* generate line number info */
8054 if (do_debug &&
8055 (last_line_num != file->line_num || last_ind != ind)) {
8056 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8057 last_ind = ind;
8058 last_line_num = file->line_num;
8061 if (is_expr) {
8062 /* default return value is (void) */
8063 vpushi(0);
8064 vtop->type.t = VT_VOID;
8067 if (tok == TOK_IF) {
8068 /* if test */
8069 next();
8070 skip('(');
8071 gexpr();
8072 skip(')');
8073 a = gtst(1, 0);
8074 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8075 c = tok;
8076 if (c == TOK_ELSE) {
8077 next();
8078 d = gjmp(0);
8079 gsym(a);
8080 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8081 gsym(d); /* patch else jmp */
8082 } else
8083 gsym(a);
8084 } else if (tok == TOK_WHILE) {
8085 next();
8086 d = ind;
8087 skip('(');
8088 gexpr();
8089 skip(')');
8090 a = gtst(1, 0);
8091 b = 0;
8092 block(&a, &b, case_sym, def_sym, case_reg, 0);
8093 gjmp_addr(d);
8094 gsym(a);
8095 gsym_addr(b, d);
8096 } else if (tok == '{') {
8097 Sym *llabel;
8099 next();
8100 /* record local declaration stack position */
8101 s = local_stack;
8102 llabel = local_label_stack;
8103 /* handle local labels declarations */
8104 if (tok == TOK_LABEL) {
8105 next();
8106 for(;;) {
8107 if (tok < TOK_UIDENT)
8108 expect("label identifier");
8109 label_push(&local_label_stack, tok, LABEL_DECLARED);
8110 next();
8111 if (tok == ',') {
8112 next();
8113 } else {
8114 skip(';');
8115 break;
8119 while (tok != '}') {
8120 decl(VT_LOCAL);
8121 if (tok != '}') {
8122 if (is_expr)
8123 vpop();
8124 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8127 /* pop locally defined labels */
8128 label_pop(&local_label_stack, llabel);
8129 /* pop locally defined symbols */
8130 sym_pop(&local_stack, s);
8131 next();
8132 } else if (tok == TOK_RETURN) {
8133 next();
8134 if (tok != ';') {
8135 gexpr();
8136 gen_assign_cast(&func_vt);
8137 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8138 CType type;
8139 /* if returning structure, must copy it to implicit
8140 first pointer arg location */
8141 #ifdef TCC_ARM_EABI
8142 int align, size;
8143 size = type_size(&func_vt,&align);
8144 if(size <= 4)
8146 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8147 && (align & 3))
8149 int addr;
8150 loc = (loc - size) & -4;
8151 addr = loc;
8152 type = func_vt;
8153 vset(&type, VT_LOCAL | VT_LVAL, addr);
8154 vswap();
8155 vstore();
8156 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8158 vtop->type = int_type;
8159 gv(RC_IRET);
8160 } else {
8161 #endif
8162 type = func_vt;
8163 mk_pointer(&type);
8164 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8165 indir();
8166 vswap();
8167 /* copy structure value to pointer */
8168 vstore();
8169 #ifdef TCC_ARM_EABI
8171 #endif
8172 } else if (is_float(func_vt.t)) {
8173 gv(RC_FRET);
8174 } else {
8175 gv(RC_IRET);
8177 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8179 skip(';');
8180 rsym = gjmp(rsym); /* jmp */
8181 } else if (tok == TOK_BREAK) {
8182 /* compute jump */
8183 if (!bsym)
8184 error("cannot break");
8185 *bsym = gjmp(*bsym);
8186 next();
8187 skip(';');
8188 } else if (tok == TOK_CONTINUE) {
8189 /* compute jump */
8190 if (!csym)
8191 error("cannot continue");
8192 *csym = gjmp(*csym);
8193 next();
8194 skip(';');
8195 } else if (tok == TOK_FOR) {
8196 int e;
8197 next();
8198 skip('(');
8199 if (tok != ';') {
8200 gexpr();
8201 vpop();
8203 skip(';');
8204 d = ind;
8205 c = ind;
8206 a = 0;
8207 b = 0;
8208 if (tok != ';') {
8209 gexpr();
8210 a = gtst(1, 0);
8212 skip(';');
8213 if (tok != ')') {
8214 e = gjmp(0);
8215 c = ind;
8216 gexpr();
8217 vpop();
8218 gjmp_addr(d);
8219 gsym(e);
8221 skip(')');
8222 block(&a, &b, case_sym, def_sym, case_reg, 0);
8223 gjmp_addr(c);
8224 gsym(a);
8225 gsym_addr(b, c);
8226 } else
8227 if (tok == TOK_DO) {
8228 next();
8229 a = 0;
8230 b = 0;
8231 d = ind;
8232 block(&a, &b, case_sym, def_sym, case_reg, 0);
8233 skip(TOK_WHILE);
8234 skip('(');
8235 gsym(b);
8236 gexpr();
8237 c = gtst(0, 0);
8238 gsym_addr(c, d);
8239 skip(')');
8240 gsym(a);
8241 skip(';');
8242 } else
8243 if (tok == TOK_SWITCH) {
8244 next();
8245 skip('(');
8246 gexpr();
8247 /* XXX: other types than integer */
8248 case_reg = gv(RC_INT);
8249 vpop();
8250 skip(')');
8251 a = 0;
8252 b = gjmp(0); /* jump to first case */
8253 c = 0;
8254 block(&a, csym, &b, &c, case_reg, 0);
8255 /* if no default, jmp after switch */
8256 if (c == 0)
8257 c = ind;
8258 /* default label */
8259 gsym_addr(b, c);
8260 /* break label */
8261 gsym(a);
8262 } else
8263 if (tok == TOK_CASE) {
8264 int v1, v2;
8265 if (!case_sym)
8266 expect("switch");
8267 next();
8268 v1 = expr_const();
8269 v2 = v1;
8270 if (gnu_ext && tok == TOK_DOTS) {
8271 next();
8272 v2 = expr_const();
8273 if (v2 < v1)
8274 warning("empty case range");
8276 /* since a case is like a label, we must skip it with a jmp */
8277 b = gjmp(0);
8278 gsym(*case_sym);
8279 vseti(case_reg, 0);
8280 vpushi(v1);
8281 if (v1 == v2) {
8282 gen_op(TOK_EQ);
8283 *case_sym = gtst(1, 0);
8284 } else {
8285 gen_op(TOK_GE);
8286 *case_sym = gtst(1, 0);
8287 vseti(case_reg, 0);
8288 vpushi(v2);
8289 gen_op(TOK_LE);
8290 *case_sym = gtst(1, *case_sym);
8292 gsym(b);
8293 skip(':');
8294 is_expr = 0;
8295 goto block_after_label;
8296 } else
8297 if (tok == TOK_DEFAULT) {
8298 next();
8299 skip(':');
8300 if (!def_sym)
8301 expect("switch");
8302 if (*def_sym)
8303 error("too many 'default'");
8304 *def_sym = ind;
8305 is_expr = 0;
8306 goto block_after_label;
8307 } else
8308 if (tok == TOK_GOTO) {
8309 next();
8310 if (tok == '*' && gnu_ext) {
8311 /* computed goto */
8312 next();
8313 gexpr();
8314 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8315 expect("pointer");
8316 ggoto();
8317 } else if (tok >= TOK_UIDENT) {
8318 s = label_find(tok);
8319 /* put forward definition if needed */
8320 if (!s) {
8321 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8322 } else {
8323 if (s->r == LABEL_DECLARED)
8324 s->r = LABEL_FORWARD;
8326 /* label already defined */
8327 if (s->r & LABEL_FORWARD)
8328 s->next = (void *)gjmp((long)s->next);
8329 else
8330 gjmp_addr((long)s->next);
8331 next();
8332 } else {
8333 expect("label identifier");
8335 skip(';');
8336 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8337 asm_instr();
8338 } else {
8339 b = is_label();
8340 if (b) {
8341 /* label case */
8342 s = label_find(b);
8343 if (s) {
8344 if (s->r == LABEL_DEFINED)
8345 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8346 gsym((long)s->next);
8347 s->r = LABEL_DEFINED;
8348 } else {
8349 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8351 s->next = (void *)ind;
8352 /* we accept this, but it is a mistake */
8353 block_after_label:
8354 if (tok == '}') {
8355 warning("deprecated use of label at end of compound statement");
8356 } else {
8357 if (is_expr)
8358 vpop();
8359 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8361 } else {
8362 /* expression case */
8363 if (tok != ';') {
8364 if (is_expr) {
8365 vpop();
8366 gexpr();
8367 } else {
8368 gexpr();
8369 vpop();
8372 skip(';');
8377 /* t is the array or struct type. c is the array or struct
8378 address. cur_index/cur_field is the pointer to the current
8379 value. 'size_only' is true if only size info is needed (only used
8380 in arrays) */
8381 static void decl_designator(CType *type, Section *sec, unsigned long c,
8382 int *cur_index, Sym **cur_field,
8383 int size_only)
8385 Sym *s, *f;
8386 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8387 CType type1;
8389 notfirst = 0;
8390 elem_size = 0;
8391 nb_elems = 1;
8392 if (gnu_ext && (l = is_label()) != 0)
8393 goto struct_field;
8394 while (tok == '[' || tok == '.') {
8395 if (tok == '[') {
8396 if (!(type->t & VT_ARRAY))
8397 expect("array type");
8398 s = type->ref;
8399 next();
8400 index = expr_const();
8401 if (index < 0 || (s->c >= 0 && index >= s->c))
8402 expect("invalid index");
8403 if (tok == TOK_DOTS && gnu_ext) {
8404 next();
8405 index_last = expr_const();
8406 if (index_last < 0 ||
8407 (s->c >= 0 && index_last >= s->c) ||
8408 index_last < index)
8409 expect("invalid index");
8410 } else {
8411 index_last = index;
8413 skip(']');
8414 if (!notfirst)
8415 *cur_index = index_last;
8416 type = pointed_type(type);
8417 elem_size = type_size(type, &align);
8418 c += index * elem_size;
8419 /* NOTE: we only support ranges for last designator */
8420 nb_elems = index_last - index + 1;
8421 if (nb_elems != 1) {
8422 notfirst = 1;
8423 break;
8425 } else {
8426 next();
8427 l = tok;
8428 next();
8429 struct_field:
8430 if ((type->t & VT_BTYPE) != VT_STRUCT)
8431 expect("struct/union type");
8432 s = type->ref;
8433 l |= SYM_FIELD;
8434 f = s->next;
8435 while (f) {
8436 if (f->v == l)
8437 break;
8438 f = f->next;
8440 if (!f)
8441 expect("field");
8442 if (!notfirst)
8443 *cur_field = f;
8444 /* XXX: fix this mess by using explicit storage field */
8445 type1 = f->type;
8446 type1.t |= (type->t & ~VT_TYPE);
8447 type = &type1;
8448 c += f->c;
8450 notfirst = 1;
8452 if (notfirst) {
8453 if (tok == '=') {
8454 next();
8455 } else {
8456 if (!gnu_ext)
8457 expect("=");
8459 } else {
8460 if (type->t & VT_ARRAY) {
8461 index = *cur_index;
8462 type = pointed_type(type);
8463 c += index * type_size(type, &align);
8464 } else {
8465 f = *cur_field;
8466 if (!f)
8467 error("too many field init");
8468 /* XXX: fix this mess by using explicit storage field */
8469 type1 = f->type;
8470 type1.t |= (type->t & ~VT_TYPE);
8471 type = &type1;
8472 c += f->c;
8475 decl_initializer(type, sec, c, 0, size_only);
8477 /* XXX: make it more general */
8478 if (!size_only && nb_elems > 1) {
8479 unsigned long c_end;
8480 uint8_t *src, *dst;
8481 int i;
8483 if (!sec)
8484 error("range init not supported yet for dynamic storage");
8485 c_end = c + nb_elems * elem_size;
8486 if (c_end > sec->data_allocated)
8487 section_realloc(sec, c_end);
8488 src = sec->data + c;
8489 dst = src;
8490 for(i = 1; i < nb_elems; i++) {
8491 dst += elem_size;
8492 memcpy(dst, src, elem_size);
8497 #define EXPR_VAL 0
8498 #define EXPR_CONST 1
8499 #define EXPR_ANY 2
8501 /* store a value or an expression directly in global data or in local array */
8502 static void init_putv(CType *type, Section *sec, unsigned long c,
8503 int v, int expr_type)
8505 int saved_global_expr, bt, bit_pos, bit_size;
8506 void *ptr;
8507 unsigned long long bit_mask;
8508 CType dtype;
8510 switch(expr_type) {
8511 case EXPR_VAL:
8512 vpushi(v);
8513 break;
8514 case EXPR_CONST:
8515 /* compound literals must be allocated globally in this case */
8516 saved_global_expr = global_expr;
8517 global_expr = 1;
8518 expr_const1();
8519 global_expr = saved_global_expr;
8520 /* NOTE: symbols are accepted */
8521 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8522 error("initializer element is not constant");
8523 break;
8524 case EXPR_ANY:
8525 expr_eq();
8526 break;
8529 dtype = *type;
8530 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8532 if (sec) {
8533 /* XXX: not portable */
8534 /* XXX: generate error if incorrect relocation */
8535 gen_assign_cast(&dtype);
8536 bt = type->t & VT_BTYPE;
8537 ptr = sec->data + c;
8538 /* XXX: make code faster ? */
8539 if (!(type->t & VT_BITFIELD)) {
8540 bit_pos = 0;
8541 bit_size = 32;
8542 bit_mask = -1LL;
8543 } else {
8544 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8545 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8546 bit_mask = (1LL << bit_size) - 1;
8548 if ((vtop->r & VT_SYM) &&
8549 (bt == VT_BYTE ||
8550 bt == VT_SHORT ||
8551 bt == VT_DOUBLE ||
8552 bt == VT_LDOUBLE ||
8553 bt == VT_LLONG ||
8554 (bt == VT_INT && bit_size != 32)))
8555 error("initializer element is not computable at load time");
8556 switch(bt) {
8557 case VT_BYTE:
8558 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8559 break;
8560 case VT_SHORT:
8561 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8562 break;
8563 case VT_DOUBLE:
8564 *(double *)ptr = vtop->c.d;
8565 break;
8566 case VT_LDOUBLE:
8567 *(long double *)ptr = vtop->c.ld;
8568 break;
8569 case VT_LLONG:
8570 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8571 break;
8572 default:
8573 if (vtop->r & VT_SYM) {
8574 greloc(sec, vtop->sym, c, R_DATA_32);
8576 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8577 break;
8579 vtop--;
8580 } else {
8581 vset(&dtype, VT_LOCAL|VT_LVAL, c);
8582 vswap();
8583 vstore();
8584 vpop();
8588 /* put zeros for variable based init */
8589 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8591 if (sec) {
8592 /* nothing to do because globals are already set to zero */
8593 } else {
8594 vpush_global_sym(&func_old_type, TOK_memset);
8595 vseti(VT_LOCAL, c);
8596 vpushi(0);
8597 vpushi(size);
8598 gfunc_call(3);
8602 /* 't' contains the type and storage info. 'c' is the offset of the
8603 object in section 'sec'. If 'sec' is NULL, it means stack based
8604 allocation. 'first' is true if array '{' must be read (multi
8605 dimension implicit array init handling). 'size_only' is true if
8606 size only evaluation is wanted (only for arrays). */
8607 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8608 int first, int size_only)
8610 int index, array_length, n, no_oblock, nb, parlevel, i;
8611 int size1, align1, expr_type;
8612 Sym *s, *f;
8613 CType *t1;
8615 if (type->t & VT_ARRAY) {
8616 s = type->ref;
8617 n = s->c;
8618 array_length = 0;
8619 t1 = pointed_type(type);
8620 size1 = type_size(t1, &align1);
8622 no_oblock = 1;
8623 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8624 tok == '{') {
8625 skip('{');
8626 no_oblock = 0;
8629 /* only parse strings here if correct type (otherwise: handle
8630 them as ((w)char *) expressions */
8631 if ((tok == TOK_LSTR &&
8632 #ifdef TCC_TARGET_PE
8633 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)) ||
8634 #else
8635 (t1->t & VT_BTYPE) == VT_INT) ||
8636 #endif
8637 (tok == TOK_STR &&
8638 (t1->t & VT_BTYPE) == VT_BYTE)) {
8639 while (tok == TOK_STR || tok == TOK_LSTR) {
8640 int cstr_len, ch;
8641 CString *cstr;
8643 cstr = tokc.cstr;
8644 /* compute maximum number of chars wanted */
8645 if (tok == TOK_STR)
8646 cstr_len = cstr->size;
8647 else
8648 cstr_len = cstr->size / sizeof(nwchar_t);
8649 cstr_len--;
8650 nb = cstr_len;
8651 if (n >= 0 && nb > (n - array_length))
8652 nb = n - array_length;
8653 if (!size_only) {
8654 if (cstr_len > nb)
8655 warning("initializer-string for array is too long");
8656 /* in order to go faster for common case (char
8657 string in global variable, we handle it
8658 specifically */
8659 if (sec && tok == TOK_STR && size1 == 1) {
8660 memcpy(sec->data + c + array_length, cstr->data, nb);
8661 } else {
8662 for(i=0;i<nb;i++) {
8663 if (tok == TOK_STR)
8664 ch = ((unsigned char *)cstr->data)[i];
8665 else
8666 ch = ((nwchar_t *)cstr->data)[i];
8667 init_putv(t1, sec, c + (array_length + i) * size1,
8668 ch, EXPR_VAL);
8672 array_length += nb;
8673 next();
8675 /* only add trailing zero if enough storage (no
8676 warning in this case since it is standard) */
8677 if (n < 0 || array_length < n) {
8678 if (!size_only) {
8679 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8681 array_length++;
8683 } else {
8684 index = 0;
8685 while (tok != '}') {
8686 decl_designator(type, sec, c, &index, NULL, size_only);
8687 if (n >= 0 && index >= n)
8688 error("index too large");
8689 /* must put zero in holes (note that doing it that way
8690 ensures that it even works with designators) */
8691 if (!size_only && array_length < index) {
8692 init_putz(t1, sec, c + array_length * size1,
8693 (index - array_length) * size1);
8695 index++;
8696 if (index > array_length)
8697 array_length = index;
8698 /* special test for multi dimensional arrays (may not
8699 be strictly correct if designators are used at the
8700 same time) */
8701 if (index >= n && no_oblock)
8702 break;
8703 if (tok == '}')
8704 break;
8705 skip(',');
8708 if (!no_oblock)
8709 skip('}');
8710 /* put zeros at the end */
8711 if (!size_only && n >= 0 && array_length < n) {
8712 init_putz(t1, sec, c + array_length * size1,
8713 (n - array_length) * size1);
8715 /* patch type size if needed */
8716 if (n < 0)
8717 s->c = array_length;
8718 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8719 (sec || !first || tok == '{')) {
8720 int par_count;
8722 /* NOTE: the previous test is a specific case for automatic
8723 struct/union init */
8724 /* XXX: union needs only one init */
8726 /* XXX: this test is incorrect for local initializers
8727 beginning with ( without {. It would be much more difficult
8728 to do it correctly (ideally, the expression parser should
8729 be used in all cases) */
8730 par_count = 0;
8731 if (tok == '(') {
8732 AttributeDef ad1;
8733 CType type1;
8734 next();
8735 while (tok == '(') {
8736 par_count++;
8737 next();
8739 if (!parse_btype(&type1, &ad1))
8740 expect("cast");
8741 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8742 #if 0
8743 if (!is_assignable_types(type, &type1))
8744 error("invalid type for cast");
8745 #endif
8746 skip(')');
8748 no_oblock = 1;
8749 if (first || tok == '{') {
8750 skip('{');
8751 no_oblock = 0;
8753 s = type->ref;
8754 f = s->next;
8755 array_length = 0;
8756 index = 0;
8757 n = s->c;
8758 while (tok != '}') {
8759 decl_designator(type, sec, c, NULL, &f, size_only);
8760 index = f->c;
8761 if (!size_only && array_length < index) {
8762 init_putz(type, sec, c + array_length,
8763 index - array_length);
8765 index = index + type_size(&f->type, &align1);
8766 if (index > array_length)
8767 array_length = index;
8768 f = f->next;
8769 if (no_oblock && f == NULL)
8770 break;
8771 if (tok == '}')
8772 break;
8773 skip(',');
8775 /* put zeros at the end */
8776 if (!size_only && array_length < n) {
8777 init_putz(type, sec, c + array_length,
8778 n - array_length);
8780 if (!no_oblock)
8781 skip('}');
8782 while (par_count) {
8783 skip(')');
8784 par_count--;
8786 } else if (tok == '{') {
8787 next();
8788 decl_initializer(type, sec, c, first, size_only);
8789 skip('}');
8790 } else if (size_only) {
8791 /* just skip expression */
8792 parlevel = 0;
8793 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8794 tok != -1) {
8795 if (tok == '(')
8796 parlevel++;
8797 else if (tok == ')')
8798 parlevel--;
8799 next();
8801 } else {
8802 /* currently, we always use constant expression for globals
8803 (may change for scripting case) */
8804 expr_type = EXPR_CONST;
8805 if (!sec)
8806 expr_type = EXPR_ANY;
8807 init_putv(type, sec, c, 0, expr_type);
8811 /* parse an initializer for type 't' if 'has_init' is non zero, and
8812 allocate space in local or global data space ('r' is either
8813 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8814 variable 'v' of scope 'scope' is declared before initializers are
8815 parsed. If 'v' is zero, then a reference to the new object is put
8816 in the value stack. If 'has_init' is 2, a special parsing is done
8817 to handle string constants. */
8818 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8819 int has_init, int v, int scope)
8821 int size, align, addr, data_offset;
8822 int level;
8823 ParseState saved_parse_state;
8824 TokenString init_str;
8825 Section *sec;
8827 size = type_size(type, &align);
8828 /* If unknown size, we must evaluate it before
8829 evaluating initializers because
8830 initializers can generate global data too
8831 (e.g. string pointers or ISOC99 compound
8832 literals). It also simplifies local
8833 initializers handling */
8834 tok_str_new(&init_str);
8835 if (size < 0) {
8836 if (!has_init)
8837 error("unknown type size");
8838 /* get all init string */
8839 if (has_init == 2) {
8840 /* only get strings */
8841 while (tok == TOK_STR || tok == TOK_LSTR) {
8842 tok_str_add_tok(&init_str);
8843 next();
8845 } else {
8846 level = 0;
8847 while (level > 0 || (tok != ',' && tok != ';')) {
8848 if (tok < 0)
8849 error("unexpected end of file in initializer");
8850 tok_str_add_tok(&init_str);
8851 if (tok == '{')
8852 level++;
8853 else if (tok == '}') {
8854 if (level == 0)
8855 break;
8856 level--;
8858 next();
8861 tok_str_add(&init_str, -1);
8862 tok_str_add(&init_str, 0);
8864 /* compute size */
8865 save_parse_state(&saved_parse_state);
8867 macro_ptr = init_str.str;
8868 next();
8869 decl_initializer(type, NULL, 0, 1, 1);
8870 /* prepare second initializer parsing */
8871 macro_ptr = init_str.str;
8872 next();
8874 /* if still unknown size, error */
8875 size = type_size(type, &align);
8876 if (size < 0)
8877 error("unknown type size");
8879 /* take into account specified alignment if bigger */
8880 if (ad->aligned) {
8881 if (ad->aligned > align)
8882 align = ad->aligned;
8883 } else if (ad->packed) {
8884 align = 1;
8886 if ((r & VT_VALMASK) == VT_LOCAL) {
8887 sec = NULL;
8888 if (do_bounds_check && (type->t & VT_ARRAY))
8889 loc--;
8890 loc = (loc - size) & -align;
8891 addr = loc;
8892 /* handles bounds */
8893 /* XXX: currently, since we do only one pass, we cannot track
8894 '&' operators, so we add only arrays */
8895 if (do_bounds_check && (type->t & VT_ARRAY)) {
8896 unsigned long *bounds_ptr;
8897 /* add padding between regions */
8898 loc--;
8899 /* then add local bound info */
8900 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8901 bounds_ptr[0] = addr;
8902 bounds_ptr[1] = size;
8904 if (v) {
8905 /* local variable */
8906 sym_push(v, type, r, addr);
8907 } else {
8908 /* push local reference */
8909 vset(type, r, addr);
8911 } else {
8912 Sym *sym;
8914 sym = NULL;
8915 if (v && scope == VT_CONST) {
8916 /* see if the symbol was already defined */
8917 sym = sym_find(v);
8918 if (sym) {
8919 if (!is_compatible_types(&sym->type, type))
8920 error("incompatible types for redefinition of '%s'",
8921 get_tok_str(v, NULL));
8922 if (sym->type.t & VT_EXTERN) {
8923 /* if the variable is extern, it was not allocated */
8924 sym->type.t &= ~VT_EXTERN;
8925 /* set array size if it was ommited in extern
8926 declaration */
8927 if ((sym->type.t & VT_ARRAY) &&
8928 sym->type.ref->c < 0 &&
8929 type->ref->c >= 0)
8930 sym->type.ref->c = type->ref->c;
8931 } else {
8932 /* we accept several definitions of the same
8933 global variable. this is tricky, because we
8934 must play with the SHN_COMMON type of the symbol */
8935 /* XXX: should check if the variable was already
8936 initialized. It is incorrect to initialized it
8937 twice */
8938 /* no init data, we won't add more to the symbol */
8939 if (!has_init)
8940 goto no_alloc;
8945 /* allocate symbol in corresponding section */
8946 sec = ad->section;
8947 if (!sec) {
8948 if (has_init)
8949 sec = data_section;
8950 else if (tcc_state->nocommon)
8951 sec = bss_section;
8953 if (sec) {
8954 data_offset = sec->data_offset;
8955 data_offset = (data_offset + align - 1) & -align;
8956 addr = data_offset;
8957 /* very important to increment global pointer at this time
8958 because initializers themselves can create new initializers */
8959 data_offset += size;
8960 /* add padding if bound check */
8961 if (do_bounds_check)
8962 data_offset++;
8963 sec->data_offset = data_offset;
8964 /* allocate section space to put the data */
8965 if (sec->sh_type != SHT_NOBITS &&
8966 data_offset > sec->data_allocated)
8967 section_realloc(sec, data_offset);
8968 /* align section if needed */
8969 if (align > sec->sh_addralign)
8970 sec->sh_addralign = align;
8971 } else {
8972 addr = 0; /* avoid warning */
8975 if (v) {
8976 if (scope != VT_CONST || !sym) {
8977 sym = sym_push(v, type, r | VT_SYM, 0);
8979 /* update symbol definition */
8980 if (sec) {
8981 put_extern_sym(sym, sec, addr, size);
8982 } else {
8983 Elf32_Sym *esym;
8984 /* put a common area */
8985 put_extern_sym(sym, NULL, align, size);
8986 /* XXX: find a nicer way */
8987 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8988 esym->st_shndx = SHN_COMMON;
8990 } else {
8991 CValue cval;
8993 /* push global reference */
8994 sym = get_sym_ref(type, sec, addr, size);
8995 cval.ul = 0;
8996 vsetc(type, VT_CONST | VT_SYM, &cval);
8997 vtop->sym = sym;
9000 /* handles bounds now because the symbol must be defined
9001 before for the relocation */
9002 if (do_bounds_check) {
9003 unsigned long *bounds_ptr;
9005 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9006 /* then add global bound info */
9007 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9008 bounds_ptr[0] = 0; /* relocated */
9009 bounds_ptr[1] = size;
9012 if (has_init) {
9013 decl_initializer(type, sec, addr, 1, 0);
9014 /* restore parse state if needed */
9015 if (init_str.str) {
9016 tok_str_free(init_str.str);
9017 restore_parse_state(&saved_parse_state);
9020 no_alloc: ;
9023 void put_func_debug(Sym *sym)
9025 char buf[512];
9027 /* stabs info */
9028 /* XXX: we put here a dummy type */
9029 snprintf(buf, sizeof(buf), "%s:%c1",
9030 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9031 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9032 cur_text_section, sym->c);
9033 last_ind = 0;
9034 last_line_num = 0;
9037 /* parse an old style function declaration list */
9038 /* XXX: check multiple parameter */
9039 static void func_decl_list(Sym *func_sym)
9041 AttributeDef ad;
9042 int v;
9043 Sym *s;
9044 CType btype, type;
9046 /* parse each declaration */
9047 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9048 if (!parse_btype(&btype, &ad))
9049 expect("declaration list");
9050 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9051 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9052 tok == ';') {
9053 /* we accept no variable after */
9054 } else {
9055 for(;;) {
9056 type = btype;
9057 type_decl(&type, &ad, &v, TYPE_DIRECT);
9058 /* find parameter in function parameter list */
9059 s = func_sym->next;
9060 while (s != NULL) {
9061 if ((s->v & ~SYM_FIELD) == v)
9062 goto found;
9063 s = s->next;
9065 error("declaration for parameter '%s' but no such parameter",
9066 get_tok_str(v, NULL));
9067 found:
9068 /* check that no storage specifier except 'register' was given */
9069 if (type.t & VT_STORAGE)
9070 error("storage class specified for '%s'", get_tok_str(v, NULL));
9071 convert_parameter_type(&type);
9072 /* we can add the type (NOTE: it could be local to the function) */
9073 s->type = type;
9074 /* accept other parameters */
9075 if (tok == ',')
9076 next();
9077 else
9078 break;
9081 skip(';');
9085 /* parse a function defined by symbol 'sym' and generate its code in
9086 'cur_text_section' */
9087 static void gen_function(Sym *sym)
9089 int saved_nocode_wanted = nocode_wanted;
9090 nocode_wanted = 0;
9091 ind = cur_text_section->data_offset;
9092 /* NOTE: we patch the symbol size later */
9093 put_extern_sym(sym, cur_text_section, ind, 0);
9094 funcname = get_tok_str(sym->v, NULL);
9095 func_ind = ind;
9096 /* put debug symbol */
9097 if (do_debug)
9098 put_func_debug(sym);
9099 /* push a dummy symbol to enable local sym storage */
9100 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9101 gfunc_prolog(&sym->type);
9102 rsym = 0;
9103 block(NULL, NULL, NULL, NULL, 0, 0);
9104 gsym(rsym);
9105 gfunc_epilog();
9106 cur_text_section->data_offset = ind;
9107 label_pop(&global_label_stack, NULL);
9108 sym_pop(&local_stack, NULL); /* reset local stack */
9109 /* end of function */
9110 /* patch symbol size */
9111 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
9112 ind - func_ind;
9113 if (do_debug) {
9114 put_stabn(N_FUN, 0, 0, ind - func_ind);
9116 funcname = ""; /* for safety */
9117 func_vt.t = VT_VOID; /* for safety */
9118 ind = 0; /* for safety */
9119 nocode_wanted = saved_nocode_wanted;
9122 static void gen_inline_functions(void)
9124 Sym *sym;
9125 CType *type;
9126 int *str, inline_generated;
9128 /* iterate while inline function are referenced */
9129 for(;;) {
9130 inline_generated = 0;
9131 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9132 type = &sym->type;
9133 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9134 (type->t & (VT_STATIC | VT_INLINE)) ==
9135 (VT_STATIC | VT_INLINE) &&
9136 sym->c != 0) {
9137 /* the function was used: generate its code and
9138 convert it to a normal function */
9139 str = (int *)sym->r;
9140 sym->r = VT_SYM | VT_CONST;
9141 type->t &= ~VT_INLINE;
9143 macro_ptr = str;
9144 next();
9145 cur_text_section = text_section;
9146 gen_function(sym);
9147 macro_ptr = NULL; /* fail safe */
9149 tok_str_free(str);
9150 inline_generated = 1;
9153 if (!inline_generated)
9154 break;
9157 /* free all remaining inline function tokens */
9158 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9159 type = &sym->type;
9160 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9161 (type->t & (VT_STATIC | VT_INLINE)) ==
9162 (VT_STATIC | VT_INLINE)) {
9163 str = (int *)sym->r;
9164 tok_str_free(str);
9165 sym->r = 0; /* fail safe */
9170 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9171 static void decl(int l)
9173 int v, has_init, r;
9174 CType type, btype;
9175 Sym *sym;
9176 AttributeDef ad;
9178 while (1) {
9179 if (!parse_btype(&btype, &ad)) {
9180 /* skip redundant ';' */
9181 /* XXX: find more elegant solution */
9182 if (tok == ';') {
9183 next();
9184 continue;
9186 if (l == VT_CONST &&
9187 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9188 /* global asm block */
9189 asm_global_instr();
9190 continue;
9192 /* special test for old K&R protos without explicit int
9193 type. Only accepted when defining global data */
9194 if (l == VT_LOCAL || tok < TOK_DEFINE)
9195 break;
9196 btype.t = VT_INT;
9198 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9199 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9200 tok == ';') {
9201 /* we accept no variable after */
9202 next();
9203 continue;
9205 while (1) { /* iterate thru each declaration */
9206 type = btype;
9207 type_decl(&type, &ad, &v, TYPE_DIRECT);
9208 #if 0
9210 char buf[500];
9211 type_to_str(buf, sizeof(buf), &type, get_tok_str(v, NULL));
9212 printf("type = '%s'\n", buf);
9214 #endif
9215 if ((type.t & VT_BTYPE) == VT_FUNC) {
9216 /* if old style function prototype, we accept a
9217 declaration list */
9218 sym = type.ref;
9219 if (sym->c == FUNC_OLD)
9220 func_decl_list(sym);
9223 if (tok == '{') {
9224 if (l == VT_LOCAL)
9225 error("cannot use local functions");
9226 if ((type.t & VT_BTYPE) != VT_FUNC)
9227 expect("function definition");
9229 /* reject abstract declarators in function definition */
9230 sym = type.ref;
9231 while ((sym = sym->next) != NULL)
9232 if (!(sym->v & ~SYM_FIELD))
9233 expect("identifier");
9235 /* XXX: cannot do better now: convert extern line to static inline */
9236 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9237 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9239 sym = sym_find(v);
9240 if (sym) {
9241 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9242 goto func_error1;
9243 /* specific case: if not func_call defined, we put
9244 the one of the prototype */
9245 /* XXX: should have default value */
9246 if (sym->type.ref->r != FUNC_CDECL &&
9247 type.ref->r == FUNC_CDECL)
9248 type.ref->r = sym->type.ref->r;
9249 if (!is_compatible_types(&sym->type, &type)) {
9250 func_error1:
9251 error("incompatible types for redefinition of '%s'",
9252 get_tok_str(v, NULL));
9254 /* if symbol is already defined, then put complete type */
9255 sym->type = type;
9256 } else {
9257 /* put function symbol */
9258 sym = global_identifier_push(v, type.t, 0);
9259 sym->type.ref = type.ref;
9262 /* static inline functions are just recorded as a kind
9263 of macro. Their code will be emitted at the end of
9264 the compilation unit only if they are used */
9265 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9266 (VT_INLINE | VT_STATIC)) {
9267 TokenString func_str;
9268 int block_level;
9270 tok_str_new(&func_str);
9272 block_level = 0;
9273 for(;;) {
9274 int t;
9275 if (tok == TOK_EOF)
9276 error("unexpected end of file");
9277 tok_str_add_tok(&func_str);
9278 t = tok;
9279 next();
9280 if (t == '{') {
9281 block_level++;
9282 } else if (t == '}') {
9283 block_level--;
9284 if (block_level == 0)
9285 break;
9288 tok_str_add(&func_str, -1);
9289 tok_str_add(&func_str, 0);
9290 sym->r = (int)func_str.str;
9291 } else {
9292 /* compute text section */
9293 cur_text_section = ad.section;
9294 if (!cur_text_section)
9295 cur_text_section = text_section;
9296 sym->r = VT_SYM | VT_CONST;
9297 gen_function(sym);
9298 #ifdef TCC_TARGET_PE
9299 if (ad.dllexport) {
9300 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
9302 #endif
9304 break;
9305 } else {
9306 if (btype.t & VT_TYPEDEF) {
9307 /* save typedefed type */
9308 /* XXX: test storage specifiers ? */
9309 sym = sym_push(v, &type, 0, 0);
9310 sym->type.t |= VT_TYPEDEF;
9311 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9312 /* external function definition */
9313 /* specific case for func_call attribute */
9314 if (ad.func_call)
9315 type.ref->r = ad.func_call;
9316 external_sym(v, &type, 0);
9317 } else {
9318 /* not lvalue if array */
9319 r = 0;
9320 if (!(type.t & VT_ARRAY))
9321 r |= lvalue_type(type.t);
9322 has_init = (tok == '=');
9323 if ((btype.t & VT_EXTERN) ||
9324 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9325 !has_init && l == VT_CONST && type.ref->c < 0)) {
9326 /* external variable */
9327 /* NOTE: as GCC, uninitialized global static
9328 arrays of null size are considered as
9329 extern */
9330 external_sym(v, &type, r);
9331 } else {
9332 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9333 if (type.t & VT_STATIC)
9334 r |= VT_CONST;
9335 else
9336 r |= l;
9337 if (has_init)
9338 next();
9339 decl_initializer_alloc(&type, &ad, r,
9340 has_init, v, l);
9343 if (tok != ',') {
9344 skip(';');
9345 break;
9347 next();
9353 /* better than nothing, but needs extension to handle '-E' option
9354 correctly too */
9355 static void preprocess_init(TCCState *s1)
9357 s1->include_stack_ptr = s1->include_stack;
9358 /* XXX: move that before to avoid having to initialize
9359 file->ifdef_stack_ptr ? */
9360 s1->ifdef_stack_ptr = s1->ifdef_stack;
9361 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9363 /* XXX: not ANSI compliant: bound checking says error */
9364 vtop = vstack - 1;
9365 s1->pack_stack[0] = 0;
9366 s1->pack_stack_ptr = s1->pack_stack;
9369 /* compile the C file opened in 'file'. Return non zero if errors. */
9370 static int tcc_compile(TCCState *s1)
9372 Sym *define_start;
9373 char buf[512];
9374 volatile int section_sym;
9376 #ifdef INC_DEBUG
9377 printf("%s: **** new file\n", file->filename);
9378 #endif
9379 preprocess_init(s1);
9381 funcname = "";
9382 anon_sym = SYM_FIRST_ANOM;
9384 /* file info: full path + filename */
9385 section_sym = 0; /* avoid warning */
9386 if (do_debug) {
9387 section_sym = put_elf_sym(symtab_section, 0, 0,
9388 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9389 text_section->sh_num, NULL);
9390 getcwd(buf, sizeof(buf));
9391 pstrcat(buf, sizeof(buf), "/");
9392 put_stabs_r(buf, N_SO, 0, 0,
9393 text_section->data_offset, text_section, section_sym);
9394 put_stabs_r(file->filename, N_SO, 0, 0,
9395 text_section->data_offset, text_section, section_sym);
9397 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9398 symbols can be safely used */
9399 put_elf_sym(symtab_section, 0, 0,
9400 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9401 SHN_ABS, file->filename);
9403 /* define some often used types */
9404 int_type.t = VT_INT;
9406 char_pointer_type.t = VT_BYTE;
9407 mk_pointer(&char_pointer_type);
9409 func_old_type.t = VT_FUNC;
9410 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9412 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9413 float_type.t = VT_FLOAT;
9414 double_type.t = VT_DOUBLE;
9416 func_float_type.t = VT_FUNC;
9417 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9418 func_double_type.t = VT_FUNC;
9419 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9420 #endif
9422 #if 0
9423 /* define 'void *alloca(unsigned int)' builtin function */
9425 Sym *s1;
9427 p = anon_sym++;
9428 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9429 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9430 s1->next = NULL;
9431 sym->next = s1;
9432 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9434 #endif
9436 define_start = define_stack;
9437 nocode_wanted = 1;
9439 if (setjmp(s1->error_jmp_buf) == 0) {
9440 s1->nb_errors = 0;
9441 s1->error_set_jmp_enabled = 1;
9443 ch = file->buf_ptr[0];
9444 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9445 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9446 next();
9447 decl(VT_CONST);
9448 if (tok != TOK_EOF)
9449 expect("declaration");
9451 /* end of translation unit info */
9452 if (do_debug) {
9453 put_stabs_r(NULL, N_SO, 0, 0,
9454 text_section->data_offset, text_section, section_sym);
9457 s1->error_set_jmp_enabled = 0;
9459 /* reset define stack, but leave -Dsymbols (may be incorrect if
9460 they are undefined) */
9461 free_defines(define_start);
9463 gen_inline_functions();
9465 sym_pop(&global_stack, NULL);
9467 return s1->nb_errors != 0 ? -1 : 0;
9470 /* Preprocess the current file */
9471 /* XXX: add line and file infos, add options to preserve spaces */
9472 static int tcc_preprocess(TCCState *s1)
9474 Sym *define_start;
9475 int last_is_space;
9477 preprocess_init(s1);
9479 define_start = define_stack;
9481 ch = file->buf_ptr[0];
9482 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9483 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9484 PARSE_FLAG_LINEFEED;
9485 last_is_space = 1;
9486 next();
9487 for(;;) {
9488 if (tok == TOK_EOF) {
9489 break;
9490 } else if (tok == TOK_LINEFEED) {
9491 last_is_space = 1;
9492 } else {
9493 if (!last_is_space)
9494 fputc(' ', s1->outfile);
9495 last_is_space = 0;
9497 fputs(get_tok_str(tok, &tokc), s1->outfile);
9498 next();
9500 free_defines(define_start);
9501 return 0;
9504 #ifdef LIBTCC
9505 int tcc_compile_string(TCCState *s, const char *str)
9507 BufferedFile bf1, *bf = &bf1;
9508 int ret, len;
9509 char *buf;
9511 /* init file structure */
9512 bf->fd = -1;
9513 /* XXX: avoid copying */
9514 len = strlen(str);
9515 buf = tcc_malloc(len + 1);
9516 if (!buf)
9517 return -1;
9518 memcpy(buf, str, len);
9519 buf[len] = CH_EOB;
9520 bf->buf_ptr = buf;
9521 bf->buf_end = buf + len;
9522 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9523 bf->line_num = 1;
9524 file = bf;
9526 ret = tcc_compile(s);
9528 tcc_free(buf);
9530 /* currently, no need to close */
9531 return ret;
9533 #endif
9535 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9536 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9538 BufferedFile bf1, *bf = &bf1;
9540 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9541 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9542 /* default value */
9543 if (!value)
9544 value = "1";
9545 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9547 /* init file structure */
9548 bf->fd = -1;
9549 bf->buf_ptr = bf->buffer;
9550 bf->buf_end = bf->buffer + strlen(bf->buffer);
9551 *bf->buf_end = CH_EOB;
9552 bf->filename[0] = '\0';
9553 bf->line_num = 1;
9554 file = bf;
9556 s1->include_stack_ptr = s1->include_stack;
9558 /* parse with define parser */
9559 ch = file->buf_ptr[0];
9560 next_nomacro();
9561 parse_define();
9562 file = NULL;
9565 /* undefine a preprocessor symbol */
9566 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9568 TokenSym *ts;
9569 Sym *s;
9570 ts = tok_alloc(sym, strlen(sym));
9571 s = define_find(ts->tok);
9572 /* undefine symbol by putting an invalid name */
9573 if (s)
9574 define_undef(s);
9577 #ifdef CONFIG_TCC_ASM
9579 #ifdef TCC_TARGET_I386
9580 #include "i386-asm.c"
9581 #endif
9582 #include "tccasm.c"
9584 #else
9585 static void asm_instr(void)
9587 error("inline asm() not supported");
9589 static void asm_global_instr(void)
9591 error("inline asm() not supported");
9593 #endif
9595 #include "tccelf.c"
9597 #ifdef TCC_TARGET_COFF
9598 #include "tcccoff.c"
9599 #endif
9601 #ifdef TCC_TARGET_PE
9602 #include "tccpe.c"
9603 #endif
9605 /* print the position in the source file of PC value 'pc' by reading
9606 the stabs debug information */
9607 static void rt_printline(unsigned long wanted_pc)
9609 Stab_Sym *sym, *sym_end;
9610 char func_name[128], last_func_name[128];
9611 unsigned long func_addr, last_pc, pc;
9612 const char *incl_files[INCLUDE_STACK_SIZE];
9613 int incl_index, len, last_line_num, i;
9614 const char *str, *p;
9616 fprintf(stderr, "0x%08lx:", wanted_pc);
9618 func_name[0] = '\0';
9619 func_addr = 0;
9620 incl_index = 0;
9621 last_func_name[0] = '\0';
9622 last_pc = 0xffffffff;
9623 last_line_num = 1;
9624 sym = (Stab_Sym *)stab_section->data + 1;
9625 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9626 while (sym < sym_end) {
9627 switch(sym->n_type) {
9628 /* function start or end */
9629 case N_FUN:
9630 if (sym->n_strx == 0) {
9631 /* we test if between last line and end of function */
9632 pc = sym->n_value + func_addr;
9633 if (wanted_pc >= last_pc && wanted_pc < pc)
9634 goto found;
9635 func_name[0] = '\0';
9636 func_addr = 0;
9637 } else {
9638 str = stabstr_section->data + sym->n_strx;
9639 p = strchr(str, ':');
9640 if (!p) {
9641 pstrcpy(func_name, sizeof(func_name), str);
9642 } else {
9643 len = p - str;
9644 if (len > sizeof(func_name) - 1)
9645 len = sizeof(func_name) - 1;
9646 memcpy(func_name, str, len);
9647 func_name[len] = '\0';
9649 func_addr = sym->n_value;
9651 break;
9652 /* line number info */
9653 case N_SLINE:
9654 pc = sym->n_value + func_addr;
9655 if (wanted_pc >= last_pc && wanted_pc < pc)
9656 goto found;
9657 last_pc = pc;
9658 last_line_num = sym->n_desc;
9659 /* XXX: slow! */
9660 strcpy(last_func_name, func_name);
9661 break;
9662 /* include files */
9663 case N_BINCL:
9664 str = stabstr_section->data + sym->n_strx;
9665 add_incl:
9666 if (incl_index < INCLUDE_STACK_SIZE) {
9667 incl_files[incl_index++] = str;
9669 break;
9670 case N_EINCL:
9671 if (incl_index > 1)
9672 incl_index--;
9673 break;
9674 case N_SO:
9675 if (sym->n_strx == 0) {
9676 incl_index = 0; /* end of translation unit */
9677 } else {
9678 str = stabstr_section->data + sym->n_strx;
9679 /* do not add path */
9680 len = strlen(str);
9681 if (len > 0 && str[len - 1] != '/')
9682 goto add_incl;
9684 break;
9686 sym++;
9689 /* second pass: we try symtab symbols (no line number info) */
9690 incl_index = 0;
9692 Elf32_Sym *sym, *sym_end;
9693 int type;
9695 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9696 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9697 sym < sym_end;
9698 sym++) {
9699 type = ELF32_ST_TYPE(sym->st_info);
9700 if (type == STT_FUNC) {
9701 if (wanted_pc >= sym->st_value &&
9702 wanted_pc < sym->st_value + sym->st_size) {
9703 pstrcpy(last_func_name, sizeof(last_func_name),
9704 strtab_section->data + sym->st_name);
9705 goto found;
9710 /* did not find any info: */
9711 fprintf(stderr, " ???\n");
9712 return;
9713 found:
9714 if (last_func_name[0] != '\0') {
9715 fprintf(stderr, " %s()", last_func_name);
9717 if (incl_index > 0) {
9718 fprintf(stderr, " (%s:%d",
9719 incl_files[incl_index - 1], last_line_num);
9720 for(i = incl_index - 2; i >= 0; i--)
9721 fprintf(stderr, ", included from %s", incl_files[i]);
9722 fprintf(stderr, ")");
9724 fprintf(stderr, "\n");
9727 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9729 #ifdef __i386__
9731 /* fix for glibc 2.1 */
9732 #ifndef REG_EIP
9733 #define REG_EIP EIP
9734 #define REG_EBP EBP
9735 #endif
9737 /* return the PC at frame level 'level'. Return non zero if not found */
9738 static int rt_get_caller_pc(unsigned long *paddr,
9739 ucontext_t *uc, int level)
9741 unsigned long fp;
9742 int i;
9744 if (level == 0) {
9745 #if defined(__FreeBSD__)
9746 *paddr = uc->uc_mcontext.mc_eip;
9747 #elif defined(__dietlibc__)
9748 *paddr = uc->uc_mcontext.eip;
9749 #else
9750 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9751 #endif
9752 return 0;
9753 } else {
9754 #if defined(__FreeBSD__)
9755 fp = uc->uc_mcontext.mc_ebp;
9756 #elif defined(__dietlibc__)
9757 fp = uc->uc_mcontext.ebp;
9758 #else
9759 fp = uc->uc_mcontext.gregs[REG_EBP];
9760 #endif
9761 for(i=1;i<level;i++) {
9762 /* XXX: check address validity with program info */
9763 if (fp <= 0x1000 || fp >= 0xc0000000)
9764 return -1;
9765 fp = ((unsigned long *)fp)[0];
9767 *paddr = ((unsigned long *)fp)[1];
9768 return 0;
9771 #else
9773 #warning add arch specific rt_get_caller_pc()
9775 static int rt_get_caller_pc(unsigned long *paddr,
9776 ucontext_t *uc, int level)
9778 return -1;
9780 #endif
9782 /* emit a run time error at position 'pc' */
9783 void rt_error(ucontext_t *uc, const char *fmt, ...)
9785 va_list ap;
9786 unsigned long pc;
9787 int i;
9789 va_start(ap, fmt);
9790 fprintf(stderr, "Runtime error: ");
9791 vfprintf(stderr, fmt, ap);
9792 fprintf(stderr, "\n");
9793 for(i=0;i<num_callers;i++) {
9794 if (rt_get_caller_pc(&pc, uc, i) < 0)
9795 break;
9796 if (i == 0)
9797 fprintf(stderr, "at ");
9798 else
9799 fprintf(stderr, "by ");
9800 rt_printline(pc);
9802 exit(255);
9803 va_end(ap);
9806 /* signal handler for fatal errors */
9807 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9809 ucontext_t *uc = puc;
9811 switch(signum) {
9812 case SIGFPE:
9813 switch(siginf->si_code) {
9814 case FPE_INTDIV:
9815 case FPE_FLTDIV:
9816 rt_error(uc, "division by zero");
9817 break;
9818 default:
9819 rt_error(uc, "floating point exception");
9820 break;
9822 break;
9823 case SIGBUS:
9824 case SIGSEGV:
9825 if (rt_bound_error_msg && *rt_bound_error_msg)
9826 rt_error(uc, *rt_bound_error_msg);
9827 else
9828 rt_error(uc, "dereferencing invalid pointer");
9829 break;
9830 case SIGILL:
9831 rt_error(uc, "illegal instruction");
9832 break;
9833 case SIGABRT:
9834 rt_error(uc, "abort() called");
9835 break;
9836 default:
9837 rt_error(uc, "caught signal %d", signum);
9838 break;
9840 exit(255);
9842 #endif
9844 /* do all relocations (needed before using tcc_get_symbol()) */
9845 int tcc_relocate(TCCState *s1)
9847 Section *s;
9848 int i;
9850 s1->nb_errors = 0;
9852 #ifdef TCC_TARGET_PE
9853 pe_add_runtime(s1);
9854 #else
9855 tcc_add_runtime(s1);
9856 #endif
9858 relocate_common_syms();
9860 tcc_add_linker_symbols(s1);
9862 build_got_entries(s1);
9864 /* compute relocation address : section are relocated in place. We
9865 also alloc the bss space */
9866 for(i = 1; i < s1->nb_sections; i++) {
9867 s = s1->sections[i];
9868 if (s->sh_flags & SHF_ALLOC) {
9869 if (s->sh_type == SHT_NOBITS)
9870 s->data = tcc_mallocz(s->data_offset);
9871 s->sh_addr = (unsigned long)s->data;
9875 relocate_syms(s1, 1);
9877 if (s1->nb_errors != 0)
9878 return -1;
9880 /* relocate each section */
9881 for(i = 1; i < s1->nb_sections; i++) {
9882 s = s1->sections[i];
9883 if (s->reloc)
9884 relocate_section(s1, s);
9887 /* mark executable sections as executable in memory */
9888 for(i = 1; i < s1->nb_sections; i++) {
9889 s = s1->sections[i];
9890 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
9891 (SHF_ALLOC | SHF_EXECINSTR)) {
9892 #ifdef WIN32
9894 unsigned long old_protect;
9895 VirtualProtect(s->data, s->data_offset,
9896 PAGE_EXECUTE_READWRITE, &old_protect);
9898 #else
9900 unsigned long start, end;
9901 start = (unsigned long)(s->data) & ~(PAGESIZE - 1);
9902 end = (unsigned long)(s->data + s->data_offset);
9903 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
9904 mprotect((void *)start, end - start,
9905 PROT_READ | PROT_WRITE | PROT_EXEC);
9907 #endif
9910 return 0;
9913 /* launch the compiled program with the given arguments */
9914 int tcc_run(TCCState *s1, int argc, char **argv)
9916 int (*prog_main)(int, char **);
9918 if (tcc_relocate(s1) < 0)
9919 return -1;
9921 prog_main = tcc_get_symbol_err(s1, "main");
9923 if (do_debug) {
9924 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9925 error("debug mode currently not available for Windows");
9926 #else
9927 struct sigaction sigact;
9928 /* install TCC signal handlers to print debug info on fatal
9929 runtime errors */
9930 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9931 sigact.sa_sigaction = sig_error;
9932 sigemptyset(&sigact.sa_mask);
9933 sigaction(SIGFPE, &sigact, NULL);
9934 sigaction(SIGILL, &sigact, NULL);
9935 sigaction(SIGSEGV, &sigact, NULL);
9936 sigaction(SIGBUS, &sigact, NULL);
9937 sigaction(SIGABRT, &sigact, NULL);
9938 #endif
9941 #ifdef CONFIG_TCC_BCHECK
9942 if (do_bounds_check) {
9943 void (*bound_init)(void);
9945 /* set error function */
9946 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9947 "__bound_error_msg");
9949 /* XXX: use .init section so that it also work in binary ? */
9950 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9951 bound_init();
9953 #endif
9954 return (*prog_main)(argc, argv);
9957 TCCState *tcc_new(void)
9959 const char *p, *r;
9960 TCCState *s;
9961 TokenSym *ts;
9962 int i, c;
9964 s = tcc_mallocz(sizeof(TCCState));
9965 if (!s)
9966 return NULL;
9967 tcc_state = s;
9968 s->output_type = TCC_OUTPUT_MEMORY;
9970 /* init isid table */
9971 for(i=0;i<256;i++)
9972 isidnum_table[i] = isid(i) || isnum(i);
9974 /* add all tokens */
9975 table_ident = NULL;
9976 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9978 tok_ident = TOK_IDENT;
9979 p = tcc_keywords;
9980 while (*p) {
9981 r = p;
9982 for(;;) {
9983 c = *r++;
9984 if (c == '\0')
9985 break;
9987 ts = tok_alloc(p, r - p - 1);
9988 p = r;
9991 /* we add dummy defines for some special macros to speed up tests
9992 and to have working defined() */
9993 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9994 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9995 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9996 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9998 /* standard defines */
9999 tcc_define_symbol(s, "__STDC__", NULL);
10000 #if defined(TCC_TARGET_I386)
10001 tcc_define_symbol(s, "__i386__", NULL);
10002 #endif
10003 #if defined(TCC_TARGET_ARM)
10004 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10005 tcc_define_symbol(s, "__arm_elf__", NULL);
10006 tcc_define_symbol(s, "__arm_elf", NULL);
10007 tcc_define_symbol(s, "arm_elf", NULL);
10008 tcc_define_symbol(s, "__arm__", NULL);
10009 tcc_define_symbol(s, "__arm", NULL);
10010 tcc_define_symbol(s, "arm", NULL);
10011 tcc_define_symbol(s, "__APCS_32__", NULL);
10012 #endif
10013 #if defined(linux)
10014 tcc_define_symbol(s, "__linux__", NULL);
10015 tcc_define_symbol(s, "linux", NULL);
10016 #endif
10017 /* tiny C specific defines */
10018 tcc_define_symbol(s, "__TINYC__", NULL);
10020 /* tiny C & gcc defines */
10021 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10022 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10023 #ifdef TCC_TARGET_PE
10024 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10025 #else
10026 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10027 #endif
10029 /* default library paths */
10030 #ifdef TCC_TARGET_PE
10032 char buf[1024];
10033 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10034 tcc_add_library_path(s, buf);
10036 #else
10037 tcc_add_library_path(s, "/usr/local/lib");
10038 tcc_add_library_path(s, "/usr/lib");
10039 tcc_add_library_path(s, "/lib");
10040 #endif
10042 /* no section zero */
10043 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10045 /* create standard sections */
10046 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10047 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10048 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10050 /* symbols are always generated for linking stage */
10051 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10052 ".strtab",
10053 ".hashtab", SHF_PRIVATE);
10054 strtab_section = symtab_section->link;
10056 /* private symbol table for dynamic symbols */
10057 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10058 ".dynstrtab",
10059 ".dynhashtab", SHF_PRIVATE);
10060 s->alacarte_link = 1;
10062 #ifdef CHAR_IS_UNSIGNED
10063 s->char_is_unsigned = 1;
10064 #endif
10065 #if defined(TCC_TARGET_PE) && 0
10066 /* XXX: currently the PE linker is not ready to support that */
10067 s->leading_underscore = 1;
10068 #endif
10069 return s;
10072 void tcc_delete(TCCState *s1)
10074 int i, n;
10076 /* free -D defines */
10077 free_defines(NULL);
10079 /* free tokens */
10080 n = tok_ident - TOK_IDENT;
10081 for(i = 0; i < n; i++)
10082 tcc_free(table_ident[i]);
10083 tcc_free(table_ident);
10085 /* free all sections */
10087 free_section(symtab_section->hash);
10089 free_section(s1->dynsymtab_section->hash);
10090 free_section(s1->dynsymtab_section->link);
10091 free_section(s1->dynsymtab_section);
10093 for(i = 1; i < s1->nb_sections; i++)
10094 free_section(s1->sections[i]);
10095 tcc_free(s1->sections);
10097 /* free loaded dlls array */
10098 for(i = 0; i < s1->nb_loaded_dlls; i++)
10099 tcc_free(s1->loaded_dlls[i]);
10100 tcc_free(s1->loaded_dlls);
10102 /* library paths */
10103 for(i = 0; i < s1->nb_library_paths; i++)
10104 tcc_free(s1->library_paths[i]);
10105 tcc_free(s1->library_paths);
10107 /* cached includes */
10108 for(i = 0; i < s1->nb_cached_includes; i++)
10109 tcc_free(s1->cached_includes[i]);
10110 tcc_free(s1->cached_includes);
10112 for(i = 0; i < s1->nb_include_paths; i++)
10113 tcc_free(s1->include_paths[i]);
10114 tcc_free(s1->include_paths);
10116 for(i = 0; i < s1->nb_sysinclude_paths; i++)
10117 tcc_free(s1->sysinclude_paths[i]);
10118 tcc_free(s1->sysinclude_paths);
10120 tcc_free(s1);
10123 int tcc_add_include_path(TCCState *s1, const char *pathname)
10125 char *pathname1;
10127 pathname1 = tcc_strdup(pathname);
10128 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10129 return 0;
10132 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10134 char *pathname1;
10136 pathname1 = tcc_strdup(pathname);
10137 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10138 return 0;
10141 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10143 const char *ext, *filename1;
10144 Elf32_Ehdr ehdr;
10145 int fd, ret;
10146 BufferedFile *saved_file;
10148 /* find source file type with extension */
10149 filename1 = strrchr(filename, '/');
10150 if (filename1)
10151 filename1++;
10152 else
10153 filename1 = filename;
10154 ext = strrchr(filename1, '.');
10155 if (ext)
10156 ext++;
10158 /* open the file */
10159 saved_file = file;
10160 file = tcc_open(s1, filename);
10161 if (!file) {
10162 if (flags & AFF_PRINT_ERROR) {
10163 error_noabort("file '%s' not found", filename);
10165 ret = -1;
10166 goto fail1;
10169 if (flags & AFF_PREPROCESS) {
10170 ret = tcc_preprocess(s1);
10171 } else if (!ext || !strcmp(ext, "c")) {
10172 /* C file assumed */
10173 ret = tcc_compile(s1);
10174 } else
10175 #ifdef CONFIG_TCC_ASM
10176 if (!strcmp(ext, "S")) {
10177 /* preprocessed assembler */
10178 ret = tcc_assemble(s1, 1);
10179 } else if (!strcmp(ext, "s")) {
10180 /* non preprocessed assembler */
10181 ret = tcc_assemble(s1, 0);
10182 } else
10183 #endif
10184 #ifdef TCC_TARGET_PE
10185 if (!strcmp(ext, "def")) {
10186 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
10187 } else
10188 #endif
10190 fd = file->fd;
10191 /* assume executable format: auto guess file type */
10192 ret = read(fd, &ehdr, sizeof(ehdr));
10193 lseek(fd, 0, SEEK_SET);
10194 if (ret <= 0) {
10195 error_noabort("could not read header");
10196 goto fail;
10197 } else if (ret != sizeof(ehdr)) {
10198 goto try_load_script;
10201 if (ehdr.e_ident[0] == ELFMAG0 &&
10202 ehdr.e_ident[1] == ELFMAG1 &&
10203 ehdr.e_ident[2] == ELFMAG2 &&
10204 ehdr.e_ident[3] == ELFMAG3) {
10205 file->line_num = 0; /* do not display line number if error */
10206 if (ehdr.e_type == ET_REL) {
10207 ret = tcc_load_object_file(s1, fd, 0);
10208 } else if (ehdr.e_type == ET_DYN) {
10209 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10210 #ifdef TCC_TARGET_PE
10211 ret = -1;
10212 #else
10213 void *h;
10214 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10215 if (h)
10216 ret = 0;
10217 else
10218 ret = -1;
10219 #endif
10220 } else {
10221 ret = tcc_load_dll(s1, fd, filename,
10222 (flags & AFF_REFERENCED_DLL) != 0);
10224 } else {
10225 error_noabort("unrecognized ELF file");
10226 goto fail;
10228 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10229 file->line_num = 0; /* do not display line number if error */
10230 ret = tcc_load_archive(s1, fd);
10231 } else
10232 #ifdef TCC_TARGET_COFF
10233 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10234 ret = tcc_load_coff(s1, fd);
10235 } else
10236 #endif
10238 /* as GNU ld, consider it is an ld script if not recognized */
10239 try_load_script:
10240 ret = tcc_load_ldscript(s1);
10241 if (ret < 0) {
10242 error_noabort("unrecognized file type");
10243 goto fail;
10247 the_end:
10248 tcc_close(file);
10249 fail1:
10250 file = saved_file;
10251 return ret;
10252 fail:
10253 ret = -1;
10254 goto the_end;
10257 int tcc_add_file(TCCState *s, const char *filename)
10259 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10262 int tcc_add_library_path(TCCState *s, const char *pathname)
10264 char *pathname1;
10266 pathname1 = tcc_strdup(pathname);
10267 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10268 return 0;
10271 /* find and load a dll. Return non zero if not found */
10272 /* XXX: add '-rpath' option support ? */
10273 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10275 char buf[1024];
10276 int i;
10278 for(i = 0; i < s->nb_library_paths; i++) {
10279 snprintf(buf, sizeof(buf), "%s/%s",
10280 s->library_paths[i], filename);
10281 if (tcc_add_file_internal(s, buf, flags) == 0)
10282 return 0;
10284 return -1;
10287 /* the library name is the same as the argument of the '-l' option */
10288 int tcc_add_library(TCCState *s, const char *libraryname)
10290 char buf[1024];
10291 int i;
10293 /* first we look for the dynamic library if not static linking */
10294 if (!s->static_link) {
10295 #ifdef TCC_TARGET_PE
10296 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10297 #else
10298 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10299 #endif
10300 if (tcc_add_dll(s, buf, 0) == 0)
10301 return 0;
10304 /* then we look for the static library */
10305 for(i = 0; i < s->nb_library_paths; i++) {
10306 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10307 s->library_paths[i], libraryname);
10308 if (tcc_add_file_internal(s, buf, 0) == 0)
10309 return 0;
10311 return -1;
10314 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10316 add_elf_sym(symtab_section, val, 0,
10317 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10318 SHN_ABS, name);
10319 return 0;
10322 int tcc_set_output_type(TCCState *s, int output_type)
10324 s->output_type = output_type;
10326 if (!s->nostdinc) {
10327 char buf[1024];
10329 /* default include paths */
10330 /* XXX: reverse order needed if -isystem support */
10331 #ifndef TCC_TARGET_PE
10332 tcc_add_sysinclude_path(s, "/usr/local/include");
10333 tcc_add_sysinclude_path(s, "/usr/include");
10334 #endif
10335 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10336 tcc_add_sysinclude_path(s, buf);
10337 #ifdef TCC_TARGET_PE
10338 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10339 tcc_add_sysinclude_path(s, buf);
10340 #endif
10343 /* if bound checking, then add corresponding sections */
10344 #ifdef CONFIG_TCC_BCHECK
10345 if (do_bounds_check) {
10346 /* define symbol */
10347 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10348 /* create bounds sections */
10349 bounds_section = new_section(s, ".bounds",
10350 SHT_PROGBITS, SHF_ALLOC);
10351 lbounds_section = new_section(s, ".lbounds",
10352 SHT_PROGBITS, SHF_ALLOC);
10354 #endif
10356 if (s->char_is_unsigned) {
10357 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10360 /* add debug sections */
10361 if (do_debug) {
10362 /* stab symbols */
10363 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10364 stab_section->sh_entsize = sizeof(Stab_Sym);
10365 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10366 put_elf_str(stabstr_section, "");
10367 stab_section->link = stabstr_section;
10368 /* put first entry */
10369 put_stabs("", 0, 0, 0, 0);
10372 /* add libc crt1/crti objects */
10373 #ifndef TCC_TARGET_PE
10374 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10375 !s->nostdlib) {
10376 if (output_type != TCC_OUTPUT_DLL)
10377 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10378 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10380 #endif
10381 return 0;
10384 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10385 #define FD_INVERT 0x0002 /* invert value before storing */
10387 typedef struct FlagDef {
10388 uint16_t offset;
10389 uint16_t flags;
10390 const char *name;
10391 } FlagDef;
10393 static const FlagDef warning_defs[] = {
10394 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10395 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10396 { offsetof(TCCState, warn_error), 0, "error" },
10397 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10398 "implicit-function-declaration" },
10401 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10402 const char *name, int value)
10404 int i;
10405 const FlagDef *p;
10406 const char *r;
10408 r = name;
10409 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10410 r += 3;
10411 value = !value;
10413 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10414 if (!strcmp(r, p->name))
10415 goto found;
10417 return -1;
10418 found:
10419 if (p->flags & FD_INVERT)
10420 value = !value;
10421 *(int *)((uint8_t *)s + p->offset) = value;
10422 return 0;
10426 /* set/reset a warning */
10427 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10429 int i;
10430 const FlagDef *p;
10432 if (!strcmp(warning_name, "all")) {
10433 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10434 if (p->flags & WD_ALL)
10435 *(int *)((uint8_t *)s + p->offset) = 1;
10437 return 0;
10438 } else {
10439 return set_flag(s, warning_defs, countof(warning_defs),
10440 warning_name, value);
10444 static const FlagDef flag_defs[] = {
10445 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10446 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10447 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10448 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10451 /* set/reset a flag */
10452 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10454 return set_flag(s, flag_defs, countof(flag_defs),
10455 flag_name, value);
10458 /* extract the basename of a file */
10459 static char *tcc_basename(const char *name)
10461 char *p = strchr(name, 0);
10462 while (p > name
10463 && p[-1] != '/'
10464 #ifdef WIN32
10465 && p[-1] != '\\'
10466 #endif
10468 --p;
10469 return p;
10472 #if !defined(LIBTCC)
10474 static int64_t getclock_us(void)
10476 #ifdef WIN32
10477 struct _timeb tb;
10478 _ftime(&tb);
10479 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10480 #else
10481 struct timeval tv;
10482 gettimeofday(&tv, NULL);
10483 return tv.tv_sec * 1000000LL + tv.tv_usec;
10484 #endif
10487 void help(void)
10489 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10490 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10491 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10492 " [infile1 infile2...] [-run infile args...]\n"
10493 "\n"
10494 "General options:\n"
10495 " -v display current version\n"
10496 " -c compile only - generate an object file\n"
10497 " -o outfile set output filename\n"
10498 " -Bdir set tcc internal library path\n"
10499 " -bench output compilation statistics\n"
10500 " -run run compiled source\n"
10501 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10502 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10503 " -w disable all warnings\n"
10504 "Preprocessor options:\n"
10505 " -E preprocess only\n"
10506 " -Idir add include path 'dir'\n"
10507 " -Dsym[=val] define 'sym' with value 'val'\n"
10508 " -Usym undefine 'sym'\n"
10509 "Linker options:\n"
10510 " -Ldir add library path 'dir'\n"
10511 " -llib link with dynamic or static library 'lib'\n"
10512 " -shared generate a shared library\n"
10513 " -static static linking\n"
10514 " -rdynamic export all global symbols to dynamic linker\n"
10515 " -r relocatable output\n"
10516 "Debugger options:\n"
10517 " -g generate runtime debug info\n"
10518 #ifdef CONFIG_TCC_BCHECK
10519 " -b compile with built-in memory and bounds checker (implies -g)\n"
10520 #endif
10521 " -bt N show N callers in stack traces\n"
10525 #define TCC_OPTION_HAS_ARG 0x0001
10526 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10528 typedef struct TCCOption {
10529 const char *name;
10530 uint16_t index;
10531 uint16_t flags;
10532 } TCCOption;
10534 enum {
10535 TCC_OPTION_HELP,
10536 TCC_OPTION_I,
10537 TCC_OPTION_D,
10538 TCC_OPTION_U,
10539 TCC_OPTION_L,
10540 TCC_OPTION_B,
10541 TCC_OPTION_l,
10542 TCC_OPTION_bench,
10543 TCC_OPTION_bt,
10544 TCC_OPTION_b,
10545 TCC_OPTION_g,
10546 TCC_OPTION_c,
10547 TCC_OPTION_static,
10548 TCC_OPTION_shared,
10549 TCC_OPTION_o,
10550 TCC_OPTION_r,
10551 TCC_OPTION_Wl,
10552 TCC_OPTION_W,
10553 TCC_OPTION_O,
10554 TCC_OPTION_m,
10555 TCC_OPTION_f,
10556 TCC_OPTION_nostdinc,
10557 TCC_OPTION_nostdlib,
10558 TCC_OPTION_print_search_dirs,
10559 TCC_OPTION_rdynamic,
10560 TCC_OPTION_run,
10561 TCC_OPTION_v,
10562 TCC_OPTION_w,
10563 TCC_OPTION_pipe,
10564 TCC_OPTION_E,
10567 static const TCCOption tcc_options[] = {
10568 { "h", TCC_OPTION_HELP, 0 },
10569 { "?", TCC_OPTION_HELP, 0 },
10570 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10571 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10572 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10573 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10574 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10575 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10576 { "bench", TCC_OPTION_bench, 0 },
10577 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10578 #ifdef CONFIG_TCC_BCHECK
10579 { "b", TCC_OPTION_b, 0 },
10580 #endif
10581 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10582 { "c", TCC_OPTION_c, 0 },
10583 { "static", TCC_OPTION_static, 0 },
10584 { "shared", TCC_OPTION_shared, 0 },
10585 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10586 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10587 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10588 { "r", TCC_OPTION_r, 0 },
10589 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10590 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10591 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10592 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10593 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10594 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10595 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10596 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10597 { "v", TCC_OPTION_v, 0 },
10598 { "w", TCC_OPTION_w, 0 },
10599 { "pipe", TCC_OPTION_pipe, 0},
10600 { "E", TCC_OPTION_E, 0},
10601 { NULL },
10604 /* convert 'str' into an array of space separated strings */
10605 static int expand_args(char ***pargv, const char *str)
10607 const char *s1;
10608 char **argv, *arg;
10609 int argc, len;
10611 argc = 0;
10612 argv = NULL;
10613 for(;;) {
10614 while (is_space(*str))
10615 str++;
10616 if (*str == '\0')
10617 break;
10618 s1 = str;
10619 while (*str != '\0' && !is_space(*str))
10620 str++;
10621 len = str - s1;
10622 arg = tcc_malloc(len + 1);
10623 memcpy(arg, s1, len);
10624 arg[len] = '\0';
10625 dynarray_add((void ***)&argv, &argc, arg);
10627 *pargv = argv;
10628 return argc;
10631 static char **files;
10632 static int nb_files, nb_libraries;
10633 static int multiple_files;
10634 static int print_search_dirs;
10635 static int output_type;
10636 static int reloc_output;
10637 static const char *outfile;
10639 int parse_args(TCCState *s, int argc, char **argv)
10641 int optind;
10642 const TCCOption *popt;
10643 const char *optarg, *p1, *r1;
10644 char *r;
10646 optind = 0;
10647 while (1) {
10648 if (optind >= argc) {
10649 if (nb_files == 0 && !print_search_dirs)
10650 goto show_help;
10651 else
10652 break;
10654 r = argv[optind++];
10655 if (r[0] != '-') {
10656 /* add a new file */
10657 dynarray_add((void ***)&files, &nb_files, r);
10658 if (!multiple_files) {
10659 optind--;
10660 /* argv[0] will be this file */
10661 break;
10663 } else {
10664 /* find option in table (match only the first chars */
10665 popt = tcc_options;
10666 for(;;) {
10667 p1 = popt->name;
10668 if (p1 == NULL)
10669 error("invalid option -- '%s'", r);
10670 r1 = r + 1;
10671 for(;;) {
10672 if (*p1 == '\0')
10673 goto option_found;
10674 if (*r1 != *p1)
10675 break;
10676 p1++;
10677 r1++;
10679 popt++;
10681 option_found:
10682 if (popt->flags & TCC_OPTION_HAS_ARG) {
10683 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10684 optarg = r1;
10685 } else {
10686 if (optind >= argc)
10687 error("argument to '%s' is missing", r);
10688 optarg = argv[optind++];
10690 } else {
10691 if (*r1 != '\0')
10692 goto show_help;
10693 optarg = NULL;
10696 switch(popt->index) {
10697 case TCC_OPTION_HELP:
10698 show_help:
10699 help();
10700 exit(1);
10701 case TCC_OPTION_I:
10702 if (tcc_add_include_path(s, optarg) < 0)
10703 error("too many include paths");
10704 break;
10705 case TCC_OPTION_D:
10707 char *sym, *value;
10708 sym = (char *)optarg;
10709 value = strchr(sym, '=');
10710 if (value) {
10711 *value = '\0';
10712 value++;
10714 tcc_define_symbol(s, sym, value);
10716 break;
10717 case TCC_OPTION_U:
10718 tcc_undefine_symbol(s, optarg);
10719 break;
10720 case TCC_OPTION_L:
10721 tcc_add_library_path(s, optarg);
10722 break;
10723 case TCC_OPTION_B:
10724 /* set tcc utilities path (mainly for tcc development) */
10725 tcc_lib_path = optarg;
10726 break;
10727 case TCC_OPTION_l:
10728 dynarray_add((void ***)&files, &nb_files, r);
10729 nb_libraries++;
10730 break;
10731 case TCC_OPTION_bench:
10732 do_bench = 1;
10733 break;
10734 case TCC_OPTION_bt:
10735 num_callers = atoi(optarg);
10736 break;
10737 #ifdef CONFIG_TCC_BCHECK
10738 case TCC_OPTION_b:
10739 do_bounds_check = 1;
10740 do_debug = 1;
10741 break;
10742 #endif
10743 case TCC_OPTION_g:
10744 do_debug = 1;
10745 break;
10746 case TCC_OPTION_c:
10747 multiple_files = 1;
10748 output_type = TCC_OUTPUT_OBJ;
10749 break;
10750 case TCC_OPTION_static:
10751 s->static_link = 1;
10752 break;
10753 case TCC_OPTION_shared:
10754 output_type = TCC_OUTPUT_DLL;
10755 break;
10756 case TCC_OPTION_o:
10757 multiple_files = 1;
10758 outfile = optarg;
10759 break;
10760 case TCC_OPTION_r:
10761 /* generate a .o merging several output files */
10762 reloc_output = 1;
10763 output_type = TCC_OUTPUT_OBJ;
10764 break;
10765 case TCC_OPTION_nostdinc:
10766 s->nostdinc = 1;
10767 break;
10768 case TCC_OPTION_nostdlib:
10769 s->nostdlib = 1;
10770 break;
10771 case TCC_OPTION_print_search_dirs:
10772 print_search_dirs = 1;
10773 break;
10774 case TCC_OPTION_run:
10776 int argc1;
10777 char **argv1;
10778 argc1 = expand_args(&argv1, optarg);
10779 if (argc1 > 0) {
10780 parse_args(s, argc1, argv1);
10782 multiple_files = 0;
10783 output_type = TCC_OUTPUT_MEMORY;
10785 break;
10786 case TCC_OPTION_v:
10787 printf("tcc version %s\n", TCC_VERSION);
10788 exit(0);
10789 case TCC_OPTION_f:
10790 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10791 goto unsupported_option;
10792 break;
10793 case TCC_OPTION_W:
10794 if (tcc_set_warning(s, optarg, 1) < 0 &&
10795 s->warn_unsupported)
10796 goto unsupported_option;
10797 break;
10798 case TCC_OPTION_w:
10799 s->warn_none = 1;
10800 break;
10801 case TCC_OPTION_rdynamic:
10802 s->rdynamic = 1;
10803 break;
10804 case TCC_OPTION_Wl:
10806 const char *p;
10807 if (strstart(optarg, "-Ttext,", &p)) {
10808 s->text_addr = strtoul(p, NULL, 16);
10809 s->has_text_addr = 1;
10810 } else if (strstart(optarg, "--oformat,", &p)) {
10811 if (strstart(p, "elf32-", NULL)) {
10812 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10813 } else if (!strcmp(p, "binary")) {
10814 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10815 } else
10816 #ifdef TCC_TARGET_COFF
10817 if (!strcmp(p, "coff")) {
10818 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10819 } else
10820 #endif
10822 error("target %s not found", p);
10824 } else {
10825 error("unsupported linker option '%s'", optarg);
10828 break;
10829 case TCC_OPTION_E:
10830 output_type = TCC_OUTPUT_PREPROCESS;
10831 break;
10832 default:
10833 if (s->warn_unsupported) {
10834 unsupported_option:
10835 warning("unsupported option '%s'", r);
10837 break;
10841 return optind;
10844 int main(int argc, char **argv)
10846 int i;
10847 TCCState *s;
10848 int nb_objfiles, ret, optind;
10849 char objfilename[1024];
10850 int64_t start_time = 0;
10852 #ifdef WIN32
10853 tcc_lib_path = w32_tcc_lib_path();
10854 #endif
10856 s = tcc_new();
10857 output_type = TCC_OUTPUT_EXE;
10858 outfile = NULL;
10859 multiple_files = 1;
10860 files = NULL;
10861 nb_files = 0;
10862 nb_libraries = 0;
10863 reloc_output = 0;
10864 print_search_dirs = 0;
10866 optind = parse_args(s, argc - 1, argv + 1) + 1;
10868 if (print_search_dirs) {
10869 /* enough for Linux kernel */
10870 printf("install: %s/\n", tcc_lib_path);
10871 return 0;
10874 nb_objfiles = nb_files - nb_libraries;
10876 /* if outfile provided without other options, we output an
10877 executable */
10878 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10879 output_type = TCC_OUTPUT_EXE;
10881 /* check -c consistency : only single file handled. XXX: checks file type */
10882 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10883 /* accepts only a single input file */
10884 if (nb_objfiles != 1)
10885 error("cannot specify multiple files with -c");
10886 if (nb_libraries != 0)
10887 error("cannot specify libraries with -c");
10891 if (output_type == TCC_OUTPUT_PREPROCESS) {
10892 if (!outfile) {
10893 s->outfile = stdout;
10894 } else {
10895 s->outfile = fopen(outfile, "wb");
10896 if (!s->outfile)
10897 error("could not open '%s", outfile);
10899 } else if (output_type != TCC_OUTPUT_MEMORY) {
10900 if (!outfile) {
10901 /* compute default outfile name */
10902 pstrcpy(objfilename, sizeof(objfilename) - 1,
10903 /* strip path */
10904 tcc_basename(files[0]));
10905 #ifdef TCC_TARGET_PE
10906 pe_guess_outfile(objfilename, output_type);
10907 #else
10908 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10909 char *ext = strrchr(objfilename, '.');
10910 if (!ext)
10911 goto default_outfile;
10912 /* add .o extension */
10913 strcpy(ext + 1, "o");
10914 } else {
10915 default_outfile:
10916 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10918 #endif
10919 outfile = objfilename;
10923 if (do_bench) {
10924 start_time = getclock_us();
10927 tcc_set_output_type(s, output_type);
10929 /* compile or add each files or library */
10930 for(i = 0;i < nb_files; i++) {
10931 const char *filename;
10933 filename = files[i];
10934 if (output_type == TCC_OUTPUT_PREPROCESS) {
10935 tcc_add_file_internal(s, filename,
10936 AFF_PRINT_ERROR | AFF_PREPROCESS);
10937 } else {
10938 if (filename[0] == '-') {
10939 if (tcc_add_library(s, filename + 2) < 0)
10940 error("cannot find %s", filename);
10941 } else {
10942 if (tcc_add_file(s, filename) < 0) {
10943 ret = 1;
10944 goto the_end;
10950 /* free all files */
10951 tcc_free(files);
10953 if (do_bench) {
10954 double total_time;
10955 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10956 if (total_time < 0.001)
10957 total_time = 0.001;
10958 if (total_bytes < 1)
10959 total_bytes = 1;
10960 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10961 tok_ident - TOK_IDENT, total_lines, total_bytes,
10962 total_time, (int)(total_lines / total_time),
10963 total_bytes / total_time / 1000000.0);
10966 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
10967 if (outfile)
10968 fclose(s->outfile);
10969 ret = 0;
10970 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
10971 ret = tcc_run(s, argc - optind, argv + optind);
10972 } else
10973 #ifdef TCC_TARGET_PE
10974 if (s->output_type != TCC_OUTPUT_OBJ) {
10975 ret = tcc_output_pe(s, outfile);
10976 } else
10977 #endif
10979 ret = tcc_output_file(s, outfile) ? 1 : 0;
10981 the_end:
10982 /* XXX: cannot do it with bound checking because of the malloc hooks */
10983 if (!do_bounds_check)
10984 tcc_delete(s);
10986 #ifdef MEM_DEBUG
10987 if (do_bench) {
10988 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10990 #endif
10991 return ret;
10994 #endif