enable backtrace only when it's supported
[tinycc.git] / tcc.c
blob7334b52fa0f184124963713a21b63617543be99d
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 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
116 #define CONFIG_TCC_BACKTRACE
117 #endif
119 #define FALSE 0
120 #define false 0
121 #define TRUE 1
122 #define true 1
123 typedef int BOOL;
125 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
126 executables or dlls */
127 #define CONFIG_TCC_CRT_PREFIX CONFIG_SYSROOT "/usr/lib"
129 #define INCLUDE_STACK_SIZE 32
130 #define IFDEF_STACK_SIZE 64
131 #define VSTACK_SIZE 256
132 #define STRING_MAX_SIZE 1024
133 #define PACK_STACK_SIZE 8
135 #define TOK_HASH_SIZE 8192 /* must be a power of two */
136 #define TOK_ALLOC_INCR 512 /* must be a power of two */
137 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
139 /* token symbol management */
140 typedef struct TokenSym {
141 struct TokenSym *hash_next;
142 struct Sym *sym_define; /* direct pointer to define */
143 struct Sym *sym_label; /* direct pointer to label */
144 struct Sym *sym_struct; /* direct pointer to structure */
145 struct Sym *sym_identifier; /* direct pointer to identifier */
146 int tok; /* token number */
147 int len;
148 char str[1];
149 } TokenSym;
151 #ifdef TCC_TARGET_PE
152 typedef unsigned short nwchar_t;
153 #else
154 typedef int nwchar_t;
155 #endif
157 typedef struct CString {
158 int size; /* size in bytes */
159 void *data; /* either 'char *' or 'nwchar_t *' */
160 int size_allocated;
161 void *data_allocated; /* if non NULL, data has been malloced */
162 } CString;
164 /* type definition */
165 typedef struct CType {
166 int t;
167 struct Sym *ref;
168 } CType;
170 /* constant value */
171 typedef union CValue {
172 long double ld;
173 double d;
174 float f;
175 int i;
176 unsigned int ui;
177 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
178 long long ll;
179 unsigned long long ull;
180 struct CString *cstr;
181 void *ptr;
182 int tab[1];
183 } CValue;
185 /* value on stack */
186 typedef struct SValue {
187 CType type; /* type */
188 unsigned short r; /* register + flags */
189 unsigned short r2; /* second register, used for 'long long'
190 type. If not used, set to VT_CONST */
191 CValue c; /* constant, if VT_CONST */
192 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
193 } SValue;
195 /* symbol management */
196 typedef struct Sym {
197 int v; /* symbol token */
198 long r; /* associated register */
199 long c; /* associated number */
200 CType type; /* associated type */
201 struct Sym *next; /* next related symbol */
202 struct Sym *prev; /* prev symbol in stack */
203 struct Sym *prev_tok; /* previous symbol for this token */
204 } Sym;
206 /* section definition */
207 /* XXX: use directly ELF structure for parameters ? */
208 /* special flag to indicate that the section should not be linked to
209 the other ones */
210 #define SHF_PRIVATE 0x80000000
212 typedef struct Section {
213 unsigned long data_offset; /* current data offset */
214 unsigned char *data; /* section data */
215 unsigned long data_allocated; /* used for realloc() handling */
216 int sh_name; /* elf section name (only used during output) */
217 int sh_num; /* elf section number */
218 int sh_type; /* elf section type */
219 int sh_flags; /* elf section flags */
220 int sh_info; /* elf section info */
221 int sh_addralign; /* elf section alignment */
222 int sh_entsize; /* elf entry size */
223 unsigned long sh_size; /* section size (only used during output) */
224 unsigned long sh_addr; /* address at which the section is relocated */
225 unsigned long sh_offset; /* file offset */
226 int nb_hashed_syms; /* used to resize the hash table */
227 struct Section *link; /* link to another section */
228 struct Section *reloc; /* corresponding section for relocation, if any */
229 struct Section *hash; /* hash table for symbols */
230 struct Section *next;
231 char name[1]; /* section name */
232 } Section;
234 typedef struct DLLReference {
235 int level;
236 void *handle;
237 char name[1];
238 } DLLReference;
240 /* GNUC attribute definition */
241 typedef struct AttributeDef {
242 int aligned;
243 int packed;
244 Section *section;
245 int func_attr; /* calling convention, exports, ... */
246 } AttributeDef;
248 /* -------------------------------------------------- */
249 /* gr: wrappers for casting sym->r for other purposes */
250 typedef struct {
251 unsigned
252 func_call : 8,
253 func_args : 8,
254 func_export : 1;
255 } func_attr_t;
257 #define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
258 #define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
259 #define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
260 #define INLINE_DEF(r) (*(int **)&(r))
261 /* -------------------------------------------------- */
263 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
264 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
265 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
267 /* stored in 'Sym.c' field */
268 #define FUNC_NEW 1 /* ansi function prototype */
269 #define FUNC_OLD 2 /* old function prototype */
270 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
272 /* stored in 'Sym.r' field */
273 #define FUNC_CDECL 0 /* standard c call */
274 #define FUNC_STDCALL 1 /* pascal c call */
275 #define FUNC_FASTCALL1 2 /* first param in %eax */
276 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
277 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
278 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
280 /* field 'Sym.t' for macros */
281 #define MACRO_OBJ 0 /* object like macro */
282 #define MACRO_FUNC 1 /* function like macro */
284 /* field 'Sym.r' for C labels */
285 #define LABEL_DEFINED 0 /* label is defined */
286 #define LABEL_FORWARD 1 /* label is forward defined */
287 #define LABEL_DECLARED 2 /* label is declared but never used */
289 /* type_decl() types */
290 #define TYPE_ABSTRACT 1 /* type without variable */
291 #define TYPE_DIRECT 2 /* type with variable */
293 #define IO_BUF_SIZE 8192
295 typedef struct BufferedFile {
296 uint8_t *buf_ptr;
297 uint8_t *buf_end;
298 int fd;
299 int line_num; /* current line number - here to simplify code */
300 int ifndef_macro; /* #ifndef macro / #endif search */
301 int ifndef_macro_saved; /* saved ifndef_macro */
302 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
303 char inc_type; /* type of include */
304 char inc_filename[512]; /* filename specified by the user */
305 char filename[1024]; /* current filename - here to simplify code */
306 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
307 } BufferedFile;
309 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
310 #define CH_EOF (-1) /* end of file */
312 /* parsing state (used to save parser state to reparse part of the
313 source several times) */
314 typedef struct ParseState {
315 int *macro_ptr;
316 int line_num;
317 int tok;
318 CValue tokc;
319 } ParseState;
321 /* used to record tokens */
322 typedef struct TokenString {
323 int *str;
324 int len;
325 int allocated_len;
326 int last_line_num;
327 } TokenString;
329 /* include file cache, used to find files faster and also to eliminate
330 inclusion if the include file is protected by #ifndef ... #endif */
331 typedef struct CachedInclude {
332 int ifndef_macro;
333 int hash_next; /* -1 if none */
334 char type; /* '"' or '>' to give include type */
335 char filename[1]; /* path specified in #include */
336 } CachedInclude;
338 #define CACHED_INCLUDES_HASH_SIZE 512
340 /* parser */
341 static struct BufferedFile *file;
342 static int ch, tok;
343 static CValue tokc;
344 static CString tokcstr; /* current parsed string, if any */
345 /* additional informations about token */
346 static int tok_flags;
347 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
348 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
349 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
350 #define TOK_FLAG_EOF 0x0008 /* end of file */
352 static int *macro_ptr, *macro_ptr_allocated;
353 static int *unget_saved_macro_ptr;
354 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
355 static int unget_buffer_enabled;
356 static int parse_flags;
357 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
358 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
359 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
360 token. line feed is also
361 returned at eof */
362 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
363 #define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
365 static Section *text_section, *data_section, *bss_section; /* predefined sections */
366 static Section *cur_text_section; /* current section where function code is
367 generated */
368 #ifdef CONFIG_TCC_ASM
369 static Section *last_text_section; /* to handle .previous asm directive */
370 #endif
371 /* bound check related sections */
372 static Section *bounds_section; /* contains global data bound description */
373 static Section *lbounds_section; /* contains local data bound description */
374 /* symbol sections */
375 static Section *symtab_section, *strtab_section;
377 /* debug sections */
378 static Section *stab_section, *stabstr_section;
380 /* loc : local variable index
381 ind : output code index
382 rsym: return symbol
383 anon_sym: anonymous symbol index
385 static int rsym, anon_sym, ind, loc;
386 /* expression generation modifiers */
387 static int const_wanted; /* true if constant wanted */
388 static int nocode_wanted; /* true if no code generation wanted for an expression */
389 static int global_expr; /* true if compound literals must be allocated
390 globally (used during initializers parsing */
391 static CType func_vt; /* current function return type (used by return
392 instruction) */
393 static int func_vc;
394 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
395 static int tok_ident;
396 static TokenSym **table_ident;
397 static TokenSym *hash_ident[TOK_HASH_SIZE];
398 static char token_buf[STRING_MAX_SIZE + 1];
399 static char *funcname;
400 static Sym *global_stack, *local_stack;
401 static Sym *define_stack;
402 static Sym *global_label_stack, *local_label_stack;
403 /* symbol allocator */
404 #define SYM_POOL_NB (8192 / sizeof(Sym))
405 static Sym *sym_free_first;
406 static void **sym_pools;
407 static int nb_sym_pools;
409 static SValue vstack[VSTACK_SIZE], *vtop;
410 /* some predefined types */
411 static CType char_pointer_type, func_old_type, int_type;
412 /* true if isid(c) || isnum(c) */
413 static unsigned char isidnum_table[256-CH_EOF];
415 /* display some information during compilation */
416 static int verbose = 0;
418 /* compile with debug symbol (and use them if error during execution) */
419 static int do_debug = 0;
421 /* compile with built-in memory and bounds checker */
422 static int do_bounds_check = 0;
424 /* display benchmark infos */
425 #if !defined(LIBTCC)
426 static int do_bench = 0;
427 #endif
428 static int total_lines;
429 static int total_bytes;
431 /* use GNU C extensions */
432 static int gnu_ext = 1;
434 /* use Tiny C extensions */
435 static int tcc_ext = 1;
437 /* max number of callers shown if error */
438 #ifdef CONFIG_TCC_BACKTRACE
439 static int num_callers = 6;
440 static const char **rt_bound_error_msg;
441 #endif
443 /* XXX: get rid of this ASAP */
444 static struct TCCState *tcc_state;
446 /* give the path of the tcc libraries */
447 static const char *tcc_lib_path = CONFIG_TCCDIR;
449 struct TCCState {
450 int output_type;
452 BufferedFile **include_stack_ptr;
453 int *ifdef_stack_ptr;
455 /* include file handling */
456 char **include_paths;
457 int nb_include_paths;
458 char **sysinclude_paths;
459 int nb_sysinclude_paths;
460 CachedInclude **cached_includes;
461 int nb_cached_includes;
463 char **library_paths;
464 int nb_library_paths;
466 /* array of all loaded dlls (including those referenced by loaded
467 dlls) */
468 DLLReference **loaded_dlls;
469 int nb_loaded_dlls;
471 /* sections */
472 Section **sections;
473 int nb_sections; /* number of sections, including first dummy section */
475 Section **priv_sections;
476 int nb_priv_sections; /* number of private sections */
478 /* got handling */
479 Section *got;
480 Section *plt;
481 unsigned long *got_offsets;
482 int nb_got_offsets;
483 /* give the correspondance from symtab indexes to dynsym indexes */
484 int *symtab_to_dynsym;
486 /* temporary dynamic symbol sections (for dll loading) */
487 Section *dynsymtab_section;
488 /* exported dynamic symbol section */
489 Section *dynsym;
491 int nostdinc; /* if true, no standard headers are added */
492 int nostdlib; /* if true, no standard libraries are added */
494 int nocommon; /* if true, do not use common symbols for .bss data */
496 /* if true, static linking is performed */
497 int static_link;
499 /* soname as specified on the command line (-soname) */
500 const char *soname;
502 /* if true, all symbols are exported */
503 int rdynamic;
505 /* if true, only link in referenced objects from archive */
506 int alacarte_link;
508 /* address of text section */
509 unsigned long text_addr;
510 int has_text_addr;
512 /* output format, see TCC_OUTPUT_FORMAT_xxx */
513 int output_format;
515 /* C language options */
516 int char_is_unsigned;
517 int leading_underscore;
519 /* warning switches */
520 int warn_write_strings;
521 int warn_unsupported;
522 int warn_error;
523 int warn_none;
524 int warn_implicit_function_declaration;
526 /* error handling */
527 void *error_opaque;
528 void (*error_func)(void *opaque, const char *msg);
529 int error_set_jmp_enabled;
530 jmp_buf error_jmp_buf;
531 int nb_errors;
533 /* tiny assembler state */
534 Sym *asm_labels;
536 /* see include_stack_ptr */
537 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
539 /* see ifdef_stack_ptr */
540 int ifdef_stack[IFDEF_STACK_SIZE];
542 /* see cached_includes */
543 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
545 /* pack stack */
546 int pack_stack[PACK_STACK_SIZE];
547 int *pack_stack_ptr;
549 /* output file for preprocessing */
550 FILE *outfile;
552 /* for tcc_relocate */
553 int runtime_added;
555 #ifdef TCC_TARGET_X86_64
556 /* write PLT and GOT here */
557 char *runtime_plt_and_got;
558 unsigned int runtime_plt_and_got_offset;
559 #endif
562 /* The current value can be: */
563 #define VT_VALMASK 0x00ff
564 #define VT_CONST 0x00f0 /* constant in vc
565 (must be first non register value) */
566 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
567 #define VT_LOCAL 0x00f2 /* offset on stack */
568 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
569 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
570 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
571 #define VT_LVAL 0x0100 /* var is an lvalue */
572 #define VT_SYM 0x0200 /* a symbol value is added */
573 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
574 char/short stored in integer registers) */
575 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
576 dereferencing value */
577 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
578 bounding function call point is in vc */
579 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
580 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
581 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
582 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
584 /* types */
585 #define VT_INT 0 /* integer type */
586 #define VT_BYTE 1 /* signed byte type */
587 #define VT_SHORT 2 /* short type */
588 #define VT_VOID 3 /* void type */
589 #define VT_PTR 4 /* pointer */
590 #define VT_ENUM 5 /* enum definition */
591 #define VT_FUNC 6 /* function type */
592 #define VT_STRUCT 7 /* struct/union definition */
593 #define VT_FLOAT 8 /* IEEE float */
594 #define VT_DOUBLE 9 /* IEEE double */
595 #define VT_LDOUBLE 10 /* IEEE long double */
596 #define VT_BOOL 11 /* ISOC99 boolean type */
597 #define VT_LLONG 12 /* 64 bit integer */
598 #define VT_LONG 13 /* long integer (NEVER USED as type, only
599 during parsing) */
600 #define VT_BTYPE 0x000f /* mask for basic type */
601 #define VT_UNSIGNED 0x0010 /* unsigned type */
602 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
603 #define VT_BITFIELD 0x0040 /* bitfield modifier */
604 #define VT_CONSTANT 0x0800 /* const modifier */
605 #define VT_VOLATILE 0x1000 /* volatile modifier */
606 #define VT_SIGNED 0x2000 /* signed type */
608 /* storage */
609 #define VT_EXTERN 0x00000080 /* extern definition */
610 #define VT_STATIC 0x00000100 /* static variable */
611 #define VT_TYPEDEF 0x00000200 /* typedef definition */
612 #define VT_INLINE 0x00000400 /* inline definition */
614 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
616 /* type mask (except storage) */
617 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
618 #define VT_TYPE (~(VT_STORAGE))
620 /* token values */
622 /* warning: the following compare tokens depend on i386 asm code */
623 #define TOK_ULT 0x92
624 #define TOK_UGE 0x93
625 #define TOK_EQ 0x94
626 #define TOK_NE 0x95
627 #define TOK_ULE 0x96
628 #define TOK_UGT 0x97
629 #define TOK_Nset 0x98
630 #define TOK_Nclear 0x99
631 #define TOK_LT 0x9c
632 #define TOK_GE 0x9d
633 #define TOK_LE 0x9e
634 #define TOK_GT 0x9f
636 #define TOK_LAND 0xa0
637 #define TOK_LOR 0xa1
639 #define TOK_DEC 0xa2
640 #define TOK_MID 0xa3 /* inc/dec, to void constant */
641 #define TOK_INC 0xa4
642 #define TOK_UDIV 0xb0 /* unsigned division */
643 #define TOK_UMOD 0xb1 /* unsigned modulo */
644 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
645 #define TOK_CINT 0xb3 /* number in tokc */
646 #define TOK_CCHAR 0xb4 /* char constant in tokc */
647 #define TOK_STR 0xb5 /* pointer to string in tokc */
648 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
649 #define TOK_LCHAR 0xb7
650 #define TOK_LSTR 0xb8
651 #define TOK_CFLOAT 0xb9 /* float constant */
652 #define TOK_LINENUM 0xba /* line number info */
653 #define TOK_CDOUBLE 0xc0 /* double constant */
654 #define TOK_CLDOUBLE 0xc1 /* long double constant */
655 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
656 #define TOK_ADDC1 0xc3 /* add with carry generation */
657 #define TOK_ADDC2 0xc4 /* add with carry use */
658 #define TOK_SUBC1 0xc5 /* add with carry generation */
659 #define TOK_SUBC2 0xc6 /* add with carry use */
660 #define TOK_CUINT 0xc8 /* unsigned int constant */
661 #define TOK_CLLONG 0xc9 /* long long constant */
662 #define TOK_CULLONG 0xca /* unsigned long long constant */
663 #define TOK_ARROW 0xcb
664 #define TOK_DOTS 0xcc /* three dots */
665 #define TOK_SHR 0xcd /* unsigned shift right */
666 #define TOK_PPNUM 0xce /* preprocessor number */
668 #define TOK_SHL 0x01 /* shift left */
669 #define TOK_SAR 0x02 /* signed shift right */
671 /* assignement operators : normal operator or 0x80 */
672 #define TOK_A_MOD 0xa5
673 #define TOK_A_AND 0xa6
674 #define TOK_A_MUL 0xaa
675 #define TOK_A_ADD 0xab
676 #define TOK_A_SUB 0xad
677 #define TOK_A_DIV 0xaf
678 #define TOK_A_XOR 0xde
679 #define TOK_A_OR 0xfc
680 #define TOK_A_SHL 0x81
681 #define TOK_A_SAR 0x82
683 #ifndef offsetof
684 #define offsetof(type, field) ((size_t) &((type *)0)->field)
685 #endif
687 #ifndef countof
688 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
689 #endif
691 /* WARNING: the content of this string encodes token numbers */
692 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";
694 #define TOK_EOF (-1) /* end of file */
695 #define TOK_LINEFEED 10 /* line feed */
697 /* all identificators and strings have token above that */
698 #define TOK_IDENT 256
700 /* only used for i386 asm opcodes definitions */
701 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
703 #define DEF_BWL(x) \
704 DEF(TOK_ASM_ ## x ## b, #x "b") \
705 DEF(TOK_ASM_ ## x ## w, #x "w") \
706 DEF(TOK_ASM_ ## x ## l, #x "l") \
707 DEF(TOK_ASM_ ## x, #x)
709 #define DEF_WL(x) \
710 DEF(TOK_ASM_ ## x ## w, #x "w") \
711 DEF(TOK_ASM_ ## x ## l, #x "l") \
712 DEF(TOK_ASM_ ## x, #x)
714 #define DEF_FP1(x) \
715 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
716 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
717 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
718 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
720 #define DEF_FP(x) \
721 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
722 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
723 DEF_FP1(x)
725 #define DEF_ASMTEST(x) \
726 DEF_ASM(x ## o) \
727 DEF_ASM(x ## no) \
728 DEF_ASM(x ## b) \
729 DEF_ASM(x ## c) \
730 DEF_ASM(x ## nae) \
731 DEF_ASM(x ## nb) \
732 DEF_ASM(x ## nc) \
733 DEF_ASM(x ## ae) \
734 DEF_ASM(x ## e) \
735 DEF_ASM(x ## z) \
736 DEF_ASM(x ## ne) \
737 DEF_ASM(x ## nz) \
738 DEF_ASM(x ## be) \
739 DEF_ASM(x ## na) \
740 DEF_ASM(x ## nbe) \
741 DEF_ASM(x ## a) \
742 DEF_ASM(x ## s) \
743 DEF_ASM(x ## ns) \
744 DEF_ASM(x ## p) \
745 DEF_ASM(x ## pe) \
746 DEF_ASM(x ## np) \
747 DEF_ASM(x ## po) \
748 DEF_ASM(x ## l) \
749 DEF_ASM(x ## nge) \
750 DEF_ASM(x ## nl) \
751 DEF_ASM(x ## ge) \
752 DEF_ASM(x ## le) \
753 DEF_ASM(x ## ng) \
754 DEF_ASM(x ## nle) \
755 DEF_ASM(x ## g)
757 #define TOK_ASM_int TOK_INT
759 enum tcc_token {
760 TOK_LAST = TOK_IDENT - 1,
761 #define DEF(id, str) id,
762 #include "tcctok.h"
763 #undef DEF
766 static const char tcc_keywords[] =
767 #define DEF(id, str) str "\0"
768 #include "tcctok.h"
769 #undef DEF
772 #define TOK_UIDENT TOK_DEFINE
774 #ifdef _WIN32
775 #define snprintf _snprintf
776 #define vsnprintf _vsnprintf
777 #ifndef __GNUC__
778 #define strtold (long double)strtod
779 #define strtof (float)strtod
780 #define strtoll (long long)strtol
781 #endif
782 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
783 || defined(__OpenBSD__)
784 /* currently incorrect */
785 long double strtold(const char *nptr, char **endptr)
787 return (long double)strtod(nptr, endptr);
789 float strtof(const char *nptr, char **endptr)
791 return (float)strtod(nptr, endptr);
793 #else
794 /* XXX: need to define this to use them in non ISOC99 context */
795 extern float strtof (const char *__nptr, char **__endptr);
796 extern long double strtold (const char *__nptr, char **__endptr);
797 #endif
799 static char *pstrcpy(char *buf, int buf_size, const char *s);
800 static char *pstrcat(char *buf, int buf_size, const char *s);
801 static char *tcc_basename(const char *name);
802 static char *tcc_fileextension (const char *p);
804 static void next(void);
805 static void next_nomacro(void);
806 static void next_nomacro_spc(void);
807 static void parse_expr_type(CType *type);
808 static void expr_type(CType *type);
809 static void unary_type(CType *type);
810 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
811 int case_reg, int is_expr);
812 static int expr_const(void);
813 static void expr_eq(void);
814 static void gexpr(void);
815 static void gen_inline_functions(void);
816 static void decl(int l);
817 static void decl_initializer(CType *type, Section *sec, unsigned long c,
818 int first, int size_only);
819 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
820 int has_init, int v, int scope);
821 int gv(int rc);
822 void gv2(int rc1, int rc2);
823 void move_reg(int r, int s);
824 void save_regs(int n);
825 void save_reg(int r);
826 void vpop(void);
827 void vswap(void);
828 void vdup(void);
829 int get_reg(int rc);
830 int get_reg_ex(int rc,int rc2);
832 struct macro_level {
833 struct macro_level *prev;
834 int *p;
837 static void macro_subst(TokenString *tok_str, Sym **nested_list,
838 const int *macro_str, struct macro_level **can_read_stream);
839 void gen_op(int op);
840 void force_charshort_cast(int t);
841 static void gen_cast(CType *type);
842 void vstore(void);
843 static Sym *sym_find(int v);
844 static Sym *sym_push(int v, CType *type, int r, int c);
846 /* type handling */
847 static int type_size(CType *type, int *a);
848 static inline CType *pointed_type(CType *type);
849 static int pointed_size(CType *type);
850 static int lvalue_type(int t);
851 static int parse_btype(CType *type, AttributeDef *ad);
852 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
853 static int compare_types(CType *type1, CType *type2, int unqualified);
854 static int is_compatible_types(CType *type1, CType *type2);
855 static int is_compatible_parameter_types(CType *type1, CType *type2);
857 int ieee_finite(double d);
858 void error(const char *fmt, ...);
859 void vpushi(int v);
860 void vpushll(long long v);
861 void vrott(int n);
862 void vnrott(int n);
863 void lexpand_nr(void);
864 static void vpush_global_sym(CType *type, int v);
865 void vset(CType *type, int r, int v);
866 void type_to_str(char *buf, int buf_size,
867 CType *type, const char *varstr);
868 char *get_tok_str(int v, CValue *cv);
869 static Sym *get_sym_ref(CType *type, Section *sec,
870 unsigned long offset, unsigned long size);
871 static Sym *external_global_sym(int v, CType *type, int r);
873 /* section generation */
874 static void section_realloc(Section *sec, unsigned long new_size);
875 static void *section_ptr_add(Section *sec, unsigned long size);
876 static void put_extern_sym(Sym *sym, Section *section,
877 unsigned long value, unsigned long size);
878 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
879 static int put_elf_str(Section *s, const char *sym);
880 static int put_elf_sym(Section *s,
881 unsigned long value, unsigned long size,
882 int info, int other, int shndx, const char *name);
883 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
884 int info, int other, int sh_num, const char *name);
885 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
886 int type, int symbol);
887 static void put_stabs(const char *str, int type, int other, int desc,
888 unsigned long value);
889 static void put_stabs_r(const char *str, int type, int other, int desc,
890 unsigned long value, Section *sec, int sym_index);
891 static void put_stabn(int type, int other, int desc, int value);
892 static void put_stabd(int type, int other, int desc);
893 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
895 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
896 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
897 #define AFF_PREPROCESS 0x0004 /* preprocess file */
898 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
900 /* tcccoff.c */
901 int tcc_output_coff(TCCState *s1, FILE *f);
903 /* tccpe.c */
904 void *resolve_sym(TCCState *s1, const char *sym, int type);
905 int pe_load_def_file(struct TCCState *s1, int fd);
906 int pe_test_res_file(void *v, int size);
907 int pe_load_res_file(struct TCCState *s1, int fd);
908 void pe_add_runtime(struct TCCState *s1);
909 void pe_guess_outfile(char *objfilename, int output_type);
910 int pe_output_file(struct TCCState *s1, const char *filename);
912 /* tccasm.c */
914 #ifdef CONFIG_TCC_ASM
916 typedef struct ExprValue {
917 uint32_t v;
918 Sym *sym;
919 } ExprValue;
921 #define MAX_ASM_OPERANDS 30
923 typedef struct ASMOperand {
924 int id; /* GCC 3 optionnal identifier (0 if number only supported */
925 char *constraint;
926 char asm_str[16]; /* computed asm string for operand */
927 SValue *vt; /* C value of the expression */
928 int ref_index; /* if >= 0, gives reference to a output constraint */
929 int input_index; /* if >= 0, gives reference to an input constraint */
930 int priority; /* priority, used to assign registers */
931 int reg; /* if >= 0, register number used for this operand */
932 int is_llong; /* true if double register value */
933 int is_memory; /* true if memory operand */
934 int is_rw; /* for '+' modifier */
935 } ASMOperand;
937 static void asm_expr(TCCState *s1, ExprValue *pe);
938 static int asm_int_expr(TCCState *s1);
939 static int find_constraint(ASMOperand *operands, int nb_operands,
940 const char *name, const char **pp);
942 static int tcc_assemble(TCCState *s1, int do_preprocess);
944 #endif
946 static void asm_instr(void);
947 static void asm_global_instr(void);
949 /* true if float/double/long double type */
950 static inline int is_float(int t)
952 int bt;
953 bt = t & VT_BTYPE;
954 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
957 #ifdef TCC_TARGET_I386
958 #include "i386-gen.c"
959 #endif
961 #ifdef TCC_TARGET_ARM
962 #include "arm-gen.c"
963 #endif
965 #ifdef TCC_TARGET_C67
966 #include "c67-gen.c"
967 #endif
969 #ifdef TCC_TARGET_X86_64
970 #include "x86_64-gen.c"
971 #endif
973 #ifdef CONFIG_TCC_STATIC
975 #define RTLD_LAZY 0x001
976 #define RTLD_NOW 0x002
977 #define RTLD_GLOBAL 0x100
978 #define RTLD_DEFAULT NULL
980 /* dummy function for profiling */
981 void *dlopen(const char *filename, int flag)
983 return NULL;
986 void dlclose(void *p)
990 const char *dlerror(void)
992 return "error";
995 typedef struct TCCSyms {
996 char *str;
997 void *ptr;
998 } TCCSyms;
1000 #define TCCSYM(a) { #a, &a, },
1002 /* add the symbol you want here if no dynamic linking is done */
1003 static TCCSyms tcc_syms[] = {
1004 #if !defined(CONFIG_TCCBOOT)
1005 TCCSYM(printf)
1006 TCCSYM(fprintf)
1007 TCCSYM(fopen)
1008 TCCSYM(fclose)
1009 #endif
1010 { NULL, NULL },
1013 void *resolve_sym(TCCState *s1, const char *symbol, int type)
1015 TCCSyms *p;
1016 p = tcc_syms;
1017 while (p->str != NULL) {
1018 if (!strcmp(p->str, symbol))
1019 return p->ptr;
1020 p++;
1022 return NULL;
1025 #elif !defined(_WIN32)
1027 #include <dlfcn.h>
1029 void *resolve_sym(TCCState *s1, const char *sym, int type)
1031 return dlsym(RTLD_DEFAULT, sym);
1034 #endif
1036 /********************************************************/
1038 /* we use our own 'finite' function to avoid potential problems with
1039 non standard math libs */
1040 /* XXX: endianness dependent */
1041 int ieee_finite(double d)
1043 int *p = (int *)&d;
1044 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
1047 /* copy a string and truncate it. */
1048 static char *pstrcpy(char *buf, int buf_size, const char *s)
1050 char *q, *q_end;
1051 int c;
1053 if (buf_size > 0) {
1054 q = buf;
1055 q_end = buf + buf_size - 1;
1056 while (q < q_end) {
1057 c = *s++;
1058 if (c == '\0')
1059 break;
1060 *q++ = c;
1062 *q = '\0';
1064 return buf;
1067 /* strcat and truncate. */
1068 static char *pstrcat(char *buf, int buf_size, const char *s)
1070 int len;
1071 len = strlen(buf);
1072 if (len < buf_size)
1073 pstrcpy(buf + len, buf_size - len, s);
1074 return buf;
1077 #ifndef LIBTCC
1078 static int strstart(const char *str, const char *val, const char **ptr)
1080 const char *p, *q;
1081 p = str;
1082 q = val;
1083 while (*q != '\0') {
1084 if (*p != *q)
1085 return 0;
1086 p++;
1087 q++;
1089 if (ptr)
1090 *ptr = p;
1091 return 1;
1093 #endif
1095 #ifdef _WIN32
1096 #define IS_PATHSEP(c) (c == '/' || c == '\\')
1097 #define IS_ABSPATH(p) (IS_PATHSEP(p[0]) || (p[0] && p[1] == ':' && IS_PATHSEP(p[2])))
1098 #define PATHCMP stricmp
1099 #else
1100 #define IS_PATHSEP(c) (c == '/')
1101 #define IS_ABSPATH(p) IS_PATHSEP(p[0])
1102 #define PATHCMP strcmp
1103 #endif
1105 /* extract the basename of a file */
1106 static char *tcc_basename(const char *name)
1108 char *p = strchr(name, 0);
1109 while (p > name && !IS_PATHSEP(p[-1]))
1110 --p;
1111 return p;
1114 static char *tcc_fileextension (const char *name)
1116 char *b = tcc_basename(name);
1117 char *e = strrchr(b, '.');
1118 return e ? e : strchr(b, 0);
1121 #ifdef _WIN32
1122 char *normalize_slashes(char *path)
1124 char *p;
1125 for (p = path; *p; ++p)
1126 if (*p == '\\')
1127 *p = '/';
1128 return path;
1131 void tcc_set_lib_path_w32(TCCState *s)
1133 /* on win32, we suppose the lib and includes are at the location
1134 of 'tcc.exe' */
1135 char path[1024], *p;
1136 GetModuleFileNameA(NULL, path, sizeof path);
1137 p = tcc_basename(normalize_slashes(strlwr(path)));
1138 if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
1139 p -= 5;
1140 else if (p > path)
1141 p--;
1142 *p = 0;
1143 tcc_set_lib_path(s, path);
1145 #endif
1147 void set_pages_executable(void *ptr, unsigned long length)
1149 #ifdef _WIN32
1150 unsigned long old_protect;
1151 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
1152 #else
1153 unsigned long start, end;
1154 start = (unsigned long)ptr & ~(PAGESIZE - 1);
1155 end = (unsigned long)ptr + length;
1156 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
1157 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
1158 #endif
1161 /* memory management */
1162 #ifdef MEM_DEBUG
1163 int mem_cur_size;
1164 int mem_max_size;
1165 unsigned malloc_usable_size(void*);
1166 #endif
1168 static inline void tcc_free(void *ptr)
1170 #ifdef MEM_DEBUG
1171 mem_cur_size -= malloc_usable_size(ptr);
1172 #endif
1173 free(ptr);
1176 static void *tcc_malloc(unsigned long size)
1178 void *ptr;
1179 ptr = malloc(size);
1180 if (!ptr && size)
1181 error("memory full");
1182 #ifdef MEM_DEBUG
1183 mem_cur_size += malloc_usable_size(ptr);
1184 if (mem_cur_size > mem_max_size)
1185 mem_max_size = mem_cur_size;
1186 #endif
1187 return ptr;
1190 static void *tcc_mallocz(unsigned long size)
1192 void *ptr;
1193 ptr = tcc_malloc(size);
1194 memset(ptr, 0, size);
1195 return ptr;
1198 static inline void *tcc_realloc(void *ptr, unsigned long size)
1200 void *ptr1;
1201 #ifdef MEM_DEBUG
1202 mem_cur_size -= malloc_usable_size(ptr);
1203 #endif
1204 ptr1 = realloc(ptr, size);
1205 #ifdef MEM_DEBUG
1206 /* NOTE: count not correct if alloc error, but not critical */
1207 mem_cur_size += malloc_usable_size(ptr1);
1208 if (mem_cur_size > mem_max_size)
1209 mem_max_size = mem_cur_size;
1210 #endif
1211 return ptr1;
1214 static char *tcc_strdup(const char *str)
1216 char *ptr;
1217 ptr = tcc_malloc(strlen(str) + 1);
1218 strcpy(ptr, str);
1219 return ptr;
1222 #define free(p) use_tcc_free(p)
1223 #define malloc(s) use_tcc_malloc(s)
1224 #define realloc(p, s) use_tcc_realloc(p, s)
1226 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1228 int nb, nb_alloc;
1229 void **pp;
1231 nb = *nb_ptr;
1232 pp = *ptab;
1233 /* every power of two we double array size */
1234 if ((nb & (nb - 1)) == 0) {
1235 if (!nb)
1236 nb_alloc = 1;
1237 else
1238 nb_alloc = nb * 2;
1239 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1240 if (!pp)
1241 error("memory full");
1242 *ptab = pp;
1244 pp[nb++] = data;
1245 *nb_ptr = nb;
1248 static void dynarray_reset(void *pp, int *n)
1250 void **p;
1251 for (p = *(void***)pp; *n; ++p, --*n)
1252 if (*p)
1253 tcc_free(*p);
1254 tcc_free(*(void**)pp);
1255 *(void**)pp = NULL;
1258 /* symbol allocator */
1259 static Sym *__sym_malloc(void)
1261 Sym *sym_pool, *sym, *last_sym;
1262 int i;
1264 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1265 dynarray_add(&sym_pools, &nb_sym_pools, sym_pool);
1267 last_sym = sym_free_first;
1268 sym = sym_pool;
1269 for(i = 0; i < SYM_POOL_NB; i++) {
1270 sym->next = last_sym;
1271 last_sym = sym;
1272 sym++;
1274 sym_free_first = last_sym;
1275 return last_sym;
1278 static inline Sym *sym_malloc(void)
1280 Sym *sym;
1281 sym = sym_free_first;
1282 if (!sym)
1283 sym = __sym_malloc();
1284 sym_free_first = sym->next;
1285 return sym;
1288 static inline void sym_free(Sym *sym)
1290 sym->next = sym_free_first;
1291 sym_free_first = sym;
1294 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1296 Section *sec;
1298 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1299 strcpy(sec->name, name);
1300 sec->sh_type = sh_type;
1301 sec->sh_flags = sh_flags;
1302 switch(sh_type) {
1303 case SHT_HASH:
1304 case SHT_REL:
1305 case SHT_RELA:
1306 case SHT_DYNSYM:
1307 case SHT_SYMTAB:
1308 case SHT_DYNAMIC:
1309 sec->sh_addralign = 4;
1310 break;
1311 case SHT_STRTAB:
1312 sec->sh_addralign = 1;
1313 break;
1314 default:
1315 sec->sh_addralign = 32; /* default conservative alignment */
1316 break;
1319 if (sh_flags & SHF_PRIVATE) {
1320 dynarray_add((void ***)&s1->priv_sections, &s1->nb_priv_sections, sec);
1321 } else {
1322 sec->sh_num = s1->nb_sections;
1323 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1326 return sec;
1329 static void free_section(Section *s)
1331 tcc_free(s->data);
1334 /* realloc section and set its content to zero */
1335 static void section_realloc(Section *sec, unsigned long new_size)
1337 unsigned long size;
1338 unsigned char *data;
1340 size = sec->data_allocated;
1341 if (size == 0)
1342 size = 1;
1343 while (size < new_size)
1344 size = size * 2;
1345 data = tcc_realloc(sec->data, size);
1346 if (!data)
1347 error("memory full");
1348 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1349 sec->data = data;
1350 sec->data_allocated = size;
1353 /* reserve at least 'size' bytes in section 'sec' from
1354 sec->data_offset. */
1355 static void *section_ptr_add(Section *sec, unsigned long size)
1357 unsigned long offset, offset1;
1359 offset = sec->data_offset;
1360 offset1 = offset + size;
1361 if (offset1 > sec->data_allocated)
1362 section_realloc(sec, offset1);
1363 sec->data_offset = offset1;
1364 return sec->data + offset;
1367 /* return a reference to a section, and create it if it does not
1368 exists */
1369 Section *find_section(TCCState *s1, const char *name)
1371 Section *sec;
1372 int i;
1373 for(i = 1; i < s1->nb_sections; i++) {
1374 sec = s1->sections[i];
1375 if (!strcmp(name, sec->name))
1376 return sec;
1378 /* sections are created as PROGBITS */
1379 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1382 #define SECTION_ABS ((void *)1)
1384 /* update sym->c so that it points to an external symbol in section
1385 'section' with value 'value' */
1386 static void put_extern_sym2(Sym *sym, Section *section,
1387 unsigned long value, unsigned long size,
1388 int can_add_underscore)
1390 int sym_type, sym_bind, sh_num, info, other, attr;
1391 ElfW(Sym) *esym;
1392 const char *name;
1393 char buf1[256];
1395 if (section == NULL)
1396 sh_num = SHN_UNDEF;
1397 else if (section == SECTION_ABS)
1398 sh_num = SHN_ABS;
1399 else
1400 sh_num = section->sh_num;
1402 other = attr = 0;
1404 if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
1405 sym_type = STT_FUNC;
1406 #ifdef TCC_TARGET_PE
1407 if (sym->type.ref)
1408 attr = sym->type.ref->r;
1409 if (FUNC_EXPORT(attr))
1410 other |= 1;
1411 if (FUNC_CALL(attr) == FUNC_STDCALL)
1412 other |= 2;
1413 #endif
1414 } else {
1415 sym_type = STT_OBJECT;
1418 if (sym->type.t & VT_STATIC)
1419 sym_bind = STB_LOCAL;
1420 else
1421 sym_bind = STB_GLOBAL;
1423 if (!sym->c) {
1424 name = get_tok_str(sym->v, NULL);
1425 #ifdef CONFIG_TCC_BCHECK
1426 if (do_bounds_check) {
1427 char buf[32];
1429 /* XXX: avoid doing that for statics ? */
1430 /* if bound checking is activated, we change some function
1431 names by adding the "__bound" prefix */
1432 switch(sym->v) {
1433 #if 0
1434 /* XXX: we rely only on malloc hooks */
1435 case TOK_malloc:
1436 case TOK_free:
1437 case TOK_realloc:
1438 case TOK_memalign:
1439 case TOK_calloc:
1440 #endif
1441 case TOK_memcpy:
1442 case TOK_memmove:
1443 case TOK_memset:
1444 case TOK_strlen:
1445 case TOK_strcpy:
1446 case TOK__alloca:
1447 strcpy(buf, "__bound_");
1448 strcat(buf, name);
1449 name = buf;
1450 break;
1453 #endif
1455 #ifdef TCC_TARGET_PE
1456 if ((other & 2) && can_add_underscore) {
1457 sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
1458 name = buf1;
1459 } else
1460 #endif
1461 if (tcc_state->leading_underscore && can_add_underscore) {
1462 buf1[0] = '_';
1463 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1464 name = buf1;
1466 info = ELFW(ST_INFO)(sym_bind, sym_type);
1467 sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
1468 } else {
1469 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
1470 esym->st_value = value;
1471 esym->st_size = size;
1472 esym->st_shndx = sh_num;
1473 esym->st_other |= other;
1477 static void put_extern_sym(Sym *sym, Section *section,
1478 unsigned long value, unsigned long size)
1480 put_extern_sym2(sym, section, value, size, 1);
1483 /* add a new relocation entry to symbol 'sym' in section 's' */
1484 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1486 if (!sym->c)
1487 put_extern_sym(sym, NULL, 0, 0);
1488 /* now we can add ELF relocation info */
1489 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1492 static inline int isid(int c)
1494 return (c >= 'a' && c <= 'z') ||
1495 (c >= 'A' && c <= 'Z') ||
1496 c == '_';
1499 static inline int isnum(int c)
1501 return c >= '0' && c <= '9';
1504 static inline int isoct(int c)
1506 return c >= '0' && c <= '7';
1509 static inline int toup(int c)
1511 if (c >= 'a' && c <= 'z')
1512 return c - 'a' + 'A';
1513 else
1514 return c;
1517 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1519 int len;
1520 len = strlen(buf);
1521 vsnprintf(buf + len, buf_size - len, fmt, ap);
1524 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1526 va_list ap;
1527 va_start(ap, fmt);
1528 strcat_vprintf(buf, buf_size, fmt, ap);
1529 va_end(ap);
1532 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1534 char buf[2048];
1535 BufferedFile **f;
1537 buf[0] = '\0';
1538 if (file) {
1539 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1540 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1541 (*f)->filename, (*f)->line_num);
1542 if (file->line_num > 0) {
1543 strcat_printf(buf, sizeof(buf),
1544 "%s:%d: ", file->filename, file->line_num);
1545 } else {
1546 strcat_printf(buf, sizeof(buf),
1547 "%s: ", file->filename);
1549 } else {
1550 strcat_printf(buf, sizeof(buf),
1551 "tcc: ");
1553 if (is_warning)
1554 strcat_printf(buf, sizeof(buf), "warning: ");
1555 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1557 if (!s1->error_func) {
1558 /* default case: stderr */
1559 fprintf(stderr, "%s\n", buf);
1560 } else {
1561 s1->error_func(s1->error_opaque, buf);
1563 if (!is_warning || s1->warn_error)
1564 s1->nb_errors++;
1567 #ifdef LIBTCC
1568 void tcc_set_error_func(TCCState *s, void *error_opaque,
1569 void (*error_func)(void *opaque, const char *msg))
1571 s->error_opaque = error_opaque;
1572 s->error_func = error_func;
1574 #endif
1576 /* error without aborting current compilation */
1577 void error_noabort(const char *fmt, ...)
1579 TCCState *s1 = tcc_state;
1580 va_list ap;
1582 va_start(ap, fmt);
1583 error1(s1, 0, fmt, ap);
1584 va_end(ap);
1587 void error(const char *fmt, ...)
1589 TCCState *s1 = tcc_state;
1590 va_list ap;
1592 va_start(ap, fmt);
1593 error1(s1, 0, fmt, ap);
1594 va_end(ap);
1595 /* better than nothing: in some cases, we accept to handle errors */
1596 if (s1->error_set_jmp_enabled) {
1597 longjmp(s1->error_jmp_buf, 1);
1598 } else {
1599 /* XXX: eliminate this someday */
1600 exit(1);
1604 void expect(const char *msg)
1606 error("%s expected", msg);
1609 void warning(const char *fmt, ...)
1611 TCCState *s1 = tcc_state;
1612 va_list ap;
1614 if (s1->warn_none)
1615 return;
1617 va_start(ap, fmt);
1618 error1(s1, 1, fmt, ap);
1619 va_end(ap);
1622 void skip(int c)
1624 if (tok != c)
1625 error("'%c' expected", c);
1626 next();
1629 static void test_lvalue(void)
1631 if (!(vtop->r & VT_LVAL))
1632 expect("lvalue");
1635 /* allocate a new token */
1636 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1638 TokenSym *ts, **ptable;
1639 int i;
1641 if (tok_ident >= SYM_FIRST_ANOM)
1642 error("memory full");
1644 /* expand token table if needed */
1645 i = tok_ident - TOK_IDENT;
1646 if ((i % TOK_ALLOC_INCR) == 0) {
1647 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1648 if (!ptable)
1649 error("memory full");
1650 table_ident = ptable;
1653 ts = tcc_malloc(sizeof(TokenSym) + len);
1654 table_ident[i] = ts;
1655 ts->tok = tok_ident++;
1656 ts->sym_define = NULL;
1657 ts->sym_label = NULL;
1658 ts->sym_struct = NULL;
1659 ts->sym_identifier = NULL;
1660 ts->len = len;
1661 ts->hash_next = NULL;
1662 memcpy(ts->str, str, len);
1663 ts->str[len] = '\0';
1664 *pts = ts;
1665 return ts;
1668 #define TOK_HASH_INIT 1
1669 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1671 /* find a token and add it if not found */
1672 static TokenSym *tok_alloc(const char *str, int len)
1674 TokenSym *ts, **pts;
1675 int i;
1676 unsigned int h;
1678 h = TOK_HASH_INIT;
1679 for(i=0;i<len;i++)
1680 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1681 h &= (TOK_HASH_SIZE - 1);
1683 pts = &hash_ident[h];
1684 for(;;) {
1685 ts = *pts;
1686 if (!ts)
1687 break;
1688 if (ts->len == len && !memcmp(ts->str, str, len))
1689 return ts;
1690 pts = &(ts->hash_next);
1692 return tok_alloc_new(pts, str, len);
1695 /* CString handling */
1697 static void cstr_realloc(CString *cstr, int new_size)
1699 int size;
1700 void *data;
1702 size = cstr->size_allocated;
1703 if (size == 0)
1704 size = 8; /* no need to allocate a too small first string */
1705 while (size < new_size)
1706 size = size * 2;
1707 data = tcc_realloc(cstr->data_allocated, size);
1708 if (!data)
1709 error("memory full");
1710 cstr->data_allocated = data;
1711 cstr->size_allocated = size;
1712 cstr->data = data;
1715 /* add a byte */
1716 static inline void cstr_ccat(CString *cstr, int ch)
1718 int size;
1719 size = cstr->size + 1;
1720 if (size > cstr->size_allocated)
1721 cstr_realloc(cstr, size);
1722 ((unsigned char *)cstr->data)[size - 1] = ch;
1723 cstr->size = size;
1726 static void cstr_cat(CString *cstr, const char *str)
1728 int c;
1729 for(;;) {
1730 c = *str;
1731 if (c == '\0')
1732 break;
1733 cstr_ccat(cstr, c);
1734 str++;
1738 /* add a wide char */
1739 static void cstr_wccat(CString *cstr, int ch)
1741 int size;
1742 size = cstr->size + sizeof(nwchar_t);
1743 if (size > cstr->size_allocated)
1744 cstr_realloc(cstr, size);
1745 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1746 cstr->size = size;
1749 static void cstr_new(CString *cstr)
1751 memset(cstr, 0, sizeof(CString));
1754 /* free string and reset it to NULL */
1755 static void cstr_free(CString *cstr)
1757 tcc_free(cstr->data_allocated);
1758 cstr_new(cstr);
1761 #define cstr_reset(cstr) cstr_free(cstr)
1763 /* XXX: unicode ? */
1764 static void add_char(CString *cstr, int c)
1766 if (c == '\'' || c == '\"' || c == '\\') {
1767 /* XXX: could be more precise if char or string */
1768 cstr_ccat(cstr, '\\');
1770 if (c >= 32 && c <= 126) {
1771 cstr_ccat(cstr, c);
1772 } else {
1773 cstr_ccat(cstr, '\\');
1774 if (c == '\n') {
1775 cstr_ccat(cstr, 'n');
1776 } else {
1777 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1778 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1779 cstr_ccat(cstr, '0' + (c & 7));
1784 /* XXX: buffer overflow */
1785 /* XXX: float tokens */
1786 char *get_tok_str(int v, CValue *cv)
1788 static char buf[STRING_MAX_SIZE + 1];
1789 static CString cstr_buf;
1790 CString *cstr;
1791 unsigned char *q;
1792 char *p;
1793 int i, len;
1795 /* NOTE: to go faster, we give a fixed buffer for small strings */
1796 cstr_reset(&cstr_buf);
1797 cstr_buf.data = buf;
1798 cstr_buf.size_allocated = sizeof(buf);
1799 p = buf;
1801 switch(v) {
1802 case TOK_CINT:
1803 case TOK_CUINT:
1804 /* XXX: not quite exact, but only useful for testing */
1805 sprintf(p, "%u", cv->ui);
1806 break;
1807 case TOK_CLLONG:
1808 case TOK_CULLONG:
1809 /* XXX: not quite exact, but only useful for testing */
1810 sprintf(p, "%Lu", cv->ull);
1811 break;
1812 case TOK_LCHAR:
1813 cstr_ccat(&cstr_buf, 'L');
1814 case TOK_CCHAR:
1815 cstr_ccat(&cstr_buf, '\'');
1816 add_char(&cstr_buf, cv->i);
1817 cstr_ccat(&cstr_buf, '\'');
1818 cstr_ccat(&cstr_buf, '\0');
1819 break;
1820 case TOK_PPNUM:
1821 cstr = cv->cstr;
1822 len = cstr->size - 1;
1823 for(i=0;i<len;i++)
1824 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1825 cstr_ccat(&cstr_buf, '\0');
1826 break;
1827 case TOK_LSTR:
1828 cstr_ccat(&cstr_buf, 'L');
1829 case TOK_STR:
1830 cstr = cv->cstr;
1831 cstr_ccat(&cstr_buf, '\"');
1832 if (v == TOK_STR) {
1833 len = cstr->size - 1;
1834 for(i=0;i<len;i++)
1835 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1836 } else {
1837 len = (cstr->size / sizeof(nwchar_t)) - 1;
1838 for(i=0;i<len;i++)
1839 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1841 cstr_ccat(&cstr_buf, '\"');
1842 cstr_ccat(&cstr_buf, '\0');
1843 break;
1844 case TOK_LT:
1845 v = '<';
1846 goto addv;
1847 case TOK_GT:
1848 v = '>';
1849 goto addv;
1850 case TOK_DOTS:
1851 return strcpy(p, "...");
1852 case TOK_A_SHL:
1853 return strcpy(p, "<<=");
1854 case TOK_A_SAR:
1855 return strcpy(p, ">>=");
1856 default:
1857 if (v < TOK_IDENT) {
1858 /* search in two bytes table */
1859 q = tok_two_chars;
1860 while (*q) {
1861 if (q[2] == v) {
1862 *p++ = q[0];
1863 *p++ = q[1];
1864 *p = '\0';
1865 return buf;
1867 q += 3;
1869 addv:
1870 *p++ = v;
1871 *p = '\0';
1872 } else if (v < tok_ident) {
1873 return table_ident[v - TOK_IDENT]->str;
1874 } else if (v >= SYM_FIRST_ANOM) {
1875 /* special name for anonymous symbol */
1876 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1877 } else {
1878 /* should never happen */
1879 return NULL;
1881 break;
1883 return cstr_buf.data;
1886 /* push, without hashing */
1887 static Sym *sym_push2(Sym **ps, int v, int t, long c)
1889 Sym *s;
1890 s = sym_malloc();
1891 s->v = v;
1892 s->type.t = t;
1893 s->c = c;
1894 s->next = NULL;
1895 /* add in stack */
1896 s->prev = *ps;
1897 *ps = s;
1898 return s;
1901 /* find a symbol and return its associated structure. 's' is the top
1902 of the symbol stack */
1903 static Sym *sym_find2(Sym *s, int v)
1905 while (s) {
1906 if (s->v == v)
1907 return s;
1908 s = s->prev;
1910 return NULL;
1913 /* structure lookup */
1914 static inline Sym *struct_find(int v)
1916 v -= TOK_IDENT;
1917 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1918 return NULL;
1919 return table_ident[v]->sym_struct;
1922 /* find an identifier */
1923 static inline Sym *sym_find(int v)
1925 v -= TOK_IDENT;
1926 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1927 return NULL;
1928 return table_ident[v]->sym_identifier;
1931 /* push a given symbol on the symbol stack */
1932 static Sym *sym_push(int v, CType *type, int r, int c)
1934 Sym *s, **ps;
1935 TokenSym *ts;
1937 if (local_stack)
1938 ps = &local_stack;
1939 else
1940 ps = &global_stack;
1941 s = sym_push2(ps, v, type->t, c);
1942 s->type.ref = type->ref;
1943 s->r = r;
1944 /* don't record fields or anonymous symbols */
1945 /* XXX: simplify */
1946 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1947 /* record symbol in token array */
1948 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1949 if (v & SYM_STRUCT)
1950 ps = &ts->sym_struct;
1951 else
1952 ps = &ts->sym_identifier;
1953 s->prev_tok = *ps;
1954 *ps = s;
1956 return s;
1959 /* push a global identifier */
1960 static Sym *global_identifier_push(int v, int t, int c)
1962 Sym *s, **ps;
1963 s = sym_push2(&global_stack, v, t, c);
1964 /* don't record anonymous symbol */
1965 if (v < SYM_FIRST_ANOM) {
1966 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1967 /* modify the top most local identifier, so that
1968 sym_identifier will point to 's' when popped */
1969 while (*ps != NULL)
1970 ps = &(*ps)->prev_tok;
1971 s->prev_tok = NULL;
1972 *ps = s;
1974 return s;
1977 /* pop symbols until top reaches 'b' */
1978 static void sym_pop(Sym **ptop, Sym *b)
1980 Sym *s, *ss, **ps;
1981 TokenSym *ts;
1982 int v;
1984 s = *ptop;
1985 while(s != b) {
1986 ss = s->prev;
1987 v = s->v;
1988 /* remove symbol in token array */
1989 /* XXX: simplify */
1990 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1991 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1992 if (v & SYM_STRUCT)
1993 ps = &ts->sym_struct;
1994 else
1995 ps = &ts->sym_identifier;
1996 *ps = s->prev_tok;
1998 sym_free(s);
1999 s = ss;
2001 *ptop = b;
2004 /* I/O layer */
2006 BufferedFile *tcc_open(TCCState *s1, const char *filename)
2008 int fd;
2009 BufferedFile *bf;
2011 if (strcmp(filename, "-") == 0)
2012 fd = 0, filename = "stdin";
2013 else
2014 fd = open(filename, O_RDONLY | O_BINARY);
2015 if ((verbose == 2 && fd >= 0) || verbose == 3)
2016 printf("%s %*s%s\n", fd < 0 ? "nf":"->",
2017 (s1->include_stack_ptr - s1->include_stack), "", filename);
2018 if (fd < 0)
2019 return NULL;
2020 bf = tcc_malloc(sizeof(BufferedFile));
2021 bf->fd = fd;
2022 bf->buf_ptr = bf->buffer;
2023 bf->buf_end = bf->buffer;
2024 bf->buffer[0] = CH_EOB; /* put eob symbol */
2025 pstrcpy(bf->filename, sizeof(bf->filename), filename);
2026 #ifdef _WIN32
2027 normalize_slashes(bf->filename);
2028 #endif
2029 bf->line_num = 1;
2030 bf->ifndef_macro = 0;
2031 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
2032 // printf("opening '%s'\n", filename);
2033 return bf;
2036 void tcc_close(BufferedFile *bf)
2038 total_lines += bf->line_num;
2039 close(bf->fd);
2040 tcc_free(bf);
2043 /* fill input buffer and peek next char */
2044 static int tcc_peekc_slow(BufferedFile *bf)
2046 int len;
2047 /* only tries to read if really end of buffer */
2048 if (bf->buf_ptr >= bf->buf_end) {
2049 if (bf->fd != -1) {
2050 #if defined(PARSE_DEBUG)
2051 len = 8;
2052 #else
2053 len = IO_BUF_SIZE;
2054 #endif
2055 len = read(bf->fd, bf->buffer, len);
2056 if (len < 0)
2057 len = 0;
2058 } else {
2059 len = 0;
2061 total_bytes += len;
2062 bf->buf_ptr = bf->buffer;
2063 bf->buf_end = bf->buffer + len;
2064 *bf->buf_end = CH_EOB;
2066 if (bf->buf_ptr < bf->buf_end) {
2067 return bf->buf_ptr[0];
2068 } else {
2069 bf->buf_ptr = bf->buf_end;
2070 return CH_EOF;
2074 /* return the current character, handling end of block if necessary
2075 (but not stray) */
2076 static int handle_eob(void)
2078 return tcc_peekc_slow(file);
2081 /* read next char from current input file and handle end of input buffer */
2082 static inline void inp(void)
2084 ch = *(++(file->buf_ptr));
2085 /* end of buffer/file handling */
2086 if (ch == CH_EOB)
2087 ch = handle_eob();
2090 /* handle '\[\r]\n' */
2091 static int handle_stray_noerror(void)
2093 while (ch == '\\') {
2094 inp();
2095 if (ch == '\n') {
2096 file->line_num++;
2097 inp();
2098 } else if (ch == '\r') {
2099 inp();
2100 if (ch != '\n')
2101 goto fail;
2102 file->line_num++;
2103 inp();
2104 } else {
2105 fail:
2106 return 1;
2109 return 0;
2112 static void handle_stray(void)
2114 if (handle_stray_noerror())
2115 error("stray '\\' in program");
2118 /* skip the stray and handle the \\n case. Output an error if
2119 incorrect char after the stray */
2120 static int handle_stray1(uint8_t *p)
2122 int c;
2124 if (p >= file->buf_end) {
2125 file->buf_ptr = p;
2126 c = handle_eob();
2127 p = file->buf_ptr;
2128 if (c == '\\')
2129 goto parse_stray;
2130 } else {
2131 parse_stray:
2132 file->buf_ptr = p;
2133 ch = *p;
2134 handle_stray();
2135 p = file->buf_ptr;
2136 c = *p;
2138 return c;
2141 /* handle just the EOB case, but not stray */
2142 #define PEEKC_EOB(c, p)\
2144 p++;\
2145 c = *p;\
2146 if (c == '\\') {\
2147 file->buf_ptr = p;\
2148 c = handle_eob();\
2149 p = file->buf_ptr;\
2153 /* handle the complicated stray case */
2154 #define PEEKC(c, p)\
2156 p++;\
2157 c = *p;\
2158 if (c == '\\') {\
2159 c = handle_stray1(p);\
2160 p = file->buf_ptr;\
2164 /* input with '\[\r]\n' handling. Note that this function cannot
2165 handle other characters after '\', so you cannot call it inside
2166 strings or comments */
2167 static void minp(void)
2169 inp();
2170 if (ch == '\\')
2171 handle_stray();
2175 /* single line C++ comments */
2176 static uint8_t *parse_line_comment(uint8_t *p)
2178 int c;
2180 p++;
2181 for(;;) {
2182 c = *p;
2183 redo:
2184 if (c == '\n' || c == CH_EOF) {
2185 break;
2186 } else if (c == '\\') {
2187 file->buf_ptr = p;
2188 c = handle_eob();
2189 p = file->buf_ptr;
2190 if (c == '\\') {
2191 PEEKC_EOB(c, p);
2192 if (c == '\n') {
2193 file->line_num++;
2194 PEEKC_EOB(c, p);
2195 } else if (c == '\r') {
2196 PEEKC_EOB(c, p);
2197 if (c == '\n') {
2198 file->line_num++;
2199 PEEKC_EOB(c, p);
2202 } else {
2203 goto redo;
2205 } else {
2206 p++;
2209 return p;
2212 /* C comments */
2213 static uint8_t *parse_comment(uint8_t *p)
2215 int c;
2217 p++;
2218 for(;;) {
2219 /* fast skip loop */
2220 for(;;) {
2221 c = *p;
2222 if (c == '\n' || c == '*' || c == '\\')
2223 break;
2224 p++;
2225 c = *p;
2226 if (c == '\n' || c == '*' || c == '\\')
2227 break;
2228 p++;
2230 /* now we can handle all the cases */
2231 if (c == '\n') {
2232 file->line_num++;
2233 p++;
2234 } else if (c == '*') {
2235 p++;
2236 for(;;) {
2237 c = *p;
2238 if (c == '*') {
2239 p++;
2240 } else if (c == '/') {
2241 goto end_of_comment;
2242 } else if (c == '\\') {
2243 file->buf_ptr = p;
2244 c = handle_eob();
2245 p = file->buf_ptr;
2246 if (c == '\\') {
2247 /* skip '\[\r]\n', otherwise just skip the stray */
2248 while (c == '\\') {
2249 PEEKC_EOB(c, p);
2250 if (c == '\n') {
2251 file->line_num++;
2252 PEEKC_EOB(c, p);
2253 } else if (c == '\r') {
2254 PEEKC_EOB(c, p);
2255 if (c == '\n') {
2256 file->line_num++;
2257 PEEKC_EOB(c, p);
2259 } else {
2260 goto after_star;
2264 } else {
2265 break;
2268 after_star: ;
2269 } else {
2270 /* stray, eob or eof */
2271 file->buf_ptr = p;
2272 c = handle_eob();
2273 p = file->buf_ptr;
2274 if (c == CH_EOF) {
2275 error("unexpected end of file in comment");
2276 } else if (c == '\\') {
2277 p++;
2281 end_of_comment:
2282 p++;
2283 return p;
2286 #define cinp minp
2288 /* space exlcuding newline */
2289 static inline int is_space(int ch)
2291 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2294 static inline void skip_spaces(void)
2296 while (is_space(ch))
2297 cinp();
2300 static inline int check_space(int t, int *spc)
2302 if (is_space(t)) {
2303 if (*spc)
2304 return 1;
2305 *spc = 1;
2306 } else
2307 *spc = 0;
2308 return 0;
2311 /* parse a string without interpreting escapes */
2312 static uint8_t *parse_pp_string(uint8_t *p,
2313 int sep, CString *str)
2315 int c;
2316 p++;
2317 for(;;) {
2318 c = *p;
2319 if (c == sep) {
2320 break;
2321 } else if (c == '\\') {
2322 file->buf_ptr = p;
2323 c = handle_eob();
2324 p = file->buf_ptr;
2325 if (c == CH_EOF) {
2326 unterminated_string:
2327 /* XXX: indicate line number of start of string */
2328 error("missing terminating %c character", sep);
2329 } else if (c == '\\') {
2330 /* escape : just skip \[\r]\n */
2331 PEEKC_EOB(c, p);
2332 if (c == '\n') {
2333 file->line_num++;
2334 p++;
2335 } else if (c == '\r') {
2336 PEEKC_EOB(c, p);
2337 if (c != '\n')
2338 expect("'\n' after '\r'");
2339 file->line_num++;
2340 p++;
2341 } else if (c == CH_EOF) {
2342 goto unterminated_string;
2343 } else {
2344 if (str) {
2345 cstr_ccat(str, '\\');
2346 cstr_ccat(str, c);
2348 p++;
2351 } else if (c == '\n') {
2352 file->line_num++;
2353 goto add_char;
2354 } else if (c == '\r') {
2355 PEEKC_EOB(c, p);
2356 if (c != '\n') {
2357 if (str)
2358 cstr_ccat(str, '\r');
2359 } else {
2360 file->line_num++;
2361 goto add_char;
2363 } else {
2364 add_char:
2365 if (str)
2366 cstr_ccat(str, c);
2367 p++;
2370 p++;
2371 return p;
2374 /* skip block of text until #else, #elif or #endif. skip also pairs of
2375 #if/#endif */
2376 void preprocess_skip(void)
2378 int a, start_of_line, c, in_warn_or_error;
2379 uint8_t *p;
2381 p = file->buf_ptr;
2382 a = 0;
2383 redo_start:
2384 start_of_line = 1;
2385 in_warn_or_error = 0;
2386 for(;;) {
2387 redo_no_start:
2388 c = *p;
2389 switch(c) {
2390 case ' ':
2391 case '\t':
2392 case '\f':
2393 case '\v':
2394 case '\r':
2395 p++;
2396 goto redo_no_start;
2397 case '\n':
2398 file->line_num++;
2399 p++;
2400 goto redo_start;
2401 case '\\':
2402 file->buf_ptr = p;
2403 c = handle_eob();
2404 if (c == CH_EOF) {
2405 expect("#endif");
2406 } else if (c == '\\') {
2407 ch = file->buf_ptr[0];
2408 handle_stray_noerror();
2410 p = file->buf_ptr;
2411 goto redo_no_start;
2412 /* skip strings */
2413 case '\"':
2414 case '\'':
2415 if (in_warn_or_error)
2416 goto _default;
2417 p = parse_pp_string(p, c, NULL);
2418 break;
2419 /* skip comments */
2420 case '/':
2421 if (in_warn_or_error)
2422 goto _default;
2423 file->buf_ptr = p;
2424 ch = *p;
2425 minp();
2426 p = file->buf_ptr;
2427 if (ch == '*') {
2428 p = parse_comment(p);
2429 } else if (ch == '/') {
2430 p = parse_line_comment(p);
2432 break;
2433 case '#':
2434 p++;
2435 if (start_of_line) {
2436 file->buf_ptr = p;
2437 next_nomacro();
2438 p = file->buf_ptr;
2439 if (a == 0 &&
2440 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2441 goto the_end;
2442 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2443 a++;
2444 else if (tok == TOK_ENDIF)
2445 a--;
2446 else if( tok == TOK_ERROR || tok == TOK_WARNING)
2447 in_warn_or_error = 1;
2449 break;
2450 _default:
2451 default:
2452 p++;
2453 break;
2455 start_of_line = 0;
2457 the_end: ;
2458 file->buf_ptr = p;
2461 /* ParseState handling */
2463 /* XXX: currently, no include file info is stored. Thus, we cannot display
2464 accurate messages if the function or data definition spans multiple
2465 files */
2467 /* save current parse state in 's' */
2468 void save_parse_state(ParseState *s)
2470 s->line_num = file->line_num;
2471 s->macro_ptr = macro_ptr;
2472 s->tok = tok;
2473 s->tokc = tokc;
2476 /* restore parse state from 's' */
2477 void restore_parse_state(ParseState *s)
2479 file->line_num = s->line_num;
2480 macro_ptr = s->macro_ptr;
2481 tok = s->tok;
2482 tokc = s->tokc;
2485 /* return the number of additional 'ints' necessary to store the
2486 token */
2487 static inline int tok_ext_size(int t)
2489 switch(t) {
2490 /* 4 bytes */
2491 case TOK_CINT:
2492 case TOK_CUINT:
2493 case TOK_CCHAR:
2494 case TOK_LCHAR:
2495 case TOK_CFLOAT:
2496 case TOK_LINENUM:
2497 return 1;
2498 case TOK_STR:
2499 case TOK_LSTR:
2500 case TOK_PPNUM:
2501 error("unsupported token");
2502 return 1;
2503 case TOK_CDOUBLE:
2504 case TOK_CLLONG:
2505 case TOK_CULLONG:
2506 return 2;
2507 case TOK_CLDOUBLE:
2508 return LDOUBLE_SIZE / 4;
2509 default:
2510 return 0;
2514 /* token string handling */
2516 static inline void tok_str_new(TokenString *s)
2518 s->str = NULL;
2519 s->len = 0;
2520 s->allocated_len = 0;
2521 s->last_line_num = -1;
2524 static void tok_str_free(int *str)
2526 tcc_free(str);
2529 static int *tok_str_realloc(TokenString *s)
2531 int *str, len;
2533 if (s->allocated_len == 0) {
2534 len = 8;
2535 } else {
2536 len = s->allocated_len * 2;
2538 str = tcc_realloc(s->str, len * sizeof(int));
2539 if (!str)
2540 error("memory full");
2541 s->allocated_len = len;
2542 s->str = str;
2543 return str;
2546 static void tok_str_add(TokenString *s, int t)
2548 int len, *str;
2550 len = s->len;
2551 str = s->str;
2552 if (len >= s->allocated_len)
2553 str = tok_str_realloc(s);
2554 str[len++] = t;
2555 s->len = len;
2558 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2560 int len, *str;
2562 len = s->len;
2563 str = s->str;
2565 /* allocate space for worst case */
2566 if (len + TOK_MAX_SIZE > s->allocated_len)
2567 str = tok_str_realloc(s);
2568 str[len++] = t;
2569 switch(t) {
2570 case TOK_CINT:
2571 case TOK_CUINT:
2572 case TOK_CCHAR:
2573 case TOK_LCHAR:
2574 case TOK_CFLOAT:
2575 case TOK_LINENUM:
2576 str[len++] = cv->tab[0];
2577 break;
2578 case TOK_PPNUM:
2579 case TOK_STR:
2580 case TOK_LSTR:
2582 int nb_words;
2583 CString *cstr;
2585 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2586 while ((len + nb_words) > s->allocated_len)
2587 str = tok_str_realloc(s);
2588 cstr = (CString *)(str + len);
2589 cstr->data = NULL;
2590 cstr->size = cv->cstr->size;
2591 cstr->data_allocated = NULL;
2592 cstr->size_allocated = cstr->size;
2593 memcpy((char *)cstr + sizeof(CString),
2594 cv->cstr->data, cstr->size);
2595 len += nb_words;
2597 break;
2598 case TOK_CDOUBLE:
2599 case TOK_CLLONG:
2600 case TOK_CULLONG:
2601 #if LDOUBLE_SIZE == 8
2602 case TOK_CLDOUBLE:
2603 #endif
2604 str[len++] = cv->tab[0];
2605 str[len++] = cv->tab[1];
2606 break;
2607 #if LDOUBLE_SIZE == 12
2608 case TOK_CLDOUBLE:
2609 str[len++] = cv->tab[0];
2610 str[len++] = cv->tab[1];
2611 str[len++] = cv->tab[2];
2612 #elif LDOUBLE_SIZE == 16
2613 case TOK_CLDOUBLE:
2614 str[len++] = cv->tab[0];
2615 str[len++] = cv->tab[1];
2616 str[len++] = cv->tab[2];
2617 str[len++] = cv->tab[3];
2618 #elif LDOUBLE_SIZE != 8
2619 #error add long double size support
2620 #endif
2621 break;
2622 default:
2623 break;
2625 s->len = len;
2628 /* add the current parse token in token string 's' */
2629 static void tok_str_add_tok(TokenString *s)
2631 CValue cval;
2633 /* save line number info */
2634 if (file->line_num != s->last_line_num) {
2635 s->last_line_num = file->line_num;
2636 cval.i = s->last_line_num;
2637 tok_str_add2(s, TOK_LINENUM, &cval);
2639 tok_str_add2(s, tok, &tokc);
2642 #if LDOUBLE_SIZE == 16
2643 #define LDOUBLE_GET(p, cv) \
2644 cv.tab[0] = p[0]; \
2645 cv.tab[1] = p[1]; \
2646 cv.tab[2] = p[2]; \
2647 cv.tab[3] = p[3];
2648 #elif LDOUBLE_SIZE == 12
2649 #define LDOUBLE_GET(p, cv) \
2650 cv.tab[0] = p[0]; \
2651 cv.tab[1] = p[1]; \
2652 cv.tab[2] = p[2];
2653 #elif LDOUBLE_SIZE == 8
2654 #define LDOUBLE_GET(p, cv) \
2655 cv.tab[0] = p[0]; \
2656 cv.tab[1] = p[1];
2657 #else
2658 #error add long double size support
2659 #endif
2662 /* get a token from an integer array and increment pointer
2663 accordingly. we code it as a macro to avoid pointer aliasing. */
2664 #define TOK_GET(t, p, cv) \
2666 t = *p++; \
2667 switch(t) { \
2668 case TOK_CINT: \
2669 case TOK_CUINT: \
2670 case TOK_CCHAR: \
2671 case TOK_LCHAR: \
2672 case TOK_CFLOAT: \
2673 case TOK_LINENUM: \
2674 cv.tab[0] = *p++; \
2675 break; \
2676 case TOK_STR: \
2677 case TOK_LSTR: \
2678 case TOK_PPNUM: \
2679 cv.cstr = (CString *)p; \
2680 cv.cstr->data = (char *)p + sizeof(CString);\
2681 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2682 break; \
2683 case TOK_CDOUBLE: \
2684 case TOK_CLLONG: \
2685 case TOK_CULLONG: \
2686 cv.tab[0] = p[0]; \
2687 cv.tab[1] = p[1]; \
2688 p += 2; \
2689 break; \
2690 case TOK_CLDOUBLE: \
2691 LDOUBLE_GET(p, cv); \
2692 p += LDOUBLE_SIZE / 4; \
2693 break; \
2694 default: \
2695 break; \
2699 /* defines handling */
2700 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2702 Sym *s;
2704 s = sym_push2(&define_stack, v, macro_type, (long)str);
2705 s->next = first_arg;
2706 table_ident[v - TOK_IDENT]->sym_define = s;
2709 /* undefined a define symbol. Its name is just set to zero */
2710 static void define_undef(Sym *s)
2712 int v;
2713 v = s->v;
2714 if (v >= TOK_IDENT && v < tok_ident)
2715 table_ident[v - TOK_IDENT]->sym_define = NULL;
2716 s->v = 0;
2719 static inline Sym *define_find(int v)
2721 v -= TOK_IDENT;
2722 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2723 return NULL;
2724 return table_ident[v]->sym_define;
2727 /* free define stack until top reaches 'b' */
2728 static void free_defines(Sym *b)
2730 Sym *top, *top1;
2731 int v;
2733 top = define_stack;
2734 while (top != b) {
2735 top1 = top->prev;
2736 /* do not free args or predefined defines */
2737 if (top->c)
2738 tok_str_free((int *)top->c);
2739 v = top->v;
2740 if (v >= TOK_IDENT && v < tok_ident)
2741 table_ident[v - TOK_IDENT]->sym_define = NULL;
2742 sym_free(top);
2743 top = top1;
2745 define_stack = b;
2748 /* label lookup */
2749 static Sym *label_find(int v)
2751 v -= TOK_IDENT;
2752 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2753 return NULL;
2754 return table_ident[v]->sym_label;
2757 static Sym *label_push(Sym **ptop, int v, int flags)
2759 Sym *s, **ps;
2760 s = sym_push2(ptop, v, 0, 0);
2761 s->r = flags;
2762 ps = &table_ident[v - TOK_IDENT]->sym_label;
2763 if (ptop == &global_label_stack) {
2764 /* modify the top most local identifier, so that
2765 sym_identifier will point to 's' when popped */
2766 while (*ps != NULL)
2767 ps = &(*ps)->prev_tok;
2769 s->prev_tok = *ps;
2770 *ps = s;
2771 return s;
2774 /* pop labels until element last is reached. Look if any labels are
2775 undefined. Define symbols if '&&label' was used. */
2776 static void label_pop(Sym **ptop, Sym *slast)
2778 Sym *s, *s1;
2779 for(s = *ptop; s != slast; s = s1) {
2780 s1 = s->prev;
2781 if (s->r == LABEL_DECLARED) {
2782 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2783 } else if (s->r == LABEL_FORWARD) {
2784 error("label '%s' used but not defined",
2785 get_tok_str(s->v, NULL));
2786 } else {
2787 if (s->c) {
2788 /* define corresponding symbol. A size of
2789 1 is put. */
2790 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2793 /* remove label */
2794 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2795 sym_free(s);
2797 *ptop = slast;
2800 /* eval an expression for #if/#elif */
2801 static int expr_preprocess(void)
2803 int c, t;
2804 TokenString str;
2806 tok_str_new(&str);
2807 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2808 next(); /* do macro subst */
2809 if (tok == TOK_DEFINED) {
2810 next_nomacro();
2811 t = tok;
2812 if (t == '(')
2813 next_nomacro();
2814 c = define_find(tok) != 0;
2815 if (t == '(')
2816 next_nomacro();
2817 tok = TOK_CINT;
2818 tokc.i = c;
2819 } else if (tok >= TOK_IDENT) {
2820 /* if undefined macro */
2821 tok = TOK_CINT;
2822 tokc.i = 0;
2824 tok_str_add_tok(&str);
2826 tok_str_add(&str, -1); /* simulate end of file */
2827 tok_str_add(&str, 0);
2828 /* now evaluate C constant expression */
2829 macro_ptr = str.str;
2830 next();
2831 c = expr_const();
2832 macro_ptr = NULL;
2833 tok_str_free(str.str);
2834 return c != 0;
2837 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2838 static void tok_print(int *str)
2840 int t;
2841 CValue cval;
2843 printf("<");
2844 while (1) {
2845 TOK_GET(t, str, cval);
2846 if (!t)
2847 break;
2848 printf("%s", get_tok_str(t, &cval));
2850 printf(">\n");
2852 #endif
2854 /* parse after #define */
2855 static void parse_define(void)
2857 Sym *s, *first, **ps;
2858 int v, t, varg, is_vaargs, spc;
2859 TokenString str;
2861 v = tok;
2862 if (v < TOK_IDENT)
2863 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2864 /* XXX: should check if same macro (ANSI) */
2865 first = NULL;
2866 t = MACRO_OBJ;
2867 /* '(' must be just after macro definition for MACRO_FUNC */
2868 next_nomacro_spc();
2869 if (tok == '(') {
2870 next_nomacro();
2871 ps = &first;
2872 while (tok != ')') {
2873 varg = tok;
2874 next_nomacro();
2875 is_vaargs = 0;
2876 if (varg == TOK_DOTS) {
2877 varg = TOK___VA_ARGS__;
2878 is_vaargs = 1;
2879 } else if (tok == TOK_DOTS && gnu_ext) {
2880 is_vaargs = 1;
2881 next_nomacro();
2883 if (varg < TOK_IDENT)
2884 error("badly punctuated parameter list");
2885 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2886 *ps = s;
2887 ps = &s->next;
2888 if (tok != ',')
2889 break;
2890 next_nomacro();
2892 if (tok == ')')
2893 next_nomacro_spc();
2894 t = MACRO_FUNC;
2896 tok_str_new(&str);
2897 spc = 2;
2898 /* EOF testing necessary for '-D' handling */
2899 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2900 /* remove spaces around ## and after '#' */
2901 if (TOK_TWOSHARPS == tok) {
2902 if (1 == spc)
2903 --str.len;
2904 spc = 2;
2905 } else if ('#' == tok) {
2906 spc = 2;
2907 } else if (check_space(tok, &spc)) {
2908 goto skip;
2910 tok_str_add2(&str, tok, &tokc);
2911 skip:
2912 next_nomacro_spc();
2914 if (spc == 1)
2915 --str.len; /* remove trailing space */
2916 tok_str_add(&str, 0);
2917 #ifdef PP_DEBUG
2918 printf("define %s %d: ", get_tok_str(v, NULL), t);
2919 tok_print(str.str);
2920 #endif
2921 define_push(v, t, str.str, first);
2924 static inline int hash_cached_include(int type, const char *filename)
2926 const unsigned char *s;
2927 unsigned int h;
2929 h = TOK_HASH_INIT;
2930 h = TOK_HASH_FUNC(h, type);
2931 s = filename;
2932 while (*s) {
2933 h = TOK_HASH_FUNC(h, *s);
2934 s++;
2936 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2937 return h;
2940 /* XXX: use a token or a hash table to accelerate matching ? */
2941 static CachedInclude *search_cached_include(TCCState *s1,
2942 int type, const char *filename)
2944 CachedInclude *e;
2945 int i, h;
2946 h = hash_cached_include(type, filename);
2947 i = s1->cached_includes_hash[h];
2948 for(;;) {
2949 if (i == 0)
2950 break;
2951 e = s1->cached_includes[i - 1];
2952 if (e->type == type && !PATHCMP(e->filename, filename))
2953 return e;
2954 i = e->hash_next;
2956 return NULL;
2959 static inline void add_cached_include(TCCState *s1, int type,
2960 const char *filename, int ifndef_macro)
2962 CachedInclude *e;
2963 int h;
2965 if (search_cached_include(s1, type, filename))
2966 return;
2967 #ifdef INC_DEBUG
2968 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2969 #endif
2970 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2971 if (!e)
2972 return;
2973 e->type = type;
2974 strcpy(e->filename, filename);
2975 e->ifndef_macro = ifndef_macro;
2976 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2977 /* add in hash table */
2978 h = hash_cached_include(type, filename);
2979 e->hash_next = s1->cached_includes_hash[h];
2980 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2983 static void pragma_parse(TCCState *s1)
2985 int val;
2987 next();
2988 if (tok == TOK_pack) {
2990 This may be:
2991 #pragma pack(1) // set
2992 #pragma pack() // reset to default
2993 #pragma pack(push,1) // push & set
2994 #pragma pack(pop) // restore previous
2996 next();
2997 skip('(');
2998 if (tok == TOK_ASM_pop) {
2999 next();
3000 if (s1->pack_stack_ptr <= s1->pack_stack) {
3001 stk_error:
3002 error("out of pack stack");
3004 s1->pack_stack_ptr--;
3005 } else {
3006 val = 0;
3007 if (tok != ')') {
3008 if (tok == TOK_ASM_push) {
3009 next();
3010 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
3011 goto stk_error;
3012 s1->pack_stack_ptr++;
3013 skip(',');
3015 if (tok != TOK_CINT) {
3016 pack_error:
3017 error("invalid pack pragma");
3019 val = tokc.i;
3020 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
3021 goto pack_error;
3022 next();
3024 *s1->pack_stack_ptr = val;
3025 skip(')');
3030 /* is_bof is true if first non space token at beginning of file */
3031 static void preprocess(int is_bof)
3033 TCCState *s1 = tcc_state;
3034 int size, i, c, n, saved_parse_flags;
3035 char buf[1024], *q;
3036 char buf1[1024];
3037 BufferedFile *f;
3038 Sym *s;
3039 CachedInclude *e;
3041 saved_parse_flags = parse_flags;
3042 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
3043 PARSE_FLAG_LINEFEED;
3044 next_nomacro();
3045 redo:
3046 switch(tok) {
3047 case TOK_DEFINE:
3048 next_nomacro();
3049 parse_define();
3050 break;
3051 case TOK_UNDEF:
3052 next_nomacro();
3053 s = define_find(tok);
3054 /* undefine symbol by putting an invalid name */
3055 if (s)
3056 define_undef(s);
3057 break;
3058 case TOK_INCLUDE:
3059 case TOK_INCLUDE_NEXT:
3060 ch = file->buf_ptr[0];
3061 /* XXX: incorrect if comments : use next_nomacro with a special mode */
3062 skip_spaces();
3063 if (ch == '<') {
3064 c = '>';
3065 goto read_name;
3066 } else if (ch == '\"') {
3067 c = ch;
3068 read_name:
3069 inp();
3070 q = buf;
3071 while (ch != c && ch != '\n' && ch != CH_EOF) {
3072 if ((q - buf) < sizeof(buf) - 1)
3073 *q++ = ch;
3074 if (ch == '\\') {
3075 if (handle_stray_noerror() == 0)
3076 --q;
3077 } else
3078 inp();
3080 *q = '\0';
3081 minp();
3082 #if 0
3083 /* eat all spaces and comments after include */
3084 /* XXX: slightly incorrect */
3085 while (ch1 != '\n' && ch1 != CH_EOF)
3086 inp();
3087 #endif
3088 } else {
3089 /* computed #include : either we have only strings or
3090 we have anything enclosed in '<>' */
3091 next();
3092 buf[0] = '\0';
3093 if (tok == TOK_STR) {
3094 while (tok != TOK_LINEFEED) {
3095 if (tok != TOK_STR) {
3096 include_syntax:
3097 error("'#include' expects \"FILENAME\" or <FILENAME>");
3099 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
3100 next();
3102 c = '\"';
3103 } else {
3104 int len;
3105 while (tok != TOK_LINEFEED) {
3106 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
3107 next();
3109 len = strlen(buf);
3110 /* check syntax and remove '<>' */
3111 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
3112 goto include_syntax;
3113 memmove(buf, buf + 1, len - 2);
3114 buf[len - 2] = '\0';
3115 c = '>';
3119 e = search_cached_include(s1, c, buf);
3120 if (e && define_find(e->ifndef_macro)) {
3121 /* no need to parse the include because the 'ifndef macro'
3122 is defined */
3123 #ifdef INC_DEBUG
3124 printf("%s: skipping %s\n", file->filename, buf);
3125 #endif
3126 } else {
3127 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
3128 error("#include recursion too deep");
3129 /* push current file in stack */
3130 /* XXX: fix current line init */
3131 *s1->include_stack_ptr++ = file;
3133 /* check absolute include path */
3134 if (IS_ABSPATH(buf)) {
3135 f = tcc_open(s1, buf);
3136 if (f)
3137 goto found;
3139 if (c == '\"') {
3140 /* first search in current dir if "header.h" */
3141 size = tcc_basename(file->filename) - file->filename;
3142 if (size > sizeof(buf1) - 1)
3143 size = sizeof(buf1) - 1;
3144 memcpy(buf1, file->filename, size);
3145 buf1[size] = '\0';
3146 pstrcat(buf1, sizeof(buf1), buf);
3147 f = tcc_open(s1, buf1);
3148 if (f) {
3149 if (tok == TOK_INCLUDE_NEXT)
3150 tok = TOK_INCLUDE;
3151 else
3152 goto found;
3155 /* now search in all the include paths */
3156 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
3157 for(i = 0; i < n; i++) {
3158 const char *path;
3159 if (i < s1->nb_include_paths)
3160 path = s1->include_paths[i];
3161 else
3162 path = s1->sysinclude_paths[i - s1->nb_include_paths];
3163 pstrcpy(buf1, sizeof(buf1), path);
3164 pstrcat(buf1, sizeof(buf1), "/");
3165 pstrcat(buf1, sizeof(buf1), buf);
3166 f = tcc_open(s1, buf1);
3167 if (f) {
3168 if (tok == TOK_INCLUDE_NEXT)
3169 tok = TOK_INCLUDE;
3170 else
3171 goto found;
3174 --s1->include_stack_ptr;
3175 error("include file '%s' not found", buf);
3176 break;
3177 found:
3178 #ifdef INC_DEBUG
3179 printf("%s: including %s\n", file->filename, buf1);
3180 #endif
3181 f->inc_type = c;
3182 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
3183 file = f;
3184 /* add include file debug info */
3185 if (do_debug) {
3186 put_stabs(file->filename, N_BINCL, 0, 0, 0);
3188 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
3189 ch = file->buf_ptr[0];
3190 goto the_end;
3192 break;
3193 case TOK_IFNDEF:
3194 c = 1;
3195 goto do_ifdef;
3196 case TOK_IF:
3197 c = expr_preprocess();
3198 goto do_if;
3199 case TOK_IFDEF:
3200 c = 0;
3201 do_ifdef:
3202 next_nomacro();
3203 if (tok < TOK_IDENT)
3204 error("invalid argument for '#if%sdef'", c ? "n" : "");
3205 if (is_bof) {
3206 if (c) {
3207 #ifdef INC_DEBUG
3208 printf("#ifndef %s\n", get_tok_str(tok, NULL));
3209 #endif
3210 file->ifndef_macro = tok;
3213 c = (define_find(tok) != 0) ^ c;
3214 do_if:
3215 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
3216 error("memory full");
3217 *s1->ifdef_stack_ptr++ = c;
3218 goto test_skip;
3219 case TOK_ELSE:
3220 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3221 error("#else without matching #if");
3222 if (s1->ifdef_stack_ptr[-1] & 2)
3223 error("#else after #else");
3224 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3225 goto test_skip;
3226 case TOK_ELIF:
3227 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3228 error("#elif without matching #if");
3229 c = s1->ifdef_stack_ptr[-1];
3230 if (c > 1)
3231 error("#elif after #else");
3232 /* last #if/#elif expression was true: we skip */
3233 if (c == 1)
3234 goto skip;
3235 c = expr_preprocess();
3236 s1->ifdef_stack_ptr[-1] = c;
3237 test_skip:
3238 if (!(c & 1)) {
3239 skip:
3240 preprocess_skip();
3241 is_bof = 0;
3242 goto redo;
3244 break;
3245 case TOK_ENDIF:
3246 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3247 error("#endif without matching #if");
3248 s1->ifdef_stack_ptr--;
3249 /* '#ifndef macro' was at the start of file. Now we check if
3250 an '#endif' is exactly at the end of file */
3251 if (file->ifndef_macro &&
3252 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3253 file->ifndef_macro_saved = file->ifndef_macro;
3254 /* need to set to zero to avoid false matches if another
3255 #ifndef at middle of file */
3256 file->ifndef_macro = 0;
3257 while (tok != TOK_LINEFEED)
3258 next_nomacro();
3259 tok_flags |= TOK_FLAG_ENDIF;
3260 goto the_end;
3262 break;
3263 case TOK_LINE:
3264 next();
3265 if (tok != TOK_CINT)
3266 error("#line");
3267 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3268 next();
3269 if (tok != TOK_LINEFEED) {
3270 if (tok != TOK_STR)
3271 error("#line");
3272 pstrcpy(file->filename, sizeof(file->filename),
3273 (char *)tokc.cstr->data);
3275 break;
3276 case TOK_ERROR:
3277 case TOK_WARNING:
3278 c = tok;
3279 ch = file->buf_ptr[0];
3280 skip_spaces();
3281 q = buf;
3282 while (ch != '\n' && ch != CH_EOF) {
3283 if ((q - buf) < sizeof(buf) - 1)
3284 *q++ = ch;
3285 if (ch == '\\') {
3286 if (handle_stray_noerror() == 0)
3287 --q;
3288 } else
3289 inp();
3291 *q = '\0';
3292 if (c == TOK_ERROR)
3293 error("#error %s", buf);
3294 else
3295 warning("#warning %s", buf);
3296 break;
3297 case TOK_PRAGMA:
3298 pragma_parse(s1);
3299 break;
3300 default:
3301 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3302 /* '!' is ignored to allow C scripts. numbers are ignored
3303 to emulate cpp behaviour */
3304 } else {
3305 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3306 warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
3308 break;
3310 /* ignore other preprocess commands or #! for C scripts */
3311 while (tok != TOK_LINEFEED)
3312 next_nomacro();
3313 the_end:
3314 parse_flags = saved_parse_flags;
3317 /* evaluate escape codes in a string. */
3318 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3320 int c, n;
3321 const uint8_t *p;
3323 p = buf;
3324 for(;;) {
3325 c = *p;
3326 if (c == '\0')
3327 break;
3328 if (c == '\\') {
3329 p++;
3330 /* escape */
3331 c = *p;
3332 switch(c) {
3333 case '0': case '1': case '2': case '3':
3334 case '4': case '5': case '6': case '7':
3335 /* at most three octal digits */
3336 n = c - '0';
3337 p++;
3338 c = *p;
3339 if (isoct(c)) {
3340 n = n * 8 + c - '0';
3341 p++;
3342 c = *p;
3343 if (isoct(c)) {
3344 n = n * 8 + c - '0';
3345 p++;
3348 c = n;
3349 goto add_char_nonext;
3350 case 'x':
3351 case 'u':
3352 case 'U':
3353 p++;
3354 n = 0;
3355 for(;;) {
3356 c = *p;
3357 if (c >= 'a' && c <= 'f')
3358 c = c - 'a' + 10;
3359 else if (c >= 'A' && c <= 'F')
3360 c = c - 'A' + 10;
3361 else if (isnum(c))
3362 c = c - '0';
3363 else
3364 break;
3365 n = n * 16 + c;
3366 p++;
3368 c = n;
3369 goto add_char_nonext;
3370 case 'a':
3371 c = '\a';
3372 break;
3373 case 'b':
3374 c = '\b';
3375 break;
3376 case 'f':
3377 c = '\f';
3378 break;
3379 case 'n':
3380 c = '\n';
3381 break;
3382 case 'r':
3383 c = '\r';
3384 break;
3385 case 't':
3386 c = '\t';
3387 break;
3388 case 'v':
3389 c = '\v';
3390 break;
3391 case 'e':
3392 if (!gnu_ext)
3393 goto invalid_escape;
3394 c = 27;
3395 break;
3396 case '\'':
3397 case '\"':
3398 case '\\':
3399 case '?':
3400 break;
3401 default:
3402 invalid_escape:
3403 if (c >= '!' && c <= '~')
3404 warning("unknown escape sequence: \'\\%c\'", c);
3405 else
3406 warning("unknown escape sequence: \'\\x%x\'", c);
3407 break;
3410 p++;
3411 add_char_nonext:
3412 if (!is_long)
3413 cstr_ccat(outstr, c);
3414 else
3415 cstr_wccat(outstr, c);
3417 /* add a trailing '\0' */
3418 if (!is_long)
3419 cstr_ccat(outstr, '\0');
3420 else
3421 cstr_wccat(outstr, '\0');
3424 /* we use 64 bit numbers */
3425 #define BN_SIZE 2
3427 /* bn = (bn << shift) | or_val */
3428 void bn_lshift(unsigned int *bn, int shift, int or_val)
3430 int i;
3431 unsigned int v;
3432 for(i=0;i<BN_SIZE;i++) {
3433 v = bn[i];
3434 bn[i] = (v << shift) | or_val;
3435 or_val = v >> (32 - shift);
3439 void bn_zero(unsigned int *bn)
3441 int i;
3442 for(i=0;i<BN_SIZE;i++) {
3443 bn[i] = 0;
3447 /* parse number in null terminated string 'p' and return it in the
3448 current token */
3449 void parse_number(const char *p)
3451 int b, t, shift, frac_bits, s, exp_val, ch;
3452 char *q;
3453 unsigned int bn[BN_SIZE];
3454 double d;
3456 /* number */
3457 q = token_buf;
3458 ch = *p++;
3459 t = ch;
3460 ch = *p++;
3461 *q++ = t;
3462 b = 10;
3463 if (t == '.') {
3464 goto float_frac_parse;
3465 } else if (t == '0') {
3466 if (ch == 'x' || ch == 'X') {
3467 q--;
3468 ch = *p++;
3469 b = 16;
3470 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3471 q--;
3472 ch = *p++;
3473 b = 2;
3476 /* parse all digits. cannot check octal numbers at this stage
3477 because of floating point constants */
3478 while (1) {
3479 if (ch >= 'a' && ch <= 'f')
3480 t = ch - 'a' + 10;
3481 else if (ch >= 'A' && ch <= 'F')
3482 t = ch - 'A' + 10;
3483 else if (isnum(ch))
3484 t = ch - '0';
3485 else
3486 break;
3487 if (t >= b)
3488 break;
3489 if (q >= token_buf + STRING_MAX_SIZE) {
3490 num_too_long:
3491 error("number too long");
3493 *q++ = ch;
3494 ch = *p++;
3496 if (ch == '.' ||
3497 ((ch == 'e' || ch == 'E') && b == 10) ||
3498 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3499 if (b != 10) {
3500 /* NOTE: strtox should support that for hexa numbers, but
3501 non ISOC99 libcs do not support it, so we prefer to do
3502 it by hand */
3503 /* hexadecimal or binary floats */
3504 /* XXX: handle overflows */
3505 *q = '\0';
3506 if (b == 16)
3507 shift = 4;
3508 else
3509 shift = 2;
3510 bn_zero(bn);
3511 q = token_buf;
3512 while (1) {
3513 t = *q++;
3514 if (t == '\0') {
3515 break;
3516 } else if (t >= 'a') {
3517 t = t - 'a' + 10;
3518 } else if (t >= 'A') {
3519 t = t - 'A' + 10;
3520 } else {
3521 t = t - '0';
3523 bn_lshift(bn, shift, t);
3525 frac_bits = 0;
3526 if (ch == '.') {
3527 ch = *p++;
3528 while (1) {
3529 t = ch;
3530 if (t >= 'a' && t <= 'f') {
3531 t = t - 'a' + 10;
3532 } else if (t >= 'A' && t <= 'F') {
3533 t = t - 'A' + 10;
3534 } else if (t >= '0' && t <= '9') {
3535 t = t - '0';
3536 } else {
3537 break;
3539 if (t >= b)
3540 error("invalid digit");
3541 bn_lshift(bn, shift, t);
3542 frac_bits += shift;
3543 ch = *p++;
3546 if (ch != 'p' && ch != 'P')
3547 expect("exponent");
3548 ch = *p++;
3549 s = 1;
3550 exp_val = 0;
3551 if (ch == '+') {
3552 ch = *p++;
3553 } else if (ch == '-') {
3554 s = -1;
3555 ch = *p++;
3557 if (ch < '0' || ch > '9')
3558 expect("exponent digits");
3559 while (ch >= '0' && ch <= '9') {
3560 exp_val = exp_val * 10 + ch - '0';
3561 ch = *p++;
3563 exp_val = exp_val * s;
3565 /* now we can generate the number */
3566 /* XXX: should patch directly float number */
3567 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3568 d = ldexp(d, exp_val - frac_bits);
3569 t = toup(ch);
3570 if (t == 'F') {
3571 ch = *p++;
3572 tok = TOK_CFLOAT;
3573 /* float : should handle overflow */
3574 tokc.f = (float)d;
3575 } else if (t == 'L') {
3576 ch = *p++;
3577 tok = TOK_CLDOUBLE;
3578 /* XXX: not large enough */
3579 tokc.ld = (long double)d;
3580 } else {
3581 tok = TOK_CDOUBLE;
3582 tokc.d = d;
3584 } else {
3585 /* decimal floats */
3586 if (ch == '.') {
3587 if (q >= token_buf + STRING_MAX_SIZE)
3588 goto num_too_long;
3589 *q++ = ch;
3590 ch = *p++;
3591 float_frac_parse:
3592 while (ch >= '0' && ch <= '9') {
3593 if (q >= token_buf + STRING_MAX_SIZE)
3594 goto num_too_long;
3595 *q++ = ch;
3596 ch = *p++;
3599 if (ch == 'e' || ch == 'E') {
3600 if (q >= token_buf + STRING_MAX_SIZE)
3601 goto num_too_long;
3602 *q++ = ch;
3603 ch = *p++;
3604 if (ch == '-' || ch == '+') {
3605 if (q >= token_buf + STRING_MAX_SIZE)
3606 goto num_too_long;
3607 *q++ = ch;
3608 ch = *p++;
3610 if (ch < '0' || ch > '9')
3611 expect("exponent digits");
3612 while (ch >= '0' && ch <= '9') {
3613 if (q >= token_buf + STRING_MAX_SIZE)
3614 goto num_too_long;
3615 *q++ = ch;
3616 ch = *p++;
3619 *q = '\0';
3620 t = toup(ch);
3621 errno = 0;
3622 if (t == 'F') {
3623 ch = *p++;
3624 tok = TOK_CFLOAT;
3625 tokc.f = strtof(token_buf, NULL);
3626 } else if (t == 'L') {
3627 ch = *p++;
3628 tok = TOK_CLDOUBLE;
3629 tokc.ld = strtold(token_buf, NULL);
3630 } else {
3631 tok = TOK_CDOUBLE;
3632 tokc.d = strtod(token_buf, NULL);
3635 } else {
3636 unsigned long long n, n1;
3637 int lcount, ucount;
3639 /* integer number */
3640 *q = '\0';
3641 q = token_buf;
3642 if (b == 10 && *q == '0') {
3643 b = 8;
3644 q++;
3646 n = 0;
3647 while(1) {
3648 t = *q++;
3649 /* no need for checks except for base 10 / 8 errors */
3650 if (t == '\0') {
3651 break;
3652 } else if (t >= 'a') {
3653 t = t - 'a' + 10;
3654 } else if (t >= 'A') {
3655 t = t - 'A' + 10;
3656 } else {
3657 t = t - '0';
3658 if (t >= b)
3659 error("invalid digit");
3661 n1 = n;
3662 n = n * b + t;
3663 /* detect overflow */
3664 /* XXX: this test is not reliable */
3665 if (n < n1)
3666 error("integer constant overflow");
3669 /* XXX: not exactly ANSI compliant */
3670 if ((n & 0xffffffff00000000LL) != 0) {
3671 if ((n >> 63) != 0)
3672 tok = TOK_CULLONG;
3673 else
3674 tok = TOK_CLLONG;
3675 } else if (n > 0x7fffffff) {
3676 tok = TOK_CUINT;
3677 } else {
3678 tok = TOK_CINT;
3680 lcount = 0;
3681 ucount = 0;
3682 for(;;) {
3683 t = toup(ch);
3684 if (t == 'L') {
3685 if (lcount >= 2)
3686 error("three 'l's in integer constant");
3687 lcount++;
3688 if (lcount == 2) {
3689 if (tok == TOK_CINT)
3690 tok = TOK_CLLONG;
3691 else if (tok == TOK_CUINT)
3692 tok = TOK_CULLONG;
3694 ch = *p++;
3695 } else if (t == 'U') {
3696 if (ucount >= 1)
3697 error("two 'u's in integer constant");
3698 ucount++;
3699 if (tok == TOK_CINT)
3700 tok = TOK_CUINT;
3701 else if (tok == TOK_CLLONG)
3702 tok = TOK_CULLONG;
3703 ch = *p++;
3704 } else {
3705 break;
3708 if (tok == TOK_CINT || tok == TOK_CUINT)
3709 tokc.ui = n;
3710 else
3711 tokc.ull = n;
3713 if (ch)
3714 error("invalid number\n");
3718 #define PARSE2(c1, tok1, c2, tok2) \
3719 case c1: \
3720 PEEKC(c, p); \
3721 if (c == c2) { \
3722 p++; \
3723 tok = tok2; \
3724 } else { \
3725 tok = tok1; \
3727 break;
3729 /* return next token without macro substitution */
3730 static inline void next_nomacro1(void)
3732 int t, c, is_long;
3733 TokenSym *ts;
3734 uint8_t *p, *p1;
3735 unsigned int h;
3737 p = file->buf_ptr;
3738 redo_no_start:
3739 c = *p;
3740 switch(c) {
3741 case ' ':
3742 case '\t':
3743 tok = c;
3744 p++;
3745 goto keep_tok_flags;
3746 case '\f':
3747 case '\v':
3748 case '\r':
3749 p++;
3750 goto redo_no_start;
3751 case '\\':
3752 /* first look if it is in fact an end of buffer */
3753 if (p >= file->buf_end) {
3754 file->buf_ptr = p;
3755 handle_eob();
3756 p = file->buf_ptr;
3757 if (p >= file->buf_end)
3758 goto parse_eof;
3759 else
3760 goto redo_no_start;
3761 } else {
3762 file->buf_ptr = p;
3763 ch = *p;
3764 handle_stray();
3765 p = file->buf_ptr;
3766 goto redo_no_start;
3768 parse_eof:
3770 TCCState *s1 = tcc_state;
3771 if ((parse_flags & PARSE_FLAG_LINEFEED)
3772 && !(tok_flags & TOK_FLAG_EOF)) {
3773 tok_flags |= TOK_FLAG_EOF;
3774 tok = TOK_LINEFEED;
3775 goto keep_tok_flags;
3776 } else if (s1->include_stack_ptr == s1->include_stack ||
3777 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3778 /* no include left : end of file. */
3779 tok = TOK_EOF;
3780 } else {
3781 tok_flags &= ~TOK_FLAG_EOF;
3782 /* pop include file */
3784 /* test if previous '#endif' was after a #ifdef at
3785 start of file */
3786 if (tok_flags & TOK_FLAG_ENDIF) {
3787 #ifdef INC_DEBUG
3788 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3789 #endif
3790 add_cached_include(s1, file->inc_type, file->inc_filename,
3791 file->ifndef_macro_saved);
3794 /* add end of include file debug info */
3795 if (do_debug) {
3796 put_stabd(N_EINCL, 0, 0);
3798 /* pop include stack */
3799 tcc_close(file);
3800 s1->include_stack_ptr--;
3801 file = *s1->include_stack_ptr;
3802 p = file->buf_ptr;
3803 goto redo_no_start;
3806 break;
3808 case '\n':
3809 file->line_num++;
3810 tok_flags |= TOK_FLAG_BOL;
3811 p++;
3812 if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
3813 goto redo_no_start;
3814 tok = TOK_LINEFEED;
3815 goto keep_tok_flags;
3817 case '#':
3818 /* XXX: simplify */
3819 PEEKC(c, p);
3820 if ((tok_flags & TOK_FLAG_BOL) &&
3821 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3822 file->buf_ptr = p;
3823 preprocess(tok_flags & TOK_FLAG_BOF);
3824 p = file->buf_ptr;
3825 goto redo_no_start;
3826 } else {
3827 if (c == '#') {
3828 p++;
3829 tok = TOK_TWOSHARPS;
3830 } else {
3831 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3832 p = parse_line_comment(p - 1);
3833 goto redo_no_start;
3834 } else {
3835 tok = '#';
3839 break;
3841 case 'a': case 'b': case 'c': case 'd':
3842 case 'e': case 'f': case 'g': case 'h':
3843 case 'i': case 'j': case 'k': case 'l':
3844 case 'm': case 'n': case 'o': case 'p':
3845 case 'q': case 'r': case 's': case 't':
3846 case 'u': case 'v': case 'w': case 'x':
3847 case 'y': case 'z':
3848 case 'A': case 'B': case 'C': case 'D':
3849 case 'E': case 'F': case 'G': case 'H':
3850 case 'I': case 'J': case 'K':
3851 case 'M': case 'N': case 'O': case 'P':
3852 case 'Q': case 'R': case 'S': case 'T':
3853 case 'U': case 'V': case 'W': case 'X':
3854 case 'Y': case 'Z':
3855 case '_':
3856 parse_ident_fast:
3857 p1 = p;
3858 h = TOK_HASH_INIT;
3859 h = TOK_HASH_FUNC(h, c);
3860 p++;
3861 for(;;) {
3862 c = *p;
3863 if (!isidnum_table[c-CH_EOF])
3864 break;
3865 h = TOK_HASH_FUNC(h, c);
3866 p++;
3868 if (c != '\\') {
3869 TokenSym **pts;
3870 int len;
3872 /* fast case : no stray found, so we have the full token
3873 and we have already hashed it */
3874 len = p - p1;
3875 h &= (TOK_HASH_SIZE - 1);
3876 pts = &hash_ident[h];
3877 for(;;) {
3878 ts = *pts;
3879 if (!ts)
3880 break;
3881 if (ts->len == len && !memcmp(ts->str, p1, len))
3882 goto token_found;
3883 pts = &(ts->hash_next);
3885 ts = tok_alloc_new(pts, p1, len);
3886 token_found: ;
3887 } else {
3888 /* slower case */
3889 cstr_reset(&tokcstr);
3891 while (p1 < p) {
3892 cstr_ccat(&tokcstr, *p1);
3893 p1++;
3895 p--;
3896 PEEKC(c, p);
3897 parse_ident_slow:
3898 while (isidnum_table[c-CH_EOF]) {
3899 cstr_ccat(&tokcstr, c);
3900 PEEKC(c, p);
3902 ts = tok_alloc(tokcstr.data, tokcstr.size);
3904 tok = ts->tok;
3905 break;
3906 case 'L':
3907 t = p[1];
3908 if (t != '\\' && t != '\'' && t != '\"') {
3909 /* fast case */
3910 goto parse_ident_fast;
3911 } else {
3912 PEEKC(c, p);
3913 if (c == '\'' || c == '\"') {
3914 is_long = 1;
3915 goto str_const;
3916 } else {
3917 cstr_reset(&tokcstr);
3918 cstr_ccat(&tokcstr, 'L');
3919 goto parse_ident_slow;
3922 break;
3923 case '0': case '1': case '2': case '3':
3924 case '4': case '5': case '6': case '7':
3925 case '8': case '9':
3927 cstr_reset(&tokcstr);
3928 /* after the first digit, accept digits, alpha, '.' or sign if
3929 prefixed by 'eEpP' */
3930 parse_num:
3931 for(;;) {
3932 t = c;
3933 cstr_ccat(&tokcstr, c);
3934 PEEKC(c, p);
3935 if (!(isnum(c) || isid(c) || c == '.' ||
3936 ((c == '+' || c == '-') &&
3937 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3938 break;
3940 /* We add a trailing '\0' to ease parsing */
3941 cstr_ccat(&tokcstr, '\0');
3942 tokc.cstr = &tokcstr;
3943 tok = TOK_PPNUM;
3944 break;
3945 case '.':
3946 /* special dot handling because it can also start a number */
3947 PEEKC(c, p);
3948 if (isnum(c)) {
3949 cstr_reset(&tokcstr);
3950 cstr_ccat(&tokcstr, '.');
3951 goto parse_num;
3952 } else if (c == '.') {
3953 PEEKC(c, p);
3954 if (c != '.')
3955 expect("'.'");
3956 PEEKC(c, p);
3957 tok = TOK_DOTS;
3958 } else {
3959 tok = '.';
3961 break;
3962 case '\'':
3963 case '\"':
3964 is_long = 0;
3965 str_const:
3967 CString str;
3968 int sep;
3970 sep = c;
3972 /* parse the string */
3973 cstr_new(&str);
3974 p = parse_pp_string(p, sep, &str);
3975 cstr_ccat(&str, '\0');
3977 /* eval the escape (should be done as TOK_PPNUM) */
3978 cstr_reset(&tokcstr);
3979 parse_escape_string(&tokcstr, str.data, is_long);
3980 cstr_free(&str);
3982 if (sep == '\'') {
3983 int char_size;
3984 /* XXX: make it portable */
3985 if (!is_long)
3986 char_size = 1;
3987 else
3988 char_size = sizeof(nwchar_t);
3989 if (tokcstr.size <= char_size)
3990 error("empty character constant");
3991 if (tokcstr.size > 2 * char_size)
3992 warning("multi-character character constant");
3993 if (!is_long) {
3994 tokc.i = *(int8_t *)tokcstr.data;
3995 tok = TOK_CCHAR;
3996 } else {
3997 tokc.i = *(nwchar_t *)tokcstr.data;
3998 tok = TOK_LCHAR;
4000 } else {
4001 tokc.cstr = &tokcstr;
4002 if (!is_long)
4003 tok = TOK_STR;
4004 else
4005 tok = TOK_LSTR;
4008 break;
4010 case '<':
4011 PEEKC(c, p);
4012 if (c == '=') {
4013 p++;
4014 tok = TOK_LE;
4015 } else if (c == '<') {
4016 PEEKC(c, p);
4017 if (c == '=') {
4018 p++;
4019 tok = TOK_A_SHL;
4020 } else {
4021 tok = TOK_SHL;
4023 } else {
4024 tok = TOK_LT;
4026 break;
4028 case '>':
4029 PEEKC(c, p);
4030 if (c == '=') {
4031 p++;
4032 tok = TOK_GE;
4033 } else if (c == '>') {
4034 PEEKC(c, p);
4035 if (c == '=') {
4036 p++;
4037 tok = TOK_A_SAR;
4038 } else {
4039 tok = TOK_SAR;
4041 } else {
4042 tok = TOK_GT;
4044 break;
4046 case '&':
4047 PEEKC(c, p);
4048 if (c == '&') {
4049 p++;
4050 tok = TOK_LAND;
4051 } else if (c == '=') {
4052 p++;
4053 tok = TOK_A_AND;
4054 } else {
4055 tok = '&';
4057 break;
4059 case '|':
4060 PEEKC(c, p);
4061 if (c == '|') {
4062 p++;
4063 tok = TOK_LOR;
4064 } else if (c == '=') {
4065 p++;
4066 tok = TOK_A_OR;
4067 } else {
4068 tok = '|';
4070 break;
4072 case '+':
4073 PEEKC(c, p);
4074 if (c == '+') {
4075 p++;
4076 tok = TOK_INC;
4077 } else if (c == '=') {
4078 p++;
4079 tok = TOK_A_ADD;
4080 } else {
4081 tok = '+';
4083 break;
4085 case '-':
4086 PEEKC(c, p);
4087 if (c == '-') {
4088 p++;
4089 tok = TOK_DEC;
4090 } else if (c == '=') {
4091 p++;
4092 tok = TOK_A_SUB;
4093 } else if (c == '>') {
4094 p++;
4095 tok = TOK_ARROW;
4096 } else {
4097 tok = '-';
4099 break;
4101 PARSE2('!', '!', '=', TOK_NE)
4102 PARSE2('=', '=', '=', TOK_EQ)
4103 PARSE2('*', '*', '=', TOK_A_MUL)
4104 PARSE2('%', '%', '=', TOK_A_MOD)
4105 PARSE2('^', '^', '=', TOK_A_XOR)
4107 /* comments or operator */
4108 case '/':
4109 PEEKC(c, p);
4110 if (c == '*') {
4111 p = parse_comment(p);
4112 goto redo_no_start;
4113 } else if (c == '/') {
4114 p = parse_line_comment(p);
4115 goto redo_no_start;
4116 } else if (c == '=') {
4117 p++;
4118 tok = TOK_A_DIV;
4119 } else {
4120 tok = '/';
4122 break;
4124 /* simple tokens */
4125 case '(':
4126 case ')':
4127 case '[':
4128 case ']':
4129 case '{':
4130 case '}':
4131 case ',':
4132 case ';':
4133 case ':':
4134 case '?':
4135 case '~':
4136 case '$': /* only used in assembler */
4137 case '@': /* dito */
4138 tok = c;
4139 p++;
4140 break;
4141 default:
4142 error("unrecognized character \\x%02x", c);
4143 break;
4145 tok_flags = 0;
4146 keep_tok_flags:
4147 file->buf_ptr = p;
4148 #if defined(PARSE_DEBUG)
4149 printf("token = %s\n", get_tok_str(tok, &tokc));
4150 #endif
4153 /* return next token without macro substitution. Can read input from
4154 macro_ptr buffer */
4155 static void next_nomacro_spc(void)
4157 if (macro_ptr) {
4158 redo:
4159 tok = *macro_ptr;
4160 if (tok) {
4161 TOK_GET(tok, macro_ptr, tokc);
4162 if (tok == TOK_LINENUM) {
4163 file->line_num = tokc.i;
4164 goto redo;
4167 } else {
4168 next_nomacro1();
4172 static void next_nomacro(void)
4174 do {
4175 next_nomacro_spc();
4176 } while (is_space(tok));
4179 /* substitute args in macro_str and return allocated string */
4180 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
4182 int *st, last_tok, t, spc;
4183 Sym *s;
4184 CValue cval;
4185 TokenString str;
4186 CString cstr;
4188 tok_str_new(&str);
4189 last_tok = 0;
4190 while(1) {
4191 TOK_GET(t, macro_str, cval);
4192 if (!t)
4193 break;
4194 if (t == '#') {
4195 /* stringize */
4196 TOK_GET(t, macro_str, cval);
4197 if (!t)
4198 break;
4199 s = sym_find2(args, t);
4200 if (s) {
4201 cstr_new(&cstr);
4202 st = (int *)s->c;
4203 spc = 0;
4204 while (*st) {
4205 TOK_GET(t, st, cval);
4206 if (!check_space(t, &spc))
4207 cstr_cat(&cstr, get_tok_str(t, &cval));
4209 cstr.size -= spc;
4210 cstr_ccat(&cstr, '\0');
4211 #ifdef PP_DEBUG
4212 printf("stringize: %s\n", (char *)cstr.data);
4213 #endif
4214 /* add string */
4215 cval.cstr = &cstr;
4216 tok_str_add2(&str, TOK_STR, &cval);
4217 cstr_free(&cstr);
4218 } else {
4219 tok_str_add2(&str, t, &cval);
4221 } else if (t >= TOK_IDENT) {
4222 s = sym_find2(args, t);
4223 if (s) {
4224 st = (int *)s->c;
4225 /* if '##' is present before or after, no arg substitution */
4226 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
4227 /* special case for var arg macros : ## eats the
4228 ',' if empty VA_ARGS variable. */
4229 /* XXX: test of the ',' is not 100%
4230 reliable. should fix it to avoid security
4231 problems */
4232 if (gnu_ext && s->type.t &&
4233 last_tok == TOK_TWOSHARPS &&
4234 str.len >= 2 && str.str[str.len - 2] == ',') {
4235 if (*st == 0) {
4236 /* suppress ',' '##' */
4237 str.len -= 2;
4238 } else {
4239 /* suppress '##' and add variable */
4240 str.len--;
4241 goto add_var;
4243 } else {
4244 int t1;
4245 add_var:
4246 for(;;) {
4247 TOK_GET(t1, st, cval);
4248 if (!t1)
4249 break;
4250 tok_str_add2(&str, t1, &cval);
4253 } else {
4254 /* NOTE: the stream cannot be read when macro
4255 substituing an argument */
4256 macro_subst(&str, nested_list, st, NULL);
4258 } else {
4259 tok_str_add(&str, t);
4261 } else {
4262 tok_str_add2(&str, t, &cval);
4264 last_tok = t;
4266 tok_str_add(&str, 0);
4267 return str.str;
4270 static char const ab_month_name[12][4] =
4272 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4273 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4276 /* do macro substitution of current token with macro 's' and add
4277 result to (tok_str,tok_len). 'nested_list' is the list of all
4278 macros we got inside to avoid recursing. Return non zero if no
4279 substitution needs to be done */
4280 static int macro_subst_tok(TokenString *tok_str,
4281 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4283 Sym *args, *sa, *sa1;
4284 int mstr_allocated, parlevel, *mstr, t, t1, *p, spc;
4285 TokenString str;
4286 char *cstrval;
4287 CValue cval;
4288 CString cstr;
4289 char buf[32];
4291 /* if symbol is a macro, prepare substitution */
4292 /* special macros */
4293 if (tok == TOK___LINE__) {
4294 snprintf(buf, sizeof(buf), "%d", file->line_num);
4295 cstrval = buf;
4296 t1 = TOK_PPNUM;
4297 goto add_cstr1;
4298 } else if (tok == TOK___FILE__) {
4299 cstrval = file->filename;
4300 goto add_cstr;
4301 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4302 time_t ti;
4303 struct tm *tm;
4305 time(&ti);
4306 tm = localtime(&ti);
4307 if (tok == TOK___DATE__) {
4308 snprintf(buf, sizeof(buf), "%s %2d %d",
4309 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4310 } else {
4311 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4312 tm->tm_hour, tm->tm_min, tm->tm_sec);
4314 cstrval = buf;
4315 add_cstr:
4316 t1 = TOK_STR;
4317 add_cstr1:
4318 cstr_new(&cstr);
4319 cstr_cat(&cstr, cstrval);
4320 cstr_ccat(&cstr, '\0');
4321 cval.cstr = &cstr;
4322 tok_str_add2(tok_str, t1, &cval);
4323 cstr_free(&cstr);
4324 } else {
4325 mstr = (int *)s->c;
4326 mstr_allocated = 0;
4327 if (s->type.t == MACRO_FUNC) {
4328 /* NOTE: we do not use next_nomacro to avoid eating the
4329 next token. XXX: find better solution */
4330 redo:
4331 if (macro_ptr) {
4332 p = macro_ptr;
4333 while (is_space(t = *p) || TOK_LINEFEED == t)
4334 ++p;
4335 if (t == 0 && can_read_stream) {
4336 /* end of macro stream: we must look at the token
4337 after in the file */
4338 struct macro_level *ml = *can_read_stream;
4339 macro_ptr = NULL;
4340 if (ml)
4342 macro_ptr = ml->p;
4343 ml->p = NULL;
4344 *can_read_stream = ml -> prev;
4346 goto redo;
4348 } else {
4349 /* XXX: incorrect with comments */
4350 ch = file->buf_ptr[0];
4351 while (is_space(ch) || ch == '\n')
4352 cinp();
4353 t = ch;
4355 if (t != '(') /* no macro subst */
4356 return -1;
4358 /* argument macro */
4359 next_nomacro();
4360 next_nomacro();
4361 args = NULL;
4362 sa = s->next;
4363 /* NOTE: empty args are allowed, except if no args */
4364 for(;;) {
4365 /* handle '()' case */
4366 if (!args && !sa && tok == ')')
4367 break;
4368 if (!sa)
4369 error("macro '%s' used with too many args",
4370 get_tok_str(s->v, 0));
4371 tok_str_new(&str);
4372 parlevel = spc = 0;
4373 /* NOTE: non zero sa->t indicates VA_ARGS */
4374 while ((parlevel > 0 ||
4375 (tok != ')' &&
4376 (tok != ',' || sa->type.t))) &&
4377 tok != -1) {
4378 if (tok == '(')
4379 parlevel++;
4380 else if (tok == ')')
4381 parlevel--;
4382 if (tok == TOK_LINEFEED)
4383 tok = ' ';
4384 if (!check_space(tok, &spc))
4385 tok_str_add2(&str, tok, &tokc);
4386 next_nomacro_spc();
4388 str.len -= spc;
4389 tok_str_add(&str, 0);
4390 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str);
4391 sa = sa->next;
4392 if (tok == ')') {
4393 /* special case for gcc var args: add an empty
4394 var arg argument if it is omitted */
4395 if (sa && sa->type.t && gnu_ext)
4396 continue;
4397 else
4398 break;
4400 if (tok != ',')
4401 expect(",");
4402 next_nomacro();
4404 if (sa) {
4405 error("macro '%s' used with too few args",
4406 get_tok_str(s->v, 0));
4409 /* now subst each arg */
4410 mstr = macro_arg_subst(nested_list, mstr, args);
4411 /* free memory */
4412 sa = args;
4413 while (sa) {
4414 sa1 = sa->prev;
4415 tok_str_free((int *)sa->c);
4416 sym_free(sa);
4417 sa = sa1;
4419 mstr_allocated = 1;
4421 sym_push2(nested_list, s->v, 0, 0);
4422 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4423 /* pop nested defined symbol */
4424 sa1 = *nested_list;
4425 *nested_list = sa1->prev;
4426 sym_free(sa1);
4427 if (mstr_allocated)
4428 tok_str_free(mstr);
4430 return 0;
4433 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4434 return the resulting string (which must be freed). */
4435 static inline int *macro_twosharps(const int *macro_str)
4437 TokenSym *ts;
4438 const int *ptr, *saved_macro_ptr;
4439 int t;
4440 const char *p1, *p2;
4441 CValue cval;
4442 TokenString macro_str1;
4443 CString cstr;
4445 /* we search the first '##' */
4446 for(ptr = macro_str;;) {
4447 TOK_GET(t, ptr, cval);
4448 if (t == TOK_TWOSHARPS)
4449 break;
4450 /* nothing more to do if end of string */
4451 if (t == 0)
4452 return NULL;
4455 /* we saw '##', so we need more processing to handle it */
4456 cstr_new(&cstr);
4457 tok_str_new(&macro_str1);
4458 saved_macro_ptr = macro_ptr;
4459 /* XXX: get rid of the use of macro_ptr here */
4460 macro_ptr = (int *)macro_str;
4461 for(;;) {
4462 next_nomacro_spc();
4463 if (tok == 0)
4464 break;
4465 if (tok == TOK_TWOSHARPS)
4466 continue;
4467 while (*macro_ptr == TOK_TWOSHARPS) {
4468 t = *++macro_ptr;
4469 if (t && t != TOK_TWOSHARPS) {
4470 TOK_GET(t, macro_ptr, cval);
4471 /* We concatenate the two tokens if we have an
4472 identifier or a preprocessing number */
4473 cstr_reset(&cstr);
4474 p1 = get_tok_str(tok, &tokc);
4475 cstr_cat(&cstr, p1);
4476 p2 = get_tok_str(t, &cval);
4477 cstr_cat(&cstr, p2);
4478 cstr_ccat(&cstr, '\0');
4480 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4481 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4482 if (tok == TOK_PPNUM) {
4483 /* if number, then create a number token */
4484 /* NOTE: no need to allocate because
4485 tok_str_add2() does it */
4486 cstr_reset(&tokcstr);
4487 tokcstr = cstr;
4488 cstr_new(&cstr);
4489 tokc.cstr = &tokcstr;
4490 } else {
4491 /* if identifier, we must do a test to
4492 validate we have a correct identifier */
4493 if (t == TOK_PPNUM) {
4494 const char *p;
4495 int c;
4497 p = p2;
4498 for(;;) {
4499 c = *p;
4500 if (c == '\0')
4501 break;
4502 p++;
4503 if (!isnum(c) && !isid(c))
4504 goto error_pasting;
4507 ts = tok_alloc(cstr.data, strlen(cstr.data));
4508 tok = ts->tok; /* modify current token */
4510 } else {
4511 const char *str = cstr.data;
4512 const unsigned char *q;
4514 /* we look for a valid token */
4515 /* XXX: do more extensive checks */
4516 if (!strcmp(str, ">>=")) {
4517 tok = TOK_A_SAR;
4518 } else if (!strcmp(str, "<<=")) {
4519 tok = TOK_A_SHL;
4520 } else if (strlen(str) == 2) {
4521 /* search in two bytes table */
4522 q = tok_two_chars;
4523 for(;;) {
4524 if (!*q)
4525 goto error_pasting;
4526 if (q[0] == str[0] && q[1] == str[1])
4527 break;
4528 q += 3;
4530 tok = q[2];
4531 } else {
4532 error_pasting:
4533 /* NOTE: because get_tok_str use a static buffer,
4534 we must save it */
4535 cstr_reset(&cstr);
4536 p1 = get_tok_str(tok, &tokc);
4537 cstr_cat(&cstr, p1);
4538 cstr_ccat(&cstr, '\0');
4539 p2 = get_tok_str(t, &cval);
4540 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4541 /* cannot merge tokens: just add them separately */
4542 tok_str_add2(&macro_str1, tok, &tokc);
4543 /* XXX: free associated memory ? */
4544 tok = t;
4545 tokc = cval;
4550 tok_str_add2(&macro_str1, tok, &tokc);
4552 macro_ptr = (int *)saved_macro_ptr;
4553 cstr_free(&cstr);
4554 tok_str_add(&macro_str1, 0);
4555 return macro_str1.str;
4559 /* do macro substitution of macro_str and add result to
4560 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4561 inside to avoid recursing. */
4562 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4563 const int *macro_str, struct macro_level ** can_read_stream)
4565 Sym *s;
4566 int *macro_str1;
4567 const int *ptr;
4568 int t, ret, spc;
4569 CValue cval;
4570 struct macro_level ml;
4572 /* first scan for '##' operator handling */
4573 ptr = macro_str;
4574 macro_str1 = macro_twosharps(ptr);
4575 if (macro_str1)
4576 ptr = macro_str1;
4577 spc = 0;
4578 while (1) {
4579 /* NOTE: ptr == NULL can only happen if tokens are read from
4580 file stream due to a macro function call */
4581 if (ptr == NULL)
4582 break;
4583 TOK_GET(t, ptr, cval);
4584 if (t == 0)
4585 break;
4586 s = define_find(t);
4587 if (s != NULL) {
4588 /* if nested substitution, do nothing */
4589 if (sym_find2(*nested_list, t))
4590 goto no_subst;
4591 ml.p = macro_ptr;
4592 if (can_read_stream)
4593 ml.prev = *can_read_stream, *can_read_stream = &ml;
4594 macro_ptr = (int *)ptr;
4595 tok = t;
4596 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4597 ptr = (int *)macro_ptr;
4598 macro_ptr = ml.p;
4599 if (can_read_stream && *can_read_stream == &ml)
4600 *can_read_stream = ml.prev;
4601 if (ret != 0)
4602 goto no_subst;
4603 } else {
4604 no_subst:
4605 if (!check_space(t, &spc))
4606 tok_str_add2(tok_str, t, &cval);
4609 if (macro_str1)
4610 tok_str_free(macro_str1);
4613 /* return next token with macro substitution */
4614 static void next(void)
4616 Sym *nested_list, *s;
4617 TokenString str;
4618 struct macro_level *ml;
4620 redo:
4621 if (parse_flags & PARSE_FLAG_SPACES)
4622 next_nomacro_spc();
4623 else
4624 next_nomacro();
4625 if (!macro_ptr) {
4626 /* if not reading from macro substituted string, then try
4627 to substitute macros */
4628 if (tok >= TOK_IDENT &&
4629 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4630 s = define_find(tok);
4631 if (s) {
4632 /* we have a macro: we try to substitute */
4633 tok_str_new(&str);
4634 nested_list = NULL;
4635 ml = NULL;
4636 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4637 /* substitution done, NOTE: maybe empty */
4638 tok_str_add(&str, 0);
4639 macro_ptr = str.str;
4640 macro_ptr_allocated = str.str;
4641 goto redo;
4645 } else {
4646 if (tok == 0) {
4647 /* end of macro or end of unget buffer */
4648 if (unget_buffer_enabled) {
4649 macro_ptr = unget_saved_macro_ptr;
4650 unget_buffer_enabled = 0;
4651 } else {
4652 /* end of macro string: free it */
4653 tok_str_free(macro_ptr_allocated);
4654 macro_ptr = NULL;
4656 goto redo;
4660 /* convert preprocessor tokens into C tokens */
4661 if (tok == TOK_PPNUM &&
4662 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4663 parse_number((char *)tokc.cstr->data);
4667 /* push back current token and set current token to 'last_tok'. Only
4668 identifier case handled for labels. */
4669 static inline void unget_tok(int last_tok)
4671 int i, n;
4672 int *q;
4673 unget_saved_macro_ptr = macro_ptr;
4674 unget_buffer_enabled = 1;
4675 q = unget_saved_buffer;
4676 macro_ptr = q;
4677 *q++ = tok;
4678 n = tok_ext_size(tok) - 1;
4679 for(i=0;i<n;i++)
4680 *q++ = tokc.tab[i];
4681 *q = 0; /* end of token string */
4682 tok = last_tok;
4686 void swap(int *p, int *q)
4688 int t;
4689 t = *p;
4690 *p = *q;
4691 *q = t;
4694 void vsetc(CType *type, int r, CValue *vc)
4696 int v;
4698 if (vtop >= vstack + (VSTACK_SIZE - 1))
4699 error("memory full");
4700 /* cannot let cpu flags if other instruction are generated. Also
4701 avoid leaving VT_JMP anywhere except on the top of the stack
4702 because it would complicate the code generator. */
4703 if (vtop >= vstack) {
4704 v = vtop->r & VT_VALMASK;
4705 if (v == VT_CMP || (v & ~1) == VT_JMP)
4706 gv(RC_INT);
4708 vtop++;
4709 vtop->type = *type;
4710 vtop->r = r;
4711 vtop->r2 = VT_CONST;
4712 vtop->c = *vc;
4715 /* push integer constant */
4716 void vpushi(int v)
4718 CValue cval;
4719 cval.i = v;
4720 vsetc(&int_type, VT_CONST, &cval);
4723 /* push long long constant */
4724 void vpushll(long long v)
4726 CValue cval;
4727 CType ctype;
4728 ctype.t = VT_LLONG;
4729 cval.ull = v;
4730 vsetc(&ctype, VT_CONST, &cval);
4733 /* Return a static symbol pointing to a section */
4734 static Sym *get_sym_ref(CType *type, Section *sec,
4735 unsigned long offset, unsigned long size)
4737 int v;
4738 Sym *sym;
4740 v = anon_sym++;
4741 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4742 sym->type.ref = type->ref;
4743 sym->r = VT_CONST | VT_SYM;
4744 put_extern_sym(sym, sec, offset, size);
4745 return sym;
4748 /* push a reference to a section offset by adding a dummy symbol */
4749 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4751 CValue cval;
4753 cval.ul = 0;
4754 vsetc(type, VT_CONST | VT_SYM, &cval);
4755 vtop->sym = get_sym_ref(type, sec, offset, size);
4758 /* define a new external reference to a symbol 'v' of type 'u' */
4759 static Sym *external_global_sym(int v, CType *type, int r)
4761 Sym *s;
4763 s = sym_find(v);
4764 if (!s) {
4765 /* push forward reference */
4766 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4767 s->type.ref = type->ref;
4768 s->r = r | VT_CONST | VT_SYM;
4770 return s;
4773 /* define a new external reference to a symbol 'v' of type 'u' */
4774 static Sym *external_sym(int v, CType *type, int r)
4776 Sym *s;
4778 s = sym_find(v);
4779 if (!s) {
4780 /* push forward reference */
4781 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4782 s->type.t |= VT_EXTERN;
4783 } else {
4784 if (!is_compatible_types(&s->type, type))
4785 error("incompatible types for redefinition of '%s'",
4786 get_tok_str(v, NULL));
4788 return s;
4791 /* push a reference to global symbol v */
4792 static void vpush_global_sym(CType *type, int v)
4794 Sym *sym;
4795 CValue cval;
4797 sym = external_global_sym(v, type, 0);
4798 cval.ul = 0;
4799 vsetc(type, VT_CONST | VT_SYM, &cval);
4800 vtop->sym = sym;
4803 void vset(CType *type, int r, int v)
4805 CValue cval;
4807 cval.i = v;
4808 vsetc(type, r, &cval);
4811 void vseti(int r, int v)
4813 CType type;
4814 type.t = VT_INT;
4815 vset(&type, r, v);
4818 void vswap(void)
4820 SValue tmp;
4822 tmp = vtop[0];
4823 vtop[0] = vtop[-1];
4824 vtop[-1] = tmp;
4827 void vpushv(SValue *v)
4829 if (vtop >= vstack + (VSTACK_SIZE - 1))
4830 error("memory full");
4831 vtop++;
4832 *vtop = *v;
4835 void vdup(void)
4837 vpushv(vtop);
4840 /* save r to the memory stack, and mark it as being free */
4841 void save_reg(int r)
4843 int l, saved, size, align;
4844 SValue *p, sv;
4845 CType *type;
4847 /* modify all stack values */
4848 saved = 0;
4849 l = 0;
4850 for(p=vstack;p<=vtop;p++) {
4851 if ((p->r & VT_VALMASK) == r ||
4852 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4853 /* must save value on stack if not already done */
4854 if (!saved) {
4855 /* NOTE: must reload 'r' because r might be equal to r2 */
4856 r = p->r & VT_VALMASK;
4857 /* store register in the stack */
4858 type = &p->type;
4859 if ((p->r & VT_LVAL) ||
4860 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4861 #ifdef TCC_TARGET_X86_64
4862 type = &char_pointer_type;
4863 #else
4864 type = &int_type;
4865 #endif
4866 size = type_size(type, &align);
4867 loc = (loc - size) & -align;
4868 sv.type.t = type->t;
4869 sv.r = VT_LOCAL | VT_LVAL;
4870 sv.c.ul = loc;
4871 store(r, &sv);
4872 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
4873 /* x86 specific: need to pop fp register ST0 if saved */
4874 if (r == TREG_ST0) {
4875 o(0xd9dd); /* fstp %st(1) */
4877 #endif
4878 #ifndef TCC_TARGET_X86_64
4879 /* special long long case */
4880 if ((type->t & VT_BTYPE) == VT_LLONG) {
4881 sv.c.ul += 4;
4882 store(p->r2, &sv);
4884 #endif
4885 l = loc;
4886 saved = 1;
4888 /* mark that stack entry as being saved on the stack */
4889 if (p->r & VT_LVAL) {
4890 /* also clear the bounded flag because the
4891 relocation address of the function was stored in
4892 p->c.ul */
4893 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4894 } else {
4895 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4897 p->r2 = VT_CONST;
4898 p->c.ul = l;
4903 /* find a register of class 'rc2' with at most one reference on stack.
4904 * If none, call get_reg(rc) */
4905 int get_reg_ex(int rc, int rc2)
4907 int r;
4908 SValue *p;
4910 for(r=0;r<NB_REGS;r++) {
4911 if (reg_classes[r] & rc2) {
4912 int n;
4913 n=0;
4914 for(p = vstack; p <= vtop; p++) {
4915 if ((p->r & VT_VALMASK) == r ||
4916 (p->r2 & VT_VALMASK) == r)
4917 n++;
4919 if (n <= 1)
4920 return r;
4923 return get_reg(rc);
4926 /* find a free register of class 'rc'. If none, save one register */
4927 int get_reg(int rc)
4929 int r;
4930 SValue *p;
4932 /* find a free register */
4933 for(r=0;r<NB_REGS;r++) {
4934 if (reg_classes[r] & rc) {
4935 for(p=vstack;p<=vtop;p++) {
4936 if ((p->r & VT_VALMASK) == r ||
4937 (p->r2 & VT_VALMASK) == r)
4938 goto notfound;
4940 return r;
4942 notfound: ;
4945 /* no register left : free the first one on the stack (VERY
4946 IMPORTANT to start from the bottom to ensure that we don't
4947 spill registers used in gen_opi()) */
4948 for(p=vstack;p<=vtop;p++) {
4949 r = p->r & VT_VALMASK;
4950 if (r < VT_CONST && (reg_classes[r] & rc))
4951 goto save_found;
4952 /* also look at second register (if long long) */
4953 r = p->r2 & VT_VALMASK;
4954 if (r < VT_CONST && (reg_classes[r] & rc)) {
4955 save_found:
4956 save_reg(r);
4957 return r;
4960 /* Should never comes here */
4961 return -1;
4964 /* save registers up to (vtop - n) stack entry */
4965 void save_regs(int n)
4967 int r;
4968 SValue *p, *p1;
4969 p1 = vtop - n;
4970 for(p = vstack;p <= p1; p++) {
4971 r = p->r & VT_VALMASK;
4972 if (r < VT_CONST) {
4973 save_reg(r);
4978 /* move register 's' to 'r', and flush previous value of r to memory
4979 if needed */
4980 void move_reg(int r, int s)
4982 SValue sv;
4984 if (r != s) {
4985 save_reg(r);
4986 sv.type.t = VT_INT;
4987 sv.r = s;
4988 sv.c.ul = 0;
4989 load(r, &sv);
4993 /* get address of vtop (vtop MUST BE an lvalue) */
4994 void gaddrof(void)
4996 vtop->r &= ~VT_LVAL;
4997 /* tricky: if saved lvalue, then we can go back to lvalue */
4998 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4999 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
5002 #ifdef CONFIG_TCC_BCHECK
5003 /* generate lvalue bound code */
5004 void gbound(void)
5006 int lval_type;
5007 CType type1;
5009 vtop->r &= ~VT_MUSTBOUND;
5010 /* if lvalue, then use checking code before dereferencing */
5011 if (vtop->r & VT_LVAL) {
5012 /* if not VT_BOUNDED value, then make one */
5013 if (!(vtop->r & VT_BOUNDED)) {
5014 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
5015 /* must save type because we must set it to int to get pointer */
5016 type1 = vtop->type;
5017 vtop->type.t = VT_INT;
5018 gaddrof();
5019 vpushi(0);
5020 gen_bounded_ptr_add();
5021 vtop->r |= lval_type;
5022 vtop->type = type1;
5024 /* then check for dereferencing */
5025 gen_bounded_ptr_deref();
5028 #endif
5030 /* store vtop a register belonging to class 'rc'. lvalues are
5031 converted to values. Cannot be used if cannot be converted to
5032 register value (such as structures). */
5033 int gv(int rc)
5035 int r, rc2, bit_pos, bit_size, size, align, i;
5037 /* NOTE: get_reg can modify vstack[] */
5038 if (vtop->type.t & VT_BITFIELD) {
5039 CType type;
5040 int bits = 32;
5041 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
5042 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5043 /* remove bit field info to avoid loops */
5044 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5045 /* cast to int to propagate signedness in following ops */
5046 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
5047 type.t = VT_LLONG;
5048 bits = 64;
5049 } else
5050 type.t = VT_INT;
5051 if((vtop->type.t & VT_UNSIGNED) ||
5052 (vtop->type.t & VT_BTYPE) == VT_BOOL)
5053 type.t |= VT_UNSIGNED;
5054 gen_cast(&type);
5055 /* generate shifts */
5056 vpushi(bits - (bit_pos + bit_size));
5057 gen_op(TOK_SHL);
5058 vpushi(bits - bit_size);
5059 /* NOTE: transformed to SHR if unsigned */
5060 gen_op(TOK_SAR);
5061 r = gv(rc);
5062 } else {
5063 if (is_float(vtop->type.t) &&
5064 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5065 Sym *sym;
5066 int *ptr;
5067 unsigned long offset;
5068 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5069 CValue check;
5070 #endif
5072 /* XXX: unify with initializers handling ? */
5073 /* CPUs usually cannot use float constants, so we store them
5074 generically in data segment */
5075 size = type_size(&vtop->type, &align);
5076 offset = (data_section->data_offset + align - 1) & -align;
5077 data_section->data_offset = offset;
5078 /* XXX: not portable yet */
5079 #if defined(__i386__) || defined(__x86_64__)
5080 /* Zero pad x87 tenbyte long doubles */
5081 if (size == LDOUBLE_SIZE)
5082 vtop->c.tab[2] &= 0xffff;
5083 #endif
5084 ptr = section_ptr_add(data_section, size);
5085 size = size >> 2;
5086 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5087 check.d = 1;
5088 if(check.tab[0])
5089 for(i=0;i<size;i++)
5090 ptr[i] = vtop->c.tab[size-1-i];
5091 else
5092 #endif
5093 for(i=0;i<size;i++)
5094 ptr[i] = vtop->c.tab[i];
5095 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
5096 vtop->r |= VT_LVAL | VT_SYM;
5097 vtop->sym = sym;
5098 vtop->c.ul = 0;
5100 #ifdef CONFIG_TCC_BCHECK
5101 if (vtop->r & VT_MUSTBOUND)
5102 gbound();
5103 #endif
5105 r = vtop->r & VT_VALMASK;
5106 rc2 = RC_INT;
5107 if (rc == RC_IRET)
5108 rc2 = RC_LRET;
5109 /* need to reload if:
5110 - constant
5111 - lvalue (need to dereference pointer)
5112 - already a register, but not in the right class */
5113 if (r >= VT_CONST ||
5114 (vtop->r & VT_LVAL) ||
5115 !(reg_classes[r] & rc) ||
5116 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
5117 !(reg_classes[vtop->r2] & rc2))) {
5118 r = get_reg(rc);
5119 #ifndef TCC_TARGET_X86_64
5120 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
5121 int r2;
5122 unsigned long long ll;
5123 /* two register type load : expand to two words
5124 temporarily */
5125 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5126 /* load constant */
5127 ll = vtop->c.ull;
5128 vtop->c.ui = ll; /* first word */
5129 load(r, vtop);
5130 vtop->r = r; /* save register value */
5131 vpushi(ll >> 32); /* second word */
5132 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
5133 (vtop->r & VT_LVAL)) {
5134 /* We do not want to modifier the long long
5135 pointer here, so the safest (and less
5136 efficient) is to save all the other registers
5137 in the stack. XXX: totally inefficient. */
5138 save_regs(1);
5139 /* load from memory */
5140 load(r, vtop);
5141 vdup();
5142 vtop[-1].r = r; /* save register value */
5143 /* increment pointer to get second word */
5144 vtop->type.t = VT_INT;
5145 gaddrof();
5146 vpushi(4);
5147 gen_op('+');
5148 vtop->r |= VT_LVAL;
5149 } else {
5150 /* move registers */
5151 load(r, vtop);
5152 vdup();
5153 vtop[-1].r = r; /* save register value */
5154 vtop->r = vtop[-1].r2;
5156 /* allocate second register */
5157 r2 = get_reg(rc2);
5158 load(r2, vtop);
5159 vpop();
5160 /* write second register */
5161 vtop->r2 = r2;
5162 } else
5163 #endif
5164 if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
5165 int t1, t;
5166 /* lvalue of scalar type : need to use lvalue type
5167 because of possible cast */
5168 t = vtop->type.t;
5169 t1 = t;
5170 /* compute memory access type */
5171 if (vtop->r & VT_LVAL_BYTE)
5172 t = VT_BYTE;
5173 else if (vtop->r & VT_LVAL_SHORT)
5174 t = VT_SHORT;
5175 if (vtop->r & VT_LVAL_UNSIGNED)
5176 t |= VT_UNSIGNED;
5177 vtop->type.t = t;
5178 load(r, vtop);
5179 /* restore wanted type */
5180 vtop->type.t = t1;
5181 } else {
5182 /* one register type load */
5183 load(r, vtop);
5186 vtop->r = r;
5187 #ifdef TCC_TARGET_C67
5188 /* uses register pairs for doubles */
5189 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5190 vtop->r2 = r+1;
5191 #endif
5193 return r;
5196 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
5197 void gv2(int rc1, int rc2)
5199 int v;
5201 /* generate more generic register first. But VT_JMP or VT_CMP
5202 values must be generated first in all cases to avoid possible
5203 reload errors */
5204 v = vtop[0].r & VT_VALMASK;
5205 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
5206 vswap();
5207 gv(rc1);
5208 vswap();
5209 gv(rc2);
5210 /* test if reload is needed for first register */
5211 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
5212 vswap();
5213 gv(rc1);
5214 vswap();
5216 } else {
5217 gv(rc2);
5218 vswap();
5219 gv(rc1);
5220 vswap();
5221 /* test if reload is needed for first register */
5222 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
5223 gv(rc2);
5228 /* wrapper around RC_FRET to return a register by type */
5229 int rc_fret(int t)
5231 #ifdef TCC_TARGET_X86_64
5232 if (t == VT_LDOUBLE) {
5233 return RC_ST0;
5235 #endif
5236 return RC_FRET;
5239 /* wrapper around REG_FRET to return a register by type */
5240 int reg_fret(int t)
5242 #ifdef TCC_TARGET_X86_64
5243 if (t == VT_LDOUBLE) {
5244 return TREG_ST0;
5246 #endif
5247 return REG_FRET;
5250 /* expand long long on stack in two int registers */
5251 void lexpand(void)
5253 int u;
5255 u = vtop->type.t & VT_UNSIGNED;
5256 gv(RC_INT);
5257 vdup();
5258 vtop[0].r = vtop[-1].r2;
5259 vtop[0].r2 = VT_CONST;
5260 vtop[-1].r2 = VT_CONST;
5261 vtop[0].type.t = VT_INT | u;
5262 vtop[-1].type.t = VT_INT | u;
5265 #ifdef TCC_TARGET_ARM
5266 /* expand long long on stack */
5267 void lexpand_nr(void)
5269 int u,v;
5271 u = vtop->type.t & VT_UNSIGNED;
5272 vdup();
5273 vtop->r2 = VT_CONST;
5274 vtop->type.t = VT_INT | u;
5275 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
5276 if (v == VT_CONST) {
5277 vtop[-1].c.ui = vtop->c.ull;
5278 vtop->c.ui = vtop->c.ull >> 32;
5279 vtop->r = VT_CONST;
5280 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
5281 vtop->c.ui += 4;
5282 vtop->r = vtop[-1].r;
5283 } else if (v > VT_CONST) {
5284 vtop--;
5285 lexpand();
5286 } else
5287 vtop->r = vtop[-1].r2;
5288 vtop[-1].r2 = VT_CONST;
5289 vtop[-1].type.t = VT_INT | u;
5291 #endif
5293 /* build a long long from two ints */
5294 void lbuild(int t)
5296 gv2(RC_INT, RC_INT);
5297 vtop[-1].r2 = vtop[0].r;
5298 vtop[-1].type.t = t;
5299 vpop();
5302 /* rotate n first stack elements to the bottom
5303 I1 ... In -> I2 ... In I1 [top is right]
5305 void vrotb(int n)
5307 int i;
5308 SValue tmp;
5310 tmp = vtop[-n + 1];
5311 for(i=-n+1;i!=0;i++)
5312 vtop[i] = vtop[i+1];
5313 vtop[0] = tmp;
5316 /* rotate n first stack elements to the top
5317 I1 ... In -> In I1 ... I(n-1) [top is right]
5319 void vrott(int n)
5321 int i;
5322 SValue tmp;
5324 tmp = vtop[0];
5325 for(i = 0;i < n - 1; i++)
5326 vtop[-i] = vtop[-i - 1];
5327 vtop[-n + 1] = tmp;
5330 #ifdef TCC_TARGET_ARM
5331 /* like vrott but in other direction
5332 In ... I1 -> I(n-1) ... I1 In [top is right]
5334 void vnrott(int n)
5336 int i;
5337 SValue tmp;
5339 tmp = vtop[-n + 1];
5340 for(i = n - 1; i > 0; i--)
5341 vtop[-i] = vtop[-i + 1];
5342 vtop[0] = tmp;
5344 #endif
5346 /* pop stack value */
5347 void vpop(void)
5349 int v;
5350 v = vtop->r & VT_VALMASK;
5351 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
5352 /* for x86, we need to pop the FP stack */
5353 if (v == TREG_ST0 && !nocode_wanted) {
5354 o(0xd9dd); /* fstp %st(1) */
5355 } else
5356 #endif
5357 if (v == VT_JMP || v == VT_JMPI) {
5358 /* need to put correct jump if && or || without test */
5359 gsym(vtop->c.ul);
5361 vtop--;
5364 /* convert stack entry to register and duplicate its value in another
5365 register */
5366 void gv_dup(void)
5368 int rc, t, r, r1;
5369 SValue sv;
5371 t = vtop->type.t;
5372 if ((t & VT_BTYPE) == VT_LLONG) {
5373 lexpand();
5374 gv_dup();
5375 vswap();
5376 vrotb(3);
5377 gv_dup();
5378 vrotb(4);
5379 /* stack: H L L1 H1 */
5380 lbuild(t);
5381 vrotb(3);
5382 vrotb(3);
5383 vswap();
5384 lbuild(t);
5385 vswap();
5386 } else {
5387 /* duplicate value */
5388 rc = RC_INT;
5389 sv.type.t = VT_INT;
5390 if (is_float(t)) {
5391 rc = RC_FLOAT;
5392 #ifdef TCC_TARGET_X86_64
5393 if ((t & VT_BTYPE) == VT_LDOUBLE) {
5394 rc = RC_ST0;
5396 #endif
5397 sv.type.t = t;
5399 r = gv(rc);
5400 r1 = get_reg(rc);
5401 sv.r = r;
5402 sv.c.ul = 0;
5403 load(r1, &sv); /* move r to r1 */
5404 vdup();
5405 /* duplicates value */
5406 vtop->r = r1;
5410 #ifndef TCC_TARGET_X86_64
5411 /* generate CPU independent (unsigned) long long operations */
5412 void gen_opl(int op)
5414 int t, a, b, op1, c, i;
5415 int func;
5416 unsigned short reg_iret = REG_IRET;
5417 unsigned short reg_lret = REG_LRET;
5418 SValue tmp;
5420 switch(op) {
5421 case '/':
5422 case TOK_PDIV:
5423 func = TOK___divdi3;
5424 goto gen_func;
5425 case TOK_UDIV:
5426 func = TOK___udivdi3;
5427 goto gen_func;
5428 case '%':
5429 func = TOK___moddi3;
5430 goto gen_mod_func;
5431 case TOK_UMOD:
5432 func = TOK___umoddi3;
5433 gen_mod_func:
5434 #ifdef TCC_ARM_EABI
5435 reg_iret = TREG_R2;
5436 reg_lret = TREG_R3;
5437 #endif
5438 gen_func:
5439 /* call generic long long function */
5440 vpush_global_sym(&func_old_type, func);
5441 vrott(3);
5442 gfunc_call(2);
5443 vpushi(0);
5444 vtop->r = reg_iret;
5445 vtop->r2 = reg_lret;
5446 break;
5447 case '^':
5448 case '&':
5449 case '|':
5450 case '*':
5451 case '+':
5452 case '-':
5453 t = vtop->type.t;
5454 vswap();
5455 lexpand();
5456 vrotb(3);
5457 lexpand();
5458 /* stack: L1 H1 L2 H2 */
5459 tmp = vtop[0];
5460 vtop[0] = vtop[-3];
5461 vtop[-3] = tmp;
5462 tmp = vtop[-2];
5463 vtop[-2] = vtop[-3];
5464 vtop[-3] = tmp;
5465 vswap();
5466 /* stack: H1 H2 L1 L2 */
5467 if (op == '*') {
5468 vpushv(vtop - 1);
5469 vpushv(vtop - 1);
5470 gen_op(TOK_UMULL);
5471 lexpand();
5472 /* stack: H1 H2 L1 L2 ML MH */
5473 for(i=0;i<4;i++)
5474 vrotb(6);
5475 /* stack: ML MH H1 H2 L1 L2 */
5476 tmp = vtop[0];
5477 vtop[0] = vtop[-2];
5478 vtop[-2] = tmp;
5479 /* stack: ML MH H1 L2 H2 L1 */
5480 gen_op('*');
5481 vrotb(3);
5482 vrotb(3);
5483 gen_op('*');
5484 /* stack: ML MH M1 M2 */
5485 gen_op('+');
5486 gen_op('+');
5487 } else if (op == '+' || op == '-') {
5488 /* XXX: add non carry method too (for MIPS or alpha) */
5489 if (op == '+')
5490 op1 = TOK_ADDC1;
5491 else
5492 op1 = TOK_SUBC1;
5493 gen_op(op1);
5494 /* stack: H1 H2 (L1 op L2) */
5495 vrotb(3);
5496 vrotb(3);
5497 gen_op(op1 + 1); /* TOK_xxxC2 */
5498 } else {
5499 gen_op(op);
5500 /* stack: H1 H2 (L1 op L2) */
5501 vrotb(3);
5502 vrotb(3);
5503 /* stack: (L1 op L2) H1 H2 */
5504 gen_op(op);
5505 /* stack: (L1 op L2) (H1 op H2) */
5507 /* stack: L H */
5508 lbuild(t);
5509 break;
5510 case TOK_SAR:
5511 case TOK_SHR:
5512 case TOK_SHL:
5513 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5514 t = vtop[-1].type.t;
5515 vswap();
5516 lexpand();
5517 vrotb(3);
5518 /* stack: L H shift */
5519 c = (int)vtop->c.i;
5520 /* constant: simpler */
5521 /* NOTE: all comments are for SHL. the other cases are
5522 done by swaping words */
5523 vpop();
5524 if (op != TOK_SHL)
5525 vswap();
5526 if (c >= 32) {
5527 /* stack: L H */
5528 vpop();
5529 if (c > 32) {
5530 vpushi(c - 32);
5531 gen_op(op);
5533 if (op != TOK_SAR) {
5534 vpushi(0);
5535 } else {
5536 gv_dup();
5537 vpushi(31);
5538 gen_op(TOK_SAR);
5540 vswap();
5541 } else {
5542 vswap();
5543 gv_dup();
5544 /* stack: H L L */
5545 vpushi(c);
5546 gen_op(op);
5547 vswap();
5548 vpushi(32 - c);
5549 if (op == TOK_SHL)
5550 gen_op(TOK_SHR);
5551 else
5552 gen_op(TOK_SHL);
5553 vrotb(3);
5554 /* stack: L L H */
5555 vpushi(c);
5556 if (op == TOK_SHL)
5557 gen_op(TOK_SHL);
5558 else
5559 gen_op(TOK_SHR);
5560 gen_op('|');
5562 if (op != TOK_SHL)
5563 vswap();
5564 lbuild(t);
5565 } else {
5566 /* XXX: should provide a faster fallback on x86 ? */
5567 switch(op) {
5568 case TOK_SAR:
5569 func = TOK___ashrdi3;
5570 goto gen_func;
5571 case TOK_SHR:
5572 func = TOK___lshrdi3;
5573 goto gen_func;
5574 case TOK_SHL:
5575 func = TOK___ashldi3;
5576 goto gen_func;
5579 break;
5580 default:
5581 /* compare operations */
5582 t = vtop->type.t;
5583 vswap();
5584 lexpand();
5585 vrotb(3);
5586 lexpand();
5587 /* stack: L1 H1 L2 H2 */
5588 tmp = vtop[-1];
5589 vtop[-1] = vtop[-2];
5590 vtop[-2] = tmp;
5591 /* stack: L1 L2 H1 H2 */
5592 /* compare high */
5593 op1 = op;
5594 /* when values are equal, we need to compare low words. since
5595 the jump is inverted, we invert the test too. */
5596 if (op1 == TOK_LT)
5597 op1 = TOK_LE;
5598 else if (op1 == TOK_GT)
5599 op1 = TOK_GE;
5600 else if (op1 == TOK_ULT)
5601 op1 = TOK_ULE;
5602 else if (op1 == TOK_UGT)
5603 op1 = TOK_UGE;
5604 a = 0;
5605 b = 0;
5606 gen_op(op1);
5607 if (op1 != TOK_NE) {
5608 a = gtst(1, 0);
5610 if (op != TOK_EQ) {
5611 /* generate non equal test */
5612 /* XXX: NOT PORTABLE yet */
5613 if (a == 0) {
5614 b = gtst(0, 0);
5615 } else {
5616 #if defined(TCC_TARGET_I386)
5617 b = psym(0x850f, 0);
5618 #elif defined(TCC_TARGET_ARM)
5619 b = ind;
5620 o(0x1A000000 | encbranch(ind, 0, 1));
5621 #elif defined(TCC_TARGET_C67)
5622 error("not implemented");
5623 #else
5624 #error not supported
5625 #endif
5628 /* compare low. Always unsigned */
5629 op1 = op;
5630 if (op1 == TOK_LT)
5631 op1 = TOK_ULT;
5632 else if (op1 == TOK_LE)
5633 op1 = TOK_ULE;
5634 else if (op1 == TOK_GT)
5635 op1 = TOK_UGT;
5636 else if (op1 == TOK_GE)
5637 op1 = TOK_UGE;
5638 gen_op(op1);
5639 a = gtst(1, a);
5640 gsym(b);
5641 vseti(VT_JMPI, a);
5642 break;
5645 #endif
5647 /* handle integer constant optimizations and various machine
5648 independent opt */
5649 void gen_opic(int op)
5651 int c1, c2, t1, t2, n;
5652 SValue *v1, *v2;
5653 long long l1, l2;
5654 typedef unsigned long long U;
5656 v1 = vtop - 1;
5657 v2 = vtop;
5658 t1 = v1->type.t & VT_BTYPE;
5659 t2 = v2->type.t & VT_BTYPE;
5661 if (t1 == VT_LLONG)
5662 l1 = v1->c.ll;
5663 else if (v1->type.t & VT_UNSIGNED)
5664 l1 = v1->c.ui;
5665 else
5666 l1 = v1->c.i;
5668 if (t2 == VT_LLONG)
5669 l2 = v2->c.ll;
5670 else if (v2->type.t & VT_UNSIGNED)
5671 l2 = v2->c.ui;
5672 else
5673 l2 = v2->c.i;
5675 /* currently, we cannot do computations with forward symbols */
5676 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5677 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5678 if (c1 && c2) {
5679 switch(op) {
5680 case '+': l1 += l2; break;
5681 case '-': l1 -= l2; break;
5682 case '&': l1 &= l2; break;
5683 case '^': l1 ^= l2; break;
5684 case '|': l1 |= l2; break;
5685 case '*': l1 *= l2; break;
5687 case TOK_PDIV:
5688 case '/':
5689 case '%':
5690 case TOK_UDIV:
5691 case TOK_UMOD:
5692 /* if division by zero, generate explicit division */
5693 if (l2 == 0) {
5694 if (const_wanted)
5695 error("division by zero in constant");
5696 goto general_case;
5698 switch(op) {
5699 default: l1 /= l2; break;
5700 case '%': l1 %= l2; break;
5701 case TOK_UDIV: l1 = (U)l1 / l2; break;
5702 case TOK_UMOD: l1 = (U)l1 % l2; break;
5704 break;
5705 case TOK_SHL: l1 <<= l2; break;
5706 case TOK_SHR: l1 = (U)l1 >> l2; break;
5707 case TOK_SAR: l1 >>= l2; break;
5708 /* tests */
5709 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5710 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5711 case TOK_EQ: l1 = l1 == l2; break;
5712 case TOK_NE: l1 = l1 != l2; break;
5713 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5714 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5715 case TOK_LT: l1 = l1 < l2; break;
5716 case TOK_GE: l1 = l1 >= l2; break;
5717 case TOK_LE: l1 = l1 <= l2; break;
5718 case TOK_GT: l1 = l1 > l2; break;
5719 /* logical */
5720 case TOK_LAND: l1 = l1 && l2; break;
5721 case TOK_LOR: l1 = l1 || l2; break;
5722 default:
5723 goto general_case;
5725 v1->c.ll = l1;
5726 vtop--;
5727 } else {
5728 /* if commutative ops, put c2 as constant */
5729 if (c1 && (op == '+' || op == '&' || op == '^' ||
5730 op == '|' || op == '*')) {
5731 vswap();
5732 c2 = c1; //c = c1, c1 = c2, c2 = c;
5733 l2 = l1; //l = l1, l1 = l2, l2 = l;
5735 /* Filter out NOP operations like x*1, x-0, x&-1... */
5736 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5737 op == TOK_PDIV) &&
5738 l2 == 1) ||
5739 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5740 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5741 l2 == 0) ||
5742 (op == '&' &&
5743 l2 == -1))) {
5744 /* nothing to do */
5745 vtop--;
5746 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5747 /* try to use shifts instead of muls or divs */
5748 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5749 n = -1;
5750 while (l2) {
5751 l2 >>= 1;
5752 n++;
5754 vtop->c.ll = n;
5755 if (op == '*')
5756 op = TOK_SHL;
5757 else if (op == TOK_PDIV)
5758 op = TOK_SAR;
5759 else
5760 op = TOK_SHR;
5762 goto general_case;
5763 } else if (c2 && (op == '+' || op == '-') &&
5764 ((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5765 (VT_CONST | VT_SYM) ||
5766 (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
5767 /* symbol + constant case */
5768 if (op == '-')
5769 l2 = -l2;
5770 vtop--;
5771 vtop->c.ll += l2;
5772 } else {
5773 general_case:
5774 if (!nocode_wanted) {
5775 /* call low level op generator */
5776 if (t1 == VT_LLONG || t2 == VT_LLONG)
5777 gen_opl(op);
5778 else
5779 gen_opi(op);
5780 } else {
5781 vtop--;
5787 /* generate a floating point operation with constant propagation */
5788 void gen_opif(int op)
5790 int c1, c2;
5791 SValue *v1, *v2;
5792 long double f1, f2;
5794 v1 = vtop - 1;
5795 v2 = vtop;
5796 /* currently, we cannot do computations with forward symbols */
5797 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5798 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5799 if (c1 && c2) {
5800 if (v1->type.t == VT_FLOAT) {
5801 f1 = v1->c.f;
5802 f2 = v2->c.f;
5803 } else if (v1->type.t == VT_DOUBLE) {
5804 f1 = v1->c.d;
5805 f2 = v2->c.d;
5806 } else {
5807 f1 = v1->c.ld;
5808 f2 = v2->c.ld;
5811 /* NOTE: we only do constant propagation if finite number (not
5812 NaN or infinity) (ANSI spec) */
5813 if (!ieee_finite(f1) || !ieee_finite(f2))
5814 goto general_case;
5816 switch(op) {
5817 case '+': f1 += f2; break;
5818 case '-': f1 -= f2; break;
5819 case '*': f1 *= f2; break;
5820 case '/':
5821 if (f2 == 0.0) {
5822 if (const_wanted)
5823 error("division by zero in constant");
5824 goto general_case;
5826 f1 /= f2;
5827 break;
5828 /* XXX: also handles tests ? */
5829 default:
5830 goto general_case;
5832 /* XXX: overflow test ? */
5833 if (v1->type.t == VT_FLOAT) {
5834 v1->c.f = f1;
5835 } else if (v1->type.t == VT_DOUBLE) {
5836 v1->c.d = f1;
5837 } else {
5838 v1->c.ld = f1;
5840 vtop--;
5841 } else {
5842 general_case:
5843 if (!nocode_wanted) {
5844 gen_opf(op);
5845 } else {
5846 vtop--;
5851 static int pointed_size(CType *type)
5853 int align;
5854 return type_size(pointed_type(type), &align);
5857 static inline int is_null_pointer(SValue *p)
5859 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5860 return 0;
5861 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5862 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5865 static inline int is_integer_btype(int bt)
5867 return (bt == VT_BYTE || bt == VT_SHORT ||
5868 bt == VT_INT || bt == VT_LLONG);
5871 /* check types for comparison or substraction of pointers */
5872 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5874 CType *type1, *type2, tmp_type1, tmp_type2;
5875 int bt1, bt2;
5877 /* null pointers are accepted for all comparisons as gcc */
5878 if (is_null_pointer(p1) || is_null_pointer(p2))
5879 return;
5880 type1 = &p1->type;
5881 type2 = &p2->type;
5882 bt1 = type1->t & VT_BTYPE;
5883 bt2 = type2->t & VT_BTYPE;
5884 /* accept comparison between pointer and integer with a warning */
5885 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5886 if (op != TOK_LOR && op != TOK_LAND )
5887 warning("comparison between pointer and integer");
5888 return;
5891 /* both must be pointers or implicit function pointers */
5892 if (bt1 == VT_PTR) {
5893 type1 = pointed_type(type1);
5894 } else if (bt1 != VT_FUNC)
5895 goto invalid_operands;
5897 if (bt2 == VT_PTR) {
5898 type2 = pointed_type(type2);
5899 } else if (bt2 != VT_FUNC) {
5900 invalid_operands:
5901 error("invalid operands to binary %s", get_tok_str(op, NULL));
5903 if ((type1->t & VT_BTYPE) == VT_VOID ||
5904 (type2->t & VT_BTYPE) == VT_VOID)
5905 return;
5906 tmp_type1 = *type1;
5907 tmp_type2 = *type2;
5908 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5909 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5910 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5911 /* gcc-like error if '-' is used */
5912 if (op == '-')
5913 goto invalid_operands;
5914 else
5915 warning("comparison of distinct pointer types lacks a cast");
5919 /* generic gen_op: handles types problems */
5920 void gen_op(int op)
5922 int u, t1, t2, bt1, bt2, t;
5923 CType type1;
5925 t1 = vtop[-1].type.t;
5926 t2 = vtop[0].type.t;
5927 bt1 = t1 & VT_BTYPE;
5928 bt2 = t2 & VT_BTYPE;
5930 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5931 /* at least one operand is a pointer */
5932 /* relationnal op: must be both pointers */
5933 if (op >= TOK_ULT && op <= TOK_LOR) {
5934 check_comparison_pointer_types(vtop - 1, vtop, op);
5935 /* pointers are handled are unsigned */
5936 #ifdef TCC_TARGET_X86_64
5937 t = VT_LLONG | VT_UNSIGNED;
5938 #else
5939 t = VT_INT | VT_UNSIGNED;
5940 #endif
5941 goto std_op;
5943 /* if both pointers, then it must be the '-' op */
5944 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5945 if (op != '-')
5946 error("cannot use pointers here");
5947 check_comparison_pointer_types(vtop - 1, vtop, op);
5948 /* XXX: check that types are compatible */
5949 u = pointed_size(&vtop[-1].type);
5950 gen_opic(op);
5951 /* set to integer type */
5952 #ifdef TCC_TARGET_X86_64
5953 vtop->type.t = VT_LLONG;
5954 #else
5955 vtop->type.t = VT_INT;
5956 #endif
5957 vpushi(u);
5958 gen_op(TOK_PDIV);
5959 } else {
5960 /* exactly one pointer : must be '+' or '-'. */
5961 if (op != '-' && op != '+')
5962 error("cannot use pointers here");
5963 /* Put pointer as first operand */
5964 if (bt2 == VT_PTR) {
5965 vswap();
5966 swap(&t1, &t2);
5968 type1 = vtop[-1].type;
5969 #ifdef TCC_TARGET_X86_64
5970 vpushll(pointed_size(&vtop[-1].type));
5971 #else
5972 /* XXX: cast to int ? (long long case) */
5973 vpushi(pointed_size(&vtop[-1].type));
5974 #endif
5975 gen_op('*');
5976 #ifdef CONFIG_TCC_BCHECK
5977 /* if evaluating constant expression, no code should be
5978 generated, so no bound check */
5979 if (do_bounds_check && !const_wanted) {
5980 /* if bounded pointers, we generate a special code to
5981 test bounds */
5982 if (op == '-') {
5983 vpushi(0);
5984 vswap();
5985 gen_op('-');
5987 gen_bounded_ptr_add();
5988 } else
5989 #endif
5991 gen_opic(op);
5993 /* put again type if gen_opic() swaped operands */
5994 vtop->type = type1;
5996 } else if (is_float(bt1) || is_float(bt2)) {
5997 /* compute bigger type and do implicit casts */
5998 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5999 t = VT_LDOUBLE;
6000 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
6001 t = VT_DOUBLE;
6002 } else {
6003 t = VT_FLOAT;
6005 /* floats can only be used for a few operations */
6006 if (op != '+' && op != '-' && op != '*' && op != '/' &&
6007 (op < TOK_ULT || op > TOK_GT))
6008 error("invalid operands for binary operation");
6009 goto std_op;
6010 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
6011 /* cast to biggest op */
6012 t = VT_LLONG;
6013 /* convert to unsigned if it does not fit in a long long */
6014 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
6015 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
6016 t |= VT_UNSIGNED;
6017 goto std_op;
6018 } else {
6019 /* integer operations */
6020 t = VT_INT;
6021 /* convert to unsigned if it does not fit in an integer */
6022 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
6023 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
6024 t |= VT_UNSIGNED;
6025 std_op:
6026 /* XXX: currently, some unsigned operations are explicit, so
6027 we modify them here */
6028 if (t & VT_UNSIGNED) {
6029 if (op == TOK_SAR)
6030 op = TOK_SHR;
6031 else if (op == '/')
6032 op = TOK_UDIV;
6033 else if (op == '%')
6034 op = TOK_UMOD;
6035 else if (op == TOK_LT)
6036 op = TOK_ULT;
6037 else if (op == TOK_GT)
6038 op = TOK_UGT;
6039 else if (op == TOK_LE)
6040 op = TOK_ULE;
6041 else if (op == TOK_GE)
6042 op = TOK_UGE;
6044 vswap();
6045 type1.t = t;
6046 gen_cast(&type1);
6047 vswap();
6048 /* special case for shifts and long long: we keep the shift as
6049 an integer */
6050 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
6051 type1.t = VT_INT;
6052 gen_cast(&type1);
6053 if (is_float(t))
6054 gen_opif(op);
6055 else
6056 gen_opic(op);
6057 if (op >= TOK_ULT && op <= TOK_GT) {
6058 /* relationnal op: the result is an int */
6059 vtop->type.t = VT_INT;
6060 } else {
6061 vtop->type.t = t;
6066 #ifndef TCC_TARGET_ARM
6067 /* generic itof for unsigned long long case */
6068 void gen_cvt_itof1(int t)
6070 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
6071 (VT_LLONG | VT_UNSIGNED)) {
6073 if (t == VT_FLOAT)
6074 vpush_global_sym(&func_old_type, TOK___floatundisf);
6075 #if LDOUBLE_SIZE != 8
6076 else if (t == VT_LDOUBLE)
6077 vpush_global_sym(&func_old_type, TOK___floatundixf);
6078 #endif
6079 else
6080 vpush_global_sym(&func_old_type, TOK___floatundidf);
6081 vrott(2);
6082 gfunc_call(1);
6083 vpushi(0);
6084 vtop->r = reg_fret(t);
6085 } else {
6086 gen_cvt_itof(t);
6089 #endif
6091 /* generic ftoi for unsigned long long case */
6092 void gen_cvt_ftoi1(int t)
6094 int st;
6096 if (t == (VT_LLONG | VT_UNSIGNED)) {
6097 /* not handled natively */
6098 st = vtop->type.t & VT_BTYPE;
6099 if (st == VT_FLOAT)
6100 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
6101 #if LDOUBLE_SIZE != 8
6102 else if (st == VT_LDOUBLE)
6103 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
6104 #endif
6105 else
6106 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
6107 vrott(2);
6108 gfunc_call(1);
6109 vpushi(0);
6110 vtop->r = REG_IRET;
6111 vtop->r2 = REG_LRET;
6112 } else {
6113 gen_cvt_ftoi(t);
6117 /* force char or short cast */
6118 void force_charshort_cast(int t)
6120 int bits, dbt;
6121 dbt = t & VT_BTYPE;
6122 /* XXX: add optimization if lvalue : just change type and offset */
6123 if (dbt == VT_BYTE)
6124 bits = 8;
6125 else
6126 bits = 16;
6127 if (t & VT_UNSIGNED) {
6128 vpushi((1 << bits) - 1);
6129 gen_op('&');
6130 } else {
6131 bits = 32 - bits;
6132 vpushi(bits);
6133 gen_op(TOK_SHL);
6134 /* result must be signed or the SAR is converted to an SHL
6135 This was not the case when "t" was a signed short
6136 and the last value on the stack was an unsigned int */
6137 vtop->type.t &= ~VT_UNSIGNED;
6138 vpushi(bits);
6139 gen_op(TOK_SAR);
6143 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
6144 static void gen_cast(CType *type)
6146 int sbt, dbt, sf, df, c, p;
6148 /* special delayed cast for char/short */
6149 /* XXX: in some cases (multiple cascaded casts), it may still
6150 be incorrect */
6151 if (vtop->r & VT_MUSTCAST) {
6152 vtop->r &= ~VT_MUSTCAST;
6153 force_charshort_cast(vtop->type.t);
6156 /* bitfields first get cast to ints */
6157 if (vtop->type.t & VT_BITFIELD) {
6158 gv(RC_INT);
6161 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
6162 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
6164 if (sbt != dbt) {
6165 sf = is_float(sbt);
6166 df = is_float(dbt);
6167 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6168 p = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM);
6169 if (c) {
6170 /* constant case: we can do it now */
6171 /* XXX: in ISOC, cannot do it if error in convert */
6172 if (sbt == VT_FLOAT)
6173 vtop->c.ld = vtop->c.f;
6174 else if (sbt == VT_DOUBLE)
6175 vtop->c.ld = vtop->c.d;
6177 if (df) {
6178 if ((sbt & VT_BTYPE) == VT_LLONG) {
6179 if (sbt & VT_UNSIGNED)
6180 vtop->c.ld = vtop->c.ull;
6181 else
6182 vtop->c.ld = vtop->c.ll;
6183 } else if(!sf) {
6184 if (sbt & VT_UNSIGNED)
6185 vtop->c.ld = vtop->c.ui;
6186 else
6187 vtop->c.ld = vtop->c.i;
6190 if (dbt == VT_FLOAT)
6191 vtop->c.f = (float)vtop->c.ld;
6192 else if (dbt == VT_DOUBLE)
6193 vtop->c.d = (double)vtop->c.ld;
6194 } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
6195 vtop->c.ull = (unsigned long long)vtop->c.ld;
6196 } else if (sf && dbt == VT_BOOL) {
6197 vtop->c.i = (vtop->c.ld != 0);
6198 } else {
6199 if(sf)
6200 vtop->c.ll = (long long)vtop->c.ld;
6201 else if (sbt == (VT_LLONG|VT_UNSIGNED))
6202 vtop->c.ll = vtop->c.ull;
6203 else if (sbt & VT_UNSIGNED)
6204 vtop->c.ll = vtop->c.ui;
6205 else if (sbt != VT_LLONG)
6206 vtop->c.ll = vtop->c.i;
6208 if (dbt == (VT_LLONG|VT_UNSIGNED))
6209 vtop->c.ull = vtop->c.ll;
6210 else if (dbt == VT_BOOL)
6211 vtop->c.i = (vtop->c.ll != 0);
6212 else if (dbt != VT_LLONG) {
6213 int s = 0;
6214 if ((dbt & VT_BTYPE) == VT_BYTE)
6215 s = 24;
6216 else if ((dbt & VT_BTYPE) == VT_SHORT)
6217 s = 16;
6219 if(dbt & VT_UNSIGNED)
6220 vtop->c.ui = ((unsigned int)vtop->c.ll << s) >> s;
6221 else
6222 vtop->c.i = ((int)vtop->c.ll << s) >> s;
6225 } else if (p && dbt == VT_BOOL) {
6226 vtop->r = VT_CONST;
6227 vtop->c.i = 1;
6228 } else if (!nocode_wanted) {
6229 /* non constant case: generate code */
6230 if (sf && df) {
6231 /* convert from fp to fp */
6232 gen_cvt_ftof(dbt);
6233 } else if (df) {
6234 /* convert int to fp */
6235 gen_cvt_itof1(dbt);
6236 } else if (sf) {
6237 /* convert fp to int */
6238 if (dbt == VT_BOOL) {
6239 vpushi(0);
6240 gen_op(TOK_NE);
6241 } else {
6242 /* we handle char/short/etc... with generic code */
6243 if (dbt != (VT_INT | VT_UNSIGNED) &&
6244 dbt != (VT_LLONG | VT_UNSIGNED) &&
6245 dbt != VT_LLONG)
6246 dbt = VT_INT;
6247 gen_cvt_ftoi1(dbt);
6248 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
6249 /* additional cast for char/short... */
6250 vtop->type.t = dbt;
6251 gen_cast(type);
6254 #ifndef TCC_TARGET_X86_64
6255 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
6256 if ((sbt & VT_BTYPE) != VT_LLONG) {
6257 /* scalar to long long */
6258 /* machine independent conversion */
6259 gv(RC_INT);
6260 /* generate high word */
6261 if (sbt == (VT_INT | VT_UNSIGNED)) {
6262 vpushi(0);
6263 gv(RC_INT);
6264 } else {
6265 if (sbt == VT_PTR) {
6266 /* cast from pointer to int before we apply
6267 shift operation, which pointers don't support*/
6268 gen_cast(&int_type);
6270 gv_dup();
6271 vpushi(31);
6272 gen_op(TOK_SAR);
6274 /* patch second register */
6275 vtop[-1].r2 = vtop->r;
6276 vpop();
6278 #else
6279 } else if ((dbt & VT_BTYPE) == VT_LLONG ||
6280 (dbt & VT_BTYPE) == VT_PTR) {
6281 /* XXX: not sure if this is perfect... need more tests */
6282 if ((sbt & VT_BTYPE) != VT_LLONG) {
6283 int r = gv(RC_INT);
6284 if (sbt != (VT_INT | VT_UNSIGNED) &&
6285 sbt != VT_PTR && sbt != VT_FUNC) {
6286 /* x86_64 specific: movslq */
6287 o(0x6348);
6288 o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r));
6291 #endif
6292 } else if (dbt == VT_BOOL) {
6293 /* scalar to bool */
6294 vpushi(0);
6295 gen_op(TOK_NE);
6296 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
6297 (dbt & VT_BTYPE) == VT_SHORT) {
6298 if (sbt == VT_PTR) {
6299 vtop->type.t = VT_INT;
6300 warning("nonportable conversion from pointer to char/short");
6302 force_charshort_cast(dbt);
6303 } else if ((dbt & VT_BTYPE) == VT_INT) {
6304 /* scalar to int */
6305 if (sbt == VT_LLONG) {
6306 /* from long long: just take low order word */
6307 lexpand();
6308 vpop();
6310 /* if lvalue and single word type, nothing to do because
6311 the lvalue already contains the real type size (see
6312 VT_LVAL_xxx constants) */
6315 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
6316 /* if we are casting between pointer types,
6317 we must update the VT_LVAL_xxx size */
6318 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
6319 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
6321 vtop->type = *type;
6324 /* return type size. Put alignment at 'a' */
6325 static int type_size(CType *type, int *a)
6327 Sym *s;
6328 int bt;
6330 bt = type->t & VT_BTYPE;
6331 if (bt == VT_STRUCT) {
6332 /* struct/union */
6333 s = type->ref;
6334 *a = s->r;
6335 return s->c;
6336 } else if (bt == VT_PTR) {
6337 if (type->t & VT_ARRAY) {
6338 int ts;
6340 s = type->ref;
6341 ts = type_size(&s->type, a);
6343 if (ts < 0 && s->c < 0)
6344 ts = -ts;
6346 return ts * s->c;
6347 } else {
6348 *a = PTR_SIZE;
6349 return PTR_SIZE;
6351 } else if (bt == VT_LDOUBLE) {
6352 *a = LDOUBLE_ALIGN;
6353 return LDOUBLE_SIZE;
6354 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
6355 #ifdef TCC_TARGET_I386
6356 #ifdef TCC_TARGET_PE
6357 *a = 8;
6358 #else
6359 *a = 4;
6360 #endif
6361 #elif defined(TCC_TARGET_ARM)
6362 #ifdef TCC_ARM_EABI
6363 *a = 8;
6364 #else
6365 *a = 4;
6366 #endif
6367 #else
6368 *a = 8;
6369 #endif
6370 return 8;
6371 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6372 *a = 4;
6373 return 4;
6374 } else if (bt == VT_SHORT) {
6375 *a = 2;
6376 return 2;
6377 } else {
6378 /* char, void, function, _Bool */
6379 *a = 1;
6380 return 1;
6384 /* return the pointed type of t */
6385 static inline CType *pointed_type(CType *type)
6387 return &type->ref->type;
6390 /* modify type so that its it is a pointer to type. */
6391 static void mk_pointer(CType *type)
6393 Sym *s;
6394 s = sym_push(SYM_FIELD, type, 0, -1);
6395 type->t = VT_PTR | (type->t & ~VT_TYPE);
6396 type->ref = s;
6399 /* compare function types. OLD functions match any new functions */
6400 static int is_compatible_func(CType *type1, CType *type2)
6402 Sym *s1, *s2;
6404 s1 = type1->ref;
6405 s2 = type2->ref;
6406 if (!is_compatible_types(&s1->type, &s2->type))
6407 return 0;
6408 /* check func_call */
6409 if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
6410 return 0;
6411 /* XXX: not complete */
6412 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6413 return 1;
6414 if (s1->c != s2->c)
6415 return 0;
6416 while (s1 != NULL) {
6417 if (s2 == NULL)
6418 return 0;
6419 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6420 return 0;
6421 s1 = s1->next;
6422 s2 = s2->next;
6424 if (s2)
6425 return 0;
6426 return 1;
6429 /* return true if type1 and type2 are the same. If unqualified is
6430 true, qualifiers on the types are ignored.
6432 - enums are not checked as gcc __builtin_types_compatible_p ()
6434 static int compare_types(CType *type1, CType *type2, int unqualified)
6436 int bt1, t1, t2;
6438 t1 = type1->t & VT_TYPE;
6439 t2 = type2->t & VT_TYPE;
6440 if (unqualified) {
6441 /* strip qualifiers before comparing */
6442 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6443 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6445 /* XXX: bitfields ? */
6446 if (t1 != t2)
6447 return 0;
6448 /* test more complicated cases */
6449 bt1 = t1 & VT_BTYPE;
6450 if (bt1 == VT_PTR) {
6451 type1 = pointed_type(type1);
6452 type2 = pointed_type(type2);
6453 return is_compatible_types(type1, type2);
6454 } else if (bt1 == VT_STRUCT) {
6455 return (type1->ref == type2->ref);
6456 } else if (bt1 == VT_FUNC) {
6457 return is_compatible_func(type1, type2);
6458 } else {
6459 return 1;
6463 /* return true if type1 and type2 are exactly the same (including
6464 qualifiers).
6466 static int is_compatible_types(CType *type1, CType *type2)
6468 return compare_types(type1,type2,0);
6471 /* return true if type1 and type2 are the same (ignoring qualifiers).
6473 static int is_compatible_parameter_types(CType *type1, CType *type2)
6475 return compare_types(type1,type2,1);
6478 /* print a type. If 'varstr' is not NULL, then the variable is also
6479 printed in the type */
6480 /* XXX: union */
6481 /* XXX: add array and function pointers */
6482 void type_to_str(char *buf, int buf_size,
6483 CType *type, const char *varstr)
6485 int bt, v, t;
6486 Sym *s, *sa;
6487 char buf1[256];
6488 const char *tstr;
6490 t = type->t & VT_TYPE;
6491 bt = t & VT_BTYPE;
6492 buf[0] = '\0';
6493 if (t & VT_CONSTANT)
6494 pstrcat(buf, buf_size, "const ");
6495 if (t & VT_VOLATILE)
6496 pstrcat(buf, buf_size, "volatile ");
6497 if (t & VT_UNSIGNED)
6498 pstrcat(buf, buf_size, "unsigned ");
6499 switch(bt) {
6500 case VT_VOID:
6501 tstr = "void";
6502 goto add_tstr;
6503 case VT_BOOL:
6504 tstr = "_Bool";
6505 goto add_tstr;
6506 case VT_BYTE:
6507 tstr = "char";
6508 goto add_tstr;
6509 case VT_SHORT:
6510 tstr = "short";
6511 goto add_tstr;
6512 case VT_INT:
6513 tstr = "int";
6514 goto add_tstr;
6515 case VT_LONG:
6516 tstr = "long";
6517 goto add_tstr;
6518 case VT_LLONG:
6519 tstr = "long long";
6520 goto add_tstr;
6521 case VT_FLOAT:
6522 tstr = "float";
6523 goto add_tstr;
6524 case VT_DOUBLE:
6525 tstr = "double";
6526 goto add_tstr;
6527 case VT_LDOUBLE:
6528 tstr = "long double";
6529 add_tstr:
6530 pstrcat(buf, buf_size, tstr);
6531 break;
6532 case VT_ENUM:
6533 case VT_STRUCT:
6534 if (bt == VT_STRUCT)
6535 tstr = "struct ";
6536 else
6537 tstr = "enum ";
6538 pstrcat(buf, buf_size, tstr);
6539 v = type->ref->v & ~SYM_STRUCT;
6540 if (v >= SYM_FIRST_ANOM)
6541 pstrcat(buf, buf_size, "<anonymous>");
6542 else
6543 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6544 break;
6545 case VT_FUNC:
6546 s = type->ref;
6547 type_to_str(buf, buf_size, &s->type, varstr);
6548 pstrcat(buf, buf_size, "(");
6549 sa = s->next;
6550 while (sa != NULL) {
6551 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6552 pstrcat(buf, buf_size, buf1);
6553 sa = sa->next;
6554 if (sa)
6555 pstrcat(buf, buf_size, ", ");
6557 pstrcat(buf, buf_size, ")");
6558 goto no_var;
6559 case VT_PTR:
6560 s = type->ref;
6561 pstrcpy(buf1, sizeof(buf1), "*");
6562 if (varstr)
6563 pstrcat(buf1, sizeof(buf1), varstr);
6564 type_to_str(buf, buf_size, &s->type, buf1);
6565 goto no_var;
6567 if (varstr) {
6568 pstrcat(buf, buf_size, " ");
6569 pstrcat(buf, buf_size, varstr);
6571 no_var: ;
6574 /* verify type compatibility to store vtop in 'dt' type, and generate
6575 casts if needed. */
6576 static void gen_assign_cast(CType *dt)
6578 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6579 char buf1[256], buf2[256];
6580 int dbt, sbt;
6582 st = &vtop->type; /* source type */
6583 dbt = dt->t & VT_BTYPE;
6584 sbt = st->t & VT_BTYPE;
6585 if (dt->t & VT_CONSTANT)
6586 warning("assignment of read-only location");
6587 switch(dbt) {
6588 case VT_PTR:
6589 /* special cases for pointers */
6590 /* '0' can also be a pointer */
6591 if (is_null_pointer(vtop))
6592 goto type_ok;
6593 /* accept implicit pointer to integer cast with warning */
6594 if (is_integer_btype(sbt)) {
6595 warning("assignment makes pointer from integer without a cast");
6596 goto type_ok;
6598 type1 = pointed_type(dt);
6599 /* a function is implicitely a function pointer */
6600 if (sbt == VT_FUNC) {
6601 if ((type1->t & VT_BTYPE) != VT_VOID &&
6602 !is_compatible_types(pointed_type(dt), st))
6603 goto error;
6604 else
6605 goto type_ok;
6607 if (sbt != VT_PTR)
6608 goto error;
6609 type2 = pointed_type(st);
6610 if ((type1->t & VT_BTYPE) == VT_VOID ||
6611 (type2->t & VT_BTYPE) == VT_VOID) {
6612 /* void * can match anything */
6613 } else {
6614 /* exact type match, except for unsigned */
6615 tmp_type1 = *type1;
6616 tmp_type2 = *type2;
6617 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6618 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6619 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6620 warning("assignment from incompatible pointer type");
6622 /* check const and volatile */
6623 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6624 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6625 warning("assignment discards qualifiers from pointer target type");
6626 break;
6627 case VT_BYTE:
6628 case VT_SHORT:
6629 case VT_INT:
6630 case VT_LLONG:
6631 if (sbt == VT_PTR || sbt == VT_FUNC) {
6632 warning("assignment makes integer from pointer without a cast");
6634 /* XXX: more tests */
6635 break;
6636 case VT_STRUCT:
6637 tmp_type1 = *dt;
6638 tmp_type2 = *st;
6639 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6640 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6641 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6642 error:
6643 type_to_str(buf1, sizeof(buf1), st, NULL);
6644 type_to_str(buf2, sizeof(buf2), dt, NULL);
6645 error("cannot cast '%s' to '%s'", buf1, buf2);
6647 break;
6649 type_ok:
6650 gen_cast(dt);
6653 /* store vtop in lvalue pushed on stack */
6654 void vstore(void)
6656 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6658 ft = vtop[-1].type.t;
6659 sbt = vtop->type.t & VT_BTYPE;
6660 dbt = ft & VT_BTYPE;
6661 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6662 (sbt == VT_INT && dbt == VT_SHORT)) {
6663 /* optimize char/short casts */
6664 delayed_cast = VT_MUSTCAST;
6665 vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));
6666 /* XXX: factorize */
6667 if (ft & VT_CONSTANT)
6668 warning("assignment of read-only location");
6669 } else {
6670 delayed_cast = 0;
6671 if (!(ft & VT_BITFIELD))
6672 gen_assign_cast(&vtop[-1].type);
6675 if (sbt == VT_STRUCT) {
6676 /* if structure, only generate pointer */
6677 /* structure assignment : generate memcpy */
6678 /* XXX: optimize if small size */
6679 if (!nocode_wanted) {
6680 size = type_size(&vtop->type, &align);
6682 #ifdef TCC_ARM_EABI
6683 if(!(align & 7))
6684 vpush_global_sym(&func_old_type, TOK_memcpy8);
6685 else if(!(align & 3))
6686 vpush_global_sym(&func_old_type, TOK_memcpy4);
6687 else
6688 #endif
6689 vpush_global_sym(&func_old_type, TOK_memcpy);
6691 /* destination */
6692 vpushv(vtop - 2);
6693 vtop->type.t = VT_PTR;
6694 gaddrof();
6695 /* source */
6696 vpushv(vtop - 2);
6697 vtop->type.t = VT_PTR;
6698 gaddrof();
6699 /* type size */
6700 vpushi(size);
6701 gfunc_call(3);
6703 vswap();
6704 vpop();
6705 } else {
6706 vswap();
6707 vpop();
6709 /* leave source on stack */
6710 } else if (ft & VT_BITFIELD) {
6711 /* bitfield store handling */
6712 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6713 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6714 /* remove bit field info to avoid loops */
6715 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6717 /* duplicate source into other register */
6718 gv_dup();
6719 vswap();
6720 vrott(3);
6722 if((ft & VT_BTYPE) == VT_BOOL) {
6723 gen_cast(&vtop[-1].type);
6724 vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
6727 /* duplicate destination */
6728 vdup();
6729 vtop[-1] = vtop[-2];
6731 /* mask and shift source */
6732 if((ft & VT_BTYPE) != VT_BOOL) {
6733 if((ft & VT_BTYPE) == VT_LLONG) {
6734 vpushll((1ULL << bit_size) - 1ULL);
6735 } else {
6736 vpushi((1 << bit_size) - 1);
6738 gen_op('&');
6740 vpushi(bit_pos);
6741 gen_op(TOK_SHL);
6742 /* load destination, mask and or with source */
6743 vswap();
6744 if((ft & VT_BTYPE) == VT_LLONG) {
6745 vpushll(~(((1ULL << bit_size) - 1ULL) << bit_pos));
6746 } else {
6747 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6749 gen_op('&');
6750 gen_op('|');
6751 /* store result */
6752 vstore();
6754 /* pop off shifted source from "duplicate source..." above */
6755 vpop();
6757 } else {
6758 #ifdef CONFIG_TCC_BCHECK
6759 /* bound check case */
6760 if (vtop[-1].r & VT_MUSTBOUND) {
6761 vswap();
6762 gbound();
6763 vswap();
6765 #endif
6766 if (!nocode_wanted) {
6767 rc = RC_INT;
6768 if (is_float(ft)) {
6769 rc = RC_FLOAT;
6770 #ifdef TCC_TARGET_X86_64
6771 if ((ft & VT_BTYPE) == VT_LDOUBLE) {
6772 rc = RC_ST0;
6774 #endif
6776 r = gv(rc); /* generate value */
6777 /* if lvalue was saved on stack, must read it */
6778 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6779 SValue sv;
6780 t = get_reg(RC_INT);
6781 #ifdef TCC_TARGET_X86_64
6782 sv.type.t = VT_PTR;
6783 #else
6784 sv.type.t = VT_INT;
6785 #endif
6786 sv.r = VT_LOCAL | VT_LVAL;
6787 sv.c.ul = vtop[-1].c.ul;
6788 load(t, &sv);
6789 vtop[-1].r = t | VT_LVAL;
6791 store(r, vtop - 1);
6792 #ifndef TCC_TARGET_X86_64
6793 /* two word case handling : store second register at word + 4 */
6794 if ((ft & VT_BTYPE) == VT_LLONG) {
6795 vswap();
6796 /* convert to int to increment easily */
6797 vtop->type.t = VT_INT;
6798 gaddrof();
6799 vpushi(4);
6800 gen_op('+');
6801 vtop->r |= VT_LVAL;
6802 vswap();
6803 /* XXX: it works because r2 is spilled last ! */
6804 store(vtop->r2, vtop - 1);
6806 #endif
6808 vswap();
6809 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6810 vtop->r |= delayed_cast;
6814 /* post defines POST/PRE add. c is the token ++ or -- */
6815 void inc(int post, int c)
6817 test_lvalue();
6818 vdup(); /* save lvalue */
6819 if (post) {
6820 gv_dup(); /* duplicate value */
6821 vrotb(3);
6822 vrotb(3);
6824 /* add constant */
6825 vpushi(c - TOK_MID);
6826 gen_op('+');
6827 vstore(); /* store value */
6828 if (post)
6829 vpop(); /* if post op, return saved value */
6832 /* Parse GNUC __attribute__ extension. Currently, the following
6833 extensions are recognized:
6834 - aligned(n) : set data/function alignment.
6835 - packed : force data alignment to 1
6836 - section(x) : generate data/code in this section.
6837 - unused : currently ignored, but may be used someday.
6838 - regparm(n) : pass function parameters in registers (i386 only)
6840 static void parse_attribute(AttributeDef *ad)
6842 int t, n;
6844 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6845 next();
6846 skip('(');
6847 skip('(');
6848 while (tok != ')') {
6849 if (tok < TOK_IDENT)
6850 expect("attribute name");
6851 t = tok;
6852 next();
6853 switch(t) {
6854 case TOK_SECTION1:
6855 case TOK_SECTION2:
6856 skip('(');
6857 if (tok != TOK_STR)
6858 expect("section name");
6859 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6860 next();
6861 skip(')');
6862 break;
6863 case TOK_ALIGNED1:
6864 case TOK_ALIGNED2:
6865 if (tok == '(') {
6866 next();
6867 n = expr_const();
6868 if (n <= 0 || (n & (n - 1)) != 0)
6869 error("alignment must be a positive power of two");
6870 skip(')');
6871 } else {
6872 n = MAX_ALIGN;
6874 ad->aligned = n;
6875 break;
6876 case TOK_PACKED1:
6877 case TOK_PACKED2:
6878 ad->packed = 1;
6879 break;
6880 case TOK_UNUSED1:
6881 case TOK_UNUSED2:
6882 /* currently, no need to handle it because tcc does not
6883 track unused objects */
6884 break;
6885 case TOK_NORETURN1:
6886 case TOK_NORETURN2:
6887 /* currently, no need to handle it because tcc does not
6888 track unused objects */
6889 break;
6890 case TOK_CDECL1:
6891 case TOK_CDECL2:
6892 case TOK_CDECL3:
6893 FUNC_CALL(ad->func_attr) = FUNC_CDECL;
6894 break;
6895 case TOK_STDCALL1:
6896 case TOK_STDCALL2:
6897 case TOK_STDCALL3:
6898 FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
6899 break;
6900 #ifdef TCC_TARGET_I386
6901 case TOK_REGPARM1:
6902 case TOK_REGPARM2:
6903 skip('(');
6904 n = expr_const();
6905 if (n > 3)
6906 n = 3;
6907 else if (n < 0)
6908 n = 0;
6909 if (n > 0)
6910 FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
6911 skip(')');
6912 break;
6913 case TOK_FASTCALL1:
6914 case TOK_FASTCALL2:
6915 case TOK_FASTCALL3:
6916 FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
6917 break;
6918 #endif
6919 case TOK_DLLEXPORT:
6920 FUNC_EXPORT(ad->func_attr) = 1;
6921 break;
6922 default:
6923 if (tcc_state->warn_unsupported)
6924 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6925 /* skip parameters */
6926 if (tok == '(') {
6927 int parenthesis = 0;
6928 do {
6929 if (tok == '(')
6930 parenthesis++;
6931 else if (tok == ')')
6932 parenthesis--;
6933 next();
6934 } while (parenthesis && tok != -1);
6936 break;
6938 if (tok != ',')
6939 break;
6940 next();
6942 skip(')');
6943 skip(')');
6947 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6948 static void struct_decl(CType *type, int u)
6950 int a, v, size, align, maxalign, c, offset;
6951 int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt;
6952 Sym *s, *ss, *ass, **ps;
6953 AttributeDef ad;
6954 CType type1, btype;
6956 a = tok; /* save decl type */
6957 next();
6958 if (tok != '{') {
6959 v = tok;
6960 next();
6961 /* struct already defined ? return it */
6962 if (v < TOK_IDENT)
6963 expect("struct/union/enum name");
6964 s = struct_find(v);
6965 if (s) {
6966 if (s->type.t != a)
6967 error("invalid type");
6968 goto do_decl;
6970 } else {
6971 v = anon_sym++;
6973 type1.t = a;
6974 /* we put an undefined size for struct/union */
6975 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6976 s->r = 0; /* default alignment is zero as gcc */
6977 /* put struct/union/enum name in type */
6978 do_decl:
6979 type->t = u;
6980 type->ref = s;
6982 if (tok == '{') {
6983 next();
6984 if (s->c != -1)
6985 error("struct/union/enum already defined");
6986 /* cannot be empty */
6987 c = 0;
6988 /* non empty enums are not allowed */
6989 if (a == TOK_ENUM) {
6990 for(;;) {
6991 v = tok;
6992 if (v < TOK_UIDENT)
6993 expect("identifier");
6994 next();
6995 if (tok == '=') {
6996 next();
6997 c = expr_const();
6999 /* enum symbols have static storage */
7000 ss = sym_push(v, &int_type, VT_CONST, c);
7001 ss->type.t |= VT_STATIC;
7002 if (tok != ',')
7003 break;
7004 next();
7005 c++;
7006 /* NOTE: we accept a trailing comma */
7007 if (tok == '}')
7008 break;
7010 skip('}');
7011 } else {
7012 maxalign = 1;
7013 ps = &s->next;
7014 prevbt = VT_INT;
7015 bit_pos = 0;
7016 offset = 0;
7017 while (tok != '}') {
7018 parse_btype(&btype, &ad);
7019 while (1) {
7020 bit_size = -1;
7021 v = 0;
7022 type1 = btype;
7023 if (tok != ':') {
7024 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
7025 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
7026 expect("identifier");
7027 if ((type1.t & VT_BTYPE) == VT_FUNC ||
7028 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
7029 error("invalid type for '%s'",
7030 get_tok_str(v, NULL));
7032 if (tok == ':') {
7033 next();
7034 bit_size = expr_const();
7035 /* XXX: handle v = 0 case for messages */
7036 if (bit_size < 0)
7037 error("negative width in bit-field '%s'",
7038 get_tok_str(v, NULL));
7039 if (v && bit_size == 0)
7040 error("zero width for bit-field '%s'",
7041 get_tok_str(v, NULL));
7043 size = type_size(&type1, &align);
7044 if (ad.aligned) {
7045 if (align < ad.aligned)
7046 align = ad.aligned;
7047 } else if (ad.packed) {
7048 align = 1;
7049 } else if (*tcc_state->pack_stack_ptr) {
7050 if (align > *tcc_state->pack_stack_ptr)
7051 align = *tcc_state->pack_stack_ptr;
7053 lbit_pos = 0;
7054 if (bit_size >= 0) {
7055 bt = type1.t & VT_BTYPE;
7056 if (bt != VT_INT &&
7057 bt != VT_BYTE &&
7058 bt != VT_SHORT &&
7059 bt != VT_BOOL &&
7060 bt != VT_ENUM &&
7061 bt != VT_LLONG)
7062 error("bitfields must have scalar type");
7063 bsize = size * 8;
7064 if (bit_size > bsize) {
7065 error("width of '%s' exceeds its type",
7066 get_tok_str(v, NULL));
7067 } else if (bit_size == bsize) {
7068 /* no need for bit fields */
7069 bit_pos = 0;
7070 } else if (bit_size == 0) {
7071 /* XXX: what to do if only padding in a
7072 structure ? */
7073 /* zero size: means to pad */
7074 bit_pos = 0;
7075 } else {
7076 /* we do not have enough room ?
7077 did the type change?
7078 is it a union? */
7079 if ((bit_pos + bit_size) > bsize ||
7080 bt != prevbt || a == TOK_UNION)
7081 bit_pos = 0;
7082 lbit_pos = bit_pos;
7083 /* XXX: handle LSB first */
7084 type1.t |= VT_BITFIELD |
7085 (bit_pos << VT_STRUCT_SHIFT) |
7086 (bit_size << (VT_STRUCT_SHIFT + 6));
7087 bit_pos += bit_size;
7089 prevbt = bt;
7090 } else {
7091 bit_pos = 0;
7093 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
7094 /* add new memory data only if starting
7095 bit field */
7096 if (lbit_pos == 0) {
7097 if (a == TOK_STRUCT) {
7098 c = (c + align - 1) & -align;
7099 offset = c;
7100 if (size > 0)
7101 c += size;
7102 } else {
7103 offset = 0;
7104 if (size > c)
7105 c = size;
7107 if (align > maxalign)
7108 maxalign = align;
7110 #if 0
7111 printf("add field %s offset=%d",
7112 get_tok_str(v, NULL), offset);
7113 if (type1.t & VT_BITFIELD) {
7114 printf(" pos=%d size=%d",
7115 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
7116 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
7118 printf("\n");
7119 #endif
7121 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
7122 ass = type1.ref;
7123 while ((ass = ass->next) != NULL) {
7124 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
7125 *ps = ss;
7126 ps = &ss->next;
7128 } else if (v) {
7129 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
7130 *ps = ss;
7131 ps = &ss->next;
7133 if (tok == ';' || tok == TOK_EOF)
7134 break;
7135 skip(',');
7137 skip(';');
7139 skip('}');
7140 /* store size and alignment */
7141 s->c = (c + maxalign - 1) & -maxalign;
7142 s->r = maxalign;
7147 /* return 0 if no type declaration. otherwise, return the basic type
7148 and skip it.
7150 static int parse_btype(CType *type, AttributeDef *ad)
7152 int t, u, type_found, typespec_found, typedef_found;
7153 Sym *s;
7154 CType type1;
7156 memset(ad, 0, sizeof(AttributeDef));
7157 type_found = 0;
7158 typespec_found = 0;
7159 typedef_found = 0;
7160 t = 0;
7161 while(1) {
7162 switch(tok) {
7163 case TOK_EXTENSION:
7164 /* currently, we really ignore extension */
7165 next();
7166 continue;
7168 /* basic types */
7169 case TOK_CHAR:
7170 u = VT_BYTE;
7171 basic_type:
7172 next();
7173 basic_type1:
7174 if ((t & VT_BTYPE) != 0)
7175 error("too many basic types");
7176 t |= u;
7177 typespec_found = 1;
7178 break;
7179 case TOK_VOID:
7180 u = VT_VOID;
7181 goto basic_type;
7182 case TOK_SHORT:
7183 u = VT_SHORT;
7184 goto basic_type;
7185 case TOK_INT:
7186 next();
7187 typespec_found = 1;
7188 break;
7189 case TOK_LONG:
7190 next();
7191 if ((t & VT_BTYPE) == VT_DOUBLE) {
7192 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
7193 } else if ((t & VT_BTYPE) == VT_LONG) {
7194 t = (t & ~VT_BTYPE) | VT_LLONG;
7195 } else {
7196 u = VT_LONG;
7197 goto basic_type1;
7199 break;
7200 case TOK_BOOL:
7201 u = VT_BOOL;
7202 goto basic_type;
7203 case TOK_FLOAT:
7204 u = VT_FLOAT;
7205 goto basic_type;
7206 case TOK_DOUBLE:
7207 next();
7208 if ((t & VT_BTYPE) == VT_LONG) {
7209 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
7210 } else {
7211 u = VT_DOUBLE;
7212 goto basic_type1;
7214 break;
7215 case TOK_ENUM:
7216 struct_decl(&type1, VT_ENUM);
7217 basic_type2:
7218 u = type1.t;
7219 type->ref = type1.ref;
7220 goto basic_type1;
7221 case TOK_STRUCT:
7222 case TOK_UNION:
7223 struct_decl(&type1, VT_STRUCT);
7224 goto basic_type2;
7226 /* type modifiers */
7227 case TOK_CONST1:
7228 case TOK_CONST2:
7229 case TOK_CONST3:
7230 t |= VT_CONSTANT;
7231 next();
7232 break;
7233 case TOK_VOLATILE1:
7234 case TOK_VOLATILE2:
7235 case TOK_VOLATILE3:
7236 t |= VT_VOLATILE;
7237 next();
7238 break;
7239 case TOK_SIGNED1:
7240 case TOK_SIGNED2:
7241 case TOK_SIGNED3:
7242 typespec_found = 1;
7243 t |= VT_SIGNED;
7244 next();
7245 break;
7246 case TOK_REGISTER:
7247 case TOK_AUTO:
7248 case TOK_RESTRICT1:
7249 case TOK_RESTRICT2:
7250 case TOK_RESTRICT3:
7251 next();
7252 break;
7253 case TOK_UNSIGNED:
7254 t |= VT_UNSIGNED;
7255 next();
7256 typespec_found = 1;
7257 break;
7259 /* storage */
7260 case TOK_EXTERN:
7261 t |= VT_EXTERN;
7262 next();
7263 break;
7264 case TOK_STATIC:
7265 t |= VT_STATIC;
7266 next();
7267 break;
7268 case TOK_TYPEDEF:
7269 t |= VT_TYPEDEF;
7270 next();
7271 break;
7272 case TOK_INLINE1:
7273 case TOK_INLINE2:
7274 case TOK_INLINE3:
7275 t |= VT_INLINE;
7276 next();
7277 break;
7279 /* GNUC attribute */
7280 case TOK_ATTRIBUTE1:
7281 case TOK_ATTRIBUTE2:
7282 parse_attribute(ad);
7283 break;
7284 /* GNUC typeof */
7285 case TOK_TYPEOF1:
7286 case TOK_TYPEOF2:
7287 case TOK_TYPEOF3:
7288 next();
7289 parse_expr_type(&type1);
7290 goto basic_type2;
7291 default:
7292 if (typespec_found || typedef_found)
7293 goto the_end;
7294 s = sym_find(tok);
7295 if (!s || !(s->type.t & VT_TYPEDEF))
7296 goto the_end;
7297 typedef_found = 1;
7298 t |= (s->type.t & ~VT_TYPEDEF);
7299 type->ref = s->type.ref;
7300 next();
7301 typespec_found = 1;
7302 break;
7304 type_found = 1;
7306 the_end:
7307 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
7308 error("signed and unsigned modifier");
7309 if (tcc_state->char_is_unsigned) {
7310 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
7311 t |= VT_UNSIGNED;
7313 t &= ~VT_SIGNED;
7315 /* long is never used as type */
7316 if ((t & VT_BTYPE) == VT_LONG)
7317 #ifndef TCC_TARGET_X86_64
7318 t = (t & ~VT_BTYPE) | VT_INT;
7319 #else
7320 t = (t & ~VT_BTYPE) | VT_LLONG;
7321 #endif
7322 type->t = t;
7323 return type_found;
7326 /* convert a function parameter type (array to pointer and function to
7327 function pointer) */
7328 static inline void convert_parameter_type(CType *pt)
7330 /* remove const and volatile qualifiers (XXX: const could be used
7331 to indicate a const function parameter */
7332 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
7333 /* array must be transformed to pointer according to ANSI C */
7334 pt->t &= ~VT_ARRAY;
7335 if ((pt->t & VT_BTYPE) == VT_FUNC) {
7336 mk_pointer(pt);
7340 static void post_type(CType *type, AttributeDef *ad)
7342 int n, l, t1, arg_size, align;
7343 Sym **plast, *s, *first;
7344 AttributeDef ad1;
7345 CType pt;
7347 if (tok == '(') {
7348 /* function declaration */
7349 next();
7350 l = 0;
7351 first = NULL;
7352 plast = &first;
7353 arg_size = 0;
7354 if (tok != ')') {
7355 for(;;) {
7356 /* read param name and compute offset */
7357 if (l != FUNC_OLD) {
7358 if (!parse_btype(&pt, &ad1)) {
7359 if (l) {
7360 error("invalid type");
7361 } else {
7362 l = FUNC_OLD;
7363 goto old_proto;
7366 l = FUNC_NEW;
7367 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
7368 break;
7369 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
7370 if ((pt.t & VT_BTYPE) == VT_VOID)
7371 error("parameter declared as void");
7372 arg_size += (type_size(&pt, &align) + 3) & ~3;
7373 } else {
7374 old_proto:
7375 n = tok;
7376 if (n < TOK_UIDENT)
7377 expect("identifier");
7378 pt.t = VT_INT;
7379 next();
7381 convert_parameter_type(&pt);
7382 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
7383 *plast = s;
7384 plast = &s->next;
7385 if (tok == ')')
7386 break;
7387 skip(',');
7388 if (l == FUNC_NEW && tok == TOK_DOTS) {
7389 l = FUNC_ELLIPSIS;
7390 next();
7391 break;
7395 /* if no parameters, then old type prototype */
7396 if (l == 0)
7397 l = FUNC_OLD;
7398 skip(')');
7399 t1 = type->t & VT_STORAGE;
7400 /* NOTE: const is ignored in returned type as it has a special
7401 meaning in gcc / C++ */
7402 type->t &= ~(VT_STORAGE | VT_CONSTANT);
7403 post_type(type, ad);
7404 /* we push a anonymous symbol which will contain the function prototype */
7405 FUNC_ARGS(ad->func_attr) = arg_size;
7406 s = sym_push(SYM_FIELD, type, ad->func_attr, l);
7407 s->next = first;
7408 type->t = t1 | VT_FUNC;
7409 type->ref = s;
7410 } else if (tok == '[') {
7411 /* array definition */
7412 next();
7413 if (tok == TOK_RESTRICT1)
7414 next();
7415 n = -1;
7416 if (tok != ']') {
7417 n = expr_const();
7418 if (n < 0)
7419 error("invalid array size");
7421 skip(']');
7422 /* parse next post type */
7423 t1 = type->t & VT_STORAGE;
7424 type->t &= ~VT_STORAGE;
7425 post_type(type, ad);
7427 /* we push a anonymous symbol which will contain the array
7428 element type */
7429 s = sym_push(SYM_FIELD, type, 0, n);
7430 type->t = t1 | VT_ARRAY | VT_PTR;
7431 type->ref = s;
7435 /* Parse a type declaration (except basic type), and return the type
7436 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7437 expected. 'type' should contain the basic type. 'ad' is the
7438 attribute definition of the basic type. It can be modified by
7439 type_decl().
7441 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7443 Sym *s;
7444 CType type1, *type2;
7445 int qualifiers;
7447 while (tok == '*') {
7448 qualifiers = 0;
7449 redo:
7450 next();
7451 switch(tok) {
7452 case TOK_CONST1:
7453 case TOK_CONST2:
7454 case TOK_CONST3:
7455 qualifiers |= VT_CONSTANT;
7456 goto redo;
7457 case TOK_VOLATILE1:
7458 case TOK_VOLATILE2:
7459 case TOK_VOLATILE3:
7460 qualifiers |= VT_VOLATILE;
7461 goto redo;
7462 case TOK_RESTRICT1:
7463 case TOK_RESTRICT2:
7464 case TOK_RESTRICT3:
7465 goto redo;
7467 mk_pointer(type);
7468 type->t |= qualifiers;
7471 /* XXX: clarify attribute handling */
7472 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7473 parse_attribute(ad);
7475 /* recursive type */
7476 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7477 type1.t = 0; /* XXX: same as int */
7478 if (tok == '(') {
7479 next();
7480 /* XXX: this is not correct to modify 'ad' at this point, but
7481 the syntax is not clear */
7482 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7483 parse_attribute(ad);
7484 type_decl(&type1, ad, v, td);
7485 skip(')');
7486 } else {
7487 /* type identifier */
7488 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7489 *v = tok;
7490 next();
7491 } else {
7492 if (!(td & TYPE_ABSTRACT))
7493 expect("identifier");
7494 *v = 0;
7497 post_type(type, ad);
7498 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7499 parse_attribute(ad);
7500 if (!type1.t)
7501 return;
7502 /* append type at the end of type1 */
7503 type2 = &type1;
7504 for(;;) {
7505 s = type2->ref;
7506 type2 = &s->type;
7507 if (!type2->t) {
7508 *type2 = *type;
7509 break;
7512 *type = type1;
7515 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7516 static int lvalue_type(int t)
7518 int bt, r;
7519 r = VT_LVAL;
7520 bt = t & VT_BTYPE;
7521 if (bt == VT_BYTE || bt == VT_BOOL)
7522 r |= VT_LVAL_BYTE;
7523 else if (bt == VT_SHORT)
7524 r |= VT_LVAL_SHORT;
7525 else
7526 return r;
7527 if (t & VT_UNSIGNED)
7528 r |= VT_LVAL_UNSIGNED;
7529 return r;
7532 /* indirection with full error checking and bound check */
7533 static void indir(void)
7535 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7536 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7537 return;
7538 expect("pointer");
7540 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7541 gv(RC_INT);
7542 vtop->type = *pointed_type(&vtop->type);
7543 /* Arrays and functions are never lvalues */
7544 if (!(vtop->type.t & VT_ARRAY)
7545 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7546 vtop->r |= lvalue_type(vtop->type.t);
7547 /* if bound checking, the referenced pointer must be checked */
7548 if (do_bounds_check)
7549 vtop->r |= VT_MUSTBOUND;
7553 /* pass a parameter to a function and do type checking and casting */
7554 static void gfunc_param_typed(Sym *func, Sym *arg)
7556 int func_type;
7557 CType type;
7559 func_type = func->c;
7560 if (func_type == FUNC_OLD ||
7561 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7562 /* default casting : only need to convert float to double */
7563 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7564 type.t = VT_DOUBLE;
7565 gen_cast(&type);
7567 } else if (arg == NULL) {
7568 error("too many arguments to function");
7569 } else {
7570 type = arg->type;
7571 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7572 gen_assign_cast(&type);
7576 /* parse an expression of the form '(type)' or '(expr)' and return its
7577 type */
7578 static void parse_expr_type(CType *type)
7580 int n;
7581 AttributeDef ad;
7583 skip('(');
7584 if (parse_btype(type, &ad)) {
7585 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7586 } else {
7587 expr_type(type);
7589 skip(')');
7592 static void parse_type(CType *type)
7594 AttributeDef ad;
7595 int n;
7597 if (!parse_btype(type, &ad)) {
7598 expect("type");
7600 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7603 static void vpush_tokc(int t)
7605 CType type;
7606 type.t = t;
7607 vsetc(&type, VT_CONST, &tokc);
7610 static void unary(void)
7612 int n, t, align, size, r;
7613 CType type;
7614 Sym *s;
7615 AttributeDef ad;
7617 /* XXX: GCC 2.95.3 does not generate a table although it should be
7618 better here */
7619 tok_next:
7620 switch(tok) {
7621 case TOK_EXTENSION:
7622 next();
7623 goto tok_next;
7624 case TOK_CINT:
7625 case TOK_CCHAR:
7626 case TOK_LCHAR:
7627 vpushi(tokc.i);
7628 next();
7629 break;
7630 case TOK_CUINT:
7631 vpush_tokc(VT_INT | VT_UNSIGNED);
7632 next();
7633 break;
7634 case TOK_CLLONG:
7635 vpush_tokc(VT_LLONG);
7636 next();
7637 break;
7638 case TOK_CULLONG:
7639 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7640 next();
7641 break;
7642 case TOK_CFLOAT:
7643 vpush_tokc(VT_FLOAT);
7644 next();
7645 break;
7646 case TOK_CDOUBLE:
7647 vpush_tokc(VT_DOUBLE);
7648 next();
7649 break;
7650 case TOK_CLDOUBLE:
7651 vpush_tokc(VT_LDOUBLE);
7652 next();
7653 break;
7654 case TOK___FUNCTION__:
7655 if (!gnu_ext)
7656 goto tok_identifier;
7657 /* fall thru */
7658 case TOK___FUNC__:
7660 void *ptr;
7661 int len;
7662 /* special function name identifier */
7663 len = strlen(funcname) + 1;
7664 /* generate char[len] type */
7665 type.t = VT_BYTE;
7666 mk_pointer(&type);
7667 type.t |= VT_ARRAY;
7668 type.ref->c = len;
7669 vpush_ref(&type, data_section, data_section->data_offset, len);
7670 ptr = section_ptr_add(data_section, len);
7671 memcpy(ptr, funcname, len);
7672 next();
7674 break;
7675 case TOK_LSTR:
7676 #ifdef TCC_TARGET_PE
7677 t = VT_SHORT | VT_UNSIGNED;
7678 #else
7679 t = VT_INT;
7680 #endif
7681 goto str_init;
7682 case TOK_STR:
7683 /* string parsing */
7684 t = VT_BYTE;
7685 str_init:
7686 if (tcc_state->warn_write_strings)
7687 t |= VT_CONSTANT;
7688 type.t = t;
7689 mk_pointer(&type);
7690 type.t |= VT_ARRAY;
7691 memset(&ad, 0, sizeof(AttributeDef));
7692 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7693 break;
7694 case '(':
7695 next();
7696 /* cast ? */
7697 if (parse_btype(&type, &ad)) {
7698 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7699 skip(')');
7700 /* check ISOC99 compound literal */
7701 if (tok == '{') {
7702 /* data is allocated locally by default */
7703 if (global_expr)
7704 r = VT_CONST;
7705 else
7706 r = VT_LOCAL;
7707 /* all except arrays are lvalues */
7708 if (!(type.t & VT_ARRAY))
7709 r |= lvalue_type(type.t);
7710 memset(&ad, 0, sizeof(AttributeDef));
7711 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7712 } else {
7713 unary();
7714 gen_cast(&type);
7716 } else if (tok == '{') {
7717 /* save all registers */
7718 save_regs(0);
7719 /* statement expression : we do not accept break/continue
7720 inside as GCC does */
7721 block(NULL, NULL, NULL, NULL, 0, 1);
7722 skip(')');
7723 } else {
7724 gexpr();
7725 skip(')');
7727 break;
7728 case '*':
7729 next();
7730 unary();
7731 indir();
7732 break;
7733 case '&':
7734 next();
7735 unary();
7736 /* functions names must be treated as function pointers,
7737 except for unary '&' and sizeof. Since we consider that
7738 functions are not lvalues, we only have to handle it
7739 there and in function calls. */
7740 /* arrays can also be used although they are not lvalues */
7741 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7742 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7743 test_lvalue();
7744 mk_pointer(&vtop->type);
7745 gaddrof();
7746 break;
7747 case '!':
7748 next();
7749 unary();
7750 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
7751 CType boolean;
7752 boolean.t = VT_BOOL;
7753 gen_cast(&boolean);
7754 vtop->c.i = !vtop->c.i;
7755 } else if ((vtop->r & VT_VALMASK) == VT_CMP)
7756 vtop->c.i = vtop->c.i ^ 1;
7757 else {
7758 save_regs(1);
7759 vseti(VT_JMP, gtst(1, 0));
7761 break;
7762 case '~':
7763 next();
7764 unary();
7765 vpushi(-1);
7766 gen_op('^');
7767 break;
7768 case '+':
7769 next();
7770 /* in order to force cast, we add zero */
7771 unary();
7772 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7773 error("pointer not accepted for unary plus");
7774 vpushi(0);
7775 gen_op('+');
7776 break;
7777 case TOK_SIZEOF:
7778 case TOK_ALIGNOF1:
7779 case TOK_ALIGNOF2:
7780 t = tok;
7781 next();
7782 if (tok == '(') {
7783 parse_expr_type(&type);
7784 } else {
7785 unary_type(&type);
7787 size = type_size(&type, &align);
7788 if (t == TOK_SIZEOF) {
7789 if (size < 0)
7790 error("sizeof applied to an incomplete type");
7791 vpushi(size);
7792 } else {
7793 vpushi(align);
7795 vtop->type.t |= VT_UNSIGNED;
7796 break;
7798 case TOK_builtin_types_compatible_p:
7800 CType type1, type2;
7801 next();
7802 skip('(');
7803 parse_type(&type1);
7804 skip(',');
7805 parse_type(&type2);
7806 skip(')');
7807 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7808 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7809 vpushi(is_compatible_types(&type1, &type2));
7811 break;
7812 case TOK_builtin_constant_p:
7814 int saved_nocode_wanted, res;
7815 next();
7816 skip('(');
7817 saved_nocode_wanted = nocode_wanted;
7818 nocode_wanted = 1;
7819 gexpr();
7820 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7821 vpop();
7822 nocode_wanted = saved_nocode_wanted;
7823 skip(')');
7824 vpushi(res);
7826 break;
7827 case TOK_builtin_frame_address:
7829 CType type;
7830 next();
7831 skip('(');
7832 if (tok != TOK_CINT) {
7833 error("__builtin_frame_address only takes integers");
7835 if (tokc.i != 0) {
7836 error("TCC only supports __builtin_frame_address(0)");
7838 next();
7839 skip(')');
7840 type.t = VT_VOID;
7841 mk_pointer(&type);
7842 vset(&type, VT_LOCAL, 0);
7844 break;
7845 #ifdef TCC_TARGET_X86_64
7846 case TOK_builtin_malloc:
7847 tok = TOK_malloc;
7848 goto tok_identifier;
7849 case TOK_builtin_free:
7850 tok = TOK_free;
7851 goto tok_identifier;
7852 #endif
7853 case TOK_INC:
7854 case TOK_DEC:
7855 t = tok;
7856 next();
7857 unary();
7858 inc(0, t);
7859 break;
7860 case '-':
7861 next();
7862 vpushi(0);
7863 unary();
7864 gen_op('-');
7865 break;
7866 case TOK_LAND:
7867 if (!gnu_ext)
7868 goto tok_identifier;
7869 next();
7870 /* allow to take the address of a label */
7871 if (tok < TOK_UIDENT)
7872 expect("label identifier");
7873 s = label_find(tok);
7874 if (!s) {
7875 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7876 } else {
7877 if (s->r == LABEL_DECLARED)
7878 s->r = LABEL_FORWARD;
7880 if (!s->type.t) {
7881 s->type.t = VT_VOID;
7882 mk_pointer(&s->type);
7883 s->type.t |= VT_STATIC;
7885 vset(&s->type, VT_CONST | VT_SYM, 0);
7886 vtop->sym = s;
7887 next();
7888 break;
7889 default:
7890 tok_identifier:
7891 t = tok;
7892 next();
7893 if (t < TOK_UIDENT)
7894 expect("identifier");
7895 s = sym_find(t);
7896 if (!s) {
7897 if (tok != '(')
7898 error("'%s' undeclared", get_tok_str(t, NULL));
7899 /* for simple function calls, we tolerate undeclared
7900 external reference to int() function */
7901 if (tcc_state->warn_implicit_function_declaration)
7902 warning("implicit declaration of function '%s'",
7903 get_tok_str(t, NULL));
7904 s = external_global_sym(t, &func_old_type, 0);
7906 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7907 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7908 /* if referencing an inline function, then we generate a
7909 symbol to it if not already done. It will have the
7910 effect to generate code for it at the end of the
7911 compilation unit. Inline function as always
7912 generated in the text section. */
7913 if (!s->c)
7914 put_extern_sym(s, text_section, 0, 0);
7915 r = VT_SYM | VT_CONST;
7916 } else {
7917 r = s->r;
7919 vset(&s->type, r, s->c);
7920 /* if forward reference, we must point to s */
7921 if (vtop->r & VT_SYM) {
7922 vtop->sym = s;
7923 vtop->c.ul = 0;
7925 break;
7928 /* post operations */
7929 while (1) {
7930 if (tok == TOK_INC || tok == TOK_DEC) {
7931 inc(1, tok);
7932 next();
7933 } else if (tok == '.' || tok == TOK_ARROW) {
7934 /* field */
7935 if (tok == TOK_ARROW)
7936 indir();
7937 test_lvalue();
7938 gaddrof();
7939 next();
7940 /* expect pointer on structure */
7941 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7942 expect("struct or union");
7943 s = vtop->type.ref;
7944 /* find field */
7945 tok |= SYM_FIELD;
7946 while ((s = s->next) != NULL) {
7947 if (s->v == tok)
7948 break;
7950 if (!s)
7951 error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL));
7952 /* add field offset to pointer */
7953 vtop->type = char_pointer_type; /* change type to 'char *' */
7954 vpushi(s->c);
7955 gen_op('+');
7956 /* change type to field type, and set to lvalue */
7957 vtop->type = s->type;
7958 /* an array is never an lvalue */
7959 if (!(vtop->type.t & VT_ARRAY)) {
7960 vtop->r |= lvalue_type(vtop->type.t);
7961 /* if bound checking, the referenced pointer must be checked */
7962 if (do_bounds_check)
7963 vtop->r |= VT_MUSTBOUND;
7965 next();
7966 } else if (tok == '[') {
7967 next();
7968 gexpr();
7969 gen_op('+');
7970 indir();
7971 skip(']');
7972 } else if (tok == '(') {
7973 SValue ret;
7974 Sym *sa;
7975 int nb_args;
7977 /* function call */
7978 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7979 /* pointer test (no array accepted) */
7980 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7981 vtop->type = *pointed_type(&vtop->type);
7982 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7983 goto error_func;
7984 } else {
7985 error_func:
7986 expect("function pointer");
7988 } else {
7989 vtop->r &= ~VT_LVAL; /* no lvalue */
7991 /* get return type */
7992 s = vtop->type.ref;
7993 next();
7994 sa = s->next; /* first parameter */
7995 nb_args = 0;
7996 ret.r2 = VT_CONST;
7997 /* compute first implicit argument if a structure is returned */
7998 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7999 /* get some space for the returned structure */
8000 size = type_size(&s->type, &align);
8001 loc = (loc - size) & -align;
8002 ret.type = s->type;
8003 ret.r = VT_LOCAL | VT_LVAL;
8004 /* pass it as 'int' to avoid structure arg passing
8005 problems */
8006 vseti(VT_LOCAL, loc);
8007 ret.c = vtop->c;
8008 nb_args++;
8009 } else {
8010 ret.type = s->type;
8011 /* return in register */
8012 if (is_float(ret.type.t)) {
8013 ret.r = reg_fret(ret.type.t);
8014 } else {
8015 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
8016 ret.r2 = REG_LRET;
8017 ret.r = REG_IRET;
8019 ret.c.i = 0;
8021 if (tok != ')') {
8022 for(;;) {
8023 expr_eq();
8024 gfunc_param_typed(s, sa);
8025 nb_args++;
8026 if (sa)
8027 sa = sa->next;
8028 if (tok == ')')
8029 break;
8030 skip(',');
8033 if (sa)
8034 error("too few arguments to function");
8035 skip(')');
8036 if (!nocode_wanted) {
8037 gfunc_call(nb_args);
8038 } else {
8039 vtop -= (nb_args + 1);
8041 /* return value */
8042 vsetc(&ret.type, ret.r, &ret.c);
8043 vtop->r2 = ret.r2;
8044 } else {
8045 break;
8050 static void uneq(void)
8052 int t;
8054 unary();
8055 if (tok == '=' ||
8056 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
8057 tok == TOK_A_XOR || tok == TOK_A_OR ||
8058 tok == TOK_A_SHL || tok == TOK_A_SAR) {
8059 test_lvalue();
8060 t = tok;
8061 next();
8062 if (t == '=') {
8063 expr_eq();
8064 } else {
8065 vdup();
8066 expr_eq();
8067 gen_op(t & 0x7f);
8069 vstore();
8073 static void expr_prod(void)
8075 int t;
8077 uneq();
8078 while (tok == '*' || tok == '/' || tok == '%') {
8079 t = tok;
8080 next();
8081 uneq();
8082 gen_op(t);
8086 static void expr_sum(void)
8088 int t;
8090 expr_prod();
8091 while (tok == '+' || tok == '-') {
8092 t = tok;
8093 next();
8094 expr_prod();
8095 gen_op(t);
8099 static void expr_shift(void)
8101 int t;
8103 expr_sum();
8104 while (tok == TOK_SHL || tok == TOK_SAR) {
8105 t = tok;
8106 next();
8107 expr_sum();
8108 gen_op(t);
8112 static void expr_cmp(void)
8114 int t;
8116 expr_shift();
8117 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
8118 tok == TOK_ULT || tok == TOK_UGE) {
8119 t = tok;
8120 next();
8121 expr_shift();
8122 gen_op(t);
8126 static void expr_cmpeq(void)
8128 int t;
8130 expr_cmp();
8131 while (tok == TOK_EQ || tok == TOK_NE) {
8132 t = tok;
8133 next();
8134 expr_cmp();
8135 gen_op(t);
8139 static void expr_and(void)
8141 expr_cmpeq();
8142 while (tok == '&') {
8143 next();
8144 expr_cmpeq();
8145 gen_op('&');
8149 static void expr_xor(void)
8151 expr_and();
8152 while (tok == '^') {
8153 next();
8154 expr_and();
8155 gen_op('^');
8159 static void expr_or(void)
8161 expr_xor();
8162 while (tok == '|') {
8163 next();
8164 expr_xor();
8165 gen_op('|');
8169 /* XXX: fix this mess */
8170 static void expr_land_const(void)
8172 expr_or();
8173 while (tok == TOK_LAND) {
8174 next();
8175 expr_or();
8176 gen_op(TOK_LAND);
8180 /* XXX: fix this mess */
8181 static void expr_lor_const(void)
8183 expr_land_const();
8184 while (tok == TOK_LOR) {
8185 next();
8186 expr_land_const();
8187 gen_op(TOK_LOR);
8191 /* only used if non constant */
8192 static void expr_land(void)
8194 int t;
8196 expr_or();
8197 if (tok == TOK_LAND) {
8198 t = 0;
8199 save_regs(1);
8200 for(;;) {
8201 t = gtst(1, t);
8202 if (tok != TOK_LAND) {
8203 vseti(VT_JMPI, t);
8204 break;
8206 next();
8207 expr_or();
8212 static void expr_lor(void)
8214 int t;
8216 expr_land();
8217 if (tok == TOK_LOR) {
8218 t = 0;
8219 save_regs(1);
8220 for(;;) {
8221 t = gtst(0, t);
8222 if (tok != TOK_LOR) {
8223 vseti(VT_JMP, t);
8224 break;
8226 next();
8227 expr_land();
8232 /* XXX: better constant handling */
8233 static void expr_eq(void)
8235 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
8236 SValue sv;
8237 CType type, type1, type2;
8239 if (const_wanted) {
8240 expr_lor_const();
8241 if (tok == '?') {
8242 CType boolean;
8243 int c;
8244 boolean.t = VT_BOOL;
8245 vdup();
8246 gen_cast(&boolean);
8247 c = vtop->c.i;
8248 vpop();
8249 next();
8250 if (tok != ':' || !gnu_ext) {
8251 vpop();
8252 gexpr();
8254 if (!c)
8255 vpop();
8256 skip(':');
8257 expr_eq();
8258 if (c)
8259 vpop();
8261 } else {
8262 expr_lor();
8263 if (tok == '?') {
8264 next();
8265 if (vtop != vstack) {
8266 /* needed to avoid having different registers saved in
8267 each branch */
8268 if (is_float(vtop->type.t)) {
8269 rc = RC_FLOAT;
8270 #ifdef TCC_TARGET_X86_64
8271 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
8272 rc = RC_ST0;
8274 #endif
8276 else
8277 rc = RC_INT;
8278 gv(rc);
8279 save_regs(1);
8281 if (tok == ':' && gnu_ext) {
8282 gv_dup();
8283 tt = gtst(1, 0);
8284 } else {
8285 tt = gtst(1, 0);
8286 gexpr();
8288 type1 = vtop->type;
8289 sv = *vtop; /* save value to handle it later */
8290 vtop--; /* no vpop so that FP stack is not flushed */
8291 skip(':');
8292 u = gjmp(0);
8293 gsym(tt);
8294 expr_eq();
8295 type2 = vtop->type;
8297 t1 = type1.t;
8298 bt1 = t1 & VT_BTYPE;
8299 t2 = type2.t;
8300 bt2 = t2 & VT_BTYPE;
8301 /* cast operands to correct type according to ISOC rules */
8302 if (is_float(bt1) || is_float(bt2)) {
8303 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
8304 type.t = VT_LDOUBLE;
8305 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
8306 type.t = VT_DOUBLE;
8307 } else {
8308 type.t = VT_FLOAT;
8310 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
8311 /* cast to biggest op */
8312 type.t = VT_LLONG;
8313 /* convert to unsigned if it does not fit in a long long */
8314 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
8315 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
8316 type.t |= VT_UNSIGNED;
8317 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
8318 /* XXX: test pointer compatibility */
8319 type = type1;
8320 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
8321 /* XXX: test function pointer compatibility */
8322 type = type1;
8323 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
8324 /* XXX: test structure compatibility */
8325 type = type1;
8326 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
8327 /* NOTE: as an extension, we accept void on only one side */
8328 type.t = VT_VOID;
8329 } else {
8330 /* integer operations */
8331 type.t = VT_INT;
8332 /* convert to unsigned if it does not fit in an integer */
8333 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
8334 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
8335 type.t |= VT_UNSIGNED;
8338 /* now we convert second operand */
8339 gen_cast(&type);
8340 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8341 gaddrof();
8342 rc = RC_INT;
8343 if (is_float(type.t)) {
8344 rc = RC_FLOAT;
8345 #ifdef TCC_TARGET_X86_64
8346 if ((type.t & VT_BTYPE) == VT_LDOUBLE) {
8347 rc = RC_ST0;
8349 #endif
8350 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
8351 /* for long longs, we use fixed registers to avoid having
8352 to handle a complicated move */
8353 rc = RC_IRET;
8356 r2 = gv(rc);
8357 /* this is horrible, but we must also convert first
8358 operand */
8359 tt = gjmp(0);
8360 gsym(u);
8361 /* put again first value and cast it */
8362 *vtop = sv;
8363 gen_cast(&type);
8364 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8365 gaddrof();
8366 r1 = gv(rc);
8367 move_reg(r2, r1);
8368 vtop->r = r2;
8369 gsym(tt);
8374 static void gexpr(void)
8376 while (1) {
8377 expr_eq();
8378 if (tok != ',')
8379 break;
8380 vpop();
8381 next();
8385 /* parse an expression and return its type without any side effect. */
8386 static void expr_type(CType *type)
8388 int saved_nocode_wanted;
8390 saved_nocode_wanted = nocode_wanted;
8391 nocode_wanted = 1;
8392 gexpr();
8393 *type = vtop->type;
8394 vpop();
8395 nocode_wanted = saved_nocode_wanted;
8398 /* parse a unary expression and return its type without any side
8399 effect. */
8400 static void unary_type(CType *type)
8402 int a;
8404 a = nocode_wanted;
8405 nocode_wanted = 1;
8406 unary();
8407 *type = vtop->type;
8408 vpop();
8409 nocode_wanted = a;
8412 /* parse a constant expression and return value in vtop. */
8413 static void expr_const1(void)
8415 int a;
8416 a = const_wanted;
8417 const_wanted = 1;
8418 expr_eq();
8419 const_wanted = a;
8422 /* parse an integer constant and return its value. */
8423 static int expr_const(void)
8425 int c;
8426 expr_const1();
8427 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8428 expect("constant expression");
8429 c = vtop->c.i;
8430 vpop();
8431 return c;
8434 /* return the label token if current token is a label, otherwise
8435 return zero */
8436 static int is_label(void)
8438 int last_tok;
8440 /* fast test first */
8441 if (tok < TOK_UIDENT)
8442 return 0;
8443 /* no need to save tokc because tok is an identifier */
8444 last_tok = tok;
8445 next();
8446 if (tok == ':') {
8447 next();
8448 return last_tok;
8449 } else {
8450 unget_tok(last_tok);
8451 return 0;
8455 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8456 int case_reg, int is_expr)
8458 int a, b, c, d;
8459 Sym *s;
8461 /* generate line number info */
8462 if (do_debug &&
8463 (last_line_num != file->line_num || last_ind != ind)) {
8464 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8465 last_ind = ind;
8466 last_line_num = file->line_num;
8469 if (is_expr) {
8470 /* default return value is (void) */
8471 vpushi(0);
8472 vtop->type.t = VT_VOID;
8475 if (tok == TOK_IF) {
8476 /* if test */
8477 next();
8478 skip('(');
8479 gexpr();
8480 skip(')');
8481 a = gtst(1, 0);
8482 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8483 c = tok;
8484 if (c == TOK_ELSE) {
8485 next();
8486 d = gjmp(0);
8487 gsym(a);
8488 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8489 gsym(d); /* patch else jmp */
8490 } else
8491 gsym(a);
8492 } else if (tok == TOK_WHILE) {
8493 next();
8494 d = ind;
8495 skip('(');
8496 gexpr();
8497 skip(')');
8498 a = gtst(1, 0);
8499 b = 0;
8500 block(&a, &b, case_sym, def_sym, case_reg, 0);
8501 gjmp_addr(d);
8502 gsym(a);
8503 gsym_addr(b, d);
8504 } else if (tok == '{') {
8505 Sym *llabel;
8507 next();
8508 /* record local declaration stack position */
8509 s = local_stack;
8510 llabel = local_label_stack;
8511 /* handle local labels declarations */
8512 if (tok == TOK_LABEL) {
8513 next();
8514 for(;;) {
8515 if (tok < TOK_UIDENT)
8516 expect("label identifier");
8517 label_push(&local_label_stack, tok, LABEL_DECLARED);
8518 next();
8519 if (tok == ',') {
8520 next();
8521 } else {
8522 skip(';');
8523 break;
8527 while (tok != '}') {
8528 decl(VT_LOCAL);
8529 if (tok != '}') {
8530 if (is_expr)
8531 vpop();
8532 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8535 /* pop locally defined labels */
8536 label_pop(&local_label_stack, llabel);
8537 /* pop locally defined symbols */
8538 if(is_expr) {
8539 /* XXX: this solution makes only valgrind happy...
8540 triggered by gcc.c-torture/execute/20000917-1.c */
8541 Sym *p;
8542 switch(vtop->type.t & VT_BTYPE) {
8543 case VT_PTR:
8544 case VT_STRUCT:
8545 case VT_ENUM:
8546 case VT_FUNC:
8547 for(p=vtop->type.ref;p;p=p->prev)
8548 if(p->prev==s)
8549 error("unsupported expression type");
8552 sym_pop(&local_stack, s);
8553 next();
8554 } else if (tok == TOK_RETURN) {
8555 next();
8556 if (tok != ';') {
8557 gexpr();
8558 gen_assign_cast(&func_vt);
8559 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8560 CType type;
8561 /* if returning structure, must copy it to implicit
8562 first pointer arg location */
8563 #ifdef TCC_ARM_EABI
8564 int align, size;
8565 size = type_size(&func_vt,&align);
8566 if(size <= 4)
8568 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8569 && (align & 3))
8571 int addr;
8572 loc = (loc - size) & -4;
8573 addr = loc;
8574 type = func_vt;
8575 vset(&type, VT_LOCAL | VT_LVAL, addr);
8576 vswap();
8577 vstore();
8578 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8580 vtop->type = int_type;
8581 gv(RC_IRET);
8582 } else {
8583 #endif
8584 type = func_vt;
8585 mk_pointer(&type);
8586 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8587 indir();
8588 vswap();
8589 /* copy structure value to pointer */
8590 vstore();
8591 #ifdef TCC_ARM_EABI
8593 #endif
8594 } else if (is_float(func_vt.t)) {
8595 gv(rc_fret(func_vt.t));
8596 } else {
8597 gv(RC_IRET);
8599 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8601 skip(';');
8602 rsym = gjmp(rsym); /* jmp */
8603 } else if (tok == TOK_BREAK) {
8604 /* compute jump */
8605 if (!bsym)
8606 error("cannot break");
8607 *bsym = gjmp(*bsym);
8608 next();
8609 skip(';');
8610 } else if (tok == TOK_CONTINUE) {
8611 /* compute jump */
8612 if (!csym)
8613 error("cannot continue");
8614 *csym = gjmp(*csym);
8615 next();
8616 skip(';');
8617 } else if (tok == TOK_FOR) {
8618 int e;
8619 next();
8620 skip('(');
8621 if (tok != ';') {
8622 gexpr();
8623 vpop();
8625 skip(';');
8626 d = ind;
8627 c = ind;
8628 a = 0;
8629 b = 0;
8630 if (tok != ';') {
8631 gexpr();
8632 a = gtst(1, 0);
8634 skip(';');
8635 if (tok != ')') {
8636 e = gjmp(0);
8637 c = ind;
8638 gexpr();
8639 vpop();
8640 gjmp_addr(d);
8641 gsym(e);
8643 skip(')');
8644 block(&a, &b, case_sym, def_sym, case_reg, 0);
8645 gjmp_addr(c);
8646 gsym(a);
8647 gsym_addr(b, c);
8648 } else
8649 if (tok == TOK_DO) {
8650 next();
8651 a = 0;
8652 b = 0;
8653 d = ind;
8654 block(&a, &b, case_sym, def_sym, case_reg, 0);
8655 skip(TOK_WHILE);
8656 skip('(');
8657 gsym(b);
8658 gexpr();
8659 c = gtst(0, 0);
8660 gsym_addr(c, d);
8661 skip(')');
8662 gsym(a);
8663 skip(';');
8664 } else
8665 if (tok == TOK_SWITCH) {
8666 next();
8667 skip('(');
8668 gexpr();
8669 /* XXX: other types than integer */
8670 case_reg = gv(RC_INT);
8671 vpop();
8672 skip(')');
8673 a = 0;
8674 b = gjmp(0); /* jump to first case */
8675 c = 0;
8676 block(&a, csym, &b, &c, case_reg, 0);
8677 /* if no default, jmp after switch */
8678 if (c == 0)
8679 c = ind;
8680 /* default label */
8681 gsym_addr(b, c);
8682 /* break label */
8683 gsym(a);
8684 } else
8685 if (tok == TOK_CASE) {
8686 int v1, v2;
8687 if (!case_sym)
8688 expect("switch");
8689 next();
8690 v1 = expr_const();
8691 v2 = v1;
8692 if (gnu_ext && tok == TOK_DOTS) {
8693 next();
8694 v2 = expr_const();
8695 if (v2 < v1)
8696 warning("empty case range");
8698 /* since a case is like a label, we must skip it with a jmp */
8699 b = gjmp(0);
8700 gsym(*case_sym);
8701 vseti(case_reg, 0);
8702 vpushi(v1);
8703 if (v1 == v2) {
8704 gen_op(TOK_EQ);
8705 *case_sym = gtst(1, 0);
8706 } else {
8707 gen_op(TOK_GE);
8708 *case_sym = gtst(1, 0);
8709 vseti(case_reg, 0);
8710 vpushi(v2);
8711 gen_op(TOK_LE);
8712 *case_sym = gtst(1, *case_sym);
8714 gsym(b);
8715 skip(':');
8716 is_expr = 0;
8717 goto block_after_label;
8718 } else
8719 if (tok == TOK_DEFAULT) {
8720 next();
8721 skip(':');
8722 if (!def_sym)
8723 expect("switch");
8724 if (*def_sym)
8725 error("too many 'default'");
8726 *def_sym = ind;
8727 is_expr = 0;
8728 goto block_after_label;
8729 } else
8730 if (tok == TOK_GOTO) {
8731 next();
8732 if (tok == '*' && gnu_ext) {
8733 /* computed goto */
8734 next();
8735 gexpr();
8736 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8737 expect("pointer");
8738 ggoto();
8739 } else if (tok >= TOK_UIDENT) {
8740 s = label_find(tok);
8741 /* put forward definition if needed */
8742 if (!s) {
8743 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8744 } else {
8745 if (s->r == LABEL_DECLARED)
8746 s->r = LABEL_FORWARD;
8748 /* label already defined */
8749 if (s->r & LABEL_FORWARD)
8750 s->next = (void *)gjmp((long)s->next);
8751 else
8752 gjmp_addr((long)s->next);
8753 next();
8754 } else {
8755 expect("label identifier");
8757 skip(';');
8758 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8759 asm_instr();
8760 } else {
8761 b = is_label();
8762 if (b) {
8763 /* label case */
8764 s = label_find(b);
8765 if (s) {
8766 if (s->r == LABEL_DEFINED)
8767 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8768 gsym((long)s->next);
8769 s->r = LABEL_DEFINED;
8770 } else {
8771 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8773 s->next = (void *)ind;
8774 /* we accept this, but it is a mistake */
8775 block_after_label:
8776 if (tok == '}') {
8777 warning("deprecated use of label at end of compound statement");
8778 } else {
8779 if (is_expr)
8780 vpop();
8781 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8783 } else {
8784 /* expression case */
8785 if (tok != ';') {
8786 if (is_expr) {
8787 vpop();
8788 gexpr();
8789 } else {
8790 gexpr();
8791 vpop();
8794 skip(';');
8799 /* t is the array or struct type. c is the array or struct
8800 address. cur_index/cur_field is the pointer to the current
8801 value. 'size_only' is true if only size info is needed (only used
8802 in arrays) */
8803 static void decl_designator(CType *type, Section *sec, unsigned long c,
8804 int *cur_index, Sym **cur_field,
8805 int size_only)
8807 Sym *s, *f;
8808 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8809 CType type1;
8811 notfirst = 0;
8812 elem_size = 0;
8813 nb_elems = 1;
8814 if (gnu_ext && (l = is_label()) != 0)
8815 goto struct_field;
8816 while (tok == '[' || tok == '.') {
8817 if (tok == '[') {
8818 if (!(type->t & VT_ARRAY))
8819 expect("array type");
8820 s = type->ref;
8821 next();
8822 index = expr_const();
8823 if (index < 0 || (s->c >= 0 && index >= s->c))
8824 expect("invalid index");
8825 if (tok == TOK_DOTS && gnu_ext) {
8826 next();
8827 index_last = expr_const();
8828 if (index_last < 0 ||
8829 (s->c >= 0 && index_last >= s->c) ||
8830 index_last < index)
8831 expect("invalid index");
8832 } else {
8833 index_last = index;
8835 skip(']');
8836 if (!notfirst)
8837 *cur_index = index_last;
8838 type = pointed_type(type);
8839 elem_size = type_size(type, &align);
8840 c += index * elem_size;
8841 /* NOTE: we only support ranges for last designator */
8842 nb_elems = index_last - index + 1;
8843 if (nb_elems != 1) {
8844 notfirst = 1;
8845 break;
8847 } else {
8848 next();
8849 l = tok;
8850 next();
8851 struct_field:
8852 if ((type->t & VT_BTYPE) != VT_STRUCT)
8853 expect("struct/union type");
8854 s = type->ref;
8855 l |= SYM_FIELD;
8856 f = s->next;
8857 while (f) {
8858 if (f->v == l)
8859 break;
8860 f = f->next;
8862 if (!f)
8863 expect("field");
8864 if (!notfirst)
8865 *cur_field = f;
8866 /* XXX: fix this mess by using explicit storage field */
8867 type1 = f->type;
8868 type1.t |= (type->t & ~VT_TYPE);
8869 type = &type1;
8870 c += f->c;
8872 notfirst = 1;
8874 if (notfirst) {
8875 if (tok == '=') {
8876 next();
8877 } else {
8878 if (!gnu_ext)
8879 expect("=");
8881 } else {
8882 if (type->t & VT_ARRAY) {
8883 index = *cur_index;
8884 type = pointed_type(type);
8885 c += index * type_size(type, &align);
8886 } else {
8887 f = *cur_field;
8888 if (!f)
8889 error("too many field init");
8890 /* XXX: fix this mess by using explicit storage field */
8891 type1 = f->type;
8892 type1.t |= (type->t & ~VT_TYPE);
8893 type = &type1;
8894 c += f->c;
8897 decl_initializer(type, sec, c, 0, size_only);
8899 /* XXX: make it more general */
8900 if (!size_only && nb_elems > 1) {
8901 unsigned long c_end;
8902 uint8_t *src, *dst;
8903 int i;
8905 if (!sec)
8906 error("range init not supported yet for dynamic storage");
8907 c_end = c + nb_elems * elem_size;
8908 if (c_end > sec->data_allocated)
8909 section_realloc(sec, c_end);
8910 src = sec->data + c;
8911 dst = src;
8912 for(i = 1; i < nb_elems; i++) {
8913 dst += elem_size;
8914 memcpy(dst, src, elem_size);
8919 #define EXPR_VAL 0
8920 #define EXPR_CONST 1
8921 #define EXPR_ANY 2
8923 /* store a value or an expression directly in global data or in local array */
8924 static void init_putv(CType *type, Section *sec, unsigned long c,
8925 int v, int expr_type)
8927 int saved_global_expr, bt, bit_pos, bit_size;
8928 void *ptr;
8929 unsigned long long bit_mask;
8930 CType dtype;
8932 switch(expr_type) {
8933 case EXPR_VAL:
8934 vpushi(v);
8935 break;
8936 case EXPR_CONST:
8937 /* compound literals must be allocated globally in this case */
8938 saved_global_expr = global_expr;
8939 global_expr = 1;
8940 expr_const1();
8941 global_expr = saved_global_expr;
8942 /* NOTE: symbols are accepted */
8943 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8944 error("initializer element is not constant");
8945 break;
8946 case EXPR_ANY:
8947 expr_eq();
8948 break;
8951 dtype = *type;
8952 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8954 if (sec) {
8955 /* XXX: not portable */
8956 /* XXX: generate error if incorrect relocation */
8957 gen_assign_cast(&dtype);
8958 bt = type->t & VT_BTYPE;
8959 /* we'll write at most 12 bytes */
8960 if (c + 12 > sec->data_allocated) {
8961 section_realloc(sec, c + 12);
8963 ptr = sec->data + c;
8964 /* XXX: make code faster ? */
8965 if (!(type->t & VT_BITFIELD)) {
8966 bit_pos = 0;
8967 bit_size = 32;
8968 bit_mask = -1LL;
8969 } else {
8970 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8971 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8972 bit_mask = (1LL << bit_size) - 1;
8974 if ((vtop->r & VT_SYM) &&
8975 (bt == VT_BYTE ||
8976 bt == VT_SHORT ||
8977 bt == VT_DOUBLE ||
8978 bt == VT_LDOUBLE ||
8979 bt == VT_LLONG ||
8980 (bt == VT_INT && bit_size != 32)))
8981 error("initializer element is not computable at load time");
8982 switch(bt) {
8983 case VT_BOOL:
8984 vtop->c.i = (vtop->c.i != 0);
8985 case VT_BYTE:
8986 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8987 break;
8988 case VT_SHORT:
8989 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8990 break;
8991 case VT_DOUBLE:
8992 *(double *)ptr = vtop->c.d;
8993 break;
8994 case VT_LDOUBLE:
8995 *(long double *)ptr = vtop->c.ld;
8996 break;
8997 case VT_LLONG:
8998 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8999 break;
9000 default:
9001 if (vtop->r & VT_SYM) {
9002 greloc(sec, vtop->sym, c, R_DATA_32);
9004 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
9005 break;
9007 vtop--;
9008 } else {
9009 vset(&dtype, VT_LOCAL|VT_LVAL, c);
9010 vswap();
9011 vstore();
9012 vpop();
9016 /* put zeros for variable based init */
9017 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
9019 if (sec) {
9020 /* nothing to do because globals are already set to zero */
9021 } else {
9022 vpush_global_sym(&func_old_type, TOK_memset);
9023 vseti(VT_LOCAL, c);
9024 vpushi(0);
9025 vpushi(size);
9026 gfunc_call(3);
9030 /* 't' contains the type and storage info. 'c' is the offset of the
9031 object in section 'sec'. If 'sec' is NULL, it means stack based
9032 allocation. 'first' is true if array '{' must be read (multi
9033 dimension implicit array init handling). 'size_only' is true if
9034 size only evaluation is wanted (only for arrays). */
9035 static void decl_initializer(CType *type, Section *sec, unsigned long c,
9036 int first, int size_only)
9038 int index, array_length, n, no_oblock, nb, parlevel, i;
9039 int size1, align1, expr_type;
9040 Sym *s, *f;
9041 CType *t1;
9043 if (type->t & VT_ARRAY) {
9044 s = type->ref;
9045 n = s->c;
9046 array_length = 0;
9047 t1 = pointed_type(type);
9048 size1 = type_size(t1, &align1);
9050 no_oblock = 1;
9051 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
9052 tok == '{') {
9053 skip('{');
9054 no_oblock = 0;
9057 /* only parse strings here if correct type (otherwise: handle
9058 them as ((w)char *) expressions */
9059 if ((tok == TOK_LSTR &&
9060 #ifdef TCC_TARGET_PE
9061 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
9062 #else
9063 (t1->t & VT_BTYPE) == VT_INT
9064 #endif
9065 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
9066 while (tok == TOK_STR || tok == TOK_LSTR) {
9067 int cstr_len, ch;
9068 CString *cstr;
9070 cstr = tokc.cstr;
9071 /* compute maximum number of chars wanted */
9072 if (tok == TOK_STR)
9073 cstr_len = cstr->size;
9074 else
9075 cstr_len = cstr->size / sizeof(nwchar_t);
9076 cstr_len--;
9077 nb = cstr_len;
9078 if (n >= 0 && nb > (n - array_length))
9079 nb = n - array_length;
9080 if (!size_only) {
9081 if (cstr_len > nb)
9082 warning("initializer-string for array is too long");
9083 /* in order to go faster for common case (char
9084 string in global variable, we handle it
9085 specifically */
9086 if (sec && tok == TOK_STR && size1 == 1) {
9087 memcpy(sec->data + c + array_length, cstr->data, nb);
9088 } else {
9089 for(i=0;i<nb;i++) {
9090 if (tok == TOK_STR)
9091 ch = ((unsigned char *)cstr->data)[i];
9092 else
9093 ch = ((nwchar_t *)cstr->data)[i];
9094 init_putv(t1, sec, c + (array_length + i) * size1,
9095 ch, EXPR_VAL);
9099 array_length += nb;
9100 next();
9102 /* only add trailing zero if enough storage (no
9103 warning in this case since it is standard) */
9104 if (n < 0 || array_length < n) {
9105 if (!size_only) {
9106 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
9108 array_length++;
9110 } else {
9111 index = 0;
9112 while (tok != '}') {
9113 decl_designator(type, sec, c, &index, NULL, size_only);
9114 if (n >= 0 && index >= n)
9115 error("index too large");
9116 /* must put zero in holes (note that doing it that way
9117 ensures that it even works with designators) */
9118 if (!size_only && array_length < index) {
9119 init_putz(t1, sec, c + array_length * size1,
9120 (index - array_length) * size1);
9122 index++;
9123 if (index > array_length)
9124 array_length = index;
9125 /* special test for multi dimensional arrays (may not
9126 be strictly correct if designators are used at the
9127 same time) */
9128 if (index >= n && no_oblock)
9129 break;
9130 if (tok == '}')
9131 break;
9132 skip(',');
9135 if (!no_oblock)
9136 skip('}');
9137 /* put zeros at the end */
9138 if (!size_only && n >= 0 && array_length < n) {
9139 init_putz(t1, sec, c + array_length * size1,
9140 (n - array_length) * size1);
9142 /* patch type size if needed */
9143 if (n < 0)
9144 s->c = array_length;
9145 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
9146 (sec || !first || tok == '{')) {
9147 int par_count;
9149 /* NOTE: the previous test is a specific case for automatic
9150 struct/union init */
9151 /* XXX: union needs only one init */
9153 /* XXX: this test is incorrect for local initializers
9154 beginning with ( without {. It would be much more difficult
9155 to do it correctly (ideally, the expression parser should
9156 be used in all cases) */
9157 par_count = 0;
9158 if (tok == '(') {
9159 AttributeDef ad1;
9160 CType type1;
9161 next();
9162 while (tok == '(') {
9163 par_count++;
9164 next();
9166 if (!parse_btype(&type1, &ad1))
9167 expect("cast");
9168 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
9169 #if 0
9170 if (!is_assignable_types(type, &type1))
9171 error("invalid type for cast");
9172 #endif
9173 skip(')');
9175 no_oblock = 1;
9176 if (first || tok == '{') {
9177 skip('{');
9178 no_oblock = 0;
9180 s = type->ref;
9181 f = s->next;
9182 array_length = 0;
9183 index = 0;
9184 n = s->c;
9185 while (tok != '}') {
9186 decl_designator(type, sec, c, NULL, &f, size_only);
9187 index = f->c;
9188 if (!size_only && array_length < index) {
9189 init_putz(type, sec, c + array_length,
9190 index - array_length);
9192 index = index + type_size(&f->type, &align1);
9193 if (index > array_length)
9194 array_length = index;
9195 f = f->next;
9196 if (no_oblock && f == NULL)
9197 break;
9198 if (tok == '}')
9199 break;
9200 skip(',');
9202 /* put zeros at the end */
9203 if (!size_only && array_length < n) {
9204 init_putz(type, sec, c + array_length,
9205 n - array_length);
9207 if (!no_oblock)
9208 skip('}');
9209 while (par_count) {
9210 skip(')');
9211 par_count--;
9213 } else if (tok == '{') {
9214 next();
9215 decl_initializer(type, sec, c, first, size_only);
9216 skip('}');
9217 } else if (size_only) {
9218 /* just skip expression */
9219 parlevel = 0;
9220 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
9221 tok != -1) {
9222 if (tok == '(')
9223 parlevel++;
9224 else if (tok == ')')
9225 parlevel--;
9226 next();
9228 } else {
9229 /* currently, we always use constant expression for globals
9230 (may change for scripting case) */
9231 expr_type = EXPR_CONST;
9232 if (!sec)
9233 expr_type = EXPR_ANY;
9234 init_putv(type, sec, c, 0, expr_type);
9238 /* parse an initializer for type 't' if 'has_init' is non zero, and
9239 allocate space in local or global data space ('r' is either
9240 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
9241 variable 'v' of scope 'scope' is declared before initializers are
9242 parsed. If 'v' is zero, then a reference to the new object is put
9243 in the value stack. If 'has_init' is 2, a special parsing is done
9244 to handle string constants. */
9245 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
9246 int has_init, int v, int scope)
9248 int size, align, addr, data_offset;
9249 int level;
9250 ParseState saved_parse_state = {0};
9251 TokenString init_str;
9252 Section *sec;
9254 size = type_size(type, &align);
9255 /* If unknown size, we must evaluate it before
9256 evaluating initializers because
9257 initializers can generate global data too
9258 (e.g. string pointers or ISOC99 compound
9259 literals). It also simplifies local
9260 initializers handling */
9261 tok_str_new(&init_str);
9262 if (size < 0) {
9263 if (!has_init)
9264 error("unknown type size");
9265 /* get all init string */
9266 if (has_init == 2) {
9267 /* only get strings */
9268 while (tok == TOK_STR || tok == TOK_LSTR) {
9269 tok_str_add_tok(&init_str);
9270 next();
9272 } else {
9273 level = 0;
9274 while (level > 0 || (tok != ',' && tok != ';')) {
9275 if (tok < 0)
9276 error("unexpected end of file in initializer");
9277 tok_str_add_tok(&init_str);
9278 if (tok == '{')
9279 level++;
9280 else if (tok == '}') {
9281 level--;
9282 if (level <= 0) {
9283 next();
9284 break;
9287 next();
9290 tok_str_add(&init_str, -1);
9291 tok_str_add(&init_str, 0);
9293 /* compute size */
9294 save_parse_state(&saved_parse_state);
9296 macro_ptr = init_str.str;
9297 next();
9298 decl_initializer(type, NULL, 0, 1, 1);
9299 /* prepare second initializer parsing */
9300 macro_ptr = init_str.str;
9301 next();
9303 /* if still unknown size, error */
9304 size = type_size(type, &align);
9305 if (size < 0)
9306 error("unknown type size");
9308 /* take into account specified alignment if bigger */
9309 if (ad->aligned) {
9310 if (ad->aligned > align)
9311 align = ad->aligned;
9312 } else if (ad->packed) {
9313 align = 1;
9315 if ((r & VT_VALMASK) == VT_LOCAL) {
9316 sec = NULL;
9317 if (do_bounds_check && (type->t & VT_ARRAY))
9318 loc--;
9319 loc = (loc - size) & -align;
9320 addr = loc;
9321 /* handles bounds */
9322 /* XXX: currently, since we do only one pass, we cannot track
9323 '&' operators, so we add only arrays */
9324 if (do_bounds_check && (type->t & VT_ARRAY)) {
9325 unsigned long *bounds_ptr;
9326 /* add padding between regions */
9327 loc--;
9328 /* then add local bound info */
9329 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
9330 bounds_ptr[0] = addr;
9331 bounds_ptr[1] = size;
9333 if (v) {
9334 /* local variable */
9335 sym_push(v, type, r, addr);
9336 } else {
9337 /* push local reference */
9338 vset(type, r, addr);
9340 } else {
9341 Sym *sym;
9343 sym = NULL;
9344 if (v && scope == VT_CONST) {
9345 /* see if the symbol was already defined */
9346 sym = sym_find(v);
9347 if (sym) {
9348 if (!is_compatible_types(&sym->type, type))
9349 error("incompatible types for redefinition of '%s'",
9350 get_tok_str(v, NULL));
9351 if (sym->type.t & VT_EXTERN) {
9352 /* if the variable is extern, it was not allocated */
9353 sym->type.t &= ~VT_EXTERN;
9354 /* set array size if it was ommited in extern
9355 declaration */
9356 if ((sym->type.t & VT_ARRAY) &&
9357 sym->type.ref->c < 0 &&
9358 type->ref->c >= 0)
9359 sym->type.ref->c = type->ref->c;
9360 } else {
9361 /* we accept several definitions of the same
9362 global variable. this is tricky, because we
9363 must play with the SHN_COMMON type of the symbol */
9364 /* XXX: should check if the variable was already
9365 initialized. It is incorrect to initialized it
9366 twice */
9367 /* no init data, we won't add more to the symbol */
9368 if (!has_init)
9369 goto no_alloc;
9374 /* allocate symbol in corresponding section */
9375 sec = ad->section;
9376 if (!sec) {
9377 if (has_init)
9378 sec = data_section;
9379 else if (tcc_state->nocommon)
9380 sec = bss_section;
9382 if (sec) {
9383 data_offset = sec->data_offset;
9384 data_offset = (data_offset + align - 1) & -align;
9385 addr = data_offset;
9386 /* very important to increment global pointer at this time
9387 because initializers themselves can create new initializers */
9388 data_offset += size;
9389 /* add padding if bound check */
9390 if (do_bounds_check)
9391 data_offset++;
9392 sec->data_offset = data_offset;
9393 /* allocate section space to put the data */
9394 if (sec->sh_type != SHT_NOBITS &&
9395 data_offset > sec->data_allocated)
9396 section_realloc(sec, data_offset);
9397 /* align section if needed */
9398 if (align > sec->sh_addralign)
9399 sec->sh_addralign = align;
9400 } else {
9401 addr = 0; /* avoid warning */
9404 if (v) {
9405 if (scope != VT_CONST || !sym) {
9406 sym = sym_push(v, type, r | VT_SYM, 0);
9408 /* update symbol definition */
9409 if (sec) {
9410 put_extern_sym(sym, sec, addr, size);
9411 } else {
9412 ElfW(Sym) *esym;
9413 /* put a common area */
9414 put_extern_sym(sym, NULL, align, size);
9415 /* XXX: find a nicer way */
9416 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
9417 esym->st_shndx = SHN_COMMON;
9419 } else {
9420 CValue cval;
9422 /* push global reference */
9423 sym = get_sym_ref(type, sec, addr, size);
9424 cval.ul = 0;
9425 vsetc(type, VT_CONST | VT_SYM, &cval);
9426 vtop->sym = sym;
9429 /* handles bounds now because the symbol must be defined
9430 before for the relocation */
9431 if (do_bounds_check) {
9432 unsigned long *bounds_ptr;
9434 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9435 /* then add global bound info */
9436 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9437 bounds_ptr[0] = 0; /* relocated */
9438 bounds_ptr[1] = size;
9441 if (has_init) {
9442 decl_initializer(type, sec, addr, 1, 0);
9443 /* restore parse state if needed */
9444 if (init_str.str) {
9445 tok_str_free(init_str.str);
9446 restore_parse_state(&saved_parse_state);
9449 no_alloc: ;
9452 void put_func_debug(Sym *sym)
9454 char buf[512];
9456 /* stabs info */
9457 /* XXX: we put here a dummy type */
9458 snprintf(buf, sizeof(buf), "%s:%c1",
9459 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9460 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9461 cur_text_section, sym->c);
9462 /* //gr gdb wants a line at the function */
9463 put_stabn(N_SLINE, 0, file->line_num, 0);
9464 last_ind = 0;
9465 last_line_num = 0;
9468 /* parse an old style function declaration list */
9469 /* XXX: check multiple parameter */
9470 static void func_decl_list(Sym *func_sym)
9472 AttributeDef ad;
9473 int v;
9474 Sym *s;
9475 CType btype, type;
9477 /* parse each declaration */
9478 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9479 if (!parse_btype(&btype, &ad))
9480 expect("declaration list");
9481 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9482 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9483 tok == ';') {
9484 /* we accept no variable after */
9485 } else {
9486 for(;;) {
9487 type = btype;
9488 type_decl(&type, &ad, &v, TYPE_DIRECT);
9489 /* find parameter in function parameter list */
9490 s = func_sym->next;
9491 while (s != NULL) {
9492 if ((s->v & ~SYM_FIELD) == v)
9493 goto found;
9494 s = s->next;
9496 error("declaration for parameter '%s' but no such parameter",
9497 get_tok_str(v, NULL));
9498 found:
9499 /* check that no storage specifier except 'register' was given */
9500 if (type.t & VT_STORAGE)
9501 error("storage class specified for '%s'", get_tok_str(v, NULL));
9502 convert_parameter_type(&type);
9503 /* we can add the type (NOTE: it could be local to the function) */
9504 s->type = type;
9505 /* accept other parameters */
9506 if (tok == ',')
9507 next();
9508 else
9509 break;
9512 skip(';');
9516 /* parse a function defined by symbol 'sym' and generate its code in
9517 'cur_text_section' */
9518 static void gen_function(Sym *sym)
9520 int saved_nocode_wanted = nocode_wanted;
9521 nocode_wanted = 0;
9522 ind = cur_text_section->data_offset;
9523 /* NOTE: we patch the symbol size later */
9524 put_extern_sym(sym, cur_text_section, ind, 0);
9525 funcname = get_tok_str(sym->v, NULL);
9526 func_ind = ind;
9527 /* put debug symbol */
9528 if (do_debug)
9529 put_func_debug(sym);
9530 /* push a dummy symbol to enable local sym storage */
9531 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9532 gfunc_prolog(&sym->type);
9533 rsym = 0;
9534 block(NULL, NULL, NULL, NULL, 0, 0);
9535 gsym(rsym);
9536 gfunc_epilog();
9537 cur_text_section->data_offset = ind;
9538 label_pop(&global_label_stack, NULL);
9539 sym_pop(&local_stack, NULL); /* reset local stack */
9540 /* end of function */
9541 /* patch symbol size */
9542 ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size =
9543 ind - func_ind;
9544 if (do_debug) {
9545 put_stabn(N_FUN, 0, 0, ind - func_ind);
9547 /* It's better to crash than to generate wrong code */
9548 cur_text_section = NULL;
9549 funcname = ""; /* for safety */
9550 func_vt.t = VT_VOID; /* for safety */
9551 ind = 0; /* for safety */
9552 nocode_wanted = saved_nocode_wanted;
9555 static void gen_inline_functions(void)
9557 Sym *sym;
9558 CType *type;
9559 int *str, inline_generated;
9561 /* iterate while inline function are referenced */
9562 for(;;) {
9563 inline_generated = 0;
9564 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9565 type = &sym->type;
9566 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9567 (type->t & (VT_STATIC | VT_INLINE)) ==
9568 (VT_STATIC | VT_INLINE) &&
9569 sym->c != 0) {
9570 /* the function was used: generate its code and
9571 convert it to a normal function */
9572 str = INLINE_DEF(sym->r);
9573 sym->r = VT_SYM | VT_CONST;
9574 sym->type.t &= ~VT_INLINE;
9576 macro_ptr = str;
9577 next();
9578 cur_text_section = text_section;
9579 gen_function(sym);
9580 macro_ptr = NULL; /* fail safe */
9582 tok_str_free(str);
9583 inline_generated = 1;
9586 if (!inline_generated)
9587 break;
9590 /* free all remaining inline function tokens */
9591 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9592 type = &sym->type;
9593 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9594 (type->t & (VT_STATIC | VT_INLINE)) ==
9595 (VT_STATIC | VT_INLINE)) {
9596 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9597 if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
9598 continue;
9599 str = INLINE_DEF(sym->r);
9600 tok_str_free(str);
9601 sym->r = 0; /* fail safe */
9606 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9607 static void decl(int l)
9609 int v, has_init, r;
9610 CType type, btype;
9611 Sym *sym;
9612 AttributeDef ad;
9614 while (1) {
9615 if (!parse_btype(&btype, &ad)) {
9616 /* skip redundant ';' */
9617 /* XXX: find more elegant solution */
9618 if (tok == ';') {
9619 next();
9620 continue;
9622 if (l == VT_CONST &&
9623 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9624 /* global asm block */
9625 asm_global_instr();
9626 continue;
9628 /* special test for old K&R protos without explicit int
9629 type. Only accepted when defining global data */
9630 if (l == VT_LOCAL || tok < TOK_DEFINE)
9631 break;
9632 btype.t = VT_INT;
9634 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9635 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9636 tok == ';') {
9637 /* we accept no variable after */
9638 next();
9639 continue;
9641 while (1) { /* iterate thru each declaration */
9642 type = btype;
9643 type_decl(&type, &ad, &v, TYPE_DIRECT);
9644 #if 0
9646 char buf[500];
9647 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
9648 printf("type = '%s'\n", buf);
9650 #endif
9651 if ((type.t & VT_BTYPE) == VT_FUNC) {
9652 /* if old style function prototype, we accept a
9653 declaration list */
9654 sym = type.ref;
9655 if (sym->c == FUNC_OLD)
9656 func_decl_list(sym);
9659 if (tok == '{') {
9660 if (l == VT_LOCAL)
9661 error("cannot use local functions");
9662 if ((type.t & VT_BTYPE) != VT_FUNC)
9663 expect("function definition");
9665 /* reject abstract declarators in function definition */
9666 sym = type.ref;
9667 while ((sym = sym->next) != NULL)
9668 if (!(sym->v & ~SYM_FIELD))
9669 expect("identifier");
9671 /* XXX: cannot do better now: convert extern line to static inline */
9672 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9673 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9675 sym = sym_find(v);
9676 if (sym) {
9677 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9678 goto func_error1;
9679 /* specific case: if not func_call defined, we put
9680 the one of the prototype */
9681 /* XXX: should have default value */
9682 r = sym->type.ref->r;
9683 if (FUNC_CALL(r) != FUNC_CDECL
9684 && FUNC_CALL(type.ref->r) == FUNC_CDECL)
9685 FUNC_CALL(type.ref->r) = FUNC_CALL(r);
9686 if (FUNC_EXPORT(r))
9687 FUNC_EXPORT(type.ref->r) = 1;
9689 if (!is_compatible_types(&sym->type, &type)) {
9690 func_error1:
9691 error("incompatible types for redefinition of '%s'",
9692 get_tok_str(v, NULL));
9694 /* if symbol is already defined, then put complete type */
9695 sym->type = type;
9696 } else {
9697 /* put function symbol */
9698 sym = global_identifier_push(v, type.t, 0);
9699 sym->type.ref = type.ref;
9702 /* static inline functions are just recorded as a kind
9703 of macro. Their code will be emitted at the end of
9704 the compilation unit only if they are used */
9705 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9706 (VT_INLINE | VT_STATIC)) {
9707 TokenString func_str;
9708 int block_level;
9710 tok_str_new(&func_str);
9712 block_level = 0;
9713 for(;;) {
9714 int t;
9715 if (tok == TOK_EOF)
9716 error("unexpected end of file");
9717 tok_str_add_tok(&func_str);
9718 t = tok;
9719 next();
9720 if (t == '{') {
9721 block_level++;
9722 } else if (t == '}') {
9723 block_level--;
9724 if (block_level == 0)
9725 break;
9728 tok_str_add(&func_str, -1);
9729 tok_str_add(&func_str, 0);
9730 INLINE_DEF(sym->r) = func_str.str;
9731 } else {
9732 /* compute text section */
9733 cur_text_section = ad.section;
9734 if (!cur_text_section)
9735 cur_text_section = text_section;
9736 sym->r = VT_SYM | VT_CONST;
9737 gen_function(sym);
9739 break;
9740 } else {
9741 if (btype.t & VT_TYPEDEF) {
9742 /* save typedefed type */
9743 /* XXX: test storage specifiers ? */
9744 sym = sym_push(v, &type, 0, 0);
9745 sym->type.t |= VT_TYPEDEF;
9746 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9747 /* external function definition */
9748 /* specific case for func_call attribute */
9749 if (ad.func_attr)
9750 type.ref->r = ad.func_attr;
9751 external_sym(v, &type, 0);
9752 } else {
9753 /* not lvalue if array */
9754 r = 0;
9755 if (!(type.t & VT_ARRAY))
9756 r |= lvalue_type(type.t);
9757 has_init = (tok == '=');
9758 if ((btype.t & VT_EXTERN) ||
9759 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9760 !has_init && l == VT_CONST && type.ref->c < 0)) {
9761 /* external variable */
9762 /* NOTE: as GCC, uninitialized global static
9763 arrays of null size are considered as
9764 extern */
9765 external_sym(v, &type, r);
9766 } else {
9767 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9768 if (type.t & VT_STATIC)
9769 r |= VT_CONST;
9770 else
9771 r |= l;
9772 if (has_init)
9773 next();
9774 decl_initializer_alloc(&type, &ad, r,
9775 has_init, v, l);
9778 if (tok != ',') {
9779 skip(';');
9780 break;
9782 next();
9788 /* better than nothing, but needs extension to handle '-E' option
9789 correctly too */
9790 static void preprocess_init(TCCState *s1)
9792 s1->include_stack_ptr = s1->include_stack;
9793 /* XXX: move that before to avoid having to initialize
9794 file->ifdef_stack_ptr ? */
9795 s1->ifdef_stack_ptr = s1->ifdef_stack;
9796 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9798 /* XXX: not ANSI compliant: bound checking says error */
9799 vtop = vstack - 1;
9800 s1->pack_stack[0] = 0;
9801 s1->pack_stack_ptr = s1->pack_stack;
9804 /* compile the C file opened in 'file'. Return non zero if errors. */
9805 static int tcc_compile(TCCState *s1)
9807 Sym *define_start;
9808 char buf[512];
9809 volatile int section_sym;
9811 #ifdef INC_DEBUG
9812 printf("%s: **** new file\n", file->filename);
9813 #endif
9814 preprocess_init(s1);
9816 cur_text_section = NULL;
9817 funcname = "";
9818 anon_sym = SYM_FIRST_ANOM;
9820 /* file info: full path + filename */
9821 section_sym = 0; /* avoid warning */
9822 if (do_debug) {
9823 section_sym = put_elf_sym(symtab_section, 0, 0,
9824 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
9825 text_section->sh_num, NULL);
9826 getcwd(buf, sizeof(buf));
9827 #ifdef _WIN32
9828 normalize_slashes(buf);
9829 #endif
9830 pstrcat(buf, sizeof(buf), "/");
9831 put_stabs_r(buf, N_SO, 0, 0,
9832 text_section->data_offset, text_section, section_sym);
9833 put_stabs_r(file->filename, N_SO, 0, 0,
9834 text_section->data_offset, text_section, section_sym);
9836 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9837 symbols can be safely used */
9838 put_elf_sym(symtab_section, 0, 0,
9839 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
9840 SHN_ABS, file->filename);
9842 /* define some often used types */
9843 int_type.t = VT_INT;
9845 char_pointer_type.t = VT_BYTE;
9846 mk_pointer(&char_pointer_type);
9848 func_old_type.t = VT_FUNC;
9849 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9851 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9852 float_type.t = VT_FLOAT;
9853 double_type.t = VT_DOUBLE;
9855 func_float_type.t = VT_FUNC;
9856 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9857 func_double_type.t = VT_FUNC;
9858 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9859 #endif
9861 #if 0
9862 /* define 'void *alloca(unsigned int)' builtin function */
9864 Sym *s1;
9866 p = anon_sym++;
9867 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9868 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9869 s1->next = NULL;
9870 sym->next = s1;
9871 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9873 #endif
9875 define_start = define_stack;
9876 nocode_wanted = 1;
9878 if (setjmp(s1->error_jmp_buf) == 0) {
9879 s1->nb_errors = 0;
9880 s1->error_set_jmp_enabled = 1;
9882 ch = file->buf_ptr[0];
9883 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9884 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9885 next();
9886 decl(VT_CONST);
9887 if (tok != TOK_EOF)
9888 expect("declaration");
9890 /* end of translation unit info */
9891 if (do_debug) {
9892 put_stabs_r(NULL, N_SO, 0, 0,
9893 text_section->data_offset, text_section, section_sym);
9896 s1->error_set_jmp_enabled = 0;
9898 /* reset define stack, but leave -Dsymbols (may be incorrect if
9899 they are undefined) */
9900 free_defines(define_start);
9902 gen_inline_functions();
9904 sym_pop(&global_stack, NULL);
9905 sym_pop(&local_stack, NULL);
9907 return s1->nb_errors != 0 ? -1 : 0;
9910 /* Preprocess the current file */
9911 static int tcc_preprocess(TCCState *s1)
9913 Sym *define_start;
9914 BufferedFile *file_ref;
9915 int token_seen, line_ref;
9917 preprocess_init(s1);
9918 define_start = define_stack;
9919 ch = file->buf_ptr[0];
9920 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9921 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9922 PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES;
9923 token_seen = 0;
9924 line_ref = 0;
9925 file_ref = NULL;
9927 for (;;) {
9928 next();
9929 if (tok == TOK_EOF) {
9930 break;
9931 } else if (tok == TOK_LINEFEED) {
9932 if (!token_seen)
9933 continue;
9934 ++line_ref;
9935 token_seen = 0;
9936 } else if (!token_seen) {
9937 int d = file->line_num - line_ref;
9938 if (file != file_ref || d < 0 || d >= 8)
9939 fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename);
9940 else
9941 while (d)
9942 fputs("\n", s1->outfile), --d;
9943 line_ref = (file_ref = file)->line_num;
9944 token_seen = 1;
9946 fputs(get_tok_str(tok, &tokc), s1->outfile);
9948 free_defines(define_start);
9949 return 0;
9952 #ifdef LIBTCC
9953 int tcc_compile_string(TCCState *s, const char *str)
9955 BufferedFile bf1, *bf = &bf1;
9956 int ret, len;
9957 char *buf;
9959 /* init file structure */
9960 bf->fd = -1;
9961 /* XXX: avoid copying */
9962 len = strlen(str);
9963 buf = tcc_malloc(len + 1);
9964 if (!buf)
9965 return -1;
9966 memcpy(buf, str, len);
9967 buf[len] = CH_EOB;
9968 bf->buf_ptr = buf;
9969 bf->buf_end = buf + len;
9970 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9971 bf->line_num = 1;
9972 file = bf;
9973 ret = tcc_compile(s);
9974 file = NULL;
9975 tcc_free(buf);
9977 /* currently, no need to close */
9978 return ret;
9980 #endif
9982 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9983 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9985 BufferedFile bf1, *bf = &bf1;
9987 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9988 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9989 /* default value */
9990 if (!value)
9991 value = "1";
9992 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9994 /* init file structure */
9995 bf->fd = -1;
9996 bf->buf_ptr = bf->buffer;
9997 bf->buf_end = bf->buffer + strlen(bf->buffer);
9998 *bf->buf_end = CH_EOB;
9999 bf->filename[0] = '\0';
10000 bf->line_num = 1;
10001 file = bf;
10003 s1->include_stack_ptr = s1->include_stack;
10005 /* parse with define parser */
10006 ch = file->buf_ptr[0];
10007 next_nomacro();
10008 parse_define();
10009 file = NULL;
10012 /* undefine a preprocessor symbol */
10013 void tcc_undefine_symbol(TCCState *s1, const char *sym)
10015 TokenSym *ts;
10016 Sym *s;
10017 ts = tok_alloc(sym, strlen(sym));
10018 s = define_find(ts->tok);
10019 /* undefine symbol by putting an invalid name */
10020 if (s)
10021 define_undef(s);
10024 #ifdef CONFIG_TCC_ASM
10026 #ifdef TCC_TARGET_I386
10027 #include "i386-asm.c"
10028 #endif
10029 #include "tccasm.c"
10031 #else
10032 static void asm_instr(void)
10034 error("inline asm() not supported");
10036 static void asm_global_instr(void)
10038 error("inline asm() not supported");
10040 #endif
10042 #include "tccelf.c"
10044 #ifdef TCC_TARGET_COFF
10045 #include "tcccoff.c"
10046 #endif
10048 #ifdef TCC_TARGET_PE
10049 #include "tccpe.c"
10050 #endif
10052 #ifdef CONFIG_TCC_BACKTRACE
10053 /* print the position in the source file of PC value 'pc' by reading
10054 the stabs debug information */
10055 static void rt_printline(unsigned long wanted_pc)
10057 Stab_Sym *sym, *sym_end;
10058 char func_name[128], last_func_name[128];
10059 unsigned long func_addr, last_pc, pc;
10060 const char *incl_files[INCLUDE_STACK_SIZE];
10061 int incl_index, len, last_line_num, i;
10062 const char *str, *p;
10064 fprintf(stderr, "0x%08lx:", wanted_pc);
10066 func_name[0] = '\0';
10067 func_addr = 0;
10068 incl_index = 0;
10069 last_func_name[0] = '\0';
10070 last_pc = 0xffffffff;
10071 last_line_num = 1;
10072 sym = (Stab_Sym *)stab_section->data + 1;
10073 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
10074 while (sym < sym_end) {
10075 switch(sym->n_type) {
10076 /* function start or end */
10077 case N_FUN:
10078 if (sym->n_strx == 0) {
10079 /* we test if between last line and end of function */
10080 pc = sym->n_value + func_addr;
10081 if (wanted_pc >= last_pc && wanted_pc < pc)
10082 goto found;
10083 func_name[0] = '\0';
10084 func_addr = 0;
10085 } else {
10086 str = stabstr_section->data + sym->n_strx;
10087 p = strchr(str, ':');
10088 if (!p) {
10089 pstrcpy(func_name, sizeof(func_name), str);
10090 } else {
10091 len = p - str;
10092 if (len > sizeof(func_name) - 1)
10093 len = sizeof(func_name) - 1;
10094 memcpy(func_name, str, len);
10095 func_name[len] = '\0';
10097 func_addr = sym->n_value;
10099 break;
10100 /* line number info */
10101 case N_SLINE:
10102 pc = sym->n_value + func_addr;
10103 if (wanted_pc >= last_pc && wanted_pc < pc)
10104 goto found;
10105 last_pc = pc;
10106 last_line_num = sym->n_desc;
10107 /* XXX: slow! */
10108 strcpy(last_func_name, func_name);
10109 break;
10110 /* include files */
10111 case N_BINCL:
10112 str = stabstr_section->data + sym->n_strx;
10113 add_incl:
10114 if (incl_index < INCLUDE_STACK_SIZE) {
10115 incl_files[incl_index++] = str;
10117 break;
10118 case N_EINCL:
10119 if (incl_index > 1)
10120 incl_index--;
10121 break;
10122 case N_SO:
10123 if (sym->n_strx == 0) {
10124 incl_index = 0; /* end of translation unit */
10125 } else {
10126 str = stabstr_section->data + sym->n_strx;
10127 /* do not add path */
10128 len = strlen(str);
10129 if (len > 0 && str[len - 1] != '/')
10130 goto add_incl;
10132 break;
10134 sym++;
10137 /* second pass: we try symtab symbols (no line number info) */
10138 incl_index = 0;
10140 ElfW(Sym) *sym, *sym_end;
10141 int type;
10143 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
10144 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
10145 sym < sym_end;
10146 sym++) {
10147 type = ELFW(ST_TYPE)(sym->st_info);
10148 if (type == STT_FUNC) {
10149 if (wanted_pc >= sym->st_value &&
10150 wanted_pc < sym->st_value + sym->st_size) {
10151 pstrcpy(last_func_name, sizeof(last_func_name),
10152 strtab_section->data + sym->st_name);
10153 goto found;
10158 /* did not find any info: */
10159 fprintf(stderr, " ???\n");
10160 return;
10161 found:
10162 if (last_func_name[0] != '\0') {
10163 fprintf(stderr, " %s()", last_func_name);
10165 if (incl_index > 0) {
10166 fprintf(stderr, " (%s:%d",
10167 incl_files[incl_index - 1], last_line_num);
10168 for(i = incl_index - 2; i >= 0; i--)
10169 fprintf(stderr, ", included from %s", incl_files[i]);
10170 fprintf(stderr, ")");
10172 fprintf(stderr, "\n");
10175 #ifdef __i386__
10176 /* fix for glibc 2.1 */
10177 #ifndef REG_EIP
10178 #define REG_EIP EIP
10179 #define REG_EBP EBP
10180 #endif
10182 /* return the PC at frame level 'level'. Return non zero if not found */
10183 static int rt_get_caller_pc(unsigned long *paddr,
10184 ucontext_t *uc, int level)
10186 unsigned long fp;
10187 int i;
10189 if (level == 0) {
10190 #if defined(__FreeBSD__)
10191 *paddr = uc->uc_mcontext.mc_eip;
10192 #elif defined(__dietlibc__)
10193 *paddr = uc->uc_mcontext.eip;
10194 #else
10195 *paddr = uc->uc_mcontext.gregs[REG_EIP];
10196 #endif
10197 return 0;
10198 } else {
10199 #if defined(__FreeBSD__)
10200 fp = uc->uc_mcontext.mc_ebp;
10201 #elif defined(__dietlibc__)
10202 fp = uc->uc_mcontext.ebp;
10203 #else
10204 fp = uc->uc_mcontext.gregs[REG_EBP];
10205 #endif
10206 for(i=1;i<level;i++) {
10207 /* XXX: check address validity with program info */
10208 if (fp <= 0x1000 || fp >= 0xc0000000)
10209 return -1;
10210 fp = ((unsigned long *)fp)[0];
10212 *paddr = ((unsigned long *)fp)[1];
10213 return 0;
10216 #elif defined(__x86_64__)
10217 /* return the PC at frame level 'level'. Return non zero if not found */
10218 static int rt_get_caller_pc(unsigned long *paddr,
10219 ucontext_t *uc, int level)
10221 unsigned long fp;
10222 int i;
10224 if (level == 0) {
10225 /* XXX: only support linux */
10226 *paddr = uc->uc_mcontext.gregs[REG_RIP];
10227 return 0;
10228 } else {
10229 fp = uc->uc_mcontext.gregs[REG_RBP];
10230 for(i=1;i<level;i++) {
10231 /* XXX: check address validity with program info */
10232 if (fp <= 0x1000)
10233 return -1;
10234 fp = ((unsigned long *)fp)[0];
10236 *paddr = ((unsigned long *)fp)[1];
10237 return 0;
10240 #else
10241 #warning add arch specific rt_get_caller_pc()
10242 static int rt_get_caller_pc(unsigned long *paddr,
10243 ucontext_t *uc, int level)
10245 return -1;
10247 #endif
10249 /* emit a run time error at position 'pc' */
10250 void rt_error(ucontext_t *uc, const char *fmt, ...)
10252 va_list ap;
10253 unsigned long pc;
10254 int i;
10256 va_start(ap, fmt);
10257 fprintf(stderr, "Runtime error: ");
10258 vfprintf(stderr, fmt, ap);
10259 fprintf(stderr, "\n");
10260 for(i=0;i<num_callers;i++) {
10261 if (rt_get_caller_pc(&pc, uc, i) < 0)
10262 break;
10263 if (i == 0)
10264 fprintf(stderr, "at ");
10265 else
10266 fprintf(stderr, "by ");
10267 rt_printline(pc);
10269 exit(255);
10270 va_end(ap);
10273 /* signal handler for fatal errors */
10274 static void sig_error(int signum, siginfo_t *siginf, void *puc)
10276 ucontext_t *uc = puc;
10278 switch(signum) {
10279 case SIGFPE:
10280 switch(siginf->si_code) {
10281 case FPE_INTDIV:
10282 case FPE_FLTDIV:
10283 rt_error(uc, "division by zero");
10284 break;
10285 default:
10286 rt_error(uc, "floating point exception");
10287 break;
10289 break;
10290 case SIGBUS:
10291 case SIGSEGV:
10292 if (rt_bound_error_msg && *rt_bound_error_msg)
10293 rt_error(uc, *rt_bound_error_msg);
10294 else
10295 rt_error(uc, "dereferencing invalid pointer");
10296 break;
10297 case SIGILL:
10298 rt_error(uc, "illegal instruction");
10299 break;
10300 case SIGABRT:
10301 rt_error(uc, "abort() called");
10302 break;
10303 default:
10304 rt_error(uc, "caught signal %d", signum);
10305 break;
10307 exit(255);
10310 #endif
10312 /* copy code into memory passed in by the caller and do all relocations
10313 (needed before using tcc_get_symbol()).
10314 returns -1 on error and required size if ptr is NULL */
10315 int tcc_relocate(TCCState *s1, void *ptr)
10317 Section *s;
10318 unsigned long offset, length, mem;
10319 int i;
10321 if (0 == s1->runtime_added) {
10322 s1->runtime_added = 1;
10323 s1->nb_errors = 0;
10324 #ifdef TCC_TARGET_PE
10325 pe_add_runtime(s1);
10326 relocate_common_syms();
10327 tcc_add_linker_symbols(s1);
10328 #else
10329 tcc_add_runtime(s1);
10330 relocate_common_syms();
10331 tcc_add_linker_symbols(s1);
10332 build_got_entries(s1);
10333 #endif
10336 offset = 0, mem = (unsigned long)ptr;
10337 for(i = 1; i < s1->nb_sections; i++) {
10338 s = s1->sections[i];
10339 if (0 == (s->sh_flags & SHF_ALLOC))
10340 continue;
10341 length = s->data_offset;
10342 s->sh_addr = mem ? (mem + offset + 15) & ~15 : 0;
10343 offset = (offset + length + 15) & ~15;
10346 /* relocate symbols */
10347 relocate_syms(s1, 1);
10348 if (s1->nb_errors)
10349 return -1;
10351 #ifdef TCC_TARGET_X86_64
10352 s1->runtime_plt_and_got_offset = 0;
10353 s1->runtime_plt_and_got = (char *)(mem + offset);
10354 /* double the size of the buffer for got and plt entries
10355 XXX: calculate exact size for them? */
10356 offset *= 2;
10357 #endif
10359 if (0 == mem)
10360 return offset + 15;
10362 /* relocate each section */
10363 for(i = 1; i < s1->nb_sections; i++) {
10364 s = s1->sections[i];
10365 if (s->reloc)
10366 relocate_section(s1, s);
10369 for(i = 1; i < s1->nb_sections; i++) {
10370 s = s1->sections[i];
10371 if (0 == (s->sh_flags & SHF_ALLOC))
10372 continue;
10373 length = s->data_offset;
10374 // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
10375 ptr = (void*)s->sh_addr;
10376 if (NULL == s->data || s->sh_type == SHT_NOBITS)
10377 memset(ptr, 0, length);
10378 else
10379 memcpy(ptr, s->data, length);
10380 /* mark executable sections as executable in memory */
10381 if (s->sh_flags & SHF_EXECINSTR)
10382 set_pages_executable(ptr, length);
10384 #ifdef TCC_TARGET_X86_64
10385 set_pages_executable(s1->runtime_plt_and_got,
10386 s1->runtime_plt_and_got_offset);
10387 #endif
10388 return 0;
10391 /* launch the compiled program with the given arguments */
10392 int tcc_run(TCCState *s1, int argc, char **argv)
10394 int (*prog_main)(int, char **);
10395 void *ptr;
10396 int ret;
10398 ret = tcc_relocate(s1, NULL);
10399 if (ret < 0)
10400 return -1;
10401 ptr = tcc_malloc(ret);
10402 tcc_relocate(s1, ptr);
10404 prog_main = tcc_get_symbol_err(s1, "main");
10406 if (do_debug) {
10407 #ifdef CONFIG_TCC_BACKTRACE
10408 struct sigaction sigact;
10409 /* install TCC signal handlers to print debug info on fatal
10410 runtime errors */
10411 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
10412 sigact.sa_sigaction = sig_error;
10413 sigemptyset(&sigact.sa_mask);
10414 sigaction(SIGFPE, &sigact, NULL);
10415 sigaction(SIGILL, &sigact, NULL);
10416 sigaction(SIGSEGV, &sigact, NULL);
10417 sigaction(SIGBUS, &sigact, NULL);
10418 sigaction(SIGABRT, &sigact, NULL);
10419 #else
10420 error("debug mode not available");
10421 #endif
10424 #ifdef CONFIG_TCC_BCHECK
10425 if (do_bounds_check) {
10426 void (*bound_init)(void);
10428 /* set error function */
10429 rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
10431 /* XXX: use .init section so that it also work in binary ? */
10432 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
10433 bound_init();
10435 #endif
10436 ret = (*prog_main)(argc, argv);
10437 tcc_free(ptr);
10438 return ret;
10441 void tcc_memstats(void)
10443 #ifdef MEM_DEBUG
10444 printf("memory in use: %d\n", mem_cur_size);
10445 #endif
10448 static void tcc_cleanup(void)
10450 int i, n;
10452 if (NULL == tcc_state)
10453 return;
10454 tcc_state = NULL;
10456 /* free -D defines */
10457 free_defines(NULL);
10459 /* free tokens */
10460 n = tok_ident - TOK_IDENT;
10461 for(i = 0; i < n; i++)
10462 tcc_free(table_ident[i]);
10463 tcc_free(table_ident);
10465 /* free sym_pools */
10466 dynarray_reset(&sym_pools, &nb_sym_pools);
10467 /* string buffer */
10468 cstr_free(&tokcstr);
10469 /* reset symbol stack */
10470 sym_free_first = NULL;
10471 /* cleanup from error/setjmp */
10472 macro_ptr = NULL;
10475 TCCState *tcc_new(void)
10477 const char *p, *r;
10478 TCCState *s;
10479 TokenSym *ts;
10480 int i, c;
10482 tcc_cleanup();
10484 s = tcc_mallocz(sizeof(TCCState));
10485 if (!s)
10486 return NULL;
10487 tcc_state = s;
10488 s->output_type = TCC_OUTPUT_MEMORY;
10490 /* init isid table */
10491 for(i=CH_EOF;i<256;i++)
10492 isidnum_table[i-CH_EOF] = isid(i) || isnum(i);
10494 /* add all tokens */
10495 table_ident = NULL;
10496 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
10498 tok_ident = TOK_IDENT;
10499 p = tcc_keywords;
10500 while (*p) {
10501 r = p;
10502 for(;;) {
10503 c = *r++;
10504 if (c == '\0')
10505 break;
10507 ts = tok_alloc(p, r - p - 1);
10508 p = r;
10511 /* we add dummy defines for some special macros to speed up tests
10512 and to have working defined() */
10513 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
10514 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
10515 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
10516 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
10518 /* standard defines */
10519 tcc_define_symbol(s, "__STDC__", NULL);
10520 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
10521 #if defined(TCC_TARGET_I386)
10522 tcc_define_symbol(s, "__i386__", NULL);
10523 #endif
10524 #if defined(TCC_TARGET_X86_64)
10525 tcc_define_symbol(s, "__x86_64__", NULL);
10526 #endif
10527 #if defined(TCC_TARGET_ARM)
10528 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10529 tcc_define_symbol(s, "__arm_elf__", NULL);
10530 tcc_define_symbol(s, "__arm_elf", NULL);
10531 tcc_define_symbol(s, "arm_elf", NULL);
10532 tcc_define_symbol(s, "__arm__", NULL);
10533 tcc_define_symbol(s, "__arm", NULL);
10534 tcc_define_symbol(s, "arm", NULL);
10535 tcc_define_symbol(s, "__APCS_32__", NULL);
10536 #endif
10537 #ifdef TCC_TARGET_PE
10538 tcc_define_symbol(s, "_WIN32", NULL);
10539 #else
10540 tcc_define_symbol(s, "__unix__", NULL);
10541 tcc_define_symbol(s, "__unix", NULL);
10542 #if defined(__linux)
10543 tcc_define_symbol(s, "__linux__", NULL);
10544 tcc_define_symbol(s, "__linux", NULL);
10545 #endif
10546 #endif
10547 /* tiny C specific defines */
10548 tcc_define_symbol(s, "__TINYC__", NULL);
10550 /* tiny C & gcc defines */
10551 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10552 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10553 #ifdef TCC_TARGET_PE
10554 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10555 #else
10556 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10557 #endif
10559 #ifndef TCC_TARGET_PE
10560 /* default library paths */
10561 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/local/lib");
10562 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/lib");
10563 tcc_add_library_path(s, CONFIG_SYSROOT "/lib");
10564 #endif
10566 /* no section zero */
10567 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10569 /* create standard sections */
10570 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10571 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10572 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10574 /* symbols are always generated for linking stage */
10575 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10576 ".strtab",
10577 ".hashtab", SHF_PRIVATE);
10578 strtab_section = symtab_section->link;
10580 /* private symbol table for dynamic symbols */
10581 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10582 ".dynstrtab",
10583 ".dynhashtab", SHF_PRIVATE);
10584 s->alacarte_link = 1;
10586 #ifdef CHAR_IS_UNSIGNED
10587 s->char_is_unsigned = 1;
10588 #endif
10589 #if defined(TCC_TARGET_PE) && 0
10590 /* XXX: currently the PE linker is not ready to support that */
10591 s->leading_underscore = 1;
10592 #endif
10593 return s;
10596 void tcc_delete(TCCState *s1)
10598 int i;
10600 tcc_cleanup();
10602 /* free all sections */
10603 for(i = 1; i < s1->nb_sections; i++)
10604 free_section(s1->sections[i]);
10605 dynarray_reset(&s1->sections, &s1->nb_sections);
10607 for(i = 0; i < s1->nb_priv_sections; i++)
10608 free_section(s1->priv_sections[i]);
10609 dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
10611 /* free any loaded DLLs */
10612 for ( i = 0; i < s1->nb_loaded_dlls; i++) {
10613 DLLReference *ref = s1->loaded_dlls[i];
10614 if ( ref->handle )
10615 dlclose(ref->handle);
10618 /* free loaded dlls array */
10619 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
10621 /* free library paths */
10622 dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
10624 /* free include paths */
10625 dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
10626 dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
10627 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
10629 tcc_free(s1);
10632 int tcc_add_include_path(TCCState *s1, const char *pathname)
10634 char *pathname1;
10636 pathname1 = tcc_strdup(pathname);
10637 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10638 return 0;
10641 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10643 char *pathname1;
10645 pathname1 = tcc_strdup(pathname);
10646 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10647 return 0;
10650 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10652 const char *ext;
10653 ElfW(Ehdr) ehdr;
10654 int fd, ret;
10655 BufferedFile *saved_file;
10657 /* find source file type with extension */
10658 ext = tcc_fileextension(filename);
10659 if (ext[0])
10660 ext++;
10662 /* open the file */
10663 saved_file = file;
10664 file = tcc_open(s1, filename);
10665 if (!file) {
10666 if (flags & AFF_PRINT_ERROR) {
10667 error_noabort("file '%s' not found", filename);
10669 ret = -1;
10670 goto fail1;
10673 if (flags & AFF_PREPROCESS) {
10674 ret = tcc_preprocess(s1);
10675 } else if (!ext[0] || !PATHCMP(ext, "c")) {
10676 /* C file assumed */
10677 ret = tcc_compile(s1);
10678 } else
10679 #ifdef CONFIG_TCC_ASM
10680 if (!strcmp(ext, "S")) {
10681 /* preprocessed assembler */
10682 ret = tcc_assemble(s1, 1);
10683 } else if (!strcmp(ext, "s")) {
10684 /* non preprocessed assembler */
10685 ret = tcc_assemble(s1, 0);
10686 } else
10687 #endif
10688 #ifdef TCC_TARGET_PE
10689 if (!PATHCMP(ext, "def")) {
10690 ret = pe_load_def_file(s1, file->fd);
10691 } else
10692 #endif
10694 fd = file->fd;
10695 /* assume executable format: auto guess file type */
10696 ret = read(fd, &ehdr, sizeof(ehdr));
10697 lseek(fd, 0, SEEK_SET);
10698 if (ret <= 0) {
10699 error_noabort("could not read header");
10700 goto fail;
10701 } else if (ret != sizeof(ehdr)) {
10702 goto try_load_script;
10705 if (ehdr.e_ident[0] == ELFMAG0 &&
10706 ehdr.e_ident[1] == ELFMAG1 &&
10707 ehdr.e_ident[2] == ELFMAG2 &&
10708 ehdr.e_ident[3] == ELFMAG3) {
10709 file->line_num = 0; /* do not display line number if error */
10710 if (ehdr.e_type == ET_REL) {
10711 ret = tcc_load_object_file(s1, fd, 0);
10712 } else if (ehdr.e_type == ET_DYN) {
10713 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10714 #ifdef TCC_TARGET_PE
10715 ret = -1;
10716 #else
10717 void *h;
10718 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10719 if (h)
10720 ret = 0;
10721 else
10722 ret = -1;
10723 #endif
10724 } else {
10725 ret = tcc_load_dll(s1, fd, filename,
10726 (flags & AFF_REFERENCED_DLL) != 0);
10728 } else {
10729 error_noabort("unrecognized ELF file");
10730 goto fail;
10732 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10733 file->line_num = 0; /* do not display line number if error */
10734 ret = tcc_load_archive(s1, fd);
10735 } else
10736 #ifdef TCC_TARGET_COFF
10737 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10738 ret = tcc_load_coff(s1, fd);
10739 } else
10740 #endif
10741 #ifdef TCC_TARGET_PE
10742 if (pe_test_res_file(&ehdr, ret)) {
10743 ret = pe_load_res_file(s1, fd);
10744 } else
10745 #endif
10747 /* as GNU ld, consider it is an ld script if not recognized */
10748 try_load_script:
10749 ret = tcc_load_ldscript(s1);
10750 if (ret < 0) {
10751 error_noabort("unrecognized file type");
10752 goto fail;
10756 the_end:
10757 tcc_close(file);
10758 fail1:
10759 file = saved_file;
10760 return ret;
10761 fail:
10762 ret = -1;
10763 goto the_end;
10766 int tcc_add_file(TCCState *s, const char *filename)
10768 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10771 int tcc_add_library_path(TCCState *s, const char *pathname)
10773 char *pathname1;
10775 pathname1 = tcc_strdup(pathname);
10776 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10777 return 0;
10780 /* find and load a dll. Return non zero if not found */
10781 /* XXX: add '-rpath' option support ? */
10782 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10784 char buf[1024];
10785 int i;
10787 for(i = 0; i < s->nb_library_paths; i++) {
10788 snprintf(buf, sizeof(buf), "%s/%s",
10789 s->library_paths[i], filename);
10790 if (tcc_add_file_internal(s, buf, flags) == 0)
10791 return 0;
10793 return -1;
10796 /* the library name is the same as the argument of the '-l' option */
10797 int tcc_add_library(TCCState *s, const char *libraryname)
10799 char buf[1024];
10800 int i;
10802 /* first we look for the dynamic library if not static linking */
10803 if (!s->static_link) {
10804 #ifdef TCC_TARGET_PE
10805 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10806 #else
10807 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10808 #endif
10809 if (tcc_add_dll(s, buf, 0) == 0)
10810 return 0;
10813 /* then we look for the static library */
10814 for(i = 0; i < s->nb_library_paths; i++) {
10815 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10816 s->library_paths[i], libraryname);
10817 if (tcc_add_file_internal(s, buf, 0) == 0)
10818 return 0;
10820 return -1;
10823 int tcc_add_symbol(TCCState *s, const char *name, void *val)
10825 add_elf_sym(symtab_section, (unsigned long)val, 0,
10826 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
10827 SHN_ABS, name);
10828 return 0;
10831 int tcc_set_output_type(TCCState *s, int output_type)
10833 char buf[1024];
10835 s->output_type = output_type;
10837 if (!s->nostdinc) {
10838 /* default include paths */
10839 /* XXX: reverse order needed if -isystem support */
10840 #ifndef TCC_TARGET_PE
10841 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/local/include");
10842 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/include");
10843 #endif
10844 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10845 tcc_add_sysinclude_path(s, buf);
10846 #ifdef TCC_TARGET_PE
10847 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10848 tcc_add_sysinclude_path(s, buf);
10849 #endif
10852 /* if bound checking, then add corresponding sections */
10853 #ifdef CONFIG_TCC_BCHECK
10854 if (do_bounds_check) {
10855 /* define symbol */
10856 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10857 /* create bounds sections */
10858 bounds_section = new_section(s, ".bounds",
10859 SHT_PROGBITS, SHF_ALLOC);
10860 lbounds_section = new_section(s, ".lbounds",
10861 SHT_PROGBITS, SHF_ALLOC);
10863 #endif
10865 if (s->char_is_unsigned) {
10866 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10869 /* add debug sections */
10870 if (do_debug) {
10871 /* stab symbols */
10872 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10873 stab_section->sh_entsize = sizeof(Stab_Sym);
10874 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10875 put_elf_str(stabstr_section, "");
10876 stab_section->link = stabstr_section;
10877 /* put first entry */
10878 put_stabs("", 0, 0, 0, 0);
10881 /* add libc crt1/crti objects */
10882 #ifndef TCC_TARGET_PE
10883 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10884 !s->nostdlib) {
10885 if (output_type != TCC_OUTPUT_DLL)
10886 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10887 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10889 #endif
10891 #ifdef TCC_TARGET_PE
10892 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10893 tcc_add_library_path(s, buf);
10894 #endif
10896 return 0;
10899 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10900 #define FD_INVERT 0x0002 /* invert value before storing */
10902 typedef struct FlagDef {
10903 uint16_t offset;
10904 uint16_t flags;
10905 const char *name;
10906 } FlagDef;
10908 static const FlagDef warning_defs[] = {
10909 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10910 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10911 { offsetof(TCCState, warn_error), 0, "error" },
10912 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10913 "implicit-function-declaration" },
10916 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10917 const char *name, int value)
10919 int i;
10920 const FlagDef *p;
10921 const char *r;
10923 r = name;
10924 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10925 r += 3;
10926 value = !value;
10928 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10929 if (!strcmp(r, p->name))
10930 goto found;
10932 return -1;
10933 found:
10934 if (p->flags & FD_INVERT)
10935 value = !value;
10936 *(int *)((uint8_t *)s + p->offset) = value;
10937 return 0;
10941 /* set/reset a warning */
10942 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10944 int i;
10945 const FlagDef *p;
10947 if (!strcmp(warning_name, "all")) {
10948 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10949 if (p->flags & WD_ALL)
10950 *(int *)((uint8_t *)s + p->offset) = 1;
10952 return 0;
10953 } else {
10954 return set_flag(s, warning_defs, countof(warning_defs),
10955 warning_name, value);
10959 static const FlagDef flag_defs[] = {
10960 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10961 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10962 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10963 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10966 /* set/reset a flag */
10967 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10969 return set_flag(s, flag_defs, countof(flag_defs),
10970 flag_name, value);
10973 /* set CONFIG_TCCDIR at runtime */
10974 void tcc_set_lib_path(TCCState *s, const char *path)
10976 tcc_lib_path = tcc_strdup(path);
10979 #if !defined(LIBTCC)
10981 static int64_t getclock_us(void)
10983 #ifdef _WIN32
10984 struct _timeb tb;
10985 _ftime(&tb);
10986 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10987 #else
10988 struct timeval tv;
10989 gettimeofday(&tv, NULL);
10990 return tv.tv_sec * 1000000LL + tv.tv_usec;
10991 #endif
10994 void help(void)
10996 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10997 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10998 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
10999 " [-static] [infile1 infile2...] [-run infile args...]\n"
11000 "\n"
11001 "General options:\n"
11002 " -v display current version, increase verbosity\n"
11003 " -c compile only - generate an object file\n"
11004 " -o outfile set output filename\n"
11005 " -Bdir set tcc internal library path\n"
11006 " -bench output compilation statistics\n"
11007 " -run run compiled source\n"
11008 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
11009 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
11010 " -w disable all warnings\n"
11011 "Preprocessor options:\n"
11012 " -E preprocess only\n"
11013 " -Idir add include path 'dir'\n"
11014 " -Dsym[=val] define 'sym' with value 'val'\n"
11015 " -Usym undefine 'sym'\n"
11016 "Linker options:\n"
11017 " -Ldir add library path 'dir'\n"
11018 " -llib link with dynamic or static library 'lib'\n"
11019 " -shared generate a shared library\n"
11020 " -soname set name for shared library to be used at runtime\n"
11021 " -static static linking\n"
11022 " -rdynamic export all global symbols to dynamic linker\n"
11023 " -r generate (relocatable) object file\n"
11024 "Debugger options:\n"
11025 " -g generate runtime debug info\n"
11026 #ifdef CONFIG_TCC_BCHECK
11027 " -b compile with built-in memory and bounds checker (implies -g)\n"
11028 #endif
11029 #ifdef CONFIG_TCC_BACKTRACE
11030 " -bt N show N callers in stack traces\n"
11031 #endif
11035 #define TCC_OPTION_HAS_ARG 0x0001
11036 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
11038 typedef struct TCCOption {
11039 const char *name;
11040 uint16_t index;
11041 uint16_t flags;
11042 } TCCOption;
11044 enum {
11045 TCC_OPTION_HELP,
11046 TCC_OPTION_I,
11047 TCC_OPTION_D,
11048 TCC_OPTION_U,
11049 TCC_OPTION_L,
11050 TCC_OPTION_B,
11051 TCC_OPTION_l,
11052 TCC_OPTION_bench,
11053 TCC_OPTION_bt,
11054 TCC_OPTION_b,
11055 TCC_OPTION_g,
11056 TCC_OPTION_c,
11057 TCC_OPTION_static,
11058 TCC_OPTION_shared,
11059 TCC_OPTION_soname,
11060 TCC_OPTION_o,
11061 TCC_OPTION_r,
11062 TCC_OPTION_Wl,
11063 TCC_OPTION_W,
11064 TCC_OPTION_O,
11065 TCC_OPTION_m,
11066 TCC_OPTION_f,
11067 TCC_OPTION_nostdinc,
11068 TCC_OPTION_nostdlib,
11069 TCC_OPTION_print_search_dirs,
11070 TCC_OPTION_rdynamic,
11071 TCC_OPTION_run,
11072 TCC_OPTION_v,
11073 TCC_OPTION_w,
11074 TCC_OPTION_pipe,
11075 TCC_OPTION_E,
11078 static const TCCOption tcc_options[] = {
11079 { "h", TCC_OPTION_HELP, 0 },
11080 { "?", TCC_OPTION_HELP, 0 },
11081 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
11082 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
11083 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
11084 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
11085 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
11086 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11087 { "bench", TCC_OPTION_bench, 0 },
11088 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
11089 #ifdef CONFIG_TCC_BCHECK
11090 { "b", TCC_OPTION_b, 0 },
11091 #endif
11092 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11093 { "c", TCC_OPTION_c, 0 },
11094 { "static", TCC_OPTION_static, 0 },
11095 { "shared", TCC_OPTION_shared, 0 },
11096 { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
11097 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
11098 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11099 { "rdynamic", TCC_OPTION_rdynamic, 0 },
11100 { "r", TCC_OPTION_r, 0 },
11101 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11102 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11103 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11104 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
11105 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11106 { "nostdinc", TCC_OPTION_nostdinc, 0 },
11107 { "nostdlib", TCC_OPTION_nostdlib, 0 },
11108 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
11109 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11110 { "w", TCC_OPTION_w, 0 },
11111 { "pipe", TCC_OPTION_pipe, 0},
11112 { "E", TCC_OPTION_E, 0},
11113 { NULL },
11116 /* convert 'str' into an array of space separated strings */
11117 static int expand_args(char ***pargv, const char *str)
11119 const char *s1;
11120 char **argv, *arg;
11121 int argc, len;
11123 argc = 0;
11124 argv = NULL;
11125 for(;;) {
11126 while (is_space(*str))
11127 str++;
11128 if (*str == '\0')
11129 break;
11130 s1 = str;
11131 while (*str != '\0' && !is_space(*str))
11132 str++;
11133 len = str - s1;
11134 arg = tcc_malloc(len + 1);
11135 memcpy(arg, s1, len);
11136 arg[len] = '\0';
11137 dynarray_add((void ***)&argv, &argc, arg);
11139 *pargv = argv;
11140 return argc;
11143 static char **files;
11144 static int nb_files, nb_libraries;
11145 static int multiple_files;
11146 static int print_search_dirs;
11147 static int output_type;
11148 static int reloc_output;
11149 static const char *outfile;
11151 int parse_args(TCCState *s, int argc, char **argv)
11153 int optind;
11154 const TCCOption *popt;
11155 const char *optarg, *p1, *r1;
11156 char *r;
11158 optind = 0;
11159 while (optind < argc) {
11161 r = argv[optind++];
11162 if (r[0] != '-' || r[1] == '\0') {
11163 /* add a new file */
11164 dynarray_add((void ***)&files, &nb_files, r);
11165 if (!multiple_files) {
11166 optind--;
11167 /* argv[0] will be this file */
11168 break;
11170 } else {
11171 /* find option in table (match only the first chars */
11172 popt = tcc_options;
11173 for(;;) {
11174 p1 = popt->name;
11175 if (p1 == NULL)
11176 error("invalid option -- '%s'", r);
11177 r1 = r + 1;
11178 for(;;) {
11179 if (*p1 == '\0')
11180 goto option_found;
11181 if (*r1 != *p1)
11182 break;
11183 p1++;
11184 r1++;
11186 popt++;
11188 option_found:
11189 if (popt->flags & TCC_OPTION_HAS_ARG) {
11190 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
11191 optarg = r1;
11192 } else {
11193 if (optind >= argc)
11194 error("argument to '%s' is missing", r);
11195 optarg = argv[optind++];
11197 } else {
11198 if (*r1 != '\0')
11199 return 0;
11200 optarg = NULL;
11203 switch(popt->index) {
11204 case TCC_OPTION_HELP:
11205 return 0;
11207 case TCC_OPTION_I:
11208 if (tcc_add_include_path(s, optarg) < 0)
11209 error("too many include paths");
11210 break;
11211 case TCC_OPTION_D:
11213 char *sym, *value;
11214 sym = (char *)optarg;
11215 value = strchr(sym, '=');
11216 if (value) {
11217 *value = '\0';
11218 value++;
11220 tcc_define_symbol(s, sym, value);
11222 break;
11223 case TCC_OPTION_U:
11224 tcc_undefine_symbol(s, optarg);
11225 break;
11226 case TCC_OPTION_L:
11227 tcc_add_library_path(s, optarg);
11228 break;
11229 case TCC_OPTION_B:
11230 /* set tcc utilities path (mainly for tcc development) */
11231 tcc_set_lib_path(s, optarg);
11232 break;
11233 case TCC_OPTION_l:
11234 dynarray_add((void ***)&files, &nb_files, r);
11235 nb_libraries++;
11236 break;
11237 case TCC_OPTION_bench:
11238 do_bench = 1;
11239 break;
11240 #ifdef CONFIG_TCC_BACKTRACE
11241 case TCC_OPTION_bt:
11242 num_callers = atoi(optarg);
11243 break;
11244 #endif
11245 #ifdef CONFIG_TCC_BCHECK
11246 case TCC_OPTION_b:
11247 do_bounds_check = 1;
11248 do_debug = 1;
11249 break;
11250 #endif
11251 case TCC_OPTION_g:
11252 do_debug = 1;
11253 break;
11254 case TCC_OPTION_c:
11255 multiple_files = 1;
11256 output_type = TCC_OUTPUT_OBJ;
11257 break;
11258 case TCC_OPTION_static:
11259 s->static_link = 1;
11260 break;
11261 case TCC_OPTION_shared:
11262 output_type = TCC_OUTPUT_DLL;
11263 break;
11264 case TCC_OPTION_soname:
11265 s->soname = optarg;
11266 break;
11267 case TCC_OPTION_o:
11268 multiple_files = 1;
11269 outfile = optarg;
11270 break;
11271 case TCC_OPTION_r:
11272 /* generate a .o merging several output files */
11273 reloc_output = 1;
11274 output_type = TCC_OUTPUT_OBJ;
11275 break;
11276 case TCC_OPTION_nostdinc:
11277 s->nostdinc = 1;
11278 break;
11279 case TCC_OPTION_nostdlib:
11280 s->nostdlib = 1;
11281 break;
11282 case TCC_OPTION_print_search_dirs:
11283 print_search_dirs = 1;
11284 break;
11285 case TCC_OPTION_run:
11287 int argc1;
11288 char **argv1;
11289 argc1 = expand_args(&argv1, optarg);
11290 if (argc1 > 0) {
11291 parse_args(s, argc1, argv1);
11293 multiple_files = 0;
11294 output_type = TCC_OUTPUT_MEMORY;
11296 break;
11297 case TCC_OPTION_v:
11298 do {
11299 if (0 == verbose++)
11300 printf("tcc version %s\n", TCC_VERSION);
11301 } while (*optarg++ == 'v');
11302 break;
11303 case TCC_OPTION_f:
11304 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
11305 goto unsupported_option;
11306 break;
11307 case TCC_OPTION_W:
11308 if (tcc_set_warning(s, optarg, 1) < 0 &&
11309 s->warn_unsupported)
11310 goto unsupported_option;
11311 break;
11312 case TCC_OPTION_w:
11313 s->warn_none = 1;
11314 break;
11315 case TCC_OPTION_rdynamic:
11316 s->rdynamic = 1;
11317 break;
11318 case TCC_OPTION_Wl:
11320 const char *p;
11321 if (strstart(optarg, "-Ttext,", &p)) {
11322 s->text_addr = strtoul(p, NULL, 16);
11323 s->has_text_addr = 1;
11324 } else if (strstart(optarg, "--oformat,", &p)) {
11325 if (strstart(p, "elf32-", NULL)) {
11326 s->output_format = TCC_OUTPUT_FORMAT_ELF;
11327 } else if (!strcmp(p, "binary")) {
11328 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
11329 } else
11330 #ifdef TCC_TARGET_COFF
11331 if (!strcmp(p, "coff")) {
11332 s->output_format = TCC_OUTPUT_FORMAT_COFF;
11333 } else
11334 #endif
11336 error("target %s not found", p);
11338 } else {
11339 error("unsupported linker option '%s'", optarg);
11342 break;
11343 case TCC_OPTION_E:
11344 output_type = TCC_OUTPUT_PREPROCESS;
11345 break;
11346 default:
11347 if (s->warn_unsupported) {
11348 unsupported_option:
11349 warning("unsupported option '%s'", r);
11351 break;
11355 return optind + 1;
11358 int main(int argc, char **argv)
11360 int i;
11361 TCCState *s;
11362 int nb_objfiles, ret, optind;
11363 char objfilename[1024];
11364 int64_t start_time = 0;
11366 s = tcc_new();
11367 #ifdef _WIN32
11368 tcc_set_lib_path_w32(s);
11369 #endif
11370 output_type = TCC_OUTPUT_EXE;
11371 outfile = NULL;
11372 multiple_files = 1;
11373 files = NULL;
11374 nb_files = 0;
11375 nb_libraries = 0;
11376 reloc_output = 0;
11377 print_search_dirs = 0;
11378 ret = 0;
11380 optind = parse_args(s, argc - 1, argv + 1);
11381 if (print_search_dirs) {
11382 /* enough for Linux kernel */
11383 printf("install: %s/\n", tcc_lib_path);
11384 return 0;
11386 if (optind == 0 || nb_files == 0) {
11387 if (optind && verbose)
11388 return 0;
11389 help();
11390 return 1;
11393 nb_objfiles = nb_files - nb_libraries;
11395 /* if outfile provided without other options, we output an
11396 executable */
11397 if (outfile && output_type == TCC_OUTPUT_MEMORY)
11398 output_type = TCC_OUTPUT_EXE;
11400 /* check -c consistency : only single file handled. XXX: checks file type */
11401 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
11402 /* accepts only a single input file */
11403 if (nb_objfiles != 1)
11404 error("cannot specify multiple files with -c");
11405 if (nb_libraries != 0)
11406 error("cannot specify libraries with -c");
11410 if (output_type == TCC_OUTPUT_PREPROCESS) {
11411 if (!outfile) {
11412 s->outfile = stdout;
11413 } else {
11414 s->outfile = fopen(outfile, "w");
11415 if (!s->outfile)
11416 error("could not open '%s", outfile);
11418 } else if (output_type != TCC_OUTPUT_MEMORY) {
11419 if (!outfile) {
11420 /* compute default outfile name */
11421 char *ext;
11422 const char *name =
11423 strcmp(files[0], "-") == 0 ? "a" : tcc_basename(files[0]);
11424 pstrcpy(objfilename, sizeof(objfilename), name);
11425 ext = tcc_fileextension(objfilename);
11426 #ifdef TCC_TARGET_PE
11427 if (output_type == TCC_OUTPUT_DLL)
11428 strcpy(ext, ".dll");
11429 else
11430 if (output_type == TCC_OUTPUT_EXE)
11431 strcpy(ext, ".exe");
11432 else
11433 #endif
11434 if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
11435 strcpy(ext, ".o");
11436 else
11437 pstrcpy(objfilename, sizeof(objfilename), "a.out");
11438 outfile = objfilename;
11442 if (do_bench) {
11443 start_time = getclock_us();
11446 tcc_set_output_type(s, output_type);
11448 /* compile or add each files or library */
11449 for(i = 0; i < nb_files && ret == 0; i++) {
11450 const char *filename;
11452 filename = files[i];
11453 if (output_type == TCC_OUTPUT_PREPROCESS) {
11454 if (tcc_add_file_internal(s, filename,
11455 AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
11456 ret = 1;
11457 } else if (filename[0] == '-' && filename[1]) {
11458 if (tcc_add_library(s, filename + 2) < 0)
11459 error("cannot find %s", filename);
11460 } else {
11461 if (1 == verbose)
11462 printf("-> %s\n", filename);
11463 if (tcc_add_file(s, filename) < 0)
11464 ret = 1;
11468 /* free all files */
11469 tcc_free(files);
11471 if (ret)
11472 goto the_end;
11474 if (do_bench) {
11475 double total_time;
11476 total_time = (double)(getclock_us() - start_time) / 1000000.0;
11477 if (total_time < 0.001)
11478 total_time = 0.001;
11479 if (total_bytes < 1)
11480 total_bytes = 1;
11481 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11482 tok_ident - TOK_IDENT, total_lines, total_bytes,
11483 total_time, (int)(total_lines / total_time),
11484 total_bytes / total_time / 1000000.0);
11487 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
11488 if (outfile)
11489 fclose(s->outfile);
11490 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
11491 ret = tcc_run(s, argc - optind, argv + optind);
11492 } else
11493 ret = tcc_output_file(s, outfile) ? 1 : 0;
11494 the_end:
11495 /* XXX: cannot do it with bound checking because of the malloc hooks */
11496 if (!do_bounds_check)
11497 tcc_delete(s);
11499 #ifdef MEM_DEBUG
11500 if (do_bench) {
11501 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
11503 #endif
11504 return ret;
11507 #endif