tcc -E: preserve spaces, alternative solution
[tinycc.git] / tcc.c
blob793acb30881a35ffdc543d02bf960f257f6a4cc0
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define _GNU_SOURCE
21 #include "config.h"
23 #ifdef CONFIG_TCCBOOT
25 #include "tccboot.h"
26 #define CONFIG_TCC_STATIC
28 #else
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <math.h>
36 #include <signal.h>
37 #include <fcntl.h>
38 #include <setjmp.h>
39 #include <time.h>
41 #ifdef _WIN32
42 #include <windows.h>
43 #include <sys/timeb.h>
44 #ifdef _MSC_VER
45 #define inline __inline
46 #endif
47 #endif
49 #ifndef _WIN32
50 #include <unistd.h>
51 #include <sys/time.h>
52 #include <sys/ucontext.h>
53 #include <sys/mman.h>
54 #endif
56 #endif /* !CONFIG_TCCBOOT */
58 #ifndef PAGESIZE
59 #define PAGESIZE 4096
60 #endif
62 #include "elf.h"
63 #include "stab.h"
65 #ifndef O_BINARY
66 #define O_BINARY 0
67 #endif
69 #include "libtcc.h"
71 /* parser debug */
72 //#define PARSE_DEBUG
73 /* preprocessor debug */
74 //#define PP_DEBUG
75 /* include file debug */
76 //#define INC_DEBUG
78 //#define MEM_DEBUG
80 /* assembler debug */
81 //#define ASM_DEBUG
83 /* target selection */
84 //#define TCC_TARGET_I386 /* i386 code generator */
85 //#define TCC_TARGET_ARM /* ARMv4 code generator */
86 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
87 //#define TCC_TARGET_X86_64 /* x86-64 code generator */
89 /* default target is I386 */
90 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
91 !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)
92 #define TCC_TARGET_I386
93 #endif
95 #if !defined(_WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
96 !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)
97 #define CONFIG_TCC_BCHECK /* enable bound checking code */
98 #endif
100 #if defined(_WIN32) && !defined(TCC_TARGET_PE)
101 #define CONFIG_TCC_STATIC
102 #endif
104 /* define it to include assembler support */
105 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67) && \
106 !defined(TCC_TARGET_X86_64)
107 #define CONFIG_TCC_ASM
108 #endif
110 /* object format selection */
111 #if defined(TCC_TARGET_C67)
112 #define TCC_TARGET_COFF
113 #endif
115 #define FALSE 0
116 #define false 0
117 #define TRUE 1
118 #define true 1
119 typedef int BOOL;
121 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
122 executables or dlls */
123 #define CONFIG_TCC_CRT_PREFIX CONFIG_SYSROOT "/usr/lib"
125 #define INCLUDE_STACK_SIZE 32
126 #define IFDEF_STACK_SIZE 64
127 #define VSTACK_SIZE 256
128 #define STRING_MAX_SIZE 1024
129 #define PACK_STACK_SIZE 8
131 #define TOK_HASH_SIZE 8192 /* must be a power of two */
132 #define TOK_ALLOC_INCR 512 /* must be a power of two */
133 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
135 /* token symbol management */
136 typedef struct TokenSym {
137 struct TokenSym *hash_next;
138 struct Sym *sym_define; /* direct pointer to define */
139 struct Sym *sym_label; /* direct pointer to label */
140 struct Sym *sym_struct; /* direct pointer to structure */
141 struct Sym *sym_identifier; /* direct pointer to identifier */
142 int tok; /* token number */
143 int len;
144 char str[1];
145 } TokenSym;
147 #ifdef TCC_TARGET_PE
148 typedef unsigned short nwchar_t;
149 #else
150 typedef int nwchar_t;
151 #endif
153 typedef struct CString {
154 int size; /* size in bytes */
155 void *data; /* either 'char *' or 'nwchar_t *' */
156 int size_allocated;
157 void *data_allocated; /* if non NULL, data has been malloced */
158 } CString;
160 /* type definition */
161 typedef struct CType {
162 int t;
163 struct Sym *ref;
164 } CType;
166 /* constant value */
167 typedef union CValue {
168 long double ld;
169 double d;
170 float f;
171 int i;
172 unsigned int ui;
173 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
174 long long ll;
175 unsigned long long ull;
176 struct CString *cstr;
177 void *ptr;
178 int tab[1];
179 } CValue;
181 /* value on stack */
182 typedef struct SValue {
183 CType type; /* type */
184 unsigned short r; /* register + flags */
185 unsigned short r2; /* second register, used for 'long long'
186 type. If not used, set to VT_CONST */
187 CValue c; /* constant, if VT_CONST */
188 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
189 } SValue;
191 /* symbol management */
192 typedef struct Sym {
193 int v; /* symbol token */
194 long r; /* associated register */
195 long c; /* associated number */
196 CType type; /* associated type */
197 struct Sym *next; /* next related symbol */
198 struct Sym *prev; /* prev symbol in stack */
199 struct Sym *prev_tok; /* previous symbol for this token */
200 } Sym;
202 /* section definition */
203 /* XXX: use directly ELF structure for parameters ? */
204 /* special flag to indicate that the section should not be linked to
205 the other ones */
206 #define SHF_PRIVATE 0x80000000
208 typedef struct Section {
209 unsigned long data_offset; /* current data offset */
210 unsigned char *data; /* section data */
211 unsigned long data_allocated; /* used for realloc() handling */
212 int sh_name; /* elf section name (only used during output) */
213 int sh_num; /* elf section number */
214 int sh_type; /* elf section type */
215 int sh_flags; /* elf section flags */
216 int sh_info; /* elf section info */
217 int sh_addralign; /* elf section alignment */
218 int sh_entsize; /* elf entry size */
219 unsigned long sh_size; /* section size (only used during output) */
220 unsigned long sh_addr; /* address at which the section is relocated */
221 unsigned long sh_offset; /* file offset */
222 int nb_hashed_syms; /* used to resize the hash table */
223 struct Section *link; /* link to another section */
224 struct Section *reloc; /* corresponding section for relocation, if any */
225 struct Section *hash; /* hash table for symbols */
226 struct Section *next;
227 char name[1]; /* section name */
228 } Section;
230 typedef struct DLLReference {
231 int level;
232 void *handle;
233 char name[1];
234 } DLLReference;
236 /* GNUC attribute definition */
237 typedef struct AttributeDef {
238 int aligned;
239 int packed;
240 Section *section;
241 int func_attr; /* calling convention, exports, ... */
242 } AttributeDef;
244 /* -------------------------------------------------- */
245 /* gr: wrappers for casting sym->r for other purposes */
246 typedef struct {
247 unsigned
248 func_call : 8,
249 func_args : 8,
250 func_export : 1;
251 } func_attr_t;
253 #define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
254 #define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
255 #define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
256 #define INLINE_DEF(r) (*(int **)&(r))
257 /* -------------------------------------------------- */
259 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
260 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
261 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
263 /* stored in 'Sym.c' field */
264 #define FUNC_NEW 1 /* ansi function prototype */
265 #define FUNC_OLD 2 /* old function prototype */
266 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
268 /* stored in 'Sym.r' field */
269 #define FUNC_CDECL 0 /* standard c call */
270 #define FUNC_STDCALL 1 /* pascal c call */
271 #define FUNC_FASTCALL1 2 /* first param in %eax */
272 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
273 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
274 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
276 /* field 'Sym.t' for macros */
277 #define MACRO_OBJ 0 /* object like macro */
278 #define MACRO_FUNC 1 /* function like macro */
280 /* field 'Sym.r' for C labels */
281 #define LABEL_DEFINED 0 /* label is defined */
282 #define LABEL_FORWARD 1 /* label is forward defined */
283 #define LABEL_DECLARED 2 /* label is declared but never used */
285 /* type_decl() types */
286 #define TYPE_ABSTRACT 1 /* type without variable */
287 #define TYPE_DIRECT 2 /* type with variable */
289 #define IO_BUF_SIZE 8192
291 typedef struct BufferedFile {
292 uint8_t *buf_ptr;
293 uint8_t *buf_end;
294 int fd;
295 int line_num; /* current line number - here to simplify code */
296 int ifndef_macro; /* #ifndef macro / #endif search */
297 int ifndef_macro_saved; /* saved ifndef_macro */
298 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
299 char inc_type; /* type of include */
300 char inc_filename[512]; /* filename specified by the user */
301 char filename[1024]; /* current filename - here to simplify code */
302 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
303 } BufferedFile;
305 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
306 #define CH_EOF (-1) /* end of file */
308 /* parsing state (used to save parser state to reparse part of the
309 source several times) */
310 typedef struct ParseState {
311 int *macro_ptr;
312 int line_num;
313 int tok;
314 CValue tokc;
315 } ParseState;
317 /* used to record tokens */
318 typedef struct TokenString {
319 int *str;
320 int len;
321 int allocated_len;
322 int last_line_num;
323 } TokenString;
325 /* include file cache, used to find files faster and also to eliminate
326 inclusion if the include file is protected by #ifndef ... #endif */
327 typedef struct CachedInclude {
328 int ifndef_macro;
329 int hash_next; /* -1 if none */
330 char type; /* '"' or '>' to give include type */
331 char filename[1]; /* path specified in #include */
332 } CachedInclude;
334 #define CACHED_INCLUDES_HASH_SIZE 512
336 /* parser */
337 static struct BufferedFile *file;
338 static int ch, tok;
339 static CValue tokc;
340 static CString tokcstr; /* current parsed string, if any */
341 /* additional informations about token */
342 static int tok_flags;
343 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
344 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
345 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
346 #define TOK_FLAG_EOF 0x0008 /* end of file */
348 static int *macro_ptr, *macro_ptr_allocated;
349 static int *unget_saved_macro_ptr;
350 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
351 static int unget_buffer_enabled;
352 static int parse_flags;
353 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
354 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
355 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
356 token. line feed is also
357 returned at eof */
358 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
359 #define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
361 static Section *text_section, *data_section, *bss_section; /* predefined sections */
362 static Section *cur_text_section; /* current section where function code is
363 generated */
364 #ifdef CONFIG_TCC_ASM
365 static Section *last_text_section; /* to handle .previous asm directive */
366 #endif
367 /* bound check related sections */
368 static Section *bounds_section; /* contains global data bound description */
369 static Section *lbounds_section; /* contains local data bound description */
370 /* symbol sections */
371 static Section *symtab_section, *strtab_section;
373 /* debug sections */
374 static Section *stab_section, *stabstr_section;
376 /* loc : local variable index
377 ind : output code index
378 rsym: return symbol
379 anon_sym: anonymous symbol index
381 static int rsym, anon_sym, ind, loc;
382 /* expression generation modifiers */
383 static int const_wanted; /* true if constant wanted */
384 static int nocode_wanted; /* true if no code generation wanted for an expression */
385 static int global_expr; /* true if compound literals must be allocated
386 globally (used during initializers parsing */
387 static CType func_vt; /* current function return type (used by return
388 instruction) */
389 static int func_vc;
390 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
391 static int tok_ident;
392 static TokenSym **table_ident;
393 static TokenSym *hash_ident[TOK_HASH_SIZE];
394 static char token_buf[STRING_MAX_SIZE + 1];
395 static char *funcname;
396 static Sym *global_stack, *local_stack;
397 static Sym *define_stack;
398 static Sym *global_label_stack, *local_label_stack;
399 /* symbol allocator */
400 #define SYM_POOL_NB (8192 / sizeof(Sym))
401 static Sym *sym_free_first;
402 static void **sym_pools;
403 static int nb_sym_pools;
405 static SValue vstack[VSTACK_SIZE], *vtop;
406 /* some predefined types */
407 static CType char_pointer_type, func_old_type, int_type;
408 /* true if isid(c) || isnum(c) */
409 static unsigned char isidnum_table[256-CH_EOF];
411 /* display some information during compilation */
412 static int verbose = 0;
414 /* compile with debug symbol (and use them if error during execution) */
415 static int do_debug = 0;
417 /* compile with built-in memory and bounds checker */
418 static int do_bounds_check = 0;
420 /* display benchmark infos */
421 #if !defined(LIBTCC)
422 static int do_bench = 0;
423 #endif
424 static int total_lines;
425 static int total_bytes;
427 /* use GNU C extensions */
428 static int gnu_ext = 1;
430 /* use Tiny C extensions */
431 static int tcc_ext = 1;
433 /* max number of callers shown if error */
434 static int num_callers = 6;
435 static const char **rt_bound_error_msg;
437 /* XXX: get rid of this ASAP */
438 static struct TCCState *tcc_state;
440 /* give the path of the tcc libraries */
441 static const char *tcc_lib_path = CONFIG_TCCDIR;
443 struct TCCState {
444 int output_type;
446 BufferedFile **include_stack_ptr;
447 int *ifdef_stack_ptr;
449 /* include file handling */
450 char **include_paths;
451 int nb_include_paths;
452 char **sysinclude_paths;
453 int nb_sysinclude_paths;
454 CachedInclude **cached_includes;
455 int nb_cached_includes;
457 char **library_paths;
458 int nb_library_paths;
460 /* array of all loaded dlls (including those referenced by loaded
461 dlls) */
462 DLLReference **loaded_dlls;
463 int nb_loaded_dlls;
465 /* sections */
466 Section **sections;
467 int nb_sections; /* number of sections, including first dummy section */
469 Section **priv_sections;
470 int nb_priv_sections; /* number of private sections */
472 /* got handling */
473 Section *got;
474 Section *plt;
475 unsigned long *got_offsets;
476 int nb_got_offsets;
477 /* give the correspondance from symtab indexes to dynsym indexes */
478 int *symtab_to_dynsym;
480 /* temporary dynamic symbol sections (for dll loading) */
481 Section *dynsymtab_section;
482 /* exported dynamic symbol section */
483 Section *dynsym;
485 int nostdinc; /* if true, no standard headers are added */
486 int nostdlib; /* if true, no standard libraries are added */
488 int nocommon; /* if true, do not use common symbols for .bss data */
490 /* if true, static linking is performed */
491 int static_link;
493 /* soname as specified on the command line (-soname) */
494 const char *soname;
496 /* if true, all symbols are exported */
497 int rdynamic;
499 /* if true, only link in referenced objects from archive */
500 int alacarte_link;
502 /* address of text section */
503 unsigned long text_addr;
504 int has_text_addr;
506 /* output format, see TCC_OUTPUT_FORMAT_xxx */
507 int output_format;
509 /* C language options */
510 int char_is_unsigned;
511 int leading_underscore;
513 /* warning switches */
514 int warn_write_strings;
515 int warn_unsupported;
516 int warn_error;
517 int warn_none;
518 int warn_implicit_function_declaration;
520 /* error handling */
521 void *error_opaque;
522 void (*error_func)(void *opaque, const char *msg);
523 int error_set_jmp_enabled;
524 jmp_buf error_jmp_buf;
525 int nb_errors;
527 /* tiny assembler state */
528 Sym *asm_labels;
530 /* see include_stack_ptr */
531 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
533 /* see ifdef_stack_ptr */
534 int ifdef_stack[IFDEF_STACK_SIZE];
536 /* see cached_includes */
537 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
539 /* pack stack */
540 int pack_stack[PACK_STACK_SIZE];
541 int *pack_stack_ptr;
543 /* output file for preprocessing */
544 FILE *outfile;
546 /* for tcc_relocate */
547 int runtime_added;
549 #ifdef TCC_TARGET_X86_64
550 /* write PLT and GOT here */
551 char *runtime_plt_and_got;
552 unsigned int runtime_plt_and_got_offset;
553 #endif
556 /* The current value can be: */
557 #define VT_VALMASK 0x00ff
558 #define VT_CONST 0x00f0 /* constant in vc
559 (must be first non register value) */
560 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
561 #define VT_LOCAL 0x00f2 /* offset on stack */
562 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
563 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
564 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
565 #define VT_LVAL 0x0100 /* var is an lvalue */
566 #define VT_SYM 0x0200 /* a symbol value is added */
567 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
568 char/short stored in integer registers) */
569 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
570 dereferencing value */
571 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
572 bounding function call point is in vc */
573 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
574 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
575 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
576 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
578 /* types */
579 #define VT_INT 0 /* integer type */
580 #define VT_BYTE 1 /* signed byte type */
581 #define VT_SHORT 2 /* short type */
582 #define VT_VOID 3 /* void type */
583 #define VT_PTR 4 /* pointer */
584 #define VT_ENUM 5 /* enum definition */
585 #define VT_FUNC 6 /* function type */
586 #define VT_STRUCT 7 /* struct/union definition */
587 #define VT_FLOAT 8 /* IEEE float */
588 #define VT_DOUBLE 9 /* IEEE double */
589 #define VT_LDOUBLE 10 /* IEEE long double */
590 #define VT_BOOL 11 /* ISOC99 boolean type */
591 #define VT_LLONG 12 /* 64 bit integer */
592 #define VT_LONG 13 /* long integer (NEVER USED as type, only
593 during parsing) */
594 #define VT_BTYPE 0x000f /* mask for basic type */
595 #define VT_UNSIGNED 0x0010 /* unsigned type */
596 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
597 #define VT_BITFIELD 0x0040 /* bitfield modifier */
598 #define VT_CONSTANT 0x0800 /* const modifier */
599 #define VT_VOLATILE 0x1000 /* volatile modifier */
600 #define VT_SIGNED 0x2000 /* signed type */
602 /* storage */
603 #define VT_EXTERN 0x00000080 /* extern definition */
604 #define VT_STATIC 0x00000100 /* static variable */
605 #define VT_TYPEDEF 0x00000200 /* typedef definition */
606 #define VT_INLINE 0x00000400 /* inline definition */
608 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
610 /* type mask (except storage) */
611 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
612 #define VT_TYPE (~(VT_STORAGE))
614 /* token values */
616 /* warning: the following compare tokens depend on i386 asm code */
617 #define TOK_ULT 0x92
618 #define TOK_UGE 0x93
619 #define TOK_EQ 0x94
620 #define TOK_NE 0x95
621 #define TOK_ULE 0x96
622 #define TOK_UGT 0x97
623 #define TOK_Nset 0x98
624 #define TOK_Nclear 0x99
625 #define TOK_LT 0x9c
626 #define TOK_GE 0x9d
627 #define TOK_LE 0x9e
628 #define TOK_GT 0x9f
630 #define TOK_LAND 0xa0
631 #define TOK_LOR 0xa1
633 #define TOK_DEC 0xa2
634 #define TOK_MID 0xa3 /* inc/dec, to void constant */
635 #define TOK_INC 0xa4
636 #define TOK_UDIV 0xb0 /* unsigned division */
637 #define TOK_UMOD 0xb1 /* unsigned modulo */
638 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
639 #define TOK_CINT 0xb3 /* number in tokc */
640 #define TOK_CCHAR 0xb4 /* char constant in tokc */
641 #define TOK_STR 0xb5 /* pointer to string in tokc */
642 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
643 #define TOK_LCHAR 0xb7
644 #define TOK_LSTR 0xb8
645 #define TOK_CFLOAT 0xb9 /* float constant */
646 #define TOK_LINENUM 0xba /* line number info */
647 #define TOK_CDOUBLE 0xc0 /* double constant */
648 #define TOK_CLDOUBLE 0xc1 /* long double constant */
649 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
650 #define TOK_ADDC1 0xc3 /* add with carry generation */
651 #define TOK_ADDC2 0xc4 /* add with carry use */
652 #define TOK_SUBC1 0xc5 /* add with carry generation */
653 #define TOK_SUBC2 0xc6 /* add with carry use */
654 #define TOK_CUINT 0xc8 /* unsigned int constant */
655 #define TOK_CLLONG 0xc9 /* long long constant */
656 #define TOK_CULLONG 0xca /* unsigned long long constant */
657 #define TOK_ARROW 0xcb
658 #define TOK_DOTS 0xcc /* three dots */
659 #define TOK_SHR 0xcd /* unsigned shift right */
660 #define TOK_PPNUM 0xce /* preprocessor number */
662 #define TOK_SHL 0x01 /* shift left */
663 #define TOK_SAR 0x02 /* signed shift right */
665 /* assignement operators : normal operator or 0x80 */
666 #define TOK_A_MOD 0xa5
667 #define TOK_A_AND 0xa6
668 #define TOK_A_MUL 0xaa
669 #define TOK_A_ADD 0xab
670 #define TOK_A_SUB 0xad
671 #define TOK_A_DIV 0xaf
672 #define TOK_A_XOR 0xde
673 #define TOK_A_OR 0xfc
674 #define TOK_A_SHL 0x81
675 #define TOK_A_SAR 0x82
677 #ifndef offsetof
678 #define offsetof(type, field) ((size_t) &((type *)0)->field)
679 #endif
681 #ifndef countof
682 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
683 #endif
685 /* WARNING: the content of this string encodes token numbers */
686 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";
688 #define TOK_EOF (-1) /* end of file */
689 #define TOK_LINEFEED 10 /* line feed */
691 /* all identificators and strings have token above that */
692 #define TOK_IDENT 256
694 /* only used for i386 asm opcodes definitions */
695 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
697 #define DEF_BWL(x) \
698 DEF(TOK_ASM_ ## x ## b, #x "b") \
699 DEF(TOK_ASM_ ## x ## w, #x "w") \
700 DEF(TOK_ASM_ ## x ## l, #x "l") \
701 DEF(TOK_ASM_ ## x, #x)
703 #define DEF_WL(x) \
704 DEF(TOK_ASM_ ## x ## w, #x "w") \
705 DEF(TOK_ASM_ ## x ## l, #x "l") \
706 DEF(TOK_ASM_ ## x, #x)
708 #define DEF_FP1(x) \
709 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
710 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
711 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
712 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
714 #define DEF_FP(x) \
715 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
716 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
717 DEF_FP1(x)
719 #define DEF_ASMTEST(x) \
720 DEF_ASM(x ## o) \
721 DEF_ASM(x ## no) \
722 DEF_ASM(x ## b) \
723 DEF_ASM(x ## c) \
724 DEF_ASM(x ## nae) \
725 DEF_ASM(x ## nb) \
726 DEF_ASM(x ## nc) \
727 DEF_ASM(x ## ae) \
728 DEF_ASM(x ## e) \
729 DEF_ASM(x ## z) \
730 DEF_ASM(x ## ne) \
731 DEF_ASM(x ## nz) \
732 DEF_ASM(x ## be) \
733 DEF_ASM(x ## na) \
734 DEF_ASM(x ## nbe) \
735 DEF_ASM(x ## a) \
736 DEF_ASM(x ## s) \
737 DEF_ASM(x ## ns) \
738 DEF_ASM(x ## p) \
739 DEF_ASM(x ## pe) \
740 DEF_ASM(x ## np) \
741 DEF_ASM(x ## po) \
742 DEF_ASM(x ## l) \
743 DEF_ASM(x ## nge) \
744 DEF_ASM(x ## nl) \
745 DEF_ASM(x ## ge) \
746 DEF_ASM(x ## le) \
747 DEF_ASM(x ## ng) \
748 DEF_ASM(x ## nle) \
749 DEF_ASM(x ## g)
751 #define TOK_ASM_int TOK_INT
753 enum tcc_token {
754 TOK_LAST = TOK_IDENT - 1,
755 #define DEF(id, str) id,
756 #include "tcctok.h"
757 #undef DEF
760 static const char tcc_keywords[] =
761 #define DEF(id, str) str "\0"
762 #include "tcctok.h"
763 #undef DEF
766 #define TOK_UIDENT TOK_DEFINE
768 #ifdef _WIN32
769 #define snprintf _snprintf
770 #define vsnprintf _vsnprintf
771 #ifndef __GNUC__
772 #define strtold (long double)strtod
773 #define strtof (float)strtod
774 #define strtoll (long long)strtol
775 #endif
776 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
777 || defined(__OpenBSD__)
778 /* currently incorrect */
779 long double strtold(const char *nptr, char **endptr)
781 return (long double)strtod(nptr, endptr);
783 float strtof(const char *nptr, char **endptr)
785 return (float)strtod(nptr, endptr);
787 #else
788 /* XXX: need to define this to use them in non ISOC99 context */
789 extern float strtof (const char *__nptr, char **__endptr);
790 extern long double strtold (const char *__nptr, char **__endptr);
791 #endif
793 static char *pstrcpy(char *buf, int buf_size, const char *s);
794 static char *pstrcat(char *buf, int buf_size, const char *s);
795 static char *tcc_basename(const char *name);
796 static char *tcc_fileextension (const char *p);
798 static void next(void);
799 static void next_nomacro(void);
800 static void next_nomacro_spc(void);
801 static void parse_expr_type(CType *type);
802 static void expr_type(CType *type);
803 static void unary_type(CType *type);
804 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
805 int case_reg, int is_expr);
806 static int expr_const(void);
807 static void expr_eq(void);
808 static void gexpr(void);
809 static void gen_inline_functions(void);
810 static void decl(int l);
811 static void decl_initializer(CType *type, Section *sec, unsigned long c,
812 int first, int size_only);
813 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
814 int has_init, int v, int scope);
815 int gv(int rc);
816 void gv2(int rc1, int rc2);
817 void move_reg(int r, int s);
818 void save_regs(int n);
819 void save_reg(int r);
820 void vpop(void);
821 void vswap(void);
822 void vdup(void);
823 int get_reg(int rc);
824 int get_reg_ex(int rc,int rc2);
826 struct macro_level {
827 struct macro_level *prev;
828 int *p;
831 static void macro_subst(TokenString *tok_str, Sym **nested_list,
832 const int *macro_str, struct macro_level **can_read_stream);
833 void gen_op(int op);
834 void force_charshort_cast(int t);
835 static void gen_cast(CType *type);
836 void vstore(void);
837 static Sym *sym_find(int v);
838 static Sym *sym_push(int v, CType *type, int r, int c);
840 /* type handling */
841 static int type_size(CType *type, int *a);
842 static inline CType *pointed_type(CType *type);
843 static int pointed_size(CType *type);
844 static int lvalue_type(int t);
845 static int parse_btype(CType *type, AttributeDef *ad);
846 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
847 static int compare_types(CType *type1, CType *type2, int unqualified);
848 static int is_compatible_types(CType *type1, CType *type2);
849 static int is_compatible_parameter_types(CType *type1, CType *type2);
851 int ieee_finite(double d);
852 void error(const char *fmt, ...);
853 void vpushi(int v);
854 void vpushll(long long v);
855 void vrott(int n);
856 void vnrott(int n);
857 void lexpand_nr(void);
858 static void vpush_global_sym(CType *type, int v);
859 void vset(CType *type, int r, int v);
860 void type_to_str(char *buf, int buf_size,
861 CType *type, const char *varstr);
862 char *get_tok_str(int v, CValue *cv);
863 static Sym *get_sym_ref(CType *type, Section *sec,
864 unsigned long offset, unsigned long size);
865 static Sym *external_global_sym(int v, CType *type, int r);
867 /* section generation */
868 static void section_realloc(Section *sec, unsigned long new_size);
869 static void *section_ptr_add(Section *sec, unsigned long size);
870 static void put_extern_sym(Sym *sym, Section *section,
871 unsigned long value, unsigned long size);
872 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
873 static int put_elf_str(Section *s, const char *sym);
874 static int put_elf_sym(Section *s,
875 unsigned long value, unsigned long size,
876 int info, int other, int shndx, const char *name);
877 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
878 int info, int other, int sh_num, const char *name);
879 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
880 int type, int symbol);
881 static void put_stabs(const char *str, int type, int other, int desc,
882 unsigned long value);
883 static void put_stabs_r(const char *str, int type, int other, int desc,
884 unsigned long value, Section *sec, int sym_index);
885 static void put_stabn(int type, int other, int desc, int value);
886 static void put_stabd(int type, int other, int desc);
887 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
889 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
890 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
891 #define AFF_PREPROCESS 0x0004 /* preprocess file */
892 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
894 /* tcccoff.c */
895 int tcc_output_coff(TCCState *s1, FILE *f);
897 /* tccpe.c */
898 void *resolve_sym(TCCState *s1, const char *sym, int type);
899 int pe_load_def_file(struct TCCState *s1, int fd);
900 int pe_test_res_file(void *v, int size);
901 int pe_load_res_file(struct TCCState *s1, int fd);
902 void pe_add_runtime(struct TCCState *s1);
903 void pe_guess_outfile(char *objfilename, int output_type);
904 int pe_output_file(struct TCCState *s1, const char *filename);
906 /* tccasm.c */
908 #ifdef CONFIG_TCC_ASM
910 typedef struct ExprValue {
911 uint32_t v;
912 Sym *sym;
913 } ExprValue;
915 #define MAX_ASM_OPERANDS 30
917 typedef struct ASMOperand {
918 int id; /* GCC 3 optionnal identifier (0 if number only supported */
919 char *constraint;
920 char asm_str[16]; /* computed asm string for operand */
921 SValue *vt; /* C value of the expression */
922 int ref_index; /* if >= 0, gives reference to a output constraint */
923 int input_index; /* if >= 0, gives reference to an input constraint */
924 int priority; /* priority, used to assign registers */
925 int reg; /* if >= 0, register number used for this operand */
926 int is_llong; /* true if double register value */
927 int is_memory; /* true if memory operand */
928 int is_rw; /* for '+' modifier */
929 } ASMOperand;
931 static void asm_expr(TCCState *s1, ExprValue *pe);
932 static int asm_int_expr(TCCState *s1);
933 static int find_constraint(ASMOperand *operands, int nb_operands,
934 const char *name, const char **pp);
936 static int tcc_assemble(TCCState *s1, int do_preprocess);
938 #endif
940 static void asm_instr(void);
941 static void asm_global_instr(void);
943 /* true if float/double/long double type */
944 static inline int is_float(int t)
946 int bt;
947 bt = t & VT_BTYPE;
948 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
951 #ifdef TCC_TARGET_I386
952 #include "i386-gen.c"
953 #endif
955 #ifdef TCC_TARGET_ARM
956 #include "arm-gen.c"
957 #endif
959 #ifdef TCC_TARGET_C67
960 #include "c67-gen.c"
961 #endif
963 #ifdef TCC_TARGET_X86_64
964 #include "x86_64-gen.c"
965 #endif
967 #ifdef CONFIG_TCC_STATIC
969 #define RTLD_LAZY 0x001
970 #define RTLD_NOW 0x002
971 #define RTLD_GLOBAL 0x100
972 #define RTLD_DEFAULT NULL
974 /* dummy function for profiling */
975 void *dlopen(const char *filename, int flag)
977 return NULL;
980 void dlclose(void *p)
984 const char *dlerror(void)
986 return "error";
989 typedef struct TCCSyms {
990 char *str;
991 void *ptr;
992 } TCCSyms;
994 #define TCCSYM(a) { #a, &a, },
996 /* add the symbol you want here if no dynamic linking is done */
997 static TCCSyms tcc_syms[] = {
998 #if !defined(CONFIG_TCCBOOT)
999 TCCSYM(printf)
1000 TCCSYM(fprintf)
1001 TCCSYM(fopen)
1002 TCCSYM(fclose)
1003 #endif
1004 { NULL, NULL },
1007 void *resolve_sym(TCCState *s1, const char *symbol, int type)
1009 TCCSyms *p;
1010 p = tcc_syms;
1011 while (p->str != NULL) {
1012 if (!strcmp(p->str, symbol))
1013 return p->ptr;
1014 p++;
1016 return NULL;
1019 #elif !defined(_WIN32)
1021 #include <dlfcn.h>
1023 void *resolve_sym(TCCState *s1, const char *sym, int type)
1025 return dlsym(RTLD_DEFAULT, sym);
1028 #endif
1030 /********************************************************/
1032 /* we use our own 'finite' function to avoid potential problems with
1033 non standard math libs */
1034 /* XXX: endianness dependent */
1035 int ieee_finite(double d)
1037 int *p = (int *)&d;
1038 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
1041 /* copy a string and truncate it. */
1042 static char *pstrcpy(char *buf, int buf_size, const char *s)
1044 char *q, *q_end;
1045 int c;
1047 if (buf_size > 0) {
1048 q = buf;
1049 q_end = buf + buf_size - 1;
1050 while (q < q_end) {
1051 c = *s++;
1052 if (c == '\0')
1053 break;
1054 *q++ = c;
1056 *q = '\0';
1058 return buf;
1061 /* strcat and truncate. */
1062 static char *pstrcat(char *buf, int buf_size, const char *s)
1064 int len;
1065 len = strlen(buf);
1066 if (len < buf_size)
1067 pstrcpy(buf + len, buf_size - len, s);
1068 return buf;
1071 #ifndef LIBTCC
1072 static int strstart(const char *str, const char *val, const char **ptr)
1074 const char *p, *q;
1075 p = str;
1076 q = val;
1077 while (*q != '\0') {
1078 if (*p != *q)
1079 return 0;
1080 p++;
1081 q++;
1083 if (ptr)
1084 *ptr = p;
1085 return 1;
1087 #endif
1089 #ifdef _WIN32
1090 #define IS_PATHSEP(c) (c == '/' || c == '\\')
1091 #define IS_ABSPATH(p) (IS_PATHSEP(p[0]) || (p[0] && p[1] == ':' && IS_PATHSEP(p[2])))
1092 #define PATHCMP stricmp
1093 #else
1094 #define IS_PATHSEP(c) (c == '/')
1095 #define IS_ABSPATH(p) IS_PATHSEP(p[0])
1096 #define PATHCMP strcmp
1097 #endif
1099 /* extract the basename of a file */
1100 static char *tcc_basename(const char *name)
1102 char *p = strchr(name, 0);
1103 while (p > name && !IS_PATHSEP(p[-1]))
1104 --p;
1105 return p;
1108 static char *tcc_fileextension (const char *name)
1110 char *b = tcc_basename(name);
1111 char *e = strrchr(b, '.');
1112 return e ? e : strchr(b, 0);
1115 #ifdef _WIN32
1116 char *normalize_slashes(char *path)
1118 char *p;
1119 for (p = path; *p; ++p)
1120 if (*p == '\\')
1121 *p = '/';
1122 return path;
1125 char *w32_tcc_lib_path(void)
1127 /* on win32, we suppose the lib and includes are at the location
1128 of 'tcc.exe' */
1129 char path[1024], *p;
1130 GetModuleFileNameA(NULL, path, sizeof path);
1131 p = tcc_basename(normalize_slashes(strlwr(path)));
1132 if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
1133 p -= 5;
1134 else if (p > path)
1135 p--;
1136 *p = 0;
1137 return strdup(path);
1139 #endif
1141 void set_pages_executable(void *ptr, unsigned long length)
1143 #ifdef _WIN32
1144 unsigned long old_protect;
1145 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
1146 #else
1147 unsigned long start, end;
1148 start = (unsigned long)ptr & ~(PAGESIZE - 1);
1149 end = (unsigned long)ptr + length;
1150 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
1151 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
1152 #endif
1155 /* memory management */
1156 #ifdef MEM_DEBUG
1157 int mem_cur_size;
1158 int mem_max_size;
1159 unsigned malloc_usable_size(void*);
1160 #endif
1162 static inline void tcc_free(void *ptr)
1164 #ifdef MEM_DEBUG
1165 mem_cur_size -= malloc_usable_size(ptr);
1166 #endif
1167 free(ptr);
1170 static void *tcc_malloc(unsigned long size)
1172 void *ptr;
1173 ptr = malloc(size);
1174 if (!ptr && size)
1175 error("memory full");
1176 #ifdef MEM_DEBUG
1177 mem_cur_size += malloc_usable_size(ptr);
1178 if (mem_cur_size > mem_max_size)
1179 mem_max_size = mem_cur_size;
1180 #endif
1181 return ptr;
1184 static void *tcc_mallocz(unsigned long size)
1186 void *ptr;
1187 ptr = tcc_malloc(size);
1188 memset(ptr, 0, size);
1189 return ptr;
1192 static inline void *tcc_realloc(void *ptr, unsigned long size)
1194 void *ptr1;
1195 #ifdef MEM_DEBUG
1196 mem_cur_size -= malloc_usable_size(ptr);
1197 #endif
1198 ptr1 = realloc(ptr, size);
1199 #ifdef MEM_DEBUG
1200 /* NOTE: count not correct if alloc error, but not critical */
1201 mem_cur_size += malloc_usable_size(ptr1);
1202 if (mem_cur_size > mem_max_size)
1203 mem_max_size = mem_cur_size;
1204 #endif
1205 return ptr1;
1208 static char *tcc_strdup(const char *str)
1210 char *ptr;
1211 ptr = tcc_malloc(strlen(str) + 1);
1212 strcpy(ptr, str);
1213 return ptr;
1216 #define free(p) use_tcc_free(p)
1217 #define malloc(s) use_tcc_malloc(s)
1218 #define realloc(p, s) use_tcc_realloc(p, s)
1220 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1222 int nb, nb_alloc;
1223 void **pp;
1225 nb = *nb_ptr;
1226 pp = *ptab;
1227 /* every power of two we double array size */
1228 if ((nb & (nb - 1)) == 0) {
1229 if (!nb)
1230 nb_alloc = 1;
1231 else
1232 nb_alloc = nb * 2;
1233 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1234 if (!pp)
1235 error("memory full");
1236 *ptab = pp;
1238 pp[nb++] = data;
1239 *nb_ptr = nb;
1242 static void dynarray_reset(void *pp, int *n)
1244 void **p;
1245 for (p = *(void***)pp; *n; ++p, --*n)
1246 if (*p)
1247 tcc_free(*p);
1248 tcc_free(*(void**)pp);
1249 *(void**)pp = NULL;
1252 /* symbol allocator */
1253 static Sym *__sym_malloc(void)
1255 Sym *sym_pool, *sym, *last_sym;
1256 int i;
1258 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1259 dynarray_add(&sym_pools, &nb_sym_pools, sym_pool);
1261 last_sym = sym_free_first;
1262 sym = sym_pool;
1263 for(i = 0; i < SYM_POOL_NB; i++) {
1264 sym->next = last_sym;
1265 last_sym = sym;
1266 sym++;
1268 sym_free_first = last_sym;
1269 return last_sym;
1272 static inline Sym *sym_malloc(void)
1274 Sym *sym;
1275 sym = sym_free_first;
1276 if (!sym)
1277 sym = __sym_malloc();
1278 sym_free_first = sym->next;
1279 return sym;
1282 static inline void sym_free(Sym *sym)
1284 sym->next = sym_free_first;
1285 sym_free_first = sym;
1288 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1290 Section *sec;
1292 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1293 strcpy(sec->name, name);
1294 sec->sh_type = sh_type;
1295 sec->sh_flags = sh_flags;
1296 switch(sh_type) {
1297 case SHT_HASH:
1298 case SHT_REL:
1299 case SHT_RELA:
1300 case SHT_DYNSYM:
1301 case SHT_SYMTAB:
1302 case SHT_DYNAMIC:
1303 sec->sh_addralign = 4;
1304 break;
1305 case SHT_STRTAB:
1306 sec->sh_addralign = 1;
1307 break;
1308 default:
1309 sec->sh_addralign = 32; /* default conservative alignment */
1310 break;
1313 if (sh_flags & SHF_PRIVATE) {
1314 dynarray_add((void ***)&s1->priv_sections, &s1->nb_priv_sections, sec);
1315 } else {
1316 sec->sh_num = s1->nb_sections;
1317 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1320 return sec;
1323 static void free_section(Section *s)
1325 tcc_free(s->data);
1328 /* realloc section and set its content to zero */
1329 static void section_realloc(Section *sec, unsigned long new_size)
1331 unsigned long size;
1332 unsigned char *data;
1334 size = sec->data_allocated;
1335 if (size == 0)
1336 size = 1;
1337 while (size < new_size)
1338 size = size * 2;
1339 data = tcc_realloc(sec->data, size);
1340 if (!data)
1341 error("memory full");
1342 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1343 sec->data = data;
1344 sec->data_allocated = size;
1347 /* reserve at least 'size' bytes in section 'sec' from
1348 sec->data_offset. */
1349 static void *section_ptr_add(Section *sec, unsigned long size)
1351 unsigned long offset, offset1;
1353 offset = sec->data_offset;
1354 offset1 = offset + size;
1355 if (offset1 > sec->data_allocated)
1356 section_realloc(sec, offset1);
1357 sec->data_offset = offset1;
1358 return sec->data + offset;
1361 /* return a reference to a section, and create it if it does not
1362 exists */
1363 Section *find_section(TCCState *s1, const char *name)
1365 Section *sec;
1366 int i;
1367 for(i = 1; i < s1->nb_sections; i++) {
1368 sec = s1->sections[i];
1369 if (!strcmp(name, sec->name))
1370 return sec;
1372 /* sections are created as PROGBITS */
1373 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1376 #define SECTION_ABS ((void *)1)
1378 /* update sym->c so that it points to an external symbol in section
1379 'section' with value 'value' */
1380 static void put_extern_sym2(Sym *sym, Section *section,
1381 unsigned long value, unsigned long size,
1382 int can_add_underscore)
1384 int sym_type, sym_bind, sh_num, info, other, attr;
1385 ElfW(Sym) *esym;
1386 const char *name;
1387 char buf1[256];
1389 if (section == NULL)
1390 sh_num = SHN_UNDEF;
1391 else if (section == SECTION_ABS)
1392 sh_num = SHN_ABS;
1393 else
1394 sh_num = section->sh_num;
1396 other = attr = 0;
1398 if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
1399 sym_type = STT_FUNC;
1400 #ifdef TCC_TARGET_PE
1401 if (sym->type.ref)
1402 attr = sym->type.ref->r;
1403 if (FUNC_EXPORT(attr))
1404 other |= 1;
1405 if (FUNC_CALL(attr) == FUNC_STDCALL)
1406 other |= 2;
1407 #endif
1408 } else {
1409 sym_type = STT_OBJECT;
1412 if (sym->type.t & VT_STATIC)
1413 sym_bind = STB_LOCAL;
1414 else
1415 sym_bind = STB_GLOBAL;
1417 if (!sym->c) {
1418 name = get_tok_str(sym->v, NULL);
1419 #ifdef CONFIG_TCC_BCHECK
1420 if (do_bounds_check) {
1421 char buf[32];
1423 /* XXX: avoid doing that for statics ? */
1424 /* if bound checking is activated, we change some function
1425 names by adding the "__bound" prefix */
1426 switch(sym->v) {
1427 #if 0
1428 /* XXX: we rely only on malloc hooks */
1429 case TOK_malloc:
1430 case TOK_free:
1431 case TOK_realloc:
1432 case TOK_memalign:
1433 case TOK_calloc:
1434 #endif
1435 case TOK_memcpy:
1436 case TOK_memmove:
1437 case TOK_memset:
1438 case TOK_strlen:
1439 case TOK_strcpy:
1440 case TOK__alloca:
1441 strcpy(buf, "__bound_");
1442 strcat(buf, name);
1443 name = buf;
1444 break;
1447 #endif
1449 #ifdef TCC_TARGET_PE
1450 if ((other & 2) && can_add_underscore) {
1451 sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
1452 name = buf1;
1453 } else
1454 #endif
1455 if (tcc_state->leading_underscore && can_add_underscore) {
1456 buf1[0] = '_';
1457 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1458 name = buf1;
1460 info = ELFW(ST_INFO)(sym_bind, sym_type);
1461 sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
1462 } else {
1463 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
1464 esym->st_value = value;
1465 esym->st_size = size;
1466 esym->st_shndx = sh_num;
1467 esym->st_other |= other;
1471 static void put_extern_sym(Sym *sym, Section *section,
1472 unsigned long value, unsigned long size)
1474 put_extern_sym2(sym, section, value, size, 1);
1477 /* add a new relocation entry to symbol 'sym' in section 's' */
1478 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1480 if (!sym->c)
1481 put_extern_sym(sym, NULL, 0, 0);
1482 /* now we can add ELF relocation info */
1483 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1486 static inline int isid(int c)
1488 return (c >= 'a' && c <= 'z') ||
1489 (c >= 'A' && c <= 'Z') ||
1490 c == '_';
1493 static inline int isnum(int c)
1495 return c >= '0' && c <= '9';
1498 static inline int isoct(int c)
1500 return c >= '0' && c <= '7';
1503 static inline int toup(int c)
1505 if (c >= 'a' && c <= 'z')
1506 return c - 'a' + 'A';
1507 else
1508 return c;
1511 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1513 int len;
1514 len = strlen(buf);
1515 vsnprintf(buf + len, buf_size - len, fmt, ap);
1518 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1520 va_list ap;
1521 va_start(ap, fmt);
1522 strcat_vprintf(buf, buf_size, fmt, ap);
1523 va_end(ap);
1526 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1528 char buf[2048];
1529 BufferedFile **f;
1531 buf[0] = '\0';
1532 if (file) {
1533 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1534 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1535 (*f)->filename, (*f)->line_num);
1536 if (file->line_num > 0) {
1537 strcat_printf(buf, sizeof(buf),
1538 "%s:%d: ", file->filename, file->line_num);
1539 } else {
1540 strcat_printf(buf, sizeof(buf),
1541 "%s: ", file->filename);
1543 } else {
1544 strcat_printf(buf, sizeof(buf),
1545 "tcc: ");
1547 if (is_warning)
1548 strcat_printf(buf, sizeof(buf), "warning: ");
1549 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1551 if (!s1->error_func) {
1552 /* default case: stderr */
1553 fprintf(stderr, "%s\n", buf);
1554 } else {
1555 s1->error_func(s1->error_opaque, buf);
1557 if (!is_warning || s1->warn_error)
1558 s1->nb_errors++;
1561 #ifdef LIBTCC
1562 void tcc_set_error_func(TCCState *s, void *error_opaque,
1563 void (*error_func)(void *opaque, const char *msg))
1565 s->error_opaque = error_opaque;
1566 s->error_func = error_func;
1568 #endif
1570 /* error without aborting current compilation */
1571 void error_noabort(const char *fmt, ...)
1573 TCCState *s1 = tcc_state;
1574 va_list ap;
1576 va_start(ap, fmt);
1577 error1(s1, 0, fmt, ap);
1578 va_end(ap);
1581 void error(const char *fmt, ...)
1583 TCCState *s1 = tcc_state;
1584 va_list ap;
1586 va_start(ap, fmt);
1587 error1(s1, 0, fmt, ap);
1588 va_end(ap);
1589 /* better than nothing: in some cases, we accept to handle errors */
1590 if (s1->error_set_jmp_enabled) {
1591 longjmp(s1->error_jmp_buf, 1);
1592 } else {
1593 /* XXX: eliminate this someday */
1594 exit(1);
1598 void expect(const char *msg)
1600 error("%s expected", msg);
1603 void warning(const char *fmt, ...)
1605 TCCState *s1 = tcc_state;
1606 va_list ap;
1608 if (s1->warn_none)
1609 return;
1611 va_start(ap, fmt);
1612 error1(s1, 1, fmt, ap);
1613 va_end(ap);
1616 void skip(int c)
1618 if (tok != c)
1619 error("'%c' expected", c);
1620 next();
1623 static void test_lvalue(void)
1625 if (!(vtop->r & VT_LVAL))
1626 expect("lvalue");
1629 /* allocate a new token */
1630 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1632 TokenSym *ts, **ptable;
1633 int i;
1635 if (tok_ident >= SYM_FIRST_ANOM)
1636 error("memory full");
1638 /* expand token table if needed */
1639 i = tok_ident - TOK_IDENT;
1640 if ((i % TOK_ALLOC_INCR) == 0) {
1641 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1642 if (!ptable)
1643 error("memory full");
1644 table_ident = ptable;
1647 ts = tcc_malloc(sizeof(TokenSym) + len);
1648 table_ident[i] = ts;
1649 ts->tok = tok_ident++;
1650 ts->sym_define = NULL;
1651 ts->sym_label = NULL;
1652 ts->sym_struct = NULL;
1653 ts->sym_identifier = NULL;
1654 ts->len = len;
1655 ts->hash_next = NULL;
1656 memcpy(ts->str, str, len);
1657 ts->str[len] = '\0';
1658 *pts = ts;
1659 return ts;
1662 #define TOK_HASH_INIT 1
1663 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1665 /* find a token and add it if not found */
1666 static TokenSym *tok_alloc(const char *str, int len)
1668 TokenSym *ts, **pts;
1669 int i;
1670 unsigned int h;
1672 h = TOK_HASH_INIT;
1673 for(i=0;i<len;i++)
1674 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1675 h &= (TOK_HASH_SIZE - 1);
1677 pts = &hash_ident[h];
1678 for(;;) {
1679 ts = *pts;
1680 if (!ts)
1681 break;
1682 if (ts->len == len && !memcmp(ts->str, str, len))
1683 return ts;
1684 pts = &(ts->hash_next);
1686 return tok_alloc_new(pts, str, len);
1689 /* CString handling */
1691 static void cstr_realloc(CString *cstr, int new_size)
1693 int size;
1694 void *data;
1696 size = cstr->size_allocated;
1697 if (size == 0)
1698 size = 8; /* no need to allocate a too small first string */
1699 while (size < new_size)
1700 size = size * 2;
1701 data = tcc_realloc(cstr->data_allocated, size);
1702 if (!data)
1703 error("memory full");
1704 cstr->data_allocated = data;
1705 cstr->size_allocated = size;
1706 cstr->data = data;
1709 /* add a byte */
1710 static inline void cstr_ccat(CString *cstr, int ch)
1712 int size;
1713 size = cstr->size + 1;
1714 if (size > cstr->size_allocated)
1715 cstr_realloc(cstr, size);
1716 ((unsigned char *)cstr->data)[size - 1] = ch;
1717 cstr->size = size;
1720 static void cstr_cat(CString *cstr, const char *str)
1722 int c;
1723 for(;;) {
1724 c = *str;
1725 if (c == '\0')
1726 break;
1727 cstr_ccat(cstr, c);
1728 str++;
1732 /* add a wide char */
1733 static void cstr_wccat(CString *cstr, int ch)
1735 int size;
1736 size = cstr->size + sizeof(nwchar_t);
1737 if (size > cstr->size_allocated)
1738 cstr_realloc(cstr, size);
1739 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1740 cstr->size = size;
1743 static void cstr_new(CString *cstr)
1745 memset(cstr, 0, sizeof(CString));
1748 /* free string and reset it to NULL */
1749 static void cstr_free(CString *cstr)
1751 tcc_free(cstr->data_allocated);
1752 cstr_new(cstr);
1755 #define cstr_reset(cstr) cstr_free(cstr)
1757 /* XXX: unicode ? */
1758 static void add_char(CString *cstr, int c)
1760 if (c == '\'' || c == '\"' || c == '\\') {
1761 /* XXX: could be more precise if char or string */
1762 cstr_ccat(cstr, '\\');
1764 if (c >= 32 && c <= 126) {
1765 cstr_ccat(cstr, c);
1766 } else {
1767 cstr_ccat(cstr, '\\');
1768 if (c == '\n') {
1769 cstr_ccat(cstr, 'n');
1770 } else {
1771 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1772 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1773 cstr_ccat(cstr, '0' + (c & 7));
1778 /* XXX: buffer overflow */
1779 /* XXX: float tokens */
1780 char *get_tok_str(int v, CValue *cv)
1782 static char buf[STRING_MAX_SIZE + 1];
1783 static CString cstr_buf;
1784 CString *cstr;
1785 unsigned char *q;
1786 char *p;
1787 int i, len;
1789 /* NOTE: to go faster, we give a fixed buffer for small strings */
1790 cstr_reset(&cstr_buf);
1791 cstr_buf.data = buf;
1792 cstr_buf.size_allocated = sizeof(buf);
1793 p = buf;
1795 switch(v) {
1796 case TOK_CINT:
1797 case TOK_CUINT:
1798 /* XXX: not quite exact, but only useful for testing */
1799 sprintf(p, "%u", cv->ui);
1800 break;
1801 case TOK_CLLONG:
1802 case TOK_CULLONG:
1803 /* XXX: not quite exact, but only useful for testing */
1804 sprintf(p, "%Lu", cv->ull);
1805 break;
1806 case TOK_LCHAR:
1807 cstr_ccat(&cstr_buf, 'L');
1808 case TOK_CCHAR:
1809 cstr_ccat(&cstr_buf, '\'');
1810 add_char(&cstr_buf, cv->i);
1811 cstr_ccat(&cstr_buf, '\'');
1812 cstr_ccat(&cstr_buf, '\0');
1813 break;
1814 case TOK_PPNUM:
1815 cstr = cv->cstr;
1816 len = cstr->size - 1;
1817 for(i=0;i<len;i++)
1818 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1819 cstr_ccat(&cstr_buf, '\0');
1820 break;
1821 case TOK_LSTR:
1822 cstr_ccat(&cstr_buf, 'L');
1823 case TOK_STR:
1824 cstr = cv->cstr;
1825 cstr_ccat(&cstr_buf, '\"');
1826 if (v == TOK_STR) {
1827 len = cstr->size - 1;
1828 for(i=0;i<len;i++)
1829 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1830 } else {
1831 len = (cstr->size / sizeof(nwchar_t)) - 1;
1832 for(i=0;i<len;i++)
1833 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1835 cstr_ccat(&cstr_buf, '\"');
1836 cstr_ccat(&cstr_buf, '\0');
1837 break;
1838 case TOK_LT:
1839 v = '<';
1840 goto addv;
1841 case TOK_GT:
1842 v = '>';
1843 goto addv;
1844 case TOK_DOTS:
1845 return strcpy(p, "...");
1846 case TOK_A_SHL:
1847 return strcpy(p, "<<=");
1848 case TOK_A_SAR:
1849 return strcpy(p, ">>=");
1850 default:
1851 if (v < TOK_IDENT) {
1852 /* search in two bytes table */
1853 q = tok_two_chars;
1854 while (*q) {
1855 if (q[2] == v) {
1856 *p++ = q[0];
1857 *p++ = q[1];
1858 *p = '\0';
1859 return buf;
1861 q += 3;
1863 addv:
1864 *p++ = v;
1865 *p = '\0';
1866 } else if (v < tok_ident) {
1867 return table_ident[v - TOK_IDENT]->str;
1868 } else if (v >= SYM_FIRST_ANOM) {
1869 /* special name for anonymous symbol */
1870 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1871 } else {
1872 /* should never happen */
1873 return NULL;
1875 break;
1877 return cstr_buf.data;
1880 /* push, without hashing */
1881 static Sym *sym_push2(Sym **ps, int v, int t, long c)
1883 Sym *s;
1884 s = sym_malloc();
1885 s->v = v;
1886 s->type.t = t;
1887 s->c = c;
1888 s->next = NULL;
1889 /* add in stack */
1890 s->prev = *ps;
1891 *ps = s;
1892 return s;
1895 /* find a symbol and return its associated structure. 's' is the top
1896 of the symbol stack */
1897 static Sym *sym_find2(Sym *s, int v)
1899 while (s) {
1900 if (s->v == v)
1901 return s;
1902 s = s->prev;
1904 return NULL;
1907 /* structure lookup */
1908 static inline Sym *struct_find(int v)
1910 v -= TOK_IDENT;
1911 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1912 return NULL;
1913 return table_ident[v]->sym_struct;
1916 /* find an identifier */
1917 static inline Sym *sym_find(int v)
1919 v -= TOK_IDENT;
1920 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1921 return NULL;
1922 return table_ident[v]->sym_identifier;
1925 /* push a given symbol on the symbol stack */
1926 static Sym *sym_push(int v, CType *type, int r, int c)
1928 Sym *s, **ps;
1929 TokenSym *ts;
1931 if (local_stack)
1932 ps = &local_stack;
1933 else
1934 ps = &global_stack;
1935 s = sym_push2(ps, v, type->t, c);
1936 s->type.ref = type->ref;
1937 s->r = r;
1938 /* don't record fields or anonymous symbols */
1939 /* XXX: simplify */
1940 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1941 /* record symbol in token array */
1942 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1943 if (v & SYM_STRUCT)
1944 ps = &ts->sym_struct;
1945 else
1946 ps = &ts->sym_identifier;
1947 s->prev_tok = *ps;
1948 *ps = s;
1950 return s;
1953 /* push a global identifier */
1954 static Sym *global_identifier_push(int v, int t, int c)
1956 Sym *s, **ps;
1957 s = sym_push2(&global_stack, v, t, c);
1958 /* don't record anonymous symbol */
1959 if (v < SYM_FIRST_ANOM) {
1960 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1961 /* modify the top most local identifier, so that
1962 sym_identifier will point to 's' when popped */
1963 while (*ps != NULL)
1964 ps = &(*ps)->prev_tok;
1965 s->prev_tok = NULL;
1966 *ps = s;
1968 return s;
1971 /* pop symbols until top reaches 'b' */
1972 static void sym_pop(Sym **ptop, Sym *b)
1974 Sym *s, *ss, **ps;
1975 TokenSym *ts;
1976 int v;
1978 s = *ptop;
1979 while(s != b) {
1980 ss = s->prev;
1981 v = s->v;
1982 /* remove symbol in token array */
1983 /* XXX: simplify */
1984 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1985 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1986 if (v & SYM_STRUCT)
1987 ps = &ts->sym_struct;
1988 else
1989 ps = &ts->sym_identifier;
1990 *ps = s->prev_tok;
1992 sym_free(s);
1993 s = ss;
1995 *ptop = b;
1998 /* I/O layer */
2000 BufferedFile *tcc_open(TCCState *s1, const char *filename)
2002 int fd;
2003 BufferedFile *bf;
2005 if (strcmp(filename, "-") == 0)
2006 fd = 0, filename = "stdin";
2007 else
2008 fd = open(filename, O_RDONLY | O_BINARY);
2009 if ((verbose == 2 && fd >= 0) || verbose == 3)
2010 printf("%s %*s%s\n", fd < 0 ? "nf":"->",
2011 (s1->include_stack_ptr - s1->include_stack), "", filename);
2012 if (fd < 0)
2013 return NULL;
2014 bf = tcc_malloc(sizeof(BufferedFile));
2015 bf->fd = fd;
2016 bf->buf_ptr = bf->buffer;
2017 bf->buf_end = bf->buffer;
2018 bf->buffer[0] = CH_EOB; /* put eob symbol */
2019 pstrcpy(bf->filename, sizeof(bf->filename), filename);
2020 #ifdef _WIN32
2021 normalize_slashes(bf->filename);
2022 #endif
2023 bf->line_num = 1;
2024 bf->ifndef_macro = 0;
2025 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
2026 // printf("opening '%s'\n", filename);
2027 return bf;
2030 void tcc_close(BufferedFile *bf)
2032 total_lines += bf->line_num;
2033 close(bf->fd);
2034 tcc_free(bf);
2037 /* fill input buffer and peek next char */
2038 static int tcc_peekc_slow(BufferedFile *bf)
2040 int len;
2041 /* only tries to read if really end of buffer */
2042 if (bf->buf_ptr >= bf->buf_end) {
2043 if (bf->fd != -1) {
2044 #if defined(PARSE_DEBUG)
2045 len = 8;
2046 #else
2047 len = IO_BUF_SIZE;
2048 #endif
2049 len = read(bf->fd, bf->buffer, len);
2050 if (len < 0)
2051 len = 0;
2052 } else {
2053 len = 0;
2055 total_bytes += len;
2056 bf->buf_ptr = bf->buffer;
2057 bf->buf_end = bf->buffer + len;
2058 *bf->buf_end = CH_EOB;
2060 if (bf->buf_ptr < bf->buf_end) {
2061 return bf->buf_ptr[0];
2062 } else {
2063 bf->buf_ptr = bf->buf_end;
2064 return CH_EOF;
2068 /* return the current character, handling end of block if necessary
2069 (but not stray) */
2070 static int handle_eob(void)
2072 return tcc_peekc_slow(file);
2075 /* read next char from current input file and handle end of input buffer */
2076 static inline void inp(void)
2078 ch = *(++(file->buf_ptr));
2079 /* end of buffer/file handling */
2080 if (ch == CH_EOB)
2081 ch = handle_eob();
2084 /* handle '\[\r]\n' */
2085 static int handle_stray_noerror(void)
2087 while (ch == '\\') {
2088 inp();
2089 if (ch == '\n') {
2090 file->line_num++;
2091 inp();
2092 } else if (ch == '\r') {
2093 inp();
2094 if (ch != '\n')
2095 goto fail;
2096 file->line_num++;
2097 inp();
2098 } else {
2099 fail:
2100 return 1;
2103 return 0;
2106 static void handle_stray(void)
2108 if (handle_stray_noerror())
2109 error("stray '\\' in program");
2112 /* skip the stray and handle the \\n case. Output an error if
2113 incorrect char after the stray */
2114 static int handle_stray1(uint8_t *p)
2116 int c;
2118 if (p >= file->buf_end) {
2119 file->buf_ptr = p;
2120 c = handle_eob();
2121 p = file->buf_ptr;
2122 if (c == '\\')
2123 goto parse_stray;
2124 } else {
2125 parse_stray:
2126 file->buf_ptr = p;
2127 ch = *p;
2128 handle_stray();
2129 p = file->buf_ptr;
2130 c = *p;
2132 return c;
2135 /* handle just the EOB case, but not stray */
2136 #define PEEKC_EOB(c, p)\
2138 p++;\
2139 c = *p;\
2140 if (c == '\\') {\
2141 file->buf_ptr = p;\
2142 c = handle_eob();\
2143 p = file->buf_ptr;\
2147 /* handle the complicated stray case */
2148 #define PEEKC(c, p)\
2150 p++;\
2151 c = *p;\
2152 if (c == '\\') {\
2153 c = handle_stray1(p);\
2154 p = file->buf_ptr;\
2158 /* input with '\[\r]\n' handling. Note that this function cannot
2159 handle other characters after '\', so you cannot call it inside
2160 strings or comments */
2161 static void minp(void)
2163 inp();
2164 if (ch == '\\')
2165 handle_stray();
2169 /* single line C++ comments */
2170 static uint8_t *parse_line_comment(uint8_t *p)
2172 int c;
2174 p++;
2175 for(;;) {
2176 c = *p;
2177 redo:
2178 if (c == '\n' || c == CH_EOF) {
2179 break;
2180 } else if (c == '\\') {
2181 file->buf_ptr = p;
2182 c = handle_eob();
2183 p = file->buf_ptr;
2184 if (c == '\\') {
2185 PEEKC_EOB(c, p);
2186 if (c == '\n') {
2187 file->line_num++;
2188 PEEKC_EOB(c, p);
2189 } else if (c == '\r') {
2190 PEEKC_EOB(c, p);
2191 if (c == '\n') {
2192 file->line_num++;
2193 PEEKC_EOB(c, p);
2196 } else {
2197 goto redo;
2199 } else {
2200 p++;
2203 return p;
2206 /* C comments */
2207 static uint8_t *parse_comment(uint8_t *p)
2209 int c;
2211 p++;
2212 for(;;) {
2213 /* fast skip loop */
2214 for(;;) {
2215 c = *p;
2216 if (c == '\n' || c == '*' || c == '\\')
2217 break;
2218 p++;
2219 c = *p;
2220 if (c == '\n' || c == '*' || c == '\\')
2221 break;
2222 p++;
2224 /* now we can handle all the cases */
2225 if (c == '\n') {
2226 file->line_num++;
2227 p++;
2228 } else if (c == '*') {
2229 p++;
2230 for(;;) {
2231 c = *p;
2232 if (c == '*') {
2233 p++;
2234 } else if (c == '/') {
2235 goto end_of_comment;
2236 } else if (c == '\\') {
2237 file->buf_ptr = p;
2238 c = handle_eob();
2239 p = file->buf_ptr;
2240 if (c == '\\') {
2241 /* skip '\[\r]\n', otherwise just skip the stray */
2242 while (c == '\\') {
2243 PEEKC_EOB(c, p);
2244 if (c == '\n') {
2245 file->line_num++;
2246 PEEKC_EOB(c, p);
2247 } else if (c == '\r') {
2248 PEEKC_EOB(c, p);
2249 if (c == '\n') {
2250 file->line_num++;
2251 PEEKC_EOB(c, p);
2253 } else {
2254 goto after_star;
2258 } else {
2259 break;
2262 after_star: ;
2263 } else {
2264 /* stray, eob or eof */
2265 file->buf_ptr = p;
2266 c = handle_eob();
2267 p = file->buf_ptr;
2268 if (c == CH_EOF) {
2269 error("unexpected end of file in comment");
2270 } else if (c == '\\') {
2271 p++;
2275 end_of_comment:
2276 p++;
2277 return p;
2280 #define cinp minp
2282 /* space exlcuding newline */
2283 static inline int is_space(int ch)
2285 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2288 static inline void skip_spaces(void)
2290 while (is_space(ch))
2291 cinp();
2294 static inline int check_space(int t, int *spc)
2296 if (is_space(t)) {
2297 if (*spc)
2298 return 1;
2299 *spc = 1;
2300 } else
2301 *spc = 0;
2302 return 0;
2305 /* parse a string without interpreting escapes */
2306 static uint8_t *parse_pp_string(uint8_t *p,
2307 int sep, CString *str)
2309 int c;
2310 p++;
2311 for(;;) {
2312 c = *p;
2313 if (c == sep) {
2314 break;
2315 } else if (c == '\\') {
2316 file->buf_ptr = p;
2317 c = handle_eob();
2318 p = file->buf_ptr;
2319 if (c == CH_EOF) {
2320 unterminated_string:
2321 /* XXX: indicate line number of start of string */
2322 error("missing terminating %c character", sep);
2323 } else if (c == '\\') {
2324 /* escape : just skip \[\r]\n */
2325 PEEKC_EOB(c, p);
2326 if (c == '\n') {
2327 file->line_num++;
2328 p++;
2329 } else if (c == '\r') {
2330 PEEKC_EOB(c, p);
2331 if (c != '\n')
2332 expect("'\n' after '\r'");
2333 file->line_num++;
2334 p++;
2335 } else if (c == CH_EOF) {
2336 goto unterminated_string;
2337 } else {
2338 if (str) {
2339 cstr_ccat(str, '\\');
2340 cstr_ccat(str, c);
2342 p++;
2345 } else if (c == '\n') {
2346 file->line_num++;
2347 goto add_char;
2348 } else if (c == '\r') {
2349 PEEKC_EOB(c, p);
2350 if (c != '\n') {
2351 if (str)
2352 cstr_ccat(str, '\r');
2353 } else {
2354 file->line_num++;
2355 goto add_char;
2357 } else {
2358 add_char:
2359 if (str)
2360 cstr_ccat(str, c);
2361 p++;
2364 p++;
2365 return p;
2368 /* skip block of text until #else, #elif or #endif. skip also pairs of
2369 #if/#endif */
2370 void preprocess_skip(void)
2372 int a, start_of_line, c, in_warn_or_error;
2373 uint8_t *p;
2375 p = file->buf_ptr;
2376 a = 0;
2377 redo_start:
2378 start_of_line = 1;
2379 in_warn_or_error = 0;
2380 for(;;) {
2381 redo_no_start:
2382 c = *p;
2383 switch(c) {
2384 case ' ':
2385 case '\t':
2386 case '\f':
2387 case '\v':
2388 case '\r':
2389 p++;
2390 goto redo_no_start;
2391 case '\n':
2392 file->line_num++;
2393 p++;
2394 goto redo_start;
2395 case '\\':
2396 file->buf_ptr = p;
2397 c = handle_eob();
2398 if (c == CH_EOF) {
2399 expect("#endif");
2400 } else if (c == '\\') {
2401 ch = file->buf_ptr[0];
2402 handle_stray_noerror();
2404 p = file->buf_ptr;
2405 goto redo_no_start;
2406 /* skip strings */
2407 case '\"':
2408 case '\'':
2409 if (in_warn_or_error)
2410 goto _default;
2411 p = parse_pp_string(p, c, NULL);
2412 break;
2413 /* skip comments */
2414 case '/':
2415 if (in_warn_or_error)
2416 goto _default;
2417 file->buf_ptr = p;
2418 ch = *p;
2419 minp();
2420 p = file->buf_ptr;
2421 if (ch == '*') {
2422 p = parse_comment(p);
2423 } else if (ch == '/') {
2424 p = parse_line_comment(p);
2426 break;
2427 case '#':
2428 p++;
2429 if (start_of_line) {
2430 file->buf_ptr = p;
2431 next_nomacro();
2432 p = file->buf_ptr;
2433 if (a == 0 &&
2434 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2435 goto the_end;
2436 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2437 a++;
2438 else if (tok == TOK_ENDIF)
2439 a--;
2440 else if( tok == TOK_ERROR || tok == TOK_WARNING)
2441 in_warn_or_error = 1;
2443 break;
2444 _default:
2445 default:
2446 p++;
2447 break;
2449 start_of_line = 0;
2451 the_end: ;
2452 file->buf_ptr = p;
2455 /* ParseState handling */
2457 /* XXX: currently, no include file info is stored. Thus, we cannot display
2458 accurate messages if the function or data definition spans multiple
2459 files */
2461 /* save current parse state in 's' */
2462 void save_parse_state(ParseState *s)
2464 s->line_num = file->line_num;
2465 s->macro_ptr = macro_ptr;
2466 s->tok = tok;
2467 s->tokc = tokc;
2470 /* restore parse state from 's' */
2471 void restore_parse_state(ParseState *s)
2473 file->line_num = s->line_num;
2474 macro_ptr = s->macro_ptr;
2475 tok = s->tok;
2476 tokc = s->tokc;
2479 /* return the number of additional 'ints' necessary to store the
2480 token */
2481 static inline int tok_ext_size(int t)
2483 switch(t) {
2484 /* 4 bytes */
2485 case TOK_CINT:
2486 case TOK_CUINT:
2487 case TOK_CCHAR:
2488 case TOK_LCHAR:
2489 case TOK_CFLOAT:
2490 case TOK_LINENUM:
2491 return 1;
2492 case TOK_STR:
2493 case TOK_LSTR:
2494 case TOK_PPNUM:
2495 error("unsupported token");
2496 return 1;
2497 case TOK_CDOUBLE:
2498 case TOK_CLLONG:
2499 case TOK_CULLONG:
2500 return 2;
2501 case TOK_CLDOUBLE:
2502 return LDOUBLE_SIZE / 4;
2503 default:
2504 return 0;
2508 /* token string handling */
2510 static inline void tok_str_new(TokenString *s)
2512 s->str = NULL;
2513 s->len = 0;
2514 s->allocated_len = 0;
2515 s->last_line_num = -1;
2518 static void tok_str_free(int *str)
2520 tcc_free(str);
2523 static int *tok_str_realloc(TokenString *s)
2525 int *str, len;
2527 if (s->allocated_len == 0) {
2528 len = 8;
2529 } else {
2530 len = s->allocated_len * 2;
2532 str = tcc_realloc(s->str, len * sizeof(int));
2533 if (!str)
2534 error("memory full");
2535 s->allocated_len = len;
2536 s->str = str;
2537 return str;
2540 static void tok_str_add(TokenString *s, int t)
2542 int len, *str;
2544 len = s->len;
2545 str = s->str;
2546 if (len >= s->allocated_len)
2547 str = tok_str_realloc(s);
2548 str[len++] = t;
2549 s->len = len;
2552 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2554 int len, *str;
2556 len = s->len;
2557 str = s->str;
2559 /* allocate space for worst case */
2560 if (len + TOK_MAX_SIZE > s->allocated_len)
2561 str = tok_str_realloc(s);
2562 str[len++] = t;
2563 switch(t) {
2564 case TOK_CINT:
2565 case TOK_CUINT:
2566 case TOK_CCHAR:
2567 case TOK_LCHAR:
2568 case TOK_CFLOAT:
2569 case TOK_LINENUM:
2570 str[len++] = cv->tab[0];
2571 break;
2572 case TOK_PPNUM:
2573 case TOK_STR:
2574 case TOK_LSTR:
2576 int nb_words;
2577 CString *cstr;
2579 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2580 while ((len + nb_words) > s->allocated_len)
2581 str = tok_str_realloc(s);
2582 cstr = (CString *)(str + len);
2583 cstr->data = NULL;
2584 cstr->size = cv->cstr->size;
2585 cstr->data_allocated = NULL;
2586 cstr->size_allocated = cstr->size;
2587 memcpy((char *)cstr + sizeof(CString),
2588 cv->cstr->data, cstr->size);
2589 len += nb_words;
2591 break;
2592 case TOK_CDOUBLE:
2593 case TOK_CLLONG:
2594 case TOK_CULLONG:
2595 #if LDOUBLE_SIZE == 8
2596 case TOK_CLDOUBLE:
2597 #endif
2598 str[len++] = cv->tab[0];
2599 str[len++] = cv->tab[1];
2600 break;
2601 #if LDOUBLE_SIZE == 12
2602 case TOK_CLDOUBLE:
2603 str[len++] = cv->tab[0];
2604 str[len++] = cv->tab[1];
2605 str[len++] = cv->tab[2];
2606 #elif LDOUBLE_SIZE == 16
2607 case TOK_CLDOUBLE:
2608 str[len++] = cv->tab[0];
2609 str[len++] = cv->tab[1];
2610 str[len++] = cv->tab[2];
2611 str[len++] = cv->tab[3];
2612 #elif LDOUBLE_SIZE != 8
2613 #error add long double size support
2614 #endif
2615 break;
2616 default:
2617 break;
2619 s->len = len;
2622 /* add the current parse token in token string 's' */
2623 static void tok_str_add_tok(TokenString *s)
2625 CValue cval;
2627 /* save line number info */
2628 if (file->line_num != s->last_line_num) {
2629 s->last_line_num = file->line_num;
2630 cval.i = s->last_line_num;
2631 tok_str_add2(s, TOK_LINENUM, &cval);
2633 tok_str_add2(s, tok, &tokc);
2636 #if LDOUBLE_SIZE == 16
2637 #define LDOUBLE_GET(p, cv) \
2638 cv.tab[0] = p[0]; \
2639 cv.tab[1] = p[1]; \
2640 cv.tab[2] = p[2]; \
2641 cv.tab[3] = p[3];
2642 #elif LDOUBLE_SIZE == 12
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 #elif LDOUBLE_SIZE == 8
2648 #define LDOUBLE_GET(p, cv) \
2649 cv.tab[0] = p[0]; \
2650 cv.tab[1] = p[1];
2651 #else
2652 #error add long double size support
2653 #endif
2656 /* get a token from an integer array and increment pointer
2657 accordingly. we code it as a macro to avoid pointer aliasing. */
2658 #define TOK_GET(t, p, cv) \
2660 t = *p++; \
2661 switch(t) { \
2662 case TOK_CINT: \
2663 case TOK_CUINT: \
2664 case TOK_CCHAR: \
2665 case TOK_LCHAR: \
2666 case TOK_CFLOAT: \
2667 case TOK_LINENUM: \
2668 cv.tab[0] = *p++; \
2669 break; \
2670 case TOK_STR: \
2671 case TOK_LSTR: \
2672 case TOK_PPNUM: \
2673 cv.cstr = (CString *)p; \
2674 cv.cstr->data = (char *)p + sizeof(CString);\
2675 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2676 break; \
2677 case TOK_CDOUBLE: \
2678 case TOK_CLLONG: \
2679 case TOK_CULLONG: \
2680 cv.tab[0] = p[0]; \
2681 cv.tab[1] = p[1]; \
2682 p += 2; \
2683 break; \
2684 case TOK_CLDOUBLE: \
2685 LDOUBLE_GET(p, cv); \
2686 p += LDOUBLE_SIZE / 4; \
2687 break; \
2688 default: \
2689 break; \
2693 /* defines handling */
2694 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2696 Sym *s;
2698 s = sym_push2(&define_stack, v, macro_type, (long)str);
2699 s->next = first_arg;
2700 table_ident[v - TOK_IDENT]->sym_define = s;
2703 /* undefined a define symbol. Its name is just set to zero */
2704 static void define_undef(Sym *s)
2706 int v;
2707 v = s->v;
2708 if (v >= TOK_IDENT && v < tok_ident)
2709 table_ident[v - TOK_IDENT]->sym_define = NULL;
2710 s->v = 0;
2713 static inline Sym *define_find(int v)
2715 v -= TOK_IDENT;
2716 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2717 return NULL;
2718 return table_ident[v]->sym_define;
2721 /* free define stack until top reaches 'b' */
2722 static void free_defines(Sym *b)
2724 Sym *top, *top1;
2725 int v;
2727 top = define_stack;
2728 while (top != b) {
2729 top1 = top->prev;
2730 /* do not free args or predefined defines */
2731 if (top->c)
2732 tok_str_free((int *)top->c);
2733 v = top->v;
2734 if (v >= TOK_IDENT && v < tok_ident)
2735 table_ident[v - TOK_IDENT]->sym_define = NULL;
2736 sym_free(top);
2737 top = top1;
2739 define_stack = b;
2742 /* label lookup */
2743 static Sym *label_find(int v)
2745 v -= TOK_IDENT;
2746 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2747 return NULL;
2748 return table_ident[v]->sym_label;
2751 static Sym *label_push(Sym **ptop, int v, int flags)
2753 Sym *s, **ps;
2754 s = sym_push2(ptop, v, 0, 0);
2755 s->r = flags;
2756 ps = &table_ident[v - TOK_IDENT]->sym_label;
2757 if (ptop == &global_label_stack) {
2758 /* modify the top most local identifier, so that
2759 sym_identifier will point to 's' when popped */
2760 while (*ps != NULL)
2761 ps = &(*ps)->prev_tok;
2763 s->prev_tok = *ps;
2764 *ps = s;
2765 return s;
2768 /* pop labels until element last is reached. Look if any labels are
2769 undefined. Define symbols if '&&label' was used. */
2770 static void label_pop(Sym **ptop, Sym *slast)
2772 Sym *s, *s1;
2773 for(s = *ptop; s != slast; s = s1) {
2774 s1 = s->prev;
2775 if (s->r == LABEL_DECLARED) {
2776 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2777 } else if (s->r == LABEL_FORWARD) {
2778 error("label '%s' used but not defined",
2779 get_tok_str(s->v, NULL));
2780 } else {
2781 if (s->c) {
2782 /* define corresponding symbol. A size of
2783 1 is put. */
2784 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2787 /* remove label */
2788 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2789 sym_free(s);
2791 *ptop = slast;
2794 /* eval an expression for #if/#elif */
2795 static int expr_preprocess(void)
2797 int c, t;
2798 TokenString str;
2800 tok_str_new(&str);
2801 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2802 next(); /* do macro subst */
2803 if (tok == TOK_DEFINED) {
2804 next_nomacro();
2805 t = tok;
2806 if (t == '(')
2807 next_nomacro();
2808 c = define_find(tok) != 0;
2809 if (t == '(')
2810 next_nomacro();
2811 tok = TOK_CINT;
2812 tokc.i = c;
2813 } else if (tok >= TOK_IDENT) {
2814 /* if undefined macro */
2815 tok = TOK_CINT;
2816 tokc.i = 0;
2818 tok_str_add_tok(&str);
2820 tok_str_add(&str, -1); /* simulate end of file */
2821 tok_str_add(&str, 0);
2822 /* now evaluate C constant expression */
2823 macro_ptr = str.str;
2824 next();
2825 c = expr_const();
2826 macro_ptr = NULL;
2827 tok_str_free(str.str);
2828 return c != 0;
2831 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2832 static void tok_print(int *str)
2834 int t;
2835 CValue cval;
2837 printf("<");
2838 while (1) {
2839 TOK_GET(t, str, cval);
2840 if (!t)
2841 break;
2842 printf("%s", get_tok_str(t, &cval));
2844 printf(">\n");
2846 #endif
2848 /* parse after #define */
2849 static void parse_define(void)
2851 Sym *s, *first, **ps;
2852 int v, t, varg, is_vaargs, spc;
2853 TokenString str;
2855 v = tok;
2856 if (v < TOK_IDENT)
2857 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2858 /* XXX: should check if same macro (ANSI) */
2859 first = NULL;
2860 t = MACRO_OBJ;
2861 /* '(' must be just after macro definition for MACRO_FUNC */
2862 next_nomacro_spc();
2863 if (tok == '(') {
2864 next_nomacro();
2865 ps = &first;
2866 while (tok != ')') {
2867 varg = tok;
2868 next_nomacro();
2869 is_vaargs = 0;
2870 if (varg == TOK_DOTS) {
2871 varg = TOK___VA_ARGS__;
2872 is_vaargs = 1;
2873 } else if (tok == TOK_DOTS && gnu_ext) {
2874 is_vaargs = 1;
2875 next_nomacro();
2877 if (varg < TOK_IDENT)
2878 error("badly punctuated parameter list");
2879 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2880 *ps = s;
2881 ps = &s->next;
2882 if (tok != ',')
2883 break;
2884 next_nomacro();
2886 if (tok == ')')
2887 next_nomacro_spc();
2888 t = MACRO_FUNC;
2890 tok_str_new(&str);
2891 spc = 2;
2892 /* EOF testing necessary for '-D' handling */
2893 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2894 /* remove spaces around ## and after '#' */
2895 if (TOK_TWOSHARPS == tok) {
2896 if (1 == spc)
2897 --str.len;
2898 spc = 2;
2899 } else if ('#' == tok) {
2900 spc = 2;
2901 } else if (check_space(tok, &spc)) {
2902 goto skip;
2904 tok_str_add2(&str, tok, &tokc);
2905 skip:
2906 next_nomacro_spc();
2908 if (spc == 1)
2909 --str.len; /* remove trailing space */
2910 tok_str_add(&str, 0);
2911 #ifdef PP_DEBUG
2912 printf("define %s %d: ", get_tok_str(v, NULL), t);
2913 tok_print(str.str);
2914 #endif
2915 define_push(v, t, str.str, first);
2918 static inline int hash_cached_include(int type, const char *filename)
2920 const unsigned char *s;
2921 unsigned int h;
2923 h = TOK_HASH_INIT;
2924 h = TOK_HASH_FUNC(h, type);
2925 s = filename;
2926 while (*s) {
2927 h = TOK_HASH_FUNC(h, *s);
2928 s++;
2930 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2931 return h;
2934 /* XXX: use a token or a hash table to accelerate matching ? */
2935 static CachedInclude *search_cached_include(TCCState *s1,
2936 int type, const char *filename)
2938 CachedInclude *e;
2939 int i, h;
2940 h = hash_cached_include(type, filename);
2941 i = s1->cached_includes_hash[h];
2942 for(;;) {
2943 if (i == 0)
2944 break;
2945 e = s1->cached_includes[i - 1];
2946 if (e->type == type && !PATHCMP(e->filename, filename))
2947 return e;
2948 i = e->hash_next;
2950 return NULL;
2953 static inline void add_cached_include(TCCState *s1, int type,
2954 const char *filename, int ifndef_macro)
2956 CachedInclude *e;
2957 int h;
2959 if (search_cached_include(s1, type, filename))
2960 return;
2961 #ifdef INC_DEBUG
2962 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2963 #endif
2964 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2965 if (!e)
2966 return;
2967 e->type = type;
2968 strcpy(e->filename, filename);
2969 e->ifndef_macro = ifndef_macro;
2970 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2971 /* add in hash table */
2972 h = hash_cached_include(type, filename);
2973 e->hash_next = s1->cached_includes_hash[h];
2974 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2977 static void pragma_parse(TCCState *s1)
2979 int val;
2981 next();
2982 if (tok == TOK_pack) {
2984 This may be:
2985 #pragma pack(1) // set
2986 #pragma pack() // reset to default
2987 #pragma pack(push,1) // push & set
2988 #pragma pack(pop) // restore previous
2990 next();
2991 skip('(');
2992 if (tok == TOK_ASM_pop) {
2993 next();
2994 if (s1->pack_stack_ptr <= s1->pack_stack) {
2995 stk_error:
2996 error("out of pack stack");
2998 s1->pack_stack_ptr--;
2999 } else {
3000 val = 0;
3001 if (tok != ')') {
3002 if (tok == TOK_ASM_push) {
3003 next();
3004 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
3005 goto stk_error;
3006 s1->pack_stack_ptr++;
3007 skip(',');
3009 if (tok != TOK_CINT) {
3010 pack_error:
3011 error("invalid pack pragma");
3013 val = tokc.i;
3014 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
3015 goto pack_error;
3016 next();
3018 *s1->pack_stack_ptr = val;
3019 skip(')');
3024 /* is_bof is true if first non space token at beginning of file */
3025 static void preprocess(int is_bof)
3027 TCCState *s1 = tcc_state;
3028 int size, i, c, n, saved_parse_flags;
3029 char buf[1024], *q;
3030 char buf1[1024];
3031 BufferedFile *f;
3032 Sym *s;
3033 CachedInclude *e;
3035 saved_parse_flags = parse_flags;
3036 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
3037 PARSE_FLAG_LINEFEED;
3038 next_nomacro();
3039 redo:
3040 switch(tok) {
3041 case TOK_DEFINE:
3042 next_nomacro();
3043 parse_define();
3044 break;
3045 case TOK_UNDEF:
3046 next_nomacro();
3047 s = define_find(tok);
3048 /* undefine symbol by putting an invalid name */
3049 if (s)
3050 define_undef(s);
3051 break;
3052 case TOK_INCLUDE:
3053 case TOK_INCLUDE_NEXT:
3054 ch = file->buf_ptr[0];
3055 /* XXX: incorrect if comments : use next_nomacro with a special mode */
3056 skip_spaces();
3057 if (ch == '<') {
3058 c = '>';
3059 goto read_name;
3060 } else if (ch == '\"') {
3061 c = ch;
3062 read_name:
3063 inp();
3064 q = buf;
3065 while (ch != c && ch != '\n' && ch != CH_EOF) {
3066 if ((q - buf) < sizeof(buf) - 1)
3067 *q++ = ch;
3068 if (ch == '\\') {
3069 if (handle_stray_noerror() == 0)
3070 --q;
3071 } else
3072 inp();
3074 *q = '\0';
3075 minp();
3076 #if 0
3077 /* eat all spaces and comments after include */
3078 /* XXX: slightly incorrect */
3079 while (ch1 != '\n' && ch1 != CH_EOF)
3080 inp();
3081 #endif
3082 } else {
3083 /* computed #include : either we have only strings or
3084 we have anything enclosed in '<>' */
3085 next();
3086 buf[0] = '\0';
3087 if (tok == TOK_STR) {
3088 while (tok != TOK_LINEFEED) {
3089 if (tok != TOK_STR) {
3090 include_syntax:
3091 error("'#include' expects \"FILENAME\" or <FILENAME>");
3093 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
3094 next();
3096 c = '\"';
3097 } else {
3098 int len;
3099 while (tok != TOK_LINEFEED) {
3100 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
3101 next();
3103 len = strlen(buf);
3104 /* check syntax and remove '<>' */
3105 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
3106 goto include_syntax;
3107 memmove(buf, buf + 1, len - 2);
3108 buf[len - 2] = '\0';
3109 c = '>';
3113 e = search_cached_include(s1, c, buf);
3114 if (e && define_find(e->ifndef_macro)) {
3115 /* no need to parse the include because the 'ifndef macro'
3116 is defined */
3117 #ifdef INC_DEBUG
3118 printf("%s: skipping %s\n", file->filename, buf);
3119 #endif
3120 } else {
3121 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
3122 error("#include recursion too deep");
3123 /* push current file in stack */
3124 /* XXX: fix current line init */
3125 *s1->include_stack_ptr++ = file;
3127 /* check absolute include path */
3128 if (IS_ABSPATH(buf)) {
3129 f = tcc_open(s1, buf);
3130 if (f)
3131 goto found;
3133 if (c == '\"') {
3134 /* first search in current dir if "header.h" */
3135 size = tcc_basename(file->filename) - file->filename;
3136 if (size > sizeof(buf1) - 1)
3137 size = sizeof(buf1) - 1;
3138 memcpy(buf1, file->filename, size);
3139 buf1[size] = '\0';
3140 pstrcat(buf1, sizeof(buf1), buf);
3141 f = tcc_open(s1, buf1);
3142 if (f) {
3143 if (tok == TOK_INCLUDE_NEXT)
3144 tok = TOK_INCLUDE;
3145 else
3146 goto found;
3149 /* now search in all the include paths */
3150 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
3151 for(i = 0; i < n; i++) {
3152 const char *path;
3153 if (i < s1->nb_include_paths)
3154 path = s1->include_paths[i];
3155 else
3156 path = s1->sysinclude_paths[i - s1->nb_include_paths];
3157 pstrcpy(buf1, sizeof(buf1), path);
3158 pstrcat(buf1, sizeof(buf1), "/");
3159 pstrcat(buf1, sizeof(buf1), buf);
3160 f = tcc_open(s1, buf1);
3161 if (f) {
3162 if (tok == TOK_INCLUDE_NEXT)
3163 tok = TOK_INCLUDE;
3164 else
3165 goto found;
3168 --s1->include_stack_ptr;
3169 error("include file '%s' not found", buf);
3170 break;
3171 found:
3172 #ifdef INC_DEBUG
3173 printf("%s: including %s\n", file->filename, buf1);
3174 #endif
3175 f->inc_type = c;
3176 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
3177 file = f;
3178 /* add include file debug info */
3179 if (do_debug) {
3180 put_stabs(file->filename, N_BINCL, 0, 0, 0);
3182 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
3183 ch = file->buf_ptr[0];
3184 goto the_end;
3186 break;
3187 case TOK_IFNDEF:
3188 c = 1;
3189 goto do_ifdef;
3190 case TOK_IF:
3191 c = expr_preprocess();
3192 goto do_if;
3193 case TOK_IFDEF:
3194 c = 0;
3195 do_ifdef:
3196 next_nomacro();
3197 if (tok < TOK_IDENT)
3198 error("invalid argument for '#if%sdef'", c ? "n" : "");
3199 if (is_bof) {
3200 if (c) {
3201 #ifdef INC_DEBUG
3202 printf("#ifndef %s\n", get_tok_str(tok, NULL));
3203 #endif
3204 file->ifndef_macro = tok;
3207 c = (define_find(tok) != 0) ^ c;
3208 do_if:
3209 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
3210 error("memory full");
3211 *s1->ifdef_stack_ptr++ = c;
3212 goto test_skip;
3213 case TOK_ELSE:
3214 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3215 error("#else without matching #if");
3216 if (s1->ifdef_stack_ptr[-1] & 2)
3217 error("#else after #else");
3218 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3219 goto test_skip;
3220 case TOK_ELIF:
3221 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3222 error("#elif without matching #if");
3223 c = s1->ifdef_stack_ptr[-1];
3224 if (c > 1)
3225 error("#elif after #else");
3226 /* last #if/#elif expression was true: we skip */
3227 if (c == 1)
3228 goto skip;
3229 c = expr_preprocess();
3230 s1->ifdef_stack_ptr[-1] = c;
3231 test_skip:
3232 if (!(c & 1)) {
3233 skip:
3234 preprocess_skip();
3235 is_bof = 0;
3236 goto redo;
3238 break;
3239 case TOK_ENDIF:
3240 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3241 error("#endif without matching #if");
3242 s1->ifdef_stack_ptr--;
3243 /* '#ifndef macro' was at the start of file. Now we check if
3244 an '#endif' is exactly at the end of file */
3245 if (file->ifndef_macro &&
3246 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3247 file->ifndef_macro_saved = file->ifndef_macro;
3248 /* need to set to zero to avoid false matches if another
3249 #ifndef at middle of file */
3250 file->ifndef_macro = 0;
3251 while (tok != TOK_LINEFEED)
3252 next_nomacro();
3253 tok_flags |= TOK_FLAG_ENDIF;
3254 goto the_end;
3256 break;
3257 case TOK_LINE:
3258 next();
3259 if (tok != TOK_CINT)
3260 error("#line");
3261 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3262 next();
3263 if (tok != TOK_LINEFEED) {
3264 if (tok != TOK_STR)
3265 error("#line");
3266 pstrcpy(file->filename, sizeof(file->filename),
3267 (char *)tokc.cstr->data);
3269 break;
3270 case TOK_ERROR:
3271 case TOK_WARNING:
3272 c = tok;
3273 ch = file->buf_ptr[0];
3274 skip_spaces();
3275 q = buf;
3276 while (ch != '\n' && ch != CH_EOF) {
3277 if ((q - buf) < sizeof(buf) - 1)
3278 *q++ = ch;
3279 if (ch == '\\') {
3280 if (handle_stray_noerror() == 0)
3281 --q;
3282 } else
3283 inp();
3285 *q = '\0';
3286 if (c == TOK_ERROR)
3287 error("#error %s", buf);
3288 else
3289 warning("#warning %s", buf);
3290 break;
3291 case TOK_PRAGMA:
3292 pragma_parse(s1);
3293 break;
3294 default:
3295 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3296 /* '!' is ignored to allow C scripts. numbers are ignored
3297 to emulate cpp behaviour */
3298 } else {
3299 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3300 warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
3302 break;
3304 /* ignore other preprocess commands or #! for C scripts */
3305 while (tok != TOK_LINEFEED)
3306 next_nomacro();
3307 the_end:
3308 parse_flags = saved_parse_flags;
3311 /* evaluate escape codes in a string. */
3312 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3314 int c, n;
3315 const uint8_t *p;
3317 p = buf;
3318 for(;;) {
3319 c = *p;
3320 if (c == '\0')
3321 break;
3322 if (c == '\\') {
3323 p++;
3324 /* escape */
3325 c = *p;
3326 switch(c) {
3327 case '0': case '1': case '2': case '3':
3328 case '4': case '5': case '6': case '7':
3329 /* at most three octal digits */
3330 n = c - '0';
3331 p++;
3332 c = *p;
3333 if (isoct(c)) {
3334 n = n * 8 + c - '0';
3335 p++;
3336 c = *p;
3337 if (isoct(c)) {
3338 n = n * 8 + c - '0';
3339 p++;
3342 c = n;
3343 goto add_char_nonext;
3344 case 'x':
3345 case 'u':
3346 case 'U':
3347 p++;
3348 n = 0;
3349 for(;;) {
3350 c = *p;
3351 if (c >= 'a' && c <= 'f')
3352 c = c - 'a' + 10;
3353 else if (c >= 'A' && c <= 'F')
3354 c = c - 'A' + 10;
3355 else if (isnum(c))
3356 c = c - '0';
3357 else
3358 break;
3359 n = n * 16 + c;
3360 p++;
3362 c = n;
3363 goto add_char_nonext;
3364 case 'a':
3365 c = '\a';
3366 break;
3367 case 'b':
3368 c = '\b';
3369 break;
3370 case 'f':
3371 c = '\f';
3372 break;
3373 case 'n':
3374 c = '\n';
3375 break;
3376 case 'r':
3377 c = '\r';
3378 break;
3379 case 't':
3380 c = '\t';
3381 break;
3382 case 'v':
3383 c = '\v';
3384 break;
3385 case 'e':
3386 if (!gnu_ext)
3387 goto invalid_escape;
3388 c = 27;
3389 break;
3390 case '\'':
3391 case '\"':
3392 case '\\':
3393 case '?':
3394 break;
3395 default:
3396 invalid_escape:
3397 if (c >= '!' && c <= '~')
3398 warning("unknown escape sequence: \'\\%c\'", c);
3399 else
3400 warning("unknown escape sequence: \'\\x%x\'", c);
3401 break;
3404 p++;
3405 add_char_nonext:
3406 if (!is_long)
3407 cstr_ccat(outstr, c);
3408 else
3409 cstr_wccat(outstr, c);
3411 /* add a trailing '\0' */
3412 if (!is_long)
3413 cstr_ccat(outstr, '\0');
3414 else
3415 cstr_wccat(outstr, '\0');
3418 /* we use 64 bit numbers */
3419 #define BN_SIZE 2
3421 /* bn = (bn << shift) | or_val */
3422 void bn_lshift(unsigned int *bn, int shift, int or_val)
3424 int i;
3425 unsigned int v;
3426 for(i=0;i<BN_SIZE;i++) {
3427 v = bn[i];
3428 bn[i] = (v << shift) | or_val;
3429 or_val = v >> (32 - shift);
3433 void bn_zero(unsigned int *bn)
3435 int i;
3436 for(i=0;i<BN_SIZE;i++) {
3437 bn[i] = 0;
3441 /* parse number in null terminated string 'p' and return it in the
3442 current token */
3443 void parse_number(const char *p)
3445 int b, t, shift, frac_bits, s, exp_val, ch;
3446 char *q;
3447 unsigned int bn[BN_SIZE];
3448 double d;
3450 /* number */
3451 q = token_buf;
3452 ch = *p++;
3453 t = ch;
3454 ch = *p++;
3455 *q++ = t;
3456 b = 10;
3457 if (t == '.') {
3458 goto float_frac_parse;
3459 } else if (t == '0') {
3460 if (ch == 'x' || ch == 'X') {
3461 q--;
3462 ch = *p++;
3463 b = 16;
3464 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3465 q--;
3466 ch = *p++;
3467 b = 2;
3470 /* parse all digits. cannot check octal numbers at this stage
3471 because of floating point constants */
3472 while (1) {
3473 if (ch >= 'a' && ch <= 'f')
3474 t = ch - 'a' + 10;
3475 else if (ch >= 'A' && ch <= 'F')
3476 t = ch - 'A' + 10;
3477 else if (isnum(ch))
3478 t = ch - '0';
3479 else
3480 break;
3481 if (t >= b)
3482 break;
3483 if (q >= token_buf + STRING_MAX_SIZE) {
3484 num_too_long:
3485 error("number too long");
3487 *q++ = ch;
3488 ch = *p++;
3490 if (ch == '.' ||
3491 ((ch == 'e' || ch == 'E') && b == 10) ||
3492 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3493 if (b != 10) {
3494 /* NOTE: strtox should support that for hexa numbers, but
3495 non ISOC99 libcs do not support it, so we prefer to do
3496 it by hand */
3497 /* hexadecimal or binary floats */
3498 /* XXX: handle overflows */
3499 *q = '\0';
3500 if (b == 16)
3501 shift = 4;
3502 else
3503 shift = 2;
3504 bn_zero(bn);
3505 q = token_buf;
3506 while (1) {
3507 t = *q++;
3508 if (t == '\0') {
3509 break;
3510 } else if (t >= 'a') {
3511 t = t - 'a' + 10;
3512 } else if (t >= 'A') {
3513 t = t - 'A' + 10;
3514 } else {
3515 t = t - '0';
3517 bn_lshift(bn, shift, t);
3519 frac_bits = 0;
3520 if (ch == '.') {
3521 ch = *p++;
3522 while (1) {
3523 t = ch;
3524 if (t >= 'a' && t <= 'f') {
3525 t = t - 'a' + 10;
3526 } else if (t >= 'A' && t <= 'F') {
3527 t = t - 'A' + 10;
3528 } else if (t >= '0' && t <= '9') {
3529 t = t - '0';
3530 } else {
3531 break;
3533 if (t >= b)
3534 error("invalid digit");
3535 bn_lshift(bn, shift, t);
3536 frac_bits += shift;
3537 ch = *p++;
3540 if (ch != 'p' && ch != 'P')
3541 expect("exponent");
3542 ch = *p++;
3543 s = 1;
3544 exp_val = 0;
3545 if (ch == '+') {
3546 ch = *p++;
3547 } else if (ch == '-') {
3548 s = -1;
3549 ch = *p++;
3551 if (ch < '0' || ch > '9')
3552 expect("exponent digits");
3553 while (ch >= '0' && ch <= '9') {
3554 exp_val = exp_val * 10 + ch - '0';
3555 ch = *p++;
3557 exp_val = exp_val * s;
3559 /* now we can generate the number */
3560 /* XXX: should patch directly float number */
3561 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3562 d = ldexp(d, exp_val - frac_bits);
3563 t = toup(ch);
3564 if (t == 'F') {
3565 ch = *p++;
3566 tok = TOK_CFLOAT;
3567 /* float : should handle overflow */
3568 tokc.f = (float)d;
3569 } else if (t == 'L') {
3570 ch = *p++;
3571 tok = TOK_CLDOUBLE;
3572 /* XXX: not large enough */
3573 tokc.ld = (long double)d;
3574 } else {
3575 tok = TOK_CDOUBLE;
3576 tokc.d = d;
3578 } else {
3579 /* decimal floats */
3580 if (ch == '.') {
3581 if (q >= token_buf + STRING_MAX_SIZE)
3582 goto num_too_long;
3583 *q++ = ch;
3584 ch = *p++;
3585 float_frac_parse:
3586 while (ch >= '0' && ch <= '9') {
3587 if (q >= token_buf + STRING_MAX_SIZE)
3588 goto num_too_long;
3589 *q++ = ch;
3590 ch = *p++;
3593 if (ch == 'e' || ch == 'E') {
3594 if (q >= token_buf + STRING_MAX_SIZE)
3595 goto num_too_long;
3596 *q++ = ch;
3597 ch = *p++;
3598 if (ch == '-' || ch == '+') {
3599 if (q >= token_buf + STRING_MAX_SIZE)
3600 goto num_too_long;
3601 *q++ = ch;
3602 ch = *p++;
3604 if (ch < '0' || ch > '9')
3605 expect("exponent digits");
3606 while (ch >= '0' && ch <= '9') {
3607 if (q >= token_buf + STRING_MAX_SIZE)
3608 goto num_too_long;
3609 *q++ = ch;
3610 ch = *p++;
3613 *q = '\0';
3614 t = toup(ch);
3615 errno = 0;
3616 if (t == 'F') {
3617 ch = *p++;
3618 tok = TOK_CFLOAT;
3619 tokc.f = strtof(token_buf, NULL);
3620 } else if (t == 'L') {
3621 ch = *p++;
3622 tok = TOK_CLDOUBLE;
3623 tokc.ld = strtold(token_buf, NULL);
3624 } else {
3625 tok = TOK_CDOUBLE;
3626 tokc.d = strtod(token_buf, NULL);
3629 } else {
3630 unsigned long long n, n1;
3631 int lcount, ucount;
3633 /* integer number */
3634 *q = '\0';
3635 q = token_buf;
3636 if (b == 10 && *q == '0') {
3637 b = 8;
3638 q++;
3640 n = 0;
3641 while(1) {
3642 t = *q++;
3643 /* no need for checks except for base 10 / 8 errors */
3644 if (t == '\0') {
3645 break;
3646 } else if (t >= 'a') {
3647 t = t - 'a' + 10;
3648 } else if (t >= 'A') {
3649 t = t - 'A' + 10;
3650 } else {
3651 t = t - '0';
3652 if (t >= b)
3653 error("invalid digit");
3655 n1 = n;
3656 n = n * b + t;
3657 /* detect overflow */
3658 /* XXX: this test is not reliable */
3659 if (n < n1)
3660 error("integer constant overflow");
3663 /* XXX: not exactly ANSI compliant */
3664 if ((n & 0xffffffff00000000LL) != 0) {
3665 if ((n >> 63) != 0)
3666 tok = TOK_CULLONG;
3667 else
3668 tok = TOK_CLLONG;
3669 } else if (n > 0x7fffffff) {
3670 tok = TOK_CUINT;
3671 } else {
3672 tok = TOK_CINT;
3674 lcount = 0;
3675 ucount = 0;
3676 for(;;) {
3677 t = toup(ch);
3678 if (t == 'L') {
3679 if (lcount >= 2)
3680 error("three 'l's in integer constant");
3681 lcount++;
3682 if (lcount == 2) {
3683 if (tok == TOK_CINT)
3684 tok = TOK_CLLONG;
3685 else if (tok == TOK_CUINT)
3686 tok = TOK_CULLONG;
3688 ch = *p++;
3689 } else if (t == 'U') {
3690 if (ucount >= 1)
3691 error("two 'u's in integer constant");
3692 ucount++;
3693 if (tok == TOK_CINT)
3694 tok = TOK_CUINT;
3695 else if (tok == TOK_CLLONG)
3696 tok = TOK_CULLONG;
3697 ch = *p++;
3698 } else {
3699 break;
3702 if (tok == TOK_CINT || tok == TOK_CUINT)
3703 tokc.ui = n;
3704 else
3705 tokc.ull = n;
3707 if (ch)
3708 error("invalid number\n");
3712 #define PARSE2(c1, tok1, c2, tok2) \
3713 case c1: \
3714 PEEKC(c, p); \
3715 if (c == c2) { \
3716 p++; \
3717 tok = tok2; \
3718 } else { \
3719 tok = tok1; \
3721 break;
3723 /* return next token without macro substitution */
3724 static inline void next_nomacro1(void)
3726 int t, c, is_long;
3727 TokenSym *ts;
3728 uint8_t *p, *p1;
3729 unsigned int h;
3731 p = file->buf_ptr;
3732 redo_no_start:
3733 c = *p;
3734 switch(c) {
3735 case ' ':
3736 case '\t':
3737 tok = c;
3738 p++;
3739 goto keep_tok_flags;
3740 case '\f':
3741 case '\v':
3742 case '\r':
3743 p++;
3744 goto redo_no_start;
3745 case '\\':
3746 /* first look if it is in fact an end of buffer */
3747 if (p >= file->buf_end) {
3748 file->buf_ptr = p;
3749 handle_eob();
3750 p = file->buf_ptr;
3751 if (p >= file->buf_end)
3752 goto parse_eof;
3753 else
3754 goto redo_no_start;
3755 } else {
3756 file->buf_ptr = p;
3757 ch = *p;
3758 handle_stray();
3759 p = file->buf_ptr;
3760 goto redo_no_start;
3762 parse_eof:
3764 TCCState *s1 = tcc_state;
3765 if ((parse_flags & PARSE_FLAG_LINEFEED)
3766 && !(tok_flags & TOK_FLAG_EOF)) {
3767 tok_flags |= TOK_FLAG_EOF;
3768 tok = TOK_LINEFEED;
3769 goto keep_tok_flags;
3770 } else if (s1->include_stack_ptr == s1->include_stack ||
3771 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3772 /* no include left : end of file. */
3773 tok = TOK_EOF;
3774 } else {
3775 tok_flags &= ~TOK_FLAG_EOF;
3776 /* pop include file */
3778 /* test if previous '#endif' was after a #ifdef at
3779 start of file */
3780 if (tok_flags & TOK_FLAG_ENDIF) {
3781 #ifdef INC_DEBUG
3782 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3783 #endif
3784 add_cached_include(s1, file->inc_type, file->inc_filename,
3785 file->ifndef_macro_saved);
3788 /* add end of include file debug info */
3789 if (do_debug) {
3790 put_stabd(N_EINCL, 0, 0);
3792 /* pop include stack */
3793 tcc_close(file);
3794 s1->include_stack_ptr--;
3795 file = *s1->include_stack_ptr;
3796 p = file->buf_ptr;
3797 goto redo_no_start;
3800 break;
3802 case '\n':
3803 file->line_num++;
3804 tok_flags |= TOK_FLAG_BOL;
3805 p++;
3806 if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
3807 goto redo_no_start;
3808 tok = TOK_LINEFEED;
3809 goto keep_tok_flags;
3811 case '#':
3812 /* XXX: simplify */
3813 PEEKC(c, p);
3814 if ((tok_flags & TOK_FLAG_BOL) &&
3815 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3816 file->buf_ptr = p;
3817 preprocess(tok_flags & TOK_FLAG_BOF);
3818 p = file->buf_ptr;
3819 goto redo_no_start;
3820 } else {
3821 if (c == '#') {
3822 p++;
3823 tok = TOK_TWOSHARPS;
3824 } else {
3825 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3826 p = parse_line_comment(p - 1);
3827 goto redo_no_start;
3828 } else {
3829 tok = '#';
3833 break;
3835 case 'a': case 'b': case 'c': case 'd':
3836 case 'e': case 'f': case 'g': case 'h':
3837 case 'i': case 'j': case 'k': case 'l':
3838 case 'm': case 'n': case 'o': case 'p':
3839 case 'q': case 'r': case 's': case 't':
3840 case 'u': case 'v': case 'w': case 'x':
3841 case 'y': case 'z':
3842 case 'A': case 'B': case 'C': case 'D':
3843 case 'E': case 'F': case 'G': case 'H':
3844 case 'I': case 'J': case 'K':
3845 case 'M': case 'N': case 'O': case 'P':
3846 case 'Q': case 'R': case 'S': case 'T':
3847 case 'U': case 'V': case 'W': case 'X':
3848 case 'Y': case 'Z':
3849 case '_':
3850 parse_ident_fast:
3851 p1 = p;
3852 h = TOK_HASH_INIT;
3853 h = TOK_HASH_FUNC(h, c);
3854 p++;
3855 for(;;) {
3856 c = *p;
3857 if (!isidnum_table[c-CH_EOF])
3858 break;
3859 h = TOK_HASH_FUNC(h, c);
3860 p++;
3862 if (c != '\\') {
3863 TokenSym **pts;
3864 int len;
3866 /* fast case : no stray found, so we have the full token
3867 and we have already hashed it */
3868 len = p - p1;
3869 h &= (TOK_HASH_SIZE - 1);
3870 pts = &hash_ident[h];
3871 for(;;) {
3872 ts = *pts;
3873 if (!ts)
3874 break;
3875 if (ts->len == len && !memcmp(ts->str, p1, len))
3876 goto token_found;
3877 pts = &(ts->hash_next);
3879 ts = tok_alloc_new(pts, p1, len);
3880 token_found: ;
3881 } else {
3882 /* slower case */
3883 cstr_reset(&tokcstr);
3885 while (p1 < p) {
3886 cstr_ccat(&tokcstr, *p1);
3887 p1++;
3889 p--;
3890 PEEKC(c, p);
3891 parse_ident_slow:
3892 while (isidnum_table[c-CH_EOF]) {
3893 cstr_ccat(&tokcstr, c);
3894 PEEKC(c, p);
3896 ts = tok_alloc(tokcstr.data, tokcstr.size);
3898 tok = ts->tok;
3899 break;
3900 case 'L':
3901 t = p[1];
3902 if (t != '\\' && t != '\'' && t != '\"') {
3903 /* fast case */
3904 goto parse_ident_fast;
3905 } else {
3906 PEEKC(c, p);
3907 if (c == '\'' || c == '\"') {
3908 is_long = 1;
3909 goto str_const;
3910 } else {
3911 cstr_reset(&tokcstr);
3912 cstr_ccat(&tokcstr, 'L');
3913 goto parse_ident_slow;
3916 break;
3917 case '0': case '1': case '2': case '3':
3918 case '4': case '5': case '6': case '7':
3919 case '8': case '9':
3921 cstr_reset(&tokcstr);
3922 /* after the first digit, accept digits, alpha, '.' or sign if
3923 prefixed by 'eEpP' */
3924 parse_num:
3925 for(;;) {
3926 t = c;
3927 cstr_ccat(&tokcstr, c);
3928 PEEKC(c, p);
3929 if (!(isnum(c) || isid(c) || c == '.' ||
3930 ((c == '+' || c == '-') &&
3931 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3932 break;
3934 /* We add a trailing '\0' to ease parsing */
3935 cstr_ccat(&tokcstr, '\0');
3936 tokc.cstr = &tokcstr;
3937 tok = TOK_PPNUM;
3938 break;
3939 case '.':
3940 /* special dot handling because it can also start a number */
3941 PEEKC(c, p);
3942 if (isnum(c)) {
3943 cstr_reset(&tokcstr);
3944 cstr_ccat(&tokcstr, '.');
3945 goto parse_num;
3946 } else if (c == '.') {
3947 PEEKC(c, p);
3948 if (c != '.')
3949 expect("'.'");
3950 PEEKC(c, p);
3951 tok = TOK_DOTS;
3952 } else {
3953 tok = '.';
3955 break;
3956 case '\'':
3957 case '\"':
3958 is_long = 0;
3959 str_const:
3961 CString str;
3962 int sep;
3964 sep = c;
3966 /* parse the string */
3967 cstr_new(&str);
3968 p = parse_pp_string(p, sep, &str);
3969 cstr_ccat(&str, '\0');
3971 /* eval the escape (should be done as TOK_PPNUM) */
3972 cstr_reset(&tokcstr);
3973 parse_escape_string(&tokcstr, str.data, is_long);
3974 cstr_free(&str);
3976 if (sep == '\'') {
3977 int char_size;
3978 /* XXX: make it portable */
3979 if (!is_long)
3980 char_size = 1;
3981 else
3982 char_size = sizeof(nwchar_t);
3983 if (tokcstr.size <= char_size)
3984 error("empty character constant");
3985 if (tokcstr.size > 2 * char_size)
3986 warning("multi-character character constant");
3987 if (!is_long) {
3988 tokc.i = *(int8_t *)tokcstr.data;
3989 tok = TOK_CCHAR;
3990 } else {
3991 tokc.i = *(nwchar_t *)tokcstr.data;
3992 tok = TOK_LCHAR;
3994 } else {
3995 tokc.cstr = &tokcstr;
3996 if (!is_long)
3997 tok = TOK_STR;
3998 else
3999 tok = TOK_LSTR;
4002 break;
4004 case '<':
4005 PEEKC(c, p);
4006 if (c == '=') {
4007 p++;
4008 tok = TOK_LE;
4009 } else if (c == '<') {
4010 PEEKC(c, p);
4011 if (c == '=') {
4012 p++;
4013 tok = TOK_A_SHL;
4014 } else {
4015 tok = TOK_SHL;
4017 } else {
4018 tok = TOK_LT;
4020 break;
4022 case '>':
4023 PEEKC(c, p);
4024 if (c == '=') {
4025 p++;
4026 tok = TOK_GE;
4027 } else if (c == '>') {
4028 PEEKC(c, p);
4029 if (c == '=') {
4030 p++;
4031 tok = TOK_A_SAR;
4032 } else {
4033 tok = TOK_SAR;
4035 } else {
4036 tok = TOK_GT;
4038 break;
4040 case '&':
4041 PEEKC(c, p);
4042 if (c == '&') {
4043 p++;
4044 tok = TOK_LAND;
4045 } else if (c == '=') {
4046 p++;
4047 tok = TOK_A_AND;
4048 } else {
4049 tok = '&';
4051 break;
4053 case '|':
4054 PEEKC(c, p);
4055 if (c == '|') {
4056 p++;
4057 tok = TOK_LOR;
4058 } else if (c == '=') {
4059 p++;
4060 tok = TOK_A_OR;
4061 } else {
4062 tok = '|';
4064 break;
4066 case '+':
4067 PEEKC(c, p);
4068 if (c == '+') {
4069 p++;
4070 tok = TOK_INC;
4071 } else if (c == '=') {
4072 p++;
4073 tok = TOK_A_ADD;
4074 } else {
4075 tok = '+';
4077 break;
4079 case '-':
4080 PEEKC(c, p);
4081 if (c == '-') {
4082 p++;
4083 tok = TOK_DEC;
4084 } else if (c == '=') {
4085 p++;
4086 tok = TOK_A_SUB;
4087 } else if (c == '>') {
4088 p++;
4089 tok = TOK_ARROW;
4090 } else {
4091 tok = '-';
4093 break;
4095 PARSE2('!', '!', '=', TOK_NE)
4096 PARSE2('=', '=', '=', TOK_EQ)
4097 PARSE2('*', '*', '=', TOK_A_MUL)
4098 PARSE2('%', '%', '=', TOK_A_MOD)
4099 PARSE2('^', '^', '=', TOK_A_XOR)
4101 /* comments or operator */
4102 case '/':
4103 PEEKC(c, p);
4104 if (c == '*') {
4105 p = parse_comment(p);
4106 goto redo_no_start;
4107 } else if (c == '/') {
4108 p = parse_line_comment(p);
4109 goto redo_no_start;
4110 } else if (c == '=') {
4111 p++;
4112 tok = TOK_A_DIV;
4113 } else {
4114 tok = '/';
4116 break;
4118 /* simple tokens */
4119 case '(':
4120 case ')':
4121 case '[':
4122 case ']':
4123 case '{':
4124 case '}':
4125 case ',':
4126 case ';':
4127 case ':':
4128 case '?':
4129 case '~':
4130 case '$': /* only used in assembler */
4131 case '@': /* dito */
4132 tok = c;
4133 p++;
4134 break;
4135 default:
4136 error("unrecognized character \\x%02x", c);
4137 break;
4139 tok_flags = 0;
4140 keep_tok_flags:
4141 file->buf_ptr = p;
4142 #if defined(PARSE_DEBUG)
4143 printf("token = %s\n", get_tok_str(tok, &tokc));
4144 #endif
4147 /* return next token without macro substitution. Can read input from
4148 macro_ptr buffer */
4149 static void next_nomacro_spc(void)
4151 if (macro_ptr) {
4152 redo:
4153 tok = *macro_ptr;
4154 if (tok) {
4155 TOK_GET(tok, macro_ptr, tokc);
4156 if (tok == TOK_LINENUM) {
4157 file->line_num = tokc.i;
4158 goto redo;
4161 } else {
4162 next_nomacro1();
4166 static void next_nomacro(void)
4168 do {
4169 next_nomacro_spc();
4170 } while (is_space(tok));
4173 /* substitute args in macro_str and return allocated string */
4174 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
4176 int *st, last_tok, t, spc;
4177 Sym *s;
4178 CValue cval;
4179 TokenString str;
4180 CString cstr;
4182 tok_str_new(&str);
4183 last_tok = 0;
4184 while(1) {
4185 TOK_GET(t, macro_str, cval);
4186 if (!t)
4187 break;
4188 if (t == '#') {
4189 /* stringize */
4190 TOK_GET(t, macro_str, cval);
4191 if (!t)
4192 break;
4193 s = sym_find2(args, t);
4194 if (s) {
4195 cstr_new(&cstr);
4196 st = (int *)s->c;
4197 spc = 0;
4198 while (*st) {
4199 TOK_GET(t, st, cval);
4200 if (!check_space(t, &spc))
4201 cstr_cat(&cstr, get_tok_str(t, &cval));
4203 cstr.size -= spc;
4204 cstr_ccat(&cstr, '\0');
4205 #ifdef PP_DEBUG
4206 printf("stringize: %s\n", (char *)cstr.data);
4207 #endif
4208 /* add string */
4209 cval.cstr = &cstr;
4210 tok_str_add2(&str, TOK_STR, &cval);
4211 cstr_free(&cstr);
4212 } else {
4213 tok_str_add2(&str, t, &cval);
4215 } else if (t >= TOK_IDENT) {
4216 s = sym_find2(args, t);
4217 if (s) {
4218 st = (int *)s->c;
4219 /* if '##' is present before or after, no arg substitution */
4220 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
4221 /* special case for var arg macros : ## eats the
4222 ',' if empty VA_ARGS variable. */
4223 /* XXX: test of the ',' is not 100%
4224 reliable. should fix it to avoid security
4225 problems */
4226 if (gnu_ext && s->type.t &&
4227 last_tok == TOK_TWOSHARPS &&
4228 str.len >= 2 && str.str[str.len - 2] == ',') {
4229 if (*st == 0) {
4230 /* suppress ',' '##' */
4231 str.len -= 2;
4232 } else {
4233 /* suppress '##' and add variable */
4234 str.len--;
4235 goto add_var;
4237 } else {
4238 int t1;
4239 add_var:
4240 for(;;) {
4241 TOK_GET(t1, st, cval);
4242 if (!t1)
4243 break;
4244 tok_str_add2(&str, t1, &cval);
4247 } else {
4248 /* NOTE: the stream cannot be read when macro
4249 substituing an argument */
4250 macro_subst(&str, nested_list, st, NULL);
4252 } else {
4253 tok_str_add(&str, t);
4255 } else {
4256 tok_str_add2(&str, t, &cval);
4258 last_tok = t;
4260 tok_str_add(&str, 0);
4261 return str.str;
4264 static char const ab_month_name[12][4] =
4266 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4267 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4270 /* do macro substitution of current token with macro 's' and add
4271 result to (tok_str,tok_len). 'nested_list' is the list of all
4272 macros we got inside to avoid recursing. Return non zero if no
4273 substitution needs to be done */
4274 static int macro_subst_tok(TokenString *tok_str,
4275 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4277 Sym *args, *sa, *sa1;
4278 int mstr_allocated, parlevel, *mstr, t, t1, *p, spc;
4279 TokenString str;
4280 char *cstrval;
4281 CValue cval;
4282 CString cstr;
4283 char buf[32];
4285 /* if symbol is a macro, prepare substitution */
4286 /* special macros */
4287 if (tok == TOK___LINE__) {
4288 snprintf(buf, sizeof(buf), "%d", file->line_num);
4289 cstrval = buf;
4290 t1 = TOK_PPNUM;
4291 goto add_cstr1;
4292 } else if (tok == TOK___FILE__) {
4293 cstrval = file->filename;
4294 goto add_cstr;
4295 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4296 time_t ti;
4297 struct tm *tm;
4299 time(&ti);
4300 tm = localtime(&ti);
4301 if (tok == TOK___DATE__) {
4302 snprintf(buf, sizeof(buf), "%s %2d %d",
4303 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4304 } else {
4305 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4306 tm->tm_hour, tm->tm_min, tm->tm_sec);
4308 cstrval = buf;
4309 add_cstr:
4310 t1 = TOK_STR;
4311 add_cstr1:
4312 cstr_new(&cstr);
4313 cstr_cat(&cstr, cstrval);
4314 cstr_ccat(&cstr, '\0');
4315 cval.cstr = &cstr;
4316 tok_str_add2(tok_str, t1, &cval);
4317 cstr_free(&cstr);
4318 } else {
4319 mstr = (int *)s->c;
4320 mstr_allocated = 0;
4321 if (s->type.t == MACRO_FUNC) {
4322 /* NOTE: we do not use next_nomacro to avoid eating the
4323 next token. XXX: find better solution */
4324 redo:
4325 if (macro_ptr) {
4326 p = macro_ptr;
4327 while (is_space(t = *p) || TOK_LINEFEED == t)
4328 ++p;
4329 if (t == 0 && can_read_stream) {
4330 /* end of macro stream: we must look at the token
4331 after in the file */
4332 struct macro_level *ml = *can_read_stream;
4333 macro_ptr = NULL;
4334 if (ml)
4336 macro_ptr = ml->p;
4337 ml->p = NULL;
4338 *can_read_stream = ml -> prev;
4340 goto redo;
4342 } else {
4343 /* XXX: incorrect with comments */
4344 ch = file->buf_ptr[0];
4345 while (is_space(ch) || ch == '\n')
4346 cinp();
4347 t = ch;
4349 if (t != '(') /* no macro subst */
4350 return -1;
4352 /* argument macro */
4353 next_nomacro();
4354 next_nomacro();
4355 args = NULL;
4356 sa = s->next;
4357 /* NOTE: empty args are allowed, except if no args */
4358 for(;;) {
4359 /* handle '()' case */
4360 if (!args && !sa && tok == ')')
4361 break;
4362 if (!sa)
4363 error("macro '%s' used with too many args",
4364 get_tok_str(s->v, 0));
4365 tok_str_new(&str);
4366 parlevel = spc = 0;
4367 /* NOTE: non zero sa->t indicates VA_ARGS */
4368 while ((parlevel > 0 ||
4369 (tok != ')' &&
4370 (tok != ',' || sa->type.t))) &&
4371 tok != -1) {
4372 if (tok == '(')
4373 parlevel++;
4374 else if (tok == ')')
4375 parlevel--;
4376 if (tok == TOK_LINEFEED)
4377 tok = ' ';
4378 if (!check_space(tok, &spc))
4379 tok_str_add2(&str, tok, &tokc);
4380 next_nomacro_spc();
4382 str.len -= spc;
4383 tok_str_add(&str, 0);
4384 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str);
4385 sa = sa->next;
4386 if (tok == ')') {
4387 /* special case for gcc var args: add an empty
4388 var arg argument if it is omitted */
4389 if (sa && sa->type.t && gnu_ext)
4390 continue;
4391 else
4392 break;
4394 if (tok != ',')
4395 expect(",");
4396 next_nomacro();
4398 if (sa) {
4399 error("macro '%s' used with too few args",
4400 get_tok_str(s->v, 0));
4403 /* now subst each arg */
4404 mstr = macro_arg_subst(nested_list, mstr, args);
4405 /* free memory */
4406 sa = args;
4407 while (sa) {
4408 sa1 = sa->prev;
4409 tok_str_free((int *)sa->c);
4410 sym_free(sa);
4411 sa = sa1;
4413 mstr_allocated = 1;
4415 sym_push2(nested_list, s->v, 0, 0);
4416 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4417 /* pop nested defined symbol */
4418 sa1 = *nested_list;
4419 *nested_list = sa1->prev;
4420 sym_free(sa1);
4421 if (mstr_allocated)
4422 tok_str_free(mstr);
4424 return 0;
4427 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4428 return the resulting string (which must be freed). */
4429 static inline int *macro_twosharps(const int *macro_str)
4431 TokenSym *ts;
4432 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4433 int t;
4434 const char *p1, *p2;
4435 CValue cval;
4436 TokenString macro_str1;
4437 CString cstr;
4439 start_macro_ptr = macro_str;
4440 /* we search the first '##' */
4441 for(;;) {
4442 macro_ptr1 = macro_str;
4443 TOK_GET(t, macro_str, cval);
4444 /* nothing more to do if end of string */
4445 if (t == 0)
4446 return NULL;
4447 if (*macro_str == TOK_TWOSHARPS)
4448 break;
4451 /* we saw '##', so we need more processing to handle it */
4452 cstr_new(&cstr);
4453 tok_str_new(&macro_str1);
4454 tok = t;
4455 tokc = cval;
4457 /* add all tokens seen so far */
4458 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4459 TOK_GET(t, ptr, cval);
4460 tok_str_add2(&macro_str1, t, &cval);
4462 saved_macro_ptr = macro_ptr;
4463 /* XXX: get rid of the use of macro_ptr here */
4464 macro_ptr = (int *)macro_str;
4465 for(;;) {
4466 while (*macro_ptr == TOK_TWOSHARPS) {
4467 macro_ptr++;
4468 macro_ptr1 = macro_ptr;
4469 t = *macro_ptr;
4470 if (t) {
4471 TOK_GET(t, macro_ptr, cval);
4472 /* We concatenate the two tokens if we have an
4473 identifier or a preprocessing number */
4474 cstr_reset(&cstr);
4475 p1 = get_tok_str(tok, &tokc);
4476 cstr_cat(&cstr, p1);
4477 p2 = get_tok_str(t, &cval);
4478 cstr_cat(&cstr, p2);
4479 cstr_ccat(&cstr, '\0');
4481 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4482 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4483 if (tok == TOK_PPNUM) {
4484 /* if number, then create a number token */
4485 /* NOTE: no need to allocate because
4486 tok_str_add2() does it */
4487 cstr_reset(&tokcstr);
4488 tokcstr = cstr;
4489 cstr_new(&cstr);
4490 tokc.cstr = &tokcstr;
4491 } else {
4492 /* if identifier, we must do a test to
4493 validate we have a correct identifier */
4494 if (t == TOK_PPNUM) {
4495 const char *p;
4496 int c;
4498 p = p2;
4499 for(;;) {
4500 c = *p;
4501 if (c == '\0')
4502 break;
4503 p++;
4504 if (!isnum(c) && !isid(c))
4505 goto error_pasting;
4508 ts = tok_alloc(cstr.data, strlen(cstr.data));
4509 tok = ts->tok; /* modify current token */
4511 } else {
4512 const char *str = cstr.data;
4513 const unsigned char *q;
4515 /* we look for a valid token */
4516 /* XXX: do more extensive checks */
4517 if (!strcmp(str, ">>=")) {
4518 tok = TOK_A_SAR;
4519 } else if (!strcmp(str, "<<=")) {
4520 tok = TOK_A_SHL;
4521 } else if (strlen(str) == 2) {
4522 /* search in two bytes table */
4523 q = tok_two_chars;
4524 for(;;) {
4525 if (!*q)
4526 goto error_pasting;
4527 if (q[0] == str[0] && q[1] == str[1])
4528 break;
4529 q += 3;
4531 tok = q[2];
4532 } else {
4533 error_pasting:
4534 /* NOTE: because get_tok_str use a static buffer,
4535 we must save it */
4536 cstr_reset(&cstr);
4537 p1 = get_tok_str(tok, &tokc);
4538 cstr_cat(&cstr, p1);
4539 cstr_ccat(&cstr, '\0');
4540 p2 = get_tok_str(t, &cval);
4541 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4542 /* cannot merge tokens: just add them separately */
4543 tok_str_add2(&macro_str1, tok, &tokc);
4544 /* XXX: free associated memory ? */
4545 tok = t;
4546 tokc = cval;
4551 tok_str_add2(&macro_str1, tok, &tokc);
4552 next_nomacro();
4553 if (tok == 0)
4554 break;
4556 macro_ptr = (int *)saved_macro_ptr;
4557 cstr_free(&cstr);
4558 tok_str_add(&macro_str1, 0);
4559 return macro_str1.str;
4563 /* do macro substitution of macro_str and add result to
4564 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4565 inside to avoid recursing. */
4566 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4567 const int *macro_str, struct macro_level ** can_read_stream)
4569 Sym *s;
4570 int *macro_str1;
4571 const int *ptr;
4572 int t, ret, spc;
4573 CValue cval;
4574 struct macro_level ml;
4576 /* first scan for '##' operator handling */
4577 ptr = macro_str;
4578 macro_str1 = macro_twosharps(ptr);
4579 if (macro_str1)
4580 ptr = macro_str1;
4581 spc = 0;
4582 while (1) {
4583 /* NOTE: ptr == NULL can only happen if tokens are read from
4584 file stream due to a macro function call */
4585 if (ptr == NULL)
4586 break;
4587 TOK_GET(t, ptr, cval);
4588 if (t == 0)
4589 break;
4590 s = define_find(t);
4591 if (s != NULL) {
4592 /* if nested substitution, do nothing */
4593 if (sym_find2(*nested_list, t))
4594 goto no_subst;
4595 ml.p = macro_ptr;
4596 if (can_read_stream)
4597 ml.prev = *can_read_stream, *can_read_stream = &ml;
4598 macro_ptr = (int *)ptr;
4599 tok = t;
4600 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4601 ptr = (int *)macro_ptr;
4602 macro_ptr = ml.p;
4603 if (can_read_stream && *can_read_stream == &ml)
4604 *can_read_stream = ml.prev;
4605 if (ret != 0)
4606 goto no_subst;
4607 } else {
4608 no_subst:
4609 if (!check_space(t, &spc))
4610 tok_str_add2(tok_str, t, &cval);
4613 if (macro_str1)
4614 tok_str_free(macro_str1);
4617 /* return next token with macro substitution */
4618 static void next(void)
4620 Sym *nested_list, *s;
4621 TokenString str;
4622 struct macro_level *ml;
4624 redo:
4625 if (parse_flags & PARSE_FLAG_SPACES)
4626 next_nomacro_spc();
4627 else
4628 next_nomacro();
4629 if (!macro_ptr) {
4630 /* if not reading from macro substituted string, then try
4631 to substitute macros */
4632 if (tok >= TOK_IDENT &&
4633 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4634 s = define_find(tok);
4635 if (s) {
4636 /* we have a macro: we try to substitute */
4637 tok_str_new(&str);
4638 nested_list = NULL;
4639 ml = NULL;
4640 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4641 /* substitution done, NOTE: maybe empty */
4642 tok_str_add(&str, 0);
4643 macro_ptr = str.str;
4644 macro_ptr_allocated = str.str;
4645 goto redo;
4649 } else {
4650 if (tok == 0) {
4651 /* end of macro or end of unget buffer */
4652 if (unget_buffer_enabled) {
4653 macro_ptr = unget_saved_macro_ptr;
4654 unget_buffer_enabled = 0;
4655 } else {
4656 /* end of macro string: free it */
4657 tok_str_free(macro_ptr_allocated);
4658 macro_ptr = NULL;
4660 goto redo;
4664 /* convert preprocessor tokens into C tokens */
4665 if (tok == TOK_PPNUM &&
4666 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4667 parse_number((char *)tokc.cstr->data);
4671 /* push back current token and set current token to 'last_tok'. Only
4672 identifier case handled for labels. */
4673 static inline void unget_tok(int last_tok)
4675 int i, n;
4676 int *q;
4677 unget_saved_macro_ptr = macro_ptr;
4678 unget_buffer_enabled = 1;
4679 q = unget_saved_buffer;
4680 macro_ptr = q;
4681 *q++ = tok;
4682 n = tok_ext_size(tok) - 1;
4683 for(i=0;i<n;i++)
4684 *q++ = tokc.tab[i];
4685 *q = 0; /* end of token string */
4686 tok = last_tok;
4690 void swap(int *p, int *q)
4692 int t;
4693 t = *p;
4694 *p = *q;
4695 *q = t;
4698 void vsetc(CType *type, int r, CValue *vc)
4700 int v;
4702 if (vtop >= vstack + (VSTACK_SIZE - 1))
4703 error("memory full");
4704 /* cannot let cpu flags if other instruction are generated. Also
4705 avoid leaving VT_JMP anywhere except on the top of the stack
4706 because it would complicate the code generator. */
4707 if (vtop >= vstack) {
4708 v = vtop->r & VT_VALMASK;
4709 if (v == VT_CMP || (v & ~1) == VT_JMP)
4710 gv(RC_INT);
4712 vtop++;
4713 vtop->type = *type;
4714 vtop->r = r;
4715 vtop->r2 = VT_CONST;
4716 vtop->c = *vc;
4719 /* push integer constant */
4720 void vpushi(int v)
4722 CValue cval;
4723 cval.i = v;
4724 vsetc(&int_type, VT_CONST, &cval);
4727 /* push long long constant */
4728 void vpushll(long long v)
4730 CValue cval;
4731 CType ctype;
4732 ctype.t = VT_LLONG;
4733 cval.ull = v;
4734 vsetc(&ctype, VT_CONST, &cval);
4737 /* Return a static symbol pointing to a section */
4738 static Sym *get_sym_ref(CType *type, Section *sec,
4739 unsigned long offset, unsigned long size)
4741 int v;
4742 Sym *sym;
4744 v = anon_sym++;
4745 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4746 sym->type.ref = type->ref;
4747 sym->r = VT_CONST | VT_SYM;
4748 put_extern_sym(sym, sec, offset, size);
4749 return sym;
4752 /* push a reference to a section offset by adding a dummy symbol */
4753 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4755 CValue cval;
4757 cval.ul = 0;
4758 vsetc(type, VT_CONST | VT_SYM, &cval);
4759 vtop->sym = get_sym_ref(type, sec, offset, size);
4762 /* define a new external reference to a symbol 'v' of type 'u' */
4763 static Sym *external_global_sym(int v, CType *type, int r)
4765 Sym *s;
4767 s = sym_find(v);
4768 if (!s) {
4769 /* push forward reference */
4770 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4771 s->type.ref = type->ref;
4772 s->r = r | VT_CONST | VT_SYM;
4774 return s;
4777 /* define a new external reference to a symbol 'v' of type 'u' */
4778 static Sym *external_sym(int v, CType *type, int r)
4780 Sym *s;
4782 s = sym_find(v);
4783 if (!s) {
4784 /* push forward reference */
4785 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4786 s->type.t |= VT_EXTERN;
4787 } else {
4788 if (!is_compatible_types(&s->type, type))
4789 error("incompatible types for redefinition of '%s'",
4790 get_tok_str(v, NULL));
4792 return s;
4795 /* push a reference to global symbol v */
4796 static void vpush_global_sym(CType *type, int v)
4798 Sym *sym;
4799 CValue cval;
4801 sym = external_global_sym(v, type, 0);
4802 cval.ul = 0;
4803 vsetc(type, VT_CONST | VT_SYM, &cval);
4804 vtop->sym = sym;
4807 void vset(CType *type, int r, int v)
4809 CValue cval;
4811 cval.i = v;
4812 vsetc(type, r, &cval);
4815 void vseti(int r, int v)
4817 CType type;
4818 type.t = VT_INT;
4819 vset(&type, r, v);
4822 void vswap(void)
4824 SValue tmp;
4826 tmp = vtop[0];
4827 vtop[0] = vtop[-1];
4828 vtop[-1] = tmp;
4831 void vpushv(SValue *v)
4833 if (vtop >= vstack + (VSTACK_SIZE - 1))
4834 error("memory full");
4835 vtop++;
4836 *vtop = *v;
4839 void vdup(void)
4841 vpushv(vtop);
4844 /* save r to the memory stack, and mark it as being free */
4845 void save_reg(int r)
4847 int l, saved, size, align;
4848 SValue *p, sv;
4849 CType *type;
4851 /* modify all stack values */
4852 saved = 0;
4853 l = 0;
4854 for(p=vstack;p<=vtop;p++) {
4855 if ((p->r & VT_VALMASK) == r ||
4856 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4857 /* must save value on stack if not already done */
4858 if (!saved) {
4859 /* NOTE: must reload 'r' because r might be equal to r2 */
4860 r = p->r & VT_VALMASK;
4861 /* store register in the stack */
4862 type = &p->type;
4863 if ((p->r & VT_LVAL) ||
4864 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4865 #ifdef TCC_TARGET_X86_64
4866 type = &char_pointer_type;
4867 #else
4868 type = &int_type;
4869 #endif
4870 size = type_size(type, &align);
4871 loc = (loc - size) & -align;
4872 sv.type.t = type->t;
4873 sv.r = VT_LOCAL | VT_LVAL;
4874 sv.c.ul = loc;
4875 store(r, &sv);
4876 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
4877 /* x86 specific: need to pop fp register ST0 if saved */
4878 if (r == TREG_ST0) {
4879 o(0xd9dd); /* fstp %st(1) */
4881 #endif
4882 #ifndef TCC_TARGET_X86_64
4883 /* special long long case */
4884 if ((type->t & VT_BTYPE) == VT_LLONG) {
4885 sv.c.ul += 4;
4886 store(p->r2, &sv);
4888 #endif
4889 l = loc;
4890 saved = 1;
4892 /* mark that stack entry as being saved on the stack */
4893 if (p->r & VT_LVAL) {
4894 /* also clear the bounded flag because the
4895 relocation address of the function was stored in
4896 p->c.ul */
4897 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4898 } else {
4899 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4901 p->r2 = VT_CONST;
4902 p->c.ul = l;
4907 /* find a register of class 'rc2' with at most one reference on stack.
4908 * If none, call get_reg(rc) */
4909 int get_reg_ex(int rc, int rc2)
4911 int r;
4912 SValue *p;
4914 for(r=0;r<NB_REGS;r++) {
4915 if (reg_classes[r] & rc2) {
4916 int n;
4917 n=0;
4918 for(p = vstack; p <= vtop; p++) {
4919 if ((p->r & VT_VALMASK) == r ||
4920 (p->r2 & VT_VALMASK) == r)
4921 n++;
4923 if (n <= 1)
4924 return r;
4927 return get_reg(rc);
4930 /* find a free register of class 'rc'. If none, save one register */
4931 int get_reg(int rc)
4933 int r;
4934 SValue *p;
4936 /* find a free register */
4937 for(r=0;r<NB_REGS;r++) {
4938 if (reg_classes[r] & rc) {
4939 for(p=vstack;p<=vtop;p++) {
4940 if ((p->r & VT_VALMASK) == r ||
4941 (p->r2 & VT_VALMASK) == r)
4942 goto notfound;
4944 return r;
4946 notfound: ;
4949 /* no register left : free the first one on the stack (VERY
4950 IMPORTANT to start from the bottom to ensure that we don't
4951 spill registers used in gen_opi()) */
4952 for(p=vstack;p<=vtop;p++) {
4953 r = p->r & VT_VALMASK;
4954 if (r < VT_CONST && (reg_classes[r] & rc))
4955 goto save_found;
4956 /* also look at second register (if long long) */
4957 r = p->r2 & VT_VALMASK;
4958 if (r < VT_CONST && (reg_classes[r] & rc)) {
4959 save_found:
4960 save_reg(r);
4961 return r;
4964 /* Should never comes here */
4965 return -1;
4968 /* save registers up to (vtop - n) stack entry */
4969 void save_regs(int n)
4971 int r;
4972 SValue *p, *p1;
4973 p1 = vtop - n;
4974 for(p = vstack;p <= p1; p++) {
4975 r = p->r & VT_VALMASK;
4976 if (r < VT_CONST) {
4977 save_reg(r);
4982 /* move register 's' to 'r', and flush previous value of r to memory
4983 if needed */
4984 void move_reg(int r, int s)
4986 SValue sv;
4988 if (r != s) {
4989 save_reg(r);
4990 sv.type.t = VT_INT;
4991 sv.r = s;
4992 sv.c.ul = 0;
4993 load(r, &sv);
4997 /* get address of vtop (vtop MUST BE an lvalue) */
4998 void gaddrof(void)
5000 vtop->r &= ~VT_LVAL;
5001 /* tricky: if saved lvalue, then we can go back to lvalue */
5002 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
5003 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
5006 #ifdef CONFIG_TCC_BCHECK
5007 /* generate lvalue bound code */
5008 void gbound(void)
5010 int lval_type;
5011 CType type1;
5013 vtop->r &= ~VT_MUSTBOUND;
5014 /* if lvalue, then use checking code before dereferencing */
5015 if (vtop->r & VT_LVAL) {
5016 /* if not VT_BOUNDED value, then make one */
5017 if (!(vtop->r & VT_BOUNDED)) {
5018 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
5019 /* must save type because we must set it to int to get pointer */
5020 type1 = vtop->type;
5021 vtop->type.t = VT_INT;
5022 gaddrof();
5023 vpushi(0);
5024 gen_bounded_ptr_add();
5025 vtop->r |= lval_type;
5026 vtop->type = type1;
5028 /* then check for dereferencing */
5029 gen_bounded_ptr_deref();
5032 #endif
5034 /* store vtop a register belonging to class 'rc'. lvalues are
5035 converted to values. Cannot be used if cannot be converted to
5036 register value (such as structures). */
5037 int gv(int rc)
5039 int r, rc2, bit_pos, bit_size, size, align, i;
5041 /* NOTE: get_reg can modify vstack[] */
5042 if (vtop->type.t & VT_BITFIELD) {
5043 CType type;
5044 int bits = 32;
5045 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
5046 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5047 /* remove bit field info to avoid loops */
5048 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5049 /* cast to int to propagate signedness in following ops */
5050 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
5051 type.t = VT_LLONG;
5052 bits = 64;
5053 } else
5054 type.t = VT_INT;
5055 if((vtop->type.t & VT_UNSIGNED) ||
5056 (vtop->type.t & VT_BTYPE) == VT_BOOL)
5057 type.t |= VT_UNSIGNED;
5058 gen_cast(&type);
5059 /* generate shifts */
5060 vpushi(bits - (bit_pos + bit_size));
5061 gen_op(TOK_SHL);
5062 vpushi(bits - bit_size);
5063 /* NOTE: transformed to SHR if unsigned */
5064 gen_op(TOK_SAR);
5065 r = gv(rc);
5066 } else {
5067 if (is_float(vtop->type.t) &&
5068 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5069 Sym *sym;
5070 int *ptr;
5071 unsigned long offset;
5072 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5073 CValue check;
5074 #endif
5076 /* XXX: unify with initializers handling ? */
5077 /* CPUs usually cannot use float constants, so we store them
5078 generically in data segment */
5079 size = type_size(&vtop->type, &align);
5080 offset = (data_section->data_offset + align - 1) & -align;
5081 data_section->data_offset = offset;
5082 /* XXX: not portable yet */
5083 #if defined(__i386__) || defined(__x86_64__)
5084 /* Zero pad x87 tenbyte long doubles */
5085 if (size == LDOUBLE_SIZE)
5086 vtop->c.tab[2] &= 0xffff;
5087 #endif
5088 ptr = section_ptr_add(data_section, size);
5089 size = size >> 2;
5090 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5091 check.d = 1;
5092 if(check.tab[0])
5093 for(i=0;i<size;i++)
5094 ptr[i] = vtop->c.tab[size-1-i];
5095 else
5096 #endif
5097 for(i=0;i<size;i++)
5098 ptr[i] = vtop->c.tab[i];
5099 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
5100 vtop->r |= VT_LVAL | VT_SYM;
5101 vtop->sym = sym;
5102 vtop->c.ul = 0;
5104 #ifdef CONFIG_TCC_BCHECK
5105 if (vtop->r & VT_MUSTBOUND)
5106 gbound();
5107 #endif
5109 r = vtop->r & VT_VALMASK;
5110 rc2 = RC_INT;
5111 if (rc == RC_IRET)
5112 rc2 = RC_LRET;
5113 /* need to reload if:
5114 - constant
5115 - lvalue (need to dereference pointer)
5116 - already a register, but not in the right class */
5117 if (r >= VT_CONST ||
5118 (vtop->r & VT_LVAL) ||
5119 !(reg_classes[r] & rc) ||
5120 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
5121 !(reg_classes[vtop->r2] & rc2))) {
5122 r = get_reg(rc);
5123 #ifndef TCC_TARGET_X86_64
5124 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
5125 int r2;
5126 unsigned long long ll;
5127 /* two register type load : expand to two words
5128 temporarily */
5129 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5130 /* load constant */
5131 ll = vtop->c.ull;
5132 vtop->c.ui = ll; /* first word */
5133 load(r, vtop);
5134 vtop->r = r; /* save register value */
5135 vpushi(ll >> 32); /* second word */
5136 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
5137 (vtop->r & VT_LVAL)) {
5138 /* We do not want to modifier the long long
5139 pointer here, so the safest (and less
5140 efficient) is to save all the other registers
5141 in the stack. XXX: totally inefficient. */
5142 save_regs(1);
5143 /* load from memory */
5144 load(r, vtop);
5145 vdup();
5146 vtop[-1].r = r; /* save register value */
5147 /* increment pointer to get second word */
5148 vtop->type.t = VT_INT;
5149 gaddrof();
5150 vpushi(4);
5151 gen_op('+');
5152 vtop->r |= VT_LVAL;
5153 } else {
5154 /* move registers */
5155 load(r, vtop);
5156 vdup();
5157 vtop[-1].r = r; /* save register value */
5158 vtop->r = vtop[-1].r2;
5160 /* allocate second register */
5161 r2 = get_reg(rc2);
5162 load(r2, vtop);
5163 vpop();
5164 /* write second register */
5165 vtop->r2 = r2;
5166 } else
5167 #endif
5168 if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
5169 int t1, t;
5170 /* lvalue of scalar type : need to use lvalue type
5171 because of possible cast */
5172 t = vtop->type.t;
5173 t1 = t;
5174 /* compute memory access type */
5175 if (vtop->r & VT_LVAL_BYTE)
5176 t = VT_BYTE;
5177 else if (vtop->r & VT_LVAL_SHORT)
5178 t = VT_SHORT;
5179 if (vtop->r & VT_LVAL_UNSIGNED)
5180 t |= VT_UNSIGNED;
5181 vtop->type.t = t;
5182 load(r, vtop);
5183 /* restore wanted type */
5184 vtop->type.t = t1;
5185 } else {
5186 /* one register type load */
5187 load(r, vtop);
5190 vtop->r = r;
5191 #ifdef TCC_TARGET_C67
5192 /* uses register pairs for doubles */
5193 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5194 vtop->r2 = r+1;
5195 #endif
5197 return r;
5200 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
5201 void gv2(int rc1, int rc2)
5203 int v;
5205 /* generate more generic register first. But VT_JMP or VT_CMP
5206 values must be generated first in all cases to avoid possible
5207 reload errors */
5208 v = vtop[0].r & VT_VALMASK;
5209 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
5210 vswap();
5211 gv(rc1);
5212 vswap();
5213 gv(rc2);
5214 /* test if reload is needed for first register */
5215 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
5216 vswap();
5217 gv(rc1);
5218 vswap();
5220 } else {
5221 gv(rc2);
5222 vswap();
5223 gv(rc1);
5224 vswap();
5225 /* test if reload is needed for first register */
5226 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
5227 gv(rc2);
5232 /* wrapper around RC_FRET to return a register by type */
5233 int rc_fret(int t)
5235 #ifdef TCC_TARGET_X86_64
5236 if (t == VT_LDOUBLE) {
5237 return RC_ST0;
5239 #endif
5240 return RC_FRET;
5243 /* wrapper around REG_FRET to return a register by type */
5244 int reg_fret(int t)
5246 #ifdef TCC_TARGET_X86_64
5247 if (t == VT_LDOUBLE) {
5248 return TREG_ST0;
5250 #endif
5251 return REG_FRET;
5254 /* expand long long on stack in two int registers */
5255 void lexpand(void)
5257 int u;
5259 u = vtop->type.t & VT_UNSIGNED;
5260 gv(RC_INT);
5261 vdup();
5262 vtop[0].r = vtop[-1].r2;
5263 vtop[0].r2 = VT_CONST;
5264 vtop[-1].r2 = VT_CONST;
5265 vtop[0].type.t = VT_INT | u;
5266 vtop[-1].type.t = VT_INT | u;
5269 #ifdef TCC_TARGET_ARM
5270 /* expand long long on stack */
5271 void lexpand_nr(void)
5273 int u,v;
5275 u = vtop->type.t & VT_UNSIGNED;
5276 vdup();
5277 vtop->r2 = VT_CONST;
5278 vtop->type.t = VT_INT | u;
5279 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
5280 if (v == VT_CONST) {
5281 vtop[-1].c.ui = vtop->c.ull;
5282 vtop->c.ui = vtop->c.ull >> 32;
5283 vtop->r = VT_CONST;
5284 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
5285 vtop->c.ui += 4;
5286 vtop->r = vtop[-1].r;
5287 } else if (v > VT_CONST) {
5288 vtop--;
5289 lexpand();
5290 } else
5291 vtop->r = vtop[-1].r2;
5292 vtop[-1].r2 = VT_CONST;
5293 vtop[-1].type.t = VT_INT | u;
5295 #endif
5297 /* build a long long from two ints */
5298 void lbuild(int t)
5300 gv2(RC_INT, RC_INT);
5301 vtop[-1].r2 = vtop[0].r;
5302 vtop[-1].type.t = t;
5303 vpop();
5306 /* rotate n first stack elements to the bottom
5307 I1 ... In -> I2 ... In I1 [top is right]
5309 void vrotb(int n)
5311 int i;
5312 SValue tmp;
5314 tmp = vtop[-n + 1];
5315 for(i=-n+1;i!=0;i++)
5316 vtop[i] = vtop[i+1];
5317 vtop[0] = tmp;
5320 /* rotate n first stack elements to the top
5321 I1 ... In -> In I1 ... I(n-1) [top is right]
5323 void vrott(int n)
5325 int i;
5326 SValue tmp;
5328 tmp = vtop[0];
5329 for(i = 0;i < n - 1; i++)
5330 vtop[-i] = vtop[-i - 1];
5331 vtop[-n + 1] = tmp;
5334 #ifdef TCC_TARGET_ARM
5335 /* like vrott but in other direction
5336 In ... I1 -> I(n-1) ... I1 In [top is right]
5338 void vnrott(int n)
5340 int i;
5341 SValue tmp;
5343 tmp = vtop[-n + 1];
5344 for(i = n - 1; i > 0; i--)
5345 vtop[-i] = vtop[-i + 1];
5346 vtop[0] = tmp;
5348 #endif
5350 /* pop stack value */
5351 void vpop(void)
5353 int v;
5354 v = vtop->r & VT_VALMASK;
5355 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
5356 /* for x86, we need to pop the FP stack */
5357 if (v == TREG_ST0 && !nocode_wanted) {
5358 o(0xd9dd); /* fstp %st(1) */
5359 } else
5360 #endif
5361 if (v == VT_JMP || v == VT_JMPI) {
5362 /* need to put correct jump if && or || without test */
5363 gsym(vtop->c.ul);
5365 vtop--;
5368 /* convert stack entry to register and duplicate its value in another
5369 register */
5370 void gv_dup(void)
5372 int rc, t, r, r1;
5373 SValue sv;
5375 t = vtop->type.t;
5376 if ((t & VT_BTYPE) == VT_LLONG) {
5377 lexpand();
5378 gv_dup();
5379 vswap();
5380 vrotb(3);
5381 gv_dup();
5382 vrotb(4);
5383 /* stack: H L L1 H1 */
5384 lbuild(t);
5385 vrotb(3);
5386 vrotb(3);
5387 vswap();
5388 lbuild(t);
5389 vswap();
5390 } else {
5391 /* duplicate value */
5392 rc = RC_INT;
5393 sv.type.t = VT_INT;
5394 if (is_float(t)) {
5395 rc = RC_FLOAT;
5396 #ifdef TCC_TARGET_X86_64
5397 if ((t & VT_BTYPE) == VT_LDOUBLE) {
5398 rc = RC_ST0;
5400 #endif
5401 sv.type.t = t;
5403 r = gv(rc);
5404 r1 = get_reg(rc);
5405 sv.r = r;
5406 sv.c.ul = 0;
5407 load(r1, &sv); /* move r to r1 */
5408 vdup();
5409 /* duplicates value */
5410 vtop->r = r1;
5414 #ifndef TCC_TARGET_X86_64
5415 /* generate CPU independent (unsigned) long long operations */
5416 void gen_opl(int op)
5418 int t, a, b, op1, c, i;
5419 int func;
5420 unsigned short reg_iret = REG_IRET;
5421 unsigned short reg_lret = REG_LRET;
5422 SValue tmp;
5424 switch(op) {
5425 case '/':
5426 case TOK_PDIV:
5427 func = TOK___divdi3;
5428 goto gen_func;
5429 case TOK_UDIV:
5430 func = TOK___udivdi3;
5431 goto gen_func;
5432 case '%':
5433 func = TOK___moddi3;
5434 goto gen_mod_func;
5435 case TOK_UMOD:
5436 func = TOK___umoddi3;
5437 gen_mod_func:
5438 #ifdef TCC_ARM_EABI
5439 reg_iret = TREG_R2;
5440 reg_lret = TREG_R3;
5441 #endif
5442 gen_func:
5443 /* call generic long long function */
5444 vpush_global_sym(&func_old_type, func);
5445 vrott(3);
5446 gfunc_call(2);
5447 vpushi(0);
5448 vtop->r = reg_iret;
5449 vtop->r2 = reg_lret;
5450 break;
5451 case '^':
5452 case '&':
5453 case '|':
5454 case '*':
5455 case '+':
5456 case '-':
5457 t = vtop->type.t;
5458 vswap();
5459 lexpand();
5460 vrotb(3);
5461 lexpand();
5462 /* stack: L1 H1 L2 H2 */
5463 tmp = vtop[0];
5464 vtop[0] = vtop[-3];
5465 vtop[-3] = tmp;
5466 tmp = vtop[-2];
5467 vtop[-2] = vtop[-3];
5468 vtop[-3] = tmp;
5469 vswap();
5470 /* stack: H1 H2 L1 L2 */
5471 if (op == '*') {
5472 vpushv(vtop - 1);
5473 vpushv(vtop - 1);
5474 gen_op(TOK_UMULL);
5475 lexpand();
5476 /* stack: H1 H2 L1 L2 ML MH */
5477 for(i=0;i<4;i++)
5478 vrotb(6);
5479 /* stack: ML MH H1 H2 L1 L2 */
5480 tmp = vtop[0];
5481 vtop[0] = vtop[-2];
5482 vtop[-2] = tmp;
5483 /* stack: ML MH H1 L2 H2 L1 */
5484 gen_op('*');
5485 vrotb(3);
5486 vrotb(3);
5487 gen_op('*');
5488 /* stack: ML MH M1 M2 */
5489 gen_op('+');
5490 gen_op('+');
5491 } else if (op == '+' || op == '-') {
5492 /* XXX: add non carry method too (for MIPS or alpha) */
5493 if (op == '+')
5494 op1 = TOK_ADDC1;
5495 else
5496 op1 = TOK_SUBC1;
5497 gen_op(op1);
5498 /* stack: H1 H2 (L1 op L2) */
5499 vrotb(3);
5500 vrotb(3);
5501 gen_op(op1 + 1); /* TOK_xxxC2 */
5502 } else {
5503 gen_op(op);
5504 /* stack: H1 H2 (L1 op L2) */
5505 vrotb(3);
5506 vrotb(3);
5507 /* stack: (L1 op L2) H1 H2 */
5508 gen_op(op);
5509 /* stack: (L1 op L2) (H1 op H2) */
5511 /* stack: L H */
5512 lbuild(t);
5513 break;
5514 case TOK_SAR:
5515 case TOK_SHR:
5516 case TOK_SHL:
5517 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5518 t = vtop[-1].type.t;
5519 vswap();
5520 lexpand();
5521 vrotb(3);
5522 /* stack: L H shift */
5523 c = (int)vtop->c.i;
5524 /* constant: simpler */
5525 /* NOTE: all comments are for SHL. the other cases are
5526 done by swaping words */
5527 vpop();
5528 if (op != TOK_SHL)
5529 vswap();
5530 if (c >= 32) {
5531 /* stack: L H */
5532 vpop();
5533 if (c > 32) {
5534 vpushi(c - 32);
5535 gen_op(op);
5537 if (op != TOK_SAR) {
5538 vpushi(0);
5539 } else {
5540 gv_dup();
5541 vpushi(31);
5542 gen_op(TOK_SAR);
5544 vswap();
5545 } else {
5546 vswap();
5547 gv_dup();
5548 /* stack: H L L */
5549 vpushi(c);
5550 gen_op(op);
5551 vswap();
5552 vpushi(32 - c);
5553 if (op == TOK_SHL)
5554 gen_op(TOK_SHR);
5555 else
5556 gen_op(TOK_SHL);
5557 vrotb(3);
5558 /* stack: L L H */
5559 vpushi(c);
5560 if (op == TOK_SHL)
5561 gen_op(TOK_SHL);
5562 else
5563 gen_op(TOK_SHR);
5564 gen_op('|');
5566 if (op != TOK_SHL)
5567 vswap();
5568 lbuild(t);
5569 } else {
5570 /* XXX: should provide a faster fallback on x86 ? */
5571 switch(op) {
5572 case TOK_SAR:
5573 func = TOK___ashrdi3;
5574 goto gen_func;
5575 case TOK_SHR:
5576 func = TOK___lshrdi3;
5577 goto gen_func;
5578 case TOK_SHL:
5579 func = TOK___ashldi3;
5580 goto gen_func;
5583 break;
5584 default:
5585 /* compare operations */
5586 t = vtop->type.t;
5587 vswap();
5588 lexpand();
5589 vrotb(3);
5590 lexpand();
5591 /* stack: L1 H1 L2 H2 */
5592 tmp = vtop[-1];
5593 vtop[-1] = vtop[-2];
5594 vtop[-2] = tmp;
5595 /* stack: L1 L2 H1 H2 */
5596 /* compare high */
5597 op1 = op;
5598 /* when values are equal, we need to compare low words. since
5599 the jump is inverted, we invert the test too. */
5600 if (op1 == TOK_LT)
5601 op1 = TOK_LE;
5602 else if (op1 == TOK_GT)
5603 op1 = TOK_GE;
5604 else if (op1 == TOK_ULT)
5605 op1 = TOK_ULE;
5606 else if (op1 == TOK_UGT)
5607 op1 = TOK_UGE;
5608 a = 0;
5609 b = 0;
5610 gen_op(op1);
5611 if (op1 != TOK_NE) {
5612 a = gtst(1, 0);
5614 if (op != TOK_EQ) {
5615 /* generate non equal test */
5616 /* XXX: NOT PORTABLE yet */
5617 if (a == 0) {
5618 b = gtst(0, 0);
5619 } else {
5620 #if defined(TCC_TARGET_I386)
5621 b = psym(0x850f, 0);
5622 #elif defined(TCC_TARGET_ARM)
5623 b = ind;
5624 o(0x1A000000 | encbranch(ind, 0, 1));
5625 #elif defined(TCC_TARGET_C67)
5626 error("not implemented");
5627 #else
5628 #error not supported
5629 #endif
5632 /* compare low. Always unsigned */
5633 op1 = op;
5634 if (op1 == TOK_LT)
5635 op1 = TOK_ULT;
5636 else if (op1 == TOK_LE)
5637 op1 = TOK_ULE;
5638 else if (op1 == TOK_GT)
5639 op1 = TOK_UGT;
5640 else if (op1 == TOK_GE)
5641 op1 = TOK_UGE;
5642 gen_op(op1);
5643 a = gtst(1, a);
5644 gsym(b);
5645 vseti(VT_JMPI, a);
5646 break;
5649 #endif
5651 /* handle integer constant optimizations and various machine
5652 independent opt */
5653 void gen_opic(int op)
5655 int c1, c2, t1, t2, n;
5656 SValue *v1, *v2;
5657 long long l1, l2;
5658 typedef unsigned long long U;
5660 v1 = vtop - 1;
5661 v2 = vtop;
5662 t1 = v1->type.t & VT_BTYPE;
5663 t2 = v2->type.t & VT_BTYPE;
5665 if (t1 == VT_LLONG)
5666 l1 = v1->c.ll;
5667 else if (v1->type.t & VT_UNSIGNED)
5668 l1 = v1->c.ui;
5669 else
5670 l1 = v1->c.i;
5672 if (t2 == VT_LLONG)
5673 l2 = v2->c.ll;
5674 else if (v2->type.t & VT_UNSIGNED)
5675 l2 = v2->c.ui;
5676 else
5677 l2 = v2->c.i;
5679 /* currently, we cannot do computations with forward symbols */
5680 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5681 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5682 if (c1 && c2) {
5683 switch(op) {
5684 case '+': l1 += l2; break;
5685 case '-': l1 -= l2; break;
5686 case '&': l1 &= l2; break;
5687 case '^': l1 ^= l2; break;
5688 case '|': l1 |= l2; break;
5689 case '*': l1 *= l2; break;
5691 case TOK_PDIV:
5692 case '/':
5693 case '%':
5694 case TOK_UDIV:
5695 case TOK_UMOD:
5696 /* if division by zero, generate explicit division */
5697 if (l2 == 0) {
5698 if (const_wanted)
5699 error("division by zero in constant");
5700 goto general_case;
5702 switch(op) {
5703 default: l1 /= l2; break;
5704 case '%': l1 %= l2; break;
5705 case TOK_UDIV: l1 = (U)l1 / l2; break;
5706 case TOK_UMOD: l1 = (U)l1 % l2; break;
5708 break;
5709 case TOK_SHL: l1 <<= l2; break;
5710 case TOK_SHR: l1 = (U)l1 >> l2; break;
5711 case TOK_SAR: l1 >>= l2; break;
5712 /* tests */
5713 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5714 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5715 case TOK_EQ: l1 = l1 == l2; break;
5716 case TOK_NE: l1 = l1 != l2; break;
5717 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5718 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5719 case TOK_LT: l1 = l1 < l2; break;
5720 case TOK_GE: l1 = l1 >= l2; break;
5721 case TOK_LE: l1 = l1 <= l2; break;
5722 case TOK_GT: l1 = l1 > l2; break;
5723 /* logical */
5724 case TOK_LAND: l1 = l1 && l2; break;
5725 case TOK_LOR: l1 = l1 || l2; break;
5726 default:
5727 goto general_case;
5729 v1->c.ll = l1;
5730 vtop--;
5731 } else {
5732 /* if commutative ops, put c2 as constant */
5733 if (c1 && (op == '+' || op == '&' || op == '^' ||
5734 op == '|' || op == '*')) {
5735 vswap();
5736 c2 = c1; //c = c1, c1 = c2, c2 = c;
5737 l2 = l1; //l = l1, l1 = l2, l2 = l;
5739 /* Filter out NOP operations like x*1, x-0, x&-1... */
5740 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5741 op == TOK_PDIV) &&
5742 l2 == 1) ||
5743 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5744 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5745 l2 == 0) ||
5746 (op == '&' &&
5747 l2 == -1))) {
5748 /* nothing to do */
5749 vtop--;
5750 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5751 /* try to use shifts instead of muls or divs */
5752 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5753 n = -1;
5754 while (l2) {
5755 l2 >>= 1;
5756 n++;
5758 vtop->c.ll = n;
5759 if (op == '*')
5760 op = TOK_SHL;
5761 else if (op == TOK_PDIV)
5762 op = TOK_SAR;
5763 else
5764 op = TOK_SHR;
5766 goto general_case;
5767 } else if (c2 && (op == '+' || op == '-') &&
5768 ((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5769 (VT_CONST | VT_SYM) ||
5770 (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
5771 /* symbol + constant case */
5772 if (op == '-')
5773 l2 = -l2;
5774 vtop--;
5775 vtop->c.ll += l2;
5776 } else {
5777 general_case:
5778 if (!nocode_wanted) {
5779 /* call low level op generator */
5780 if (t1 == VT_LLONG || t2 == VT_LLONG)
5781 gen_opl(op);
5782 else
5783 gen_opi(op);
5784 } else {
5785 vtop--;
5791 /* generate a floating point operation with constant propagation */
5792 void gen_opif(int op)
5794 int c1, c2;
5795 SValue *v1, *v2;
5796 long double f1, f2;
5798 v1 = vtop - 1;
5799 v2 = vtop;
5800 /* currently, we cannot do computations with forward symbols */
5801 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5802 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5803 if (c1 && c2) {
5804 if (v1->type.t == VT_FLOAT) {
5805 f1 = v1->c.f;
5806 f2 = v2->c.f;
5807 } else if (v1->type.t == VT_DOUBLE) {
5808 f1 = v1->c.d;
5809 f2 = v2->c.d;
5810 } else {
5811 f1 = v1->c.ld;
5812 f2 = v2->c.ld;
5815 /* NOTE: we only do constant propagation if finite number (not
5816 NaN or infinity) (ANSI spec) */
5817 if (!ieee_finite(f1) || !ieee_finite(f2))
5818 goto general_case;
5820 switch(op) {
5821 case '+': f1 += f2; break;
5822 case '-': f1 -= f2; break;
5823 case '*': f1 *= f2; break;
5824 case '/':
5825 if (f2 == 0.0) {
5826 if (const_wanted)
5827 error("division by zero in constant");
5828 goto general_case;
5830 f1 /= f2;
5831 break;
5832 /* XXX: also handles tests ? */
5833 default:
5834 goto general_case;
5836 /* XXX: overflow test ? */
5837 if (v1->type.t == VT_FLOAT) {
5838 v1->c.f = f1;
5839 } else if (v1->type.t == VT_DOUBLE) {
5840 v1->c.d = f1;
5841 } else {
5842 v1->c.ld = f1;
5844 vtop--;
5845 } else {
5846 general_case:
5847 if (!nocode_wanted) {
5848 gen_opf(op);
5849 } else {
5850 vtop--;
5855 static int pointed_size(CType *type)
5857 int align;
5858 return type_size(pointed_type(type), &align);
5861 static inline int is_null_pointer(SValue *p)
5863 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5864 return 0;
5865 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5866 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5869 static inline int is_integer_btype(int bt)
5871 return (bt == VT_BYTE || bt == VT_SHORT ||
5872 bt == VT_INT || bt == VT_LLONG);
5875 /* check types for comparison or substraction of pointers */
5876 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5878 CType *type1, *type2, tmp_type1, tmp_type2;
5879 int bt1, bt2;
5881 /* null pointers are accepted for all comparisons as gcc */
5882 if (is_null_pointer(p1) || is_null_pointer(p2))
5883 return;
5884 type1 = &p1->type;
5885 type2 = &p2->type;
5886 bt1 = type1->t & VT_BTYPE;
5887 bt2 = type2->t & VT_BTYPE;
5888 /* accept comparison between pointer and integer with a warning */
5889 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5890 if (op != TOK_LOR && op != TOK_LAND )
5891 warning("comparison between pointer and integer");
5892 return;
5895 /* both must be pointers or implicit function pointers */
5896 if (bt1 == VT_PTR) {
5897 type1 = pointed_type(type1);
5898 } else if (bt1 != VT_FUNC)
5899 goto invalid_operands;
5901 if (bt2 == VT_PTR) {
5902 type2 = pointed_type(type2);
5903 } else if (bt2 != VT_FUNC) {
5904 invalid_operands:
5905 error("invalid operands to binary %s", get_tok_str(op, NULL));
5907 if ((type1->t & VT_BTYPE) == VT_VOID ||
5908 (type2->t & VT_BTYPE) == VT_VOID)
5909 return;
5910 tmp_type1 = *type1;
5911 tmp_type2 = *type2;
5912 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5913 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5914 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5915 /* gcc-like error if '-' is used */
5916 if (op == '-')
5917 goto invalid_operands;
5918 else
5919 warning("comparison of distinct pointer types lacks a cast");
5923 /* generic gen_op: handles types problems */
5924 void gen_op(int op)
5926 int u, t1, t2, bt1, bt2, t;
5927 CType type1;
5929 t1 = vtop[-1].type.t;
5930 t2 = vtop[0].type.t;
5931 bt1 = t1 & VT_BTYPE;
5932 bt2 = t2 & VT_BTYPE;
5934 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5935 /* at least one operand is a pointer */
5936 /* relationnal op: must be both pointers */
5937 if (op >= TOK_ULT && op <= TOK_LOR) {
5938 check_comparison_pointer_types(vtop - 1, vtop, op);
5939 /* pointers are handled are unsigned */
5940 #ifdef TCC_TARGET_X86_64
5941 t = VT_LLONG | VT_UNSIGNED;
5942 #else
5943 t = VT_INT | VT_UNSIGNED;
5944 #endif
5945 goto std_op;
5947 /* if both pointers, then it must be the '-' op */
5948 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5949 if (op != '-')
5950 error("cannot use pointers here");
5951 check_comparison_pointer_types(vtop - 1, vtop, op);
5952 /* XXX: check that types are compatible */
5953 u = pointed_size(&vtop[-1].type);
5954 gen_opic(op);
5955 /* set to integer type */
5956 #ifdef TCC_TARGET_X86_64
5957 vtop->type.t = VT_LLONG;
5958 #else
5959 vtop->type.t = VT_INT;
5960 #endif
5961 vpushi(u);
5962 gen_op(TOK_PDIV);
5963 } else {
5964 /* exactly one pointer : must be '+' or '-'. */
5965 if (op != '-' && op != '+')
5966 error("cannot use pointers here");
5967 /* Put pointer as first operand */
5968 if (bt2 == VT_PTR) {
5969 vswap();
5970 swap(&t1, &t2);
5972 type1 = vtop[-1].type;
5973 #ifdef TCC_TARGET_X86_64
5974 vpushll(pointed_size(&vtop[-1].type));
5975 #else
5976 /* XXX: cast to int ? (long long case) */
5977 vpushi(pointed_size(&vtop[-1].type));
5978 #endif
5979 gen_op('*');
5980 #ifdef CONFIG_TCC_BCHECK
5981 /* if evaluating constant expression, no code should be
5982 generated, so no bound check */
5983 if (do_bounds_check && !const_wanted) {
5984 /* if bounded pointers, we generate a special code to
5985 test bounds */
5986 if (op == '-') {
5987 vpushi(0);
5988 vswap();
5989 gen_op('-');
5991 gen_bounded_ptr_add();
5992 } else
5993 #endif
5995 gen_opic(op);
5997 /* put again type if gen_opic() swaped operands */
5998 vtop->type = type1;
6000 } else if (is_float(bt1) || is_float(bt2)) {
6001 /* compute bigger type and do implicit casts */
6002 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
6003 t = VT_LDOUBLE;
6004 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
6005 t = VT_DOUBLE;
6006 } else {
6007 t = VT_FLOAT;
6009 /* floats can only be used for a few operations */
6010 if (op != '+' && op != '-' && op != '*' && op != '/' &&
6011 (op < TOK_ULT || op > TOK_GT))
6012 error("invalid operands for binary operation");
6013 goto std_op;
6014 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
6015 /* cast to biggest op */
6016 t = VT_LLONG;
6017 /* convert to unsigned if it does not fit in a long long */
6018 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
6019 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
6020 t |= VT_UNSIGNED;
6021 goto std_op;
6022 } else {
6023 /* integer operations */
6024 t = VT_INT;
6025 /* convert to unsigned if it does not fit in an integer */
6026 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
6027 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
6028 t |= VT_UNSIGNED;
6029 std_op:
6030 /* XXX: currently, some unsigned operations are explicit, so
6031 we modify them here */
6032 if (t & VT_UNSIGNED) {
6033 if (op == TOK_SAR)
6034 op = TOK_SHR;
6035 else if (op == '/')
6036 op = TOK_UDIV;
6037 else if (op == '%')
6038 op = TOK_UMOD;
6039 else if (op == TOK_LT)
6040 op = TOK_ULT;
6041 else if (op == TOK_GT)
6042 op = TOK_UGT;
6043 else if (op == TOK_LE)
6044 op = TOK_ULE;
6045 else if (op == TOK_GE)
6046 op = TOK_UGE;
6048 vswap();
6049 type1.t = t;
6050 gen_cast(&type1);
6051 vswap();
6052 /* special case for shifts and long long: we keep the shift as
6053 an integer */
6054 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
6055 type1.t = VT_INT;
6056 gen_cast(&type1);
6057 if (is_float(t))
6058 gen_opif(op);
6059 else
6060 gen_opic(op);
6061 if (op >= TOK_ULT && op <= TOK_GT) {
6062 /* relationnal op: the result is an int */
6063 vtop->type.t = VT_INT;
6064 } else {
6065 vtop->type.t = t;
6070 #ifndef TCC_TARGET_ARM
6071 /* generic itof for unsigned long long case */
6072 void gen_cvt_itof1(int t)
6074 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
6075 (VT_LLONG | VT_UNSIGNED)) {
6077 if (t == VT_FLOAT)
6078 vpush_global_sym(&func_old_type, TOK___floatundisf);
6079 #if LDOUBLE_SIZE != 8
6080 else if (t == VT_LDOUBLE)
6081 vpush_global_sym(&func_old_type, TOK___floatundixf);
6082 #endif
6083 else
6084 vpush_global_sym(&func_old_type, TOK___floatundidf);
6085 vrott(2);
6086 gfunc_call(1);
6087 vpushi(0);
6088 vtop->r = reg_fret(t);
6089 } else {
6090 gen_cvt_itof(t);
6093 #endif
6095 /* generic ftoi for unsigned long long case */
6096 void gen_cvt_ftoi1(int t)
6098 int st;
6100 if (t == (VT_LLONG | VT_UNSIGNED)) {
6101 /* not handled natively */
6102 st = vtop->type.t & VT_BTYPE;
6103 if (st == VT_FLOAT)
6104 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
6105 #if LDOUBLE_SIZE != 8
6106 else if (st == VT_LDOUBLE)
6107 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
6108 #endif
6109 else
6110 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
6111 vrott(2);
6112 gfunc_call(1);
6113 vpushi(0);
6114 vtop->r = REG_IRET;
6115 vtop->r2 = REG_LRET;
6116 } else {
6117 gen_cvt_ftoi(t);
6121 /* force char or short cast */
6122 void force_charshort_cast(int t)
6124 int bits, dbt;
6125 dbt = t & VT_BTYPE;
6126 /* XXX: add optimization if lvalue : just change type and offset */
6127 if (dbt == VT_BYTE)
6128 bits = 8;
6129 else
6130 bits = 16;
6131 if (t & VT_UNSIGNED) {
6132 vpushi((1 << bits) - 1);
6133 gen_op('&');
6134 } else {
6135 bits = 32 - bits;
6136 vpushi(bits);
6137 gen_op(TOK_SHL);
6138 /* result must be signed or the SAR is converted to an SHL
6139 This was not the case when "t" was a signed short
6140 and the last value on the stack was an unsigned int */
6141 vtop->type.t &= ~VT_UNSIGNED;
6142 vpushi(bits);
6143 gen_op(TOK_SAR);
6147 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
6148 static void gen_cast(CType *type)
6150 int sbt, dbt, sf, df, c, p;
6152 /* special delayed cast for char/short */
6153 /* XXX: in some cases (multiple cascaded casts), it may still
6154 be incorrect */
6155 if (vtop->r & VT_MUSTCAST) {
6156 vtop->r &= ~VT_MUSTCAST;
6157 force_charshort_cast(vtop->type.t);
6160 /* bitfields first get cast to ints */
6161 if (vtop->type.t & VT_BITFIELD) {
6162 gv(RC_INT);
6165 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
6166 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
6168 if (sbt != dbt) {
6169 sf = is_float(sbt);
6170 df = is_float(dbt);
6171 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6172 p = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM);
6173 if (c) {
6174 /* constant case: we can do it now */
6175 /* XXX: in ISOC, cannot do it if error in convert */
6176 if (sbt == VT_FLOAT)
6177 vtop->c.ld = vtop->c.f;
6178 else if (sbt == VT_DOUBLE)
6179 vtop->c.ld = vtop->c.d;
6181 if (df) {
6182 if ((sbt & VT_BTYPE) == VT_LLONG) {
6183 if (sbt & VT_UNSIGNED)
6184 vtop->c.ld = vtop->c.ull;
6185 else
6186 vtop->c.ld = vtop->c.ll;
6187 } else if(!sf) {
6188 if (sbt & VT_UNSIGNED)
6189 vtop->c.ld = vtop->c.ui;
6190 else
6191 vtop->c.ld = vtop->c.i;
6194 if (dbt == VT_FLOAT)
6195 vtop->c.f = (float)vtop->c.ld;
6196 else if (dbt == VT_DOUBLE)
6197 vtop->c.d = (double)vtop->c.ld;
6198 } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
6199 vtop->c.ull = (unsigned long long)vtop->c.ld;
6200 } else if (sf && dbt == VT_BOOL) {
6201 vtop->c.i = (vtop->c.ld != 0);
6202 } else {
6203 if(sf)
6204 vtop->c.ll = (long long)vtop->c.ld;
6205 else if (sbt == (VT_LLONG|VT_UNSIGNED))
6206 vtop->c.ll = vtop->c.ull;
6207 else if (sbt & VT_UNSIGNED)
6208 vtop->c.ll = vtop->c.ui;
6209 else if (sbt != VT_LLONG)
6210 vtop->c.ll = vtop->c.i;
6212 if (dbt == (VT_LLONG|VT_UNSIGNED))
6213 vtop->c.ull = vtop->c.ll;
6214 else if (dbt == VT_BOOL)
6215 vtop->c.i = (vtop->c.ll != 0);
6216 else if (dbt != VT_LLONG) {
6217 int s = 0;
6218 if ((dbt & VT_BTYPE) == VT_BYTE)
6219 s = 24;
6220 else if ((dbt & VT_BTYPE) == VT_SHORT)
6221 s = 16;
6223 if(dbt & VT_UNSIGNED)
6224 vtop->c.ui = ((unsigned int)vtop->c.ll << s) >> s;
6225 else
6226 vtop->c.i = ((int)vtop->c.ll << s) >> s;
6229 } else if (p && dbt == VT_BOOL) {
6230 vtop->r = VT_CONST;
6231 vtop->c.i = 1;
6232 } else if (!nocode_wanted) {
6233 /* non constant case: generate code */
6234 if (sf && df) {
6235 /* convert from fp to fp */
6236 gen_cvt_ftof(dbt);
6237 } else if (df) {
6238 /* convert int to fp */
6239 gen_cvt_itof1(dbt);
6240 } else if (sf) {
6241 /* convert fp to int */
6242 if (dbt == VT_BOOL) {
6243 vpushi(0);
6244 gen_op(TOK_NE);
6245 } else {
6246 /* we handle char/short/etc... with generic code */
6247 if (dbt != (VT_INT | VT_UNSIGNED) &&
6248 dbt != (VT_LLONG | VT_UNSIGNED) &&
6249 dbt != VT_LLONG)
6250 dbt = VT_INT;
6251 gen_cvt_ftoi1(dbt);
6252 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
6253 /* additional cast for char/short... */
6254 vtop->type.t = dbt;
6255 gen_cast(type);
6258 #ifndef TCC_TARGET_X86_64
6259 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
6260 if ((sbt & VT_BTYPE) != VT_LLONG) {
6261 /* scalar to long long */
6262 /* machine independent conversion */
6263 gv(RC_INT);
6264 /* generate high word */
6265 if (sbt == (VT_INT | VT_UNSIGNED)) {
6266 vpushi(0);
6267 gv(RC_INT);
6268 } else {
6269 if (sbt == VT_PTR) {
6270 /* cast from pointer to int before we apply
6271 shift operation, which pointers don't support*/
6272 gen_cast(&int_type);
6274 gv_dup();
6275 vpushi(31);
6276 gen_op(TOK_SAR);
6278 /* patch second register */
6279 vtop[-1].r2 = vtop->r;
6280 vpop();
6282 #else
6283 } else if ((dbt & VT_BTYPE) == VT_LLONG ||
6284 (dbt & VT_BTYPE) == VT_PTR) {
6285 /* XXX: not sure if this is perfect... need more tests */
6286 if ((sbt & VT_BTYPE) != VT_LLONG) {
6287 int r = gv(RC_INT);
6288 if (sbt != (VT_INT | VT_UNSIGNED) &&
6289 sbt != VT_PTR && sbt != VT_FUNC) {
6290 /* x86_64 specific: movslq */
6291 o(0x6348);
6292 o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r));
6295 #endif
6296 } else if (dbt == VT_BOOL) {
6297 /* scalar to bool */
6298 vpushi(0);
6299 gen_op(TOK_NE);
6300 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
6301 (dbt & VT_BTYPE) == VT_SHORT) {
6302 if (sbt == VT_PTR) {
6303 vtop->type.t = VT_INT;
6304 warning("nonportable conversion from pointer to char/short");
6306 force_charshort_cast(dbt);
6307 } else if ((dbt & VT_BTYPE) == VT_INT) {
6308 /* scalar to int */
6309 if (sbt == VT_LLONG) {
6310 /* from long long: just take low order word */
6311 lexpand();
6312 vpop();
6314 /* if lvalue and single word type, nothing to do because
6315 the lvalue already contains the real type size (see
6316 VT_LVAL_xxx constants) */
6319 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
6320 /* if we are casting between pointer types,
6321 we must update the VT_LVAL_xxx size */
6322 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
6323 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
6325 vtop->type = *type;
6328 /* return type size. Put alignment at 'a' */
6329 static int type_size(CType *type, int *a)
6331 Sym *s;
6332 int bt;
6334 bt = type->t & VT_BTYPE;
6335 if (bt == VT_STRUCT) {
6336 /* struct/union */
6337 s = type->ref;
6338 *a = s->r;
6339 return s->c;
6340 } else if (bt == VT_PTR) {
6341 if (type->t & VT_ARRAY) {
6342 int ts;
6344 s = type->ref;
6345 ts = type_size(&s->type, a);
6347 if (ts < 0 && s->c < 0)
6348 ts = -ts;
6350 return ts * s->c;
6351 } else {
6352 *a = PTR_SIZE;
6353 return PTR_SIZE;
6355 } else if (bt == VT_LDOUBLE) {
6356 *a = LDOUBLE_ALIGN;
6357 return LDOUBLE_SIZE;
6358 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
6359 #ifdef TCC_TARGET_I386
6360 #ifdef TCC_TARGET_PE
6361 *a = 8;
6362 #else
6363 *a = 4;
6364 #endif
6365 #elif defined(TCC_TARGET_ARM)
6366 #ifdef TCC_ARM_EABI
6367 *a = 8;
6368 #else
6369 *a = 4;
6370 #endif
6371 #else
6372 *a = 8;
6373 #endif
6374 return 8;
6375 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6376 *a = 4;
6377 return 4;
6378 } else if (bt == VT_SHORT) {
6379 *a = 2;
6380 return 2;
6381 } else {
6382 /* char, void, function, _Bool */
6383 *a = 1;
6384 return 1;
6388 /* return the pointed type of t */
6389 static inline CType *pointed_type(CType *type)
6391 return &type->ref->type;
6394 /* modify type so that its it is a pointer to type. */
6395 static void mk_pointer(CType *type)
6397 Sym *s;
6398 s = sym_push(SYM_FIELD, type, 0, -1);
6399 type->t = VT_PTR | (type->t & ~VT_TYPE);
6400 type->ref = s;
6403 /* compare function types. OLD functions match any new functions */
6404 static int is_compatible_func(CType *type1, CType *type2)
6406 Sym *s1, *s2;
6408 s1 = type1->ref;
6409 s2 = type2->ref;
6410 if (!is_compatible_types(&s1->type, &s2->type))
6411 return 0;
6412 /* check func_call */
6413 if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
6414 return 0;
6415 /* XXX: not complete */
6416 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6417 return 1;
6418 if (s1->c != s2->c)
6419 return 0;
6420 while (s1 != NULL) {
6421 if (s2 == NULL)
6422 return 0;
6423 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6424 return 0;
6425 s1 = s1->next;
6426 s2 = s2->next;
6428 if (s2)
6429 return 0;
6430 return 1;
6433 /* return true if type1 and type2 are the same. If unqualified is
6434 true, qualifiers on the types are ignored.
6436 - enums are not checked as gcc __builtin_types_compatible_p ()
6438 static int compare_types(CType *type1, CType *type2, int unqualified)
6440 int bt1, t1, t2;
6442 t1 = type1->t & VT_TYPE;
6443 t2 = type2->t & VT_TYPE;
6444 if (unqualified) {
6445 /* strip qualifiers before comparing */
6446 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6447 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6449 /* XXX: bitfields ? */
6450 if (t1 != t2)
6451 return 0;
6452 /* test more complicated cases */
6453 bt1 = t1 & VT_BTYPE;
6454 if (bt1 == VT_PTR) {
6455 type1 = pointed_type(type1);
6456 type2 = pointed_type(type2);
6457 return is_compatible_types(type1, type2);
6458 } else if (bt1 == VT_STRUCT) {
6459 return (type1->ref == type2->ref);
6460 } else if (bt1 == VT_FUNC) {
6461 return is_compatible_func(type1, type2);
6462 } else {
6463 return 1;
6467 /* return true if type1 and type2 are exactly the same (including
6468 qualifiers).
6470 static int is_compatible_types(CType *type1, CType *type2)
6472 return compare_types(type1,type2,0);
6475 /* return true if type1 and type2 are the same (ignoring qualifiers).
6477 static int is_compatible_parameter_types(CType *type1, CType *type2)
6479 return compare_types(type1,type2,1);
6482 /* print a type. If 'varstr' is not NULL, then the variable is also
6483 printed in the type */
6484 /* XXX: union */
6485 /* XXX: add array and function pointers */
6486 void type_to_str(char *buf, int buf_size,
6487 CType *type, const char *varstr)
6489 int bt, v, t;
6490 Sym *s, *sa;
6491 char buf1[256];
6492 const char *tstr;
6494 t = type->t & VT_TYPE;
6495 bt = t & VT_BTYPE;
6496 buf[0] = '\0';
6497 if (t & VT_CONSTANT)
6498 pstrcat(buf, buf_size, "const ");
6499 if (t & VT_VOLATILE)
6500 pstrcat(buf, buf_size, "volatile ");
6501 if (t & VT_UNSIGNED)
6502 pstrcat(buf, buf_size, "unsigned ");
6503 switch(bt) {
6504 case VT_VOID:
6505 tstr = "void";
6506 goto add_tstr;
6507 case VT_BOOL:
6508 tstr = "_Bool";
6509 goto add_tstr;
6510 case VT_BYTE:
6511 tstr = "char";
6512 goto add_tstr;
6513 case VT_SHORT:
6514 tstr = "short";
6515 goto add_tstr;
6516 case VT_INT:
6517 tstr = "int";
6518 goto add_tstr;
6519 case VT_LONG:
6520 tstr = "long";
6521 goto add_tstr;
6522 case VT_LLONG:
6523 tstr = "long long";
6524 goto add_tstr;
6525 case VT_FLOAT:
6526 tstr = "float";
6527 goto add_tstr;
6528 case VT_DOUBLE:
6529 tstr = "double";
6530 goto add_tstr;
6531 case VT_LDOUBLE:
6532 tstr = "long double";
6533 add_tstr:
6534 pstrcat(buf, buf_size, tstr);
6535 break;
6536 case VT_ENUM:
6537 case VT_STRUCT:
6538 if (bt == VT_STRUCT)
6539 tstr = "struct ";
6540 else
6541 tstr = "enum ";
6542 pstrcat(buf, buf_size, tstr);
6543 v = type->ref->v & ~SYM_STRUCT;
6544 if (v >= SYM_FIRST_ANOM)
6545 pstrcat(buf, buf_size, "<anonymous>");
6546 else
6547 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6548 break;
6549 case VT_FUNC:
6550 s = type->ref;
6551 type_to_str(buf, buf_size, &s->type, varstr);
6552 pstrcat(buf, buf_size, "(");
6553 sa = s->next;
6554 while (sa != NULL) {
6555 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6556 pstrcat(buf, buf_size, buf1);
6557 sa = sa->next;
6558 if (sa)
6559 pstrcat(buf, buf_size, ", ");
6561 pstrcat(buf, buf_size, ")");
6562 goto no_var;
6563 case VT_PTR:
6564 s = type->ref;
6565 pstrcpy(buf1, sizeof(buf1), "*");
6566 if (varstr)
6567 pstrcat(buf1, sizeof(buf1), varstr);
6568 type_to_str(buf, buf_size, &s->type, buf1);
6569 goto no_var;
6571 if (varstr) {
6572 pstrcat(buf, buf_size, " ");
6573 pstrcat(buf, buf_size, varstr);
6575 no_var: ;
6578 /* verify type compatibility to store vtop in 'dt' type, and generate
6579 casts if needed. */
6580 static void gen_assign_cast(CType *dt)
6582 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6583 char buf1[256], buf2[256];
6584 int dbt, sbt;
6586 st = &vtop->type; /* source type */
6587 dbt = dt->t & VT_BTYPE;
6588 sbt = st->t & VT_BTYPE;
6589 if (dt->t & VT_CONSTANT)
6590 warning("assignment of read-only location");
6591 switch(dbt) {
6592 case VT_PTR:
6593 /* special cases for pointers */
6594 /* '0' can also be a pointer */
6595 if (is_null_pointer(vtop))
6596 goto type_ok;
6597 /* accept implicit pointer to integer cast with warning */
6598 if (is_integer_btype(sbt)) {
6599 warning("assignment makes pointer from integer without a cast");
6600 goto type_ok;
6602 type1 = pointed_type(dt);
6603 /* a function is implicitely a function pointer */
6604 if (sbt == VT_FUNC) {
6605 if ((type1->t & VT_BTYPE) != VT_VOID &&
6606 !is_compatible_types(pointed_type(dt), st))
6607 goto error;
6608 else
6609 goto type_ok;
6611 if (sbt != VT_PTR)
6612 goto error;
6613 type2 = pointed_type(st);
6614 if ((type1->t & VT_BTYPE) == VT_VOID ||
6615 (type2->t & VT_BTYPE) == VT_VOID) {
6616 /* void * can match anything */
6617 } else {
6618 /* exact type match, except for unsigned */
6619 tmp_type1 = *type1;
6620 tmp_type2 = *type2;
6621 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6622 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6623 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6624 warning("assignment from incompatible pointer type");
6626 /* check const and volatile */
6627 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6628 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6629 warning("assignment discards qualifiers from pointer target type");
6630 break;
6631 case VT_BYTE:
6632 case VT_SHORT:
6633 case VT_INT:
6634 case VT_LLONG:
6635 if (sbt == VT_PTR || sbt == VT_FUNC) {
6636 warning("assignment makes integer from pointer without a cast");
6638 /* XXX: more tests */
6639 break;
6640 case VT_STRUCT:
6641 tmp_type1 = *dt;
6642 tmp_type2 = *st;
6643 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6644 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6645 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6646 error:
6647 type_to_str(buf1, sizeof(buf1), st, NULL);
6648 type_to_str(buf2, sizeof(buf2), dt, NULL);
6649 error("cannot cast '%s' to '%s'", buf1, buf2);
6651 break;
6653 type_ok:
6654 gen_cast(dt);
6657 /* store vtop in lvalue pushed on stack */
6658 void vstore(void)
6660 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6662 ft = vtop[-1].type.t;
6663 sbt = vtop->type.t & VT_BTYPE;
6664 dbt = ft & VT_BTYPE;
6665 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6666 (sbt == VT_INT && dbt == VT_SHORT)) {
6667 /* optimize char/short casts */
6668 delayed_cast = VT_MUSTCAST;
6669 vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));
6670 /* XXX: factorize */
6671 if (ft & VT_CONSTANT)
6672 warning("assignment of read-only location");
6673 } else {
6674 delayed_cast = 0;
6675 if (!(ft & VT_BITFIELD))
6676 gen_assign_cast(&vtop[-1].type);
6679 if (sbt == VT_STRUCT) {
6680 /* if structure, only generate pointer */
6681 /* structure assignment : generate memcpy */
6682 /* XXX: optimize if small size */
6683 if (!nocode_wanted) {
6684 size = type_size(&vtop->type, &align);
6686 #ifdef TCC_ARM_EABI
6687 if(!(align & 7))
6688 vpush_global_sym(&func_old_type, TOK_memcpy8);
6689 else if(!(align & 3))
6690 vpush_global_sym(&func_old_type, TOK_memcpy4);
6691 else
6692 #endif
6693 vpush_global_sym(&func_old_type, TOK_memcpy);
6695 /* destination */
6696 vpushv(vtop - 2);
6697 vtop->type.t = VT_PTR;
6698 gaddrof();
6699 /* source */
6700 vpushv(vtop - 2);
6701 vtop->type.t = VT_PTR;
6702 gaddrof();
6703 /* type size */
6704 vpushi(size);
6705 gfunc_call(3);
6707 vswap();
6708 vpop();
6709 } else {
6710 vswap();
6711 vpop();
6713 /* leave source on stack */
6714 } else if (ft & VT_BITFIELD) {
6715 /* bitfield store handling */
6716 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6717 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6718 /* remove bit field info to avoid loops */
6719 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6721 /* duplicate source into other register */
6722 gv_dup();
6723 vswap();
6724 vrott(3);
6726 if((ft & VT_BTYPE) == VT_BOOL) {
6727 gen_cast(&vtop[-1].type);
6728 vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
6731 /* duplicate destination */
6732 vdup();
6733 vtop[-1] = vtop[-2];
6735 /* mask and shift source */
6736 if((ft & VT_BTYPE) != VT_BOOL) {
6737 if((ft & VT_BTYPE) == VT_LLONG) {
6738 vpushll((1ULL << bit_size) - 1ULL);
6739 } else {
6740 vpushi((1 << bit_size) - 1);
6742 gen_op('&');
6744 vpushi(bit_pos);
6745 gen_op(TOK_SHL);
6746 /* load destination, mask and or with source */
6747 vswap();
6748 if((ft & VT_BTYPE) == VT_LLONG) {
6749 vpushll(~(((1ULL << bit_size) - 1ULL) << bit_pos));
6750 } else {
6751 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6753 gen_op('&');
6754 gen_op('|');
6755 /* store result */
6756 vstore();
6758 /* pop off shifted source from "duplicate source..." above */
6759 vpop();
6761 } else {
6762 #ifdef CONFIG_TCC_BCHECK
6763 /* bound check case */
6764 if (vtop[-1].r & VT_MUSTBOUND) {
6765 vswap();
6766 gbound();
6767 vswap();
6769 #endif
6770 if (!nocode_wanted) {
6771 rc = RC_INT;
6772 if (is_float(ft)) {
6773 rc = RC_FLOAT;
6774 #ifdef TCC_TARGET_X86_64
6775 if ((ft & VT_BTYPE) == VT_LDOUBLE) {
6776 rc = RC_ST0;
6778 #endif
6780 r = gv(rc); /* generate value */
6781 /* if lvalue was saved on stack, must read it */
6782 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6783 SValue sv;
6784 t = get_reg(RC_INT);
6785 #ifdef TCC_TARGET_X86_64
6786 sv.type.t = VT_PTR;
6787 #else
6788 sv.type.t = VT_INT;
6789 #endif
6790 sv.r = VT_LOCAL | VT_LVAL;
6791 sv.c.ul = vtop[-1].c.ul;
6792 load(t, &sv);
6793 vtop[-1].r = t | VT_LVAL;
6795 store(r, vtop - 1);
6796 #ifndef TCC_TARGET_X86_64
6797 /* two word case handling : store second register at word + 4 */
6798 if ((ft & VT_BTYPE) == VT_LLONG) {
6799 vswap();
6800 /* convert to int to increment easily */
6801 vtop->type.t = VT_INT;
6802 gaddrof();
6803 vpushi(4);
6804 gen_op('+');
6805 vtop->r |= VT_LVAL;
6806 vswap();
6807 /* XXX: it works because r2 is spilled last ! */
6808 store(vtop->r2, vtop - 1);
6810 #endif
6812 vswap();
6813 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6814 vtop->r |= delayed_cast;
6818 /* post defines POST/PRE add. c is the token ++ or -- */
6819 void inc(int post, int c)
6821 test_lvalue();
6822 vdup(); /* save lvalue */
6823 if (post) {
6824 gv_dup(); /* duplicate value */
6825 vrotb(3);
6826 vrotb(3);
6828 /* add constant */
6829 vpushi(c - TOK_MID);
6830 gen_op('+');
6831 vstore(); /* store value */
6832 if (post)
6833 vpop(); /* if post op, return saved value */
6836 /* Parse GNUC __attribute__ extension. Currently, the following
6837 extensions are recognized:
6838 - aligned(n) : set data/function alignment.
6839 - packed : force data alignment to 1
6840 - section(x) : generate data/code in this section.
6841 - unused : currently ignored, but may be used someday.
6842 - regparm(n) : pass function parameters in registers (i386 only)
6844 static void parse_attribute(AttributeDef *ad)
6846 int t, n;
6848 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6849 next();
6850 skip('(');
6851 skip('(');
6852 while (tok != ')') {
6853 if (tok < TOK_IDENT)
6854 expect("attribute name");
6855 t = tok;
6856 next();
6857 switch(t) {
6858 case TOK_SECTION1:
6859 case TOK_SECTION2:
6860 skip('(');
6861 if (tok != TOK_STR)
6862 expect("section name");
6863 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6864 next();
6865 skip(')');
6866 break;
6867 case TOK_ALIGNED1:
6868 case TOK_ALIGNED2:
6869 if (tok == '(') {
6870 next();
6871 n = expr_const();
6872 if (n <= 0 || (n & (n - 1)) != 0)
6873 error("alignment must be a positive power of two");
6874 skip(')');
6875 } else {
6876 n = MAX_ALIGN;
6878 ad->aligned = n;
6879 break;
6880 case TOK_PACKED1:
6881 case TOK_PACKED2:
6882 ad->packed = 1;
6883 break;
6884 case TOK_UNUSED1:
6885 case TOK_UNUSED2:
6886 /* currently, no need to handle it because tcc does not
6887 track unused objects */
6888 break;
6889 case TOK_NORETURN1:
6890 case TOK_NORETURN2:
6891 /* currently, no need to handle it because tcc does not
6892 track unused objects */
6893 break;
6894 case TOK_CDECL1:
6895 case TOK_CDECL2:
6896 case TOK_CDECL3:
6897 FUNC_CALL(ad->func_attr) = FUNC_CDECL;
6898 break;
6899 case TOK_STDCALL1:
6900 case TOK_STDCALL2:
6901 case TOK_STDCALL3:
6902 FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
6903 break;
6904 #ifdef TCC_TARGET_I386
6905 case TOK_REGPARM1:
6906 case TOK_REGPARM2:
6907 skip('(');
6908 n = expr_const();
6909 if (n > 3)
6910 n = 3;
6911 else if (n < 0)
6912 n = 0;
6913 if (n > 0)
6914 FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
6915 skip(')');
6916 break;
6917 case TOK_FASTCALL1:
6918 case TOK_FASTCALL2:
6919 case TOK_FASTCALL3:
6920 FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
6921 break;
6922 #endif
6923 case TOK_DLLEXPORT:
6924 FUNC_EXPORT(ad->func_attr) = 1;
6925 break;
6926 default:
6927 if (tcc_state->warn_unsupported)
6928 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6929 /* skip parameters */
6930 if (tok == '(') {
6931 int parenthesis = 0;
6932 do {
6933 if (tok == '(')
6934 parenthesis++;
6935 else if (tok == ')')
6936 parenthesis--;
6937 next();
6938 } while (parenthesis && tok != -1);
6940 break;
6942 if (tok != ',')
6943 break;
6944 next();
6946 skip(')');
6947 skip(')');
6951 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6952 static void struct_decl(CType *type, int u)
6954 int a, v, size, align, maxalign, c, offset;
6955 int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt;
6956 Sym *s, *ss, *ass, **ps;
6957 AttributeDef ad;
6958 CType type1, btype;
6960 a = tok; /* save decl type */
6961 next();
6962 if (tok != '{') {
6963 v = tok;
6964 next();
6965 /* struct already defined ? return it */
6966 if (v < TOK_IDENT)
6967 expect("struct/union/enum name");
6968 s = struct_find(v);
6969 if (s) {
6970 if (s->type.t != a)
6971 error("invalid type");
6972 goto do_decl;
6974 } else {
6975 v = anon_sym++;
6977 type1.t = a;
6978 /* we put an undefined size for struct/union */
6979 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6980 s->r = 0; /* default alignment is zero as gcc */
6981 /* put struct/union/enum name in type */
6982 do_decl:
6983 type->t = u;
6984 type->ref = s;
6986 if (tok == '{') {
6987 next();
6988 if (s->c != -1)
6989 error("struct/union/enum already defined");
6990 /* cannot be empty */
6991 c = 0;
6992 /* non empty enums are not allowed */
6993 if (a == TOK_ENUM) {
6994 for(;;) {
6995 v = tok;
6996 if (v < TOK_UIDENT)
6997 expect("identifier");
6998 next();
6999 if (tok == '=') {
7000 next();
7001 c = expr_const();
7003 /* enum symbols have static storage */
7004 ss = sym_push(v, &int_type, VT_CONST, c);
7005 ss->type.t |= VT_STATIC;
7006 if (tok != ',')
7007 break;
7008 next();
7009 c++;
7010 /* NOTE: we accept a trailing comma */
7011 if (tok == '}')
7012 break;
7014 skip('}');
7015 } else {
7016 maxalign = 1;
7017 ps = &s->next;
7018 prevbt = VT_INT;
7019 bit_pos = 0;
7020 offset = 0;
7021 while (tok != '}') {
7022 parse_btype(&btype, &ad);
7023 while (1) {
7024 bit_size = -1;
7025 v = 0;
7026 type1 = btype;
7027 if (tok != ':') {
7028 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
7029 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
7030 expect("identifier");
7031 if ((type1.t & VT_BTYPE) == VT_FUNC ||
7032 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
7033 error("invalid type for '%s'",
7034 get_tok_str(v, NULL));
7036 if (tok == ':') {
7037 next();
7038 bit_size = expr_const();
7039 /* XXX: handle v = 0 case for messages */
7040 if (bit_size < 0)
7041 error("negative width in bit-field '%s'",
7042 get_tok_str(v, NULL));
7043 if (v && bit_size == 0)
7044 error("zero width for bit-field '%s'",
7045 get_tok_str(v, NULL));
7047 size = type_size(&type1, &align);
7048 if (ad.aligned) {
7049 if (align < ad.aligned)
7050 align = ad.aligned;
7051 } else if (ad.packed) {
7052 align = 1;
7053 } else if (*tcc_state->pack_stack_ptr) {
7054 if (align > *tcc_state->pack_stack_ptr)
7055 align = *tcc_state->pack_stack_ptr;
7057 lbit_pos = 0;
7058 if (bit_size >= 0) {
7059 bt = type1.t & VT_BTYPE;
7060 if (bt != VT_INT &&
7061 bt != VT_BYTE &&
7062 bt != VT_SHORT &&
7063 bt != VT_BOOL &&
7064 bt != VT_ENUM &&
7065 bt != VT_LLONG)
7066 error("bitfields must have scalar type");
7067 bsize = size * 8;
7068 if (bit_size > bsize) {
7069 error("width of '%s' exceeds its type",
7070 get_tok_str(v, NULL));
7071 } else if (bit_size == bsize) {
7072 /* no need for bit fields */
7073 bit_pos = 0;
7074 } else if (bit_size == 0) {
7075 /* XXX: what to do if only padding in a
7076 structure ? */
7077 /* zero size: means to pad */
7078 bit_pos = 0;
7079 } else {
7080 /* we do not have enough room ?
7081 did the type change?
7082 is it a union? */
7083 if ((bit_pos + bit_size) > bsize ||
7084 bt != prevbt || a == TOK_UNION)
7085 bit_pos = 0;
7086 lbit_pos = bit_pos;
7087 /* XXX: handle LSB first */
7088 type1.t |= VT_BITFIELD |
7089 (bit_pos << VT_STRUCT_SHIFT) |
7090 (bit_size << (VT_STRUCT_SHIFT + 6));
7091 bit_pos += bit_size;
7093 prevbt = bt;
7094 } else {
7095 bit_pos = 0;
7097 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
7098 /* add new memory data only if starting
7099 bit field */
7100 if (lbit_pos == 0) {
7101 if (a == TOK_STRUCT) {
7102 c = (c + align - 1) & -align;
7103 offset = c;
7104 if (size > 0)
7105 c += size;
7106 } else {
7107 offset = 0;
7108 if (size > c)
7109 c = size;
7111 if (align > maxalign)
7112 maxalign = align;
7114 #if 0
7115 printf("add field %s offset=%d",
7116 get_tok_str(v, NULL), offset);
7117 if (type1.t & VT_BITFIELD) {
7118 printf(" pos=%d size=%d",
7119 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
7120 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
7122 printf("\n");
7123 #endif
7125 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
7126 ass = type1.ref;
7127 while ((ass = ass->next) != NULL) {
7128 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
7129 *ps = ss;
7130 ps = &ss->next;
7132 } else if (v) {
7133 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
7134 *ps = ss;
7135 ps = &ss->next;
7137 if (tok == ';' || tok == TOK_EOF)
7138 break;
7139 skip(',');
7141 skip(';');
7143 skip('}');
7144 /* store size and alignment */
7145 s->c = (c + maxalign - 1) & -maxalign;
7146 s->r = maxalign;
7151 /* return 0 if no type declaration. otherwise, return the basic type
7152 and skip it.
7154 static int parse_btype(CType *type, AttributeDef *ad)
7156 int t, u, type_found, typespec_found, typedef_found;
7157 Sym *s;
7158 CType type1;
7160 memset(ad, 0, sizeof(AttributeDef));
7161 type_found = 0;
7162 typespec_found = 0;
7163 typedef_found = 0;
7164 t = 0;
7165 while(1) {
7166 switch(tok) {
7167 case TOK_EXTENSION:
7168 /* currently, we really ignore extension */
7169 next();
7170 continue;
7172 /* basic types */
7173 case TOK_CHAR:
7174 u = VT_BYTE;
7175 basic_type:
7176 next();
7177 basic_type1:
7178 if ((t & VT_BTYPE) != 0)
7179 error("too many basic types");
7180 t |= u;
7181 typespec_found = 1;
7182 break;
7183 case TOK_VOID:
7184 u = VT_VOID;
7185 goto basic_type;
7186 case TOK_SHORT:
7187 u = VT_SHORT;
7188 goto basic_type;
7189 case TOK_INT:
7190 next();
7191 typespec_found = 1;
7192 break;
7193 case TOK_LONG:
7194 next();
7195 if ((t & VT_BTYPE) == VT_DOUBLE) {
7196 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
7197 } else if ((t & VT_BTYPE) == VT_LONG) {
7198 t = (t & ~VT_BTYPE) | VT_LLONG;
7199 } else {
7200 u = VT_LONG;
7201 goto basic_type1;
7203 break;
7204 case TOK_BOOL:
7205 u = VT_BOOL;
7206 goto basic_type;
7207 case TOK_FLOAT:
7208 u = VT_FLOAT;
7209 goto basic_type;
7210 case TOK_DOUBLE:
7211 next();
7212 if ((t & VT_BTYPE) == VT_LONG) {
7213 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
7214 } else {
7215 u = VT_DOUBLE;
7216 goto basic_type1;
7218 break;
7219 case TOK_ENUM:
7220 struct_decl(&type1, VT_ENUM);
7221 basic_type2:
7222 u = type1.t;
7223 type->ref = type1.ref;
7224 goto basic_type1;
7225 case TOK_STRUCT:
7226 case TOK_UNION:
7227 struct_decl(&type1, VT_STRUCT);
7228 goto basic_type2;
7230 /* type modifiers */
7231 case TOK_CONST1:
7232 case TOK_CONST2:
7233 case TOK_CONST3:
7234 t |= VT_CONSTANT;
7235 next();
7236 break;
7237 case TOK_VOLATILE1:
7238 case TOK_VOLATILE2:
7239 case TOK_VOLATILE3:
7240 t |= VT_VOLATILE;
7241 next();
7242 break;
7243 case TOK_SIGNED1:
7244 case TOK_SIGNED2:
7245 case TOK_SIGNED3:
7246 typespec_found = 1;
7247 t |= VT_SIGNED;
7248 next();
7249 break;
7250 case TOK_REGISTER:
7251 case TOK_AUTO:
7252 case TOK_RESTRICT1:
7253 case TOK_RESTRICT2:
7254 case TOK_RESTRICT3:
7255 next();
7256 break;
7257 case TOK_UNSIGNED:
7258 t |= VT_UNSIGNED;
7259 next();
7260 typespec_found = 1;
7261 break;
7263 /* storage */
7264 case TOK_EXTERN:
7265 t |= VT_EXTERN;
7266 next();
7267 break;
7268 case TOK_STATIC:
7269 t |= VT_STATIC;
7270 next();
7271 break;
7272 case TOK_TYPEDEF:
7273 t |= VT_TYPEDEF;
7274 next();
7275 break;
7276 case TOK_INLINE1:
7277 case TOK_INLINE2:
7278 case TOK_INLINE3:
7279 t |= VT_INLINE;
7280 next();
7281 break;
7283 /* GNUC attribute */
7284 case TOK_ATTRIBUTE1:
7285 case TOK_ATTRIBUTE2:
7286 parse_attribute(ad);
7287 break;
7288 /* GNUC typeof */
7289 case TOK_TYPEOF1:
7290 case TOK_TYPEOF2:
7291 case TOK_TYPEOF3:
7292 next();
7293 parse_expr_type(&type1);
7294 goto basic_type2;
7295 default:
7296 if (typespec_found || typedef_found)
7297 goto the_end;
7298 s = sym_find(tok);
7299 if (!s || !(s->type.t & VT_TYPEDEF))
7300 goto the_end;
7301 typedef_found = 1;
7302 t |= (s->type.t & ~VT_TYPEDEF);
7303 type->ref = s->type.ref;
7304 next();
7305 typespec_found = 1;
7306 break;
7308 type_found = 1;
7310 the_end:
7311 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
7312 error("signed and unsigned modifier");
7313 if (tcc_state->char_is_unsigned) {
7314 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
7315 t |= VT_UNSIGNED;
7317 t &= ~VT_SIGNED;
7319 /* long is never used as type */
7320 if ((t & VT_BTYPE) == VT_LONG)
7321 #ifndef TCC_TARGET_X86_64
7322 t = (t & ~VT_BTYPE) | VT_INT;
7323 #else
7324 t = (t & ~VT_BTYPE) | VT_LLONG;
7325 #endif
7326 type->t = t;
7327 return type_found;
7330 /* convert a function parameter type (array to pointer and function to
7331 function pointer) */
7332 static inline void convert_parameter_type(CType *pt)
7334 /* remove const and volatile qualifiers (XXX: const could be used
7335 to indicate a const function parameter */
7336 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
7337 /* array must be transformed to pointer according to ANSI C */
7338 pt->t &= ~VT_ARRAY;
7339 if ((pt->t & VT_BTYPE) == VT_FUNC) {
7340 mk_pointer(pt);
7344 static void post_type(CType *type, AttributeDef *ad)
7346 int n, l, t1, arg_size, align;
7347 Sym **plast, *s, *first;
7348 AttributeDef ad1;
7349 CType pt;
7351 if (tok == '(') {
7352 /* function declaration */
7353 next();
7354 l = 0;
7355 first = NULL;
7356 plast = &first;
7357 arg_size = 0;
7358 if (tok != ')') {
7359 for(;;) {
7360 /* read param name and compute offset */
7361 if (l != FUNC_OLD) {
7362 if (!parse_btype(&pt, &ad1)) {
7363 if (l) {
7364 error("invalid type");
7365 } else {
7366 l = FUNC_OLD;
7367 goto old_proto;
7370 l = FUNC_NEW;
7371 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
7372 break;
7373 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
7374 if ((pt.t & VT_BTYPE) == VT_VOID)
7375 error("parameter declared as void");
7376 arg_size += (type_size(&pt, &align) + 3) & ~3;
7377 } else {
7378 old_proto:
7379 n = tok;
7380 if (n < TOK_UIDENT)
7381 expect("identifier");
7382 pt.t = VT_INT;
7383 next();
7385 convert_parameter_type(&pt);
7386 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
7387 *plast = s;
7388 plast = &s->next;
7389 if (tok == ')')
7390 break;
7391 skip(',');
7392 if (l == FUNC_NEW && tok == TOK_DOTS) {
7393 l = FUNC_ELLIPSIS;
7394 next();
7395 break;
7399 /* if no parameters, then old type prototype */
7400 if (l == 0)
7401 l = FUNC_OLD;
7402 skip(')');
7403 t1 = type->t & VT_STORAGE;
7404 /* NOTE: const is ignored in returned type as it has a special
7405 meaning in gcc / C++ */
7406 type->t &= ~(VT_STORAGE | VT_CONSTANT);
7407 post_type(type, ad);
7408 /* we push a anonymous symbol which will contain the function prototype */
7409 FUNC_ARGS(ad->func_attr) = arg_size;
7410 s = sym_push(SYM_FIELD, type, ad->func_attr, l);
7411 s->next = first;
7412 type->t = t1 | VT_FUNC;
7413 type->ref = s;
7414 } else if (tok == '[') {
7415 /* array definition */
7416 next();
7417 if (tok == TOK_RESTRICT1)
7418 next();
7419 n = -1;
7420 if (tok != ']') {
7421 n = expr_const();
7422 if (n < 0)
7423 error("invalid array size");
7425 skip(']');
7426 /* parse next post type */
7427 t1 = type->t & VT_STORAGE;
7428 type->t &= ~VT_STORAGE;
7429 post_type(type, ad);
7431 /* we push a anonymous symbol which will contain the array
7432 element type */
7433 s = sym_push(SYM_FIELD, type, 0, n);
7434 type->t = t1 | VT_ARRAY | VT_PTR;
7435 type->ref = s;
7439 /* Parse a type declaration (except basic type), and return the type
7440 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7441 expected. 'type' should contain the basic type. 'ad' is the
7442 attribute definition of the basic type. It can be modified by
7443 type_decl().
7445 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7447 Sym *s;
7448 CType type1, *type2;
7449 int qualifiers;
7451 while (tok == '*') {
7452 qualifiers = 0;
7453 redo:
7454 next();
7455 switch(tok) {
7456 case TOK_CONST1:
7457 case TOK_CONST2:
7458 case TOK_CONST3:
7459 qualifiers |= VT_CONSTANT;
7460 goto redo;
7461 case TOK_VOLATILE1:
7462 case TOK_VOLATILE2:
7463 case TOK_VOLATILE3:
7464 qualifiers |= VT_VOLATILE;
7465 goto redo;
7466 case TOK_RESTRICT1:
7467 case TOK_RESTRICT2:
7468 case TOK_RESTRICT3:
7469 goto redo;
7471 mk_pointer(type);
7472 type->t |= qualifiers;
7475 /* XXX: clarify attribute handling */
7476 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7477 parse_attribute(ad);
7479 /* recursive type */
7480 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7481 type1.t = 0; /* XXX: same as int */
7482 if (tok == '(') {
7483 next();
7484 /* XXX: this is not correct to modify 'ad' at this point, but
7485 the syntax is not clear */
7486 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7487 parse_attribute(ad);
7488 type_decl(&type1, ad, v, td);
7489 skip(')');
7490 } else {
7491 /* type identifier */
7492 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7493 *v = tok;
7494 next();
7495 } else {
7496 if (!(td & TYPE_ABSTRACT))
7497 expect("identifier");
7498 *v = 0;
7501 post_type(type, ad);
7502 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7503 parse_attribute(ad);
7504 if (!type1.t)
7505 return;
7506 /* append type at the end of type1 */
7507 type2 = &type1;
7508 for(;;) {
7509 s = type2->ref;
7510 type2 = &s->type;
7511 if (!type2->t) {
7512 *type2 = *type;
7513 break;
7516 *type = type1;
7519 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7520 static int lvalue_type(int t)
7522 int bt, r;
7523 r = VT_LVAL;
7524 bt = t & VT_BTYPE;
7525 if (bt == VT_BYTE || bt == VT_BOOL)
7526 r |= VT_LVAL_BYTE;
7527 else if (bt == VT_SHORT)
7528 r |= VT_LVAL_SHORT;
7529 else
7530 return r;
7531 if (t & VT_UNSIGNED)
7532 r |= VT_LVAL_UNSIGNED;
7533 return r;
7536 /* indirection with full error checking and bound check */
7537 static void indir(void)
7539 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7540 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7541 return;
7542 expect("pointer");
7544 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7545 gv(RC_INT);
7546 vtop->type = *pointed_type(&vtop->type);
7547 /* Arrays and functions are never lvalues */
7548 if (!(vtop->type.t & VT_ARRAY)
7549 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7550 vtop->r |= lvalue_type(vtop->type.t);
7551 /* if bound checking, the referenced pointer must be checked */
7552 if (do_bounds_check)
7553 vtop->r |= VT_MUSTBOUND;
7557 /* pass a parameter to a function and do type checking and casting */
7558 static void gfunc_param_typed(Sym *func, Sym *arg)
7560 int func_type;
7561 CType type;
7563 func_type = func->c;
7564 if (func_type == FUNC_OLD ||
7565 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7566 /* default casting : only need to convert float to double */
7567 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7568 type.t = VT_DOUBLE;
7569 gen_cast(&type);
7571 } else if (arg == NULL) {
7572 error("too many arguments to function");
7573 } else {
7574 type = arg->type;
7575 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7576 gen_assign_cast(&type);
7580 /* parse an expression of the form '(type)' or '(expr)' and return its
7581 type */
7582 static void parse_expr_type(CType *type)
7584 int n;
7585 AttributeDef ad;
7587 skip('(');
7588 if (parse_btype(type, &ad)) {
7589 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7590 } else {
7591 expr_type(type);
7593 skip(')');
7596 static void parse_type(CType *type)
7598 AttributeDef ad;
7599 int n;
7601 if (!parse_btype(type, &ad)) {
7602 expect("type");
7604 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7607 static void vpush_tokc(int t)
7609 CType type;
7610 type.t = t;
7611 vsetc(&type, VT_CONST, &tokc);
7614 static void unary(void)
7616 int n, t, align, size, r;
7617 CType type;
7618 Sym *s;
7619 AttributeDef ad;
7621 /* XXX: GCC 2.95.3 does not generate a table although it should be
7622 better here */
7623 tok_next:
7624 switch(tok) {
7625 case TOK_EXTENSION:
7626 next();
7627 goto tok_next;
7628 case TOK_CINT:
7629 case TOK_CCHAR:
7630 case TOK_LCHAR:
7631 vpushi(tokc.i);
7632 next();
7633 break;
7634 case TOK_CUINT:
7635 vpush_tokc(VT_INT | VT_UNSIGNED);
7636 next();
7637 break;
7638 case TOK_CLLONG:
7639 vpush_tokc(VT_LLONG);
7640 next();
7641 break;
7642 case TOK_CULLONG:
7643 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7644 next();
7645 break;
7646 case TOK_CFLOAT:
7647 vpush_tokc(VT_FLOAT);
7648 next();
7649 break;
7650 case TOK_CDOUBLE:
7651 vpush_tokc(VT_DOUBLE);
7652 next();
7653 break;
7654 case TOK_CLDOUBLE:
7655 vpush_tokc(VT_LDOUBLE);
7656 next();
7657 break;
7658 case TOK___FUNCTION__:
7659 if (!gnu_ext)
7660 goto tok_identifier;
7661 /* fall thru */
7662 case TOK___FUNC__:
7664 void *ptr;
7665 int len;
7666 /* special function name identifier */
7667 len = strlen(funcname) + 1;
7668 /* generate char[len] type */
7669 type.t = VT_BYTE;
7670 mk_pointer(&type);
7671 type.t |= VT_ARRAY;
7672 type.ref->c = len;
7673 vpush_ref(&type, data_section, data_section->data_offset, len);
7674 ptr = section_ptr_add(data_section, len);
7675 memcpy(ptr, funcname, len);
7676 next();
7678 break;
7679 case TOK_LSTR:
7680 #ifdef TCC_TARGET_PE
7681 t = VT_SHORT | VT_UNSIGNED;
7682 #else
7683 t = VT_INT;
7684 #endif
7685 goto str_init;
7686 case TOK_STR:
7687 /* string parsing */
7688 t = VT_BYTE;
7689 str_init:
7690 if (tcc_state->warn_write_strings)
7691 t |= VT_CONSTANT;
7692 type.t = t;
7693 mk_pointer(&type);
7694 type.t |= VT_ARRAY;
7695 memset(&ad, 0, sizeof(AttributeDef));
7696 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7697 break;
7698 case '(':
7699 next();
7700 /* cast ? */
7701 if (parse_btype(&type, &ad)) {
7702 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7703 skip(')');
7704 /* check ISOC99 compound literal */
7705 if (tok == '{') {
7706 /* data is allocated locally by default */
7707 if (global_expr)
7708 r = VT_CONST;
7709 else
7710 r = VT_LOCAL;
7711 /* all except arrays are lvalues */
7712 if (!(type.t & VT_ARRAY))
7713 r |= lvalue_type(type.t);
7714 memset(&ad, 0, sizeof(AttributeDef));
7715 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7716 } else {
7717 unary();
7718 gen_cast(&type);
7720 } else if (tok == '{') {
7721 /* save all registers */
7722 save_regs(0);
7723 /* statement expression : we do not accept break/continue
7724 inside as GCC does */
7725 block(NULL, NULL, NULL, NULL, 0, 1);
7726 skip(')');
7727 } else {
7728 gexpr();
7729 skip(')');
7731 break;
7732 case '*':
7733 next();
7734 unary();
7735 indir();
7736 break;
7737 case '&':
7738 next();
7739 unary();
7740 /* functions names must be treated as function pointers,
7741 except for unary '&' and sizeof. Since we consider that
7742 functions are not lvalues, we only have to handle it
7743 there and in function calls. */
7744 /* arrays can also be used although they are not lvalues */
7745 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7746 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7747 test_lvalue();
7748 mk_pointer(&vtop->type);
7749 gaddrof();
7750 break;
7751 case '!':
7752 next();
7753 unary();
7754 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
7755 CType boolean;
7756 boolean.t = VT_BOOL;
7757 gen_cast(&boolean);
7758 vtop->c.i = !vtop->c.i;
7759 } else if ((vtop->r & VT_VALMASK) == VT_CMP)
7760 vtop->c.i = vtop->c.i ^ 1;
7761 else {
7762 save_regs(1);
7763 vseti(VT_JMP, gtst(1, 0));
7765 break;
7766 case '~':
7767 next();
7768 unary();
7769 vpushi(-1);
7770 gen_op('^');
7771 break;
7772 case '+':
7773 next();
7774 /* in order to force cast, we add zero */
7775 unary();
7776 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7777 error("pointer not accepted for unary plus");
7778 vpushi(0);
7779 gen_op('+');
7780 break;
7781 case TOK_SIZEOF:
7782 case TOK_ALIGNOF1:
7783 case TOK_ALIGNOF2:
7784 t = tok;
7785 next();
7786 if (tok == '(') {
7787 parse_expr_type(&type);
7788 } else {
7789 unary_type(&type);
7791 size = type_size(&type, &align);
7792 if (t == TOK_SIZEOF) {
7793 if (size < 0)
7794 error("sizeof applied to an incomplete type");
7795 vpushi(size);
7796 } else {
7797 vpushi(align);
7799 vtop->type.t |= VT_UNSIGNED;
7800 break;
7802 case TOK_builtin_types_compatible_p:
7804 CType type1, type2;
7805 next();
7806 skip('(');
7807 parse_type(&type1);
7808 skip(',');
7809 parse_type(&type2);
7810 skip(')');
7811 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7812 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7813 vpushi(is_compatible_types(&type1, &type2));
7815 break;
7816 case TOK_builtin_constant_p:
7818 int saved_nocode_wanted, res;
7819 next();
7820 skip('(');
7821 saved_nocode_wanted = nocode_wanted;
7822 nocode_wanted = 1;
7823 gexpr();
7824 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7825 vpop();
7826 nocode_wanted = saved_nocode_wanted;
7827 skip(')');
7828 vpushi(res);
7830 break;
7831 case TOK_builtin_frame_address:
7833 CType type;
7834 next();
7835 skip('(');
7836 if (tok != TOK_CINT) {
7837 error("__builtin_frame_address only takes integers");
7839 if (tokc.i != 0) {
7840 error("TCC only supports __builtin_frame_address(0)");
7842 next();
7843 skip(')');
7844 type.t = VT_VOID;
7845 mk_pointer(&type);
7846 vset(&type, VT_LOCAL, 0);
7848 break;
7849 #ifdef TCC_TARGET_X86_64
7850 case TOK_builtin_malloc:
7851 tok = TOK_malloc;
7852 goto tok_identifier;
7853 case TOK_builtin_free:
7854 tok = TOK_free;
7855 goto tok_identifier;
7856 #endif
7857 case TOK_INC:
7858 case TOK_DEC:
7859 t = tok;
7860 next();
7861 unary();
7862 inc(0, t);
7863 break;
7864 case '-':
7865 next();
7866 vpushi(0);
7867 unary();
7868 gen_op('-');
7869 break;
7870 case TOK_LAND:
7871 if (!gnu_ext)
7872 goto tok_identifier;
7873 next();
7874 /* allow to take the address of a label */
7875 if (tok < TOK_UIDENT)
7876 expect("label identifier");
7877 s = label_find(tok);
7878 if (!s) {
7879 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7880 } else {
7881 if (s->r == LABEL_DECLARED)
7882 s->r = LABEL_FORWARD;
7884 if (!s->type.t) {
7885 s->type.t = VT_VOID;
7886 mk_pointer(&s->type);
7887 s->type.t |= VT_STATIC;
7889 vset(&s->type, VT_CONST | VT_SYM, 0);
7890 vtop->sym = s;
7891 next();
7892 break;
7893 default:
7894 tok_identifier:
7895 t = tok;
7896 next();
7897 if (t < TOK_UIDENT)
7898 expect("identifier");
7899 s = sym_find(t);
7900 if (!s) {
7901 if (tok != '(')
7902 error("'%s' undeclared", get_tok_str(t, NULL));
7903 /* for simple function calls, we tolerate undeclared
7904 external reference to int() function */
7905 if (tcc_state->warn_implicit_function_declaration)
7906 warning("implicit declaration of function '%s'",
7907 get_tok_str(t, NULL));
7908 s = external_global_sym(t, &func_old_type, 0);
7910 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7911 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7912 /* if referencing an inline function, then we generate a
7913 symbol to it if not already done. It will have the
7914 effect to generate code for it at the end of the
7915 compilation unit. Inline function as always
7916 generated in the text section. */
7917 if (!s->c)
7918 put_extern_sym(s, text_section, 0, 0);
7919 r = VT_SYM | VT_CONST;
7920 } else {
7921 r = s->r;
7923 vset(&s->type, r, s->c);
7924 /* if forward reference, we must point to s */
7925 if (vtop->r & VT_SYM) {
7926 vtop->sym = s;
7927 vtop->c.ul = 0;
7929 break;
7932 /* post operations */
7933 while (1) {
7934 if (tok == TOK_INC || tok == TOK_DEC) {
7935 inc(1, tok);
7936 next();
7937 } else if (tok == '.' || tok == TOK_ARROW) {
7938 /* field */
7939 if (tok == TOK_ARROW)
7940 indir();
7941 test_lvalue();
7942 gaddrof();
7943 next();
7944 /* expect pointer on structure */
7945 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7946 expect("struct or union");
7947 s = vtop->type.ref;
7948 /* find field */
7949 tok |= SYM_FIELD;
7950 while ((s = s->next) != NULL) {
7951 if (s->v == tok)
7952 break;
7954 if (!s)
7955 error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL));
7956 /* add field offset to pointer */
7957 vtop->type = char_pointer_type; /* change type to 'char *' */
7958 vpushi(s->c);
7959 gen_op('+');
7960 /* change type to field type, and set to lvalue */
7961 vtop->type = s->type;
7962 /* an array is never an lvalue */
7963 if (!(vtop->type.t & VT_ARRAY)) {
7964 vtop->r |= lvalue_type(vtop->type.t);
7965 /* if bound checking, the referenced pointer must be checked */
7966 if (do_bounds_check)
7967 vtop->r |= VT_MUSTBOUND;
7969 next();
7970 } else if (tok == '[') {
7971 next();
7972 gexpr();
7973 gen_op('+');
7974 indir();
7975 skip(']');
7976 } else if (tok == '(') {
7977 SValue ret;
7978 Sym *sa;
7979 int nb_args;
7981 /* function call */
7982 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7983 /* pointer test (no array accepted) */
7984 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7985 vtop->type = *pointed_type(&vtop->type);
7986 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7987 goto error_func;
7988 } else {
7989 error_func:
7990 expect("function pointer");
7992 } else {
7993 vtop->r &= ~VT_LVAL; /* no lvalue */
7995 /* get return type */
7996 s = vtop->type.ref;
7997 next();
7998 sa = s->next; /* first parameter */
7999 nb_args = 0;
8000 ret.r2 = VT_CONST;
8001 /* compute first implicit argument if a structure is returned */
8002 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
8003 /* get some space for the returned structure */
8004 size = type_size(&s->type, &align);
8005 loc = (loc - size) & -align;
8006 ret.type = s->type;
8007 ret.r = VT_LOCAL | VT_LVAL;
8008 /* pass it as 'int' to avoid structure arg passing
8009 problems */
8010 vseti(VT_LOCAL, loc);
8011 ret.c = vtop->c;
8012 nb_args++;
8013 } else {
8014 ret.type = s->type;
8015 /* return in register */
8016 if (is_float(ret.type.t)) {
8017 ret.r = reg_fret(ret.type.t);
8018 } else {
8019 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
8020 ret.r2 = REG_LRET;
8021 ret.r = REG_IRET;
8023 ret.c.i = 0;
8025 if (tok != ')') {
8026 for(;;) {
8027 expr_eq();
8028 gfunc_param_typed(s, sa);
8029 nb_args++;
8030 if (sa)
8031 sa = sa->next;
8032 if (tok == ')')
8033 break;
8034 skip(',');
8037 if (sa)
8038 error("too few arguments to function");
8039 skip(')');
8040 if (!nocode_wanted) {
8041 gfunc_call(nb_args);
8042 } else {
8043 vtop -= (nb_args + 1);
8045 /* return value */
8046 vsetc(&ret.type, ret.r, &ret.c);
8047 vtop->r2 = ret.r2;
8048 } else {
8049 break;
8054 static void uneq(void)
8056 int t;
8058 unary();
8059 if (tok == '=' ||
8060 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
8061 tok == TOK_A_XOR || tok == TOK_A_OR ||
8062 tok == TOK_A_SHL || tok == TOK_A_SAR) {
8063 test_lvalue();
8064 t = tok;
8065 next();
8066 if (t == '=') {
8067 expr_eq();
8068 } else {
8069 vdup();
8070 expr_eq();
8071 gen_op(t & 0x7f);
8073 vstore();
8077 static void expr_prod(void)
8079 int t;
8081 uneq();
8082 while (tok == '*' || tok == '/' || tok == '%') {
8083 t = tok;
8084 next();
8085 uneq();
8086 gen_op(t);
8090 static void expr_sum(void)
8092 int t;
8094 expr_prod();
8095 while (tok == '+' || tok == '-') {
8096 t = tok;
8097 next();
8098 expr_prod();
8099 gen_op(t);
8103 static void expr_shift(void)
8105 int t;
8107 expr_sum();
8108 while (tok == TOK_SHL || tok == TOK_SAR) {
8109 t = tok;
8110 next();
8111 expr_sum();
8112 gen_op(t);
8116 static void expr_cmp(void)
8118 int t;
8120 expr_shift();
8121 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
8122 tok == TOK_ULT || tok == TOK_UGE) {
8123 t = tok;
8124 next();
8125 expr_shift();
8126 gen_op(t);
8130 static void expr_cmpeq(void)
8132 int t;
8134 expr_cmp();
8135 while (tok == TOK_EQ || tok == TOK_NE) {
8136 t = tok;
8137 next();
8138 expr_cmp();
8139 gen_op(t);
8143 static void expr_and(void)
8145 expr_cmpeq();
8146 while (tok == '&') {
8147 next();
8148 expr_cmpeq();
8149 gen_op('&');
8153 static void expr_xor(void)
8155 expr_and();
8156 while (tok == '^') {
8157 next();
8158 expr_and();
8159 gen_op('^');
8163 static void expr_or(void)
8165 expr_xor();
8166 while (tok == '|') {
8167 next();
8168 expr_xor();
8169 gen_op('|');
8173 /* XXX: fix this mess */
8174 static void expr_land_const(void)
8176 expr_or();
8177 while (tok == TOK_LAND) {
8178 next();
8179 expr_or();
8180 gen_op(TOK_LAND);
8184 /* XXX: fix this mess */
8185 static void expr_lor_const(void)
8187 expr_land_const();
8188 while (tok == TOK_LOR) {
8189 next();
8190 expr_land_const();
8191 gen_op(TOK_LOR);
8195 /* only used if non constant */
8196 static void expr_land(void)
8198 int t;
8200 expr_or();
8201 if (tok == TOK_LAND) {
8202 t = 0;
8203 save_regs(1);
8204 for(;;) {
8205 t = gtst(1, t);
8206 if (tok != TOK_LAND) {
8207 vseti(VT_JMPI, t);
8208 break;
8210 next();
8211 expr_or();
8216 static void expr_lor(void)
8218 int t;
8220 expr_land();
8221 if (tok == TOK_LOR) {
8222 t = 0;
8223 save_regs(1);
8224 for(;;) {
8225 t = gtst(0, t);
8226 if (tok != TOK_LOR) {
8227 vseti(VT_JMP, t);
8228 break;
8230 next();
8231 expr_land();
8236 /* XXX: better constant handling */
8237 static void expr_eq(void)
8239 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
8240 SValue sv;
8241 CType type, type1, type2;
8243 if (const_wanted) {
8244 expr_lor_const();
8245 if (tok == '?') {
8246 CType boolean;
8247 int c;
8248 boolean.t = VT_BOOL;
8249 vdup();
8250 gen_cast(&boolean);
8251 c = vtop->c.i;
8252 vpop();
8253 next();
8254 if (tok != ':' || !gnu_ext) {
8255 vpop();
8256 gexpr();
8258 if (!c)
8259 vpop();
8260 skip(':');
8261 expr_eq();
8262 if (c)
8263 vpop();
8265 } else {
8266 expr_lor();
8267 if (tok == '?') {
8268 next();
8269 if (vtop != vstack) {
8270 /* needed to avoid having different registers saved in
8271 each branch */
8272 if (is_float(vtop->type.t)) {
8273 rc = RC_FLOAT;
8274 #ifdef TCC_TARGET_X86_64
8275 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
8276 rc = RC_ST0;
8278 #endif
8280 else
8281 rc = RC_INT;
8282 gv(rc);
8283 save_regs(1);
8285 if (tok == ':' && gnu_ext) {
8286 gv_dup();
8287 tt = gtst(1, 0);
8288 } else {
8289 tt = gtst(1, 0);
8290 gexpr();
8292 type1 = vtop->type;
8293 sv = *vtop; /* save value to handle it later */
8294 vtop--; /* no vpop so that FP stack is not flushed */
8295 skip(':');
8296 u = gjmp(0);
8297 gsym(tt);
8298 expr_eq();
8299 type2 = vtop->type;
8301 t1 = type1.t;
8302 bt1 = t1 & VT_BTYPE;
8303 t2 = type2.t;
8304 bt2 = t2 & VT_BTYPE;
8305 /* cast operands to correct type according to ISOC rules */
8306 if (is_float(bt1) || is_float(bt2)) {
8307 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
8308 type.t = VT_LDOUBLE;
8309 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
8310 type.t = VT_DOUBLE;
8311 } else {
8312 type.t = VT_FLOAT;
8314 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
8315 /* cast to biggest op */
8316 type.t = VT_LLONG;
8317 /* convert to unsigned if it does not fit in a long long */
8318 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
8319 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
8320 type.t |= VT_UNSIGNED;
8321 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
8322 /* XXX: test pointer compatibility */
8323 type = type1;
8324 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
8325 /* XXX: test function pointer compatibility */
8326 type = type1;
8327 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
8328 /* XXX: test structure compatibility */
8329 type = type1;
8330 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
8331 /* NOTE: as an extension, we accept void on only one side */
8332 type.t = VT_VOID;
8333 } else {
8334 /* integer operations */
8335 type.t = VT_INT;
8336 /* convert to unsigned if it does not fit in an integer */
8337 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
8338 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
8339 type.t |= VT_UNSIGNED;
8342 /* now we convert second operand */
8343 gen_cast(&type);
8344 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8345 gaddrof();
8346 rc = RC_INT;
8347 if (is_float(type.t)) {
8348 rc = RC_FLOAT;
8349 #ifdef TCC_TARGET_X86_64
8350 if ((type.t & VT_BTYPE) == VT_LDOUBLE) {
8351 rc = RC_ST0;
8353 #endif
8354 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
8355 /* for long longs, we use fixed registers to avoid having
8356 to handle a complicated move */
8357 rc = RC_IRET;
8360 r2 = gv(rc);
8361 /* this is horrible, but we must also convert first
8362 operand */
8363 tt = gjmp(0);
8364 gsym(u);
8365 /* put again first value and cast it */
8366 *vtop = sv;
8367 gen_cast(&type);
8368 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8369 gaddrof();
8370 r1 = gv(rc);
8371 move_reg(r2, r1);
8372 vtop->r = r2;
8373 gsym(tt);
8378 static void gexpr(void)
8380 while (1) {
8381 expr_eq();
8382 if (tok != ',')
8383 break;
8384 vpop();
8385 next();
8389 /* parse an expression and return its type without any side effect. */
8390 static void expr_type(CType *type)
8392 int saved_nocode_wanted;
8394 saved_nocode_wanted = nocode_wanted;
8395 nocode_wanted = 1;
8396 gexpr();
8397 *type = vtop->type;
8398 vpop();
8399 nocode_wanted = saved_nocode_wanted;
8402 /* parse a unary expression and return its type without any side
8403 effect. */
8404 static void unary_type(CType *type)
8406 int a;
8408 a = nocode_wanted;
8409 nocode_wanted = 1;
8410 unary();
8411 *type = vtop->type;
8412 vpop();
8413 nocode_wanted = a;
8416 /* parse a constant expression and return value in vtop. */
8417 static void expr_const1(void)
8419 int a;
8420 a = const_wanted;
8421 const_wanted = 1;
8422 expr_eq();
8423 const_wanted = a;
8426 /* parse an integer constant and return its value. */
8427 static int expr_const(void)
8429 int c;
8430 expr_const1();
8431 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8432 expect("constant expression");
8433 c = vtop->c.i;
8434 vpop();
8435 return c;
8438 /* return the label token if current token is a label, otherwise
8439 return zero */
8440 static int is_label(void)
8442 int last_tok;
8444 /* fast test first */
8445 if (tok < TOK_UIDENT)
8446 return 0;
8447 /* no need to save tokc because tok is an identifier */
8448 last_tok = tok;
8449 next();
8450 if (tok == ':') {
8451 next();
8452 return last_tok;
8453 } else {
8454 unget_tok(last_tok);
8455 return 0;
8459 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8460 int case_reg, int is_expr)
8462 int a, b, c, d;
8463 Sym *s;
8465 /* generate line number info */
8466 if (do_debug &&
8467 (last_line_num != file->line_num || last_ind != ind)) {
8468 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8469 last_ind = ind;
8470 last_line_num = file->line_num;
8473 if (is_expr) {
8474 /* default return value is (void) */
8475 vpushi(0);
8476 vtop->type.t = VT_VOID;
8479 if (tok == TOK_IF) {
8480 /* if test */
8481 next();
8482 skip('(');
8483 gexpr();
8484 skip(')');
8485 a = gtst(1, 0);
8486 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8487 c = tok;
8488 if (c == TOK_ELSE) {
8489 next();
8490 d = gjmp(0);
8491 gsym(a);
8492 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8493 gsym(d); /* patch else jmp */
8494 } else
8495 gsym(a);
8496 } else if (tok == TOK_WHILE) {
8497 next();
8498 d = ind;
8499 skip('(');
8500 gexpr();
8501 skip(')');
8502 a = gtst(1, 0);
8503 b = 0;
8504 block(&a, &b, case_sym, def_sym, case_reg, 0);
8505 gjmp_addr(d);
8506 gsym(a);
8507 gsym_addr(b, d);
8508 } else if (tok == '{') {
8509 Sym *llabel;
8511 next();
8512 /* record local declaration stack position */
8513 s = local_stack;
8514 llabel = local_label_stack;
8515 /* handle local labels declarations */
8516 if (tok == TOK_LABEL) {
8517 next();
8518 for(;;) {
8519 if (tok < TOK_UIDENT)
8520 expect("label identifier");
8521 label_push(&local_label_stack, tok, LABEL_DECLARED);
8522 next();
8523 if (tok == ',') {
8524 next();
8525 } else {
8526 skip(';');
8527 break;
8531 while (tok != '}') {
8532 decl(VT_LOCAL);
8533 if (tok != '}') {
8534 if (is_expr)
8535 vpop();
8536 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8539 /* pop locally defined labels */
8540 label_pop(&local_label_stack, llabel);
8541 /* pop locally defined symbols */
8542 if(is_expr) {
8543 /* XXX: this solution makes only valgrind happy...
8544 triggered by gcc.c-torture/execute/20000917-1.c */
8545 Sym *p;
8546 switch(vtop->type.t & VT_BTYPE) {
8547 case VT_PTR:
8548 case VT_STRUCT:
8549 case VT_ENUM:
8550 case VT_FUNC:
8551 for(p=vtop->type.ref;p;p=p->prev)
8552 if(p->prev==s)
8553 error("unsupported expression type");
8556 sym_pop(&local_stack, s);
8557 next();
8558 } else if (tok == TOK_RETURN) {
8559 next();
8560 if (tok != ';') {
8561 gexpr();
8562 gen_assign_cast(&func_vt);
8563 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8564 CType type;
8565 /* if returning structure, must copy it to implicit
8566 first pointer arg location */
8567 #ifdef TCC_ARM_EABI
8568 int align, size;
8569 size = type_size(&func_vt,&align);
8570 if(size <= 4)
8572 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8573 && (align & 3))
8575 int addr;
8576 loc = (loc - size) & -4;
8577 addr = loc;
8578 type = func_vt;
8579 vset(&type, VT_LOCAL | VT_LVAL, addr);
8580 vswap();
8581 vstore();
8582 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8584 vtop->type = int_type;
8585 gv(RC_IRET);
8586 } else {
8587 #endif
8588 type = func_vt;
8589 mk_pointer(&type);
8590 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8591 indir();
8592 vswap();
8593 /* copy structure value to pointer */
8594 vstore();
8595 #ifdef TCC_ARM_EABI
8597 #endif
8598 } else if (is_float(func_vt.t)) {
8599 gv(rc_fret(func_vt.t));
8600 } else {
8601 gv(RC_IRET);
8603 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8605 skip(';');
8606 rsym = gjmp(rsym); /* jmp */
8607 } else if (tok == TOK_BREAK) {
8608 /* compute jump */
8609 if (!bsym)
8610 error("cannot break");
8611 *bsym = gjmp(*bsym);
8612 next();
8613 skip(';');
8614 } else if (tok == TOK_CONTINUE) {
8615 /* compute jump */
8616 if (!csym)
8617 error("cannot continue");
8618 *csym = gjmp(*csym);
8619 next();
8620 skip(';');
8621 } else if (tok == TOK_FOR) {
8622 int e;
8623 next();
8624 skip('(');
8625 if (tok != ';') {
8626 gexpr();
8627 vpop();
8629 skip(';');
8630 d = ind;
8631 c = ind;
8632 a = 0;
8633 b = 0;
8634 if (tok != ';') {
8635 gexpr();
8636 a = gtst(1, 0);
8638 skip(';');
8639 if (tok != ')') {
8640 e = gjmp(0);
8641 c = ind;
8642 gexpr();
8643 vpop();
8644 gjmp_addr(d);
8645 gsym(e);
8647 skip(')');
8648 block(&a, &b, case_sym, def_sym, case_reg, 0);
8649 gjmp_addr(c);
8650 gsym(a);
8651 gsym_addr(b, c);
8652 } else
8653 if (tok == TOK_DO) {
8654 next();
8655 a = 0;
8656 b = 0;
8657 d = ind;
8658 block(&a, &b, case_sym, def_sym, case_reg, 0);
8659 skip(TOK_WHILE);
8660 skip('(');
8661 gsym(b);
8662 gexpr();
8663 c = gtst(0, 0);
8664 gsym_addr(c, d);
8665 skip(')');
8666 gsym(a);
8667 skip(';');
8668 } else
8669 if (tok == TOK_SWITCH) {
8670 next();
8671 skip('(');
8672 gexpr();
8673 /* XXX: other types than integer */
8674 case_reg = gv(RC_INT);
8675 vpop();
8676 skip(')');
8677 a = 0;
8678 b = gjmp(0); /* jump to first case */
8679 c = 0;
8680 block(&a, csym, &b, &c, case_reg, 0);
8681 /* if no default, jmp after switch */
8682 if (c == 0)
8683 c = ind;
8684 /* default label */
8685 gsym_addr(b, c);
8686 /* break label */
8687 gsym(a);
8688 } else
8689 if (tok == TOK_CASE) {
8690 int v1, v2;
8691 if (!case_sym)
8692 expect("switch");
8693 next();
8694 v1 = expr_const();
8695 v2 = v1;
8696 if (gnu_ext && tok == TOK_DOTS) {
8697 next();
8698 v2 = expr_const();
8699 if (v2 < v1)
8700 warning("empty case range");
8702 /* since a case is like a label, we must skip it with a jmp */
8703 b = gjmp(0);
8704 gsym(*case_sym);
8705 vseti(case_reg, 0);
8706 vpushi(v1);
8707 if (v1 == v2) {
8708 gen_op(TOK_EQ);
8709 *case_sym = gtst(1, 0);
8710 } else {
8711 gen_op(TOK_GE);
8712 *case_sym = gtst(1, 0);
8713 vseti(case_reg, 0);
8714 vpushi(v2);
8715 gen_op(TOK_LE);
8716 *case_sym = gtst(1, *case_sym);
8718 gsym(b);
8719 skip(':');
8720 is_expr = 0;
8721 goto block_after_label;
8722 } else
8723 if (tok == TOK_DEFAULT) {
8724 next();
8725 skip(':');
8726 if (!def_sym)
8727 expect("switch");
8728 if (*def_sym)
8729 error("too many 'default'");
8730 *def_sym = ind;
8731 is_expr = 0;
8732 goto block_after_label;
8733 } else
8734 if (tok == TOK_GOTO) {
8735 next();
8736 if (tok == '*' && gnu_ext) {
8737 /* computed goto */
8738 next();
8739 gexpr();
8740 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8741 expect("pointer");
8742 ggoto();
8743 } else if (tok >= TOK_UIDENT) {
8744 s = label_find(tok);
8745 /* put forward definition if needed */
8746 if (!s) {
8747 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8748 } else {
8749 if (s->r == LABEL_DECLARED)
8750 s->r = LABEL_FORWARD;
8752 /* label already defined */
8753 if (s->r & LABEL_FORWARD)
8754 s->next = (void *)gjmp((long)s->next);
8755 else
8756 gjmp_addr((long)s->next);
8757 next();
8758 } else {
8759 expect("label identifier");
8761 skip(';');
8762 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8763 asm_instr();
8764 } else {
8765 b = is_label();
8766 if (b) {
8767 /* label case */
8768 s = label_find(b);
8769 if (s) {
8770 if (s->r == LABEL_DEFINED)
8771 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8772 gsym((long)s->next);
8773 s->r = LABEL_DEFINED;
8774 } else {
8775 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8777 s->next = (void *)ind;
8778 /* we accept this, but it is a mistake */
8779 block_after_label:
8780 if (tok == '}') {
8781 warning("deprecated use of label at end of compound statement");
8782 } else {
8783 if (is_expr)
8784 vpop();
8785 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8787 } else {
8788 /* expression case */
8789 if (tok != ';') {
8790 if (is_expr) {
8791 vpop();
8792 gexpr();
8793 } else {
8794 gexpr();
8795 vpop();
8798 skip(';');
8803 /* t is the array or struct type. c is the array or struct
8804 address. cur_index/cur_field is the pointer to the current
8805 value. 'size_only' is true if only size info is needed (only used
8806 in arrays) */
8807 static void decl_designator(CType *type, Section *sec, unsigned long c,
8808 int *cur_index, Sym **cur_field,
8809 int size_only)
8811 Sym *s, *f;
8812 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8813 CType type1;
8815 notfirst = 0;
8816 elem_size = 0;
8817 nb_elems = 1;
8818 if (gnu_ext && (l = is_label()) != 0)
8819 goto struct_field;
8820 while (tok == '[' || tok == '.') {
8821 if (tok == '[') {
8822 if (!(type->t & VT_ARRAY))
8823 expect("array type");
8824 s = type->ref;
8825 next();
8826 index = expr_const();
8827 if (index < 0 || (s->c >= 0 && index >= s->c))
8828 expect("invalid index");
8829 if (tok == TOK_DOTS && gnu_ext) {
8830 next();
8831 index_last = expr_const();
8832 if (index_last < 0 ||
8833 (s->c >= 0 && index_last >= s->c) ||
8834 index_last < index)
8835 expect("invalid index");
8836 } else {
8837 index_last = index;
8839 skip(']');
8840 if (!notfirst)
8841 *cur_index = index_last;
8842 type = pointed_type(type);
8843 elem_size = type_size(type, &align);
8844 c += index * elem_size;
8845 /* NOTE: we only support ranges for last designator */
8846 nb_elems = index_last - index + 1;
8847 if (nb_elems != 1) {
8848 notfirst = 1;
8849 break;
8851 } else {
8852 next();
8853 l = tok;
8854 next();
8855 struct_field:
8856 if ((type->t & VT_BTYPE) != VT_STRUCT)
8857 expect("struct/union type");
8858 s = type->ref;
8859 l |= SYM_FIELD;
8860 f = s->next;
8861 while (f) {
8862 if (f->v == l)
8863 break;
8864 f = f->next;
8866 if (!f)
8867 expect("field");
8868 if (!notfirst)
8869 *cur_field = f;
8870 /* XXX: fix this mess by using explicit storage field */
8871 type1 = f->type;
8872 type1.t |= (type->t & ~VT_TYPE);
8873 type = &type1;
8874 c += f->c;
8876 notfirst = 1;
8878 if (notfirst) {
8879 if (tok == '=') {
8880 next();
8881 } else {
8882 if (!gnu_ext)
8883 expect("=");
8885 } else {
8886 if (type->t & VT_ARRAY) {
8887 index = *cur_index;
8888 type = pointed_type(type);
8889 c += index * type_size(type, &align);
8890 } else {
8891 f = *cur_field;
8892 if (!f)
8893 error("too many field init");
8894 /* XXX: fix this mess by using explicit storage field */
8895 type1 = f->type;
8896 type1.t |= (type->t & ~VT_TYPE);
8897 type = &type1;
8898 c += f->c;
8901 decl_initializer(type, sec, c, 0, size_only);
8903 /* XXX: make it more general */
8904 if (!size_only && nb_elems > 1) {
8905 unsigned long c_end;
8906 uint8_t *src, *dst;
8907 int i;
8909 if (!sec)
8910 error("range init not supported yet for dynamic storage");
8911 c_end = c + nb_elems * elem_size;
8912 if (c_end > sec->data_allocated)
8913 section_realloc(sec, c_end);
8914 src = sec->data + c;
8915 dst = src;
8916 for(i = 1; i < nb_elems; i++) {
8917 dst += elem_size;
8918 memcpy(dst, src, elem_size);
8923 #define EXPR_VAL 0
8924 #define EXPR_CONST 1
8925 #define EXPR_ANY 2
8927 /* store a value or an expression directly in global data or in local array */
8928 static void init_putv(CType *type, Section *sec, unsigned long c,
8929 int v, int expr_type)
8931 int saved_global_expr, bt, bit_pos, bit_size;
8932 void *ptr;
8933 unsigned long long bit_mask;
8934 CType dtype;
8936 switch(expr_type) {
8937 case EXPR_VAL:
8938 vpushi(v);
8939 break;
8940 case EXPR_CONST:
8941 /* compound literals must be allocated globally in this case */
8942 saved_global_expr = global_expr;
8943 global_expr = 1;
8944 expr_const1();
8945 global_expr = saved_global_expr;
8946 /* NOTE: symbols are accepted */
8947 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8948 error("initializer element is not constant");
8949 break;
8950 case EXPR_ANY:
8951 expr_eq();
8952 break;
8955 dtype = *type;
8956 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8958 if (sec) {
8959 /* XXX: not portable */
8960 /* XXX: generate error if incorrect relocation */
8961 gen_assign_cast(&dtype);
8962 bt = type->t & VT_BTYPE;
8963 /* we'll write at most 12 bytes */
8964 if (c + 12 > sec->data_allocated) {
8965 section_realloc(sec, c + 12);
8967 ptr = sec->data + c;
8968 /* XXX: make code faster ? */
8969 if (!(type->t & VT_BITFIELD)) {
8970 bit_pos = 0;
8971 bit_size = 32;
8972 bit_mask = -1LL;
8973 } else {
8974 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8975 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8976 bit_mask = (1LL << bit_size) - 1;
8978 if ((vtop->r & VT_SYM) &&
8979 (bt == VT_BYTE ||
8980 bt == VT_SHORT ||
8981 bt == VT_DOUBLE ||
8982 bt == VT_LDOUBLE ||
8983 bt == VT_LLONG ||
8984 (bt == VT_INT && bit_size != 32)))
8985 error("initializer element is not computable at load time");
8986 switch(bt) {
8987 case VT_BOOL:
8988 vtop->c.i = (vtop->c.i != 0);
8989 case VT_BYTE:
8990 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8991 break;
8992 case VT_SHORT:
8993 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8994 break;
8995 case VT_DOUBLE:
8996 *(double *)ptr = vtop->c.d;
8997 break;
8998 case VT_LDOUBLE:
8999 *(long double *)ptr = vtop->c.ld;
9000 break;
9001 case VT_LLONG:
9002 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
9003 break;
9004 default:
9005 if (vtop->r & VT_SYM) {
9006 greloc(sec, vtop->sym, c, R_DATA_32);
9008 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
9009 break;
9011 vtop--;
9012 } else {
9013 vset(&dtype, VT_LOCAL|VT_LVAL, c);
9014 vswap();
9015 vstore();
9016 vpop();
9020 /* put zeros for variable based init */
9021 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
9023 if (sec) {
9024 /* nothing to do because globals are already set to zero */
9025 } else {
9026 vpush_global_sym(&func_old_type, TOK_memset);
9027 vseti(VT_LOCAL, c);
9028 vpushi(0);
9029 vpushi(size);
9030 gfunc_call(3);
9034 /* 't' contains the type and storage info. 'c' is the offset of the
9035 object in section 'sec'. If 'sec' is NULL, it means stack based
9036 allocation. 'first' is true if array '{' must be read (multi
9037 dimension implicit array init handling). 'size_only' is true if
9038 size only evaluation is wanted (only for arrays). */
9039 static void decl_initializer(CType *type, Section *sec, unsigned long c,
9040 int first, int size_only)
9042 int index, array_length, n, no_oblock, nb, parlevel, i;
9043 int size1, align1, expr_type;
9044 Sym *s, *f;
9045 CType *t1;
9047 if (type->t & VT_ARRAY) {
9048 s = type->ref;
9049 n = s->c;
9050 array_length = 0;
9051 t1 = pointed_type(type);
9052 size1 = type_size(t1, &align1);
9054 no_oblock = 1;
9055 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
9056 tok == '{') {
9057 skip('{');
9058 no_oblock = 0;
9061 /* only parse strings here if correct type (otherwise: handle
9062 them as ((w)char *) expressions */
9063 if ((tok == TOK_LSTR &&
9064 #ifdef TCC_TARGET_PE
9065 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
9066 #else
9067 (t1->t & VT_BTYPE) == VT_INT
9068 #endif
9069 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
9070 while (tok == TOK_STR || tok == TOK_LSTR) {
9071 int cstr_len, ch;
9072 CString *cstr;
9074 cstr = tokc.cstr;
9075 /* compute maximum number of chars wanted */
9076 if (tok == TOK_STR)
9077 cstr_len = cstr->size;
9078 else
9079 cstr_len = cstr->size / sizeof(nwchar_t);
9080 cstr_len--;
9081 nb = cstr_len;
9082 if (n >= 0 && nb > (n - array_length))
9083 nb = n - array_length;
9084 if (!size_only) {
9085 if (cstr_len > nb)
9086 warning("initializer-string for array is too long");
9087 /* in order to go faster for common case (char
9088 string in global variable, we handle it
9089 specifically */
9090 if (sec && tok == TOK_STR && size1 == 1) {
9091 memcpy(sec->data + c + array_length, cstr->data, nb);
9092 } else {
9093 for(i=0;i<nb;i++) {
9094 if (tok == TOK_STR)
9095 ch = ((unsigned char *)cstr->data)[i];
9096 else
9097 ch = ((nwchar_t *)cstr->data)[i];
9098 init_putv(t1, sec, c + (array_length + i) * size1,
9099 ch, EXPR_VAL);
9103 array_length += nb;
9104 next();
9106 /* only add trailing zero if enough storage (no
9107 warning in this case since it is standard) */
9108 if (n < 0 || array_length < n) {
9109 if (!size_only) {
9110 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
9112 array_length++;
9114 } else {
9115 index = 0;
9116 while (tok != '}') {
9117 decl_designator(type, sec, c, &index, NULL, size_only);
9118 if (n >= 0 && index >= n)
9119 error("index too large");
9120 /* must put zero in holes (note that doing it that way
9121 ensures that it even works with designators) */
9122 if (!size_only && array_length < index) {
9123 init_putz(t1, sec, c + array_length * size1,
9124 (index - array_length) * size1);
9126 index++;
9127 if (index > array_length)
9128 array_length = index;
9129 /* special test for multi dimensional arrays (may not
9130 be strictly correct if designators are used at the
9131 same time) */
9132 if (index >= n && no_oblock)
9133 break;
9134 if (tok == '}')
9135 break;
9136 skip(',');
9139 if (!no_oblock)
9140 skip('}');
9141 /* put zeros at the end */
9142 if (!size_only && n >= 0 && array_length < n) {
9143 init_putz(t1, sec, c + array_length * size1,
9144 (n - array_length) * size1);
9146 /* patch type size if needed */
9147 if (n < 0)
9148 s->c = array_length;
9149 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
9150 (sec || !first || tok == '{')) {
9151 int par_count;
9153 /* NOTE: the previous test is a specific case for automatic
9154 struct/union init */
9155 /* XXX: union needs only one init */
9157 /* XXX: this test is incorrect for local initializers
9158 beginning with ( without {. It would be much more difficult
9159 to do it correctly (ideally, the expression parser should
9160 be used in all cases) */
9161 par_count = 0;
9162 if (tok == '(') {
9163 AttributeDef ad1;
9164 CType type1;
9165 next();
9166 while (tok == '(') {
9167 par_count++;
9168 next();
9170 if (!parse_btype(&type1, &ad1))
9171 expect("cast");
9172 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
9173 #if 0
9174 if (!is_assignable_types(type, &type1))
9175 error("invalid type for cast");
9176 #endif
9177 skip(')');
9179 no_oblock = 1;
9180 if (first || tok == '{') {
9181 skip('{');
9182 no_oblock = 0;
9184 s = type->ref;
9185 f = s->next;
9186 array_length = 0;
9187 index = 0;
9188 n = s->c;
9189 while (tok != '}') {
9190 decl_designator(type, sec, c, NULL, &f, size_only);
9191 index = f->c;
9192 if (!size_only && array_length < index) {
9193 init_putz(type, sec, c + array_length,
9194 index - array_length);
9196 index = index + type_size(&f->type, &align1);
9197 if (index > array_length)
9198 array_length = index;
9199 f = f->next;
9200 if (no_oblock && f == NULL)
9201 break;
9202 if (tok == '}')
9203 break;
9204 skip(',');
9206 /* put zeros at the end */
9207 if (!size_only && array_length < n) {
9208 init_putz(type, sec, c + array_length,
9209 n - array_length);
9211 if (!no_oblock)
9212 skip('}');
9213 while (par_count) {
9214 skip(')');
9215 par_count--;
9217 } else if (tok == '{') {
9218 next();
9219 decl_initializer(type, sec, c, first, size_only);
9220 skip('}');
9221 } else if (size_only) {
9222 /* just skip expression */
9223 parlevel = 0;
9224 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
9225 tok != -1) {
9226 if (tok == '(')
9227 parlevel++;
9228 else if (tok == ')')
9229 parlevel--;
9230 next();
9232 } else {
9233 /* currently, we always use constant expression for globals
9234 (may change for scripting case) */
9235 expr_type = EXPR_CONST;
9236 if (!sec)
9237 expr_type = EXPR_ANY;
9238 init_putv(type, sec, c, 0, expr_type);
9242 /* parse an initializer for type 't' if 'has_init' is non zero, and
9243 allocate space in local or global data space ('r' is either
9244 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
9245 variable 'v' of scope 'scope' is declared before initializers are
9246 parsed. If 'v' is zero, then a reference to the new object is put
9247 in the value stack. If 'has_init' is 2, a special parsing is done
9248 to handle string constants. */
9249 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
9250 int has_init, int v, int scope)
9252 int size, align, addr, data_offset;
9253 int level;
9254 ParseState saved_parse_state = {0};
9255 TokenString init_str;
9256 Section *sec;
9258 size = type_size(type, &align);
9259 /* If unknown size, we must evaluate it before
9260 evaluating initializers because
9261 initializers can generate global data too
9262 (e.g. string pointers or ISOC99 compound
9263 literals). It also simplifies local
9264 initializers handling */
9265 tok_str_new(&init_str);
9266 if (size < 0) {
9267 if (!has_init)
9268 error("unknown type size");
9269 /* get all init string */
9270 if (has_init == 2) {
9271 /* only get strings */
9272 while (tok == TOK_STR || tok == TOK_LSTR) {
9273 tok_str_add_tok(&init_str);
9274 next();
9276 } else {
9277 level = 0;
9278 while (level > 0 || (tok != ',' && tok != ';')) {
9279 if (tok < 0)
9280 error("unexpected end of file in initializer");
9281 tok_str_add_tok(&init_str);
9282 if (tok == '{')
9283 level++;
9284 else if (tok == '}') {
9285 level--;
9286 if (level <= 0) {
9287 next();
9288 break;
9291 next();
9294 tok_str_add(&init_str, -1);
9295 tok_str_add(&init_str, 0);
9297 /* compute size */
9298 save_parse_state(&saved_parse_state);
9300 macro_ptr = init_str.str;
9301 next();
9302 decl_initializer(type, NULL, 0, 1, 1);
9303 /* prepare second initializer parsing */
9304 macro_ptr = init_str.str;
9305 next();
9307 /* if still unknown size, error */
9308 size = type_size(type, &align);
9309 if (size < 0)
9310 error("unknown type size");
9312 /* take into account specified alignment if bigger */
9313 if (ad->aligned) {
9314 if (ad->aligned > align)
9315 align = ad->aligned;
9316 } else if (ad->packed) {
9317 align = 1;
9319 if ((r & VT_VALMASK) == VT_LOCAL) {
9320 sec = NULL;
9321 if (do_bounds_check && (type->t & VT_ARRAY))
9322 loc--;
9323 loc = (loc - size) & -align;
9324 addr = loc;
9325 /* handles bounds */
9326 /* XXX: currently, since we do only one pass, we cannot track
9327 '&' operators, so we add only arrays */
9328 if (do_bounds_check && (type->t & VT_ARRAY)) {
9329 unsigned long *bounds_ptr;
9330 /* add padding between regions */
9331 loc--;
9332 /* then add local bound info */
9333 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
9334 bounds_ptr[0] = addr;
9335 bounds_ptr[1] = size;
9337 if (v) {
9338 /* local variable */
9339 sym_push(v, type, r, addr);
9340 } else {
9341 /* push local reference */
9342 vset(type, r, addr);
9344 } else {
9345 Sym *sym;
9347 sym = NULL;
9348 if (v && scope == VT_CONST) {
9349 /* see if the symbol was already defined */
9350 sym = sym_find(v);
9351 if (sym) {
9352 if (!is_compatible_types(&sym->type, type))
9353 error("incompatible types for redefinition of '%s'",
9354 get_tok_str(v, NULL));
9355 if (sym->type.t & VT_EXTERN) {
9356 /* if the variable is extern, it was not allocated */
9357 sym->type.t &= ~VT_EXTERN;
9358 /* set array size if it was ommited in extern
9359 declaration */
9360 if ((sym->type.t & VT_ARRAY) &&
9361 sym->type.ref->c < 0 &&
9362 type->ref->c >= 0)
9363 sym->type.ref->c = type->ref->c;
9364 } else {
9365 /* we accept several definitions of the same
9366 global variable. this is tricky, because we
9367 must play with the SHN_COMMON type of the symbol */
9368 /* XXX: should check if the variable was already
9369 initialized. It is incorrect to initialized it
9370 twice */
9371 /* no init data, we won't add more to the symbol */
9372 if (!has_init)
9373 goto no_alloc;
9378 /* allocate symbol in corresponding section */
9379 sec = ad->section;
9380 if (!sec) {
9381 if (has_init)
9382 sec = data_section;
9383 else if (tcc_state->nocommon)
9384 sec = bss_section;
9386 if (sec) {
9387 data_offset = sec->data_offset;
9388 data_offset = (data_offset + align - 1) & -align;
9389 addr = data_offset;
9390 /* very important to increment global pointer at this time
9391 because initializers themselves can create new initializers */
9392 data_offset += size;
9393 /* add padding if bound check */
9394 if (do_bounds_check)
9395 data_offset++;
9396 sec->data_offset = data_offset;
9397 /* allocate section space to put the data */
9398 if (sec->sh_type != SHT_NOBITS &&
9399 data_offset > sec->data_allocated)
9400 section_realloc(sec, data_offset);
9401 /* align section if needed */
9402 if (align > sec->sh_addralign)
9403 sec->sh_addralign = align;
9404 } else {
9405 addr = 0; /* avoid warning */
9408 if (v) {
9409 if (scope != VT_CONST || !sym) {
9410 sym = sym_push(v, type, r | VT_SYM, 0);
9412 /* update symbol definition */
9413 if (sec) {
9414 put_extern_sym(sym, sec, addr, size);
9415 } else {
9416 ElfW(Sym) *esym;
9417 /* put a common area */
9418 put_extern_sym(sym, NULL, align, size);
9419 /* XXX: find a nicer way */
9420 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
9421 esym->st_shndx = SHN_COMMON;
9423 } else {
9424 CValue cval;
9426 /* push global reference */
9427 sym = get_sym_ref(type, sec, addr, size);
9428 cval.ul = 0;
9429 vsetc(type, VT_CONST | VT_SYM, &cval);
9430 vtop->sym = sym;
9433 /* handles bounds now because the symbol must be defined
9434 before for the relocation */
9435 if (do_bounds_check) {
9436 unsigned long *bounds_ptr;
9438 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9439 /* then add global bound info */
9440 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9441 bounds_ptr[0] = 0; /* relocated */
9442 bounds_ptr[1] = size;
9445 if (has_init) {
9446 decl_initializer(type, sec, addr, 1, 0);
9447 /* restore parse state if needed */
9448 if (init_str.str) {
9449 tok_str_free(init_str.str);
9450 restore_parse_state(&saved_parse_state);
9453 no_alloc: ;
9456 void put_func_debug(Sym *sym)
9458 char buf[512];
9460 /* stabs info */
9461 /* XXX: we put here a dummy type */
9462 snprintf(buf, sizeof(buf), "%s:%c1",
9463 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9464 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9465 cur_text_section, sym->c);
9466 /* //gr gdb wants a line at the function */
9467 put_stabn(N_SLINE, 0, file->line_num, 0);
9468 last_ind = 0;
9469 last_line_num = 0;
9472 /* parse an old style function declaration list */
9473 /* XXX: check multiple parameter */
9474 static void func_decl_list(Sym *func_sym)
9476 AttributeDef ad;
9477 int v;
9478 Sym *s;
9479 CType btype, type;
9481 /* parse each declaration */
9482 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9483 if (!parse_btype(&btype, &ad))
9484 expect("declaration list");
9485 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9486 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9487 tok == ';') {
9488 /* we accept no variable after */
9489 } else {
9490 for(;;) {
9491 type = btype;
9492 type_decl(&type, &ad, &v, TYPE_DIRECT);
9493 /* find parameter in function parameter list */
9494 s = func_sym->next;
9495 while (s != NULL) {
9496 if ((s->v & ~SYM_FIELD) == v)
9497 goto found;
9498 s = s->next;
9500 error("declaration for parameter '%s' but no such parameter",
9501 get_tok_str(v, NULL));
9502 found:
9503 /* check that no storage specifier except 'register' was given */
9504 if (type.t & VT_STORAGE)
9505 error("storage class specified for '%s'", get_tok_str(v, NULL));
9506 convert_parameter_type(&type);
9507 /* we can add the type (NOTE: it could be local to the function) */
9508 s->type = type;
9509 /* accept other parameters */
9510 if (tok == ',')
9511 next();
9512 else
9513 break;
9516 skip(';');
9520 /* parse a function defined by symbol 'sym' and generate its code in
9521 'cur_text_section' */
9522 static void gen_function(Sym *sym)
9524 int saved_nocode_wanted = nocode_wanted;
9525 nocode_wanted = 0;
9526 ind = cur_text_section->data_offset;
9527 /* NOTE: we patch the symbol size later */
9528 put_extern_sym(sym, cur_text_section, ind, 0);
9529 funcname = get_tok_str(sym->v, NULL);
9530 func_ind = ind;
9531 /* put debug symbol */
9532 if (do_debug)
9533 put_func_debug(sym);
9534 /* push a dummy symbol to enable local sym storage */
9535 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9536 gfunc_prolog(&sym->type);
9537 rsym = 0;
9538 block(NULL, NULL, NULL, NULL, 0, 0);
9539 gsym(rsym);
9540 gfunc_epilog();
9541 cur_text_section->data_offset = ind;
9542 label_pop(&global_label_stack, NULL);
9543 sym_pop(&local_stack, NULL); /* reset local stack */
9544 /* end of function */
9545 /* patch symbol size */
9546 ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size =
9547 ind - func_ind;
9548 if (do_debug) {
9549 put_stabn(N_FUN, 0, 0, ind - func_ind);
9551 /* It's better to crash than to generate wrong code */
9552 cur_text_section = NULL;
9553 funcname = ""; /* for safety */
9554 func_vt.t = VT_VOID; /* for safety */
9555 ind = 0; /* for safety */
9556 nocode_wanted = saved_nocode_wanted;
9559 static void gen_inline_functions(void)
9561 Sym *sym;
9562 CType *type;
9563 int *str, inline_generated;
9565 /* iterate while inline function are referenced */
9566 for(;;) {
9567 inline_generated = 0;
9568 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9569 type = &sym->type;
9570 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9571 (type->t & (VT_STATIC | VT_INLINE)) ==
9572 (VT_STATIC | VT_INLINE) &&
9573 sym->c != 0) {
9574 /* the function was used: generate its code and
9575 convert it to a normal function */
9576 str = INLINE_DEF(sym->r);
9577 sym->r = VT_SYM | VT_CONST;
9578 sym->type.t &= ~VT_INLINE;
9580 macro_ptr = str;
9581 next();
9582 cur_text_section = text_section;
9583 gen_function(sym);
9584 macro_ptr = NULL; /* fail safe */
9586 tok_str_free(str);
9587 inline_generated = 1;
9590 if (!inline_generated)
9591 break;
9594 /* free all remaining inline function tokens */
9595 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9596 type = &sym->type;
9597 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9598 (type->t & (VT_STATIC | VT_INLINE)) ==
9599 (VT_STATIC | VT_INLINE)) {
9600 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9601 if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
9602 continue;
9603 str = INLINE_DEF(sym->r);
9604 tok_str_free(str);
9605 sym->r = 0; /* fail safe */
9610 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9611 static void decl(int l)
9613 int v, has_init, r;
9614 CType type, btype;
9615 Sym *sym;
9616 AttributeDef ad;
9618 while (1) {
9619 if (!parse_btype(&btype, &ad)) {
9620 /* skip redundant ';' */
9621 /* XXX: find more elegant solution */
9622 if (tok == ';') {
9623 next();
9624 continue;
9626 if (l == VT_CONST &&
9627 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9628 /* global asm block */
9629 asm_global_instr();
9630 continue;
9632 /* special test for old K&R protos without explicit int
9633 type. Only accepted when defining global data */
9634 if (l == VT_LOCAL || tok < TOK_DEFINE)
9635 break;
9636 btype.t = VT_INT;
9638 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9639 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9640 tok == ';') {
9641 /* we accept no variable after */
9642 next();
9643 continue;
9645 while (1) { /* iterate thru each declaration */
9646 type = btype;
9647 type_decl(&type, &ad, &v, TYPE_DIRECT);
9648 #if 0
9650 char buf[500];
9651 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
9652 printf("type = '%s'\n", buf);
9654 #endif
9655 if ((type.t & VT_BTYPE) == VT_FUNC) {
9656 /* if old style function prototype, we accept a
9657 declaration list */
9658 sym = type.ref;
9659 if (sym->c == FUNC_OLD)
9660 func_decl_list(sym);
9663 if (tok == '{') {
9664 if (l == VT_LOCAL)
9665 error("cannot use local functions");
9666 if ((type.t & VT_BTYPE) != VT_FUNC)
9667 expect("function definition");
9669 /* reject abstract declarators in function definition */
9670 sym = type.ref;
9671 while ((sym = sym->next) != NULL)
9672 if (!(sym->v & ~SYM_FIELD))
9673 expect("identifier");
9675 /* XXX: cannot do better now: convert extern line to static inline */
9676 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9677 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9679 sym = sym_find(v);
9680 if (sym) {
9681 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9682 goto func_error1;
9683 /* specific case: if not func_call defined, we put
9684 the one of the prototype */
9685 /* XXX: should have default value */
9686 r = sym->type.ref->r;
9687 if (FUNC_CALL(r) != FUNC_CDECL
9688 && FUNC_CALL(type.ref->r) == FUNC_CDECL)
9689 FUNC_CALL(type.ref->r) = FUNC_CALL(r);
9690 if (FUNC_EXPORT(r))
9691 FUNC_EXPORT(type.ref->r) = 1;
9693 if (!is_compatible_types(&sym->type, &type)) {
9694 func_error1:
9695 error("incompatible types for redefinition of '%s'",
9696 get_tok_str(v, NULL));
9698 /* if symbol is already defined, then put complete type */
9699 sym->type = type;
9700 } else {
9701 /* put function symbol */
9702 sym = global_identifier_push(v, type.t, 0);
9703 sym->type.ref = type.ref;
9706 /* static inline functions are just recorded as a kind
9707 of macro. Their code will be emitted at the end of
9708 the compilation unit only if they are used */
9709 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9710 (VT_INLINE | VT_STATIC)) {
9711 TokenString func_str;
9712 int block_level;
9714 tok_str_new(&func_str);
9716 block_level = 0;
9717 for(;;) {
9718 int t;
9719 if (tok == TOK_EOF)
9720 error("unexpected end of file");
9721 tok_str_add_tok(&func_str);
9722 t = tok;
9723 next();
9724 if (t == '{') {
9725 block_level++;
9726 } else if (t == '}') {
9727 block_level--;
9728 if (block_level == 0)
9729 break;
9732 tok_str_add(&func_str, -1);
9733 tok_str_add(&func_str, 0);
9734 INLINE_DEF(sym->r) = func_str.str;
9735 } else {
9736 /* compute text section */
9737 cur_text_section = ad.section;
9738 if (!cur_text_section)
9739 cur_text_section = text_section;
9740 sym->r = VT_SYM | VT_CONST;
9741 gen_function(sym);
9743 break;
9744 } else {
9745 if (btype.t & VT_TYPEDEF) {
9746 /* save typedefed type */
9747 /* XXX: test storage specifiers ? */
9748 sym = sym_push(v, &type, 0, 0);
9749 sym->type.t |= VT_TYPEDEF;
9750 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9751 /* external function definition */
9752 /* specific case for func_call attribute */
9753 if (ad.func_attr)
9754 type.ref->r = ad.func_attr;
9755 external_sym(v, &type, 0);
9756 } else {
9757 /* not lvalue if array */
9758 r = 0;
9759 if (!(type.t & VT_ARRAY))
9760 r |= lvalue_type(type.t);
9761 has_init = (tok == '=');
9762 if ((btype.t & VT_EXTERN) ||
9763 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9764 !has_init && l == VT_CONST && type.ref->c < 0)) {
9765 /* external variable */
9766 /* NOTE: as GCC, uninitialized global static
9767 arrays of null size are considered as
9768 extern */
9769 external_sym(v, &type, r);
9770 } else {
9771 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9772 if (type.t & VT_STATIC)
9773 r |= VT_CONST;
9774 else
9775 r |= l;
9776 if (has_init)
9777 next();
9778 decl_initializer_alloc(&type, &ad, r,
9779 has_init, v, l);
9782 if (tok != ',') {
9783 skip(';');
9784 break;
9786 next();
9792 /* better than nothing, but needs extension to handle '-E' option
9793 correctly too */
9794 static void preprocess_init(TCCState *s1)
9796 s1->include_stack_ptr = s1->include_stack;
9797 /* XXX: move that before to avoid having to initialize
9798 file->ifdef_stack_ptr ? */
9799 s1->ifdef_stack_ptr = s1->ifdef_stack;
9800 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9802 /* XXX: not ANSI compliant: bound checking says error */
9803 vtop = vstack - 1;
9804 s1->pack_stack[0] = 0;
9805 s1->pack_stack_ptr = s1->pack_stack;
9808 /* compile the C file opened in 'file'. Return non zero if errors. */
9809 static int tcc_compile(TCCState *s1)
9811 Sym *define_start;
9812 char buf[512];
9813 volatile int section_sym;
9815 #ifdef INC_DEBUG
9816 printf("%s: **** new file\n", file->filename);
9817 #endif
9818 preprocess_init(s1);
9820 cur_text_section = NULL;
9821 funcname = "";
9822 anon_sym = SYM_FIRST_ANOM;
9824 /* file info: full path + filename */
9825 section_sym = 0; /* avoid warning */
9826 if (do_debug) {
9827 section_sym = put_elf_sym(symtab_section, 0, 0,
9828 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
9829 text_section->sh_num, NULL);
9830 getcwd(buf, sizeof(buf));
9831 #ifdef _WIN32
9832 normalize_slashes(buf);
9833 #endif
9834 pstrcat(buf, sizeof(buf), "/");
9835 put_stabs_r(buf, N_SO, 0, 0,
9836 text_section->data_offset, text_section, section_sym);
9837 put_stabs_r(file->filename, N_SO, 0, 0,
9838 text_section->data_offset, text_section, section_sym);
9840 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9841 symbols can be safely used */
9842 put_elf_sym(symtab_section, 0, 0,
9843 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
9844 SHN_ABS, file->filename);
9846 /* define some often used types */
9847 int_type.t = VT_INT;
9849 char_pointer_type.t = VT_BYTE;
9850 mk_pointer(&char_pointer_type);
9852 func_old_type.t = VT_FUNC;
9853 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9855 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9856 float_type.t = VT_FLOAT;
9857 double_type.t = VT_DOUBLE;
9859 func_float_type.t = VT_FUNC;
9860 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9861 func_double_type.t = VT_FUNC;
9862 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9863 #endif
9865 #if 0
9866 /* define 'void *alloca(unsigned int)' builtin function */
9868 Sym *s1;
9870 p = anon_sym++;
9871 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9872 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9873 s1->next = NULL;
9874 sym->next = s1;
9875 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9877 #endif
9879 define_start = define_stack;
9880 nocode_wanted = 1;
9882 if (setjmp(s1->error_jmp_buf) == 0) {
9883 s1->nb_errors = 0;
9884 s1->error_set_jmp_enabled = 1;
9886 ch = file->buf_ptr[0];
9887 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9888 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9889 next();
9890 decl(VT_CONST);
9891 if (tok != TOK_EOF)
9892 expect("declaration");
9894 /* end of translation unit info */
9895 if (do_debug) {
9896 put_stabs_r(NULL, N_SO, 0, 0,
9897 text_section->data_offset, text_section, section_sym);
9900 s1->error_set_jmp_enabled = 0;
9902 /* reset define stack, but leave -Dsymbols (may be incorrect if
9903 they are undefined) */
9904 free_defines(define_start);
9906 gen_inline_functions();
9908 sym_pop(&global_stack, NULL);
9909 sym_pop(&local_stack, NULL);
9911 return s1->nb_errors != 0 ? -1 : 0;
9914 /* Preprocess the current file */
9915 static int tcc_preprocess(TCCState *s1)
9917 Sym *define_start;
9918 BufferedFile *file_ref;
9919 int token_seen, line_ref;
9921 preprocess_init(s1);
9922 define_start = define_stack;
9923 ch = file->buf_ptr[0];
9924 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9925 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9926 PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES;
9927 token_seen = 0;
9928 line_ref = 0;
9929 file_ref = NULL;
9931 for (;;) {
9932 next();
9933 if (tok == TOK_EOF) {
9934 break;
9935 } else if (tok == TOK_LINEFEED) {
9936 if (!token_seen)
9937 continue;
9938 ++line_ref;
9939 token_seen = 0;
9940 } else if (!token_seen) {
9941 int d = file->line_num - line_ref;
9942 if (file != file_ref || d < 0 || d >= 8)
9943 fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename);
9944 else
9945 while (d)
9946 fputs("\n", s1->outfile), --d;
9947 line_ref = (file_ref = file)->line_num;
9948 token_seen = 1;
9950 fputs(get_tok_str(tok, &tokc), s1->outfile);
9952 free_defines(define_start);
9953 return 0;
9956 #ifdef LIBTCC
9957 int tcc_compile_string(TCCState *s, const char *str)
9959 BufferedFile bf1, *bf = &bf1;
9960 int ret, len;
9961 char *buf;
9963 /* init file structure */
9964 bf->fd = -1;
9965 /* XXX: avoid copying */
9966 len = strlen(str);
9967 buf = tcc_malloc(len + 1);
9968 if (!buf)
9969 return -1;
9970 memcpy(buf, str, len);
9971 buf[len] = CH_EOB;
9972 bf->buf_ptr = buf;
9973 bf->buf_end = buf + len;
9974 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9975 bf->line_num = 1;
9976 file = bf;
9977 ret = tcc_compile(s);
9978 file = NULL;
9979 tcc_free(buf);
9981 /* currently, no need to close */
9982 return ret;
9984 #endif
9986 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9987 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9989 BufferedFile bf1, *bf = &bf1;
9991 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9992 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9993 /* default value */
9994 if (!value)
9995 value = "1";
9996 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9998 /* init file structure */
9999 bf->fd = -1;
10000 bf->buf_ptr = bf->buffer;
10001 bf->buf_end = bf->buffer + strlen(bf->buffer);
10002 *bf->buf_end = CH_EOB;
10003 bf->filename[0] = '\0';
10004 bf->line_num = 1;
10005 file = bf;
10007 s1->include_stack_ptr = s1->include_stack;
10009 /* parse with define parser */
10010 ch = file->buf_ptr[0];
10011 next_nomacro();
10012 parse_define();
10013 file = NULL;
10016 /* undefine a preprocessor symbol */
10017 void tcc_undefine_symbol(TCCState *s1, const char *sym)
10019 TokenSym *ts;
10020 Sym *s;
10021 ts = tok_alloc(sym, strlen(sym));
10022 s = define_find(ts->tok);
10023 /* undefine symbol by putting an invalid name */
10024 if (s)
10025 define_undef(s);
10028 #ifdef CONFIG_TCC_ASM
10030 #ifdef TCC_TARGET_I386
10031 #include "i386-asm.c"
10032 #endif
10033 #include "tccasm.c"
10035 #else
10036 static void asm_instr(void)
10038 error("inline asm() not supported");
10040 static void asm_global_instr(void)
10042 error("inline asm() not supported");
10044 #endif
10046 #include "tccelf.c"
10048 #ifdef TCC_TARGET_COFF
10049 #include "tcccoff.c"
10050 #endif
10052 #ifdef TCC_TARGET_PE
10053 #include "tccpe.c"
10054 #endif
10056 /* print the position in the source file of PC value 'pc' by reading
10057 the stabs debug information */
10058 static void rt_printline(unsigned long wanted_pc)
10060 Stab_Sym *sym, *sym_end;
10061 char func_name[128], last_func_name[128];
10062 unsigned long func_addr, last_pc, pc;
10063 const char *incl_files[INCLUDE_STACK_SIZE];
10064 int incl_index, len, last_line_num, i;
10065 const char *str, *p;
10067 fprintf(stderr, "0x%08lx:", wanted_pc);
10069 func_name[0] = '\0';
10070 func_addr = 0;
10071 incl_index = 0;
10072 last_func_name[0] = '\0';
10073 last_pc = 0xffffffff;
10074 last_line_num = 1;
10075 sym = (Stab_Sym *)stab_section->data + 1;
10076 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
10077 while (sym < sym_end) {
10078 switch(sym->n_type) {
10079 /* function start or end */
10080 case N_FUN:
10081 if (sym->n_strx == 0) {
10082 /* we test if between last line and end of function */
10083 pc = sym->n_value + func_addr;
10084 if (wanted_pc >= last_pc && wanted_pc < pc)
10085 goto found;
10086 func_name[0] = '\0';
10087 func_addr = 0;
10088 } else {
10089 str = stabstr_section->data + sym->n_strx;
10090 p = strchr(str, ':');
10091 if (!p) {
10092 pstrcpy(func_name, sizeof(func_name), str);
10093 } else {
10094 len = p - str;
10095 if (len > sizeof(func_name) - 1)
10096 len = sizeof(func_name) - 1;
10097 memcpy(func_name, str, len);
10098 func_name[len] = '\0';
10100 func_addr = sym->n_value;
10102 break;
10103 /* line number info */
10104 case N_SLINE:
10105 pc = sym->n_value + func_addr;
10106 if (wanted_pc >= last_pc && wanted_pc < pc)
10107 goto found;
10108 last_pc = pc;
10109 last_line_num = sym->n_desc;
10110 /* XXX: slow! */
10111 strcpy(last_func_name, func_name);
10112 break;
10113 /* include files */
10114 case N_BINCL:
10115 str = stabstr_section->data + sym->n_strx;
10116 add_incl:
10117 if (incl_index < INCLUDE_STACK_SIZE) {
10118 incl_files[incl_index++] = str;
10120 break;
10121 case N_EINCL:
10122 if (incl_index > 1)
10123 incl_index--;
10124 break;
10125 case N_SO:
10126 if (sym->n_strx == 0) {
10127 incl_index = 0; /* end of translation unit */
10128 } else {
10129 str = stabstr_section->data + sym->n_strx;
10130 /* do not add path */
10131 len = strlen(str);
10132 if (len > 0 && str[len - 1] != '/')
10133 goto add_incl;
10135 break;
10137 sym++;
10140 /* second pass: we try symtab symbols (no line number info) */
10141 incl_index = 0;
10143 ElfW(Sym) *sym, *sym_end;
10144 int type;
10146 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
10147 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
10148 sym < sym_end;
10149 sym++) {
10150 type = ELFW(ST_TYPE)(sym->st_info);
10151 if (type == STT_FUNC) {
10152 if (wanted_pc >= sym->st_value &&
10153 wanted_pc < sym->st_value + sym->st_size) {
10154 pstrcpy(last_func_name, sizeof(last_func_name),
10155 strtab_section->data + sym->st_name);
10156 goto found;
10161 /* did not find any info: */
10162 fprintf(stderr, " ???\n");
10163 return;
10164 found:
10165 if (last_func_name[0] != '\0') {
10166 fprintf(stderr, " %s()", last_func_name);
10168 if (incl_index > 0) {
10169 fprintf(stderr, " (%s:%d",
10170 incl_files[incl_index - 1], last_line_num);
10171 for(i = incl_index - 2; i >= 0; i--)
10172 fprintf(stderr, ", included from %s", incl_files[i]);
10173 fprintf(stderr, ")");
10175 fprintf(stderr, "\n");
10178 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
10180 #ifdef __i386__
10182 /* fix for glibc 2.1 */
10183 #ifndef REG_EIP
10184 #define REG_EIP EIP
10185 #define REG_EBP EBP
10186 #endif
10188 /* return the PC at frame level 'level'. Return non zero if not found */
10189 static int rt_get_caller_pc(unsigned long *paddr,
10190 ucontext_t *uc, int level)
10192 unsigned long fp;
10193 int i;
10195 if (level == 0) {
10196 #if defined(__FreeBSD__)
10197 *paddr = uc->uc_mcontext.mc_eip;
10198 #elif defined(__dietlibc__)
10199 *paddr = uc->uc_mcontext.eip;
10200 #else
10201 *paddr = uc->uc_mcontext.gregs[REG_EIP];
10202 #endif
10203 return 0;
10204 } else {
10205 #if defined(__FreeBSD__)
10206 fp = uc->uc_mcontext.mc_ebp;
10207 #elif defined(__dietlibc__)
10208 fp = uc->uc_mcontext.ebp;
10209 #else
10210 fp = uc->uc_mcontext.gregs[REG_EBP];
10211 #endif
10212 for(i=1;i<level;i++) {
10213 /* XXX: check address validity with program info */
10214 if (fp <= 0x1000 || fp >= 0xc0000000)
10215 return -1;
10216 fp = ((unsigned long *)fp)[0];
10218 *paddr = ((unsigned long *)fp)[1];
10219 return 0;
10222 #elif defined(__x86_64__)
10223 /* return the PC at frame level 'level'. Return non zero if not found */
10224 static int rt_get_caller_pc(unsigned long *paddr,
10225 ucontext_t *uc, int level)
10227 unsigned long fp;
10228 int i;
10230 if (level == 0) {
10231 /* XXX: only support linux */
10232 *paddr = uc->uc_mcontext.gregs[REG_RIP];
10233 return 0;
10234 } else {
10235 fp = uc->uc_mcontext.gregs[REG_RBP];
10236 for(i=1;i<level;i++) {
10237 /* XXX: check address validity with program info */
10238 if (fp <= 0x1000)
10239 return -1;
10240 fp = ((unsigned long *)fp)[0];
10242 *paddr = ((unsigned long *)fp)[1];
10243 return 0;
10246 #else
10248 #warning add arch specific rt_get_caller_pc()
10250 static int rt_get_caller_pc(unsigned long *paddr,
10251 ucontext_t *uc, int level)
10253 return -1;
10255 #endif
10257 /* emit a run time error at position 'pc' */
10258 void rt_error(ucontext_t *uc, const char *fmt, ...)
10260 va_list ap;
10261 unsigned long pc;
10262 int i;
10264 va_start(ap, fmt);
10265 fprintf(stderr, "Runtime error: ");
10266 vfprintf(stderr, fmt, ap);
10267 fprintf(stderr, "\n");
10268 for(i=0;i<num_callers;i++) {
10269 if (rt_get_caller_pc(&pc, uc, i) < 0)
10270 break;
10271 if (i == 0)
10272 fprintf(stderr, "at ");
10273 else
10274 fprintf(stderr, "by ");
10275 rt_printline(pc);
10277 exit(255);
10278 va_end(ap);
10281 /* signal handler for fatal errors */
10282 static void sig_error(int signum, siginfo_t *siginf, void *puc)
10284 ucontext_t *uc = puc;
10286 switch(signum) {
10287 case SIGFPE:
10288 switch(siginf->si_code) {
10289 case FPE_INTDIV:
10290 case FPE_FLTDIV:
10291 rt_error(uc, "division by zero");
10292 break;
10293 default:
10294 rt_error(uc, "floating point exception");
10295 break;
10297 break;
10298 case SIGBUS:
10299 case SIGSEGV:
10300 if (rt_bound_error_msg && *rt_bound_error_msg)
10301 rt_error(uc, *rt_bound_error_msg);
10302 else
10303 rt_error(uc, "dereferencing invalid pointer");
10304 break;
10305 case SIGILL:
10306 rt_error(uc, "illegal instruction");
10307 break;
10308 case SIGABRT:
10309 rt_error(uc, "abort() called");
10310 break;
10311 default:
10312 rt_error(uc, "caught signal %d", signum);
10313 break;
10315 exit(255);
10317 #endif
10319 /* copy code into memory passed in by the caller and do all relocations
10320 (needed before using tcc_get_symbol()).
10321 returns -1 on error and required size if ptr is NULL */
10322 int tcc_relocate(TCCState *s1, void *ptr)
10324 Section *s;
10325 unsigned long offset, length, mem;
10326 int i;
10328 s1->nb_errors = 0;
10330 if (0 == s1->runtime_added) {
10331 #ifdef TCC_TARGET_PE
10332 pe_add_runtime(s1);
10333 relocate_common_syms();
10334 tcc_add_linker_symbols(s1);
10335 #else
10336 tcc_add_runtime(s1);
10337 relocate_common_syms();
10338 tcc_add_linker_symbols(s1);
10339 build_got_entries(s1);
10340 #endif
10341 s1->runtime_added = 1;
10344 offset = 0;
10345 mem = (unsigned long)ptr;
10346 for(i = 1; i < s1->nb_sections; i++) {
10347 s = s1->sections[i];
10348 if (0 == (s->sh_flags & SHF_ALLOC))
10349 continue;
10350 length = s->data_offset;
10351 if (0 == mem) {
10352 s->sh_addr = 0;
10353 } else if (1 == mem) {
10354 /* section are relocated in place.
10355 We also alloc the bss space */
10356 if (s->sh_type == SHT_NOBITS)
10357 s->data = tcc_malloc(length);
10358 s->sh_addr = (unsigned long)s->data;
10359 } else {
10360 /* sections are relocated to new memory */
10361 s->sh_addr = (mem + offset + 15) & ~15;
10363 offset = (offset + length + 15) & ~15;
10366 #ifdef TCC_TARGET_X86_64
10367 s1->runtime_plt_and_got_offset = 0;
10368 s1->runtime_plt_and_got = (char *)(mem + offset);
10369 /* double the size of the buffer for got and plt entries
10370 XXX: calculate exact size for them? */
10371 offset *= 2;
10372 #endif
10374 if (0 == mem)
10375 return offset + 15;
10377 /* relocate symbols */
10378 relocate_syms(s1, 1);
10379 if (s1->nb_errors)
10380 return -1;
10382 /* relocate each section */
10383 for(i = 1; i < s1->nb_sections; i++) {
10384 s = s1->sections[i];
10385 if (s->reloc)
10386 relocate_section(s1, s);
10389 for(i = 1; i < s1->nb_sections; i++) {
10390 s = s1->sections[i];
10391 if (0 == (s->sh_flags & SHF_ALLOC))
10392 continue;
10393 length = s->data_offset;
10394 // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
10395 ptr = (void*)s->sh_addr;
10396 if (NULL == s->data || s->sh_type == SHT_NOBITS)
10397 memset(ptr, 0, length);
10398 else if (ptr != s->data)
10399 memcpy(ptr, s->data, length);
10400 /* mark executable sections as executable in memory */
10401 if (s->sh_flags & SHF_EXECINSTR)
10402 set_pages_executable(ptr, length);
10404 #ifdef TCC_TARGET_X86_64
10405 set_pages_executable(s1->runtime_plt_and_got,
10406 s1->runtime_plt_and_got_offset);
10407 #endif
10408 return 0;
10411 /* launch the compiled program with the given arguments */
10412 int tcc_run(TCCState *s1, int argc, char **argv)
10414 int (*prog_main)(int, char **);
10415 void *ptr;
10416 int ret;
10418 ret = tcc_relocate(s1, NULL);
10419 if (ret < 0)
10420 return -1;
10421 ptr = tcc_malloc(ret);
10422 tcc_relocate(s1, ptr);
10424 prog_main = tcc_get_symbol_err(s1, "main");
10426 if (do_debug) {
10427 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10428 error("debug mode currently not available for Windows");
10429 #else
10430 struct sigaction sigact;
10431 /* install TCC signal handlers to print debug info on fatal
10432 runtime errors */
10433 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
10434 sigact.sa_sigaction = sig_error;
10435 sigemptyset(&sigact.sa_mask);
10436 sigaction(SIGFPE, &sigact, NULL);
10437 sigaction(SIGILL, &sigact, NULL);
10438 sigaction(SIGSEGV, &sigact, NULL);
10439 sigaction(SIGBUS, &sigact, NULL);
10440 sigaction(SIGABRT, &sigact, NULL);
10441 #endif
10444 #ifdef CONFIG_TCC_BCHECK
10445 if (do_bounds_check) {
10446 void (*bound_init)(void);
10448 /* set error function */
10449 rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
10451 /* XXX: use .init section so that it also work in binary ? */
10452 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
10453 bound_init();
10455 #endif
10456 ret = (*prog_main)(argc, argv);
10457 tcc_free(ptr);
10458 return ret;
10461 void tcc_memstats(void)
10463 #ifdef MEM_DEBUG
10464 printf("memory in use: %d\n", mem_cur_size);
10465 #endif
10468 static void tcc_cleanup(void)
10470 int i, n;
10472 if (NULL == tcc_state)
10473 return;
10474 tcc_state = NULL;
10476 /* free -D defines */
10477 free_defines(NULL);
10479 /* free tokens */
10480 n = tok_ident - TOK_IDENT;
10481 for(i = 0; i < n; i++)
10482 tcc_free(table_ident[i]);
10483 tcc_free(table_ident);
10485 /* free sym_pools */
10486 dynarray_reset(&sym_pools, &nb_sym_pools);
10487 /* string buffer */
10488 cstr_free(&tokcstr);
10489 /* reset symbol stack */
10490 sym_free_first = NULL;
10491 /* cleanup from error/setjmp */
10492 macro_ptr = NULL;
10495 TCCState *tcc_new(void)
10497 const char *p, *r;
10498 TCCState *s;
10499 TokenSym *ts;
10500 int i, c;
10502 tcc_cleanup();
10504 s = tcc_mallocz(sizeof(TCCState));
10505 if (!s)
10506 return NULL;
10507 tcc_state = s;
10508 s->output_type = TCC_OUTPUT_MEMORY;
10510 /* init isid table */
10511 for(i=CH_EOF;i<256;i++)
10512 isidnum_table[i-CH_EOF] = isid(i) || isnum(i);
10514 /* add all tokens */
10515 table_ident = NULL;
10516 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
10518 tok_ident = TOK_IDENT;
10519 p = tcc_keywords;
10520 while (*p) {
10521 r = p;
10522 for(;;) {
10523 c = *r++;
10524 if (c == '\0')
10525 break;
10527 ts = tok_alloc(p, r - p - 1);
10528 p = r;
10531 /* we add dummy defines for some special macros to speed up tests
10532 and to have working defined() */
10533 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
10534 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
10535 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
10536 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
10538 /* standard defines */
10539 tcc_define_symbol(s, "__STDC__", NULL);
10540 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
10541 #if defined(TCC_TARGET_I386)
10542 tcc_define_symbol(s, "__i386__", NULL);
10543 #endif
10544 #if defined(TCC_TARGET_X86_64)
10545 tcc_define_symbol(s, "__x86_64__", NULL);
10546 #endif
10547 #if defined(TCC_TARGET_ARM)
10548 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10549 tcc_define_symbol(s, "__arm_elf__", NULL);
10550 tcc_define_symbol(s, "__arm_elf", NULL);
10551 tcc_define_symbol(s, "arm_elf", NULL);
10552 tcc_define_symbol(s, "__arm__", NULL);
10553 tcc_define_symbol(s, "__arm", NULL);
10554 tcc_define_symbol(s, "arm", NULL);
10555 tcc_define_symbol(s, "__APCS_32__", NULL);
10556 #endif
10557 #ifdef TCC_TARGET_PE
10558 tcc_define_symbol(s, "_WIN32", NULL);
10559 #else
10560 tcc_define_symbol(s, "__unix__", NULL);
10561 tcc_define_symbol(s, "__unix", NULL);
10562 #if defined(__linux)
10563 tcc_define_symbol(s, "__linux__", NULL);
10564 tcc_define_symbol(s, "__linux", NULL);
10565 #endif
10566 #endif
10567 /* tiny C specific defines */
10568 tcc_define_symbol(s, "__TINYC__", NULL);
10570 /* tiny C & gcc defines */
10571 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10572 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10573 #ifdef TCC_TARGET_PE
10574 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10575 #else
10576 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10577 #endif
10579 #ifndef TCC_TARGET_PE
10580 /* default library paths */
10581 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/local/lib");
10582 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/lib");
10583 tcc_add_library_path(s, CONFIG_SYSROOT "/lib");
10584 #endif
10586 /* no section zero */
10587 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10589 /* create standard sections */
10590 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10591 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10592 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10594 /* symbols are always generated for linking stage */
10595 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10596 ".strtab",
10597 ".hashtab", SHF_PRIVATE);
10598 strtab_section = symtab_section->link;
10600 /* private symbol table for dynamic symbols */
10601 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10602 ".dynstrtab",
10603 ".dynhashtab", SHF_PRIVATE);
10604 s->alacarte_link = 1;
10606 #ifdef CHAR_IS_UNSIGNED
10607 s->char_is_unsigned = 1;
10608 #endif
10609 #if defined(TCC_TARGET_PE) && 0
10610 /* XXX: currently the PE linker is not ready to support that */
10611 s->leading_underscore = 1;
10612 #endif
10613 return s;
10616 void tcc_delete(TCCState *s1)
10618 int i;
10620 tcc_cleanup();
10622 /* free all sections */
10623 for(i = 1; i < s1->nb_sections; i++)
10624 free_section(s1->sections[i]);
10625 dynarray_reset(&s1->sections, &s1->nb_sections);
10627 for(i = 0; i < s1->nb_priv_sections; i++)
10628 free_section(s1->priv_sections[i]);
10629 dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
10631 /* free any loaded DLLs */
10632 for ( i = 0; i < s1->nb_loaded_dlls; i++) {
10633 DLLReference *ref = s1->loaded_dlls[i];
10634 if ( ref->handle )
10635 dlclose(ref->handle);
10638 /* free loaded dlls array */
10639 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
10641 /* free library paths */
10642 dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
10644 /* free include paths */
10645 dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
10646 dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
10647 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
10649 tcc_free(s1);
10652 int tcc_add_include_path(TCCState *s1, const char *pathname)
10654 char *pathname1;
10656 pathname1 = tcc_strdup(pathname);
10657 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10658 return 0;
10661 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10663 char *pathname1;
10665 pathname1 = tcc_strdup(pathname);
10666 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10667 return 0;
10670 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10672 const char *ext;
10673 ElfW(Ehdr) ehdr;
10674 int fd, ret;
10675 BufferedFile *saved_file;
10677 /* find source file type with extension */
10678 ext = tcc_fileextension(filename);
10679 if (ext[0])
10680 ext++;
10682 /* open the file */
10683 saved_file = file;
10684 file = tcc_open(s1, filename);
10685 if (!file) {
10686 if (flags & AFF_PRINT_ERROR) {
10687 error_noabort("file '%s' not found", filename);
10689 ret = -1;
10690 goto fail1;
10693 if (flags & AFF_PREPROCESS) {
10694 ret = tcc_preprocess(s1);
10695 } else if (!ext[0] || !PATHCMP(ext, "c")) {
10696 /* C file assumed */
10697 ret = tcc_compile(s1);
10698 } else
10699 #ifdef CONFIG_TCC_ASM
10700 if (!strcmp(ext, "S")) {
10701 /* preprocessed assembler */
10702 ret = tcc_assemble(s1, 1);
10703 } else if (!strcmp(ext, "s")) {
10704 /* non preprocessed assembler */
10705 ret = tcc_assemble(s1, 0);
10706 } else
10707 #endif
10708 #ifdef TCC_TARGET_PE
10709 if (!PATHCMP(ext, "def")) {
10710 ret = pe_load_def_file(s1, file->fd);
10711 } else
10712 #endif
10714 fd = file->fd;
10715 /* assume executable format: auto guess file type */
10716 ret = read(fd, &ehdr, sizeof(ehdr));
10717 lseek(fd, 0, SEEK_SET);
10718 if (ret <= 0) {
10719 error_noabort("could not read header");
10720 goto fail;
10721 } else if (ret != sizeof(ehdr)) {
10722 goto try_load_script;
10725 if (ehdr.e_ident[0] == ELFMAG0 &&
10726 ehdr.e_ident[1] == ELFMAG1 &&
10727 ehdr.e_ident[2] == ELFMAG2 &&
10728 ehdr.e_ident[3] == ELFMAG3) {
10729 file->line_num = 0; /* do not display line number if error */
10730 if (ehdr.e_type == ET_REL) {
10731 ret = tcc_load_object_file(s1, fd, 0);
10732 } else if (ehdr.e_type == ET_DYN) {
10733 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10734 #ifdef TCC_TARGET_PE
10735 ret = -1;
10736 #else
10737 void *h;
10738 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10739 if (h)
10740 ret = 0;
10741 else
10742 ret = -1;
10743 #endif
10744 } else {
10745 ret = tcc_load_dll(s1, fd, filename,
10746 (flags & AFF_REFERENCED_DLL) != 0);
10748 } else {
10749 error_noabort("unrecognized ELF file");
10750 goto fail;
10752 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10753 file->line_num = 0; /* do not display line number if error */
10754 ret = tcc_load_archive(s1, fd);
10755 } else
10756 #ifdef TCC_TARGET_COFF
10757 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10758 ret = tcc_load_coff(s1, fd);
10759 } else
10760 #endif
10761 #ifdef TCC_TARGET_PE
10762 if (pe_test_res_file(&ehdr, ret)) {
10763 ret = pe_load_res_file(s1, fd);
10764 } else
10765 #endif
10767 /* as GNU ld, consider it is an ld script if not recognized */
10768 try_load_script:
10769 ret = tcc_load_ldscript(s1);
10770 if (ret < 0) {
10771 error_noabort("unrecognized file type");
10772 goto fail;
10776 the_end:
10777 tcc_close(file);
10778 fail1:
10779 file = saved_file;
10780 return ret;
10781 fail:
10782 ret = -1;
10783 goto the_end;
10786 int tcc_add_file(TCCState *s, const char *filename)
10788 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10791 int tcc_add_library_path(TCCState *s, const char *pathname)
10793 char *pathname1;
10795 pathname1 = tcc_strdup(pathname);
10796 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10797 return 0;
10800 /* find and load a dll. Return non zero if not found */
10801 /* XXX: add '-rpath' option support ? */
10802 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10804 char buf[1024];
10805 int i;
10807 for(i = 0; i < s->nb_library_paths; i++) {
10808 snprintf(buf, sizeof(buf), "%s/%s",
10809 s->library_paths[i], filename);
10810 if (tcc_add_file_internal(s, buf, flags) == 0)
10811 return 0;
10813 return -1;
10816 /* the library name is the same as the argument of the '-l' option */
10817 int tcc_add_library(TCCState *s, const char *libraryname)
10819 char buf[1024];
10820 int i;
10822 /* first we look for the dynamic library if not static linking */
10823 if (!s->static_link) {
10824 #ifdef TCC_TARGET_PE
10825 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10826 #else
10827 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10828 #endif
10829 if (tcc_add_dll(s, buf, 0) == 0)
10830 return 0;
10833 /* then we look for the static library */
10834 for(i = 0; i < s->nb_library_paths; i++) {
10835 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10836 s->library_paths[i], libraryname);
10837 if (tcc_add_file_internal(s, buf, 0) == 0)
10838 return 0;
10840 return -1;
10843 int tcc_add_symbol(TCCState *s, const char *name, void *val)
10845 add_elf_sym(symtab_section, (unsigned long)val, 0,
10846 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
10847 SHN_ABS, name);
10848 return 0;
10851 int tcc_set_output_type(TCCState *s, int output_type)
10853 char buf[1024];
10855 s->output_type = output_type;
10857 if (!s->nostdinc) {
10858 /* default include paths */
10859 /* XXX: reverse order needed if -isystem support */
10860 #ifndef TCC_TARGET_PE
10861 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/local/include");
10862 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/include");
10863 #endif
10864 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10865 tcc_add_sysinclude_path(s, buf);
10866 #ifdef TCC_TARGET_PE
10867 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10868 tcc_add_sysinclude_path(s, buf);
10869 #endif
10872 /* if bound checking, then add corresponding sections */
10873 #ifdef CONFIG_TCC_BCHECK
10874 if (do_bounds_check) {
10875 /* define symbol */
10876 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10877 /* create bounds sections */
10878 bounds_section = new_section(s, ".bounds",
10879 SHT_PROGBITS, SHF_ALLOC);
10880 lbounds_section = new_section(s, ".lbounds",
10881 SHT_PROGBITS, SHF_ALLOC);
10883 #endif
10885 if (s->char_is_unsigned) {
10886 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10889 /* add debug sections */
10890 if (do_debug) {
10891 /* stab symbols */
10892 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10893 stab_section->sh_entsize = sizeof(Stab_Sym);
10894 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10895 put_elf_str(stabstr_section, "");
10896 stab_section->link = stabstr_section;
10897 /* put first entry */
10898 put_stabs("", 0, 0, 0, 0);
10901 /* add libc crt1/crti objects */
10902 #ifndef TCC_TARGET_PE
10903 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10904 !s->nostdlib) {
10905 if (output_type != TCC_OUTPUT_DLL)
10906 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10907 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10909 #endif
10911 #ifdef TCC_TARGET_PE
10912 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10913 tcc_add_library_path(s, buf);
10914 #endif
10916 return 0;
10919 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10920 #define FD_INVERT 0x0002 /* invert value before storing */
10922 typedef struct FlagDef {
10923 uint16_t offset;
10924 uint16_t flags;
10925 const char *name;
10926 } FlagDef;
10928 static const FlagDef warning_defs[] = {
10929 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10930 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10931 { offsetof(TCCState, warn_error), 0, "error" },
10932 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10933 "implicit-function-declaration" },
10936 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10937 const char *name, int value)
10939 int i;
10940 const FlagDef *p;
10941 const char *r;
10943 r = name;
10944 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10945 r += 3;
10946 value = !value;
10948 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10949 if (!strcmp(r, p->name))
10950 goto found;
10952 return -1;
10953 found:
10954 if (p->flags & FD_INVERT)
10955 value = !value;
10956 *(int *)((uint8_t *)s + p->offset) = value;
10957 return 0;
10961 /* set/reset a warning */
10962 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10964 int i;
10965 const FlagDef *p;
10967 if (!strcmp(warning_name, "all")) {
10968 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10969 if (p->flags & WD_ALL)
10970 *(int *)((uint8_t *)s + p->offset) = 1;
10972 return 0;
10973 } else {
10974 return set_flag(s, warning_defs, countof(warning_defs),
10975 warning_name, value);
10979 static const FlagDef flag_defs[] = {
10980 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10981 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10982 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10983 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10986 /* set/reset a flag */
10987 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10989 return set_flag(s, flag_defs, countof(flag_defs),
10990 flag_name, value);
10993 #if !defined(LIBTCC)
10995 static int64_t getclock_us(void)
10997 #ifdef _WIN32
10998 struct _timeb tb;
10999 _ftime(&tb);
11000 return (tb.time * 1000LL + tb.millitm) * 1000LL;
11001 #else
11002 struct timeval tv;
11003 gettimeofday(&tv, NULL);
11004 return tv.tv_sec * 1000000LL + tv.tv_usec;
11005 #endif
11008 void help(void)
11010 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
11011 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
11012 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
11013 " [-static] [infile1 infile2...] [-run infile args...]\n"
11014 "\n"
11015 "General options:\n"
11016 " -v display current version, increase verbosity\n"
11017 " -c compile only - generate an object file\n"
11018 " -o outfile set output filename\n"
11019 " -Bdir set tcc internal library path\n"
11020 " -bench output compilation statistics\n"
11021 " -run run compiled source\n"
11022 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
11023 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
11024 " -w disable all warnings\n"
11025 "Preprocessor options:\n"
11026 " -E preprocess only\n"
11027 " -Idir add include path 'dir'\n"
11028 " -Dsym[=val] define 'sym' with value 'val'\n"
11029 " -Usym undefine 'sym'\n"
11030 "Linker options:\n"
11031 " -Ldir add library path 'dir'\n"
11032 " -llib link with dynamic or static library 'lib'\n"
11033 " -shared generate a shared library\n"
11034 " -soname set name for shared library to be used at runtime\n"
11035 " -static static linking\n"
11036 " -rdynamic export all global symbols to dynamic linker\n"
11037 " -r generate (relocatable) object file\n"
11038 "Debugger options:\n"
11039 " -g generate runtime debug info\n"
11040 #ifdef CONFIG_TCC_BCHECK
11041 " -b compile with built-in memory and bounds checker (implies -g)\n"
11042 #endif
11043 " -bt N show N callers in stack traces\n"
11047 #define TCC_OPTION_HAS_ARG 0x0001
11048 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
11050 typedef struct TCCOption {
11051 const char *name;
11052 uint16_t index;
11053 uint16_t flags;
11054 } TCCOption;
11056 enum {
11057 TCC_OPTION_HELP,
11058 TCC_OPTION_I,
11059 TCC_OPTION_D,
11060 TCC_OPTION_U,
11061 TCC_OPTION_L,
11062 TCC_OPTION_B,
11063 TCC_OPTION_l,
11064 TCC_OPTION_bench,
11065 TCC_OPTION_bt,
11066 TCC_OPTION_b,
11067 TCC_OPTION_g,
11068 TCC_OPTION_c,
11069 TCC_OPTION_static,
11070 TCC_OPTION_shared,
11071 TCC_OPTION_soname,
11072 TCC_OPTION_o,
11073 TCC_OPTION_r,
11074 TCC_OPTION_Wl,
11075 TCC_OPTION_W,
11076 TCC_OPTION_O,
11077 TCC_OPTION_m,
11078 TCC_OPTION_f,
11079 TCC_OPTION_nostdinc,
11080 TCC_OPTION_nostdlib,
11081 TCC_OPTION_print_search_dirs,
11082 TCC_OPTION_rdynamic,
11083 TCC_OPTION_run,
11084 TCC_OPTION_v,
11085 TCC_OPTION_w,
11086 TCC_OPTION_pipe,
11087 TCC_OPTION_E,
11090 static const TCCOption tcc_options[] = {
11091 { "h", TCC_OPTION_HELP, 0 },
11092 { "?", TCC_OPTION_HELP, 0 },
11093 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
11094 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
11095 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
11096 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
11097 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
11098 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11099 { "bench", TCC_OPTION_bench, 0 },
11100 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
11101 #ifdef CONFIG_TCC_BCHECK
11102 { "b", TCC_OPTION_b, 0 },
11103 #endif
11104 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11105 { "c", TCC_OPTION_c, 0 },
11106 { "static", TCC_OPTION_static, 0 },
11107 { "shared", TCC_OPTION_shared, 0 },
11108 { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
11109 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
11110 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11111 { "rdynamic", TCC_OPTION_rdynamic, 0 },
11112 { "r", TCC_OPTION_r, 0 },
11113 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11114 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11115 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11116 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
11117 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11118 { "nostdinc", TCC_OPTION_nostdinc, 0 },
11119 { "nostdlib", TCC_OPTION_nostdlib, 0 },
11120 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
11121 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11122 { "w", TCC_OPTION_w, 0 },
11123 { "pipe", TCC_OPTION_pipe, 0},
11124 { "E", TCC_OPTION_E, 0},
11125 { NULL },
11128 /* convert 'str' into an array of space separated strings */
11129 static int expand_args(char ***pargv, const char *str)
11131 const char *s1;
11132 char **argv, *arg;
11133 int argc, len;
11135 argc = 0;
11136 argv = NULL;
11137 for(;;) {
11138 while (is_space(*str))
11139 str++;
11140 if (*str == '\0')
11141 break;
11142 s1 = str;
11143 while (*str != '\0' && !is_space(*str))
11144 str++;
11145 len = str - s1;
11146 arg = tcc_malloc(len + 1);
11147 memcpy(arg, s1, len);
11148 arg[len] = '\0';
11149 dynarray_add((void ***)&argv, &argc, arg);
11151 *pargv = argv;
11152 return argc;
11155 static char **files;
11156 static int nb_files, nb_libraries;
11157 static int multiple_files;
11158 static int print_search_dirs;
11159 static int output_type;
11160 static int reloc_output;
11161 static const char *outfile;
11163 int parse_args(TCCState *s, int argc, char **argv)
11165 int optind;
11166 const TCCOption *popt;
11167 const char *optarg, *p1, *r1;
11168 char *r;
11170 optind = 0;
11171 while (optind < argc) {
11173 r = argv[optind++];
11174 if (r[0] != '-' || r[1] == '\0') {
11175 /* add a new file */
11176 dynarray_add((void ***)&files, &nb_files, r);
11177 if (!multiple_files) {
11178 optind--;
11179 /* argv[0] will be this file */
11180 break;
11182 } else {
11183 /* find option in table (match only the first chars */
11184 popt = tcc_options;
11185 for(;;) {
11186 p1 = popt->name;
11187 if (p1 == NULL)
11188 error("invalid option -- '%s'", r);
11189 r1 = r + 1;
11190 for(;;) {
11191 if (*p1 == '\0')
11192 goto option_found;
11193 if (*r1 != *p1)
11194 break;
11195 p1++;
11196 r1++;
11198 popt++;
11200 option_found:
11201 if (popt->flags & TCC_OPTION_HAS_ARG) {
11202 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
11203 optarg = r1;
11204 } else {
11205 if (optind >= argc)
11206 error("argument to '%s' is missing", r);
11207 optarg = argv[optind++];
11209 } else {
11210 if (*r1 != '\0')
11211 return 0;
11212 optarg = NULL;
11215 switch(popt->index) {
11216 case TCC_OPTION_HELP:
11217 return 0;
11219 case TCC_OPTION_I:
11220 if (tcc_add_include_path(s, optarg) < 0)
11221 error("too many include paths");
11222 break;
11223 case TCC_OPTION_D:
11225 char *sym, *value;
11226 sym = (char *)optarg;
11227 value = strchr(sym, '=');
11228 if (value) {
11229 *value = '\0';
11230 value++;
11232 tcc_define_symbol(s, sym, value);
11234 break;
11235 case TCC_OPTION_U:
11236 tcc_undefine_symbol(s, optarg);
11237 break;
11238 case TCC_OPTION_L:
11239 tcc_add_library_path(s, optarg);
11240 break;
11241 case TCC_OPTION_B:
11242 /* set tcc utilities path (mainly for tcc development) */
11243 tcc_lib_path = optarg;
11244 break;
11245 case TCC_OPTION_l:
11246 dynarray_add((void ***)&files, &nb_files, r);
11247 nb_libraries++;
11248 break;
11249 case TCC_OPTION_bench:
11250 do_bench = 1;
11251 break;
11252 case TCC_OPTION_bt:
11253 num_callers = atoi(optarg);
11254 break;
11255 #ifdef CONFIG_TCC_BCHECK
11256 case TCC_OPTION_b:
11257 do_bounds_check = 1;
11258 do_debug = 1;
11259 break;
11260 #endif
11261 case TCC_OPTION_g:
11262 do_debug = 1;
11263 break;
11264 case TCC_OPTION_c:
11265 multiple_files = 1;
11266 output_type = TCC_OUTPUT_OBJ;
11267 break;
11268 case TCC_OPTION_static:
11269 s->static_link = 1;
11270 break;
11271 case TCC_OPTION_shared:
11272 output_type = TCC_OUTPUT_DLL;
11273 break;
11274 case TCC_OPTION_soname:
11275 s->soname = optarg;
11276 break;
11277 case TCC_OPTION_o:
11278 multiple_files = 1;
11279 outfile = optarg;
11280 break;
11281 case TCC_OPTION_r:
11282 /* generate a .o merging several output files */
11283 reloc_output = 1;
11284 output_type = TCC_OUTPUT_OBJ;
11285 break;
11286 case TCC_OPTION_nostdinc:
11287 s->nostdinc = 1;
11288 break;
11289 case TCC_OPTION_nostdlib:
11290 s->nostdlib = 1;
11291 break;
11292 case TCC_OPTION_print_search_dirs:
11293 print_search_dirs = 1;
11294 break;
11295 case TCC_OPTION_run:
11297 int argc1;
11298 char **argv1;
11299 argc1 = expand_args(&argv1, optarg);
11300 if (argc1 > 0) {
11301 parse_args(s, argc1, argv1);
11303 multiple_files = 0;
11304 output_type = TCC_OUTPUT_MEMORY;
11306 break;
11307 case TCC_OPTION_v:
11308 do {
11309 if (0 == verbose++)
11310 printf("tcc version %s\n", TCC_VERSION);
11311 } while (*optarg++ == 'v');
11312 break;
11313 case TCC_OPTION_f:
11314 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
11315 goto unsupported_option;
11316 break;
11317 case TCC_OPTION_W:
11318 if (tcc_set_warning(s, optarg, 1) < 0 &&
11319 s->warn_unsupported)
11320 goto unsupported_option;
11321 break;
11322 case TCC_OPTION_w:
11323 s->warn_none = 1;
11324 break;
11325 case TCC_OPTION_rdynamic:
11326 s->rdynamic = 1;
11327 break;
11328 case TCC_OPTION_Wl:
11330 const char *p;
11331 if (strstart(optarg, "-Ttext,", &p)) {
11332 s->text_addr = strtoul(p, NULL, 16);
11333 s->has_text_addr = 1;
11334 } else if (strstart(optarg, "--oformat,", &p)) {
11335 if (strstart(p, "elf32-", NULL)) {
11336 s->output_format = TCC_OUTPUT_FORMAT_ELF;
11337 } else if (!strcmp(p, "binary")) {
11338 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
11339 } else
11340 #ifdef TCC_TARGET_COFF
11341 if (!strcmp(p, "coff")) {
11342 s->output_format = TCC_OUTPUT_FORMAT_COFF;
11343 } else
11344 #endif
11346 error("target %s not found", p);
11348 } else {
11349 error("unsupported linker option '%s'", optarg);
11352 break;
11353 case TCC_OPTION_E:
11354 output_type = TCC_OUTPUT_PREPROCESS;
11355 break;
11356 default:
11357 if (s->warn_unsupported) {
11358 unsupported_option:
11359 warning("unsupported option '%s'", r);
11361 break;
11365 return optind + 1;
11368 int main(int argc, char **argv)
11370 int i;
11371 TCCState *s;
11372 int nb_objfiles, ret, optind;
11373 char objfilename[1024];
11374 int64_t start_time = 0;
11376 #ifdef _WIN32
11377 tcc_lib_path = w32_tcc_lib_path();
11378 #endif
11380 s = tcc_new();
11381 output_type = TCC_OUTPUT_EXE;
11382 outfile = NULL;
11383 multiple_files = 1;
11384 files = NULL;
11385 nb_files = 0;
11386 nb_libraries = 0;
11387 reloc_output = 0;
11388 print_search_dirs = 0;
11389 ret = 0;
11391 optind = parse_args(s, argc - 1, argv + 1);
11392 if (print_search_dirs) {
11393 /* enough for Linux kernel */
11394 printf("install: %s/\n", tcc_lib_path);
11395 return 0;
11397 if (optind == 0 || nb_files == 0) {
11398 if (optind && verbose)
11399 return 0;
11400 help();
11401 return 1;
11404 nb_objfiles = nb_files - nb_libraries;
11406 /* if outfile provided without other options, we output an
11407 executable */
11408 if (outfile && output_type == TCC_OUTPUT_MEMORY)
11409 output_type = TCC_OUTPUT_EXE;
11411 /* check -c consistency : only single file handled. XXX: checks file type */
11412 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
11413 /* accepts only a single input file */
11414 if (nb_objfiles != 1)
11415 error("cannot specify multiple files with -c");
11416 if (nb_libraries != 0)
11417 error("cannot specify libraries with -c");
11421 if (output_type == TCC_OUTPUT_PREPROCESS) {
11422 if (!outfile) {
11423 s->outfile = stdout;
11424 } else {
11425 s->outfile = fopen(outfile, "w");
11426 if (!s->outfile)
11427 error("could not open '%s", outfile);
11429 } else if (output_type != TCC_OUTPUT_MEMORY) {
11430 if (!outfile) {
11431 /* compute default outfile name */
11432 char *ext;
11433 const char *name =
11434 strcmp(files[0], "-") == 0 ? "a" : tcc_basename(files[0]);
11435 pstrcpy(objfilename, sizeof(objfilename), name);
11436 ext = tcc_fileextension(objfilename);
11437 #ifdef TCC_TARGET_PE
11438 if (output_type == TCC_OUTPUT_DLL)
11439 strcpy(ext, ".dll");
11440 else
11441 if (output_type == TCC_OUTPUT_EXE)
11442 strcpy(ext, ".exe");
11443 else
11444 #endif
11445 if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
11446 strcpy(ext, ".o");
11447 else
11448 pstrcpy(objfilename, sizeof(objfilename), "a.out");
11449 outfile = objfilename;
11453 if (do_bench) {
11454 start_time = getclock_us();
11457 tcc_set_output_type(s, output_type);
11459 /* compile or add each files or library */
11460 for(i = 0; i < nb_files && ret == 0; i++) {
11461 const char *filename;
11463 filename = files[i];
11464 if (output_type == TCC_OUTPUT_PREPROCESS) {
11465 if (tcc_add_file_internal(s, filename,
11466 AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
11467 ret = 1;
11468 } else if (filename[0] == '-' && filename[1]) {
11469 if (tcc_add_library(s, filename + 2) < 0)
11470 error("cannot find %s", filename);
11471 } else {
11472 if (1 == verbose)
11473 printf("-> %s\n", filename);
11474 if (tcc_add_file(s, filename) < 0)
11475 ret = 1;
11479 /* free all files */
11480 tcc_free(files);
11482 if (ret)
11483 goto the_end;
11485 if (do_bench) {
11486 double total_time;
11487 total_time = (double)(getclock_us() - start_time) / 1000000.0;
11488 if (total_time < 0.001)
11489 total_time = 0.001;
11490 if (total_bytes < 1)
11491 total_bytes = 1;
11492 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11493 tok_ident - TOK_IDENT, total_lines, total_bytes,
11494 total_time, (int)(total_lines / total_time),
11495 total_bytes / total_time / 1000000.0);
11498 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
11499 if (outfile)
11500 fclose(s->outfile);
11501 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
11502 ret = tcc_run(s, argc - optind, argv + optind);
11503 } else
11504 ret = tcc_output_file(s, outfile) ? 1 : 0;
11505 the_end:
11506 /* XXX: cannot do it with bound checking because of the malloc hooks */
11507 if (!do_bounds_check)
11508 tcc_delete(s);
11510 #ifdef MEM_DEBUG
11511 if (do_bench) {
11512 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
11514 #endif
11515 return ret;
11518 #endif