alternative int tcc_relocate(TCCState *s1, void *ptr);
[tinycc/k1w1.git] / tcc.c
blob56cc0a669f69e8d7f34551f7310c3fb7ceeac02d
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 <signal.h>
37 #include <fcntl.h>
38 #include <setjmp.h>
39 #include <time.h>
41 #ifdef _WIN32
42 #include <windows.h>
43 #include <sys/timeb.h>
44 #ifdef _MSC_VER
45 #define inline __inline
46 #endif
47 #endif
49 #ifndef _WIN32
50 #include <unistd.h>
51 #include <sys/time.h>
52 #include <sys/ucontext.h>
53 #include <sys/mman.h>
54 #endif
56 #endif /* !CONFIG_TCCBOOT */
58 #ifndef PAGESIZE
59 #define PAGESIZE 4096
60 #endif
62 #include "elf.h"
63 #include "stab.h"
65 #ifndef O_BINARY
66 #define O_BINARY 0
67 #endif
69 #include "libtcc.h"
71 /* parser debug */
72 //#define PARSE_DEBUG
73 /* preprocessor debug */
74 //#define PP_DEBUG
75 /* include file debug */
76 //#define INC_DEBUG
78 //#define MEM_DEBUG
80 /* assembler debug */
81 //#define ASM_DEBUG
83 /* target selection */
84 //#define TCC_TARGET_I386 /* i386 code generator */
85 //#define TCC_TARGET_ARM /* ARMv4 code generator */
86 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
87 //#define TCC_TARGET_X86_64 /* x86-64 code generator */
89 /* default target is I386 */
90 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
91 !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)
92 #define TCC_TARGET_I386
93 #endif
95 #if !defined(_WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
96 !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)
97 #define CONFIG_TCC_BCHECK /* enable bound checking code */
98 #endif
100 #if defined(_WIN32) && !defined(TCC_TARGET_PE)
101 #define CONFIG_TCC_STATIC
102 #endif
104 /* define it to include assembler support */
105 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67) && \
106 !defined(TCC_TARGET_X86_64)
107 #define CONFIG_TCC_ASM
108 #endif
110 /* object format selection */
111 #if defined(TCC_TARGET_C67)
112 #define TCC_TARGET_COFF
113 #endif
115 #define FALSE 0
116 #define false 0
117 #define TRUE 1
118 #define true 1
119 typedef int BOOL;
121 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
122 executables or dlls */
123 #define CONFIG_TCC_CRT_PREFIX CONFIG_SYSROOT "/usr/lib"
125 #define INCLUDE_STACK_SIZE 32
126 #define IFDEF_STACK_SIZE 64
127 #define VSTACK_SIZE 256
128 #define STRING_MAX_SIZE 1024
129 #define PACK_STACK_SIZE 8
131 #define TOK_HASH_SIZE 8192 /* must be a power of two */
132 #define TOK_ALLOC_INCR 512 /* must be a power of two */
133 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
135 /* token symbol management */
136 typedef struct TokenSym {
137 struct TokenSym *hash_next;
138 struct Sym *sym_define; /* direct pointer to define */
139 struct Sym *sym_label; /* direct pointer to label */
140 struct Sym *sym_struct; /* direct pointer to structure */
141 struct Sym *sym_identifier; /* direct pointer to identifier */
142 int tok; /* token number */
143 int len;
144 char str[1];
145 } TokenSym;
147 #ifdef TCC_TARGET_PE
148 typedef unsigned short nwchar_t;
149 #else
150 typedef int nwchar_t;
151 #endif
153 typedef struct CString {
154 int size; /* size in bytes */
155 void *data; /* either 'char *' or 'nwchar_t *' */
156 int size_allocated;
157 void *data_allocated; /* if non NULL, data has been malloced */
158 } CString;
160 /* type definition */
161 typedef struct CType {
162 int t;
163 struct Sym *ref;
164 } CType;
166 /* constant value */
167 typedef union CValue {
168 long double ld;
169 double d;
170 float f;
171 int i;
172 unsigned int ui;
173 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
174 long long ll;
175 unsigned long long ull;
176 struct CString *cstr;
177 void *ptr;
178 int tab[1];
179 } CValue;
181 /* value on stack */
182 typedef struct SValue {
183 CType type; /* type */
184 unsigned short r; /* register + flags */
185 unsigned short r2; /* second register, used for 'long long'
186 type. If not used, set to VT_CONST */
187 CValue c; /* constant, if VT_CONST */
188 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
189 } SValue;
191 /* symbol management */
192 typedef struct Sym {
193 int v; /* symbol token */
194 long r; /* associated register */
195 long c; /* associated number */
196 CType type; /* associated type */
197 struct Sym *next; /* next related symbol */
198 struct Sym *prev; /* prev symbol in stack */
199 struct Sym *prev_tok; /* previous symbol for this token */
200 } Sym;
202 /* section definition */
203 /* XXX: use directly ELF structure for parameters ? */
204 /* special flag to indicate that the section should not be linked to
205 the other ones */
206 #define SHF_PRIVATE 0x80000000
208 typedef struct Section {
209 unsigned long data_offset; /* current data offset */
210 unsigned char *data; /* section data */
211 unsigned long data_allocated; /* used for realloc() handling */
212 int sh_name; /* elf section name (only used during output) */
213 int sh_num; /* elf section number */
214 int sh_type; /* elf section type */
215 int sh_flags; /* elf section flags */
216 int sh_info; /* elf section info */
217 int sh_addralign; /* elf section alignment */
218 int sh_entsize; /* elf entry size */
219 unsigned long sh_size; /* section size (only used during output) */
220 unsigned long sh_addr; /* address at which the section is relocated */
221 unsigned long sh_offset; /* file offset */
222 int nb_hashed_syms; /* used to resize the hash table */
223 struct Section *link; /* link to another section */
224 struct Section *reloc; /* corresponding section for relocation, if any */
225 struct Section *hash; /* hash table for symbols */
226 struct Section *next;
227 char name[1]; /* section name */
228 } Section;
230 typedef struct DLLReference {
231 int level;
232 void *handle;
233 char name[1];
234 } DLLReference;
236 /* GNUC attribute definition */
237 typedef struct AttributeDef {
238 int aligned;
239 int packed;
240 Section *section;
241 int func_attr; /* calling convention, exports, ... */
242 } AttributeDef;
244 /* -------------------------------------------------- */
245 /* gr: wrappers for casting sym->r for other purposes */
246 typedef struct {
247 unsigned
248 func_call : 8,
249 func_args : 8,
250 func_export : 1;
251 } func_attr_t;
253 #define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
254 #define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
255 #define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
256 #define INLINE_DEF(r) (*(int **)&(r))
257 /* -------------------------------------------------- */
259 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
260 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
261 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
263 /* stored in 'Sym.c' field */
264 #define FUNC_NEW 1 /* ansi function prototype */
265 #define FUNC_OLD 2 /* old function prototype */
266 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
268 /* stored in 'Sym.r' field */
269 #define FUNC_CDECL 0 /* standard c call */
270 #define FUNC_STDCALL 1 /* pascal c call */
271 #define FUNC_FASTCALL1 2 /* first param in %eax */
272 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
273 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
274 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
276 /* field 'Sym.t' for macros */
277 #define MACRO_OBJ 0 /* object like macro */
278 #define MACRO_FUNC 1 /* function like macro */
280 /* field 'Sym.r' for C labels */
281 #define LABEL_DEFINED 0 /* label is defined */
282 #define LABEL_FORWARD 1 /* label is forward defined */
283 #define LABEL_DECLARED 2 /* label is declared but never used */
285 /* type_decl() types */
286 #define TYPE_ABSTRACT 1 /* type without variable */
287 #define TYPE_DIRECT 2 /* type with variable */
289 #define IO_BUF_SIZE 8192
291 typedef struct BufferedFile {
292 uint8_t *buf_ptr;
293 uint8_t *buf_end;
294 int fd;
295 int line_num; /* current line number - here to simplify code */
296 int ifndef_macro; /* #ifndef macro / #endif search */
297 int ifndef_macro_saved; /* saved ifndef_macro */
298 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
299 char inc_type; /* type of include */
300 char inc_filename[512]; /* filename specified by the user */
301 char filename[1024]; /* current filename - here to simplify code */
302 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
303 } BufferedFile;
305 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
306 #define CH_EOF (-1) /* end of file */
308 /* parsing state (used to save parser state to reparse part of the
309 source several times) */
310 typedef struct ParseState {
311 int *macro_ptr;
312 int line_num;
313 int tok;
314 CValue tokc;
315 } ParseState;
317 /* used to record tokens */
318 typedef struct TokenString {
319 int *str;
320 int len;
321 int allocated_len;
322 int last_line_num;
323 } TokenString;
325 /* include file cache, used to find files faster and also to eliminate
326 inclusion if the include file is protected by #ifndef ... #endif */
327 typedef struct CachedInclude {
328 int ifndef_macro;
329 int hash_next; /* -1 if none */
330 char type; /* '"' or '>' to give include type */
331 char filename[1]; /* path specified in #include */
332 } CachedInclude;
334 #define CACHED_INCLUDES_HASH_SIZE 512
336 /* parser */
337 static struct BufferedFile *file;
338 static int ch, tok;
339 static CString tok_spaces; /* spaces before current token */
340 static CValue tokc;
341 static CString tokcstr; /* current parsed string, if any */
342 /* additional informations about token */
343 static int tok_flags;
344 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
345 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
346 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
347 #define TOK_FLAG_EOF 0x0008 /* end of file */
349 static int *macro_ptr, *macro_ptr_allocated;
350 static int *unget_saved_macro_ptr;
351 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
352 static int unget_buffer_enabled;
353 static int parse_flags;
354 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
355 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
356 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
357 token. line feed is also
358 returned at eof */
359 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
361 static Section *text_section, *data_section, *bss_section; /* predefined sections */
362 static Section *cur_text_section; /* current section where function code is
363 generated */
364 #ifdef CONFIG_TCC_ASM
365 static Section *last_text_section; /* to handle .previous asm directive */
366 #endif
367 /* bound check related sections */
368 static Section *bounds_section; /* contains global data bound description */
369 static Section *lbounds_section; /* contains local data bound description */
370 /* symbol sections */
371 static Section *symtab_section, *strtab_section;
373 /* debug sections */
374 static Section *stab_section, *stabstr_section;
376 /* loc : local variable index
377 ind : output code index
378 rsym: return symbol
379 anon_sym: anonymous symbol index
381 static int rsym, anon_sym, ind, loc;
382 /* expression generation modifiers */
383 static int const_wanted; /* true if constant wanted */
384 static int nocode_wanted; /* true if no code generation wanted for an expression */
385 static int global_expr; /* true if compound literals must be allocated
386 globally (used during initializers parsing */
387 static CType func_vt; /* current function return type (used by return
388 instruction) */
389 static int func_vc;
390 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
391 static int tok_ident;
392 static TokenSym **table_ident;
393 static TokenSym *hash_ident[TOK_HASH_SIZE];
394 static char token_buf[STRING_MAX_SIZE + 1];
395 static char *funcname;
396 static Sym *global_stack, *local_stack;
397 static Sym *define_stack;
398 static Sym *global_label_stack, *local_label_stack;
399 /* symbol allocator */
400 #define SYM_POOL_NB (8192 / sizeof(Sym))
401 static Sym *sym_free_first;
402 static void **sym_pools;
403 static int nb_sym_pools;
405 static SValue vstack[VSTACK_SIZE], *vtop;
406 /* some predefined types */
407 static CType char_pointer_type, func_old_type, int_type;
408 /* true if isid(c) || isnum(c) */
409 static unsigned char isidnum_table[256-CH_EOF];
411 /* display some information during compilation */
412 static int verbose = 0;
414 /* compile with debug symbol (and use them if error during execution) */
415 static int do_debug = 0;
417 /* compile with built-in memory and bounds checker */
418 static int do_bounds_check = 0;
420 /* display benchmark infos */
421 #if !defined(LIBTCC)
422 static int do_bench = 0;
423 #endif
424 static int total_lines;
425 static int total_bytes;
427 /* use GNU C extensions */
428 static int gnu_ext = 1;
430 /* use Tiny C extensions */
431 static int tcc_ext = 1;
433 /* max number of callers shown if error */
434 static int num_callers = 6;
435 static const char **rt_bound_error_msg;
437 /* XXX: get rid of this ASAP */
438 static struct TCCState *tcc_state;
440 /* give the path of the tcc libraries */
441 static const char *tcc_lib_path = CONFIG_TCCDIR;
443 struct TCCState {
444 int output_type;
446 BufferedFile **include_stack_ptr;
447 int *ifdef_stack_ptr;
449 /* include file handling */
450 char **include_paths;
451 int nb_include_paths;
452 char **sysinclude_paths;
453 int nb_sysinclude_paths;
454 CachedInclude **cached_includes;
455 int nb_cached_includes;
457 char **library_paths;
458 int nb_library_paths;
460 /* array of all loaded dlls (including those referenced by loaded
461 dlls) */
462 DLLReference **loaded_dlls;
463 int nb_loaded_dlls;
465 /* sections */
466 Section **sections;
467 int nb_sections; /* number of sections, including first dummy section */
469 Section **priv_sections;
470 int nb_priv_sections; /* number of private sections */
472 /* got handling */
473 Section *got;
474 Section *plt;
475 unsigned long *got_offsets;
476 int nb_got_offsets;
477 /* give the correspondance from symtab indexes to dynsym indexes */
478 int *symtab_to_dynsym;
480 /* temporary dynamic symbol sections (for dll loading) */
481 Section *dynsymtab_section;
482 /* exported dynamic symbol section */
483 Section *dynsym;
485 int nostdinc; /* if true, no standard headers are added */
486 int nostdlib; /* if true, no standard libraries are added */
488 int nocommon; /* if true, do not use common symbols for .bss data */
490 /* if true, static linking is performed */
491 int static_link;
493 /* soname as specified on the command line (-soname) */
494 const char *soname;
496 /* if true, all symbols are exported */
497 int rdynamic;
499 /* if true, only link in referenced objects from archive */
500 int alacarte_link;
502 /* address of text section */
503 unsigned long text_addr;
504 int has_text_addr;
506 /* output format, see TCC_OUTPUT_FORMAT_xxx */
507 int output_format;
509 /* C language options */
510 int char_is_unsigned;
511 int leading_underscore;
513 /* warning switches */
514 int warn_write_strings;
515 int warn_unsupported;
516 int warn_error;
517 int warn_none;
518 int warn_implicit_function_declaration;
520 /* error handling */
521 void *error_opaque;
522 void (*error_func)(void *opaque, const char *msg);
523 int error_set_jmp_enabled;
524 jmp_buf error_jmp_buf;
525 int nb_errors;
527 /* tiny assembler state */
528 Sym *asm_labels;
530 /* see include_stack_ptr */
531 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
533 /* see ifdef_stack_ptr */
534 int ifdef_stack[IFDEF_STACK_SIZE];
536 /* see cached_includes */
537 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
539 /* pack stack */
540 int pack_stack[PACK_STACK_SIZE];
541 int *pack_stack_ptr;
543 /* output file for preprocessing */
544 FILE *outfile;
546 /* for tcc_relocate */
547 int runtime_added;
550 /* The current value can be: */
551 #define VT_VALMASK 0x00ff
552 #define VT_CONST 0x00f0 /* constant in vc
553 (must be first non register value) */
554 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
555 #define VT_LOCAL 0x00f2 /* offset on stack */
556 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
557 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
558 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
559 #define VT_LVAL 0x0100 /* var is an lvalue */
560 #define VT_SYM 0x0200 /* a symbol value is added */
561 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
562 char/short stored in integer registers) */
563 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
564 dereferencing value */
565 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
566 bounding function call point is in vc */
567 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
568 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
569 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
570 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
572 /* types */
573 #define VT_INT 0 /* integer type */
574 #define VT_BYTE 1 /* signed byte type */
575 #define VT_SHORT 2 /* short type */
576 #define VT_VOID 3 /* void type */
577 #define VT_PTR 4 /* pointer */
578 #define VT_ENUM 5 /* enum definition */
579 #define VT_FUNC 6 /* function type */
580 #define VT_STRUCT 7 /* struct/union definition */
581 #define VT_FLOAT 8 /* IEEE float */
582 #define VT_DOUBLE 9 /* IEEE double */
583 #define VT_LDOUBLE 10 /* IEEE long double */
584 #define VT_BOOL 11 /* ISOC99 boolean type */
585 #define VT_LLONG 12 /* 64 bit integer */
586 #define VT_LONG 13 /* long integer (NEVER USED as type, only
587 during parsing) */
588 #define VT_BTYPE 0x000f /* mask for basic type */
589 #define VT_UNSIGNED 0x0010 /* unsigned type */
590 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
591 #define VT_BITFIELD 0x0040 /* bitfield modifier */
592 #define VT_CONSTANT 0x0800 /* const modifier */
593 #define VT_VOLATILE 0x1000 /* volatile modifier */
594 #define VT_SIGNED 0x2000 /* signed type */
596 /* storage */
597 #define VT_EXTERN 0x00000080 /* extern definition */
598 #define VT_STATIC 0x00000100 /* static variable */
599 #define VT_TYPEDEF 0x00000200 /* typedef definition */
600 #define VT_INLINE 0x00000400 /* inline definition */
602 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
604 /* type mask (except storage) */
605 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
606 #define VT_TYPE (~(VT_STORAGE))
608 /* token values */
610 /* warning: the following compare tokens depend on i386 asm code */
611 #define TOK_ULT 0x92
612 #define TOK_UGE 0x93
613 #define TOK_EQ 0x94
614 #define TOK_NE 0x95
615 #define TOK_ULE 0x96
616 #define TOK_UGT 0x97
617 #define TOK_Nset 0x98
618 #define TOK_Nclear 0x99
619 #define TOK_LT 0x9c
620 #define TOK_GE 0x9d
621 #define TOK_LE 0x9e
622 #define TOK_GT 0x9f
624 #define TOK_LAND 0xa0
625 #define TOK_LOR 0xa1
627 #define TOK_DEC 0xa2
628 #define TOK_MID 0xa3 /* inc/dec, to void constant */
629 #define TOK_INC 0xa4
630 #define TOK_UDIV 0xb0 /* unsigned division */
631 #define TOK_UMOD 0xb1 /* unsigned modulo */
632 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
633 #define TOK_CINT 0xb3 /* number in tokc */
634 #define TOK_CCHAR 0xb4 /* char constant in tokc */
635 #define TOK_STR 0xb5 /* pointer to string in tokc */
636 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
637 #define TOK_LCHAR 0xb7
638 #define TOK_LSTR 0xb8
639 #define TOK_CFLOAT 0xb9 /* float constant */
640 #define TOK_LINENUM 0xba /* line number info */
641 #define TOK_CDOUBLE 0xc0 /* double constant */
642 #define TOK_CLDOUBLE 0xc1 /* long double constant */
643 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
644 #define TOK_ADDC1 0xc3 /* add with carry generation */
645 #define TOK_ADDC2 0xc4 /* add with carry use */
646 #define TOK_SUBC1 0xc5 /* add with carry generation */
647 #define TOK_SUBC2 0xc6 /* add with carry use */
648 #define TOK_CUINT 0xc8 /* unsigned int constant */
649 #define TOK_CLLONG 0xc9 /* long long constant */
650 #define TOK_CULLONG 0xca /* unsigned long long constant */
651 #define TOK_ARROW 0xcb
652 #define TOK_DOTS 0xcc /* three dots */
653 #define TOK_SHR 0xcd /* unsigned shift right */
654 #define TOK_PPNUM 0xce /* preprocessor number */
656 #define TOK_SHL 0x01 /* shift left */
657 #define TOK_SAR 0x02 /* signed shift right */
659 /* assignement operators : normal operator or 0x80 */
660 #define TOK_A_MOD 0xa5
661 #define TOK_A_AND 0xa6
662 #define TOK_A_MUL 0xaa
663 #define TOK_A_ADD 0xab
664 #define TOK_A_SUB 0xad
665 #define TOK_A_DIV 0xaf
666 #define TOK_A_XOR 0xde
667 #define TOK_A_OR 0xfc
668 #define TOK_A_SHL 0x81
669 #define TOK_A_SAR 0x82
671 #ifndef offsetof
672 #define offsetof(type, field) ((size_t) &((type *)0)->field)
673 #endif
675 #ifndef countof
676 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
677 #endif
679 /* WARNING: the content of this string encodes token numbers */
680 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";
682 #define TOK_EOF (-1) /* end of file */
683 #define TOK_LINEFEED 10 /* line feed */
685 /* all identificators and strings have token above that */
686 #define TOK_IDENT 256
688 /* only used for i386 asm opcodes definitions */
689 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
691 #define DEF_BWL(x) \
692 DEF(TOK_ASM_ ## x ## b, #x "b") \
693 DEF(TOK_ASM_ ## x ## w, #x "w") \
694 DEF(TOK_ASM_ ## x ## l, #x "l") \
695 DEF(TOK_ASM_ ## x, #x)
697 #define DEF_WL(x) \
698 DEF(TOK_ASM_ ## x ## w, #x "w") \
699 DEF(TOK_ASM_ ## x ## l, #x "l") \
700 DEF(TOK_ASM_ ## x, #x)
702 #define DEF_FP1(x) \
703 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
704 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
705 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
706 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
708 #define DEF_FP(x) \
709 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
710 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
711 DEF_FP1(x)
713 #define DEF_ASMTEST(x) \
714 DEF_ASM(x ## o) \
715 DEF_ASM(x ## no) \
716 DEF_ASM(x ## b) \
717 DEF_ASM(x ## c) \
718 DEF_ASM(x ## nae) \
719 DEF_ASM(x ## nb) \
720 DEF_ASM(x ## nc) \
721 DEF_ASM(x ## ae) \
722 DEF_ASM(x ## e) \
723 DEF_ASM(x ## z) \
724 DEF_ASM(x ## ne) \
725 DEF_ASM(x ## nz) \
726 DEF_ASM(x ## be) \
727 DEF_ASM(x ## na) \
728 DEF_ASM(x ## nbe) \
729 DEF_ASM(x ## a) \
730 DEF_ASM(x ## s) \
731 DEF_ASM(x ## ns) \
732 DEF_ASM(x ## p) \
733 DEF_ASM(x ## pe) \
734 DEF_ASM(x ## np) \
735 DEF_ASM(x ## po) \
736 DEF_ASM(x ## l) \
737 DEF_ASM(x ## nge) \
738 DEF_ASM(x ## nl) \
739 DEF_ASM(x ## ge) \
740 DEF_ASM(x ## le) \
741 DEF_ASM(x ## ng) \
742 DEF_ASM(x ## nle) \
743 DEF_ASM(x ## g)
745 #define TOK_ASM_int TOK_INT
747 enum tcc_token {
748 TOK_LAST = TOK_IDENT - 1,
749 #define DEF(id, str) id,
750 #include "tcctok.h"
751 #undef DEF
754 static const char tcc_keywords[] =
755 #define DEF(id, str) str "\0"
756 #include "tcctok.h"
757 #undef DEF
760 #define TOK_UIDENT TOK_DEFINE
762 #ifdef _WIN32
763 #define snprintf _snprintf
764 #define vsnprintf _vsnprintf
765 #ifndef __GNUC__
766 #define strtold (long double)strtod
767 #define strtof (float)strtod
768 #define strtoll (long long)strtol
769 #endif
770 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
771 || defined(__OpenBSD__)
772 /* currently incorrect */
773 long double strtold(const char *nptr, char **endptr)
775 return (long double)strtod(nptr, endptr);
777 float strtof(const char *nptr, char **endptr)
779 return (float)strtod(nptr, endptr);
781 #else
782 /* XXX: need to define this to use them in non ISOC99 context */
783 extern float strtof (const char *__nptr, char **__endptr);
784 extern long double strtold (const char *__nptr, char **__endptr);
785 #endif
787 static char *pstrcpy(char *buf, int buf_size, const char *s);
788 static char *pstrcat(char *buf, int buf_size, const char *s);
789 static char *tcc_basename(const char *name);
790 static char *tcc_fileextension (const char *p);
792 static void next(void);
793 static void next_nomacro(void);
794 static void parse_expr_type(CType *type);
795 static void expr_type(CType *type);
796 static void unary_type(CType *type);
797 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
798 int case_reg, int is_expr);
799 static int expr_const(void);
800 static void expr_eq(void);
801 static void gexpr(void);
802 static void gen_inline_functions(void);
803 static void decl(int l);
804 static void decl_initializer(CType *type, Section *sec, unsigned long c,
805 int first, int size_only);
806 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
807 int has_init, int v, int scope);
808 int gv(int rc);
809 void gv2(int rc1, int rc2);
810 void move_reg(int r, int s);
811 void save_regs(int n);
812 void save_reg(int r);
813 void vpop(void);
814 void vswap(void);
815 void vdup(void);
816 int get_reg(int rc);
817 int get_reg_ex(int rc,int rc2);
819 struct macro_level {
820 struct macro_level *prev;
821 int *p;
824 static void macro_subst(TokenString *tok_str, Sym **nested_list,
825 const int *macro_str, struct macro_level **can_read_stream);
826 void gen_op(int op);
827 void force_charshort_cast(int t);
828 static void gen_cast(CType *type);
829 void vstore(void);
830 static Sym *sym_find(int v);
831 static Sym *sym_push(int v, CType *type, int r, int c);
833 /* type handling */
834 static int type_size(CType *type, int *a);
835 static inline CType *pointed_type(CType *type);
836 static int pointed_size(CType *type);
837 static int lvalue_type(int t);
838 static int parse_btype(CType *type, AttributeDef *ad);
839 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
840 static int compare_types(CType *type1, CType *type2, int unqualified);
841 static int is_compatible_types(CType *type1, CType *type2);
842 static int is_compatible_parameter_types(CType *type1, CType *type2);
844 int ieee_finite(double d);
845 void error(const char *fmt, ...);
846 void vpushi(int v);
847 void vpushll(long long v);
848 void vrott(int n);
849 void vnrott(int n);
850 void lexpand_nr(void);
851 static void vpush_global_sym(CType *type, int v);
852 void vset(CType *type, int r, int v);
853 void type_to_str(char *buf, int buf_size,
854 CType *type, const char *varstr);
855 char *get_tok_str(int v, CValue *cv);
856 static Sym *get_sym_ref(CType *type, Section *sec,
857 unsigned long offset, unsigned long size);
858 static Sym *external_global_sym(int v, CType *type, int r);
860 /* section generation */
861 static void section_realloc(Section *sec, unsigned long new_size);
862 static void *section_ptr_add(Section *sec, unsigned long size);
863 static void put_extern_sym(Sym *sym, Section *section,
864 unsigned long value, unsigned long size);
865 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
866 static int put_elf_str(Section *s, const char *sym);
867 static int put_elf_sym(Section *s,
868 unsigned long value, unsigned long size,
869 int info, int other, int shndx, const char *name);
870 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
871 int info, int other, int sh_num, const char *name);
872 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
873 int type, int symbol);
874 static void put_stabs(const char *str, int type, int other, int desc,
875 unsigned long value);
876 static void put_stabs_r(const char *str, int type, int other, int desc,
877 unsigned long value, Section *sec, int sym_index);
878 static void put_stabn(int type, int other, int desc, int value);
879 static void put_stabd(int type, int other, int desc);
880 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
882 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
883 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
884 #define AFF_PREPROCESS 0x0004 /* preprocess file */
885 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
887 /* tcccoff.c */
888 int tcc_output_coff(TCCState *s1, FILE *f);
890 /* tccpe.c */
891 void *resolve_sym(TCCState *s1, const char *sym, int type);
892 int pe_load_def_file(struct TCCState *s1, int fd);
893 int pe_test_res_file(void *v, int size);
894 int pe_load_res_file(struct TCCState *s1, int fd);
895 void pe_add_runtime(struct TCCState *s1);
896 void pe_guess_outfile(char *objfilename, int output_type);
897 int pe_output_file(struct TCCState *s1, const char *filename);
899 /* tccasm.c */
901 #ifdef CONFIG_TCC_ASM
903 typedef struct ExprValue {
904 uint32_t v;
905 Sym *sym;
906 } ExprValue;
908 #define MAX_ASM_OPERANDS 30
910 typedef struct ASMOperand {
911 int id; /* GCC 3 optionnal identifier (0 if number only supported */
912 char *constraint;
913 char asm_str[16]; /* computed asm string for operand */
914 SValue *vt; /* C value of the expression */
915 int ref_index; /* if >= 0, gives reference to a output constraint */
916 int input_index; /* if >= 0, gives reference to an input constraint */
917 int priority; /* priority, used to assign registers */
918 int reg; /* if >= 0, register number used for this operand */
919 int is_llong; /* true if double register value */
920 int is_memory; /* true if memory operand */
921 int is_rw; /* for '+' modifier */
922 } ASMOperand;
924 static void asm_expr(TCCState *s1, ExprValue *pe);
925 static int asm_int_expr(TCCState *s1);
926 static int find_constraint(ASMOperand *operands, int nb_operands,
927 const char *name, const char **pp);
929 static int tcc_assemble(TCCState *s1, int do_preprocess);
931 #endif
933 static void asm_instr(void);
934 static void asm_global_instr(void);
936 /* true if float/double/long double type */
937 static inline int is_float(int t)
939 int bt;
940 bt = t & VT_BTYPE;
941 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
944 #ifdef TCC_TARGET_I386
945 #include "i386-gen.c"
946 #endif
948 #ifdef TCC_TARGET_ARM
949 #include "arm-gen.c"
950 #endif
952 #ifdef TCC_TARGET_C67
953 #include "c67-gen.c"
954 #endif
956 #ifdef TCC_TARGET_X86_64
957 #include "x86_64-gen.c"
958 #endif
960 #ifdef CONFIG_TCC_STATIC
962 #define RTLD_LAZY 0x001
963 #define RTLD_NOW 0x002
964 #define RTLD_GLOBAL 0x100
965 #define RTLD_DEFAULT NULL
967 /* dummy function for profiling */
968 void *dlopen(const char *filename, int flag)
970 return NULL;
973 const char *dlerror(void)
975 return "error";
978 typedef struct TCCSyms {
979 char *str;
980 void *ptr;
981 } TCCSyms;
983 #define TCCSYM(a) { #a, &a, },
985 /* add the symbol you want here if no dynamic linking is done */
986 static TCCSyms tcc_syms[] = {
987 #if !defined(CONFIG_TCCBOOT)
988 TCCSYM(printf)
989 TCCSYM(fprintf)
990 TCCSYM(fopen)
991 TCCSYM(fclose)
992 #endif
993 { NULL, NULL },
996 void *resolve_sym(TCCState *s1, const char *symbol, int type)
998 TCCSyms *p;
999 p = tcc_syms;
1000 while (p->str != NULL) {
1001 if (!strcmp(p->str, symbol))
1002 return p->ptr;
1003 p++;
1005 return NULL;
1008 #elif !defined(_WIN32)
1010 #include <dlfcn.h>
1012 void *resolve_sym(TCCState *s1, const char *sym, int type)
1014 return dlsym(RTLD_DEFAULT, sym);
1017 #endif
1019 /********************************************************/
1021 /* we use our own 'finite' function to avoid potential problems with
1022 non standard math libs */
1023 /* XXX: endianness dependent */
1024 int ieee_finite(double d)
1026 int *p = (int *)&d;
1027 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
1030 /* copy a string and truncate it. */
1031 static char *pstrcpy(char *buf, int buf_size, const char *s)
1033 char *q, *q_end;
1034 int c;
1036 if (buf_size > 0) {
1037 q = buf;
1038 q_end = buf + buf_size - 1;
1039 while (q < q_end) {
1040 c = *s++;
1041 if (c == '\0')
1042 break;
1043 *q++ = c;
1045 *q = '\0';
1047 return buf;
1050 /* strcat and truncate. */
1051 static char *pstrcat(char *buf, int buf_size, const char *s)
1053 int len;
1054 len = strlen(buf);
1055 if (len < buf_size)
1056 pstrcpy(buf + len, buf_size - len, s);
1057 return buf;
1060 #ifndef LIBTCC
1061 static int strstart(const char *str, const char *val, const char **ptr)
1063 const char *p, *q;
1064 p = str;
1065 q = val;
1066 while (*q != '\0') {
1067 if (*p != *q)
1068 return 0;
1069 p++;
1070 q++;
1072 if (ptr)
1073 *ptr = p;
1074 return 1;
1076 #endif
1078 #ifdef _WIN32
1079 #define IS_PATHSEP(c) (c == '/' || c == '\\')
1080 #define IS_ABSPATH(p) (IS_PATHSEP(p[0]) || (p[0] && p[1] == ':' && IS_PATHSEP(p[2])))
1081 #define PATHCMP stricmp
1082 #else
1083 #define IS_PATHSEP(c) (c == '/')
1084 #define IS_ABSPATH(p) IS_PATHSEP(p[0])
1085 #define PATHCMP strcmp
1086 #endif
1088 /* extract the basename of a file */
1089 static char *tcc_basename(const char *name)
1091 char *p = strchr(name, 0);
1092 while (p > name && !IS_PATHSEP(p[-1]))
1093 --p;
1094 return p;
1097 static char *tcc_fileextension (const char *name)
1099 char *b = tcc_basename(name);
1100 char *e = strrchr(b, '.');
1101 return e ? e : strchr(b, 0);
1104 #ifdef _WIN32
1105 char *normalize_slashes(char *path)
1107 char *p;
1108 for (p = path; *p; ++p)
1109 if (*p == '\\')
1110 *p = '/';
1111 return path;
1114 char *w32_tcc_lib_path(void)
1116 /* on win32, we suppose the lib and includes are at the location
1117 of 'tcc.exe' */
1118 char path[1024], *p;
1119 GetModuleFileNameA(NULL, path, sizeof path);
1120 p = tcc_basename(normalize_slashes(strlwr(path)));
1121 if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
1122 p -= 5;
1123 else if (p > path)
1124 p--;
1125 *p = 0;
1126 return strdup(path);
1128 #endif
1130 void set_pages_executable(void *ptr, unsigned long length)
1132 #ifdef _WIN32
1133 unsigned long old_protect;
1134 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
1135 #else
1136 unsigned long start, end;
1137 start = (unsigned long)ptr & ~(PAGESIZE - 1);
1138 end = (unsigned long)ptr + length;
1139 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
1140 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
1141 #endif
1144 /* memory management */
1145 #ifdef MEM_DEBUG
1146 int mem_cur_size;
1147 int mem_max_size;
1148 unsigned malloc_usable_size(void*);
1149 #endif
1151 static inline void tcc_free(void *ptr)
1153 #ifdef MEM_DEBUG
1154 mem_cur_size -= malloc_usable_size(ptr);
1155 #endif
1156 free(ptr);
1159 static void *tcc_malloc(unsigned long size)
1161 void *ptr;
1162 ptr = malloc(size);
1163 if (!ptr && size)
1164 error("memory full");
1165 #ifdef MEM_DEBUG
1166 mem_cur_size += malloc_usable_size(ptr);
1167 if (mem_cur_size > mem_max_size)
1168 mem_max_size = mem_cur_size;
1169 #endif
1170 return ptr;
1173 static void *tcc_mallocz(unsigned long size)
1175 void *ptr;
1176 ptr = tcc_malloc(size);
1177 memset(ptr, 0, size);
1178 return ptr;
1181 static inline void *tcc_realloc(void *ptr, unsigned long size)
1183 void *ptr1;
1184 #ifdef MEM_DEBUG
1185 mem_cur_size -= malloc_usable_size(ptr);
1186 #endif
1187 ptr1 = realloc(ptr, size);
1188 #ifdef MEM_DEBUG
1189 /* NOTE: count not correct if alloc error, but not critical */
1190 mem_cur_size += malloc_usable_size(ptr1);
1191 if (mem_cur_size > mem_max_size)
1192 mem_max_size = mem_cur_size;
1193 #endif
1194 return ptr1;
1197 static char *tcc_strdup(const char *str)
1199 char *ptr;
1200 ptr = tcc_malloc(strlen(str) + 1);
1201 strcpy(ptr, str);
1202 return ptr;
1205 #define free(p) use_tcc_free(p)
1206 #define malloc(s) use_tcc_malloc(s)
1207 #define realloc(p, s) use_tcc_realloc(p, s)
1209 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1211 int nb, nb_alloc;
1212 void **pp;
1214 nb = *nb_ptr;
1215 pp = *ptab;
1216 /* every power of two we double array size */
1217 if ((nb & (nb - 1)) == 0) {
1218 if (!nb)
1219 nb_alloc = 1;
1220 else
1221 nb_alloc = nb * 2;
1222 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1223 if (!pp)
1224 error("memory full");
1225 *ptab = pp;
1227 pp[nb++] = data;
1228 *nb_ptr = nb;
1231 static void dynarray_reset(void *pp, int *n)
1233 void **p;
1234 for (p = *(void***)pp; *n; ++p, --*n)
1235 if (*p)
1236 tcc_free(*p);
1237 tcc_free(*(void**)pp);
1238 *(void**)pp = NULL;
1241 /* symbol allocator */
1242 static Sym *__sym_malloc(void)
1244 Sym *sym_pool, *sym, *last_sym;
1245 int i;
1247 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1248 dynarray_add(&sym_pools, &nb_sym_pools, sym_pool);
1250 last_sym = sym_free_first;
1251 sym = sym_pool;
1252 for(i = 0; i < SYM_POOL_NB; i++) {
1253 sym->next = last_sym;
1254 last_sym = sym;
1255 sym++;
1257 sym_free_first = last_sym;
1258 return last_sym;
1261 static inline Sym *sym_malloc(void)
1263 Sym *sym;
1264 sym = sym_free_first;
1265 if (!sym)
1266 sym = __sym_malloc();
1267 sym_free_first = sym->next;
1268 return sym;
1271 static inline void sym_free(Sym *sym)
1273 sym->next = sym_free_first;
1274 sym_free_first = sym;
1277 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1279 Section *sec;
1281 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1282 strcpy(sec->name, name);
1283 sec->sh_type = sh_type;
1284 sec->sh_flags = sh_flags;
1285 switch(sh_type) {
1286 case SHT_HASH:
1287 case SHT_REL:
1288 case SHT_RELA:
1289 case SHT_DYNSYM:
1290 case SHT_SYMTAB:
1291 case SHT_DYNAMIC:
1292 sec->sh_addralign = 4;
1293 break;
1294 case SHT_STRTAB:
1295 sec->sh_addralign = 1;
1296 break;
1297 default:
1298 sec->sh_addralign = 32; /* default conservative alignment */
1299 break;
1302 if (sh_flags & SHF_PRIVATE) {
1303 dynarray_add((void ***)&s1->priv_sections, &s1->nb_priv_sections, sec);
1304 } else {
1305 sec->sh_num = s1->nb_sections;
1306 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1309 return sec;
1312 static void free_section(Section *s)
1314 #ifdef TCC_TARGET_X86_64
1315 /* after tcc_relocate(), some sections share the data buffer.
1316 let's check if the data is allocated not to free the shared buffers */
1317 if (s->data_allocated)
1318 #endif
1319 tcc_free(s->data);
1322 /* realloc section and set its content to zero */
1323 static void section_realloc(Section *sec, unsigned long new_size)
1325 unsigned long size;
1326 unsigned char *data;
1328 size = sec->data_allocated;
1329 if (size == 0)
1330 size = 1;
1331 while (size < new_size)
1332 size = size * 2;
1333 data = tcc_realloc(sec->data, size);
1334 if (!data)
1335 error("memory full");
1336 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1337 sec->data = data;
1338 sec->data_allocated = size;
1341 /* reserve at least 'size' bytes in section 'sec' from
1342 sec->data_offset. */
1343 static void *section_ptr_add(Section *sec, unsigned long size)
1345 unsigned long offset, offset1;
1347 offset = sec->data_offset;
1348 offset1 = offset + size;
1349 if (offset1 > sec->data_allocated)
1350 section_realloc(sec, offset1);
1351 sec->data_offset = offset1;
1352 return sec->data + offset;
1355 /* return a reference to a section, and create it if it does not
1356 exists */
1357 Section *find_section(TCCState *s1, const char *name)
1359 Section *sec;
1360 int i;
1361 for(i = 1; i < s1->nb_sections; i++) {
1362 sec = s1->sections[i];
1363 if (!strcmp(name, sec->name))
1364 return sec;
1366 /* sections are created as PROGBITS */
1367 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1370 #define SECTION_ABS ((void *)1)
1372 /* update sym->c so that it points to an external symbol in section
1373 'section' with value 'value' */
1374 static void put_extern_sym2(Sym *sym, Section *section,
1375 unsigned long value, unsigned long size,
1376 int can_add_underscore)
1378 int sym_type, sym_bind, sh_num, info, other, attr;
1379 ElfW(Sym) *esym;
1380 const char *name;
1381 char buf1[256];
1383 if (section == NULL)
1384 sh_num = SHN_UNDEF;
1385 else if (section == SECTION_ABS)
1386 sh_num = SHN_ABS;
1387 else
1388 sh_num = section->sh_num;
1390 other = attr = 0;
1392 if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
1393 sym_type = STT_FUNC;
1394 #ifdef TCC_TARGET_PE
1395 if (sym->type.ref)
1396 attr = sym->type.ref->r;
1397 if (FUNC_EXPORT(attr))
1398 other |= 1;
1399 if (FUNC_CALL(attr) == FUNC_STDCALL)
1400 other |= 2;
1401 #endif
1402 } else {
1403 sym_type = STT_OBJECT;
1406 if (sym->type.t & VT_STATIC)
1407 sym_bind = STB_LOCAL;
1408 else
1409 sym_bind = STB_GLOBAL;
1411 if (!sym->c) {
1412 name = get_tok_str(sym->v, NULL);
1413 #ifdef CONFIG_TCC_BCHECK
1414 if (do_bounds_check) {
1415 char buf[32];
1417 /* XXX: avoid doing that for statics ? */
1418 /* if bound checking is activated, we change some function
1419 names by adding the "__bound" prefix */
1420 switch(sym->v) {
1421 #if 0
1422 /* XXX: we rely only on malloc hooks */
1423 case TOK_malloc:
1424 case TOK_free:
1425 case TOK_realloc:
1426 case TOK_memalign:
1427 case TOK_calloc:
1428 #endif
1429 case TOK_memcpy:
1430 case TOK_memmove:
1431 case TOK_memset:
1432 case TOK_strlen:
1433 case TOK_strcpy:
1434 case TOK__alloca:
1435 strcpy(buf, "__bound_");
1436 strcat(buf, name);
1437 name = buf;
1438 break;
1441 #endif
1443 #ifdef TCC_TARGET_PE
1444 if ((other & 2) && can_add_underscore) {
1445 sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
1446 name = buf1;
1447 } else
1448 #endif
1449 if (tcc_state->leading_underscore && can_add_underscore) {
1450 buf1[0] = '_';
1451 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1452 name = buf1;
1454 info = ELFW(ST_INFO)(sym_bind, sym_type);
1455 sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
1456 } else {
1457 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
1458 esym->st_value = value;
1459 esym->st_size = size;
1460 esym->st_shndx = sh_num;
1461 esym->st_other |= other;
1465 static void put_extern_sym(Sym *sym, Section *section,
1466 unsigned long value, unsigned long size)
1468 put_extern_sym2(sym, section, value, size, 1);
1471 /* add a new relocation entry to symbol 'sym' in section 's' */
1472 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1474 if (!sym->c)
1475 put_extern_sym(sym, NULL, 0, 0);
1476 /* now we can add ELF relocation info */
1477 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1480 static inline int isid(int c)
1482 return (c >= 'a' && c <= 'z') ||
1483 (c >= 'A' && c <= 'Z') ||
1484 c == '_';
1487 static inline int isnum(int c)
1489 return c >= '0' && c <= '9';
1492 static inline int isoct(int c)
1494 return c >= '0' && c <= '7';
1497 static inline int toup(int c)
1499 if (c >= 'a' && c <= 'z')
1500 return c - 'a' + 'A';
1501 else
1502 return c;
1505 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1507 int len;
1508 len = strlen(buf);
1509 vsnprintf(buf + len, buf_size - len, fmt, ap);
1512 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1514 va_list ap;
1515 va_start(ap, fmt);
1516 strcat_vprintf(buf, buf_size, fmt, ap);
1517 va_end(ap);
1520 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1522 char buf[2048];
1523 BufferedFile **f;
1525 buf[0] = '\0';
1526 if (file) {
1527 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1528 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1529 (*f)->filename, (*f)->line_num);
1530 if (file->line_num > 0) {
1531 strcat_printf(buf, sizeof(buf),
1532 "%s:%d: ", file->filename, file->line_num);
1533 } else {
1534 strcat_printf(buf, sizeof(buf),
1535 "%s: ", file->filename);
1537 } else {
1538 strcat_printf(buf, sizeof(buf),
1539 "tcc: ");
1541 if (is_warning)
1542 strcat_printf(buf, sizeof(buf), "warning: ");
1543 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1545 if (!s1->error_func) {
1546 /* default case: stderr */
1547 fprintf(stderr, "%s\n", buf);
1548 } else {
1549 s1->error_func(s1->error_opaque, buf);
1551 if (!is_warning || s1->warn_error)
1552 s1->nb_errors++;
1555 #ifdef LIBTCC
1556 void tcc_set_error_func(TCCState *s, void *error_opaque,
1557 void (*error_func)(void *opaque, const char *msg))
1559 s->error_opaque = error_opaque;
1560 s->error_func = error_func;
1562 #endif
1564 /* error without aborting current compilation */
1565 void error_noabort(const char *fmt, ...)
1567 TCCState *s1 = tcc_state;
1568 va_list ap;
1570 va_start(ap, fmt);
1571 error1(s1, 0, fmt, ap);
1572 va_end(ap);
1575 void error(const char *fmt, ...)
1577 TCCState *s1 = tcc_state;
1578 va_list ap;
1580 va_start(ap, fmt);
1581 error1(s1, 0, fmt, ap);
1582 va_end(ap);
1583 /* better than nothing: in some cases, we accept to handle errors */
1584 if (s1->error_set_jmp_enabled) {
1585 longjmp(s1->error_jmp_buf, 1);
1586 } else {
1587 /* XXX: eliminate this someday */
1588 exit(1);
1592 void expect(const char *msg)
1594 error("%s expected", msg);
1597 void warning(const char *fmt, ...)
1599 TCCState *s1 = tcc_state;
1600 va_list ap;
1602 if (s1->warn_none)
1603 return;
1605 va_start(ap, fmt);
1606 error1(s1, 1, fmt, ap);
1607 va_end(ap);
1610 void skip(int c)
1612 if (tok != c)
1613 error("'%c' expected", c);
1614 next();
1617 static void test_lvalue(void)
1619 if (!(vtop->r & VT_LVAL))
1620 expect("lvalue");
1623 /* allocate a new token */
1624 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1626 TokenSym *ts, **ptable;
1627 int i;
1629 if (tok_ident >= SYM_FIRST_ANOM)
1630 error("memory full");
1632 /* expand token table if needed */
1633 i = tok_ident - TOK_IDENT;
1634 if ((i % TOK_ALLOC_INCR) == 0) {
1635 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1636 if (!ptable)
1637 error("memory full");
1638 table_ident = ptable;
1641 ts = tcc_malloc(sizeof(TokenSym) + len);
1642 table_ident[i] = ts;
1643 ts->tok = tok_ident++;
1644 ts->sym_define = NULL;
1645 ts->sym_label = NULL;
1646 ts->sym_struct = NULL;
1647 ts->sym_identifier = NULL;
1648 ts->len = len;
1649 ts->hash_next = NULL;
1650 memcpy(ts->str, str, len);
1651 ts->str[len] = '\0';
1652 *pts = ts;
1653 return ts;
1656 #define TOK_HASH_INIT 1
1657 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1659 /* find a token and add it if not found */
1660 static TokenSym *tok_alloc(const char *str, int len)
1662 TokenSym *ts, **pts;
1663 int i;
1664 unsigned int h;
1666 h = TOK_HASH_INIT;
1667 for(i=0;i<len;i++)
1668 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1669 h &= (TOK_HASH_SIZE - 1);
1671 pts = &hash_ident[h];
1672 for(;;) {
1673 ts = *pts;
1674 if (!ts)
1675 break;
1676 if (ts->len == len && !memcmp(ts->str, str, len))
1677 return ts;
1678 pts = &(ts->hash_next);
1680 return tok_alloc_new(pts, str, len);
1683 /* CString handling */
1685 static void cstr_realloc(CString *cstr, int new_size)
1687 int size;
1688 void *data;
1690 size = cstr->size_allocated;
1691 if (size == 0)
1692 size = 8; /* no need to allocate a too small first string */
1693 while (size < new_size)
1694 size = size * 2;
1695 data = tcc_realloc(cstr->data_allocated, size);
1696 if (!data)
1697 error("memory full");
1698 cstr->data_allocated = data;
1699 cstr->size_allocated = size;
1700 cstr->data = data;
1703 /* add a byte */
1704 static inline void cstr_ccat(CString *cstr, int ch)
1706 int size;
1707 size = cstr->size + 1;
1708 if (size > cstr->size_allocated)
1709 cstr_realloc(cstr, size);
1710 ((unsigned char *)cstr->data)[size - 1] = ch;
1711 cstr->size = size;
1714 static void cstr_cat(CString *cstr, const char *str)
1716 int c;
1717 for(;;) {
1718 c = *str;
1719 if (c == '\0')
1720 break;
1721 cstr_ccat(cstr, c);
1722 str++;
1726 /* add a wide char */
1727 static void cstr_wccat(CString *cstr, int ch)
1729 int size;
1730 size = cstr->size + sizeof(nwchar_t);
1731 if (size > cstr->size_allocated)
1732 cstr_realloc(cstr, size);
1733 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1734 cstr->size = size;
1737 static void cstr_new(CString *cstr)
1739 memset(cstr, 0, sizeof(CString));
1742 /* free string and reset it to NULL */
1743 static void cstr_free(CString *cstr)
1745 tcc_free(cstr->data_allocated);
1746 cstr_new(cstr);
1749 #define cstr_reset(cstr) cstr_free(cstr)
1751 /* XXX: unicode ? */
1752 static void add_char(CString *cstr, int c)
1754 if (c == '\'' || c == '\"' || c == '\\') {
1755 /* XXX: could be more precise if char or string */
1756 cstr_ccat(cstr, '\\');
1758 if (c >= 32 && c <= 126) {
1759 cstr_ccat(cstr, c);
1760 } else {
1761 cstr_ccat(cstr, '\\');
1762 if (c == '\n') {
1763 cstr_ccat(cstr, 'n');
1764 } else {
1765 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1766 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1767 cstr_ccat(cstr, '0' + (c & 7));
1772 /* XXX: buffer overflow */
1773 /* XXX: float tokens */
1774 char *get_tok_str(int v, CValue *cv)
1776 static char buf[STRING_MAX_SIZE + 1];
1777 static CString cstr_buf;
1778 CString *cstr;
1779 unsigned char *q;
1780 char *p;
1781 int i, len;
1783 /* NOTE: to go faster, we give a fixed buffer for small strings */
1784 cstr_reset(&cstr_buf);
1785 cstr_buf.data = buf;
1786 cstr_buf.size_allocated = sizeof(buf);
1787 p = buf;
1789 switch(v) {
1790 case TOK_CINT:
1791 case TOK_CUINT:
1792 /* XXX: not quite exact, but only useful for testing */
1793 sprintf(p, "%u", cv->ui);
1794 break;
1795 case TOK_CLLONG:
1796 case TOK_CULLONG:
1797 /* XXX: not quite exact, but only useful for testing */
1798 sprintf(p, "%Lu", cv->ull);
1799 break;
1800 case TOK_LCHAR:
1801 cstr_ccat(&cstr_buf, 'L');
1802 case TOK_CCHAR:
1803 cstr_ccat(&cstr_buf, '\'');
1804 add_char(&cstr_buf, cv->i);
1805 cstr_ccat(&cstr_buf, '\'');
1806 cstr_ccat(&cstr_buf, '\0');
1807 break;
1808 case TOK_PPNUM:
1809 cstr = cv->cstr;
1810 len = cstr->size - 1;
1811 for(i=0;i<len;i++)
1812 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1813 cstr_ccat(&cstr_buf, '\0');
1814 break;
1815 case TOK_LSTR:
1816 cstr_ccat(&cstr_buf, 'L');
1817 case TOK_STR:
1818 cstr = cv->cstr;
1819 cstr_ccat(&cstr_buf, '\"');
1820 if (v == TOK_STR) {
1821 len = cstr->size - 1;
1822 for(i=0;i<len;i++)
1823 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1824 } else {
1825 len = (cstr->size / sizeof(nwchar_t)) - 1;
1826 for(i=0;i<len;i++)
1827 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1829 cstr_ccat(&cstr_buf, '\"');
1830 cstr_ccat(&cstr_buf, '\0');
1831 break;
1832 case TOK_LT:
1833 v = '<';
1834 goto addv;
1835 case TOK_GT:
1836 v = '>';
1837 goto addv;
1838 case TOK_DOTS:
1839 return strcpy(p, "...");
1840 case TOK_A_SHL:
1841 return strcpy(p, "<<=");
1842 case TOK_A_SAR:
1843 return strcpy(p, ">>=");
1844 default:
1845 if (v < TOK_IDENT) {
1846 /* search in two bytes table */
1847 q = tok_two_chars;
1848 while (*q) {
1849 if (q[2] == v) {
1850 *p++ = q[0];
1851 *p++ = q[1];
1852 *p = '\0';
1853 return buf;
1855 q += 3;
1857 addv:
1858 *p++ = v;
1859 *p = '\0';
1860 } else if (v < tok_ident) {
1861 return table_ident[v - TOK_IDENT]->str;
1862 } else if (v >= SYM_FIRST_ANOM) {
1863 /* special name for anonymous symbol */
1864 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1865 } else {
1866 /* should never happen */
1867 return NULL;
1869 break;
1871 return cstr_buf.data;
1874 /* push, without hashing */
1875 static Sym *sym_push2(Sym **ps, int v, int t, long c)
1877 Sym *s;
1878 s = sym_malloc();
1879 s->v = v;
1880 s->type.t = t;
1881 s->c = c;
1882 s->next = NULL;
1883 /* add in stack */
1884 s->prev = *ps;
1885 *ps = s;
1886 return s;
1889 /* find a symbol and return its associated structure. 's' is the top
1890 of the symbol stack */
1891 static Sym *sym_find2(Sym *s, int v)
1893 while (s) {
1894 if (s->v == v)
1895 return s;
1896 s = s->prev;
1898 return NULL;
1901 /* structure lookup */
1902 static inline Sym *struct_find(int v)
1904 v -= TOK_IDENT;
1905 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1906 return NULL;
1907 return table_ident[v]->sym_struct;
1910 /* find an identifier */
1911 static inline Sym *sym_find(int v)
1913 v -= TOK_IDENT;
1914 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1915 return NULL;
1916 return table_ident[v]->sym_identifier;
1919 /* push a given symbol on the symbol stack */
1920 static Sym *sym_push(int v, CType *type, int r, int c)
1922 Sym *s, **ps;
1923 TokenSym *ts;
1925 if (local_stack)
1926 ps = &local_stack;
1927 else
1928 ps = &global_stack;
1929 s = sym_push2(ps, v, type->t, c);
1930 s->type.ref = type->ref;
1931 s->r = r;
1932 /* don't record fields or anonymous symbols */
1933 /* XXX: simplify */
1934 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1935 /* record symbol in token array */
1936 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1937 if (v & SYM_STRUCT)
1938 ps = &ts->sym_struct;
1939 else
1940 ps = &ts->sym_identifier;
1941 s->prev_tok = *ps;
1942 *ps = s;
1944 return s;
1947 /* push a global identifier */
1948 static Sym *global_identifier_push(int v, int t, int c)
1950 Sym *s, **ps;
1951 s = sym_push2(&global_stack, v, t, c);
1952 /* don't record anonymous symbol */
1953 if (v < SYM_FIRST_ANOM) {
1954 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1955 /* modify the top most local identifier, so that
1956 sym_identifier will point to 's' when popped */
1957 while (*ps != NULL)
1958 ps = &(*ps)->prev_tok;
1959 s->prev_tok = NULL;
1960 *ps = s;
1962 return s;
1965 /* pop symbols until top reaches 'b' */
1966 static void sym_pop(Sym **ptop, Sym *b)
1968 Sym *s, *ss, **ps;
1969 TokenSym *ts;
1970 int v;
1972 s = *ptop;
1973 while(s != b) {
1974 ss = s->prev;
1975 v = s->v;
1976 /* remove symbol in token array */
1977 /* XXX: simplify */
1978 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1979 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1980 if (v & SYM_STRUCT)
1981 ps = &ts->sym_struct;
1982 else
1983 ps = &ts->sym_identifier;
1984 *ps = s->prev_tok;
1986 sym_free(s);
1987 s = ss;
1989 *ptop = b;
1992 /* I/O layer */
1994 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1996 int fd;
1997 BufferedFile *bf;
1999 if (strcmp(filename, "-") == 0)
2000 fd = 0, filename = "stdin";
2001 else
2002 fd = open(filename, O_RDONLY | O_BINARY);
2003 if ((verbose == 2 && fd >= 0) || verbose == 3)
2004 printf("%s %*s%s\n", fd < 0 ? "nf":"->",
2005 (s1->include_stack_ptr - s1->include_stack), "", filename);
2006 if (fd < 0)
2007 return NULL;
2008 bf = tcc_malloc(sizeof(BufferedFile));
2009 bf->fd = fd;
2010 bf->buf_ptr = bf->buffer;
2011 bf->buf_end = bf->buffer;
2012 bf->buffer[0] = CH_EOB; /* put eob symbol */
2013 pstrcpy(bf->filename, sizeof(bf->filename), filename);
2014 #ifdef _WIN32
2015 normalize_slashes(bf->filename);
2016 #endif
2017 bf->line_num = 1;
2018 bf->ifndef_macro = 0;
2019 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
2020 // printf("opening '%s'\n", filename);
2021 return bf;
2024 void tcc_close(BufferedFile *bf)
2026 total_lines += bf->line_num;
2027 close(bf->fd);
2028 tcc_free(bf);
2031 /* fill input buffer and peek next char */
2032 static int tcc_peekc_slow(BufferedFile *bf)
2034 int len;
2035 /* only tries to read if really end of buffer */
2036 if (bf->buf_ptr >= bf->buf_end) {
2037 if (bf->fd != -1) {
2038 #if defined(PARSE_DEBUG)
2039 len = 8;
2040 #else
2041 len = IO_BUF_SIZE;
2042 #endif
2043 len = read(bf->fd, bf->buffer, len);
2044 if (len < 0)
2045 len = 0;
2046 } else {
2047 len = 0;
2049 total_bytes += len;
2050 bf->buf_ptr = bf->buffer;
2051 bf->buf_end = bf->buffer + len;
2052 *bf->buf_end = CH_EOB;
2054 if (bf->buf_ptr < bf->buf_end) {
2055 return bf->buf_ptr[0];
2056 } else {
2057 bf->buf_ptr = bf->buf_end;
2058 return CH_EOF;
2062 /* return the current character, handling end of block if necessary
2063 (but not stray) */
2064 static int handle_eob(void)
2066 return tcc_peekc_slow(file);
2069 /* read next char from current input file and handle end of input buffer */
2070 static inline void inp(void)
2072 ch = *(++(file->buf_ptr));
2073 /* end of buffer/file handling */
2074 if (ch == CH_EOB)
2075 ch = handle_eob();
2078 /* handle '\[\r]\n' */
2079 static int handle_stray_noerror(void)
2081 while (ch == '\\') {
2082 inp();
2083 if (ch == '\n') {
2084 file->line_num++;
2085 inp();
2086 } else if (ch == '\r') {
2087 inp();
2088 if (ch != '\n')
2089 goto fail;
2090 file->line_num++;
2091 inp();
2092 } else {
2093 fail:
2094 return 1;
2097 return 0;
2100 static void handle_stray(void)
2102 if (handle_stray_noerror())
2103 error("stray '\\' in program");
2106 /* skip the stray and handle the \\n case. Output an error if
2107 incorrect char after the stray */
2108 static int handle_stray1(uint8_t *p)
2110 int c;
2112 if (p >= file->buf_end) {
2113 file->buf_ptr = p;
2114 c = handle_eob();
2115 p = file->buf_ptr;
2116 if (c == '\\')
2117 goto parse_stray;
2118 } else {
2119 parse_stray:
2120 file->buf_ptr = p;
2121 ch = *p;
2122 handle_stray();
2123 p = file->buf_ptr;
2124 c = *p;
2126 return c;
2129 /* handle just the EOB case, but not stray */
2130 #define PEEKC_EOB(c, p)\
2132 p++;\
2133 c = *p;\
2134 if (c == '\\') {\
2135 file->buf_ptr = p;\
2136 c = handle_eob();\
2137 p = file->buf_ptr;\
2141 /* handle the complicated stray case */
2142 #define PEEKC(c, p)\
2144 p++;\
2145 c = *p;\
2146 if (c == '\\') {\
2147 c = handle_stray1(p);\
2148 p = file->buf_ptr;\
2152 /* input with '\[\r]\n' handling. Note that this function cannot
2153 handle other characters after '\', so you cannot call it inside
2154 strings or comments */
2155 static void minp(void)
2157 inp();
2158 if (ch == '\\')
2159 handle_stray();
2163 /* single line C++ comments */
2164 static uint8_t *parse_line_comment(uint8_t *p)
2166 int c;
2168 p++;
2169 for(;;) {
2170 c = *p;
2171 redo:
2172 if (c == '\n' || c == CH_EOF) {
2173 break;
2174 } else if (c == '\\') {
2175 file->buf_ptr = p;
2176 c = handle_eob();
2177 p = file->buf_ptr;
2178 if (c == '\\') {
2179 PEEKC_EOB(c, p);
2180 if (c == '\n') {
2181 file->line_num++;
2182 PEEKC_EOB(c, p);
2183 } else if (c == '\r') {
2184 PEEKC_EOB(c, p);
2185 if (c == '\n') {
2186 file->line_num++;
2187 PEEKC_EOB(c, p);
2190 } else {
2191 goto redo;
2193 } else {
2194 p++;
2197 return p;
2200 /* C comments */
2201 static uint8_t *parse_comment(uint8_t *p)
2203 int c;
2205 p++;
2206 for(;;) {
2207 /* fast skip loop */
2208 for(;;) {
2209 c = *p;
2210 if (c == '\n' || c == '*' || c == '\\')
2211 break;
2212 p++;
2213 c = *p;
2214 if (c == '\n' || c == '*' || c == '\\')
2215 break;
2216 p++;
2218 /* now we can handle all the cases */
2219 if (c == '\n') {
2220 file->line_num++;
2221 p++;
2222 } else if (c == '*') {
2223 p++;
2224 for(;;) {
2225 c = *p;
2226 if (c == '*') {
2227 p++;
2228 } else if (c == '/') {
2229 goto end_of_comment;
2230 } else if (c == '\\') {
2231 file->buf_ptr = p;
2232 c = handle_eob();
2233 p = file->buf_ptr;
2234 if (c == '\\') {
2235 /* skip '\[\r]\n', otherwise just skip the stray */
2236 while (c == '\\') {
2237 PEEKC_EOB(c, p);
2238 if (c == '\n') {
2239 file->line_num++;
2240 PEEKC_EOB(c, p);
2241 } else if (c == '\r') {
2242 PEEKC_EOB(c, p);
2243 if (c == '\n') {
2244 file->line_num++;
2245 PEEKC_EOB(c, p);
2247 } else {
2248 goto after_star;
2252 } else {
2253 break;
2256 after_star: ;
2257 } else {
2258 /* stray, eob or eof */
2259 file->buf_ptr = p;
2260 c = handle_eob();
2261 p = file->buf_ptr;
2262 if (c == CH_EOF) {
2263 error("unexpected end of file in comment");
2264 } else if (c == '\\') {
2265 p++;
2269 end_of_comment:
2270 p++;
2271 return p;
2274 #define cinp minp
2276 /* space exlcuding newline */
2277 static inline int is_space(int ch)
2279 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2282 static inline void skip_spaces(void)
2284 while (is_space(ch))
2285 cinp();
2288 /* parse a string without interpreting escapes */
2289 static uint8_t *parse_pp_string(uint8_t *p,
2290 int sep, CString *str)
2292 int c;
2293 p++;
2294 for(;;) {
2295 c = *p;
2296 if (c == sep) {
2297 break;
2298 } else if (c == '\\') {
2299 file->buf_ptr = p;
2300 c = handle_eob();
2301 p = file->buf_ptr;
2302 if (c == CH_EOF) {
2303 unterminated_string:
2304 /* XXX: indicate line number of start of string */
2305 error("missing terminating %c character", sep);
2306 } else if (c == '\\') {
2307 /* escape : just skip \[\r]\n */
2308 PEEKC_EOB(c, p);
2309 if (c == '\n') {
2310 file->line_num++;
2311 p++;
2312 } else if (c == '\r') {
2313 PEEKC_EOB(c, p);
2314 if (c != '\n')
2315 expect("'\n' after '\r'");
2316 file->line_num++;
2317 p++;
2318 } else if (c == CH_EOF) {
2319 goto unterminated_string;
2320 } else {
2321 if (str) {
2322 cstr_ccat(str, '\\');
2323 cstr_ccat(str, c);
2325 p++;
2328 } else if (c == '\n') {
2329 file->line_num++;
2330 goto add_char;
2331 } else if (c == '\r') {
2332 PEEKC_EOB(c, p);
2333 if (c != '\n') {
2334 if (str)
2335 cstr_ccat(str, '\r');
2336 } else {
2337 file->line_num++;
2338 goto add_char;
2340 } else {
2341 add_char:
2342 if (str)
2343 cstr_ccat(str, c);
2344 p++;
2347 p++;
2348 return p;
2351 /* skip block of text until #else, #elif or #endif. skip also pairs of
2352 #if/#endif */
2353 void preprocess_skip(void)
2355 int a, start_of_line, c, in_warn_or_error;
2356 uint8_t *p;
2358 p = file->buf_ptr;
2359 a = 0;
2360 redo_start:
2361 start_of_line = 1;
2362 in_warn_or_error = 0;
2363 for(;;) {
2364 redo_no_start:
2365 c = *p;
2366 switch(c) {
2367 case ' ':
2368 case '\t':
2369 case '\f':
2370 case '\v':
2371 case '\r':
2372 p++;
2373 goto redo_no_start;
2374 case '\n':
2375 file->line_num++;
2376 p++;
2377 goto redo_start;
2378 case '\\':
2379 file->buf_ptr = p;
2380 c = handle_eob();
2381 if (c == CH_EOF) {
2382 expect("#endif");
2383 } else if (c == '\\') {
2384 ch = file->buf_ptr[0];
2385 handle_stray_noerror();
2387 p = file->buf_ptr;
2388 goto redo_no_start;
2389 /* skip strings */
2390 case '\"':
2391 case '\'':
2392 if (in_warn_or_error)
2393 goto _default;
2394 p = parse_pp_string(p, c, NULL);
2395 break;
2396 /* skip comments */
2397 case '/':
2398 if (in_warn_or_error)
2399 goto _default;
2400 file->buf_ptr = p;
2401 ch = *p;
2402 minp();
2403 p = file->buf_ptr;
2404 if (ch == '*') {
2405 p = parse_comment(p);
2406 } else if (ch == '/') {
2407 p = parse_line_comment(p);
2409 break;
2410 case '#':
2411 p++;
2412 if (start_of_line) {
2413 file->buf_ptr = p;
2414 next_nomacro();
2415 p = file->buf_ptr;
2416 if (a == 0 &&
2417 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2418 goto the_end;
2419 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2420 a++;
2421 else if (tok == TOK_ENDIF)
2422 a--;
2423 else if( tok == TOK_ERROR || tok == TOK_WARNING)
2424 in_warn_or_error = 1;
2426 break;
2427 _default:
2428 default:
2429 p++;
2430 break;
2432 start_of_line = 0;
2434 the_end: ;
2435 file->buf_ptr = p;
2438 /* ParseState handling */
2440 /* XXX: currently, no include file info is stored. Thus, we cannot display
2441 accurate messages if the function or data definition spans multiple
2442 files */
2444 /* save current parse state in 's' */
2445 void save_parse_state(ParseState *s)
2447 s->line_num = file->line_num;
2448 s->macro_ptr = macro_ptr;
2449 s->tok = tok;
2450 s->tokc = tokc;
2453 /* restore parse state from 's' */
2454 void restore_parse_state(ParseState *s)
2456 file->line_num = s->line_num;
2457 macro_ptr = s->macro_ptr;
2458 tok = s->tok;
2459 tokc = s->tokc;
2462 /* return the number of additional 'ints' necessary to store the
2463 token */
2464 static inline int tok_ext_size(int t)
2466 switch(t) {
2467 /* 4 bytes */
2468 case TOK_CINT:
2469 case TOK_CUINT:
2470 case TOK_CCHAR:
2471 case TOK_LCHAR:
2472 case TOK_CFLOAT:
2473 case TOK_LINENUM:
2474 return 1;
2475 case TOK_STR:
2476 case TOK_LSTR:
2477 case TOK_PPNUM:
2478 error("unsupported token");
2479 return 1;
2480 case TOK_CDOUBLE:
2481 case TOK_CLLONG:
2482 case TOK_CULLONG:
2483 return 2;
2484 case TOK_CLDOUBLE:
2485 return LDOUBLE_SIZE / 4;
2486 default:
2487 return 0;
2491 /* token string handling */
2493 static inline void tok_str_new(TokenString *s)
2495 s->str = NULL;
2496 s->len = 0;
2497 s->allocated_len = 0;
2498 s->last_line_num = -1;
2501 static void tok_str_free(int *str)
2503 tcc_free(str);
2506 static int *tok_str_realloc(TokenString *s)
2508 int *str, len;
2510 if (s->allocated_len == 0) {
2511 len = 8;
2512 } else {
2513 len = s->allocated_len * 2;
2515 str = tcc_realloc(s->str, len * sizeof(int));
2516 if (!str)
2517 error("memory full");
2518 s->allocated_len = len;
2519 s->str = str;
2520 return str;
2523 static void tok_str_add(TokenString *s, int t)
2525 int len, *str;
2527 len = s->len;
2528 str = s->str;
2529 if (len >= s->allocated_len)
2530 str = tok_str_realloc(s);
2531 str[len++] = t;
2532 s->len = len;
2535 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2537 int len, *str;
2539 len = s->len;
2540 str = s->str;
2542 /* allocate space for worst case */
2543 if (len + TOK_MAX_SIZE > s->allocated_len)
2544 str = tok_str_realloc(s);
2545 str[len++] = t;
2546 switch(t) {
2547 case TOK_CINT:
2548 case TOK_CUINT:
2549 case TOK_CCHAR:
2550 case TOK_LCHAR:
2551 case TOK_CFLOAT:
2552 case TOK_LINENUM:
2553 str[len++] = cv->tab[0];
2554 break;
2555 case TOK_PPNUM:
2556 case TOK_STR:
2557 case TOK_LSTR:
2559 int nb_words;
2560 CString *cstr;
2562 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2563 while ((len + nb_words) > s->allocated_len)
2564 str = tok_str_realloc(s);
2565 cstr = (CString *)(str + len);
2566 cstr->data = NULL;
2567 cstr->size = cv->cstr->size;
2568 cstr->data_allocated = NULL;
2569 cstr->size_allocated = cstr->size;
2570 memcpy((char *)cstr + sizeof(CString),
2571 cv->cstr->data, cstr->size);
2572 len += nb_words;
2574 break;
2575 case TOK_CDOUBLE:
2576 case TOK_CLLONG:
2577 case TOK_CULLONG:
2578 #if LDOUBLE_SIZE == 8
2579 case TOK_CLDOUBLE:
2580 #endif
2581 str[len++] = cv->tab[0];
2582 str[len++] = cv->tab[1];
2583 break;
2584 #if LDOUBLE_SIZE == 12
2585 case TOK_CLDOUBLE:
2586 str[len++] = cv->tab[0];
2587 str[len++] = cv->tab[1];
2588 str[len++] = cv->tab[2];
2589 #elif LDOUBLE_SIZE == 16
2590 case TOK_CLDOUBLE:
2591 str[len++] = cv->tab[0];
2592 str[len++] = cv->tab[1];
2593 str[len++] = cv->tab[2];
2594 str[len++] = cv->tab[3];
2595 #elif LDOUBLE_SIZE != 8
2596 #error add long double size support
2597 #endif
2598 break;
2599 default:
2600 break;
2602 s->len = len;
2605 /* add the current parse token in token string 's' */
2606 static void tok_str_add_tok(TokenString *s)
2608 CValue cval;
2610 /* save line number info */
2611 if (file->line_num != s->last_line_num) {
2612 s->last_line_num = file->line_num;
2613 cval.i = s->last_line_num;
2614 tok_str_add2(s, TOK_LINENUM, &cval);
2616 tok_str_add2(s, tok, &tokc);
2619 #if LDOUBLE_SIZE == 16
2620 #define LDOUBLE_GET(p, cv) \
2621 cv.tab[0] = p[0]; \
2622 cv.tab[1] = p[1]; \
2623 cv.tab[2] = p[2]; \
2624 cv.tab[3] = p[3];
2625 #elif LDOUBLE_SIZE == 12
2626 #define LDOUBLE_GET(p, cv) \
2627 cv.tab[0] = p[0]; \
2628 cv.tab[1] = p[1]; \
2629 cv.tab[2] = p[2];
2630 #elif LDOUBLE_SIZE == 8
2631 #define LDOUBLE_GET(p, cv) \
2632 cv.tab[0] = p[0]; \
2633 cv.tab[1] = p[1];
2634 #else
2635 #error add long double size support
2636 #endif
2639 /* get a token from an integer array and increment pointer
2640 accordingly. we code it as a macro to avoid pointer aliasing. */
2641 #define TOK_GET(t, p, cv) \
2643 t = *p++; \
2644 switch(t) { \
2645 case TOK_CINT: \
2646 case TOK_CUINT: \
2647 case TOK_CCHAR: \
2648 case TOK_LCHAR: \
2649 case TOK_CFLOAT: \
2650 case TOK_LINENUM: \
2651 cv.tab[0] = *p++; \
2652 break; \
2653 case TOK_STR: \
2654 case TOK_LSTR: \
2655 case TOK_PPNUM: \
2656 cv.cstr = (CString *)p; \
2657 cv.cstr->data = (char *)p + sizeof(CString);\
2658 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2659 break; \
2660 case TOK_CDOUBLE: \
2661 case TOK_CLLONG: \
2662 case TOK_CULLONG: \
2663 cv.tab[0] = p[0]; \
2664 cv.tab[1] = p[1]; \
2665 p += 2; \
2666 break; \
2667 case TOK_CLDOUBLE: \
2668 LDOUBLE_GET(p, cv); \
2669 p += LDOUBLE_SIZE / 4; \
2670 break; \
2671 default: \
2672 break; \
2676 /* defines handling */
2677 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2679 Sym *s;
2681 s = sym_push2(&define_stack, v, macro_type, (long)str);
2682 s->next = first_arg;
2683 table_ident[v - TOK_IDENT]->sym_define = s;
2686 /* undefined a define symbol. Its name is just set to zero */
2687 static void define_undef(Sym *s)
2689 int v;
2690 v = s->v;
2691 if (v >= TOK_IDENT && v < tok_ident)
2692 table_ident[v - TOK_IDENT]->sym_define = NULL;
2693 s->v = 0;
2696 static inline Sym *define_find(int v)
2698 v -= TOK_IDENT;
2699 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2700 return NULL;
2701 return table_ident[v]->sym_define;
2704 /* free define stack until top reaches 'b' */
2705 static void free_defines(Sym *b)
2707 Sym *top, *top1;
2708 int v;
2710 top = define_stack;
2711 while (top != b) {
2712 top1 = top->prev;
2713 /* do not free args or predefined defines */
2714 if (top->c)
2715 tok_str_free((int *)top->c);
2716 v = top->v;
2717 if (v >= TOK_IDENT && v < tok_ident)
2718 table_ident[v - TOK_IDENT]->sym_define = NULL;
2719 sym_free(top);
2720 top = top1;
2722 define_stack = b;
2725 /* label lookup */
2726 static Sym *label_find(int v)
2728 v -= TOK_IDENT;
2729 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2730 return NULL;
2731 return table_ident[v]->sym_label;
2734 static Sym *label_push(Sym **ptop, int v, int flags)
2736 Sym *s, **ps;
2737 s = sym_push2(ptop, v, 0, 0);
2738 s->r = flags;
2739 ps = &table_ident[v - TOK_IDENT]->sym_label;
2740 if (ptop == &global_label_stack) {
2741 /* modify the top most local identifier, so that
2742 sym_identifier will point to 's' when popped */
2743 while (*ps != NULL)
2744 ps = &(*ps)->prev_tok;
2746 s->prev_tok = *ps;
2747 *ps = s;
2748 return s;
2751 /* pop labels until element last is reached. Look if any labels are
2752 undefined. Define symbols if '&&label' was used. */
2753 static void label_pop(Sym **ptop, Sym *slast)
2755 Sym *s, *s1;
2756 for(s = *ptop; s != slast; s = s1) {
2757 s1 = s->prev;
2758 if (s->r == LABEL_DECLARED) {
2759 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2760 } else if (s->r == LABEL_FORWARD) {
2761 error("label '%s' used but not defined",
2762 get_tok_str(s->v, NULL));
2763 } else {
2764 if (s->c) {
2765 /* define corresponding symbol. A size of
2766 1 is put. */
2767 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2770 /* remove label */
2771 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2772 sym_free(s);
2774 *ptop = slast;
2777 /* eval an expression for #if/#elif */
2778 static int expr_preprocess(void)
2780 int c, t;
2781 TokenString str;
2783 tok_str_new(&str);
2784 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2785 next(); /* do macro subst */
2786 if (tok == TOK_DEFINED) {
2787 next_nomacro();
2788 t = tok;
2789 if (t == '(')
2790 next_nomacro();
2791 c = define_find(tok) != 0;
2792 if (t == '(')
2793 next_nomacro();
2794 tok = TOK_CINT;
2795 tokc.i = c;
2796 } else if (tok >= TOK_IDENT) {
2797 /* if undefined macro */
2798 tok = TOK_CINT;
2799 tokc.i = 0;
2801 tok_str_add_tok(&str);
2803 tok_str_add(&str, -1); /* simulate end of file */
2804 tok_str_add(&str, 0);
2805 /* now evaluate C constant expression */
2806 macro_ptr = str.str;
2807 next();
2808 c = expr_const();
2809 macro_ptr = NULL;
2810 tok_str_free(str.str);
2811 return c != 0;
2814 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2815 static void tok_print(int *str)
2817 int t;
2818 CValue cval;
2820 while (1) {
2821 TOK_GET(t, str, cval);
2822 if (!t)
2823 break;
2824 printf(" %s", get_tok_str(t, &cval));
2826 printf("\n");
2828 #endif
2830 /* parse after #define */
2831 static void parse_define(void)
2833 Sym *s, *first, **ps;
2834 int v, t, varg, is_vaargs, c;
2835 TokenString str;
2837 v = tok;
2838 if (v < TOK_IDENT)
2839 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2840 /* XXX: should check if same macro (ANSI) */
2841 first = NULL;
2842 t = MACRO_OBJ;
2843 /* '(' must be just after macro definition for MACRO_FUNC */
2844 c = file->buf_ptr[0];
2845 if (c == '\\')
2846 c = handle_stray1(file->buf_ptr);
2847 if (c == '(') {
2848 next_nomacro();
2849 next_nomacro();
2850 ps = &first;
2851 while (tok != ')') {
2852 varg = tok;
2853 next_nomacro();
2854 is_vaargs = 0;
2855 if (varg == TOK_DOTS) {
2856 varg = TOK___VA_ARGS__;
2857 is_vaargs = 1;
2858 } else if (tok == TOK_DOTS && gnu_ext) {
2859 is_vaargs = 1;
2860 next_nomacro();
2862 if (varg < TOK_IDENT)
2863 error("badly punctuated parameter list");
2864 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2865 *ps = s;
2866 ps = &s->next;
2867 if (tok != ',')
2868 break;
2869 next_nomacro();
2871 t = MACRO_FUNC;
2873 tok_str_new(&str);
2874 next_nomacro();
2875 /* EOF testing necessary for '-D' handling */
2876 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2877 tok_str_add2(&str, tok, &tokc);
2878 next_nomacro();
2880 tok_str_add(&str, 0);
2881 #ifdef PP_DEBUG
2882 printf("define %s %d: ", get_tok_str(v, NULL), t);
2883 tok_print(str.str);
2884 #endif
2885 define_push(v, t, str.str, first);
2888 static inline int hash_cached_include(int type, const char *filename)
2890 const unsigned char *s;
2891 unsigned int h;
2893 h = TOK_HASH_INIT;
2894 h = TOK_HASH_FUNC(h, type);
2895 s = filename;
2896 while (*s) {
2897 h = TOK_HASH_FUNC(h, *s);
2898 s++;
2900 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2901 return h;
2904 /* XXX: use a token or a hash table to accelerate matching ? */
2905 static CachedInclude *search_cached_include(TCCState *s1,
2906 int type, const char *filename)
2908 CachedInclude *e;
2909 int i, h;
2910 h = hash_cached_include(type, filename);
2911 i = s1->cached_includes_hash[h];
2912 for(;;) {
2913 if (i == 0)
2914 break;
2915 e = s1->cached_includes[i - 1];
2916 if (e->type == type && !PATHCMP(e->filename, filename))
2917 return e;
2918 i = e->hash_next;
2920 return NULL;
2923 static inline void add_cached_include(TCCState *s1, int type,
2924 const char *filename, int ifndef_macro)
2926 CachedInclude *e;
2927 int h;
2929 if (search_cached_include(s1, type, filename))
2930 return;
2931 #ifdef INC_DEBUG
2932 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2933 #endif
2934 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2935 if (!e)
2936 return;
2937 e->type = type;
2938 strcpy(e->filename, filename);
2939 e->ifndef_macro = ifndef_macro;
2940 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2941 /* add in hash table */
2942 h = hash_cached_include(type, filename);
2943 e->hash_next = s1->cached_includes_hash[h];
2944 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2947 static void pragma_parse(TCCState *s1)
2949 int val;
2951 next();
2952 if (tok == TOK_pack) {
2954 This may be:
2955 #pragma pack(1) // set
2956 #pragma pack() // reset to default
2957 #pragma pack(push,1) // push & set
2958 #pragma pack(pop) // restore previous
2960 next();
2961 skip('(');
2962 if (tok == TOK_ASM_pop) {
2963 next();
2964 if (s1->pack_stack_ptr <= s1->pack_stack) {
2965 stk_error:
2966 error("out of pack stack");
2968 s1->pack_stack_ptr--;
2969 } else {
2970 val = 0;
2971 if (tok != ')') {
2972 if (tok == TOK_ASM_push) {
2973 next();
2974 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2975 goto stk_error;
2976 s1->pack_stack_ptr++;
2977 skip(',');
2979 if (tok != TOK_CINT) {
2980 pack_error:
2981 error("invalid pack pragma");
2983 val = tokc.i;
2984 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2985 goto pack_error;
2986 next();
2988 *s1->pack_stack_ptr = val;
2989 skip(')');
2994 /* is_bof is true if first non space token at beginning of file */
2995 static void preprocess(int is_bof)
2997 TCCState *s1 = tcc_state;
2998 int size, i, c, n, saved_parse_flags;
2999 char buf[1024], *q;
3000 char buf1[1024];
3001 BufferedFile *f;
3002 Sym *s;
3003 CachedInclude *e;
3005 saved_parse_flags = parse_flags;
3006 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
3007 PARSE_FLAG_LINEFEED;
3008 next_nomacro();
3009 redo:
3010 switch(tok) {
3011 case TOK_DEFINE:
3012 next_nomacro();
3013 parse_define();
3014 break;
3015 case TOK_UNDEF:
3016 next_nomacro();
3017 s = define_find(tok);
3018 /* undefine symbol by putting an invalid name */
3019 if (s)
3020 define_undef(s);
3021 break;
3022 case TOK_INCLUDE:
3023 case TOK_INCLUDE_NEXT:
3024 ch = file->buf_ptr[0];
3025 /* XXX: incorrect if comments : use next_nomacro with a special mode */
3026 skip_spaces();
3027 if (ch == '<') {
3028 c = '>';
3029 goto read_name;
3030 } else if (ch == '\"') {
3031 c = ch;
3032 read_name:
3033 inp();
3034 q = buf;
3035 while (ch != c && ch != '\n' && ch != CH_EOF) {
3036 if ((q - buf) < sizeof(buf) - 1)
3037 *q++ = ch;
3038 if (ch == '\\') {
3039 if (handle_stray_noerror() == 0)
3040 --q;
3041 } else
3042 inp();
3044 *q = '\0';
3045 minp();
3046 #if 0
3047 /* eat all spaces and comments after include */
3048 /* XXX: slightly incorrect */
3049 while (ch1 != '\n' && ch1 != CH_EOF)
3050 inp();
3051 #endif
3052 } else {
3053 /* computed #include : either we have only strings or
3054 we have anything enclosed in '<>' */
3055 next();
3056 buf[0] = '\0';
3057 if (tok == TOK_STR) {
3058 while (tok != TOK_LINEFEED) {
3059 if (tok != TOK_STR) {
3060 include_syntax:
3061 error("'#include' expects \"FILENAME\" or <FILENAME>");
3063 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
3064 next();
3066 c = '\"';
3067 } else {
3068 int len;
3069 while (tok != TOK_LINEFEED) {
3070 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
3071 next();
3073 len = strlen(buf);
3074 /* check syntax and remove '<>' */
3075 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
3076 goto include_syntax;
3077 memmove(buf, buf + 1, len - 2);
3078 buf[len - 2] = '\0';
3079 c = '>';
3083 e = search_cached_include(s1, c, buf);
3084 if (e && define_find(e->ifndef_macro)) {
3085 /* no need to parse the include because the 'ifndef macro'
3086 is defined */
3087 #ifdef INC_DEBUG
3088 printf("%s: skipping %s\n", file->filename, buf);
3089 #endif
3090 } else {
3091 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
3092 error("#include recursion too deep");
3093 /* push current file in stack */
3094 /* XXX: fix current line init */
3095 *s1->include_stack_ptr++ = file;
3097 /* check absolute include path */
3098 if (IS_ABSPATH(buf)) {
3099 f = tcc_open(s1, buf);
3100 if (f)
3101 goto found;
3103 if (c == '\"') {
3104 /* first search in current dir if "header.h" */
3105 size = tcc_basename(file->filename) - file->filename;
3106 if (size > sizeof(buf1) - 1)
3107 size = sizeof(buf1) - 1;
3108 memcpy(buf1, file->filename, size);
3109 buf1[size] = '\0';
3110 pstrcat(buf1, sizeof(buf1), buf);
3111 f = tcc_open(s1, buf1);
3112 if (f) {
3113 if (tok == TOK_INCLUDE_NEXT)
3114 tok = TOK_INCLUDE;
3115 else
3116 goto found;
3119 /* now search in all the include paths */
3120 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
3121 for(i = 0; i < n; i++) {
3122 const char *path;
3123 if (i < s1->nb_include_paths)
3124 path = s1->include_paths[i];
3125 else
3126 path = s1->sysinclude_paths[i - s1->nb_include_paths];
3127 pstrcpy(buf1, sizeof(buf1), path);
3128 pstrcat(buf1, sizeof(buf1), "/");
3129 pstrcat(buf1, sizeof(buf1), buf);
3130 f = tcc_open(s1, buf1);
3131 if (f) {
3132 if (tok == TOK_INCLUDE_NEXT)
3133 tok = TOK_INCLUDE;
3134 else
3135 goto found;
3138 --s1->include_stack_ptr;
3139 error("include file '%s' not found", buf);
3140 break;
3141 found:
3142 #ifdef INC_DEBUG
3143 printf("%s: including %s\n", file->filename, buf1);
3144 #endif
3145 f->inc_type = c;
3146 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
3147 file = f;
3148 /* add include file debug info */
3149 if (do_debug) {
3150 put_stabs(file->filename, N_BINCL, 0, 0, 0);
3152 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
3153 ch = file->buf_ptr[0];
3154 goto the_end;
3156 break;
3157 case TOK_IFNDEF:
3158 c = 1;
3159 goto do_ifdef;
3160 case TOK_IF:
3161 c = expr_preprocess();
3162 goto do_if;
3163 case TOK_IFDEF:
3164 c = 0;
3165 do_ifdef:
3166 next_nomacro();
3167 if (tok < TOK_IDENT)
3168 error("invalid argument for '#if%sdef'", c ? "n" : "");
3169 if (is_bof) {
3170 if (c) {
3171 #ifdef INC_DEBUG
3172 printf("#ifndef %s\n", get_tok_str(tok, NULL));
3173 #endif
3174 file->ifndef_macro = tok;
3177 c = (define_find(tok) != 0) ^ c;
3178 do_if:
3179 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
3180 error("memory full");
3181 *s1->ifdef_stack_ptr++ = c;
3182 goto test_skip;
3183 case TOK_ELSE:
3184 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3185 error("#else without matching #if");
3186 if (s1->ifdef_stack_ptr[-1] & 2)
3187 error("#else after #else");
3188 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3189 goto test_skip;
3190 case TOK_ELIF:
3191 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3192 error("#elif without matching #if");
3193 c = s1->ifdef_stack_ptr[-1];
3194 if (c > 1)
3195 error("#elif after #else");
3196 /* last #if/#elif expression was true: we skip */
3197 if (c == 1)
3198 goto skip;
3199 c = expr_preprocess();
3200 s1->ifdef_stack_ptr[-1] = c;
3201 test_skip:
3202 if (!(c & 1)) {
3203 skip:
3204 preprocess_skip();
3205 is_bof = 0;
3206 goto redo;
3208 break;
3209 case TOK_ENDIF:
3210 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3211 error("#endif without matching #if");
3212 s1->ifdef_stack_ptr--;
3213 /* '#ifndef macro' was at the start of file. Now we check if
3214 an '#endif' is exactly at the end of file */
3215 if (file->ifndef_macro &&
3216 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3217 file->ifndef_macro_saved = file->ifndef_macro;
3218 /* need to set to zero to avoid false matches if another
3219 #ifndef at middle of file */
3220 file->ifndef_macro = 0;
3221 while (tok != TOK_LINEFEED)
3222 next_nomacro();
3223 tok_flags |= TOK_FLAG_ENDIF;
3224 goto the_end;
3226 break;
3227 case TOK_LINE:
3228 next();
3229 if (tok != TOK_CINT)
3230 error("#line");
3231 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3232 next();
3233 if (tok != TOK_LINEFEED) {
3234 if (tok != TOK_STR)
3235 error("#line");
3236 pstrcpy(file->filename, sizeof(file->filename),
3237 (char *)tokc.cstr->data);
3239 break;
3240 case TOK_ERROR:
3241 case TOK_WARNING:
3242 c = tok;
3243 ch = file->buf_ptr[0];
3244 skip_spaces();
3245 q = buf;
3246 while (ch != '\n' && ch != CH_EOF) {
3247 if ((q - buf) < sizeof(buf) - 1)
3248 *q++ = ch;
3249 if (ch == '\\') {
3250 if (handle_stray_noerror() == 0)
3251 --q;
3252 } else
3253 inp();
3255 *q = '\0';
3256 if (c == TOK_ERROR)
3257 error("#error %s", buf);
3258 else
3259 warning("#warning %s", buf);
3260 break;
3261 case TOK_PRAGMA:
3262 pragma_parse(s1);
3263 break;
3264 default:
3265 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3266 /* '!' is ignored to allow C scripts. numbers are ignored
3267 to emulate cpp behaviour */
3268 } else {
3269 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3270 warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
3272 break;
3274 /* ignore other preprocess commands or #! for C scripts */
3275 while (tok != TOK_LINEFEED)
3276 next_nomacro();
3277 the_end:
3278 parse_flags = saved_parse_flags;
3281 /* evaluate escape codes in a string. */
3282 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3284 int c, n;
3285 const uint8_t *p;
3287 p = buf;
3288 for(;;) {
3289 c = *p;
3290 if (c == '\0')
3291 break;
3292 if (c == '\\') {
3293 p++;
3294 /* escape */
3295 c = *p;
3296 switch(c) {
3297 case '0': case '1': case '2': case '3':
3298 case '4': case '5': case '6': case '7':
3299 /* at most three octal digits */
3300 n = c - '0';
3301 p++;
3302 c = *p;
3303 if (isoct(c)) {
3304 n = n * 8 + c - '0';
3305 p++;
3306 c = *p;
3307 if (isoct(c)) {
3308 n = n * 8 + c - '0';
3309 p++;
3312 c = n;
3313 goto add_char_nonext;
3314 case 'x':
3315 case 'u':
3316 case 'U':
3317 p++;
3318 n = 0;
3319 for(;;) {
3320 c = *p;
3321 if (c >= 'a' && c <= 'f')
3322 c = c - 'a' + 10;
3323 else if (c >= 'A' && c <= 'F')
3324 c = c - 'A' + 10;
3325 else if (isnum(c))
3326 c = c - '0';
3327 else
3328 break;
3329 n = n * 16 + c;
3330 p++;
3332 c = n;
3333 goto add_char_nonext;
3334 case 'a':
3335 c = '\a';
3336 break;
3337 case 'b':
3338 c = '\b';
3339 break;
3340 case 'f':
3341 c = '\f';
3342 break;
3343 case 'n':
3344 c = '\n';
3345 break;
3346 case 'r':
3347 c = '\r';
3348 break;
3349 case 't':
3350 c = '\t';
3351 break;
3352 case 'v':
3353 c = '\v';
3354 break;
3355 case 'e':
3356 if (!gnu_ext)
3357 goto invalid_escape;
3358 c = 27;
3359 break;
3360 case '\'':
3361 case '\"':
3362 case '\\':
3363 case '?':
3364 break;
3365 default:
3366 invalid_escape:
3367 if (c >= '!' && c <= '~')
3368 warning("unknown escape sequence: \'\\%c\'", c);
3369 else
3370 warning("unknown escape sequence: \'\\x%x\'", c);
3371 break;
3374 p++;
3375 add_char_nonext:
3376 if (!is_long)
3377 cstr_ccat(outstr, c);
3378 else
3379 cstr_wccat(outstr, c);
3381 /* add a trailing '\0' */
3382 if (!is_long)
3383 cstr_ccat(outstr, '\0');
3384 else
3385 cstr_wccat(outstr, '\0');
3388 /* we use 64 bit numbers */
3389 #define BN_SIZE 2
3391 /* bn = (bn << shift) | or_val */
3392 void bn_lshift(unsigned int *bn, int shift, int or_val)
3394 int i;
3395 unsigned int v;
3396 for(i=0;i<BN_SIZE;i++) {
3397 v = bn[i];
3398 bn[i] = (v << shift) | or_val;
3399 or_val = v >> (32 - shift);
3403 void bn_zero(unsigned int *bn)
3405 int i;
3406 for(i=0;i<BN_SIZE;i++) {
3407 bn[i] = 0;
3411 /* parse number in null terminated string 'p' and return it in the
3412 current token */
3413 void parse_number(const char *p)
3415 int b, t, shift, frac_bits, s, exp_val, ch;
3416 char *q;
3417 unsigned int bn[BN_SIZE];
3418 double d;
3420 /* number */
3421 q = token_buf;
3422 ch = *p++;
3423 t = ch;
3424 ch = *p++;
3425 *q++ = t;
3426 b = 10;
3427 if (t == '.') {
3428 goto float_frac_parse;
3429 } else if (t == '0') {
3430 if (ch == 'x' || ch == 'X') {
3431 q--;
3432 ch = *p++;
3433 b = 16;
3434 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3435 q--;
3436 ch = *p++;
3437 b = 2;
3440 /* parse all digits. cannot check octal numbers at this stage
3441 because of floating point constants */
3442 while (1) {
3443 if (ch >= 'a' && ch <= 'f')
3444 t = ch - 'a' + 10;
3445 else if (ch >= 'A' && ch <= 'F')
3446 t = ch - 'A' + 10;
3447 else if (isnum(ch))
3448 t = ch - '0';
3449 else
3450 break;
3451 if (t >= b)
3452 break;
3453 if (q >= token_buf + STRING_MAX_SIZE) {
3454 num_too_long:
3455 error("number too long");
3457 *q++ = ch;
3458 ch = *p++;
3460 if (ch == '.' ||
3461 ((ch == 'e' || ch == 'E') && b == 10) ||
3462 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3463 if (b != 10) {
3464 /* NOTE: strtox should support that for hexa numbers, but
3465 non ISOC99 libcs do not support it, so we prefer to do
3466 it by hand */
3467 /* hexadecimal or binary floats */
3468 /* XXX: handle overflows */
3469 *q = '\0';
3470 if (b == 16)
3471 shift = 4;
3472 else
3473 shift = 2;
3474 bn_zero(bn);
3475 q = token_buf;
3476 while (1) {
3477 t = *q++;
3478 if (t == '\0') {
3479 break;
3480 } else if (t >= 'a') {
3481 t = t - 'a' + 10;
3482 } else if (t >= 'A') {
3483 t = t - 'A' + 10;
3484 } else {
3485 t = t - '0';
3487 bn_lshift(bn, shift, t);
3489 frac_bits = 0;
3490 if (ch == '.') {
3491 ch = *p++;
3492 while (1) {
3493 t = ch;
3494 if (t >= 'a' && t <= 'f') {
3495 t = t - 'a' + 10;
3496 } else if (t >= 'A' && t <= 'F') {
3497 t = t - 'A' + 10;
3498 } else if (t >= '0' && t <= '9') {
3499 t = t - '0';
3500 } else {
3501 break;
3503 if (t >= b)
3504 error("invalid digit");
3505 bn_lshift(bn, shift, t);
3506 frac_bits += shift;
3507 ch = *p++;
3510 if (ch != 'p' && ch != 'P')
3511 expect("exponent");
3512 ch = *p++;
3513 s = 1;
3514 exp_val = 0;
3515 if (ch == '+') {
3516 ch = *p++;
3517 } else if (ch == '-') {
3518 s = -1;
3519 ch = *p++;
3521 if (ch < '0' || ch > '9')
3522 expect("exponent digits");
3523 while (ch >= '0' && ch <= '9') {
3524 exp_val = exp_val * 10 + ch - '0';
3525 ch = *p++;
3527 exp_val = exp_val * s;
3529 /* now we can generate the number */
3530 /* XXX: should patch directly float number */
3531 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3532 d = ldexp(d, exp_val - frac_bits);
3533 t = toup(ch);
3534 if (t == 'F') {
3535 ch = *p++;
3536 tok = TOK_CFLOAT;
3537 /* float : should handle overflow */
3538 tokc.f = (float)d;
3539 } else if (t == 'L') {
3540 ch = *p++;
3541 tok = TOK_CLDOUBLE;
3542 /* XXX: not large enough */
3543 tokc.ld = (long double)d;
3544 } else {
3545 tok = TOK_CDOUBLE;
3546 tokc.d = d;
3548 } else {
3549 /* decimal floats */
3550 if (ch == '.') {
3551 if (q >= token_buf + STRING_MAX_SIZE)
3552 goto num_too_long;
3553 *q++ = ch;
3554 ch = *p++;
3555 float_frac_parse:
3556 while (ch >= '0' && ch <= '9') {
3557 if (q >= token_buf + STRING_MAX_SIZE)
3558 goto num_too_long;
3559 *q++ = ch;
3560 ch = *p++;
3563 if (ch == 'e' || ch == 'E') {
3564 if (q >= token_buf + STRING_MAX_SIZE)
3565 goto num_too_long;
3566 *q++ = ch;
3567 ch = *p++;
3568 if (ch == '-' || ch == '+') {
3569 if (q >= token_buf + STRING_MAX_SIZE)
3570 goto num_too_long;
3571 *q++ = ch;
3572 ch = *p++;
3574 if (ch < '0' || ch > '9')
3575 expect("exponent digits");
3576 while (ch >= '0' && ch <= '9') {
3577 if (q >= token_buf + STRING_MAX_SIZE)
3578 goto num_too_long;
3579 *q++ = ch;
3580 ch = *p++;
3583 *q = '\0';
3584 t = toup(ch);
3585 errno = 0;
3586 if (t == 'F') {
3587 ch = *p++;
3588 tok = TOK_CFLOAT;
3589 tokc.f = strtof(token_buf, NULL);
3590 } else if (t == 'L') {
3591 ch = *p++;
3592 tok = TOK_CLDOUBLE;
3593 tokc.ld = strtold(token_buf, NULL);
3594 } else {
3595 tok = TOK_CDOUBLE;
3596 tokc.d = strtod(token_buf, NULL);
3599 } else {
3600 unsigned long long n, n1;
3601 int lcount, ucount;
3603 /* integer number */
3604 *q = '\0';
3605 q = token_buf;
3606 if (b == 10 && *q == '0') {
3607 b = 8;
3608 q++;
3610 n = 0;
3611 while(1) {
3612 t = *q++;
3613 /* no need for checks except for base 10 / 8 errors */
3614 if (t == '\0') {
3615 break;
3616 } else if (t >= 'a') {
3617 t = t - 'a' + 10;
3618 } else if (t >= 'A') {
3619 t = t - 'A' + 10;
3620 } else {
3621 t = t - '0';
3622 if (t >= b)
3623 error("invalid digit");
3625 n1 = n;
3626 n = n * b + t;
3627 /* detect overflow */
3628 /* XXX: this test is not reliable */
3629 if (n < n1)
3630 error("integer constant overflow");
3633 /* XXX: not exactly ANSI compliant */
3634 if ((n & 0xffffffff00000000LL) != 0) {
3635 if ((n >> 63) != 0)
3636 tok = TOK_CULLONG;
3637 else
3638 tok = TOK_CLLONG;
3639 } else if (n > 0x7fffffff) {
3640 tok = TOK_CUINT;
3641 } else {
3642 tok = TOK_CINT;
3644 lcount = 0;
3645 ucount = 0;
3646 for(;;) {
3647 t = toup(ch);
3648 if (t == 'L') {
3649 if (lcount >= 2)
3650 error("three 'l's in integer constant");
3651 lcount++;
3652 if (lcount == 2) {
3653 if (tok == TOK_CINT)
3654 tok = TOK_CLLONG;
3655 else if (tok == TOK_CUINT)
3656 tok = TOK_CULLONG;
3658 ch = *p++;
3659 } else if (t == 'U') {
3660 if (ucount >= 1)
3661 error("two 'u's in integer constant");
3662 ucount++;
3663 if (tok == TOK_CINT)
3664 tok = TOK_CUINT;
3665 else if (tok == TOK_CLLONG)
3666 tok = TOK_CULLONG;
3667 ch = *p++;
3668 } else {
3669 break;
3672 if (tok == TOK_CINT || tok == TOK_CUINT)
3673 tokc.ui = n;
3674 else
3675 tokc.ull = n;
3677 if (ch)
3678 error("invalid number\n");
3682 #define PARSE2(c1, tok1, c2, tok2) \
3683 case c1: \
3684 PEEKC(c, p); \
3685 if (c == c2) { \
3686 p++; \
3687 tok = tok2; \
3688 } else { \
3689 tok = tok1; \
3691 break;
3693 /* return next token without macro substitution */
3694 static inline void next_nomacro1(void)
3696 int t, c, is_long;
3697 TokenSym *ts;
3698 uint8_t *p, *p1;
3699 unsigned int h;
3701 cstr_reset(&tok_spaces);
3702 p = file->buf_ptr;
3703 redo_no_start:
3704 c = *p;
3705 switch(c) {
3706 case ' ':
3707 case '\t':
3708 case '\f':
3709 case '\v':
3710 case '\r':
3711 cstr_ccat(&tok_spaces, c);
3712 p++;
3713 goto redo_no_start;
3715 case '\\':
3716 /* first look if it is in fact an end of buffer */
3717 if (p >= file->buf_end) {
3718 file->buf_ptr = p;
3719 handle_eob();
3720 p = file->buf_ptr;
3721 if (p >= file->buf_end)
3722 goto parse_eof;
3723 else
3724 goto redo_no_start;
3725 } else {
3726 file->buf_ptr = p;
3727 ch = *p;
3728 handle_stray();
3729 p = file->buf_ptr;
3730 goto redo_no_start;
3732 parse_eof:
3734 TCCState *s1 = tcc_state;
3735 if ((parse_flags & PARSE_FLAG_LINEFEED)
3736 && !(tok_flags & TOK_FLAG_EOF)) {
3737 tok_flags |= TOK_FLAG_EOF;
3738 tok = TOK_LINEFEED;
3739 goto keep_tok_flags;
3740 } else if (s1->include_stack_ptr == s1->include_stack ||
3741 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3742 /* no include left : end of file. */
3743 tok = TOK_EOF;
3744 } else {
3745 tok_flags &= ~TOK_FLAG_EOF;
3746 /* pop include file */
3748 /* test if previous '#endif' was after a #ifdef at
3749 start of file */
3750 if (tok_flags & TOK_FLAG_ENDIF) {
3751 #ifdef INC_DEBUG
3752 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3753 #endif
3754 add_cached_include(s1, file->inc_type, file->inc_filename,
3755 file->ifndef_macro_saved);
3758 /* add end of include file debug info */
3759 if (do_debug) {
3760 put_stabd(N_EINCL, 0, 0);
3762 /* pop include stack */
3763 tcc_close(file);
3764 s1->include_stack_ptr--;
3765 file = *s1->include_stack_ptr;
3766 p = file->buf_ptr;
3767 goto redo_no_start;
3770 break;
3772 case '\n':
3773 file->line_num++;
3774 tok_flags |= TOK_FLAG_BOL;
3775 p++;
3776 if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
3777 goto redo_no_start;
3778 tok = TOK_LINEFEED;
3779 goto keep_tok_flags;
3781 case '#':
3782 /* XXX: simplify */
3783 PEEKC(c, p);
3784 if ((tok_flags & TOK_FLAG_BOL) &&
3785 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3786 file->buf_ptr = p;
3787 preprocess(tok_flags & TOK_FLAG_BOF);
3788 p = file->buf_ptr;
3789 goto redo_no_start;
3790 } else {
3791 if (c == '#') {
3792 p++;
3793 tok = TOK_TWOSHARPS;
3794 } else {
3795 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3796 p = parse_line_comment(p - 1);
3797 goto redo_no_start;
3798 } else {
3799 tok = '#';
3803 break;
3805 case 'a': case 'b': case 'c': case 'd':
3806 case 'e': case 'f': case 'g': case 'h':
3807 case 'i': case 'j': case 'k': case 'l':
3808 case 'm': case 'n': case 'o': case 'p':
3809 case 'q': case 'r': case 's': case 't':
3810 case 'u': case 'v': case 'w': case 'x':
3811 case 'y': case 'z':
3812 case 'A': case 'B': case 'C': case 'D':
3813 case 'E': case 'F': case 'G': case 'H':
3814 case 'I': case 'J': case 'K':
3815 case 'M': case 'N': case 'O': case 'P':
3816 case 'Q': case 'R': case 'S': case 'T':
3817 case 'U': case 'V': case 'W': case 'X':
3818 case 'Y': case 'Z':
3819 case '_':
3820 parse_ident_fast:
3821 p1 = p;
3822 h = TOK_HASH_INIT;
3823 h = TOK_HASH_FUNC(h, c);
3824 p++;
3825 for(;;) {
3826 c = *p;
3827 if (!isidnum_table[c-CH_EOF])
3828 break;
3829 h = TOK_HASH_FUNC(h, c);
3830 p++;
3832 if (c != '\\') {
3833 TokenSym **pts;
3834 int len;
3836 /* fast case : no stray found, so we have the full token
3837 and we have already hashed it */
3838 len = p - p1;
3839 h &= (TOK_HASH_SIZE - 1);
3840 pts = &hash_ident[h];
3841 for(;;) {
3842 ts = *pts;
3843 if (!ts)
3844 break;
3845 if (ts->len == len && !memcmp(ts->str, p1, len))
3846 goto token_found;
3847 pts = &(ts->hash_next);
3849 ts = tok_alloc_new(pts, p1, len);
3850 token_found: ;
3851 } else {
3852 /* slower case */
3853 cstr_reset(&tokcstr);
3855 while (p1 < p) {
3856 cstr_ccat(&tokcstr, *p1);
3857 p1++;
3859 p--;
3860 PEEKC(c, p);
3861 parse_ident_slow:
3862 while (isidnum_table[c-CH_EOF]) {
3863 cstr_ccat(&tokcstr, c);
3864 PEEKC(c, p);
3866 ts = tok_alloc(tokcstr.data, tokcstr.size);
3868 tok = ts->tok;
3869 break;
3870 case 'L':
3871 t = p[1];
3872 if (t != '\\' && t != '\'' && t != '\"') {
3873 /* fast case */
3874 goto parse_ident_fast;
3875 } else {
3876 PEEKC(c, p);
3877 if (c == '\'' || c == '\"') {
3878 is_long = 1;
3879 goto str_const;
3880 } else {
3881 cstr_reset(&tokcstr);
3882 cstr_ccat(&tokcstr, 'L');
3883 goto parse_ident_slow;
3886 break;
3887 case '0': case '1': case '2': case '3':
3888 case '4': case '5': case '6': case '7':
3889 case '8': case '9':
3891 cstr_reset(&tokcstr);
3892 /* after the first digit, accept digits, alpha, '.' or sign if
3893 prefixed by 'eEpP' */
3894 parse_num:
3895 for(;;) {
3896 t = c;
3897 cstr_ccat(&tokcstr, c);
3898 PEEKC(c, p);
3899 if (!(isnum(c) || isid(c) || c == '.' ||
3900 ((c == '+' || c == '-') &&
3901 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3902 break;
3904 /* We add a trailing '\0' to ease parsing */
3905 cstr_ccat(&tokcstr, '\0');
3906 tokc.cstr = &tokcstr;
3907 tok = TOK_PPNUM;
3908 break;
3909 case '.':
3910 /* special dot handling because it can also start a number */
3911 PEEKC(c, p);
3912 if (isnum(c)) {
3913 cstr_reset(&tokcstr);
3914 cstr_ccat(&tokcstr, '.');
3915 goto parse_num;
3916 } else if (c == '.') {
3917 PEEKC(c, p);
3918 if (c != '.')
3919 expect("'.'");
3920 PEEKC(c, p);
3921 tok = TOK_DOTS;
3922 } else {
3923 tok = '.';
3925 break;
3926 case '\'':
3927 case '\"':
3928 is_long = 0;
3929 str_const:
3931 CString str;
3932 int sep;
3934 sep = c;
3936 /* parse the string */
3937 cstr_new(&str);
3938 p = parse_pp_string(p, sep, &str);
3939 cstr_ccat(&str, '\0');
3941 /* eval the escape (should be done as TOK_PPNUM) */
3942 cstr_reset(&tokcstr);
3943 parse_escape_string(&tokcstr, str.data, is_long);
3944 cstr_free(&str);
3946 if (sep == '\'') {
3947 int char_size;
3948 /* XXX: make it portable */
3949 if (!is_long)
3950 char_size = 1;
3951 else
3952 char_size = sizeof(nwchar_t);
3953 if (tokcstr.size <= char_size)
3954 error("empty character constant");
3955 if (tokcstr.size > 2 * char_size)
3956 warning("multi-character character constant");
3957 if (!is_long) {
3958 tokc.i = *(int8_t *)tokcstr.data;
3959 tok = TOK_CCHAR;
3960 } else {
3961 tokc.i = *(nwchar_t *)tokcstr.data;
3962 tok = TOK_LCHAR;
3964 } else {
3965 tokc.cstr = &tokcstr;
3966 if (!is_long)
3967 tok = TOK_STR;
3968 else
3969 tok = TOK_LSTR;
3972 break;
3974 case '<':
3975 PEEKC(c, p);
3976 if (c == '=') {
3977 p++;
3978 tok = TOK_LE;
3979 } else if (c == '<') {
3980 PEEKC(c, p);
3981 if (c == '=') {
3982 p++;
3983 tok = TOK_A_SHL;
3984 } else {
3985 tok = TOK_SHL;
3987 } else {
3988 tok = TOK_LT;
3990 break;
3992 case '>':
3993 PEEKC(c, p);
3994 if (c == '=') {
3995 p++;
3996 tok = TOK_GE;
3997 } else if (c == '>') {
3998 PEEKC(c, p);
3999 if (c == '=') {
4000 p++;
4001 tok = TOK_A_SAR;
4002 } else {
4003 tok = TOK_SAR;
4005 } else {
4006 tok = TOK_GT;
4008 break;
4010 case '&':
4011 PEEKC(c, p);
4012 if (c == '&') {
4013 p++;
4014 tok = TOK_LAND;
4015 } else if (c == '=') {
4016 p++;
4017 tok = TOK_A_AND;
4018 } else {
4019 tok = '&';
4021 break;
4023 case '|':
4024 PEEKC(c, p);
4025 if (c == '|') {
4026 p++;
4027 tok = TOK_LOR;
4028 } else if (c == '=') {
4029 p++;
4030 tok = TOK_A_OR;
4031 } else {
4032 tok = '|';
4034 break;
4036 case '+':
4037 PEEKC(c, p);
4038 if (c == '+') {
4039 p++;
4040 tok = TOK_INC;
4041 } else if (c == '=') {
4042 p++;
4043 tok = TOK_A_ADD;
4044 } else {
4045 tok = '+';
4047 break;
4049 case '-':
4050 PEEKC(c, p);
4051 if (c == '-') {
4052 p++;
4053 tok = TOK_DEC;
4054 } else if (c == '=') {
4055 p++;
4056 tok = TOK_A_SUB;
4057 } else if (c == '>') {
4058 p++;
4059 tok = TOK_ARROW;
4060 } else {
4061 tok = '-';
4063 break;
4065 PARSE2('!', '!', '=', TOK_NE)
4066 PARSE2('=', '=', '=', TOK_EQ)
4067 PARSE2('*', '*', '=', TOK_A_MUL)
4068 PARSE2('%', '%', '=', TOK_A_MOD)
4069 PARSE2('^', '^', '=', TOK_A_XOR)
4071 /* comments or operator */
4072 case '/':
4073 PEEKC(c, p);
4074 if (c == '*') {
4075 p = parse_comment(p);
4076 goto redo_no_start;
4077 } else if (c == '/') {
4078 p = parse_line_comment(p);
4079 goto redo_no_start;
4080 } else if (c == '=') {
4081 p++;
4082 tok = TOK_A_DIV;
4083 } else {
4084 tok = '/';
4086 break;
4088 /* simple tokens */
4089 case '(':
4090 case ')':
4091 case '[':
4092 case ']':
4093 case '{':
4094 case '}':
4095 case ',':
4096 case ';':
4097 case ':':
4098 case '?':
4099 case '~':
4100 case '$': /* only used in assembler */
4101 case '@': /* dito */
4102 tok = c;
4103 p++;
4104 break;
4105 default:
4106 error("unrecognized character \\x%02x", c);
4107 break;
4109 tok_flags = 0;
4110 keep_tok_flags:
4111 file->buf_ptr = p;
4112 #if defined(PARSE_DEBUG)
4113 printf("token = %s\n", get_tok_str(tok, &tokc));
4114 #endif
4117 /* return next token without macro substitution. Can read input from
4118 macro_ptr buffer */
4119 static void next_nomacro(void)
4121 if (macro_ptr) {
4122 redo:
4123 tok = *macro_ptr;
4124 if (tok) {
4125 TOK_GET(tok, macro_ptr, tokc);
4126 if (tok == TOK_LINENUM) {
4127 file->line_num = tokc.i;
4128 goto redo;
4131 } else {
4132 next_nomacro1();
4136 /* substitute args in macro_str and return allocated string */
4137 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
4139 int *st, last_tok, t, notfirst;
4140 Sym *s;
4141 CValue cval;
4142 TokenString str;
4143 CString cstr;
4145 tok_str_new(&str);
4146 last_tok = 0;
4147 while(1) {
4148 TOK_GET(t, macro_str, cval);
4149 if (!t)
4150 break;
4151 if (t == '#') {
4152 /* stringize */
4153 TOK_GET(t, macro_str, cval);
4154 if (!t)
4155 break;
4156 s = sym_find2(args, t);
4157 if (s) {
4158 cstr_new(&cstr);
4159 st = (int *)s->c;
4160 notfirst = 0;
4161 while (*st) {
4162 if (notfirst)
4163 cstr_ccat(&cstr, ' ');
4164 TOK_GET(t, st, cval);
4165 cstr_cat(&cstr, get_tok_str(t, &cval));
4166 #ifndef PP_NOSPACES
4167 notfirst = 1;
4168 #endif
4170 cstr_ccat(&cstr, '\0');
4171 #ifdef PP_DEBUG
4172 printf("stringize: %s\n", (char *)cstr.data);
4173 #endif
4174 /* add string */
4175 cval.cstr = &cstr;
4176 tok_str_add2(&str, TOK_STR, &cval);
4177 cstr_free(&cstr);
4178 } else {
4179 tok_str_add2(&str, t, &cval);
4181 } else if (t >= TOK_IDENT) {
4182 s = sym_find2(args, t);
4183 if (s) {
4184 st = (int *)s->c;
4185 /* if '##' is present before or after, no arg substitution */
4186 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
4187 /* special case for var arg macros : ## eats the
4188 ',' if empty VA_ARGS variable. */
4189 /* XXX: test of the ',' is not 100%
4190 reliable. should fix it to avoid security
4191 problems */
4192 if (gnu_ext && s->type.t &&
4193 last_tok == TOK_TWOSHARPS &&
4194 str.len >= 2 && str.str[str.len - 2] == ',') {
4195 if (*st == 0) {
4196 /* suppress ',' '##' */
4197 str.len -= 2;
4198 } else {
4199 /* suppress '##' and add variable */
4200 str.len--;
4201 goto add_var;
4203 } else {
4204 int t1;
4205 add_var:
4206 for(;;) {
4207 TOK_GET(t1, st, cval);
4208 if (!t1)
4209 break;
4210 tok_str_add2(&str, t1, &cval);
4213 } else {
4214 /* NOTE: the stream cannot be read when macro
4215 substituing an argument */
4216 macro_subst(&str, nested_list, st, NULL);
4218 } else {
4219 tok_str_add(&str, t);
4221 } else {
4222 tok_str_add2(&str, t, &cval);
4224 last_tok = t;
4226 tok_str_add(&str, 0);
4227 return str.str;
4230 static char const ab_month_name[12][4] =
4232 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4233 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4236 /* do macro substitution of current token with macro 's' and add
4237 result to (tok_str,tok_len). 'nested_list' is the list of all
4238 macros we got inside to avoid recursing. Return non zero if no
4239 substitution needs to be done */
4240 static int macro_subst_tok(TokenString *tok_str,
4241 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4243 Sym *args, *sa, *sa1;
4244 int mstr_allocated, parlevel, *mstr, t, t1;
4245 TokenString str;
4246 char *cstrval;
4247 CValue cval;
4248 CString cstr;
4249 char buf[32];
4251 /* if symbol is a macro, prepare substitution */
4252 /* special macros */
4253 if (tok == TOK___LINE__) {
4254 snprintf(buf, sizeof(buf), "%d", file->line_num);
4255 cstrval = buf;
4256 t1 = TOK_PPNUM;
4257 goto add_cstr1;
4258 } else if (tok == TOK___FILE__) {
4259 cstrval = file->filename;
4260 goto add_cstr;
4261 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4262 time_t ti;
4263 struct tm *tm;
4265 time(&ti);
4266 tm = localtime(&ti);
4267 if (tok == TOK___DATE__) {
4268 snprintf(buf, sizeof(buf), "%s %2d %d",
4269 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4270 } else {
4271 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4272 tm->tm_hour, tm->tm_min, tm->tm_sec);
4274 cstrval = buf;
4275 add_cstr:
4276 t1 = TOK_STR;
4277 add_cstr1:
4278 cstr_new(&cstr);
4279 cstr_cat(&cstr, cstrval);
4280 cstr_ccat(&cstr, '\0');
4281 cval.cstr = &cstr;
4282 tok_str_add2(tok_str, t1, &cval);
4283 cstr_free(&cstr);
4284 } else {
4285 mstr = (int *)s->c;
4286 mstr_allocated = 0;
4287 if (s->type.t == MACRO_FUNC) {
4288 /* NOTE: we do not use next_nomacro to avoid eating the
4289 next token. XXX: find better solution */
4290 redo:
4291 if (macro_ptr) {
4292 t = *macro_ptr;
4293 if (t == 0 && can_read_stream) {
4294 /* end of macro stream: we must look at the token
4295 after in the file */
4296 struct macro_level *ml = *can_read_stream;
4297 macro_ptr = NULL;
4298 if (ml)
4300 macro_ptr = ml->p;
4301 ml->p = NULL;
4302 *can_read_stream = ml -> prev;
4304 goto redo;
4306 } else {
4307 /* XXX: incorrect with comments */
4308 ch = file->buf_ptr[0];
4309 while (is_space(ch) || ch == '\n')
4310 cinp();
4311 t = ch;
4313 if (t != '(') /* no macro subst */
4314 return -1;
4316 /* argument macro */
4317 next_nomacro();
4318 next_nomacro();
4319 args = NULL;
4320 sa = s->next;
4321 /* NOTE: empty args are allowed, except if no args */
4322 for(;;) {
4323 /* handle '()' case */
4324 if (!args && !sa && tok == ')')
4325 break;
4326 if (!sa)
4327 error("macro '%s' used with too many args",
4328 get_tok_str(s->v, 0));
4329 tok_str_new(&str);
4330 parlevel = 0;
4331 /* NOTE: non zero sa->t indicates VA_ARGS */
4332 while ((parlevel > 0 ||
4333 (tok != ')' &&
4334 (tok != ',' || sa->type.t))) &&
4335 tok != -1) {
4336 if (tok == '(')
4337 parlevel++;
4338 else if (tok == ')')
4339 parlevel--;
4340 if (tok != TOK_LINEFEED)
4341 tok_str_add2(&str, tok, &tokc);
4342 next_nomacro();
4344 tok_str_add(&str, 0);
4345 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str);
4346 sa = sa->next;
4347 if (tok == ')') {
4348 /* special case for gcc var args: add an empty
4349 var arg argument if it is omitted */
4350 if (sa && sa->type.t && gnu_ext)
4351 continue;
4352 else
4353 break;
4355 if (tok != ',')
4356 expect(",");
4357 next_nomacro();
4359 if (sa) {
4360 error("macro '%s' used with too few args",
4361 get_tok_str(s->v, 0));
4364 /* now subst each arg */
4365 mstr = macro_arg_subst(nested_list, mstr, args);
4366 /* free memory */
4367 sa = args;
4368 while (sa) {
4369 sa1 = sa->prev;
4370 tok_str_free((int *)sa->c);
4371 sym_free(sa);
4372 sa = sa1;
4374 mstr_allocated = 1;
4376 sym_push2(nested_list, s->v, 0, 0);
4377 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4378 /* pop nested defined symbol */
4379 sa1 = *nested_list;
4380 *nested_list = sa1->prev;
4381 sym_free(sa1);
4382 if (mstr_allocated)
4383 tok_str_free(mstr);
4385 return 0;
4388 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4389 return the resulting string (which must be freed). */
4390 static inline int *macro_twosharps(const int *macro_str)
4392 TokenSym *ts;
4393 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4394 int t;
4395 const char *p1, *p2;
4396 CValue cval;
4397 TokenString macro_str1;
4398 CString cstr;
4400 start_macro_ptr = macro_str;
4401 /* we search the first '##' */
4402 for(;;) {
4403 macro_ptr1 = macro_str;
4404 TOK_GET(t, macro_str, cval);
4405 /* nothing more to do if end of string */
4406 if (t == 0)
4407 return NULL;
4408 if (*macro_str == TOK_TWOSHARPS)
4409 break;
4412 /* we saw '##', so we need more processing to handle it */
4413 cstr_new(&cstr);
4414 tok_str_new(&macro_str1);
4415 tok = t;
4416 tokc = cval;
4418 /* add all tokens seen so far */
4419 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4420 TOK_GET(t, ptr, cval);
4421 tok_str_add2(&macro_str1, t, &cval);
4423 saved_macro_ptr = macro_ptr;
4424 /* XXX: get rid of the use of macro_ptr here */
4425 macro_ptr = (int *)macro_str;
4426 for(;;) {
4427 while (*macro_ptr == TOK_TWOSHARPS) {
4428 macro_ptr++;
4429 macro_ptr1 = macro_ptr;
4430 t = *macro_ptr;
4431 if (t) {
4432 TOK_GET(t, macro_ptr, cval);
4433 /* We concatenate the two tokens if we have an
4434 identifier or a preprocessing number */
4435 cstr_reset(&cstr);
4436 p1 = get_tok_str(tok, &tokc);
4437 cstr_cat(&cstr, p1);
4438 p2 = get_tok_str(t, &cval);
4439 cstr_cat(&cstr, p2);
4440 cstr_ccat(&cstr, '\0');
4442 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4443 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4444 if (tok == TOK_PPNUM) {
4445 /* if number, then create a number token */
4446 /* NOTE: no need to allocate because
4447 tok_str_add2() does it */
4448 cstr_reset(&tokcstr);
4449 tokcstr = cstr;
4450 cstr_new(&cstr);
4451 tokc.cstr = &tokcstr;
4452 } else {
4453 /* if identifier, we must do a test to
4454 validate we have a correct identifier */
4455 if (t == TOK_PPNUM) {
4456 const char *p;
4457 int c;
4459 p = p2;
4460 for(;;) {
4461 c = *p;
4462 if (c == '\0')
4463 break;
4464 p++;
4465 if (!isnum(c) && !isid(c))
4466 goto error_pasting;
4469 ts = tok_alloc(cstr.data, strlen(cstr.data));
4470 tok = ts->tok; /* modify current token */
4472 } else {
4473 const char *str = cstr.data;
4474 const unsigned char *q;
4476 /* we look for a valid token */
4477 /* XXX: do more extensive checks */
4478 if (!strcmp(str, ">>=")) {
4479 tok = TOK_A_SAR;
4480 } else if (!strcmp(str, "<<=")) {
4481 tok = TOK_A_SHL;
4482 } else if (strlen(str) == 2) {
4483 /* search in two bytes table */
4484 q = tok_two_chars;
4485 for(;;) {
4486 if (!*q)
4487 goto error_pasting;
4488 if (q[0] == str[0] && q[1] == str[1])
4489 break;
4490 q += 3;
4492 tok = q[2];
4493 } else {
4494 error_pasting:
4495 /* NOTE: because get_tok_str use a static buffer,
4496 we must save it */
4497 cstr_reset(&cstr);
4498 p1 = get_tok_str(tok, &tokc);
4499 cstr_cat(&cstr, p1);
4500 cstr_ccat(&cstr, '\0');
4501 p2 = get_tok_str(t, &cval);
4502 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4503 /* cannot merge tokens: just add them separately */
4504 tok_str_add2(&macro_str1, tok, &tokc);
4505 /* XXX: free associated memory ? */
4506 tok = t;
4507 tokc = cval;
4512 tok_str_add2(&macro_str1, tok, &tokc);
4513 next_nomacro();
4514 if (tok == 0)
4515 break;
4517 macro_ptr = (int *)saved_macro_ptr;
4518 cstr_free(&cstr);
4519 tok_str_add(&macro_str1, 0);
4520 return macro_str1.str;
4524 /* do macro substitution of macro_str and add result to
4525 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4526 inside to avoid recursing. */
4527 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4528 const int *macro_str, struct macro_level ** can_read_stream)
4530 Sym *s;
4531 int *macro_str1;
4532 const int *ptr;
4533 int t, ret;
4534 CValue cval;
4535 struct macro_level ml;
4537 /* first scan for '##' operator handling */
4538 ptr = macro_str;
4539 macro_str1 = macro_twosharps(ptr);
4540 if (macro_str1)
4541 ptr = macro_str1;
4542 while (1) {
4543 /* NOTE: ptr == NULL can only happen if tokens are read from
4544 file stream due to a macro function call */
4545 if (ptr == NULL)
4546 break;
4547 TOK_GET(t, ptr, cval);
4548 if (t == 0)
4549 break;
4550 s = define_find(t);
4551 if (s != NULL) {
4552 /* if nested substitution, do nothing */
4553 if (sym_find2(*nested_list, t))
4554 goto no_subst;
4555 ml.p = macro_ptr;
4556 if (can_read_stream)
4557 ml.prev = *can_read_stream, *can_read_stream = &ml;
4558 macro_ptr = (int *)ptr;
4559 tok = t;
4560 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4561 ptr = (int *)macro_ptr;
4562 macro_ptr = ml.p;
4563 if (can_read_stream && *can_read_stream == &ml)
4564 *can_read_stream = ml.prev;
4565 if (ret != 0)
4566 goto no_subst;
4567 } else {
4568 no_subst:
4569 tok_str_add2(tok_str, t, &cval);
4572 if (macro_str1)
4573 tok_str_free(macro_str1);
4576 /* return next token with macro substitution */
4577 static void next(void)
4579 Sym *nested_list, *s;
4580 TokenString str;
4581 struct macro_level *ml;
4583 redo:
4584 next_nomacro();
4585 if (!macro_ptr) {
4586 /* if not reading from macro substituted string, then try
4587 to substitute macros */
4588 if (tok >= TOK_IDENT &&
4589 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4590 s = define_find(tok);
4591 if (s) {
4592 /* we have a macro: we try to substitute */
4593 tok_str_new(&str);
4594 nested_list = NULL;
4595 ml = NULL;
4596 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4597 /* substitution done, NOTE: maybe empty */
4598 tok_str_add(&str, 0);
4599 macro_ptr = str.str;
4600 macro_ptr_allocated = str.str;
4601 goto redo;
4605 } else {
4606 if (tok == 0) {
4607 /* end of macro or end of unget buffer */
4608 if (unget_buffer_enabled) {
4609 macro_ptr = unget_saved_macro_ptr;
4610 unget_buffer_enabled = 0;
4611 } else {
4612 /* end of macro string: free it */
4613 tok_str_free(macro_ptr_allocated);
4614 macro_ptr = NULL;
4616 goto redo;
4620 /* convert preprocessor tokens into C tokens */
4621 if (tok == TOK_PPNUM &&
4622 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4623 parse_number((char *)tokc.cstr->data);
4627 /* push back current token and set current token to 'last_tok'. Only
4628 identifier case handled for labels. */
4629 static inline void unget_tok(int last_tok)
4631 int i, n;
4632 int *q;
4633 unget_saved_macro_ptr = macro_ptr;
4634 unget_buffer_enabled = 1;
4635 q = unget_saved_buffer;
4636 macro_ptr = q;
4637 *q++ = tok;
4638 n = tok_ext_size(tok) - 1;
4639 for(i=0;i<n;i++)
4640 *q++ = tokc.tab[i];
4641 *q = 0; /* end of token string */
4642 tok = last_tok;
4646 void swap(int *p, int *q)
4648 int t;
4649 t = *p;
4650 *p = *q;
4651 *q = t;
4654 void vsetc(CType *type, int r, CValue *vc)
4656 int v;
4658 if (vtop >= vstack + (VSTACK_SIZE - 1))
4659 error("memory full");
4660 /* cannot let cpu flags if other instruction are generated. Also
4661 avoid leaving VT_JMP anywhere except on the top of the stack
4662 because it would complicate the code generator. */
4663 if (vtop >= vstack) {
4664 v = vtop->r & VT_VALMASK;
4665 if (v == VT_CMP || (v & ~1) == VT_JMP)
4666 gv(RC_INT);
4668 vtop++;
4669 vtop->type = *type;
4670 vtop->r = r;
4671 vtop->r2 = VT_CONST;
4672 vtop->c = *vc;
4675 /* push integer constant */
4676 void vpushi(int v)
4678 CValue cval;
4679 cval.i = v;
4680 vsetc(&int_type, VT_CONST, &cval);
4683 /* push long long constant */
4684 void vpushll(long long v)
4686 CValue cval;
4687 CType ctype;
4688 ctype.t = VT_LLONG;
4689 cval.ull = v;
4690 vsetc(&ctype, VT_CONST, &cval);
4693 /* Return a static symbol pointing to a section */
4694 static Sym *get_sym_ref(CType *type, Section *sec,
4695 unsigned long offset, unsigned long size)
4697 int v;
4698 Sym *sym;
4700 v = anon_sym++;
4701 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4702 sym->type.ref = type->ref;
4703 sym->r = VT_CONST | VT_SYM;
4704 put_extern_sym(sym, sec, offset, size);
4705 return sym;
4708 /* push a reference to a section offset by adding a dummy symbol */
4709 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4711 CValue cval;
4713 cval.ul = 0;
4714 vsetc(type, VT_CONST | VT_SYM, &cval);
4715 vtop->sym = get_sym_ref(type, sec, offset, size);
4718 /* define a new external reference to a symbol 'v' of type 'u' */
4719 static Sym *external_global_sym(int v, CType *type, int r)
4721 Sym *s;
4723 s = sym_find(v);
4724 if (!s) {
4725 /* push forward reference */
4726 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4727 s->type.ref = type->ref;
4728 s->r = r | VT_CONST | VT_SYM;
4730 return s;
4733 /* define a new external reference to a symbol 'v' of type 'u' */
4734 static Sym *external_sym(int v, CType *type, int r)
4736 Sym *s;
4738 s = sym_find(v);
4739 if (!s) {
4740 /* push forward reference */
4741 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4742 s->type.t |= VT_EXTERN;
4743 } else {
4744 if (!is_compatible_types(&s->type, type))
4745 error("incompatible types for redefinition of '%s'",
4746 get_tok_str(v, NULL));
4748 return s;
4751 /* push a reference to global symbol v */
4752 static void vpush_global_sym(CType *type, int v)
4754 Sym *sym;
4755 CValue cval;
4757 sym = external_global_sym(v, type, 0);
4758 cval.ul = 0;
4759 vsetc(type, VT_CONST | VT_SYM, &cval);
4760 vtop->sym = sym;
4763 void vset(CType *type, int r, int v)
4765 CValue cval;
4767 cval.i = v;
4768 vsetc(type, r, &cval);
4771 void vseti(int r, int v)
4773 CType type;
4774 type.t = VT_INT;
4775 vset(&type, r, v);
4778 void vswap(void)
4780 SValue tmp;
4782 tmp = vtop[0];
4783 vtop[0] = vtop[-1];
4784 vtop[-1] = tmp;
4787 void vpushv(SValue *v)
4789 if (vtop >= vstack + (VSTACK_SIZE - 1))
4790 error("memory full");
4791 vtop++;
4792 *vtop = *v;
4795 void vdup(void)
4797 vpushv(vtop);
4800 /* save r to the memory stack, and mark it as being free */
4801 void save_reg(int r)
4803 int l, saved, size, align;
4804 SValue *p, sv;
4805 CType *type;
4807 /* modify all stack values */
4808 saved = 0;
4809 l = 0;
4810 for(p=vstack;p<=vtop;p++) {
4811 if ((p->r & VT_VALMASK) == r ||
4812 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4813 /* must save value on stack if not already done */
4814 if (!saved) {
4815 /* NOTE: must reload 'r' because r might be equal to r2 */
4816 r = p->r & VT_VALMASK;
4817 /* store register in the stack */
4818 type = &p->type;
4819 if ((p->r & VT_LVAL) ||
4820 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4821 #ifdef TCC_TARGET_X86_64
4822 type = &char_pointer_type;
4823 #else
4824 type = &int_type;
4825 #endif
4826 size = type_size(type, &align);
4827 loc = (loc - size) & -align;
4828 sv.type.t = type->t;
4829 sv.r = VT_LOCAL | VT_LVAL;
4830 sv.c.ul = loc;
4831 store(r, &sv);
4832 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
4833 /* x86 specific: need to pop fp register ST0 if saved */
4834 if (r == TREG_ST0) {
4835 o(0xd9dd); /* fstp %st(1) */
4837 #endif
4838 #ifndef TCC_TARGET_X86_64
4839 /* special long long case */
4840 if ((type->t & VT_BTYPE) == VT_LLONG) {
4841 sv.c.ul += 4;
4842 store(p->r2, &sv);
4844 #endif
4845 l = loc;
4846 saved = 1;
4848 /* mark that stack entry as being saved on the stack */
4849 if (p->r & VT_LVAL) {
4850 /* also clear the bounded flag because the
4851 relocation address of the function was stored in
4852 p->c.ul */
4853 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4854 } else {
4855 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4857 p->r2 = VT_CONST;
4858 p->c.ul = l;
4863 /* find a register of class 'rc2' with at most one reference on stack.
4864 * If none, call get_reg(rc) */
4865 int get_reg_ex(int rc, int rc2)
4867 int r;
4868 SValue *p;
4870 for(r=0;r<NB_REGS;r++) {
4871 if (reg_classes[r] & rc2) {
4872 int n;
4873 n=0;
4874 for(p = vstack; p <= vtop; p++) {
4875 if ((p->r & VT_VALMASK) == r ||
4876 (p->r2 & VT_VALMASK) == r)
4877 n++;
4879 if (n <= 1)
4880 return r;
4883 return get_reg(rc);
4886 /* find a free register of class 'rc'. If none, save one register */
4887 int get_reg(int rc)
4889 int r;
4890 SValue *p;
4892 /* find a free register */
4893 for(r=0;r<NB_REGS;r++) {
4894 if (reg_classes[r] & rc) {
4895 for(p=vstack;p<=vtop;p++) {
4896 if ((p->r & VT_VALMASK) == r ||
4897 (p->r2 & VT_VALMASK) == r)
4898 goto notfound;
4900 return r;
4902 notfound: ;
4905 /* no register left : free the first one on the stack (VERY
4906 IMPORTANT to start from the bottom to ensure that we don't
4907 spill registers used in gen_opi()) */
4908 for(p=vstack;p<=vtop;p++) {
4909 r = p->r & VT_VALMASK;
4910 if (r < VT_CONST && (reg_classes[r] & rc))
4911 goto save_found;
4912 /* also look at second register (if long long) */
4913 r = p->r2 & VT_VALMASK;
4914 if (r < VT_CONST && (reg_classes[r] & rc)) {
4915 save_found:
4916 save_reg(r);
4917 return r;
4920 /* Should never comes here */
4921 return -1;
4924 /* save registers up to (vtop - n) stack entry */
4925 void save_regs(int n)
4927 int r;
4928 SValue *p, *p1;
4929 p1 = vtop - n;
4930 for(p = vstack;p <= p1; p++) {
4931 r = p->r & VT_VALMASK;
4932 if (r < VT_CONST) {
4933 save_reg(r);
4938 /* move register 's' to 'r', and flush previous value of r to memory
4939 if needed */
4940 void move_reg(int r, int s)
4942 SValue sv;
4944 if (r != s) {
4945 save_reg(r);
4946 sv.type.t = VT_INT;
4947 sv.r = s;
4948 sv.c.ul = 0;
4949 load(r, &sv);
4953 /* get address of vtop (vtop MUST BE an lvalue) */
4954 void gaddrof(void)
4956 vtop->r &= ~VT_LVAL;
4957 /* tricky: if saved lvalue, then we can go back to lvalue */
4958 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4959 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4962 #ifdef CONFIG_TCC_BCHECK
4963 /* generate lvalue bound code */
4964 void gbound(void)
4966 int lval_type;
4967 CType type1;
4969 vtop->r &= ~VT_MUSTBOUND;
4970 /* if lvalue, then use checking code before dereferencing */
4971 if (vtop->r & VT_LVAL) {
4972 /* if not VT_BOUNDED value, then make one */
4973 if (!(vtop->r & VT_BOUNDED)) {
4974 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4975 /* must save type because we must set it to int to get pointer */
4976 type1 = vtop->type;
4977 vtop->type.t = VT_INT;
4978 gaddrof();
4979 vpushi(0);
4980 gen_bounded_ptr_add();
4981 vtop->r |= lval_type;
4982 vtop->type = type1;
4984 /* then check for dereferencing */
4985 gen_bounded_ptr_deref();
4988 #endif
4990 /* store vtop a register belonging to class 'rc'. lvalues are
4991 converted to values. Cannot be used if cannot be converted to
4992 register value (such as structures). */
4993 int gv(int rc)
4995 int r, rc2, bit_pos, bit_size, size, align, i;
4997 /* NOTE: get_reg can modify vstack[] */
4998 if (vtop->type.t & VT_BITFIELD) {
4999 CType type;
5000 int bits = 32;
5001 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
5002 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5003 /* remove bit field info to avoid loops */
5004 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5005 /* cast to int to propagate signedness in following ops */
5006 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
5007 type.t = VT_LLONG;
5008 bits = 64;
5009 } else
5010 type.t = VT_INT;
5011 if((vtop->type.t & VT_UNSIGNED) ||
5012 (vtop->type.t & VT_BTYPE) == VT_BOOL)
5013 type.t |= VT_UNSIGNED;
5014 gen_cast(&type);
5015 /* generate shifts */
5016 vpushi(bits - (bit_pos + bit_size));
5017 gen_op(TOK_SHL);
5018 vpushi(bits - bit_size);
5019 /* NOTE: transformed to SHR if unsigned */
5020 gen_op(TOK_SAR);
5021 r = gv(rc);
5022 } else {
5023 if (is_float(vtop->type.t) &&
5024 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5025 Sym *sym;
5026 int *ptr;
5027 unsigned long offset;
5028 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5029 CValue check;
5030 #endif
5032 /* XXX: unify with initializers handling ? */
5033 /* CPUs usually cannot use float constants, so we store them
5034 generically in data segment */
5035 size = type_size(&vtop->type, &align);
5036 offset = (data_section->data_offset + align - 1) & -align;
5037 data_section->data_offset = offset;
5038 /* XXX: not portable yet */
5039 #if defined(__i386__) || defined(__x86_64__)
5040 /* Zero pad x87 tenbyte long doubles */
5041 if (size == LDOUBLE_SIZE)
5042 vtop->c.tab[2] &= 0xffff;
5043 #endif
5044 ptr = section_ptr_add(data_section, size);
5045 size = size >> 2;
5046 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5047 check.d = 1;
5048 if(check.tab[0])
5049 for(i=0;i<size;i++)
5050 ptr[i] = vtop->c.tab[size-1-i];
5051 else
5052 #endif
5053 for(i=0;i<size;i++)
5054 ptr[i] = vtop->c.tab[i];
5055 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
5056 vtop->r |= VT_LVAL | VT_SYM;
5057 vtop->sym = sym;
5058 vtop->c.ul = 0;
5060 #ifdef CONFIG_TCC_BCHECK
5061 if (vtop->r & VT_MUSTBOUND)
5062 gbound();
5063 #endif
5065 r = vtop->r & VT_VALMASK;
5066 rc2 = RC_INT;
5067 if (rc == RC_IRET)
5068 rc2 = RC_LRET;
5069 /* need to reload if:
5070 - constant
5071 - lvalue (need to dereference pointer)
5072 - already a register, but not in the right class */
5073 if (r >= VT_CONST ||
5074 (vtop->r & VT_LVAL) ||
5075 !(reg_classes[r] & rc) ||
5076 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
5077 !(reg_classes[vtop->r2] & rc2))) {
5078 r = get_reg(rc);
5079 #ifndef TCC_TARGET_X86_64
5080 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
5081 int r2;
5082 unsigned long long ll;
5083 /* two register type load : expand to two words
5084 temporarily */
5085 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5086 /* load constant */
5087 ll = vtop->c.ull;
5088 vtop->c.ui = ll; /* first word */
5089 load(r, vtop);
5090 vtop->r = r; /* save register value */
5091 vpushi(ll >> 32); /* second word */
5092 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
5093 (vtop->r & VT_LVAL)) {
5094 /* We do not want to modifier the long long
5095 pointer here, so the safest (and less
5096 efficient) is to save all the other registers
5097 in the stack. XXX: totally inefficient. */
5098 save_regs(1);
5099 /* load from memory */
5100 load(r, vtop);
5101 vdup();
5102 vtop[-1].r = r; /* save register value */
5103 /* increment pointer to get second word */
5104 vtop->type.t = VT_INT;
5105 gaddrof();
5106 vpushi(4);
5107 gen_op('+');
5108 vtop->r |= VT_LVAL;
5109 } else {
5110 /* move registers */
5111 load(r, vtop);
5112 vdup();
5113 vtop[-1].r = r; /* save register value */
5114 vtop->r = vtop[-1].r2;
5116 /* allocate second register */
5117 r2 = get_reg(rc2);
5118 load(r2, vtop);
5119 vpop();
5120 /* write second register */
5121 vtop->r2 = r2;
5122 } else
5123 #endif
5124 if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
5125 int t1, t;
5126 /* lvalue of scalar type : need to use lvalue type
5127 because of possible cast */
5128 t = vtop->type.t;
5129 t1 = t;
5130 /* compute memory access type */
5131 if (vtop->r & VT_LVAL_BYTE)
5132 t = VT_BYTE;
5133 else if (vtop->r & VT_LVAL_SHORT)
5134 t = VT_SHORT;
5135 if (vtop->r & VT_LVAL_UNSIGNED)
5136 t |= VT_UNSIGNED;
5137 vtop->type.t = t;
5138 load(r, vtop);
5139 /* restore wanted type */
5140 vtop->type.t = t1;
5141 } else {
5142 /* one register type load */
5143 load(r, vtop);
5146 vtop->r = r;
5147 #ifdef TCC_TARGET_C67
5148 /* uses register pairs for doubles */
5149 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5150 vtop->r2 = r+1;
5151 #endif
5153 return r;
5156 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
5157 void gv2(int rc1, int rc2)
5159 int v;
5161 /* generate more generic register first. But VT_JMP or VT_CMP
5162 values must be generated first in all cases to avoid possible
5163 reload errors */
5164 v = vtop[0].r & VT_VALMASK;
5165 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
5166 vswap();
5167 gv(rc1);
5168 vswap();
5169 gv(rc2);
5170 /* test if reload is needed for first register */
5171 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
5172 vswap();
5173 gv(rc1);
5174 vswap();
5176 } else {
5177 gv(rc2);
5178 vswap();
5179 gv(rc1);
5180 vswap();
5181 /* test if reload is needed for first register */
5182 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
5183 gv(rc2);
5188 /* wrapper around RC_FRET to return a register by type */
5189 int rc_fret(int t)
5191 #ifdef TCC_TARGET_X86_64
5192 if (t == VT_LDOUBLE) {
5193 return RC_ST0;
5195 #endif
5196 return RC_FRET;
5199 /* wrapper around REG_FRET to return a register by type */
5200 int reg_fret(int t)
5202 #ifdef TCC_TARGET_X86_64
5203 if (t == VT_LDOUBLE) {
5204 return TREG_ST0;
5206 #endif
5207 return REG_FRET;
5210 /* expand long long on stack in two int registers */
5211 void lexpand(void)
5213 int u;
5215 u = vtop->type.t & VT_UNSIGNED;
5216 gv(RC_INT);
5217 vdup();
5218 vtop[0].r = vtop[-1].r2;
5219 vtop[0].r2 = VT_CONST;
5220 vtop[-1].r2 = VT_CONST;
5221 vtop[0].type.t = VT_INT | u;
5222 vtop[-1].type.t = VT_INT | u;
5225 #ifdef TCC_TARGET_ARM
5226 /* expand long long on stack */
5227 void lexpand_nr(void)
5229 int u,v;
5231 u = vtop->type.t & VT_UNSIGNED;
5232 vdup();
5233 vtop->r2 = VT_CONST;
5234 vtop->type.t = VT_INT | u;
5235 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
5236 if (v == VT_CONST) {
5237 vtop[-1].c.ui = vtop->c.ull;
5238 vtop->c.ui = vtop->c.ull >> 32;
5239 vtop->r = VT_CONST;
5240 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
5241 vtop->c.ui += 4;
5242 vtop->r = vtop[-1].r;
5243 } else if (v > VT_CONST) {
5244 vtop--;
5245 lexpand();
5246 } else
5247 vtop->r = vtop[-1].r2;
5248 vtop[-1].r2 = VT_CONST;
5249 vtop[-1].type.t = VT_INT | u;
5251 #endif
5253 /* build a long long from two ints */
5254 void lbuild(int t)
5256 gv2(RC_INT, RC_INT);
5257 vtop[-1].r2 = vtop[0].r;
5258 vtop[-1].type.t = t;
5259 vpop();
5262 /* rotate n first stack elements to the bottom
5263 I1 ... In -> I2 ... In I1 [top is right]
5265 void vrotb(int n)
5267 int i;
5268 SValue tmp;
5270 tmp = vtop[-n + 1];
5271 for(i=-n+1;i!=0;i++)
5272 vtop[i] = vtop[i+1];
5273 vtop[0] = tmp;
5276 /* rotate n first stack elements to the top
5277 I1 ... In -> In I1 ... I(n-1) [top is right]
5279 void vrott(int n)
5281 int i;
5282 SValue tmp;
5284 tmp = vtop[0];
5285 for(i = 0;i < n - 1; i++)
5286 vtop[-i] = vtop[-i - 1];
5287 vtop[-n + 1] = tmp;
5290 #ifdef TCC_TARGET_ARM
5291 /* like vrott but in other direction
5292 In ... I1 -> I(n-1) ... I1 In [top is right]
5294 void vnrott(int n)
5296 int i;
5297 SValue tmp;
5299 tmp = vtop[-n + 1];
5300 for(i = n - 1; i > 0; i--)
5301 vtop[-i] = vtop[-i + 1];
5302 vtop[0] = tmp;
5304 #endif
5306 /* pop stack value */
5307 void vpop(void)
5309 int v;
5310 v = vtop->r & VT_VALMASK;
5311 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
5312 /* for x86, we need to pop the FP stack */
5313 if (v == TREG_ST0 && !nocode_wanted) {
5314 o(0xd9dd); /* fstp %st(1) */
5315 } else
5316 #endif
5317 if (v == VT_JMP || v == VT_JMPI) {
5318 /* need to put correct jump if && or || without test */
5319 gsym(vtop->c.ul);
5321 vtop--;
5324 /* convert stack entry to register and duplicate its value in another
5325 register */
5326 void gv_dup(void)
5328 int rc, t, r, r1;
5329 SValue sv;
5331 t = vtop->type.t;
5332 if ((t & VT_BTYPE) == VT_LLONG) {
5333 lexpand();
5334 gv_dup();
5335 vswap();
5336 vrotb(3);
5337 gv_dup();
5338 vrotb(4);
5339 /* stack: H L L1 H1 */
5340 lbuild(t);
5341 vrotb(3);
5342 vrotb(3);
5343 vswap();
5344 lbuild(t);
5345 vswap();
5346 } else {
5347 /* duplicate value */
5348 rc = RC_INT;
5349 sv.type.t = VT_INT;
5350 if (is_float(t)) {
5351 rc = RC_FLOAT;
5352 #ifdef TCC_TARGET_X86_64
5353 if ((t & VT_BTYPE) == VT_LDOUBLE) {
5354 rc = RC_ST0;
5356 #endif
5357 sv.type.t = t;
5359 r = gv(rc);
5360 r1 = get_reg(rc);
5361 sv.r = r;
5362 sv.c.ul = 0;
5363 load(r1, &sv); /* move r to r1 */
5364 vdup();
5365 /* duplicates value */
5366 vtop->r = r1;
5370 #ifndef TCC_TARGET_X86_64
5371 /* generate CPU independent (unsigned) long long operations */
5372 void gen_opl(int op)
5374 int t, a, b, op1, c, i;
5375 int func;
5376 unsigned short reg_iret = REG_IRET;
5377 unsigned short reg_lret = REG_LRET;
5378 SValue tmp;
5380 switch(op) {
5381 case '/':
5382 case TOK_PDIV:
5383 func = TOK___divdi3;
5384 goto gen_func;
5385 case TOK_UDIV:
5386 func = TOK___udivdi3;
5387 goto gen_func;
5388 case '%':
5389 func = TOK___moddi3;
5390 goto gen_mod_func;
5391 case TOK_UMOD:
5392 func = TOK___umoddi3;
5393 gen_mod_func:
5394 #ifdef TCC_ARM_EABI
5395 reg_iret = TREG_R2;
5396 reg_lret = TREG_R3;
5397 #endif
5398 gen_func:
5399 /* call generic long long function */
5400 vpush_global_sym(&func_old_type, func);
5401 vrott(3);
5402 gfunc_call(2);
5403 vpushi(0);
5404 vtop->r = reg_iret;
5405 vtop->r2 = reg_lret;
5406 break;
5407 case '^':
5408 case '&':
5409 case '|':
5410 case '*':
5411 case '+':
5412 case '-':
5413 t = vtop->type.t;
5414 vswap();
5415 lexpand();
5416 vrotb(3);
5417 lexpand();
5418 /* stack: L1 H1 L2 H2 */
5419 tmp = vtop[0];
5420 vtop[0] = vtop[-3];
5421 vtop[-3] = tmp;
5422 tmp = vtop[-2];
5423 vtop[-2] = vtop[-3];
5424 vtop[-3] = tmp;
5425 vswap();
5426 /* stack: H1 H2 L1 L2 */
5427 if (op == '*') {
5428 vpushv(vtop - 1);
5429 vpushv(vtop - 1);
5430 gen_op(TOK_UMULL);
5431 lexpand();
5432 /* stack: H1 H2 L1 L2 ML MH */
5433 for(i=0;i<4;i++)
5434 vrotb(6);
5435 /* stack: ML MH H1 H2 L1 L2 */
5436 tmp = vtop[0];
5437 vtop[0] = vtop[-2];
5438 vtop[-2] = tmp;
5439 /* stack: ML MH H1 L2 H2 L1 */
5440 gen_op('*');
5441 vrotb(3);
5442 vrotb(3);
5443 gen_op('*');
5444 /* stack: ML MH M1 M2 */
5445 gen_op('+');
5446 gen_op('+');
5447 } else if (op == '+' || op == '-') {
5448 /* XXX: add non carry method too (for MIPS or alpha) */
5449 if (op == '+')
5450 op1 = TOK_ADDC1;
5451 else
5452 op1 = TOK_SUBC1;
5453 gen_op(op1);
5454 /* stack: H1 H2 (L1 op L2) */
5455 vrotb(3);
5456 vrotb(3);
5457 gen_op(op1 + 1); /* TOK_xxxC2 */
5458 } else {
5459 gen_op(op);
5460 /* stack: H1 H2 (L1 op L2) */
5461 vrotb(3);
5462 vrotb(3);
5463 /* stack: (L1 op L2) H1 H2 */
5464 gen_op(op);
5465 /* stack: (L1 op L2) (H1 op H2) */
5467 /* stack: L H */
5468 lbuild(t);
5469 break;
5470 case TOK_SAR:
5471 case TOK_SHR:
5472 case TOK_SHL:
5473 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5474 t = vtop[-1].type.t;
5475 vswap();
5476 lexpand();
5477 vrotb(3);
5478 /* stack: L H shift */
5479 c = (int)vtop->c.i;
5480 /* constant: simpler */
5481 /* NOTE: all comments are for SHL. the other cases are
5482 done by swaping words */
5483 vpop();
5484 if (op != TOK_SHL)
5485 vswap();
5486 if (c >= 32) {
5487 /* stack: L H */
5488 vpop();
5489 if (c > 32) {
5490 vpushi(c - 32);
5491 gen_op(op);
5493 if (op != TOK_SAR) {
5494 vpushi(0);
5495 } else {
5496 gv_dup();
5497 vpushi(31);
5498 gen_op(TOK_SAR);
5500 vswap();
5501 } else {
5502 vswap();
5503 gv_dup();
5504 /* stack: H L L */
5505 vpushi(c);
5506 gen_op(op);
5507 vswap();
5508 vpushi(32 - c);
5509 if (op == TOK_SHL)
5510 gen_op(TOK_SHR);
5511 else
5512 gen_op(TOK_SHL);
5513 vrotb(3);
5514 /* stack: L L H */
5515 vpushi(c);
5516 if (op == TOK_SHL)
5517 gen_op(TOK_SHL);
5518 else
5519 gen_op(TOK_SHR);
5520 gen_op('|');
5522 if (op != TOK_SHL)
5523 vswap();
5524 lbuild(t);
5525 } else {
5526 /* XXX: should provide a faster fallback on x86 ? */
5527 switch(op) {
5528 case TOK_SAR:
5529 func = TOK___ashrdi3;
5530 goto gen_func;
5531 case TOK_SHR:
5532 func = TOK___lshrdi3;
5533 goto gen_func;
5534 case TOK_SHL:
5535 func = TOK___ashldi3;
5536 goto gen_func;
5539 break;
5540 default:
5541 /* compare operations */
5542 t = vtop->type.t;
5543 vswap();
5544 lexpand();
5545 vrotb(3);
5546 lexpand();
5547 /* stack: L1 H1 L2 H2 */
5548 tmp = vtop[-1];
5549 vtop[-1] = vtop[-2];
5550 vtop[-2] = tmp;
5551 /* stack: L1 L2 H1 H2 */
5552 /* compare high */
5553 op1 = op;
5554 /* when values are equal, we need to compare low words. since
5555 the jump is inverted, we invert the test too. */
5556 if (op1 == TOK_LT)
5557 op1 = TOK_LE;
5558 else if (op1 == TOK_GT)
5559 op1 = TOK_GE;
5560 else if (op1 == TOK_ULT)
5561 op1 = TOK_ULE;
5562 else if (op1 == TOK_UGT)
5563 op1 = TOK_UGE;
5564 a = 0;
5565 b = 0;
5566 gen_op(op1);
5567 if (op1 != TOK_NE) {
5568 a = gtst(1, 0);
5570 if (op != TOK_EQ) {
5571 /* generate non equal test */
5572 /* XXX: NOT PORTABLE yet */
5573 if (a == 0) {
5574 b = gtst(0, 0);
5575 } else {
5576 #if defined(TCC_TARGET_I386)
5577 b = psym(0x850f, 0);
5578 #elif defined(TCC_TARGET_ARM)
5579 b = ind;
5580 o(0x1A000000 | encbranch(ind, 0, 1));
5581 #elif defined(TCC_TARGET_C67)
5582 error("not implemented");
5583 #else
5584 #error not supported
5585 #endif
5588 /* compare low. Always unsigned */
5589 op1 = op;
5590 if (op1 == TOK_LT)
5591 op1 = TOK_ULT;
5592 else if (op1 == TOK_LE)
5593 op1 = TOK_ULE;
5594 else if (op1 == TOK_GT)
5595 op1 = TOK_UGT;
5596 else if (op1 == TOK_GE)
5597 op1 = TOK_UGE;
5598 gen_op(op1);
5599 a = gtst(1, a);
5600 gsym(b);
5601 vseti(VT_JMPI, a);
5602 break;
5605 #endif
5607 /* handle integer constant optimizations and various machine
5608 independent opt */
5609 void gen_opic(int op)
5611 int c1, c2, t1, t2, n;
5612 SValue *v1, *v2;
5613 long long l1, l2;
5614 typedef unsigned long long U;
5616 v1 = vtop - 1;
5617 v2 = vtop;
5618 t1 = v1->type.t & VT_BTYPE;
5619 t2 = v2->type.t & VT_BTYPE;
5621 if (t1 == VT_LLONG)
5622 l1 = v1->c.ll;
5623 else if (v1->type.t & VT_UNSIGNED)
5624 l1 = v1->c.ui;
5625 else
5626 l1 = v1->c.i;
5628 if (t2 == VT_LLONG)
5629 l2 = v2->c.ll;
5630 else if (v2->type.t & VT_UNSIGNED)
5631 l2 = v2->c.ui;
5632 else
5633 l2 = v2->c.i;
5635 /* currently, we cannot do computations with forward symbols */
5636 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5637 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5638 if (c1 && c2) {
5639 switch(op) {
5640 case '+': l1 += l2; break;
5641 case '-': l1 -= l2; break;
5642 case '&': l1 &= l2; break;
5643 case '^': l1 ^= l2; break;
5644 case '|': l1 |= l2; break;
5645 case '*': l1 *= l2; break;
5647 case TOK_PDIV:
5648 case '/':
5649 case '%':
5650 case TOK_UDIV:
5651 case TOK_UMOD:
5652 /* if division by zero, generate explicit division */
5653 if (l2 == 0) {
5654 if (const_wanted)
5655 error("division by zero in constant");
5656 goto general_case;
5658 switch(op) {
5659 default: l1 /= l2; break;
5660 case '%': l1 %= l2; break;
5661 case TOK_UDIV: l1 = (U)l1 / l2; break;
5662 case TOK_UMOD: l1 = (U)l1 % l2; break;
5664 break;
5665 case TOK_SHL: l1 <<= l2; break;
5666 case TOK_SHR: l1 = (U)l1 >> l2; break;
5667 case TOK_SAR: l1 >>= l2; break;
5668 /* tests */
5669 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5670 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5671 case TOK_EQ: l1 = l1 == l2; break;
5672 case TOK_NE: l1 = l1 != l2; break;
5673 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5674 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5675 case TOK_LT: l1 = l1 < l2; break;
5676 case TOK_GE: l1 = l1 >= l2; break;
5677 case TOK_LE: l1 = l1 <= l2; break;
5678 case TOK_GT: l1 = l1 > l2; break;
5679 /* logical */
5680 case TOK_LAND: l1 = l1 && l2; break;
5681 case TOK_LOR: l1 = l1 || l2; break;
5682 default:
5683 goto general_case;
5685 v1->c.ll = l1;
5686 vtop--;
5687 } else {
5688 /* if commutative ops, put c2 as constant */
5689 if (c1 && (op == '+' || op == '&' || op == '^' ||
5690 op == '|' || op == '*')) {
5691 vswap();
5692 c2 = c1; //c = c1, c1 = c2, c2 = c;
5693 l2 = l1; //l = l1, l1 = l2, l2 = l;
5695 /* Filter out NOP operations like x*1, x-0, x&-1... */
5696 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5697 op == TOK_PDIV) &&
5698 l2 == 1) ||
5699 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5700 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5701 l2 == 0) ||
5702 (op == '&' &&
5703 l2 == -1))) {
5704 /* nothing to do */
5705 vtop--;
5706 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5707 /* try to use shifts instead of muls or divs */
5708 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5709 n = -1;
5710 while (l2) {
5711 l2 >>= 1;
5712 n++;
5714 vtop->c.ll = n;
5715 if (op == '*')
5716 op = TOK_SHL;
5717 else if (op == TOK_PDIV)
5718 op = TOK_SAR;
5719 else
5720 op = TOK_SHR;
5722 goto general_case;
5723 } else if (c2 && (op == '+' || op == '-') &&
5724 ((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5725 (VT_CONST | VT_SYM) ||
5726 (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
5727 /* symbol + constant case */
5728 if (op == '-')
5729 l2 = -l2;
5730 vtop--;
5731 vtop->c.ll += l2;
5732 } else {
5733 general_case:
5734 if (!nocode_wanted) {
5735 /* call low level op generator */
5736 if (t1 == VT_LLONG || t2 == VT_LLONG)
5737 gen_opl(op);
5738 else
5739 gen_opi(op);
5740 } else {
5741 vtop--;
5747 /* generate a floating point operation with constant propagation */
5748 void gen_opif(int op)
5750 int c1, c2;
5751 SValue *v1, *v2;
5752 long double f1, f2;
5754 v1 = vtop - 1;
5755 v2 = vtop;
5756 /* currently, we cannot do computations with forward symbols */
5757 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5758 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5759 if (c1 && c2) {
5760 if (v1->type.t == VT_FLOAT) {
5761 f1 = v1->c.f;
5762 f2 = v2->c.f;
5763 } else if (v1->type.t == VT_DOUBLE) {
5764 f1 = v1->c.d;
5765 f2 = v2->c.d;
5766 } else {
5767 f1 = v1->c.ld;
5768 f2 = v2->c.ld;
5771 /* NOTE: we only do constant propagation if finite number (not
5772 NaN or infinity) (ANSI spec) */
5773 if (!ieee_finite(f1) || !ieee_finite(f2))
5774 goto general_case;
5776 switch(op) {
5777 case '+': f1 += f2; break;
5778 case '-': f1 -= f2; break;
5779 case '*': f1 *= f2; break;
5780 case '/':
5781 if (f2 == 0.0) {
5782 if (const_wanted)
5783 error("division by zero in constant");
5784 goto general_case;
5786 f1 /= f2;
5787 break;
5788 /* XXX: also handles tests ? */
5789 default:
5790 goto general_case;
5792 /* XXX: overflow test ? */
5793 if (v1->type.t == VT_FLOAT) {
5794 v1->c.f = f1;
5795 } else if (v1->type.t == VT_DOUBLE) {
5796 v1->c.d = f1;
5797 } else {
5798 v1->c.ld = f1;
5800 vtop--;
5801 } else {
5802 general_case:
5803 if (!nocode_wanted) {
5804 gen_opf(op);
5805 } else {
5806 vtop--;
5811 static int pointed_size(CType *type)
5813 int align;
5814 return type_size(pointed_type(type), &align);
5817 static inline int is_null_pointer(SValue *p)
5819 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5820 return 0;
5821 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5822 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5825 static inline int is_integer_btype(int bt)
5827 return (bt == VT_BYTE || bt == VT_SHORT ||
5828 bt == VT_INT || bt == VT_LLONG);
5831 /* check types for comparison or substraction of pointers */
5832 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5834 CType *type1, *type2, tmp_type1, tmp_type2;
5835 int bt1, bt2;
5837 /* null pointers are accepted for all comparisons as gcc */
5838 if (is_null_pointer(p1) || is_null_pointer(p2))
5839 return;
5840 type1 = &p1->type;
5841 type2 = &p2->type;
5842 bt1 = type1->t & VT_BTYPE;
5843 bt2 = type2->t & VT_BTYPE;
5844 /* accept comparison between pointer and integer with a warning */
5845 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5846 if (op != TOK_LOR && op != TOK_LAND )
5847 warning("comparison between pointer and integer");
5848 return;
5851 /* both must be pointers or implicit function pointers */
5852 if (bt1 == VT_PTR) {
5853 type1 = pointed_type(type1);
5854 } else if (bt1 != VT_FUNC)
5855 goto invalid_operands;
5857 if (bt2 == VT_PTR) {
5858 type2 = pointed_type(type2);
5859 } else if (bt2 != VT_FUNC) {
5860 invalid_operands:
5861 error("invalid operands to binary %s", get_tok_str(op, NULL));
5863 if ((type1->t & VT_BTYPE) == VT_VOID ||
5864 (type2->t & VT_BTYPE) == VT_VOID)
5865 return;
5866 tmp_type1 = *type1;
5867 tmp_type2 = *type2;
5868 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5869 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5870 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5871 /* gcc-like error if '-' is used */
5872 if (op == '-')
5873 goto invalid_operands;
5874 else
5875 warning("comparison of distinct pointer types lacks a cast");
5879 /* generic gen_op: handles types problems */
5880 void gen_op(int op)
5882 int u, t1, t2, bt1, bt2, t;
5883 CType type1;
5885 t1 = vtop[-1].type.t;
5886 t2 = vtop[0].type.t;
5887 bt1 = t1 & VT_BTYPE;
5888 bt2 = t2 & VT_BTYPE;
5890 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5891 /* at least one operand is a pointer */
5892 /* relationnal op: must be both pointers */
5893 if (op >= TOK_ULT && op <= TOK_LOR) {
5894 check_comparison_pointer_types(vtop - 1, vtop, op);
5895 /* pointers are handled are unsigned */
5896 #ifdef TCC_TARGET_X86_64
5897 t = VT_LLONG | VT_UNSIGNED;
5898 #else
5899 t = VT_INT | VT_UNSIGNED;
5900 #endif
5901 goto std_op;
5903 /* if both pointers, then it must be the '-' op */
5904 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5905 if (op != '-')
5906 error("cannot use pointers here");
5907 check_comparison_pointer_types(vtop - 1, vtop, op);
5908 /* XXX: check that types are compatible */
5909 u = pointed_size(&vtop[-1].type);
5910 gen_opic(op);
5911 /* set to integer type */
5912 #ifdef TCC_TARGET_X86_64
5913 vtop->type.t = VT_LLONG;
5914 #else
5915 vtop->type.t = VT_INT;
5916 #endif
5917 vpushi(u);
5918 gen_op(TOK_PDIV);
5919 } else {
5920 /* exactly one pointer : must be '+' or '-'. */
5921 if (op != '-' && op != '+')
5922 error("cannot use pointers here");
5923 /* Put pointer as first operand */
5924 if (bt2 == VT_PTR) {
5925 vswap();
5926 swap(&t1, &t2);
5928 type1 = vtop[-1].type;
5929 #ifdef TCC_TARGET_X86_64
5930 vpushll(pointed_size(&vtop[-1].type));
5931 #else
5932 /* XXX: cast to int ? (long long case) */
5933 vpushi(pointed_size(&vtop[-1].type));
5934 #endif
5935 gen_op('*');
5936 #ifdef CONFIG_TCC_BCHECK
5937 /* if evaluating constant expression, no code should be
5938 generated, so no bound check */
5939 if (do_bounds_check && !const_wanted) {
5940 /* if bounded pointers, we generate a special code to
5941 test bounds */
5942 if (op == '-') {
5943 vpushi(0);
5944 vswap();
5945 gen_op('-');
5947 gen_bounded_ptr_add();
5948 } else
5949 #endif
5951 gen_opic(op);
5953 /* put again type if gen_opic() swaped operands */
5954 vtop->type = type1;
5956 } else if (is_float(bt1) || is_float(bt2)) {
5957 /* compute bigger type and do implicit casts */
5958 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5959 t = VT_LDOUBLE;
5960 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5961 t = VT_DOUBLE;
5962 } else {
5963 t = VT_FLOAT;
5965 /* floats can only be used for a few operations */
5966 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5967 (op < TOK_ULT || op > TOK_GT))
5968 error("invalid operands for binary operation");
5969 goto std_op;
5970 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5971 /* cast to biggest op */
5972 t = VT_LLONG;
5973 /* convert to unsigned if it does not fit in a long long */
5974 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5975 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5976 t |= VT_UNSIGNED;
5977 goto std_op;
5978 } else {
5979 /* integer operations */
5980 t = VT_INT;
5981 /* convert to unsigned if it does not fit in an integer */
5982 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5983 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5984 t |= VT_UNSIGNED;
5985 std_op:
5986 /* XXX: currently, some unsigned operations are explicit, so
5987 we modify them here */
5988 if (t & VT_UNSIGNED) {
5989 if (op == TOK_SAR)
5990 op = TOK_SHR;
5991 else if (op == '/')
5992 op = TOK_UDIV;
5993 else if (op == '%')
5994 op = TOK_UMOD;
5995 else if (op == TOK_LT)
5996 op = TOK_ULT;
5997 else if (op == TOK_GT)
5998 op = TOK_UGT;
5999 else if (op == TOK_LE)
6000 op = TOK_ULE;
6001 else if (op == TOK_GE)
6002 op = TOK_UGE;
6004 vswap();
6005 type1.t = t;
6006 gen_cast(&type1);
6007 vswap();
6008 /* special case for shifts and long long: we keep the shift as
6009 an integer */
6010 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
6011 type1.t = VT_INT;
6012 gen_cast(&type1);
6013 if (is_float(t))
6014 gen_opif(op);
6015 else
6016 gen_opic(op);
6017 if (op >= TOK_ULT && op <= TOK_GT) {
6018 /* relationnal op: the result is an int */
6019 vtop->type.t = VT_INT;
6020 } else {
6021 vtop->type.t = t;
6026 #ifndef TCC_TARGET_ARM
6027 /* generic itof for unsigned long long case */
6028 void gen_cvt_itof1(int t)
6030 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
6031 (VT_LLONG | VT_UNSIGNED)) {
6033 if (t == VT_FLOAT)
6034 vpush_global_sym(&func_old_type, TOK___floatundisf);
6035 #if LDOUBLE_SIZE != 8
6036 else if (t == VT_LDOUBLE)
6037 vpush_global_sym(&func_old_type, TOK___floatundixf);
6038 #endif
6039 else
6040 vpush_global_sym(&func_old_type, TOK___floatundidf);
6041 vrott(2);
6042 gfunc_call(1);
6043 vpushi(0);
6044 vtop->r = reg_fret(t);
6045 } else {
6046 gen_cvt_itof(t);
6049 #endif
6051 /* generic ftoi for unsigned long long case */
6052 void gen_cvt_ftoi1(int t)
6054 int st;
6056 if (t == (VT_LLONG | VT_UNSIGNED)) {
6057 /* not handled natively */
6058 st = vtop->type.t & VT_BTYPE;
6059 if (st == VT_FLOAT)
6060 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
6061 #if LDOUBLE_SIZE != 8
6062 else if (st == VT_LDOUBLE)
6063 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
6064 #endif
6065 else
6066 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
6067 vrott(2);
6068 gfunc_call(1);
6069 vpushi(0);
6070 vtop->r = REG_IRET;
6071 vtop->r2 = REG_LRET;
6072 } else {
6073 gen_cvt_ftoi(t);
6077 /* force char or short cast */
6078 void force_charshort_cast(int t)
6080 int bits, dbt;
6081 dbt = t & VT_BTYPE;
6082 /* XXX: add optimization if lvalue : just change type and offset */
6083 if (dbt == VT_BYTE)
6084 bits = 8;
6085 else
6086 bits = 16;
6087 if (t & VT_UNSIGNED) {
6088 vpushi((1 << bits) - 1);
6089 gen_op('&');
6090 } else {
6091 bits = 32 - bits;
6092 vpushi(bits);
6093 gen_op(TOK_SHL);
6094 /* result must be signed or the SAR is converted to an SHL
6095 This was not the case when "t" was a signed short
6096 and the last value on the stack was an unsigned int */
6097 vtop->type.t &= ~VT_UNSIGNED;
6098 vpushi(bits);
6099 gen_op(TOK_SAR);
6103 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
6104 static void gen_cast(CType *type)
6106 int sbt, dbt, sf, df, c, p;
6108 /* special delayed cast for char/short */
6109 /* XXX: in some cases (multiple cascaded casts), it may still
6110 be incorrect */
6111 if (vtop->r & VT_MUSTCAST) {
6112 vtop->r &= ~VT_MUSTCAST;
6113 force_charshort_cast(vtop->type.t);
6116 /* bitfields first get cast to ints */
6117 if (vtop->type.t & VT_BITFIELD) {
6118 gv(RC_INT);
6121 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
6122 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
6124 if (sbt != dbt) {
6125 sf = is_float(sbt);
6126 df = is_float(dbt);
6127 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6128 p = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM);
6129 if (c) {
6130 /* constant case: we can do it now */
6131 /* XXX: in ISOC, cannot do it if error in convert */
6132 if (sbt == VT_FLOAT)
6133 vtop->c.ld = vtop->c.f;
6134 else if (sbt == VT_DOUBLE)
6135 vtop->c.ld = vtop->c.d;
6137 if (df) {
6138 if ((sbt & VT_BTYPE) == VT_LLONG) {
6139 if (sbt & VT_UNSIGNED)
6140 vtop->c.ld = vtop->c.ull;
6141 else
6142 vtop->c.ld = vtop->c.ll;
6143 } else if(!sf) {
6144 if (sbt & VT_UNSIGNED)
6145 vtop->c.ld = vtop->c.ui;
6146 else
6147 vtop->c.ld = vtop->c.i;
6150 if (dbt == VT_FLOAT)
6151 vtop->c.f = (float)vtop->c.ld;
6152 else if (dbt == VT_DOUBLE)
6153 vtop->c.d = (double)vtop->c.ld;
6154 } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
6155 vtop->c.ull = (unsigned long long)vtop->c.ld;
6156 } else if (sf && dbt == VT_BOOL) {
6157 vtop->c.i = (vtop->c.ld != 0);
6158 } else {
6159 if(sf)
6160 vtop->c.ll = (long long)vtop->c.ld;
6161 else if (sbt == (VT_LLONG|VT_UNSIGNED))
6162 vtop->c.ll = vtop->c.ull;
6163 else if (sbt & VT_UNSIGNED)
6164 vtop->c.ll = vtop->c.ui;
6165 else if (sbt != VT_LLONG)
6166 vtop->c.ll = vtop->c.i;
6168 if (dbt == (VT_LLONG|VT_UNSIGNED))
6169 vtop->c.ull = vtop->c.ll;
6170 else if (dbt == VT_BOOL)
6171 vtop->c.i = (vtop->c.ll != 0);
6172 else if (dbt != VT_LLONG) {
6173 int s = 0;
6174 if ((dbt & VT_BTYPE) == VT_BYTE)
6175 s = 24;
6176 else if ((dbt & VT_BTYPE) == VT_SHORT)
6177 s = 16;
6179 if(dbt & VT_UNSIGNED)
6180 vtop->c.ui = ((unsigned int)vtop->c.ll << s) >> s;
6181 else
6182 vtop->c.i = ((int)vtop->c.ll << s) >> s;
6185 } else if (p && dbt == VT_BOOL) {
6186 vtop->r = VT_CONST;
6187 vtop->c.i = 1;
6188 } else if (!nocode_wanted) {
6189 /* non constant case: generate code */
6190 if (sf && df) {
6191 /* convert from fp to fp */
6192 gen_cvt_ftof(dbt);
6193 } else if (df) {
6194 /* convert int to fp */
6195 gen_cvt_itof1(dbt);
6196 } else if (sf) {
6197 /* convert fp to int */
6198 if (dbt == VT_BOOL) {
6199 vpushi(0);
6200 gen_op(TOK_NE);
6201 } else {
6202 /* we handle char/short/etc... with generic code */
6203 if (dbt != (VT_INT | VT_UNSIGNED) &&
6204 dbt != (VT_LLONG | VT_UNSIGNED) &&
6205 dbt != VT_LLONG)
6206 dbt = VT_INT;
6207 gen_cvt_ftoi1(dbt);
6208 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
6209 /* additional cast for char/short... */
6210 vtop->type.t = dbt;
6211 gen_cast(type);
6214 #ifndef TCC_TARGET_X86_64
6215 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
6216 if ((sbt & VT_BTYPE) != VT_LLONG) {
6217 /* scalar to long long */
6218 /* machine independent conversion */
6219 gv(RC_INT);
6220 /* generate high word */
6221 if (sbt == (VT_INT | VT_UNSIGNED)) {
6222 vpushi(0);
6223 gv(RC_INT);
6224 } else {
6225 if (sbt == VT_PTR) {
6226 /* cast from pointer to int before we apply
6227 shift operation, which pointers don't support*/
6228 gen_cast(&int_type);
6230 gv_dup();
6231 vpushi(31);
6232 gen_op(TOK_SAR);
6234 /* patch second register */
6235 vtop[-1].r2 = vtop->r;
6236 vpop();
6238 #else
6239 } else if ((dbt & VT_BTYPE) == VT_LLONG ||
6240 (dbt & VT_BTYPE) == VT_PTR) {
6241 /* XXX: not sure if this is perfect... need more tests */
6242 if ((sbt & VT_BTYPE) != VT_LLONG) {
6243 int r = gv(RC_INT);
6244 if (sbt != (VT_INT | VT_UNSIGNED) &&
6245 sbt != VT_PTR && sbt != VT_FUNC) {
6246 /* x86_64 specific: movslq */
6247 o(0x6348);
6248 o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r));
6251 #endif
6252 } else if (dbt == VT_BOOL) {
6253 /* scalar to bool */
6254 vpushi(0);
6255 gen_op(TOK_NE);
6256 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
6257 (dbt & VT_BTYPE) == VT_SHORT) {
6258 if (sbt == VT_PTR) {
6259 vtop->type.t = VT_INT;
6260 warning("nonportable conversion from pointer to char/short");
6262 force_charshort_cast(dbt);
6263 } else if ((dbt & VT_BTYPE) == VT_INT) {
6264 /* scalar to int */
6265 if (sbt == VT_LLONG) {
6266 /* from long long: just take low order word */
6267 lexpand();
6268 vpop();
6270 /* if lvalue and single word type, nothing to do because
6271 the lvalue already contains the real type size (see
6272 VT_LVAL_xxx constants) */
6275 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
6276 /* if we are casting between pointer types,
6277 we must update the VT_LVAL_xxx size */
6278 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
6279 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
6281 vtop->type = *type;
6284 /* return type size. Put alignment at 'a' */
6285 static int type_size(CType *type, int *a)
6287 Sym *s;
6288 int bt;
6290 bt = type->t & VT_BTYPE;
6291 if (bt == VT_STRUCT) {
6292 /* struct/union */
6293 s = type->ref;
6294 *a = s->r;
6295 return s->c;
6296 } else if (bt == VT_PTR) {
6297 if (type->t & VT_ARRAY) {
6298 int ts;
6300 s = type->ref;
6301 ts = type_size(&s->type, a);
6303 if (ts < 0 && s->c < 0)
6304 ts = -ts;
6306 return ts * s->c;
6307 } else {
6308 *a = PTR_SIZE;
6309 return PTR_SIZE;
6311 } else if (bt == VT_LDOUBLE) {
6312 *a = LDOUBLE_ALIGN;
6313 return LDOUBLE_SIZE;
6314 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
6315 #ifdef TCC_TARGET_I386
6316 #ifdef TCC_TARGET_PE
6317 *a = 8;
6318 #else
6319 *a = 4;
6320 #endif
6321 #elif defined(TCC_TARGET_ARM)
6322 #ifdef TCC_ARM_EABI
6323 *a = 8;
6324 #else
6325 *a = 4;
6326 #endif
6327 #else
6328 *a = 8;
6329 #endif
6330 return 8;
6331 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6332 *a = 4;
6333 return 4;
6334 } else if (bt == VT_SHORT) {
6335 *a = 2;
6336 return 2;
6337 } else {
6338 /* char, void, function, _Bool */
6339 *a = 1;
6340 return 1;
6344 /* return the pointed type of t */
6345 static inline CType *pointed_type(CType *type)
6347 return &type->ref->type;
6350 /* modify type so that its it is a pointer to type. */
6351 static void mk_pointer(CType *type)
6353 Sym *s;
6354 s = sym_push(SYM_FIELD, type, 0, -1);
6355 type->t = VT_PTR | (type->t & ~VT_TYPE);
6356 type->ref = s;
6359 /* compare function types. OLD functions match any new functions */
6360 static int is_compatible_func(CType *type1, CType *type2)
6362 Sym *s1, *s2;
6364 s1 = type1->ref;
6365 s2 = type2->ref;
6366 if (!is_compatible_types(&s1->type, &s2->type))
6367 return 0;
6368 /* check func_call */
6369 if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
6370 return 0;
6371 /* XXX: not complete */
6372 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6373 return 1;
6374 if (s1->c != s2->c)
6375 return 0;
6376 while (s1 != NULL) {
6377 if (s2 == NULL)
6378 return 0;
6379 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6380 return 0;
6381 s1 = s1->next;
6382 s2 = s2->next;
6384 if (s2)
6385 return 0;
6386 return 1;
6389 /* return true if type1 and type2 are the same. If unqualified is
6390 true, qualifiers on the types are ignored.
6392 - enums are not checked as gcc __builtin_types_compatible_p ()
6394 static int compare_types(CType *type1, CType *type2, int unqualified)
6396 int bt1, t1, t2;
6398 t1 = type1->t & VT_TYPE;
6399 t2 = type2->t & VT_TYPE;
6400 if (unqualified) {
6401 /* strip qualifiers before comparing */
6402 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6403 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6405 /* XXX: bitfields ? */
6406 if (t1 != t2)
6407 return 0;
6408 /* test more complicated cases */
6409 bt1 = t1 & VT_BTYPE;
6410 if (bt1 == VT_PTR) {
6411 type1 = pointed_type(type1);
6412 type2 = pointed_type(type2);
6413 return is_compatible_types(type1, type2);
6414 } else if (bt1 == VT_STRUCT) {
6415 return (type1->ref == type2->ref);
6416 } else if (bt1 == VT_FUNC) {
6417 return is_compatible_func(type1, type2);
6418 } else {
6419 return 1;
6423 /* return true if type1 and type2 are exactly the same (including
6424 qualifiers).
6426 static int is_compatible_types(CType *type1, CType *type2)
6428 return compare_types(type1,type2,0);
6431 /* return true if type1 and type2 are the same (ignoring qualifiers).
6433 static int is_compatible_parameter_types(CType *type1, CType *type2)
6435 return compare_types(type1,type2,1);
6438 /* print a type. If 'varstr' is not NULL, then the variable is also
6439 printed in the type */
6440 /* XXX: union */
6441 /* XXX: add array and function pointers */
6442 void type_to_str(char *buf, int buf_size,
6443 CType *type, const char *varstr)
6445 int bt, v, t;
6446 Sym *s, *sa;
6447 char buf1[256];
6448 const char *tstr;
6450 t = type->t & VT_TYPE;
6451 bt = t & VT_BTYPE;
6452 buf[0] = '\0';
6453 if (t & VT_CONSTANT)
6454 pstrcat(buf, buf_size, "const ");
6455 if (t & VT_VOLATILE)
6456 pstrcat(buf, buf_size, "volatile ");
6457 if (t & VT_UNSIGNED)
6458 pstrcat(buf, buf_size, "unsigned ");
6459 switch(bt) {
6460 case VT_VOID:
6461 tstr = "void";
6462 goto add_tstr;
6463 case VT_BOOL:
6464 tstr = "_Bool";
6465 goto add_tstr;
6466 case VT_BYTE:
6467 tstr = "char";
6468 goto add_tstr;
6469 case VT_SHORT:
6470 tstr = "short";
6471 goto add_tstr;
6472 case VT_INT:
6473 tstr = "int";
6474 goto add_tstr;
6475 case VT_LONG:
6476 tstr = "long";
6477 goto add_tstr;
6478 case VT_LLONG:
6479 tstr = "long long";
6480 goto add_tstr;
6481 case VT_FLOAT:
6482 tstr = "float";
6483 goto add_tstr;
6484 case VT_DOUBLE:
6485 tstr = "double";
6486 goto add_tstr;
6487 case VT_LDOUBLE:
6488 tstr = "long double";
6489 add_tstr:
6490 pstrcat(buf, buf_size, tstr);
6491 break;
6492 case VT_ENUM:
6493 case VT_STRUCT:
6494 if (bt == VT_STRUCT)
6495 tstr = "struct ";
6496 else
6497 tstr = "enum ";
6498 pstrcat(buf, buf_size, tstr);
6499 v = type->ref->v & ~SYM_STRUCT;
6500 if (v >= SYM_FIRST_ANOM)
6501 pstrcat(buf, buf_size, "<anonymous>");
6502 else
6503 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6504 break;
6505 case VT_FUNC:
6506 s = type->ref;
6507 type_to_str(buf, buf_size, &s->type, varstr);
6508 pstrcat(buf, buf_size, "(");
6509 sa = s->next;
6510 while (sa != NULL) {
6511 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6512 pstrcat(buf, buf_size, buf1);
6513 sa = sa->next;
6514 if (sa)
6515 pstrcat(buf, buf_size, ", ");
6517 pstrcat(buf, buf_size, ")");
6518 goto no_var;
6519 case VT_PTR:
6520 s = type->ref;
6521 pstrcpy(buf1, sizeof(buf1), "*");
6522 if (varstr)
6523 pstrcat(buf1, sizeof(buf1), varstr);
6524 type_to_str(buf, buf_size, &s->type, buf1);
6525 goto no_var;
6527 if (varstr) {
6528 pstrcat(buf, buf_size, " ");
6529 pstrcat(buf, buf_size, varstr);
6531 no_var: ;
6534 /* verify type compatibility to store vtop in 'dt' type, and generate
6535 casts if needed. */
6536 static void gen_assign_cast(CType *dt)
6538 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6539 char buf1[256], buf2[256];
6540 int dbt, sbt;
6542 st = &vtop->type; /* source type */
6543 dbt = dt->t & VT_BTYPE;
6544 sbt = st->t & VT_BTYPE;
6545 if (dt->t & VT_CONSTANT)
6546 warning("assignment of read-only location");
6547 switch(dbt) {
6548 case VT_PTR:
6549 /* special cases for pointers */
6550 /* '0' can also be a pointer */
6551 if (is_null_pointer(vtop))
6552 goto type_ok;
6553 /* accept implicit pointer to integer cast with warning */
6554 if (is_integer_btype(sbt)) {
6555 warning("assignment makes pointer from integer without a cast");
6556 goto type_ok;
6558 type1 = pointed_type(dt);
6559 /* a function is implicitely a function pointer */
6560 if (sbt == VT_FUNC) {
6561 if ((type1->t & VT_BTYPE) != VT_VOID &&
6562 !is_compatible_types(pointed_type(dt), st))
6563 goto error;
6564 else
6565 goto type_ok;
6567 if (sbt != VT_PTR)
6568 goto error;
6569 type2 = pointed_type(st);
6570 if ((type1->t & VT_BTYPE) == VT_VOID ||
6571 (type2->t & VT_BTYPE) == VT_VOID) {
6572 /* void * can match anything */
6573 } else {
6574 /* exact type match, except for unsigned */
6575 tmp_type1 = *type1;
6576 tmp_type2 = *type2;
6577 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6578 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6579 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6580 warning("assignment from incompatible pointer type");
6582 /* check const and volatile */
6583 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6584 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6585 warning("assignment discards qualifiers from pointer target type");
6586 break;
6587 case VT_BYTE:
6588 case VT_SHORT:
6589 case VT_INT:
6590 case VT_LLONG:
6591 if (sbt == VT_PTR || sbt == VT_FUNC) {
6592 warning("assignment makes integer from pointer without a cast");
6594 /* XXX: more tests */
6595 break;
6596 case VT_STRUCT:
6597 tmp_type1 = *dt;
6598 tmp_type2 = *st;
6599 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6600 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6601 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6602 error:
6603 type_to_str(buf1, sizeof(buf1), st, NULL);
6604 type_to_str(buf2, sizeof(buf2), dt, NULL);
6605 error("cannot cast '%s' to '%s'", buf1, buf2);
6607 break;
6609 type_ok:
6610 gen_cast(dt);
6613 /* store vtop in lvalue pushed on stack */
6614 void vstore(void)
6616 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6618 ft = vtop[-1].type.t;
6619 sbt = vtop->type.t & VT_BTYPE;
6620 dbt = ft & VT_BTYPE;
6621 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6622 (sbt == VT_INT && dbt == VT_SHORT)) {
6623 /* optimize char/short casts */
6624 delayed_cast = VT_MUSTCAST;
6625 vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));
6626 /* XXX: factorize */
6627 if (ft & VT_CONSTANT)
6628 warning("assignment of read-only location");
6629 } else {
6630 delayed_cast = 0;
6631 if (!(ft & VT_BITFIELD))
6632 gen_assign_cast(&vtop[-1].type);
6635 if (sbt == VT_STRUCT) {
6636 /* if structure, only generate pointer */
6637 /* structure assignment : generate memcpy */
6638 /* XXX: optimize if small size */
6639 if (!nocode_wanted) {
6640 size = type_size(&vtop->type, &align);
6642 #ifdef TCC_ARM_EABI
6643 if(!(align & 7))
6644 vpush_global_sym(&func_old_type, TOK_memcpy8);
6645 else if(!(align & 3))
6646 vpush_global_sym(&func_old_type, TOK_memcpy4);
6647 else
6648 #endif
6649 vpush_global_sym(&func_old_type, TOK_memcpy);
6651 /* destination */
6652 vpushv(vtop - 2);
6653 vtop->type.t = VT_PTR;
6654 gaddrof();
6655 /* source */
6656 vpushv(vtop - 2);
6657 vtop->type.t = VT_PTR;
6658 gaddrof();
6659 /* type size */
6660 vpushi(size);
6661 gfunc_call(3);
6663 vswap();
6664 vpop();
6665 } else {
6666 vswap();
6667 vpop();
6669 /* leave source on stack */
6670 } else if (ft & VT_BITFIELD) {
6671 /* bitfield store handling */
6672 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6673 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6674 /* remove bit field info to avoid loops */
6675 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6677 /* duplicate source into other register */
6678 gv_dup();
6679 vswap();
6680 vrott(3);
6682 if((ft & VT_BTYPE) == VT_BOOL) {
6683 gen_cast(&vtop[-1].type);
6684 vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
6687 /* duplicate destination */
6688 vdup();
6689 vtop[-1] = vtop[-2];
6691 /* mask and shift source */
6692 if((ft & VT_BTYPE) != VT_BOOL) {
6693 if((ft & VT_BTYPE) == VT_LLONG) {
6694 vpushll((1ULL << bit_size) - 1ULL);
6695 } else {
6696 vpushi((1 << bit_size) - 1);
6698 gen_op('&');
6700 vpushi(bit_pos);
6701 gen_op(TOK_SHL);
6702 /* load destination, mask and or with source */
6703 vswap();
6704 if((ft & VT_BTYPE) == VT_LLONG) {
6705 vpushll(~(((1ULL << bit_size) - 1ULL) << bit_pos));
6706 } else {
6707 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6709 gen_op('&');
6710 gen_op('|');
6711 /* store result */
6712 vstore();
6714 /* pop off shifted source from "duplicate source..." above */
6715 vpop();
6717 } else {
6718 #ifdef CONFIG_TCC_BCHECK
6719 /* bound check case */
6720 if (vtop[-1].r & VT_MUSTBOUND) {
6721 vswap();
6722 gbound();
6723 vswap();
6725 #endif
6726 if (!nocode_wanted) {
6727 rc = RC_INT;
6728 if (is_float(ft)) {
6729 rc = RC_FLOAT;
6730 #ifdef TCC_TARGET_X86_64
6731 if ((ft & VT_BTYPE) == VT_LDOUBLE) {
6732 rc = RC_ST0;
6734 #endif
6736 r = gv(rc); /* generate value */
6737 /* if lvalue was saved on stack, must read it */
6738 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6739 SValue sv;
6740 t = get_reg(RC_INT);
6741 #ifdef TCC_TARGET_X86_64
6742 sv.type.t = VT_PTR;
6743 #else
6744 sv.type.t = VT_INT;
6745 #endif
6746 sv.r = VT_LOCAL | VT_LVAL;
6747 sv.c.ul = vtop[-1].c.ul;
6748 load(t, &sv);
6749 vtop[-1].r = t | VT_LVAL;
6751 store(r, vtop - 1);
6752 #ifndef TCC_TARGET_X86_64
6753 /* two word case handling : store second register at word + 4 */
6754 if ((ft & VT_BTYPE) == VT_LLONG) {
6755 vswap();
6756 /* convert to int to increment easily */
6757 vtop->type.t = VT_INT;
6758 gaddrof();
6759 vpushi(4);
6760 gen_op('+');
6761 vtop->r |= VT_LVAL;
6762 vswap();
6763 /* XXX: it works because r2 is spilled last ! */
6764 store(vtop->r2, vtop - 1);
6766 #endif
6768 vswap();
6769 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6770 vtop->r |= delayed_cast;
6774 /* post defines POST/PRE add. c is the token ++ or -- */
6775 void inc(int post, int c)
6777 test_lvalue();
6778 vdup(); /* save lvalue */
6779 if (post) {
6780 gv_dup(); /* duplicate value */
6781 vrotb(3);
6782 vrotb(3);
6784 /* add constant */
6785 vpushi(c - TOK_MID);
6786 gen_op('+');
6787 vstore(); /* store value */
6788 if (post)
6789 vpop(); /* if post op, return saved value */
6792 /* Parse GNUC __attribute__ extension. Currently, the following
6793 extensions are recognized:
6794 - aligned(n) : set data/function alignment.
6795 - packed : force data alignment to 1
6796 - section(x) : generate data/code in this section.
6797 - unused : currently ignored, but may be used someday.
6798 - regparm(n) : pass function parameters in registers (i386 only)
6800 static void parse_attribute(AttributeDef *ad)
6802 int t, n;
6804 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6805 next();
6806 skip('(');
6807 skip('(');
6808 while (tok != ')') {
6809 if (tok < TOK_IDENT)
6810 expect("attribute name");
6811 t = tok;
6812 next();
6813 switch(t) {
6814 case TOK_SECTION1:
6815 case TOK_SECTION2:
6816 skip('(');
6817 if (tok != TOK_STR)
6818 expect("section name");
6819 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6820 next();
6821 skip(')');
6822 break;
6823 case TOK_ALIGNED1:
6824 case TOK_ALIGNED2:
6825 if (tok == '(') {
6826 next();
6827 n = expr_const();
6828 if (n <= 0 || (n & (n - 1)) != 0)
6829 error("alignment must be a positive power of two");
6830 skip(')');
6831 } else {
6832 n = MAX_ALIGN;
6834 ad->aligned = n;
6835 break;
6836 case TOK_PACKED1:
6837 case TOK_PACKED2:
6838 ad->packed = 1;
6839 break;
6840 case TOK_UNUSED1:
6841 case TOK_UNUSED2:
6842 /* currently, no need to handle it because tcc does not
6843 track unused objects */
6844 break;
6845 case TOK_NORETURN1:
6846 case TOK_NORETURN2:
6847 /* currently, no need to handle it because tcc does not
6848 track unused objects */
6849 break;
6850 case TOK_CDECL1:
6851 case TOK_CDECL2:
6852 case TOK_CDECL3:
6853 FUNC_CALL(ad->func_attr) = FUNC_CDECL;
6854 break;
6855 case TOK_STDCALL1:
6856 case TOK_STDCALL2:
6857 case TOK_STDCALL3:
6858 FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
6859 break;
6860 #ifdef TCC_TARGET_I386
6861 case TOK_REGPARM1:
6862 case TOK_REGPARM2:
6863 skip('(');
6864 n = expr_const();
6865 if (n > 3)
6866 n = 3;
6867 else if (n < 0)
6868 n = 0;
6869 if (n > 0)
6870 FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
6871 skip(')');
6872 break;
6873 case TOK_FASTCALL1:
6874 case TOK_FASTCALL2:
6875 case TOK_FASTCALL3:
6876 FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
6877 break;
6878 #endif
6879 case TOK_DLLEXPORT:
6880 FUNC_EXPORT(ad->func_attr) = 1;
6881 break;
6882 default:
6883 if (tcc_state->warn_unsupported)
6884 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6885 /* skip parameters */
6886 if (tok == '(') {
6887 int parenthesis = 0;
6888 do {
6889 if (tok == '(')
6890 parenthesis++;
6891 else if (tok == ')')
6892 parenthesis--;
6893 next();
6894 } while (parenthesis && tok != -1);
6896 break;
6898 if (tok != ',')
6899 break;
6900 next();
6902 skip(')');
6903 skip(')');
6907 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6908 static void struct_decl(CType *type, int u)
6910 int a, v, size, align, maxalign, c, offset;
6911 int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt;
6912 Sym *s, *ss, *ass, **ps;
6913 AttributeDef ad;
6914 CType type1, btype;
6916 a = tok; /* save decl type */
6917 next();
6918 if (tok != '{') {
6919 v = tok;
6920 next();
6921 /* struct already defined ? return it */
6922 if (v < TOK_IDENT)
6923 expect("struct/union/enum name");
6924 s = struct_find(v);
6925 if (s) {
6926 if (s->type.t != a)
6927 error("invalid type");
6928 goto do_decl;
6930 } else {
6931 v = anon_sym++;
6933 type1.t = a;
6934 /* we put an undefined size for struct/union */
6935 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6936 s->r = 0; /* default alignment is zero as gcc */
6937 /* put struct/union/enum name in type */
6938 do_decl:
6939 type->t = u;
6940 type->ref = s;
6942 if (tok == '{') {
6943 next();
6944 if (s->c != -1)
6945 error("struct/union/enum already defined");
6946 /* cannot be empty */
6947 c = 0;
6948 /* non empty enums are not allowed */
6949 if (a == TOK_ENUM) {
6950 for(;;) {
6951 v = tok;
6952 if (v < TOK_UIDENT)
6953 expect("identifier");
6954 next();
6955 if (tok == '=') {
6956 next();
6957 c = expr_const();
6959 /* enum symbols have static storage */
6960 ss = sym_push(v, &int_type, VT_CONST, c);
6961 ss->type.t |= VT_STATIC;
6962 if (tok != ',')
6963 break;
6964 next();
6965 c++;
6966 /* NOTE: we accept a trailing comma */
6967 if (tok == '}')
6968 break;
6970 skip('}');
6971 } else {
6972 maxalign = 1;
6973 ps = &s->next;
6974 prevbt = VT_INT;
6975 bit_pos = 0;
6976 offset = 0;
6977 while (tok != '}') {
6978 parse_btype(&btype, &ad);
6979 while (1) {
6980 bit_size = -1;
6981 v = 0;
6982 type1 = btype;
6983 if (tok != ':') {
6984 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6985 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6986 expect("identifier");
6987 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6988 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6989 error("invalid type for '%s'",
6990 get_tok_str(v, NULL));
6992 if (tok == ':') {
6993 next();
6994 bit_size = expr_const();
6995 /* XXX: handle v = 0 case for messages */
6996 if (bit_size < 0)
6997 error("negative width in bit-field '%s'",
6998 get_tok_str(v, NULL));
6999 if (v && bit_size == 0)
7000 error("zero width for bit-field '%s'",
7001 get_tok_str(v, NULL));
7003 size = type_size(&type1, &align);
7004 if (ad.aligned) {
7005 if (align < ad.aligned)
7006 align = ad.aligned;
7007 } else if (ad.packed) {
7008 align = 1;
7009 } else if (*tcc_state->pack_stack_ptr) {
7010 if (align > *tcc_state->pack_stack_ptr)
7011 align = *tcc_state->pack_stack_ptr;
7013 lbit_pos = 0;
7014 if (bit_size >= 0) {
7015 bt = type1.t & VT_BTYPE;
7016 if (bt != VT_INT &&
7017 bt != VT_BYTE &&
7018 bt != VT_SHORT &&
7019 bt != VT_BOOL &&
7020 bt != VT_ENUM &&
7021 bt != VT_LLONG)
7022 error("bitfields must have scalar type");
7023 bsize = size * 8;
7024 if (bit_size > bsize) {
7025 error("width of '%s' exceeds its type",
7026 get_tok_str(v, NULL));
7027 } else if (bit_size == bsize) {
7028 /* no need for bit fields */
7029 bit_pos = 0;
7030 } else if (bit_size == 0) {
7031 /* XXX: what to do if only padding in a
7032 structure ? */
7033 /* zero size: means to pad */
7034 bit_pos = 0;
7035 } else {
7036 /* we do not have enough room ?
7037 did the type change?
7038 is it a union? */
7039 if ((bit_pos + bit_size) > bsize ||
7040 bt != prevbt || a == TOK_UNION)
7041 bit_pos = 0;
7042 lbit_pos = bit_pos;
7043 /* XXX: handle LSB first */
7044 type1.t |= VT_BITFIELD |
7045 (bit_pos << VT_STRUCT_SHIFT) |
7046 (bit_size << (VT_STRUCT_SHIFT + 6));
7047 bit_pos += bit_size;
7049 prevbt = bt;
7050 } else {
7051 bit_pos = 0;
7053 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
7054 /* add new memory data only if starting
7055 bit field */
7056 if (lbit_pos == 0) {
7057 if (a == TOK_STRUCT) {
7058 c = (c + align - 1) & -align;
7059 offset = c;
7060 if (size > 0)
7061 c += size;
7062 } else {
7063 offset = 0;
7064 if (size > c)
7065 c = size;
7067 if (align > maxalign)
7068 maxalign = align;
7070 #if 0
7071 printf("add field %s offset=%d",
7072 get_tok_str(v, NULL), offset);
7073 if (type1.t & VT_BITFIELD) {
7074 printf(" pos=%d size=%d",
7075 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
7076 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
7078 printf("\n");
7079 #endif
7081 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
7082 ass = type1.ref;
7083 while ((ass = ass->next) != NULL) {
7084 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
7085 *ps = ss;
7086 ps = &ss->next;
7088 } else if (v) {
7089 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
7090 *ps = ss;
7091 ps = &ss->next;
7093 if (tok == ';' || tok == TOK_EOF)
7094 break;
7095 skip(',');
7097 skip(';');
7099 skip('}');
7100 /* store size and alignment */
7101 s->c = (c + maxalign - 1) & -maxalign;
7102 s->r = maxalign;
7107 /* return 0 if no type declaration. otherwise, return the basic type
7108 and skip it.
7110 static int parse_btype(CType *type, AttributeDef *ad)
7112 int t, u, type_found, typespec_found, typedef_found;
7113 Sym *s;
7114 CType type1;
7116 memset(ad, 0, sizeof(AttributeDef));
7117 type_found = 0;
7118 typespec_found = 0;
7119 typedef_found = 0;
7120 t = 0;
7121 while(1) {
7122 switch(tok) {
7123 case TOK_EXTENSION:
7124 /* currently, we really ignore extension */
7125 next();
7126 continue;
7128 /* basic types */
7129 case TOK_CHAR:
7130 u = VT_BYTE;
7131 basic_type:
7132 next();
7133 basic_type1:
7134 if ((t & VT_BTYPE) != 0)
7135 error("too many basic types");
7136 t |= u;
7137 typespec_found = 1;
7138 break;
7139 case TOK_VOID:
7140 u = VT_VOID;
7141 goto basic_type;
7142 case TOK_SHORT:
7143 u = VT_SHORT;
7144 goto basic_type;
7145 case TOK_INT:
7146 next();
7147 typespec_found = 1;
7148 break;
7149 case TOK_LONG:
7150 next();
7151 if ((t & VT_BTYPE) == VT_DOUBLE) {
7152 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
7153 } else if ((t & VT_BTYPE) == VT_LONG) {
7154 t = (t & ~VT_BTYPE) | VT_LLONG;
7155 } else {
7156 u = VT_LONG;
7157 goto basic_type1;
7159 break;
7160 case TOK_BOOL:
7161 u = VT_BOOL;
7162 goto basic_type;
7163 case TOK_FLOAT:
7164 u = VT_FLOAT;
7165 goto basic_type;
7166 case TOK_DOUBLE:
7167 next();
7168 if ((t & VT_BTYPE) == VT_LONG) {
7169 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
7170 } else {
7171 u = VT_DOUBLE;
7172 goto basic_type1;
7174 break;
7175 case TOK_ENUM:
7176 struct_decl(&type1, VT_ENUM);
7177 basic_type2:
7178 u = type1.t;
7179 type->ref = type1.ref;
7180 goto basic_type1;
7181 case TOK_STRUCT:
7182 case TOK_UNION:
7183 struct_decl(&type1, VT_STRUCT);
7184 goto basic_type2;
7186 /* type modifiers */
7187 case TOK_CONST1:
7188 case TOK_CONST2:
7189 case TOK_CONST3:
7190 t |= VT_CONSTANT;
7191 next();
7192 break;
7193 case TOK_VOLATILE1:
7194 case TOK_VOLATILE2:
7195 case TOK_VOLATILE3:
7196 t |= VT_VOLATILE;
7197 next();
7198 break;
7199 case TOK_SIGNED1:
7200 case TOK_SIGNED2:
7201 case TOK_SIGNED3:
7202 typespec_found = 1;
7203 t |= VT_SIGNED;
7204 next();
7205 break;
7206 case TOK_REGISTER:
7207 case TOK_AUTO:
7208 case TOK_RESTRICT1:
7209 case TOK_RESTRICT2:
7210 case TOK_RESTRICT3:
7211 next();
7212 break;
7213 case TOK_UNSIGNED:
7214 t |= VT_UNSIGNED;
7215 next();
7216 typespec_found = 1;
7217 break;
7219 /* storage */
7220 case TOK_EXTERN:
7221 t |= VT_EXTERN;
7222 next();
7223 break;
7224 case TOK_STATIC:
7225 t |= VT_STATIC;
7226 next();
7227 break;
7228 case TOK_TYPEDEF:
7229 t |= VT_TYPEDEF;
7230 next();
7231 break;
7232 case TOK_INLINE1:
7233 case TOK_INLINE2:
7234 case TOK_INLINE3:
7235 t |= VT_INLINE;
7236 next();
7237 break;
7239 /* GNUC attribute */
7240 case TOK_ATTRIBUTE1:
7241 case TOK_ATTRIBUTE2:
7242 parse_attribute(ad);
7243 break;
7244 /* GNUC typeof */
7245 case TOK_TYPEOF1:
7246 case TOK_TYPEOF2:
7247 case TOK_TYPEOF3:
7248 next();
7249 parse_expr_type(&type1);
7250 goto basic_type2;
7251 default:
7252 if (typespec_found || typedef_found)
7253 goto the_end;
7254 s = sym_find(tok);
7255 if (!s || !(s->type.t & VT_TYPEDEF))
7256 goto the_end;
7257 typedef_found = 1;
7258 t |= (s->type.t & ~VT_TYPEDEF);
7259 type->ref = s->type.ref;
7260 next();
7261 typespec_found = 1;
7262 break;
7264 type_found = 1;
7266 the_end:
7267 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
7268 error("signed and unsigned modifier");
7269 if (tcc_state->char_is_unsigned) {
7270 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
7271 t |= VT_UNSIGNED;
7273 t &= ~VT_SIGNED;
7275 /* long is never used as type */
7276 if ((t & VT_BTYPE) == VT_LONG)
7277 #ifndef TCC_TARGET_X86_64
7278 t = (t & ~VT_BTYPE) | VT_INT;
7279 #else
7280 t = (t & ~VT_BTYPE) | VT_LLONG;
7281 #endif
7282 type->t = t;
7283 return type_found;
7286 /* convert a function parameter type (array to pointer and function to
7287 function pointer) */
7288 static inline void convert_parameter_type(CType *pt)
7290 /* remove const and volatile qualifiers (XXX: const could be used
7291 to indicate a const function parameter */
7292 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
7293 /* array must be transformed to pointer according to ANSI C */
7294 pt->t &= ~VT_ARRAY;
7295 if ((pt->t & VT_BTYPE) == VT_FUNC) {
7296 mk_pointer(pt);
7300 static void post_type(CType *type, AttributeDef *ad)
7302 int n, l, t1, arg_size, align;
7303 Sym **plast, *s, *first;
7304 AttributeDef ad1;
7305 CType pt;
7307 if (tok == '(') {
7308 /* function declaration */
7309 next();
7310 l = 0;
7311 first = NULL;
7312 plast = &first;
7313 arg_size = 0;
7314 if (tok != ')') {
7315 for(;;) {
7316 /* read param name and compute offset */
7317 if (l != FUNC_OLD) {
7318 if (!parse_btype(&pt, &ad1)) {
7319 if (l) {
7320 error("invalid type");
7321 } else {
7322 l = FUNC_OLD;
7323 goto old_proto;
7326 l = FUNC_NEW;
7327 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
7328 break;
7329 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
7330 if ((pt.t & VT_BTYPE) == VT_VOID)
7331 error("parameter declared as void");
7332 arg_size += (type_size(&pt, &align) + 3) & ~3;
7333 } else {
7334 old_proto:
7335 n = tok;
7336 if (n < TOK_UIDENT)
7337 expect("identifier");
7338 pt.t = VT_INT;
7339 next();
7341 convert_parameter_type(&pt);
7342 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
7343 *plast = s;
7344 plast = &s->next;
7345 if (tok == ')')
7346 break;
7347 skip(',');
7348 if (l == FUNC_NEW && tok == TOK_DOTS) {
7349 l = FUNC_ELLIPSIS;
7350 next();
7351 break;
7355 /* if no parameters, then old type prototype */
7356 if (l == 0)
7357 l = FUNC_OLD;
7358 skip(')');
7359 t1 = type->t & VT_STORAGE;
7360 /* NOTE: const is ignored in returned type as it has a special
7361 meaning in gcc / C++ */
7362 type->t &= ~(VT_STORAGE | VT_CONSTANT);
7363 post_type(type, ad);
7364 /* we push a anonymous symbol which will contain the function prototype */
7365 FUNC_ARGS(ad->func_attr) = arg_size;
7366 s = sym_push(SYM_FIELD, type, ad->func_attr, l);
7367 s->next = first;
7368 type->t = t1 | VT_FUNC;
7369 type->ref = s;
7370 } else if (tok == '[') {
7371 /* array definition */
7372 next();
7373 if (tok == TOK_RESTRICT1)
7374 next();
7375 n = -1;
7376 if (tok != ']') {
7377 n = expr_const();
7378 if (n < 0)
7379 error("invalid array size");
7381 skip(']');
7382 /* parse next post type */
7383 t1 = type->t & VT_STORAGE;
7384 type->t &= ~VT_STORAGE;
7385 post_type(type, ad);
7387 /* we push a anonymous symbol which will contain the array
7388 element type */
7389 s = sym_push(SYM_FIELD, type, 0, n);
7390 type->t = t1 | VT_ARRAY | VT_PTR;
7391 type->ref = s;
7395 /* Parse a type declaration (except basic type), and return the type
7396 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7397 expected. 'type' should contain the basic type. 'ad' is the
7398 attribute definition of the basic type. It can be modified by
7399 type_decl().
7401 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7403 Sym *s;
7404 CType type1, *type2;
7405 int qualifiers;
7407 while (tok == '*') {
7408 qualifiers = 0;
7409 redo:
7410 next();
7411 switch(tok) {
7412 case TOK_CONST1:
7413 case TOK_CONST2:
7414 case TOK_CONST3:
7415 qualifiers |= VT_CONSTANT;
7416 goto redo;
7417 case TOK_VOLATILE1:
7418 case TOK_VOLATILE2:
7419 case TOK_VOLATILE3:
7420 qualifiers |= VT_VOLATILE;
7421 goto redo;
7422 case TOK_RESTRICT1:
7423 case TOK_RESTRICT2:
7424 case TOK_RESTRICT3:
7425 goto redo;
7427 mk_pointer(type);
7428 type->t |= qualifiers;
7431 /* XXX: clarify attribute handling */
7432 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7433 parse_attribute(ad);
7435 /* recursive type */
7436 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7437 type1.t = 0; /* XXX: same as int */
7438 if (tok == '(') {
7439 next();
7440 /* XXX: this is not correct to modify 'ad' at this point, but
7441 the syntax is not clear */
7442 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7443 parse_attribute(ad);
7444 type_decl(&type1, ad, v, td);
7445 skip(')');
7446 } else {
7447 /* type identifier */
7448 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7449 *v = tok;
7450 next();
7451 } else {
7452 if (!(td & TYPE_ABSTRACT))
7453 expect("identifier");
7454 *v = 0;
7457 post_type(type, ad);
7458 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7459 parse_attribute(ad);
7460 if (!type1.t)
7461 return;
7462 /* append type at the end of type1 */
7463 type2 = &type1;
7464 for(;;) {
7465 s = type2->ref;
7466 type2 = &s->type;
7467 if (!type2->t) {
7468 *type2 = *type;
7469 break;
7472 *type = type1;
7475 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7476 static int lvalue_type(int t)
7478 int bt, r;
7479 r = VT_LVAL;
7480 bt = t & VT_BTYPE;
7481 if (bt == VT_BYTE || bt == VT_BOOL)
7482 r |= VT_LVAL_BYTE;
7483 else if (bt == VT_SHORT)
7484 r |= VT_LVAL_SHORT;
7485 else
7486 return r;
7487 if (t & VT_UNSIGNED)
7488 r |= VT_LVAL_UNSIGNED;
7489 return r;
7492 /* indirection with full error checking and bound check */
7493 static void indir(void)
7495 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7496 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7497 return;
7498 expect("pointer");
7500 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7501 gv(RC_INT);
7502 vtop->type = *pointed_type(&vtop->type);
7503 /* Arrays and functions are never lvalues */
7504 if (!(vtop->type.t & VT_ARRAY)
7505 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7506 vtop->r |= lvalue_type(vtop->type.t);
7507 /* if bound checking, the referenced pointer must be checked */
7508 if (do_bounds_check)
7509 vtop->r |= VT_MUSTBOUND;
7513 /* pass a parameter to a function and do type checking and casting */
7514 static void gfunc_param_typed(Sym *func, Sym *arg)
7516 int func_type;
7517 CType type;
7519 func_type = func->c;
7520 if (func_type == FUNC_OLD ||
7521 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7522 /* default casting : only need to convert float to double */
7523 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7524 type.t = VT_DOUBLE;
7525 gen_cast(&type);
7527 } else if (arg == NULL) {
7528 error("too many arguments to function");
7529 } else {
7530 type = arg->type;
7531 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7532 gen_assign_cast(&type);
7536 /* parse an expression of the form '(type)' or '(expr)' and return its
7537 type */
7538 static void parse_expr_type(CType *type)
7540 int n;
7541 AttributeDef ad;
7543 skip('(');
7544 if (parse_btype(type, &ad)) {
7545 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7546 } else {
7547 expr_type(type);
7549 skip(')');
7552 static void parse_type(CType *type)
7554 AttributeDef ad;
7555 int n;
7557 if (!parse_btype(type, &ad)) {
7558 expect("type");
7560 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7563 static void vpush_tokc(int t)
7565 CType type;
7566 type.t = t;
7567 vsetc(&type, VT_CONST, &tokc);
7570 static void unary(void)
7572 int n, t, align, size, r;
7573 CType type;
7574 Sym *s;
7575 AttributeDef ad;
7577 /* XXX: GCC 2.95.3 does not generate a table although it should be
7578 better here */
7579 tok_next:
7580 switch(tok) {
7581 case TOK_EXTENSION:
7582 next();
7583 goto tok_next;
7584 case TOK_CINT:
7585 case TOK_CCHAR:
7586 case TOK_LCHAR:
7587 vpushi(tokc.i);
7588 next();
7589 break;
7590 case TOK_CUINT:
7591 vpush_tokc(VT_INT | VT_UNSIGNED);
7592 next();
7593 break;
7594 case TOK_CLLONG:
7595 vpush_tokc(VT_LLONG);
7596 next();
7597 break;
7598 case TOK_CULLONG:
7599 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7600 next();
7601 break;
7602 case TOK_CFLOAT:
7603 vpush_tokc(VT_FLOAT);
7604 next();
7605 break;
7606 case TOK_CDOUBLE:
7607 vpush_tokc(VT_DOUBLE);
7608 next();
7609 break;
7610 case TOK_CLDOUBLE:
7611 vpush_tokc(VT_LDOUBLE);
7612 next();
7613 break;
7614 case TOK___FUNCTION__:
7615 if (!gnu_ext)
7616 goto tok_identifier;
7617 /* fall thru */
7618 case TOK___FUNC__:
7620 void *ptr;
7621 int len;
7622 /* special function name identifier */
7623 len = strlen(funcname) + 1;
7624 /* generate char[len] type */
7625 type.t = VT_BYTE;
7626 mk_pointer(&type);
7627 type.t |= VT_ARRAY;
7628 type.ref->c = len;
7629 vpush_ref(&type, data_section, data_section->data_offset, len);
7630 ptr = section_ptr_add(data_section, len);
7631 memcpy(ptr, funcname, len);
7632 next();
7634 break;
7635 case TOK_LSTR:
7636 #ifdef TCC_TARGET_PE
7637 t = VT_SHORT | VT_UNSIGNED;
7638 #else
7639 t = VT_INT;
7640 #endif
7641 goto str_init;
7642 case TOK_STR:
7643 /* string parsing */
7644 t = VT_BYTE;
7645 str_init:
7646 if (tcc_state->warn_write_strings)
7647 t |= VT_CONSTANT;
7648 type.t = t;
7649 mk_pointer(&type);
7650 type.t |= VT_ARRAY;
7651 memset(&ad, 0, sizeof(AttributeDef));
7652 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7653 break;
7654 case '(':
7655 next();
7656 /* cast ? */
7657 if (parse_btype(&type, &ad)) {
7658 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7659 skip(')');
7660 /* check ISOC99 compound literal */
7661 if (tok == '{') {
7662 /* data is allocated locally by default */
7663 if (global_expr)
7664 r = VT_CONST;
7665 else
7666 r = VT_LOCAL;
7667 /* all except arrays are lvalues */
7668 if (!(type.t & VT_ARRAY))
7669 r |= lvalue_type(type.t);
7670 memset(&ad, 0, sizeof(AttributeDef));
7671 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7672 } else {
7673 unary();
7674 gen_cast(&type);
7676 } else if (tok == '{') {
7677 /* save all registers */
7678 save_regs(0);
7679 /* statement expression : we do not accept break/continue
7680 inside as GCC does */
7681 block(NULL, NULL, NULL, NULL, 0, 1);
7682 skip(')');
7683 } else {
7684 gexpr();
7685 skip(')');
7687 break;
7688 case '*':
7689 next();
7690 unary();
7691 indir();
7692 break;
7693 case '&':
7694 next();
7695 unary();
7696 /* functions names must be treated as function pointers,
7697 except for unary '&' and sizeof. Since we consider that
7698 functions are not lvalues, we only have to handle it
7699 there and in function calls. */
7700 /* arrays can also be used although they are not lvalues */
7701 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7702 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7703 test_lvalue();
7704 mk_pointer(&vtop->type);
7705 gaddrof();
7706 break;
7707 case '!':
7708 next();
7709 unary();
7710 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
7711 CType boolean;
7712 boolean.t = VT_BOOL;
7713 gen_cast(&boolean);
7714 vtop->c.i = !vtop->c.i;
7715 } else if ((vtop->r & VT_VALMASK) == VT_CMP)
7716 vtop->c.i = vtop->c.i ^ 1;
7717 else {
7718 save_regs(1);
7719 vseti(VT_JMP, gtst(1, 0));
7721 break;
7722 case '~':
7723 next();
7724 unary();
7725 vpushi(-1);
7726 gen_op('^');
7727 break;
7728 case '+':
7729 next();
7730 /* in order to force cast, we add zero */
7731 unary();
7732 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7733 error("pointer not accepted for unary plus");
7734 vpushi(0);
7735 gen_op('+');
7736 break;
7737 case TOK_SIZEOF:
7738 case TOK_ALIGNOF1:
7739 case TOK_ALIGNOF2:
7740 t = tok;
7741 next();
7742 if (tok == '(') {
7743 parse_expr_type(&type);
7744 } else {
7745 unary_type(&type);
7747 size = type_size(&type, &align);
7748 if (t == TOK_SIZEOF) {
7749 if (size < 0)
7750 error("sizeof applied to an incomplete type");
7751 vpushi(size);
7752 } else {
7753 vpushi(align);
7755 vtop->type.t |= VT_UNSIGNED;
7756 break;
7758 case TOK_builtin_types_compatible_p:
7760 CType type1, type2;
7761 next();
7762 skip('(');
7763 parse_type(&type1);
7764 skip(',');
7765 parse_type(&type2);
7766 skip(')');
7767 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7768 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7769 vpushi(is_compatible_types(&type1, &type2));
7771 break;
7772 case TOK_builtin_constant_p:
7774 int saved_nocode_wanted, res;
7775 next();
7776 skip('(');
7777 saved_nocode_wanted = nocode_wanted;
7778 nocode_wanted = 1;
7779 gexpr();
7780 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7781 vpop();
7782 nocode_wanted = saved_nocode_wanted;
7783 skip(')');
7784 vpushi(res);
7786 break;
7787 case TOK_builtin_frame_address:
7789 CType type;
7790 next();
7791 skip('(');
7792 if (tok != TOK_CINT) {
7793 error("__builtin_frame_address only takes integers");
7795 if (tokc.i != 0) {
7796 error("TCC only supports __builtin_frame_address(0)");
7798 next();
7799 skip(')');
7800 type.t = VT_VOID;
7801 mk_pointer(&type);
7802 vset(&type, VT_LOCAL, 0);
7804 break;
7805 #ifdef TCC_TARGET_X86_64
7806 case TOK_builtin_malloc:
7807 tok = TOK_malloc;
7808 goto tok_identifier;
7809 case TOK_builtin_free:
7810 tok = TOK_free;
7811 goto tok_identifier;
7812 #endif
7813 case TOK_INC:
7814 case TOK_DEC:
7815 t = tok;
7816 next();
7817 unary();
7818 inc(0, t);
7819 break;
7820 case '-':
7821 next();
7822 vpushi(0);
7823 unary();
7824 gen_op('-');
7825 break;
7826 case TOK_LAND:
7827 if (!gnu_ext)
7828 goto tok_identifier;
7829 next();
7830 /* allow to take the address of a label */
7831 if (tok < TOK_UIDENT)
7832 expect("label identifier");
7833 s = label_find(tok);
7834 if (!s) {
7835 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7836 } else {
7837 if (s->r == LABEL_DECLARED)
7838 s->r = LABEL_FORWARD;
7840 if (!s->type.t) {
7841 s->type.t = VT_VOID;
7842 mk_pointer(&s->type);
7843 s->type.t |= VT_STATIC;
7845 vset(&s->type, VT_CONST | VT_SYM, 0);
7846 vtop->sym = s;
7847 next();
7848 break;
7849 default:
7850 tok_identifier:
7851 t = tok;
7852 next();
7853 if (t < TOK_UIDENT)
7854 expect("identifier");
7855 s = sym_find(t);
7856 if (!s) {
7857 if (tok != '(')
7858 error("'%s' undeclared", get_tok_str(t, NULL));
7859 /* for simple function calls, we tolerate undeclared
7860 external reference to int() function */
7861 if (tcc_state->warn_implicit_function_declaration)
7862 warning("implicit declaration of function '%s'",
7863 get_tok_str(t, NULL));
7864 s = external_global_sym(t, &func_old_type, 0);
7866 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7867 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7868 /* if referencing an inline function, then we generate a
7869 symbol to it if not already done. It will have the
7870 effect to generate code for it at the end of the
7871 compilation unit. Inline function as always
7872 generated in the text section. */
7873 if (!s->c)
7874 put_extern_sym(s, text_section, 0, 0);
7875 r = VT_SYM | VT_CONST;
7876 } else {
7877 r = s->r;
7879 vset(&s->type, r, s->c);
7880 /* if forward reference, we must point to s */
7881 if (vtop->r & VT_SYM) {
7882 vtop->sym = s;
7883 vtop->c.ul = 0;
7885 break;
7888 /* post operations */
7889 while (1) {
7890 if (tok == TOK_INC || tok == TOK_DEC) {
7891 inc(1, tok);
7892 next();
7893 } else if (tok == '.' || tok == TOK_ARROW) {
7894 /* field */
7895 if (tok == TOK_ARROW)
7896 indir();
7897 test_lvalue();
7898 gaddrof();
7899 next();
7900 /* expect pointer on structure */
7901 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7902 expect("struct or union");
7903 s = vtop->type.ref;
7904 /* find field */
7905 tok |= SYM_FIELD;
7906 while ((s = s->next) != NULL) {
7907 if (s->v == tok)
7908 break;
7910 if (!s)
7911 error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL));
7912 /* add field offset to pointer */
7913 vtop->type = char_pointer_type; /* change type to 'char *' */
7914 vpushi(s->c);
7915 gen_op('+');
7916 /* change type to field type, and set to lvalue */
7917 vtop->type = s->type;
7918 /* an array is never an lvalue */
7919 if (!(vtop->type.t & VT_ARRAY)) {
7920 vtop->r |= lvalue_type(vtop->type.t);
7921 /* if bound checking, the referenced pointer must be checked */
7922 if (do_bounds_check)
7923 vtop->r |= VT_MUSTBOUND;
7925 next();
7926 } else if (tok == '[') {
7927 next();
7928 gexpr();
7929 gen_op('+');
7930 indir();
7931 skip(']');
7932 } else if (tok == '(') {
7933 SValue ret;
7934 Sym *sa;
7935 int nb_args;
7937 /* function call */
7938 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7939 /* pointer test (no array accepted) */
7940 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7941 vtop->type = *pointed_type(&vtop->type);
7942 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7943 goto error_func;
7944 } else {
7945 error_func:
7946 expect("function pointer");
7948 } else {
7949 vtop->r &= ~VT_LVAL; /* no lvalue */
7951 /* get return type */
7952 s = vtop->type.ref;
7953 next();
7954 sa = s->next; /* first parameter */
7955 nb_args = 0;
7956 ret.r2 = VT_CONST;
7957 /* compute first implicit argument if a structure is returned */
7958 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7959 /* get some space for the returned structure */
7960 size = type_size(&s->type, &align);
7961 loc = (loc - size) & -align;
7962 ret.type = s->type;
7963 ret.r = VT_LOCAL | VT_LVAL;
7964 /* pass it as 'int' to avoid structure arg passing
7965 problems */
7966 vseti(VT_LOCAL, loc);
7967 ret.c = vtop->c;
7968 nb_args++;
7969 } else {
7970 ret.type = s->type;
7971 /* return in register */
7972 if (is_float(ret.type.t)) {
7973 ret.r = reg_fret(ret.type.t);
7974 } else {
7975 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7976 ret.r2 = REG_LRET;
7977 ret.r = REG_IRET;
7979 ret.c.i = 0;
7981 if (tok != ')') {
7982 for(;;) {
7983 expr_eq();
7984 gfunc_param_typed(s, sa);
7985 nb_args++;
7986 if (sa)
7987 sa = sa->next;
7988 if (tok == ')')
7989 break;
7990 skip(',');
7993 if (sa)
7994 error("too few arguments to function");
7995 skip(')');
7996 if (!nocode_wanted) {
7997 gfunc_call(nb_args);
7998 } else {
7999 vtop -= (nb_args + 1);
8001 /* return value */
8002 vsetc(&ret.type, ret.r, &ret.c);
8003 vtop->r2 = ret.r2;
8004 } else {
8005 break;
8010 static void uneq(void)
8012 int t;
8014 unary();
8015 if (tok == '=' ||
8016 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
8017 tok == TOK_A_XOR || tok == TOK_A_OR ||
8018 tok == TOK_A_SHL || tok == TOK_A_SAR) {
8019 test_lvalue();
8020 t = tok;
8021 next();
8022 if (t == '=') {
8023 expr_eq();
8024 } else {
8025 vdup();
8026 expr_eq();
8027 gen_op(t & 0x7f);
8029 vstore();
8033 static void expr_prod(void)
8035 int t;
8037 uneq();
8038 while (tok == '*' || tok == '/' || tok == '%') {
8039 t = tok;
8040 next();
8041 uneq();
8042 gen_op(t);
8046 static void expr_sum(void)
8048 int t;
8050 expr_prod();
8051 while (tok == '+' || tok == '-') {
8052 t = tok;
8053 next();
8054 expr_prod();
8055 gen_op(t);
8059 static void expr_shift(void)
8061 int t;
8063 expr_sum();
8064 while (tok == TOK_SHL || tok == TOK_SAR) {
8065 t = tok;
8066 next();
8067 expr_sum();
8068 gen_op(t);
8072 static void expr_cmp(void)
8074 int t;
8076 expr_shift();
8077 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
8078 tok == TOK_ULT || tok == TOK_UGE) {
8079 t = tok;
8080 next();
8081 expr_shift();
8082 gen_op(t);
8086 static void expr_cmpeq(void)
8088 int t;
8090 expr_cmp();
8091 while (tok == TOK_EQ || tok == TOK_NE) {
8092 t = tok;
8093 next();
8094 expr_cmp();
8095 gen_op(t);
8099 static void expr_and(void)
8101 expr_cmpeq();
8102 while (tok == '&') {
8103 next();
8104 expr_cmpeq();
8105 gen_op('&');
8109 static void expr_xor(void)
8111 expr_and();
8112 while (tok == '^') {
8113 next();
8114 expr_and();
8115 gen_op('^');
8119 static void expr_or(void)
8121 expr_xor();
8122 while (tok == '|') {
8123 next();
8124 expr_xor();
8125 gen_op('|');
8129 /* XXX: fix this mess */
8130 static void expr_land_const(void)
8132 expr_or();
8133 while (tok == TOK_LAND) {
8134 next();
8135 expr_or();
8136 gen_op(TOK_LAND);
8140 /* XXX: fix this mess */
8141 static void expr_lor_const(void)
8143 expr_land_const();
8144 while (tok == TOK_LOR) {
8145 next();
8146 expr_land_const();
8147 gen_op(TOK_LOR);
8151 /* only used if non constant */
8152 static void expr_land(void)
8154 int t;
8156 expr_or();
8157 if (tok == TOK_LAND) {
8158 t = 0;
8159 save_regs(1);
8160 for(;;) {
8161 t = gtst(1, t);
8162 if (tok != TOK_LAND) {
8163 vseti(VT_JMPI, t);
8164 break;
8166 next();
8167 expr_or();
8172 static void expr_lor(void)
8174 int t;
8176 expr_land();
8177 if (tok == TOK_LOR) {
8178 t = 0;
8179 save_regs(1);
8180 for(;;) {
8181 t = gtst(0, t);
8182 if (tok != TOK_LOR) {
8183 vseti(VT_JMP, t);
8184 break;
8186 next();
8187 expr_land();
8192 /* XXX: better constant handling */
8193 static void expr_eq(void)
8195 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
8196 SValue sv;
8197 CType type, type1, type2;
8199 if (const_wanted) {
8200 expr_lor_const();
8201 if (tok == '?') {
8202 CType boolean;
8203 int c;
8204 boolean.t = VT_BOOL;
8205 vdup();
8206 gen_cast(&boolean);
8207 c = vtop->c.i;
8208 vpop();
8209 next();
8210 if (tok != ':' || !gnu_ext) {
8211 vpop();
8212 gexpr();
8214 if (!c)
8215 vpop();
8216 skip(':');
8217 expr_eq();
8218 if (c)
8219 vpop();
8221 } else {
8222 expr_lor();
8223 if (tok == '?') {
8224 next();
8225 if (vtop != vstack) {
8226 /* needed to avoid having different registers saved in
8227 each branch */
8228 if (is_float(vtop->type.t)) {
8229 rc = RC_FLOAT;
8230 #ifdef TCC_TARGET_X86_64
8231 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
8232 rc = RC_ST0;
8234 #endif
8236 else
8237 rc = RC_INT;
8238 gv(rc);
8239 save_regs(1);
8241 if (tok == ':' && gnu_ext) {
8242 gv_dup();
8243 tt = gtst(1, 0);
8244 } else {
8245 tt = gtst(1, 0);
8246 gexpr();
8248 type1 = vtop->type;
8249 sv = *vtop; /* save value to handle it later */
8250 vtop--; /* no vpop so that FP stack is not flushed */
8251 skip(':');
8252 u = gjmp(0);
8253 gsym(tt);
8254 expr_eq();
8255 type2 = vtop->type;
8257 t1 = type1.t;
8258 bt1 = t1 & VT_BTYPE;
8259 t2 = type2.t;
8260 bt2 = t2 & VT_BTYPE;
8261 /* cast operands to correct type according to ISOC rules */
8262 if (is_float(bt1) || is_float(bt2)) {
8263 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
8264 type.t = VT_LDOUBLE;
8265 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
8266 type.t = VT_DOUBLE;
8267 } else {
8268 type.t = VT_FLOAT;
8270 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
8271 /* cast to biggest op */
8272 type.t = VT_LLONG;
8273 /* convert to unsigned if it does not fit in a long long */
8274 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
8275 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
8276 type.t |= VT_UNSIGNED;
8277 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
8278 /* XXX: test pointer compatibility */
8279 type = type1;
8280 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
8281 /* XXX: test function pointer compatibility */
8282 type = type1;
8283 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
8284 /* XXX: test structure compatibility */
8285 type = type1;
8286 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
8287 /* NOTE: as an extension, we accept void on only one side */
8288 type.t = VT_VOID;
8289 } else {
8290 /* integer operations */
8291 type.t = VT_INT;
8292 /* convert to unsigned if it does not fit in an integer */
8293 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
8294 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
8295 type.t |= VT_UNSIGNED;
8298 /* now we convert second operand */
8299 gen_cast(&type);
8300 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8301 gaddrof();
8302 rc = RC_INT;
8303 if (is_float(type.t)) {
8304 rc = RC_FLOAT;
8305 #ifdef TCC_TARGET_X86_64
8306 if ((type.t & VT_BTYPE) == VT_LDOUBLE) {
8307 rc = RC_ST0;
8309 #endif
8310 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
8311 /* for long longs, we use fixed registers to avoid having
8312 to handle a complicated move */
8313 rc = RC_IRET;
8316 r2 = gv(rc);
8317 /* this is horrible, but we must also convert first
8318 operand */
8319 tt = gjmp(0);
8320 gsym(u);
8321 /* put again first value and cast it */
8322 *vtop = sv;
8323 gen_cast(&type);
8324 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8325 gaddrof();
8326 r1 = gv(rc);
8327 move_reg(r2, r1);
8328 vtop->r = r2;
8329 gsym(tt);
8334 static void gexpr(void)
8336 while (1) {
8337 expr_eq();
8338 if (tok != ',')
8339 break;
8340 vpop();
8341 next();
8345 /* parse an expression and return its type without any side effect. */
8346 static void expr_type(CType *type)
8348 int saved_nocode_wanted;
8350 saved_nocode_wanted = nocode_wanted;
8351 nocode_wanted = 1;
8352 gexpr();
8353 *type = vtop->type;
8354 vpop();
8355 nocode_wanted = saved_nocode_wanted;
8358 /* parse a unary expression and return its type without any side
8359 effect. */
8360 static void unary_type(CType *type)
8362 int a;
8364 a = nocode_wanted;
8365 nocode_wanted = 1;
8366 unary();
8367 *type = vtop->type;
8368 vpop();
8369 nocode_wanted = a;
8372 /* parse a constant expression and return value in vtop. */
8373 static void expr_const1(void)
8375 int a;
8376 a = const_wanted;
8377 const_wanted = 1;
8378 expr_eq();
8379 const_wanted = a;
8382 /* parse an integer constant and return its value. */
8383 static int expr_const(void)
8385 int c;
8386 expr_const1();
8387 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8388 expect("constant expression");
8389 c = vtop->c.i;
8390 vpop();
8391 return c;
8394 /* return the label token if current token is a label, otherwise
8395 return zero */
8396 static int is_label(void)
8398 int last_tok;
8400 /* fast test first */
8401 if (tok < TOK_UIDENT)
8402 return 0;
8403 /* no need to save tokc because tok is an identifier */
8404 last_tok = tok;
8405 next();
8406 if (tok == ':') {
8407 next();
8408 return last_tok;
8409 } else {
8410 unget_tok(last_tok);
8411 return 0;
8415 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8416 int case_reg, int is_expr)
8418 int a, b, c, d;
8419 Sym *s;
8421 /* generate line number info */
8422 if (do_debug &&
8423 (last_line_num != file->line_num || last_ind != ind)) {
8424 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8425 last_ind = ind;
8426 last_line_num = file->line_num;
8429 if (is_expr) {
8430 /* default return value is (void) */
8431 vpushi(0);
8432 vtop->type.t = VT_VOID;
8435 if (tok == TOK_IF) {
8436 /* if test */
8437 next();
8438 skip('(');
8439 gexpr();
8440 skip(')');
8441 a = gtst(1, 0);
8442 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8443 c = tok;
8444 if (c == TOK_ELSE) {
8445 next();
8446 d = gjmp(0);
8447 gsym(a);
8448 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8449 gsym(d); /* patch else jmp */
8450 } else
8451 gsym(a);
8452 } else if (tok == TOK_WHILE) {
8453 next();
8454 d = ind;
8455 skip('(');
8456 gexpr();
8457 skip(')');
8458 a = gtst(1, 0);
8459 b = 0;
8460 block(&a, &b, case_sym, def_sym, case_reg, 0);
8461 gjmp_addr(d);
8462 gsym(a);
8463 gsym_addr(b, d);
8464 } else if (tok == '{') {
8465 Sym *llabel;
8467 next();
8468 /* record local declaration stack position */
8469 s = local_stack;
8470 llabel = local_label_stack;
8471 /* handle local labels declarations */
8472 if (tok == TOK_LABEL) {
8473 next();
8474 for(;;) {
8475 if (tok < TOK_UIDENT)
8476 expect("label identifier");
8477 label_push(&local_label_stack, tok, LABEL_DECLARED);
8478 next();
8479 if (tok == ',') {
8480 next();
8481 } else {
8482 skip(';');
8483 break;
8487 while (tok != '}') {
8488 decl(VT_LOCAL);
8489 if (tok != '}') {
8490 if (is_expr)
8491 vpop();
8492 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8495 /* pop locally defined labels */
8496 label_pop(&local_label_stack, llabel);
8497 /* pop locally defined symbols */
8498 if(is_expr) {
8499 /* XXX: this solution makes only valgrind happy...
8500 triggered by gcc.c-torture/execute/20000917-1.c */
8501 Sym *p;
8502 switch(vtop->type.t & VT_BTYPE) {
8503 case VT_PTR:
8504 case VT_STRUCT:
8505 case VT_ENUM:
8506 case VT_FUNC:
8507 for(p=vtop->type.ref;p;p=p->prev)
8508 if(p->prev==s)
8509 error("unsupported expression type");
8512 sym_pop(&local_stack, s);
8513 next();
8514 } else if (tok == TOK_RETURN) {
8515 next();
8516 if (tok != ';') {
8517 gexpr();
8518 gen_assign_cast(&func_vt);
8519 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8520 CType type;
8521 /* if returning structure, must copy it to implicit
8522 first pointer arg location */
8523 #ifdef TCC_ARM_EABI
8524 int align, size;
8525 size = type_size(&func_vt,&align);
8526 if(size <= 4)
8528 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8529 && (align & 3))
8531 int addr;
8532 loc = (loc - size) & -4;
8533 addr = loc;
8534 type = func_vt;
8535 vset(&type, VT_LOCAL | VT_LVAL, addr);
8536 vswap();
8537 vstore();
8538 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8540 vtop->type = int_type;
8541 gv(RC_IRET);
8542 } else {
8543 #endif
8544 type = func_vt;
8545 mk_pointer(&type);
8546 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8547 indir();
8548 vswap();
8549 /* copy structure value to pointer */
8550 vstore();
8551 #ifdef TCC_ARM_EABI
8553 #endif
8554 } else if (is_float(func_vt.t)) {
8555 gv(rc_fret(func_vt.t));
8556 } else {
8557 gv(RC_IRET);
8559 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8561 skip(';');
8562 rsym = gjmp(rsym); /* jmp */
8563 } else if (tok == TOK_BREAK) {
8564 /* compute jump */
8565 if (!bsym)
8566 error("cannot break");
8567 *bsym = gjmp(*bsym);
8568 next();
8569 skip(';');
8570 } else if (tok == TOK_CONTINUE) {
8571 /* compute jump */
8572 if (!csym)
8573 error("cannot continue");
8574 *csym = gjmp(*csym);
8575 next();
8576 skip(';');
8577 } else if (tok == TOK_FOR) {
8578 int e;
8579 next();
8580 skip('(');
8581 if (tok != ';') {
8582 gexpr();
8583 vpop();
8585 skip(';');
8586 d = ind;
8587 c = ind;
8588 a = 0;
8589 b = 0;
8590 if (tok != ';') {
8591 gexpr();
8592 a = gtst(1, 0);
8594 skip(';');
8595 if (tok != ')') {
8596 e = gjmp(0);
8597 c = ind;
8598 gexpr();
8599 vpop();
8600 gjmp_addr(d);
8601 gsym(e);
8603 skip(')');
8604 block(&a, &b, case_sym, def_sym, case_reg, 0);
8605 gjmp_addr(c);
8606 gsym(a);
8607 gsym_addr(b, c);
8608 } else
8609 if (tok == TOK_DO) {
8610 next();
8611 a = 0;
8612 b = 0;
8613 d = ind;
8614 block(&a, &b, case_sym, def_sym, case_reg, 0);
8615 skip(TOK_WHILE);
8616 skip('(');
8617 gsym(b);
8618 gexpr();
8619 c = gtst(0, 0);
8620 gsym_addr(c, d);
8621 skip(')');
8622 gsym(a);
8623 skip(';');
8624 } else
8625 if (tok == TOK_SWITCH) {
8626 next();
8627 skip('(');
8628 gexpr();
8629 /* XXX: other types than integer */
8630 case_reg = gv(RC_INT);
8631 vpop();
8632 skip(')');
8633 a = 0;
8634 b = gjmp(0); /* jump to first case */
8635 c = 0;
8636 block(&a, csym, &b, &c, case_reg, 0);
8637 /* if no default, jmp after switch */
8638 if (c == 0)
8639 c = ind;
8640 /* default label */
8641 gsym_addr(b, c);
8642 /* break label */
8643 gsym(a);
8644 } else
8645 if (tok == TOK_CASE) {
8646 int v1, v2;
8647 if (!case_sym)
8648 expect("switch");
8649 next();
8650 v1 = expr_const();
8651 v2 = v1;
8652 if (gnu_ext && tok == TOK_DOTS) {
8653 next();
8654 v2 = expr_const();
8655 if (v2 < v1)
8656 warning("empty case range");
8658 /* since a case is like a label, we must skip it with a jmp */
8659 b = gjmp(0);
8660 gsym(*case_sym);
8661 vseti(case_reg, 0);
8662 vpushi(v1);
8663 if (v1 == v2) {
8664 gen_op(TOK_EQ);
8665 *case_sym = gtst(1, 0);
8666 } else {
8667 gen_op(TOK_GE);
8668 *case_sym = gtst(1, 0);
8669 vseti(case_reg, 0);
8670 vpushi(v2);
8671 gen_op(TOK_LE);
8672 *case_sym = gtst(1, *case_sym);
8674 gsym(b);
8675 skip(':');
8676 is_expr = 0;
8677 goto block_after_label;
8678 } else
8679 if (tok == TOK_DEFAULT) {
8680 next();
8681 skip(':');
8682 if (!def_sym)
8683 expect("switch");
8684 if (*def_sym)
8685 error("too many 'default'");
8686 *def_sym = ind;
8687 is_expr = 0;
8688 goto block_after_label;
8689 } else
8690 if (tok == TOK_GOTO) {
8691 next();
8692 if (tok == '*' && gnu_ext) {
8693 /* computed goto */
8694 next();
8695 gexpr();
8696 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8697 expect("pointer");
8698 ggoto();
8699 } else if (tok >= TOK_UIDENT) {
8700 s = label_find(tok);
8701 /* put forward definition if needed */
8702 if (!s) {
8703 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8704 } else {
8705 if (s->r == LABEL_DECLARED)
8706 s->r = LABEL_FORWARD;
8708 /* label already defined */
8709 if (s->r & LABEL_FORWARD)
8710 s->next = (void *)gjmp((long)s->next);
8711 else
8712 gjmp_addr((long)s->next);
8713 next();
8714 } else {
8715 expect("label identifier");
8717 skip(';');
8718 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8719 asm_instr();
8720 } else {
8721 b = is_label();
8722 if (b) {
8723 /* label case */
8724 s = label_find(b);
8725 if (s) {
8726 if (s->r == LABEL_DEFINED)
8727 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8728 gsym((long)s->next);
8729 s->r = LABEL_DEFINED;
8730 } else {
8731 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8733 s->next = (void *)ind;
8734 /* we accept this, but it is a mistake */
8735 block_after_label:
8736 if (tok == '}') {
8737 warning("deprecated use of label at end of compound statement");
8738 } else {
8739 if (is_expr)
8740 vpop();
8741 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8743 } else {
8744 /* expression case */
8745 if (tok != ';') {
8746 if (is_expr) {
8747 vpop();
8748 gexpr();
8749 } else {
8750 gexpr();
8751 vpop();
8754 skip(';');
8759 /* t is the array or struct type. c is the array or struct
8760 address. cur_index/cur_field is the pointer to the current
8761 value. 'size_only' is true if only size info is needed (only used
8762 in arrays) */
8763 static void decl_designator(CType *type, Section *sec, unsigned long c,
8764 int *cur_index, Sym **cur_field,
8765 int size_only)
8767 Sym *s, *f;
8768 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8769 CType type1;
8771 notfirst = 0;
8772 elem_size = 0;
8773 nb_elems = 1;
8774 if (gnu_ext && (l = is_label()) != 0)
8775 goto struct_field;
8776 while (tok == '[' || tok == '.') {
8777 if (tok == '[') {
8778 if (!(type->t & VT_ARRAY))
8779 expect("array type");
8780 s = type->ref;
8781 next();
8782 index = expr_const();
8783 if (index < 0 || (s->c >= 0 && index >= s->c))
8784 expect("invalid index");
8785 if (tok == TOK_DOTS && gnu_ext) {
8786 next();
8787 index_last = expr_const();
8788 if (index_last < 0 ||
8789 (s->c >= 0 && index_last >= s->c) ||
8790 index_last < index)
8791 expect("invalid index");
8792 } else {
8793 index_last = index;
8795 skip(']');
8796 if (!notfirst)
8797 *cur_index = index_last;
8798 type = pointed_type(type);
8799 elem_size = type_size(type, &align);
8800 c += index * elem_size;
8801 /* NOTE: we only support ranges for last designator */
8802 nb_elems = index_last - index + 1;
8803 if (nb_elems != 1) {
8804 notfirst = 1;
8805 break;
8807 } else {
8808 next();
8809 l = tok;
8810 next();
8811 struct_field:
8812 if ((type->t & VT_BTYPE) != VT_STRUCT)
8813 expect("struct/union type");
8814 s = type->ref;
8815 l |= SYM_FIELD;
8816 f = s->next;
8817 while (f) {
8818 if (f->v == l)
8819 break;
8820 f = f->next;
8822 if (!f)
8823 expect("field");
8824 if (!notfirst)
8825 *cur_field = f;
8826 /* XXX: fix this mess by using explicit storage field */
8827 type1 = f->type;
8828 type1.t |= (type->t & ~VT_TYPE);
8829 type = &type1;
8830 c += f->c;
8832 notfirst = 1;
8834 if (notfirst) {
8835 if (tok == '=') {
8836 next();
8837 } else {
8838 if (!gnu_ext)
8839 expect("=");
8841 } else {
8842 if (type->t & VT_ARRAY) {
8843 index = *cur_index;
8844 type = pointed_type(type);
8845 c += index * type_size(type, &align);
8846 } else {
8847 f = *cur_field;
8848 if (!f)
8849 error("too many field init");
8850 /* XXX: fix this mess by using explicit storage field */
8851 type1 = f->type;
8852 type1.t |= (type->t & ~VT_TYPE);
8853 type = &type1;
8854 c += f->c;
8857 decl_initializer(type, sec, c, 0, size_only);
8859 /* XXX: make it more general */
8860 if (!size_only && nb_elems > 1) {
8861 unsigned long c_end;
8862 uint8_t *src, *dst;
8863 int i;
8865 if (!sec)
8866 error("range init not supported yet for dynamic storage");
8867 c_end = c + nb_elems * elem_size;
8868 if (c_end > sec->data_allocated)
8869 section_realloc(sec, c_end);
8870 src = sec->data + c;
8871 dst = src;
8872 for(i = 1; i < nb_elems; i++) {
8873 dst += elem_size;
8874 memcpy(dst, src, elem_size);
8879 #define EXPR_VAL 0
8880 #define EXPR_CONST 1
8881 #define EXPR_ANY 2
8883 /* store a value or an expression directly in global data or in local array */
8884 static void init_putv(CType *type, Section *sec, unsigned long c,
8885 int v, int expr_type)
8887 int saved_global_expr, bt, bit_pos, bit_size;
8888 void *ptr;
8889 unsigned long long bit_mask;
8890 CType dtype;
8892 switch(expr_type) {
8893 case EXPR_VAL:
8894 vpushi(v);
8895 break;
8896 case EXPR_CONST:
8897 /* compound literals must be allocated globally in this case */
8898 saved_global_expr = global_expr;
8899 global_expr = 1;
8900 expr_const1();
8901 global_expr = saved_global_expr;
8902 /* NOTE: symbols are accepted */
8903 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8904 error("initializer element is not constant");
8905 break;
8906 case EXPR_ANY:
8907 expr_eq();
8908 break;
8911 dtype = *type;
8912 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8914 if (sec) {
8915 /* XXX: not portable */
8916 /* XXX: generate error if incorrect relocation */
8917 gen_assign_cast(&dtype);
8918 bt = type->t & VT_BTYPE;
8919 /* we'll write at most 12 bytes */
8920 if (c + 12 > sec->data_allocated) {
8921 section_realloc(sec, c + 12);
8923 ptr = sec->data + c;
8924 /* XXX: make code faster ? */
8925 if (!(type->t & VT_BITFIELD)) {
8926 bit_pos = 0;
8927 bit_size = 32;
8928 bit_mask = -1LL;
8929 } else {
8930 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8931 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8932 bit_mask = (1LL << bit_size) - 1;
8934 if ((vtop->r & VT_SYM) &&
8935 (bt == VT_BYTE ||
8936 bt == VT_SHORT ||
8937 bt == VT_DOUBLE ||
8938 bt == VT_LDOUBLE ||
8939 bt == VT_LLONG ||
8940 (bt == VT_INT && bit_size != 32)))
8941 error("initializer element is not computable at load time");
8942 switch(bt) {
8943 case VT_BOOL:
8944 vtop->c.i = (vtop->c.i != 0);
8945 case VT_BYTE:
8946 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8947 break;
8948 case VT_SHORT:
8949 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8950 break;
8951 case VT_DOUBLE:
8952 *(double *)ptr = vtop->c.d;
8953 break;
8954 case VT_LDOUBLE:
8955 *(long double *)ptr = vtop->c.ld;
8956 break;
8957 case VT_LLONG:
8958 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8959 break;
8960 default:
8961 if (vtop->r & VT_SYM) {
8962 greloc(sec, vtop->sym, c, R_DATA_32);
8964 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8965 break;
8967 vtop--;
8968 } else {
8969 vset(&dtype, VT_LOCAL|VT_LVAL, c);
8970 vswap();
8971 vstore();
8972 vpop();
8976 /* put zeros for variable based init */
8977 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8979 if (sec) {
8980 /* nothing to do because globals are already set to zero */
8981 } else {
8982 vpush_global_sym(&func_old_type, TOK_memset);
8983 vseti(VT_LOCAL, c);
8984 vpushi(0);
8985 vpushi(size);
8986 gfunc_call(3);
8990 /* 't' contains the type and storage info. 'c' is the offset of the
8991 object in section 'sec'. If 'sec' is NULL, it means stack based
8992 allocation. 'first' is true if array '{' must be read (multi
8993 dimension implicit array init handling). 'size_only' is true if
8994 size only evaluation is wanted (only for arrays). */
8995 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8996 int first, int size_only)
8998 int index, array_length, n, no_oblock, nb, parlevel, i;
8999 int size1, align1, expr_type;
9000 Sym *s, *f;
9001 CType *t1;
9003 if (type->t & VT_ARRAY) {
9004 s = type->ref;
9005 n = s->c;
9006 array_length = 0;
9007 t1 = pointed_type(type);
9008 size1 = type_size(t1, &align1);
9010 no_oblock = 1;
9011 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
9012 tok == '{') {
9013 skip('{');
9014 no_oblock = 0;
9017 /* only parse strings here if correct type (otherwise: handle
9018 them as ((w)char *) expressions */
9019 if ((tok == TOK_LSTR &&
9020 #ifdef TCC_TARGET_PE
9021 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
9022 #else
9023 (t1->t & VT_BTYPE) == VT_INT
9024 #endif
9025 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
9026 while (tok == TOK_STR || tok == TOK_LSTR) {
9027 int cstr_len, ch;
9028 CString *cstr;
9030 cstr = tokc.cstr;
9031 /* compute maximum number of chars wanted */
9032 if (tok == TOK_STR)
9033 cstr_len = cstr->size;
9034 else
9035 cstr_len = cstr->size / sizeof(nwchar_t);
9036 cstr_len--;
9037 nb = cstr_len;
9038 if (n >= 0 && nb > (n - array_length))
9039 nb = n - array_length;
9040 if (!size_only) {
9041 if (cstr_len > nb)
9042 warning("initializer-string for array is too long");
9043 /* in order to go faster for common case (char
9044 string in global variable, we handle it
9045 specifically */
9046 if (sec && tok == TOK_STR && size1 == 1) {
9047 memcpy(sec->data + c + array_length, cstr->data, nb);
9048 } else {
9049 for(i=0;i<nb;i++) {
9050 if (tok == TOK_STR)
9051 ch = ((unsigned char *)cstr->data)[i];
9052 else
9053 ch = ((nwchar_t *)cstr->data)[i];
9054 init_putv(t1, sec, c + (array_length + i) * size1,
9055 ch, EXPR_VAL);
9059 array_length += nb;
9060 next();
9062 /* only add trailing zero if enough storage (no
9063 warning in this case since it is standard) */
9064 if (n < 0 || array_length < n) {
9065 if (!size_only) {
9066 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
9068 array_length++;
9070 } else {
9071 index = 0;
9072 while (tok != '}') {
9073 decl_designator(type, sec, c, &index, NULL, size_only);
9074 if (n >= 0 && index >= n)
9075 error("index too large");
9076 /* must put zero in holes (note that doing it that way
9077 ensures that it even works with designators) */
9078 if (!size_only && array_length < index) {
9079 init_putz(t1, sec, c + array_length * size1,
9080 (index - array_length) * size1);
9082 index++;
9083 if (index > array_length)
9084 array_length = index;
9085 /* special test for multi dimensional arrays (may not
9086 be strictly correct if designators are used at the
9087 same time) */
9088 if (index >= n && no_oblock)
9089 break;
9090 if (tok == '}')
9091 break;
9092 skip(',');
9095 if (!no_oblock)
9096 skip('}');
9097 /* put zeros at the end */
9098 if (!size_only && n >= 0 && array_length < n) {
9099 init_putz(t1, sec, c + array_length * size1,
9100 (n - array_length) * size1);
9102 /* patch type size if needed */
9103 if (n < 0)
9104 s->c = array_length;
9105 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
9106 (sec || !first || tok == '{')) {
9107 int par_count;
9109 /* NOTE: the previous test is a specific case for automatic
9110 struct/union init */
9111 /* XXX: union needs only one init */
9113 /* XXX: this test is incorrect for local initializers
9114 beginning with ( without {. It would be much more difficult
9115 to do it correctly (ideally, the expression parser should
9116 be used in all cases) */
9117 par_count = 0;
9118 if (tok == '(') {
9119 AttributeDef ad1;
9120 CType type1;
9121 next();
9122 while (tok == '(') {
9123 par_count++;
9124 next();
9126 if (!parse_btype(&type1, &ad1))
9127 expect("cast");
9128 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
9129 #if 0
9130 if (!is_assignable_types(type, &type1))
9131 error("invalid type for cast");
9132 #endif
9133 skip(')');
9135 no_oblock = 1;
9136 if (first || tok == '{') {
9137 skip('{');
9138 no_oblock = 0;
9140 s = type->ref;
9141 f = s->next;
9142 array_length = 0;
9143 index = 0;
9144 n = s->c;
9145 while (tok != '}') {
9146 decl_designator(type, sec, c, NULL, &f, size_only);
9147 index = f->c;
9148 if (!size_only && array_length < index) {
9149 init_putz(type, sec, c + array_length,
9150 index - array_length);
9152 index = index + type_size(&f->type, &align1);
9153 if (index > array_length)
9154 array_length = index;
9155 f = f->next;
9156 if (no_oblock && f == NULL)
9157 break;
9158 if (tok == '}')
9159 break;
9160 skip(',');
9162 /* put zeros at the end */
9163 if (!size_only && array_length < n) {
9164 init_putz(type, sec, c + array_length,
9165 n - array_length);
9167 if (!no_oblock)
9168 skip('}');
9169 while (par_count) {
9170 skip(')');
9171 par_count--;
9173 } else if (tok == '{') {
9174 next();
9175 decl_initializer(type, sec, c, first, size_only);
9176 skip('}');
9177 } else if (size_only) {
9178 /* just skip expression */
9179 parlevel = 0;
9180 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
9181 tok != -1) {
9182 if (tok == '(')
9183 parlevel++;
9184 else if (tok == ')')
9185 parlevel--;
9186 next();
9188 } else {
9189 /* currently, we always use constant expression for globals
9190 (may change for scripting case) */
9191 expr_type = EXPR_CONST;
9192 if (!sec)
9193 expr_type = EXPR_ANY;
9194 init_putv(type, sec, c, 0, expr_type);
9198 /* parse an initializer for type 't' if 'has_init' is non zero, and
9199 allocate space in local or global data space ('r' is either
9200 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
9201 variable 'v' of scope 'scope' is declared before initializers are
9202 parsed. If 'v' is zero, then a reference to the new object is put
9203 in the value stack. If 'has_init' is 2, a special parsing is done
9204 to handle string constants. */
9205 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
9206 int has_init, int v, int scope)
9208 int size, align, addr, data_offset;
9209 int level;
9210 ParseState saved_parse_state;
9211 TokenString init_str;
9212 Section *sec;
9214 size = type_size(type, &align);
9215 /* If unknown size, we must evaluate it before
9216 evaluating initializers because
9217 initializers can generate global data too
9218 (e.g. string pointers or ISOC99 compound
9219 literals). It also simplifies local
9220 initializers handling */
9221 tok_str_new(&init_str);
9222 if (size < 0) {
9223 if (!has_init)
9224 error("unknown type size");
9225 /* get all init string */
9226 if (has_init == 2) {
9227 /* only get strings */
9228 while (tok == TOK_STR || tok == TOK_LSTR) {
9229 tok_str_add_tok(&init_str);
9230 next();
9232 } else {
9233 level = 0;
9234 while (level > 0 || (tok != ',' && tok != ';')) {
9235 if (tok < 0)
9236 error("unexpected end of file in initializer");
9237 tok_str_add_tok(&init_str);
9238 if (tok == '{')
9239 level++;
9240 else if (tok == '}') {
9241 level--;
9242 if (level <= 0) {
9243 next();
9244 break;
9247 next();
9250 tok_str_add(&init_str, -1);
9251 tok_str_add(&init_str, 0);
9253 /* compute size */
9254 save_parse_state(&saved_parse_state);
9256 macro_ptr = init_str.str;
9257 next();
9258 decl_initializer(type, NULL, 0, 1, 1);
9259 /* prepare second initializer parsing */
9260 macro_ptr = init_str.str;
9261 next();
9263 /* if still unknown size, error */
9264 size = type_size(type, &align);
9265 if (size < 0)
9266 error("unknown type size");
9268 /* take into account specified alignment if bigger */
9269 if (ad->aligned) {
9270 if (ad->aligned > align)
9271 align = ad->aligned;
9272 } else if (ad->packed) {
9273 align = 1;
9275 if ((r & VT_VALMASK) == VT_LOCAL) {
9276 sec = NULL;
9277 if (do_bounds_check && (type->t & VT_ARRAY))
9278 loc--;
9279 loc = (loc - size) & -align;
9280 addr = loc;
9281 /* handles bounds */
9282 /* XXX: currently, since we do only one pass, we cannot track
9283 '&' operators, so we add only arrays */
9284 if (do_bounds_check && (type->t & VT_ARRAY)) {
9285 unsigned long *bounds_ptr;
9286 /* add padding between regions */
9287 loc--;
9288 /* then add local bound info */
9289 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
9290 bounds_ptr[0] = addr;
9291 bounds_ptr[1] = size;
9293 if (v) {
9294 /* local variable */
9295 sym_push(v, type, r, addr);
9296 } else {
9297 /* push local reference */
9298 vset(type, r, addr);
9300 } else {
9301 Sym *sym;
9303 sym = NULL;
9304 if (v && scope == VT_CONST) {
9305 /* see if the symbol was already defined */
9306 sym = sym_find(v);
9307 if (sym) {
9308 if (!is_compatible_types(&sym->type, type))
9309 error("incompatible types for redefinition of '%s'",
9310 get_tok_str(v, NULL));
9311 if (sym->type.t & VT_EXTERN) {
9312 /* if the variable is extern, it was not allocated */
9313 sym->type.t &= ~VT_EXTERN;
9314 /* set array size if it was ommited in extern
9315 declaration */
9316 if ((sym->type.t & VT_ARRAY) &&
9317 sym->type.ref->c < 0 &&
9318 type->ref->c >= 0)
9319 sym->type.ref->c = type->ref->c;
9320 } else {
9321 /* we accept several definitions of the same
9322 global variable. this is tricky, because we
9323 must play with the SHN_COMMON type of the symbol */
9324 /* XXX: should check if the variable was already
9325 initialized. It is incorrect to initialized it
9326 twice */
9327 /* no init data, we won't add more to the symbol */
9328 if (!has_init)
9329 goto no_alloc;
9334 /* allocate symbol in corresponding section */
9335 sec = ad->section;
9336 if (!sec) {
9337 if (has_init)
9338 sec = data_section;
9339 else if (tcc_state->nocommon)
9340 sec = bss_section;
9342 if (sec) {
9343 data_offset = sec->data_offset;
9344 data_offset = (data_offset + align - 1) & -align;
9345 addr = data_offset;
9346 /* very important to increment global pointer at this time
9347 because initializers themselves can create new initializers */
9348 data_offset += size;
9349 /* add padding if bound check */
9350 if (do_bounds_check)
9351 data_offset++;
9352 sec->data_offset = data_offset;
9353 /* allocate section space to put the data */
9354 if (sec->sh_type != SHT_NOBITS &&
9355 data_offset > sec->data_allocated)
9356 section_realloc(sec, data_offset);
9357 /* align section if needed */
9358 if (align > sec->sh_addralign)
9359 sec->sh_addralign = align;
9360 } else {
9361 addr = 0; /* avoid warning */
9364 if (v) {
9365 if (scope != VT_CONST || !sym) {
9366 sym = sym_push(v, type, r | VT_SYM, 0);
9368 /* update symbol definition */
9369 if (sec) {
9370 put_extern_sym(sym, sec, addr, size);
9371 } else {
9372 ElfW(Sym) *esym;
9373 /* put a common area */
9374 put_extern_sym(sym, NULL, align, size);
9375 /* XXX: find a nicer way */
9376 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
9377 esym->st_shndx = SHN_COMMON;
9379 } else {
9380 CValue cval;
9382 /* push global reference */
9383 sym = get_sym_ref(type, sec, addr, size);
9384 cval.ul = 0;
9385 vsetc(type, VT_CONST | VT_SYM, &cval);
9386 vtop->sym = sym;
9389 /* handles bounds now because the symbol must be defined
9390 before for the relocation */
9391 if (do_bounds_check) {
9392 unsigned long *bounds_ptr;
9394 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9395 /* then add global bound info */
9396 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9397 bounds_ptr[0] = 0; /* relocated */
9398 bounds_ptr[1] = size;
9401 if (has_init) {
9402 decl_initializer(type, sec, addr, 1, 0);
9403 /* restore parse state if needed */
9404 if (init_str.str) {
9405 tok_str_free(init_str.str);
9406 restore_parse_state(&saved_parse_state);
9409 no_alloc: ;
9412 void put_func_debug(Sym *sym)
9414 char buf[512];
9416 /* stabs info */
9417 /* XXX: we put here a dummy type */
9418 snprintf(buf, sizeof(buf), "%s:%c1",
9419 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9420 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9421 cur_text_section, sym->c);
9422 /* //gr gdb wants a line at the function */
9423 put_stabn(N_SLINE, 0, file->line_num, 0);
9424 last_ind = 0;
9425 last_line_num = 0;
9428 /* parse an old style function declaration list */
9429 /* XXX: check multiple parameter */
9430 static void func_decl_list(Sym *func_sym)
9432 AttributeDef ad;
9433 int v;
9434 Sym *s;
9435 CType btype, type;
9437 /* parse each declaration */
9438 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9439 if (!parse_btype(&btype, &ad))
9440 expect("declaration list");
9441 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9442 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9443 tok == ';') {
9444 /* we accept no variable after */
9445 } else {
9446 for(;;) {
9447 type = btype;
9448 type_decl(&type, &ad, &v, TYPE_DIRECT);
9449 /* find parameter in function parameter list */
9450 s = func_sym->next;
9451 while (s != NULL) {
9452 if ((s->v & ~SYM_FIELD) == v)
9453 goto found;
9454 s = s->next;
9456 error("declaration for parameter '%s' but no such parameter",
9457 get_tok_str(v, NULL));
9458 found:
9459 /* check that no storage specifier except 'register' was given */
9460 if (type.t & VT_STORAGE)
9461 error("storage class specified for '%s'", get_tok_str(v, NULL));
9462 convert_parameter_type(&type);
9463 /* we can add the type (NOTE: it could be local to the function) */
9464 s->type = type;
9465 /* accept other parameters */
9466 if (tok == ',')
9467 next();
9468 else
9469 break;
9472 skip(';');
9476 /* parse a function defined by symbol 'sym' and generate its code in
9477 'cur_text_section' */
9478 static void gen_function(Sym *sym)
9480 int saved_nocode_wanted = nocode_wanted;
9481 nocode_wanted = 0;
9482 ind = cur_text_section->data_offset;
9483 /* NOTE: we patch the symbol size later */
9484 put_extern_sym(sym, cur_text_section, ind, 0);
9485 funcname = get_tok_str(sym->v, NULL);
9486 func_ind = ind;
9487 /* put debug symbol */
9488 if (do_debug)
9489 put_func_debug(sym);
9490 /* push a dummy symbol to enable local sym storage */
9491 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9492 gfunc_prolog(&sym->type);
9493 rsym = 0;
9494 block(NULL, NULL, NULL, NULL, 0, 0);
9495 gsym(rsym);
9496 gfunc_epilog();
9497 cur_text_section->data_offset = ind;
9498 label_pop(&global_label_stack, NULL);
9499 sym_pop(&local_stack, NULL); /* reset local stack */
9500 /* end of function */
9501 /* patch symbol size */
9502 ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size =
9503 ind - func_ind;
9504 if (do_debug) {
9505 put_stabn(N_FUN, 0, 0, ind - func_ind);
9507 /* It's better to crash than to generate wrong code */
9508 cur_text_section = NULL;
9509 funcname = ""; /* for safety */
9510 func_vt.t = VT_VOID; /* for safety */
9511 ind = 0; /* for safety */
9512 nocode_wanted = saved_nocode_wanted;
9515 static void gen_inline_functions(void)
9517 Sym *sym;
9518 CType *type;
9519 int *str, inline_generated;
9521 /* iterate while inline function are referenced */
9522 for(;;) {
9523 inline_generated = 0;
9524 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9525 type = &sym->type;
9526 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9527 (type->t & (VT_STATIC | VT_INLINE)) ==
9528 (VT_STATIC | VT_INLINE) &&
9529 sym->c != 0) {
9530 /* the function was used: generate its code and
9531 convert it to a normal function */
9532 str = INLINE_DEF(sym->r);
9533 sym->r = VT_SYM | VT_CONST;
9534 sym->type.t &= ~VT_INLINE;
9536 macro_ptr = str;
9537 next();
9538 cur_text_section = text_section;
9539 gen_function(sym);
9540 macro_ptr = NULL; /* fail safe */
9542 tok_str_free(str);
9543 inline_generated = 1;
9546 if (!inline_generated)
9547 break;
9550 /* free all remaining inline function tokens */
9551 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9552 type = &sym->type;
9553 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9554 (type->t & (VT_STATIC | VT_INLINE)) ==
9555 (VT_STATIC | VT_INLINE)) {
9556 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9557 if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
9558 continue;
9559 str = INLINE_DEF(sym->r);
9560 tok_str_free(str);
9561 sym->r = 0; /* fail safe */
9566 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9567 static void decl(int l)
9569 int v, has_init, r;
9570 CType type, btype;
9571 Sym *sym;
9572 AttributeDef ad;
9574 while (1) {
9575 if (!parse_btype(&btype, &ad)) {
9576 /* skip redundant ';' */
9577 /* XXX: find more elegant solution */
9578 if (tok == ';') {
9579 next();
9580 continue;
9582 if (l == VT_CONST &&
9583 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9584 /* global asm block */
9585 asm_global_instr();
9586 continue;
9588 /* special test for old K&R protos without explicit int
9589 type. Only accepted when defining global data */
9590 if (l == VT_LOCAL || tok < TOK_DEFINE)
9591 break;
9592 btype.t = VT_INT;
9594 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9595 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9596 tok == ';') {
9597 /* we accept no variable after */
9598 next();
9599 continue;
9601 while (1) { /* iterate thru each declaration */
9602 type = btype;
9603 type_decl(&type, &ad, &v, TYPE_DIRECT);
9604 #if 0
9606 char buf[500];
9607 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
9608 printf("type = '%s'\n", buf);
9610 #endif
9611 if ((type.t & VT_BTYPE) == VT_FUNC) {
9612 /* if old style function prototype, we accept a
9613 declaration list */
9614 sym = type.ref;
9615 if (sym->c == FUNC_OLD)
9616 func_decl_list(sym);
9619 if (tok == '{') {
9620 if (l == VT_LOCAL)
9621 error("cannot use local functions");
9622 if ((type.t & VT_BTYPE) != VT_FUNC)
9623 expect("function definition");
9625 /* reject abstract declarators in function definition */
9626 sym = type.ref;
9627 while ((sym = sym->next) != NULL)
9628 if (!(sym->v & ~SYM_FIELD))
9629 expect("identifier");
9631 /* XXX: cannot do better now: convert extern line to static inline */
9632 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9633 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9635 sym = sym_find(v);
9636 if (sym) {
9637 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9638 goto func_error1;
9639 /* specific case: if not func_call defined, we put
9640 the one of the prototype */
9641 /* XXX: should have default value */
9642 r = sym->type.ref->r;
9643 if (FUNC_CALL(r) != FUNC_CDECL
9644 && FUNC_CALL(type.ref->r) == FUNC_CDECL)
9645 FUNC_CALL(type.ref->r) = FUNC_CALL(r);
9646 if (FUNC_EXPORT(r))
9647 FUNC_EXPORT(type.ref->r) = 1;
9649 if (!is_compatible_types(&sym->type, &type)) {
9650 func_error1:
9651 error("incompatible types for redefinition of '%s'",
9652 get_tok_str(v, NULL));
9654 /* if symbol is already defined, then put complete type */
9655 sym->type = type;
9656 } else {
9657 /* put function symbol */
9658 sym = global_identifier_push(v, type.t, 0);
9659 sym->type.ref = type.ref;
9662 /* static inline functions are just recorded as a kind
9663 of macro. Their code will be emitted at the end of
9664 the compilation unit only if they are used */
9665 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9666 (VT_INLINE | VT_STATIC)) {
9667 TokenString func_str;
9668 int block_level;
9670 tok_str_new(&func_str);
9672 block_level = 0;
9673 for(;;) {
9674 int t;
9675 if (tok == TOK_EOF)
9676 error("unexpected end of file");
9677 tok_str_add_tok(&func_str);
9678 t = tok;
9679 next();
9680 if (t == '{') {
9681 block_level++;
9682 } else if (t == '}') {
9683 block_level--;
9684 if (block_level == 0)
9685 break;
9688 tok_str_add(&func_str, -1);
9689 tok_str_add(&func_str, 0);
9690 INLINE_DEF(sym->r) = func_str.str;
9691 } else {
9692 /* compute text section */
9693 cur_text_section = ad.section;
9694 if (!cur_text_section)
9695 cur_text_section = text_section;
9696 sym->r = VT_SYM | VT_CONST;
9697 gen_function(sym);
9699 break;
9700 } else {
9701 if (btype.t & VT_TYPEDEF) {
9702 /* save typedefed type */
9703 /* XXX: test storage specifiers ? */
9704 sym = sym_push(v, &type, 0, 0);
9705 sym->type.t |= VT_TYPEDEF;
9706 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9707 /* external function definition */
9708 /* specific case for func_call attribute */
9709 if (ad.func_attr)
9710 type.ref->r = ad.func_attr;
9711 external_sym(v, &type, 0);
9712 } else {
9713 /* not lvalue if array */
9714 r = 0;
9715 if (!(type.t & VT_ARRAY))
9716 r |= lvalue_type(type.t);
9717 has_init = (tok == '=');
9718 if ((btype.t & VT_EXTERN) ||
9719 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9720 !has_init && l == VT_CONST && type.ref->c < 0)) {
9721 /* external variable */
9722 /* NOTE: as GCC, uninitialized global static
9723 arrays of null size are considered as
9724 extern */
9725 external_sym(v, &type, r);
9726 } else {
9727 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9728 if (type.t & VT_STATIC)
9729 r |= VT_CONST;
9730 else
9731 r |= l;
9732 if (has_init)
9733 next();
9734 decl_initializer_alloc(&type, &ad, r,
9735 has_init, v, l);
9738 if (tok != ',') {
9739 skip(';');
9740 break;
9742 next();
9748 /* better than nothing, but needs extension to handle '-E' option
9749 correctly too */
9750 static void preprocess_init(TCCState *s1)
9752 s1->include_stack_ptr = s1->include_stack;
9753 /* XXX: move that before to avoid having to initialize
9754 file->ifdef_stack_ptr ? */
9755 s1->ifdef_stack_ptr = s1->ifdef_stack;
9756 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9758 /* XXX: not ANSI compliant: bound checking says error */
9759 vtop = vstack - 1;
9760 s1->pack_stack[0] = 0;
9761 s1->pack_stack_ptr = s1->pack_stack;
9764 /* compile the C file opened in 'file'. Return non zero if errors. */
9765 static int tcc_compile(TCCState *s1)
9767 Sym *define_start;
9768 char buf[512];
9769 volatile int section_sym;
9771 #ifdef INC_DEBUG
9772 printf("%s: **** new file\n", file->filename);
9773 #endif
9774 preprocess_init(s1);
9776 cur_text_section = NULL;
9777 funcname = "";
9778 anon_sym = SYM_FIRST_ANOM;
9780 /* file info: full path + filename */
9781 section_sym = 0; /* avoid warning */
9782 if (do_debug) {
9783 section_sym = put_elf_sym(symtab_section, 0, 0,
9784 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
9785 text_section->sh_num, NULL);
9786 getcwd(buf, sizeof(buf));
9787 #ifdef _WIN32
9788 normalize_slashes(buf);
9789 #endif
9790 pstrcat(buf, sizeof(buf), "/");
9791 put_stabs_r(buf, N_SO, 0, 0,
9792 text_section->data_offset, text_section, section_sym);
9793 put_stabs_r(file->filename, N_SO, 0, 0,
9794 text_section->data_offset, text_section, section_sym);
9796 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9797 symbols can be safely used */
9798 put_elf_sym(symtab_section, 0, 0,
9799 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
9800 SHN_ABS, file->filename);
9802 /* define some often used types */
9803 int_type.t = VT_INT;
9805 char_pointer_type.t = VT_BYTE;
9806 mk_pointer(&char_pointer_type);
9808 func_old_type.t = VT_FUNC;
9809 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9811 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9812 float_type.t = VT_FLOAT;
9813 double_type.t = VT_DOUBLE;
9815 func_float_type.t = VT_FUNC;
9816 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9817 func_double_type.t = VT_FUNC;
9818 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9819 #endif
9821 #if 0
9822 /* define 'void *alloca(unsigned int)' builtin function */
9824 Sym *s1;
9826 p = anon_sym++;
9827 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9828 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9829 s1->next = NULL;
9830 sym->next = s1;
9831 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9833 #endif
9835 define_start = define_stack;
9836 nocode_wanted = 1;
9838 if (setjmp(s1->error_jmp_buf) == 0) {
9839 s1->nb_errors = 0;
9840 s1->error_set_jmp_enabled = 1;
9842 ch = file->buf_ptr[0];
9843 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9844 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9845 next();
9846 decl(VT_CONST);
9847 if (tok != TOK_EOF)
9848 expect("declaration");
9850 /* end of translation unit info */
9851 if (do_debug) {
9852 put_stabs_r(NULL, N_SO, 0, 0,
9853 text_section->data_offset, text_section, section_sym);
9856 s1->error_set_jmp_enabled = 0;
9858 /* reset define stack, but leave -Dsymbols (may be incorrect if
9859 they are undefined) */
9860 free_defines(define_start);
9862 gen_inline_functions();
9864 sym_pop(&global_stack, NULL);
9865 sym_pop(&local_stack, NULL);
9867 return s1->nb_errors != 0 ? -1 : 0;
9870 /* Preprocess the current file */
9871 /* XXX: add line and file infos,
9872 * XXX: add options to preserve spaces (partly done, only spaces in macro are
9873 * not preserved)
9875 static int tcc_preprocess(TCCState *s1)
9877 Sym *define_start;
9878 BufferedFile *file_ref;
9879 int token_seen, line_ref;
9881 preprocess_init(s1);
9882 define_start = define_stack;
9883 ch = file->buf_ptr[0];
9885 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9886 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9887 PARSE_FLAG_LINEFEED;
9889 token_seen = 0;
9890 line_ref = 0;
9891 file_ref = NULL;
9893 for (;;) {
9894 next();
9895 if (tok == TOK_EOF) {
9896 break;
9897 } else if (tok == TOK_LINEFEED) {
9898 if (!token_seen)
9899 continue;
9900 ++line_ref;
9901 token_seen = 0;
9902 } else if (token_seen) {
9903 fwrite(tok_spaces.data, tok_spaces.size, 1, s1->outfile);
9904 } else {
9905 int d = file->line_num - line_ref;
9906 if (file != file_ref || d < 0 || d >= 8)
9907 fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename);
9908 else
9909 while (d)
9910 fputs("\n", s1->outfile), --d;
9911 line_ref = (file_ref = file)->line_num;
9912 token_seen = 1;
9914 fputs(get_tok_str(tok, &tokc), s1->outfile);
9916 free_defines(define_start);
9917 return 0;
9920 #ifdef LIBTCC
9921 int tcc_compile_string(TCCState *s, const char *str)
9923 BufferedFile bf1, *bf = &bf1;
9924 int ret, len;
9925 char *buf;
9927 /* init file structure */
9928 bf->fd = -1;
9929 /* XXX: avoid copying */
9930 len = strlen(str);
9931 buf = tcc_malloc(len + 1);
9932 if (!buf)
9933 return -1;
9934 memcpy(buf, str, len);
9935 buf[len] = CH_EOB;
9936 bf->buf_ptr = buf;
9937 bf->buf_end = buf + len;
9938 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9939 bf->line_num = 1;
9940 file = bf;
9941 ret = tcc_compile(s);
9942 file = NULL;
9943 tcc_free(buf);
9945 /* currently, no need to close */
9946 return ret;
9948 #endif
9950 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9951 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9953 BufferedFile bf1, *bf = &bf1;
9955 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9956 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9957 /* default value */
9958 if (!value)
9959 value = "1";
9960 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9962 /* init file structure */
9963 bf->fd = -1;
9964 bf->buf_ptr = bf->buffer;
9965 bf->buf_end = bf->buffer + strlen(bf->buffer);
9966 *bf->buf_end = CH_EOB;
9967 bf->filename[0] = '\0';
9968 bf->line_num = 1;
9969 file = bf;
9971 s1->include_stack_ptr = s1->include_stack;
9973 /* parse with define parser */
9974 ch = file->buf_ptr[0];
9975 next_nomacro();
9976 parse_define();
9977 file = NULL;
9980 /* undefine a preprocessor symbol */
9981 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9983 TokenSym *ts;
9984 Sym *s;
9985 ts = tok_alloc(sym, strlen(sym));
9986 s = define_find(ts->tok);
9987 /* undefine symbol by putting an invalid name */
9988 if (s)
9989 define_undef(s);
9992 #ifdef CONFIG_TCC_ASM
9994 #ifdef TCC_TARGET_I386
9995 #include "i386-asm.c"
9996 #endif
9997 #include "tccasm.c"
9999 #else
10000 static void asm_instr(void)
10002 error("inline asm() not supported");
10004 static void asm_global_instr(void)
10006 error("inline asm() not supported");
10008 #endif
10010 #include "tccelf.c"
10012 #ifdef TCC_TARGET_COFF
10013 #include "tcccoff.c"
10014 #endif
10016 #ifdef TCC_TARGET_PE
10017 #include "tccpe.c"
10018 #endif
10020 /* print the position in the source file of PC value 'pc' by reading
10021 the stabs debug information */
10022 static void rt_printline(unsigned long wanted_pc)
10024 Stab_Sym *sym, *sym_end;
10025 char func_name[128], last_func_name[128];
10026 unsigned long func_addr, last_pc, pc;
10027 const char *incl_files[INCLUDE_STACK_SIZE];
10028 int incl_index, len, last_line_num, i;
10029 const char *str, *p;
10031 fprintf(stderr, "0x%08lx:", wanted_pc);
10033 func_name[0] = '\0';
10034 func_addr = 0;
10035 incl_index = 0;
10036 last_func_name[0] = '\0';
10037 last_pc = 0xffffffff;
10038 last_line_num = 1;
10039 sym = (Stab_Sym *)stab_section->data + 1;
10040 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
10041 while (sym < sym_end) {
10042 switch(sym->n_type) {
10043 /* function start or end */
10044 case N_FUN:
10045 if (sym->n_strx == 0) {
10046 /* we test if between last line and end of function */
10047 pc = sym->n_value + func_addr;
10048 if (wanted_pc >= last_pc && wanted_pc < pc)
10049 goto found;
10050 func_name[0] = '\0';
10051 func_addr = 0;
10052 } else {
10053 str = stabstr_section->data + sym->n_strx;
10054 p = strchr(str, ':');
10055 if (!p) {
10056 pstrcpy(func_name, sizeof(func_name), str);
10057 } else {
10058 len = p - str;
10059 if (len > sizeof(func_name) - 1)
10060 len = sizeof(func_name) - 1;
10061 memcpy(func_name, str, len);
10062 func_name[len] = '\0';
10064 func_addr = sym->n_value;
10066 break;
10067 /* line number info */
10068 case N_SLINE:
10069 pc = sym->n_value + func_addr;
10070 if (wanted_pc >= last_pc && wanted_pc < pc)
10071 goto found;
10072 last_pc = pc;
10073 last_line_num = sym->n_desc;
10074 /* XXX: slow! */
10075 strcpy(last_func_name, func_name);
10076 break;
10077 /* include files */
10078 case N_BINCL:
10079 str = stabstr_section->data + sym->n_strx;
10080 add_incl:
10081 if (incl_index < INCLUDE_STACK_SIZE) {
10082 incl_files[incl_index++] = str;
10084 break;
10085 case N_EINCL:
10086 if (incl_index > 1)
10087 incl_index--;
10088 break;
10089 case N_SO:
10090 if (sym->n_strx == 0) {
10091 incl_index = 0; /* end of translation unit */
10092 } else {
10093 str = stabstr_section->data + sym->n_strx;
10094 /* do not add path */
10095 len = strlen(str);
10096 if (len > 0 && str[len - 1] != '/')
10097 goto add_incl;
10099 break;
10101 sym++;
10104 /* second pass: we try symtab symbols (no line number info) */
10105 incl_index = 0;
10107 ElfW(Sym) *sym, *sym_end;
10108 int type;
10110 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
10111 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
10112 sym < sym_end;
10113 sym++) {
10114 type = ELFW(ST_TYPE)(sym->st_info);
10115 if (type == STT_FUNC) {
10116 if (wanted_pc >= sym->st_value &&
10117 wanted_pc < sym->st_value + sym->st_size) {
10118 pstrcpy(last_func_name, sizeof(last_func_name),
10119 strtab_section->data + sym->st_name);
10120 goto found;
10125 /* did not find any info: */
10126 fprintf(stderr, " ???\n");
10127 return;
10128 found:
10129 if (last_func_name[0] != '\0') {
10130 fprintf(stderr, " %s()", last_func_name);
10132 if (incl_index > 0) {
10133 fprintf(stderr, " (%s:%d",
10134 incl_files[incl_index - 1], last_line_num);
10135 for(i = incl_index - 2; i >= 0; i--)
10136 fprintf(stderr, ", included from %s", incl_files[i]);
10137 fprintf(stderr, ")");
10139 fprintf(stderr, "\n");
10142 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
10144 #ifdef __i386__
10146 /* fix for glibc 2.1 */
10147 #ifndef REG_EIP
10148 #define REG_EIP EIP
10149 #define REG_EBP EBP
10150 #endif
10152 /* return the PC at frame level 'level'. Return non zero if not found */
10153 static int rt_get_caller_pc(unsigned long *paddr,
10154 ucontext_t *uc, int level)
10156 unsigned long fp;
10157 int i;
10159 if (level == 0) {
10160 #if defined(__FreeBSD__)
10161 *paddr = uc->uc_mcontext.mc_eip;
10162 #elif defined(__dietlibc__)
10163 *paddr = uc->uc_mcontext.eip;
10164 #else
10165 *paddr = uc->uc_mcontext.gregs[REG_EIP];
10166 #endif
10167 return 0;
10168 } else {
10169 #if defined(__FreeBSD__)
10170 fp = uc->uc_mcontext.mc_ebp;
10171 #elif defined(__dietlibc__)
10172 fp = uc->uc_mcontext.ebp;
10173 #else
10174 fp = uc->uc_mcontext.gregs[REG_EBP];
10175 #endif
10176 for(i=1;i<level;i++) {
10177 /* XXX: check address validity with program info */
10178 if (fp <= 0x1000 || fp >= 0xc0000000)
10179 return -1;
10180 fp = ((unsigned long *)fp)[0];
10182 *paddr = ((unsigned long *)fp)[1];
10183 return 0;
10186 #elif defined(__x86_64__)
10187 /* return the PC at frame level 'level'. Return non zero if not found */
10188 static int rt_get_caller_pc(unsigned long *paddr,
10189 ucontext_t *uc, int level)
10191 unsigned long fp;
10192 int i;
10194 if (level == 0) {
10195 /* XXX: only support linux */
10196 *paddr = uc->uc_mcontext.gregs[REG_RIP];
10197 return 0;
10198 } else {
10199 fp = uc->uc_mcontext.gregs[REG_RBP];
10200 for(i=1;i<level;i++) {
10201 /* XXX: check address validity with program info */
10202 if (fp <= 0x1000)
10203 return -1;
10204 fp = ((unsigned long *)fp)[0];
10206 *paddr = ((unsigned long *)fp)[1];
10207 return 0;
10210 #else
10212 #warning add arch specific rt_get_caller_pc()
10214 static int rt_get_caller_pc(unsigned long *paddr,
10215 ucontext_t *uc, int level)
10217 return -1;
10219 #endif
10221 /* emit a run time error at position 'pc' */
10222 void rt_error(ucontext_t *uc, const char *fmt, ...)
10224 va_list ap;
10225 unsigned long pc;
10226 int i;
10228 va_start(ap, fmt);
10229 fprintf(stderr, "Runtime error: ");
10230 vfprintf(stderr, fmt, ap);
10231 fprintf(stderr, "\n");
10232 for(i=0;i<num_callers;i++) {
10233 if (rt_get_caller_pc(&pc, uc, i) < 0)
10234 break;
10235 if (i == 0)
10236 fprintf(stderr, "at ");
10237 else
10238 fprintf(stderr, "by ");
10239 rt_printline(pc);
10241 exit(255);
10242 va_end(ap);
10245 /* signal handler for fatal errors */
10246 static void sig_error(int signum, siginfo_t *siginf, void *puc)
10248 ucontext_t *uc = puc;
10250 switch(signum) {
10251 case SIGFPE:
10252 switch(siginf->si_code) {
10253 case FPE_INTDIV:
10254 case FPE_FLTDIV:
10255 rt_error(uc, "division by zero");
10256 break;
10257 default:
10258 rt_error(uc, "floating point exception");
10259 break;
10261 break;
10262 case SIGBUS:
10263 case SIGSEGV:
10264 if (rt_bound_error_msg && *rt_bound_error_msg)
10265 rt_error(uc, *rt_bound_error_msg);
10266 else
10267 rt_error(uc, "dereferencing invalid pointer");
10268 break;
10269 case SIGILL:
10270 rt_error(uc, "illegal instruction");
10271 break;
10272 case SIGABRT:
10273 rt_error(uc, "abort() called");
10274 break;
10275 default:
10276 rt_error(uc, "caught signal %d", signum);
10277 break;
10279 exit(255);
10281 #endif
10283 /* copy code into memory passed in by the caller and do all relocations
10284 (needed before using tcc_get_symbol()).
10285 returns -1 on error and required size if ptr is NULL */
10286 int tcc_relocate(TCCState *s1, void *ptr)
10288 Section *s;
10289 unsigned long offset, length, mem;
10290 int i;
10292 s1->nb_errors = 0;
10294 if (0 == s1->runtime_added) {
10295 #ifdef TCC_TARGET_PE
10296 pe_add_runtime(s1);
10297 relocate_common_syms();
10298 tcc_add_linker_symbols(s1);
10299 #else
10300 tcc_add_runtime(s1);
10301 relocate_common_syms();
10302 tcc_add_linker_symbols(s1);
10303 build_got_entries(s1);
10304 #endif
10305 s1->runtime_added = 1;
10308 offset = 0;
10309 mem = (unsigned long)ptr;
10310 for(i = 1; i < s1->nb_sections; i++) {
10311 s = s1->sections[i];
10312 if (0 == (s->sh_flags & SHF_ALLOC))
10313 continue;
10314 length = s->data_offset;
10315 if (0 == mem) {
10316 s->sh_addr = 0;
10317 } else if (1 == mem) {
10318 /* section are relocated in place.
10319 We also alloc the bss space */
10320 if (s->sh_type == SHT_NOBITS)
10321 s->data = tcc_malloc(length);
10322 s->sh_addr = (unsigned long)s->data;
10323 } else {
10324 /* sections are relocated to new memory */
10325 s->sh_addr = (mem + offset + 15) & ~15;
10327 offset = (offset + length + 15) & ~15;
10330 /* relocate symbols */
10331 relocate_syms(s1, 1);
10332 if (s1->nb_errors)
10333 return -1;
10335 if (0 == mem)
10336 return offset + 15;
10338 /* relocate each section */
10339 for(i = 1; i < s1->nb_sections; i++) {
10340 s = s1->sections[i];
10341 if (s->reloc)
10342 relocate_section(s1, s);
10345 for(i = 1; i < s1->nb_sections; i++) {
10346 s = s1->sections[i];
10347 if (0 == (s->sh_flags & SHF_ALLOC))
10348 continue;
10349 length = s->data_offset;
10350 // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
10351 ptr = (void*)s->sh_addr;
10352 if (NULL == s->data || s->sh_type == SHT_NOBITS)
10353 memset(ptr, 0, length);
10354 else if (ptr != s->data)
10355 memcpy(ptr, s->data, length);
10356 /* mark executable sections as executable in memory */
10357 if (s->sh_flags & SHF_EXECINSTR)
10358 set_pages_executable(ptr, length);
10360 return 0;
10363 /* launch the compiled program with the given arguments */
10364 int tcc_run(TCCState *s1, int argc, char **argv)
10366 int (*prog_main)(int, char **);
10367 void *ptr;
10368 int ret;
10370 ret = tcc_relocate(s1, NULL);
10371 if (ret < 0)
10372 return -1;
10373 ptr = tcc_malloc(ret);
10374 tcc_relocate(s1, ptr);
10376 prog_main = tcc_get_symbol_err(s1, "main");
10378 if (do_debug) {
10379 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10380 error("debug mode currently not available for Windows");
10381 #else
10382 struct sigaction sigact;
10383 /* install TCC signal handlers to print debug info on fatal
10384 runtime errors */
10385 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
10386 sigact.sa_sigaction = sig_error;
10387 sigemptyset(&sigact.sa_mask);
10388 sigaction(SIGFPE, &sigact, NULL);
10389 sigaction(SIGILL, &sigact, NULL);
10390 sigaction(SIGSEGV, &sigact, NULL);
10391 sigaction(SIGBUS, &sigact, NULL);
10392 sigaction(SIGABRT, &sigact, NULL);
10393 #endif
10396 #ifdef CONFIG_TCC_BCHECK
10397 if (do_bounds_check) {
10398 void (*bound_init)(void);
10400 /* set error function */
10401 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
10402 "__bound_error_msg");
10404 /* XXX: use .init section so that it also work in binary ? */
10405 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
10406 bound_init();
10408 #endif
10409 ret = (*prog_main)(argc, argv);
10410 tcc_free(ptr);
10411 return ret;
10414 void tcc_memstats(void)
10416 #ifdef MEM_DEBUG
10417 printf("memory in use: %d\n", mem_cur_size);
10418 #endif
10421 static void tcc_cleanup(void)
10423 int i, n;
10425 if (NULL == tcc_state)
10426 return;
10427 tcc_state = NULL;
10429 /* free -D defines */
10430 free_defines(NULL);
10432 /* free tokens */
10433 n = tok_ident - TOK_IDENT;
10434 for(i = 0; i < n; i++)
10435 tcc_free(table_ident[i]);
10436 tcc_free(table_ident);
10438 /* free sym_pools */
10439 dynarray_reset(&sym_pools, &nb_sym_pools);
10440 /* string buffer */
10441 cstr_free(&tokcstr);
10442 /* reset symbol stack */
10443 sym_free_first = NULL;
10444 /* cleanup from error/setjmp */
10445 macro_ptr = NULL;
10448 TCCState *tcc_new(void)
10450 const char *p, *r;
10451 TCCState *s;
10452 TokenSym *ts;
10453 int i, c;
10455 tcc_cleanup();
10457 s = tcc_mallocz(sizeof(TCCState));
10458 if (!s)
10459 return NULL;
10460 tcc_state = s;
10461 s->output_type = TCC_OUTPUT_MEMORY;
10463 /* init isid table */
10464 for(i=CH_EOF;i<256;i++)
10465 isidnum_table[i-CH_EOF] = isid(i) || isnum(i);
10467 /* add all tokens */
10468 table_ident = NULL;
10469 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
10471 tok_ident = TOK_IDENT;
10472 p = tcc_keywords;
10473 while (*p) {
10474 r = p;
10475 for(;;) {
10476 c = *r++;
10477 if (c == '\0')
10478 break;
10480 ts = tok_alloc(p, r - p - 1);
10481 p = r;
10484 /* we add dummy defines for some special macros to speed up tests
10485 and to have working defined() */
10486 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
10487 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
10488 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
10489 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
10491 /* standard defines */
10492 tcc_define_symbol(s, "__STDC__", NULL);
10493 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
10494 #if defined(TCC_TARGET_I386)
10495 tcc_define_symbol(s, "__i386__", NULL);
10496 #endif
10497 #if defined(TCC_TARGET_X86_64)
10498 tcc_define_symbol(s, "__x86_64__", NULL);
10499 #endif
10500 #if defined(TCC_TARGET_ARM)
10501 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10502 tcc_define_symbol(s, "__arm_elf__", NULL);
10503 tcc_define_symbol(s, "__arm_elf", NULL);
10504 tcc_define_symbol(s, "arm_elf", NULL);
10505 tcc_define_symbol(s, "__arm__", NULL);
10506 tcc_define_symbol(s, "__arm", NULL);
10507 tcc_define_symbol(s, "arm", NULL);
10508 tcc_define_symbol(s, "__APCS_32__", NULL);
10509 #endif
10510 #ifdef TCC_TARGET_PE
10511 tcc_define_symbol(s, "_WIN32", NULL);
10512 #else
10513 tcc_define_symbol(s, "__unix__", NULL);
10514 tcc_define_symbol(s, "__unix", NULL);
10515 #if defined(__linux)
10516 tcc_define_symbol(s, "__linux__", NULL);
10517 tcc_define_symbol(s, "__linux", NULL);
10518 #endif
10519 #endif
10520 /* tiny C specific defines */
10521 tcc_define_symbol(s, "__TINYC__", NULL);
10523 /* tiny C & gcc defines */
10524 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10525 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10526 #ifdef TCC_TARGET_PE
10527 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10528 #else
10529 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10530 #endif
10532 #ifndef TCC_TARGET_PE
10533 /* default library paths */
10534 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/local/lib");
10535 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/lib");
10536 tcc_add_library_path(s, CONFIG_SYSROOT "/lib");
10537 #endif
10539 /* no section zero */
10540 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10542 /* create standard sections */
10543 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10544 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10545 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10547 /* symbols are always generated for linking stage */
10548 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10549 ".strtab",
10550 ".hashtab", SHF_PRIVATE);
10551 strtab_section = symtab_section->link;
10553 /* private symbol table for dynamic symbols */
10554 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10555 ".dynstrtab",
10556 ".dynhashtab", SHF_PRIVATE);
10557 s->alacarte_link = 1;
10559 #ifdef CHAR_IS_UNSIGNED
10560 s->char_is_unsigned = 1;
10561 #endif
10562 #if defined(TCC_TARGET_PE) && 0
10563 /* XXX: currently the PE linker is not ready to support that */
10564 s->leading_underscore = 1;
10565 #endif
10566 return s;
10569 void tcc_delete(TCCState *s1)
10571 int i;
10573 tcc_cleanup();
10575 /* free all sections */
10576 for(i = 1; i < s1->nb_sections; i++)
10577 free_section(s1->sections[i]);
10578 dynarray_reset(&s1->sections, &s1->nb_sections);
10580 for(i = 0; i < s1->nb_priv_sections; i++)
10581 free_section(s1->priv_sections[i]);
10582 dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
10584 /* free any loaded DLLs */
10585 for ( i = 0; i < s1->nb_loaded_dlls; i++) {
10586 DLLReference *ref = s1->loaded_dlls[i];
10587 if ( ref->handle )
10588 dlclose(ref->handle);
10591 /* free loaded dlls array */
10592 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
10594 /* free library paths */
10595 dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
10597 /* free include paths */
10598 dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
10599 dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
10600 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
10602 tcc_free(s1);
10605 int tcc_add_include_path(TCCState *s1, const char *pathname)
10607 char *pathname1;
10609 pathname1 = tcc_strdup(pathname);
10610 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10611 return 0;
10614 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10616 char *pathname1;
10618 pathname1 = tcc_strdup(pathname);
10619 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10620 return 0;
10623 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10625 const char *ext;
10626 ElfW(Ehdr) ehdr;
10627 int fd, ret;
10628 BufferedFile *saved_file;
10630 /* find source file type with extension */
10631 ext = tcc_fileextension(filename);
10632 if (ext[0])
10633 ext++;
10635 /* open the file */
10636 saved_file = file;
10637 file = tcc_open(s1, filename);
10638 if (!file) {
10639 if (flags & AFF_PRINT_ERROR) {
10640 error_noabort("file '%s' not found", filename);
10642 ret = -1;
10643 goto fail1;
10646 if (flags & AFF_PREPROCESS) {
10647 ret = tcc_preprocess(s1);
10648 } else if (!ext[0] || !PATHCMP(ext, "c")) {
10649 /* C file assumed */
10650 ret = tcc_compile(s1);
10651 } else
10652 #ifdef CONFIG_TCC_ASM
10653 if (!strcmp(ext, "S")) {
10654 /* preprocessed assembler */
10655 ret = tcc_assemble(s1, 1);
10656 } else if (!strcmp(ext, "s")) {
10657 /* non preprocessed assembler */
10658 ret = tcc_assemble(s1, 0);
10659 } else
10660 #endif
10661 #ifdef TCC_TARGET_PE
10662 if (!PATHCMP(ext, "def")) {
10663 ret = pe_load_def_file(s1, file->fd);
10664 } else
10665 #endif
10667 fd = file->fd;
10668 /* assume executable format: auto guess file type */
10669 ret = read(fd, &ehdr, sizeof(ehdr));
10670 lseek(fd, 0, SEEK_SET);
10671 if (ret <= 0) {
10672 error_noabort("could not read header");
10673 goto fail;
10674 } else if (ret != sizeof(ehdr)) {
10675 goto try_load_script;
10678 if (ehdr.e_ident[0] == ELFMAG0 &&
10679 ehdr.e_ident[1] == ELFMAG1 &&
10680 ehdr.e_ident[2] == ELFMAG2 &&
10681 ehdr.e_ident[3] == ELFMAG3) {
10682 file->line_num = 0; /* do not display line number if error */
10683 if (ehdr.e_type == ET_REL) {
10684 ret = tcc_load_object_file(s1, fd, 0);
10685 } else if (ehdr.e_type == ET_DYN) {
10686 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10687 #ifdef TCC_TARGET_PE
10688 ret = -1;
10689 #else
10690 void *h;
10691 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10692 if (h)
10693 ret = 0;
10694 else
10695 ret = -1;
10696 #endif
10697 } else {
10698 ret = tcc_load_dll(s1, fd, filename,
10699 (flags & AFF_REFERENCED_DLL) != 0);
10701 } else {
10702 error_noabort("unrecognized ELF file");
10703 goto fail;
10705 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10706 file->line_num = 0; /* do not display line number if error */
10707 ret = tcc_load_archive(s1, fd);
10708 } else
10709 #ifdef TCC_TARGET_COFF
10710 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10711 ret = tcc_load_coff(s1, fd);
10712 } else
10713 #endif
10714 #ifdef TCC_TARGET_PE
10715 if (pe_test_res_file(&ehdr, ret)) {
10716 ret = pe_load_res_file(s1, fd);
10717 } else
10718 #endif
10720 /* as GNU ld, consider it is an ld script if not recognized */
10721 try_load_script:
10722 ret = tcc_load_ldscript(s1);
10723 if (ret < 0) {
10724 error_noabort("unrecognized file type");
10725 goto fail;
10729 the_end:
10730 tcc_close(file);
10731 fail1:
10732 file = saved_file;
10733 return ret;
10734 fail:
10735 ret = -1;
10736 goto the_end;
10739 int tcc_add_file(TCCState *s, const char *filename)
10741 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10744 int tcc_add_library_path(TCCState *s, const char *pathname)
10746 char *pathname1;
10748 pathname1 = tcc_strdup(pathname);
10749 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10750 return 0;
10753 /* find and load a dll. Return non zero if not found */
10754 /* XXX: add '-rpath' option support ? */
10755 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10757 char buf[1024];
10758 int i;
10760 for(i = 0; i < s->nb_library_paths; i++) {
10761 snprintf(buf, sizeof(buf), "%s/%s",
10762 s->library_paths[i], filename);
10763 if (tcc_add_file_internal(s, buf, flags) == 0)
10764 return 0;
10766 return -1;
10769 /* the library name is the same as the argument of the '-l' option */
10770 int tcc_add_library(TCCState *s, const char *libraryname)
10772 char buf[1024];
10773 int i;
10775 /* first we look for the dynamic library if not static linking */
10776 if (!s->static_link) {
10777 #ifdef TCC_TARGET_PE
10778 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10779 #else
10780 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10781 #endif
10782 if (tcc_add_dll(s, buf, 0) == 0)
10783 return 0;
10786 /* then we look for the static library */
10787 for(i = 0; i < s->nb_library_paths; i++) {
10788 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10789 s->library_paths[i], libraryname);
10790 if (tcc_add_file_internal(s, buf, 0) == 0)
10791 return 0;
10793 return -1;
10796 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10798 add_elf_sym(symtab_section, val, 0,
10799 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
10800 SHN_ABS, name);
10801 return 0;
10804 int tcc_set_output_type(TCCState *s, int output_type)
10806 char buf[1024];
10808 s->output_type = output_type;
10810 if (!s->nostdinc) {
10811 /* default include paths */
10812 /* XXX: reverse order needed if -isystem support */
10813 #ifndef TCC_TARGET_PE
10814 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/local/include");
10815 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/include");
10816 #endif
10817 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10818 tcc_add_sysinclude_path(s, buf);
10819 #ifdef TCC_TARGET_PE
10820 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10821 tcc_add_sysinclude_path(s, buf);
10822 #endif
10825 /* if bound checking, then add corresponding sections */
10826 #ifdef CONFIG_TCC_BCHECK
10827 if (do_bounds_check) {
10828 /* define symbol */
10829 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10830 /* create bounds sections */
10831 bounds_section = new_section(s, ".bounds",
10832 SHT_PROGBITS, SHF_ALLOC);
10833 lbounds_section = new_section(s, ".lbounds",
10834 SHT_PROGBITS, SHF_ALLOC);
10836 #endif
10838 if (s->char_is_unsigned) {
10839 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10842 /* add debug sections */
10843 if (do_debug) {
10844 /* stab symbols */
10845 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10846 stab_section->sh_entsize = sizeof(Stab_Sym);
10847 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10848 put_elf_str(stabstr_section, "");
10849 stab_section->link = stabstr_section;
10850 /* put first entry */
10851 put_stabs("", 0, 0, 0, 0);
10854 /* add libc crt1/crti objects */
10855 #ifndef TCC_TARGET_PE
10856 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10857 !s->nostdlib) {
10858 if (output_type != TCC_OUTPUT_DLL)
10859 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10860 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10862 #endif
10864 #ifdef TCC_TARGET_PE
10865 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10866 tcc_add_library_path(s, buf);
10867 #endif
10869 return 0;
10872 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10873 #define FD_INVERT 0x0002 /* invert value before storing */
10875 typedef struct FlagDef {
10876 uint16_t offset;
10877 uint16_t flags;
10878 const char *name;
10879 } FlagDef;
10881 static const FlagDef warning_defs[] = {
10882 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10883 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10884 { offsetof(TCCState, warn_error), 0, "error" },
10885 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10886 "implicit-function-declaration" },
10889 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10890 const char *name, int value)
10892 int i;
10893 const FlagDef *p;
10894 const char *r;
10896 r = name;
10897 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10898 r += 3;
10899 value = !value;
10901 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10902 if (!strcmp(r, p->name))
10903 goto found;
10905 return -1;
10906 found:
10907 if (p->flags & FD_INVERT)
10908 value = !value;
10909 *(int *)((uint8_t *)s + p->offset) = value;
10910 return 0;
10914 /* set/reset a warning */
10915 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10917 int i;
10918 const FlagDef *p;
10920 if (!strcmp(warning_name, "all")) {
10921 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10922 if (p->flags & WD_ALL)
10923 *(int *)((uint8_t *)s + p->offset) = 1;
10925 return 0;
10926 } else {
10927 return set_flag(s, warning_defs, countof(warning_defs),
10928 warning_name, value);
10932 static const FlagDef flag_defs[] = {
10933 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10934 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10935 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10936 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10939 /* set/reset a flag */
10940 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10942 return set_flag(s, flag_defs, countof(flag_defs),
10943 flag_name, value);
10946 #if !defined(LIBTCC)
10948 static int64_t getclock_us(void)
10950 #ifdef _WIN32
10951 struct _timeb tb;
10952 _ftime(&tb);
10953 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10954 #else
10955 struct timeval tv;
10956 gettimeofday(&tv, NULL);
10957 return tv.tv_sec * 1000000LL + tv.tv_usec;
10958 #endif
10961 void help(void)
10963 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10964 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10965 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
10966 " [-static] [infile1 infile2...] [-run infile args...]\n"
10967 "\n"
10968 "General options:\n"
10969 " -v display current version, increase verbosity\n"
10970 " -c compile only - generate an object file\n"
10971 " -o outfile set output filename\n"
10972 " -Bdir set tcc internal library path\n"
10973 " -bench output compilation statistics\n"
10974 " -run run compiled source\n"
10975 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10976 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10977 " -w disable all warnings\n"
10978 "Preprocessor options:\n"
10979 " -E preprocess only\n"
10980 " -Idir add include path 'dir'\n"
10981 " -Dsym[=val] define 'sym' with value 'val'\n"
10982 " -Usym undefine 'sym'\n"
10983 "Linker options:\n"
10984 " -Ldir add library path 'dir'\n"
10985 " -llib link with dynamic or static library 'lib'\n"
10986 " -shared generate a shared library\n"
10987 " -soname set name for shared library to be used at runtime\n"
10988 " -static static linking\n"
10989 " -rdynamic export all global symbols to dynamic linker\n"
10990 " -r generate (relocatable) object file\n"
10991 "Debugger options:\n"
10992 " -g generate runtime debug info\n"
10993 #ifdef CONFIG_TCC_BCHECK
10994 " -b compile with built-in memory and bounds checker (implies -g)\n"
10995 #endif
10996 " -bt N show N callers in stack traces\n"
11000 #define TCC_OPTION_HAS_ARG 0x0001
11001 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
11003 typedef struct TCCOption {
11004 const char *name;
11005 uint16_t index;
11006 uint16_t flags;
11007 } TCCOption;
11009 enum {
11010 TCC_OPTION_HELP,
11011 TCC_OPTION_I,
11012 TCC_OPTION_D,
11013 TCC_OPTION_U,
11014 TCC_OPTION_L,
11015 TCC_OPTION_B,
11016 TCC_OPTION_l,
11017 TCC_OPTION_bench,
11018 TCC_OPTION_bt,
11019 TCC_OPTION_b,
11020 TCC_OPTION_g,
11021 TCC_OPTION_c,
11022 TCC_OPTION_static,
11023 TCC_OPTION_shared,
11024 TCC_OPTION_soname,
11025 TCC_OPTION_o,
11026 TCC_OPTION_r,
11027 TCC_OPTION_Wl,
11028 TCC_OPTION_W,
11029 TCC_OPTION_O,
11030 TCC_OPTION_m,
11031 TCC_OPTION_f,
11032 TCC_OPTION_nostdinc,
11033 TCC_OPTION_nostdlib,
11034 TCC_OPTION_print_search_dirs,
11035 TCC_OPTION_rdynamic,
11036 TCC_OPTION_run,
11037 TCC_OPTION_v,
11038 TCC_OPTION_w,
11039 TCC_OPTION_pipe,
11040 TCC_OPTION_E,
11043 static const TCCOption tcc_options[] = {
11044 { "h", TCC_OPTION_HELP, 0 },
11045 { "?", TCC_OPTION_HELP, 0 },
11046 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
11047 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
11048 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
11049 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
11050 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
11051 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11052 { "bench", TCC_OPTION_bench, 0 },
11053 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
11054 #ifdef CONFIG_TCC_BCHECK
11055 { "b", TCC_OPTION_b, 0 },
11056 #endif
11057 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11058 { "c", TCC_OPTION_c, 0 },
11059 { "static", TCC_OPTION_static, 0 },
11060 { "shared", TCC_OPTION_shared, 0 },
11061 { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
11062 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
11063 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11064 { "rdynamic", TCC_OPTION_rdynamic, 0 },
11065 { "r", TCC_OPTION_r, 0 },
11066 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11067 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11068 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11069 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
11070 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11071 { "nostdinc", TCC_OPTION_nostdinc, 0 },
11072 { "nostdlib", TCC_OPTION_nostdlib, 0 },
11073 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
11074 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11075 { "w", TCC_OPTION_w, 0 },
11076 { "pipe", TCC_OPTION_pipe, 0},
11077 { "E", TCC_OPTION_E, 0},
11078 { NULL },
11081 /* convert 'str' into an array of space separated strings */
11082 static int expand_args(char ***pargv, const char *str)
11084 const char *s1;
11085 char **argv, *arg;
11086 int argc, len;
11088 argc = 0;
11089 argv = NULL;
11090 for(;;) {
11091 while (is_space(*str))
11092 str++;
11093 if (*str == '\0')
11094 break;
11095 s1 = str;
11096 while (*str != '\0' && !is_space(*str))
11097 str++;
11098 len = str - s1;
11099 arg = tcc_malloc(len + 1);
11100 memcpy(arg, s1, len);
11101 arg[len] = '\0';
11102 dynarray_add((void ***)&argv, &argc, arg);
11104 *pargv = argv;
11105 return argc;
11108 static char **files;
11109 static int nb_files, nb_libraries;
11110 static int multiple_files;
11111 static int print_search_dirs;
11112 static int output_type;
11113 static int reloc_output;
11114 static const char *outfile;
11116 int parse_args(TCCState *s, int argc, char **argv)
11118 int optind;
11119 const TCCOption *popt;
11120 const char *optarg, *p1, *r1;
11121 char *r;
11123 optind = 0;
11124 while (optind < argc) {
11126 r = argv[optind++];
11127 if (r[0] != '-' || r[1] == '\0') {
11128 /* add a new file */
11129 dynarray_add((void ***)&files, &nb_files, r);
11130 if (!multiple_files) {
11131 optind--;
11132 /* argv[0] will be this file */
11133 break;
11135 } else {
11136 /* find option in table (match only the first chars */
11137 popt = tcc_options;
11138 for(;;) {
11139 p1 = popt->name;
11140 if (p1 == NULL)
11141 error("invalid option -- '%s'", r);
11142 r1 = r + 1;
11143 for(;;) {
11144 if (*p1 == '\0')
11145 goto option_found;
11146 if (*r1 != *p1)
11147 break;
11148 p1++;
11149 r1++;
11151 popt++;
11153 option_found:
11154 if (popt->flags & TCC_OPTION_HAS_ARG) {
11155 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
11156 optarg = r1;
11157 } else {
11158 if (optind >= argc)
11159 error("argument to '%s' is missing", r);
11160 optarg = argv[optind++];
11162 } else {
11163 if (*r1 != '\0')
11164 return 0;
11165 optarg = NULL;
11168 switch(popt->index) {
11169 case TCC_OPTION_HELP:
11170 return 0;
11172 case TCC_OPTION_I:
11173 if (tcc_add_include_path(s, optarg) < 0)
11174 error("too many include paths");
11175 break;
11176 case TCC_OPTION_D:
11178 char *sym, *value;
11179 sym = (char *)optarg;
11180 value = strchr(sym, '=');
11181 if (value) {
11182 *value = '\0';
11183 value++;
11185 tcc_define_symbol(s, sym, value);
11187 break;
11188 case TCC_OPTION_U:
11189 tcc_undefine_symbol(s, optarg);
11190 break;
11191 case TCC_OPTION_L:
11192 tcc_add_library_path(s, optarg);
11193 break;
11194 case TCC_OPTION_B:
11195 /* set tcc utilities path (mainly for tcc development) */
11196 tcc_lib_path = optarg;
11197 break;
11198 case TCC_OPTION_l:
11199 dynarray_add((void ***)&files, &nb_files, r);
11200 nb_libraries++;
11201 break;
11202 case TCC_OPTION_bench:
11203 do_bench = 1;
11204 break;
11205 case TCC_OPTION_bt:
11206 num_callers = atoi(optarg);
11207 break;
11208 #ifdef CONFIG_TCC_BCHECK
11209 case TCC_OPTION_b:
11210 do_bounds_check = 1;
11211 do_debug = 1;
11212 break;
11213 #endif
11214 case TCC_OPTION_g:
11215 do_debug = 1;
11216 break;
11217 case TCC_OPTION_c:
11218 multiple_files = 1;
11219 output_type = TCC_OUTPUT_OBJ;
11220 break;
11221 case TCC_OPTION_static:
11222 s->static_link = 1;
11223 break;
11224 case TCC_OPTION_shared:
11225 output_type = TCC_OUTPUT_DLL;
11226 break;
11227 case TCC_OPTION_soname:
11228 s->soname = optarg;
11229 break;
11230 case TCC_OPTION_o:
11231 multiple_files = 1;
11232 outfile = optarg;
11233 break;
11234 case TCC_OPTION_r:
11235 /* generate a .o merging several output files */
11236 reloc_output = 1;
11237 output_type = TCC_OUTPUT_OBJ;
11238 break;
11239 case TCC_OPTION_nostdinc:
11240 s->nostdinc = 1;
11241 break;
11242 case TCC_OPTION_nostdlib:
11243 s->nostdlib = 1;
11244 break;
11245 case TCC_OPTION_print_search_dirs:
11246 print_search_dirs = 1;
11247 break;
11248 case TCC_OPTION_run:
11250 int argc1;
11251 char **argv1;
11252 argc1 = expand_args(&argv1, optarg);
11253 if (argc1 > 0) {
11254 parse_args(s, argc1, argv1);
11256 multiple_files = 0;
11257 output_type = TCC_OUTPUT_MEMORY;
11259 break;
11260 case TCC_OPTION_v:
11261 do {
11262 if (0 == verbose++)
11263 printf("tcc version %s\n", TCC_VERSION);
11264 } while (*optarg++ == 'v');
11265 break;
11266 case TCC_OPTION_f:
11267 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
11268 goto unsupported_option;
11269 break;
11270 case TCC_OPTION_W:
11271 if (tcc_set_warning(s, optarg, 1) < 0 &&
11272 s->warn_unsupported)
11273 goto unsupported_option;
11274 break;
11275 case TCC_OPTION_w:
11276 s->warn_none = 1;
11277 break;
11278 case TCC_OPTION_rdynamic:
11279 s->rdynamic = 1;
11280 break;
11281 case TCC_OPTION_Wl:
11283 const char *p;
11284 if (strstart(optarg, "-Ttext,", &p)) {
11285 s->text_addr = strtoul(p, NULL, 16);
11286 s->has_text_addr = 1;
11287 } else if (strstart(optarg, "--oformat,", &p)) {
11288 if (strstart(p, "elf32-", NULL)) {
11289 s->output_format = TCC_OUTPUT_FORMAT_ELF;
11290 } else if (!strcmp(p, "binary")) {
11291 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
11292 } else
11293 #ifdef TCC_TARGET_COFF
11294 if (!strcmp(p, "coff")) {
11295 s->output_format = TCC_OUTPUT_FORMAT_COFF;
11296 } else
11297 #endif
11299 error("target %s not found", p);
11301 } else {
11302 error("unsupported linker option '%s'", optarg);
11305 break;
11306 case TCC_OPTION_E:
11307 output_type = TCC_OUTPUT_PREPROCESS;
11308 break;
11309 default:
11310 if (s->warn_unsupported) {
11311 unsupported_option:
11312 warning("unsupported option '%s'", r);
11314 break;
11318 return optind + 1;
11321 int main(int argc, char **argv)
11323 int i;
11324 TCCState *s;
11325 int nb_objfiles, ret, optind;
11326 char objfilename[1024];
11327 int64_t start_time = 0;
11329 #ifdef _WIN32
11330 tcc_lib_path = w32_tcc_lib_path();
11331 #endif
11333 s = tcc_new();
11334 output_type = TCC_OUTPUT_EXE;
11335 outfile = NULL;
11336 multiple_files = 1;
11337 files = NULL;
11338 nb_files = 0;
11339 nb_libraries = 0;
11340 reloc_output = 0;
11341 print_search_dirs = 0;
11342 ret = 0;
11344 optind = parse_args(s, argc - 1, argv + 1);
11345 if (print_search_dirs) {
11346 /* enough for Linux kernel */
11347 printf("install: %s/\n", tcc_lib_path);
11348 return 0;
11350 if (optind == 0 || nb_files == 0) {
11351 if (optind && verbose)
11352 return 0;
11353 help();
11354 return 1;
11357 nb_objfiles = nb_files - nb_libraries;
11359 /* if outfile provided without other options, we output an
11360 executable */
11361 if (outfile && output_type == TCC_OUTPUT_MEMORY)
11362 output_type = TCC_OUTPUT_EXE;
11364 /* check -c consistency : only single file handled. XXX: checks file type */
11365 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
11366 /* accepts only a single input file */
11367 if (nb_objfiles != 1)
11368 error("cannot specify multiple files with -c");
11369 if (nb_libraries != 0)
11370 error("cannot specify libraries with -c");
11374 if (output_type == TCC_OUTPUT_PREPROCESS) {
11375 if (!outfile) {
11376 s->outfile = stdout;
11377 } else {
11378 s->outfile = fopen(outfile, "w");
11379 if (!s->outfile)
11380 error("could not open '%s", outfile);
11382 } else if (output_type != TCC_OUTPUT_MEMORY) {
11383 if (!outfile) {
11384 /* compute default outfile name */
11385 char *ext;
11386 const char *name =
11387 strcmp(files[0], "-") == 0 ? "a" : tcc_basename(files[0]);
11388 pstrcpy(objfilename, sizeof(objfilename), name);
11389 ext = tcc_fileextension(objfilename);
11390 #ifdef TCC_TARGET_PE
11391 if (output_type == TCC_OUTPUT_DLL)
11392 strcpy(ext, ".dll");
11393 else
11394 if (output_type == TCC_OUTPUT_EXE)
11395 strcpy(ext, ".exe");
11396 else
11397 #endif
11398 if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
11399 strcpy(ext, ".o");
11400 else
11401 pstrcpy(objfilename, sizeof(objfilename), "a.out");
11402 outfile = objfilename;
11406 if (do_bench) {
11407 start_time = getclock_us();
11410 tcc_set_output_type(s, output_type);
11412 /* compile or add each files or library */
11413 for(i = 0; i < nb_files && ret == 0; i++) {
11414 const char *filename;
11416 filename = files[i];
11417 if (output_type == TCC_OUTPUT_PREPROCESS) {
11418 if (tcc_add_file_internal(s, filename,
11419 AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
11420 ret = 1;
11421 } else if (filename[0] == '-' && filename[1]) {
11422 if (tcc_add_library(s, filename + 2) < 0)
11423 error("cannot find %s", filename);
11424 } else {
11425 if (1 == verbose)
11426 printf("-> %s\n", filename);
11427 if (tcc_add_file(s, filename) < 0)
11428 ret = 1;
11432 /* free all files */
11433 tcc_free(files);
11435 if (ret)
11436 goto the_end;
11438 if (do_bench) {
11439 double total_time;
11440 total_time = (double)(getclock_us() - start_time) / 1000000.0;
11441 if (total_time < 0.001)
11442 total_time = 0.001;
11443 if (total_bytes < 1)
11444 total_bytes = 1;
11445 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11446 tok_ident - TOK_IDENT, total_lines, total_bytes,
11447 total_time, (int)(total_lines / total_time),
11448 total_bytes / total_time / 1000000.0);
11451 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
11452 if (outfile)
11453 fclose(s->outfile);
11454 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
11455 ret = tcc_run(s, argc - optind, argv + optind);
11456 } else
11457 ret = tcc_output_file(s, outfile) ? 1 : 0;
11458 the_end:
11459 /* XXX: cannot do it with bound checking because of the malloc hooks */
11460 if (!do_bounds_check)
11461 tcc_delete(s);
11463 #ifdef MEM_DEBUG
11464 if (do_bench) {
11465 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
11467 #endif
11468 return ret;
11471 #endif