tcc -E: fix pasting empty tokens
[tinycc.git] / tcc.c
blob00758bc933617041046b346f2dd1ea1ba688c81c
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 *ptr, *saved_macro_ptr;
4433 int t;
4434 const char *p1, *p2;
4435 CValue cval;
4436 TokenString macro_str1;
4437 CString cstr;
4439 /* we search the first '##' */
4440 for(ptr = macro_str;;) {
4441 TOK_GET(t, ptr, cval);
4442 if (t == TOK_TWOSHARPS)
4443 break;
4444 /* nothing more to do if end of string */
4445 if (t == 0)
4446 return NULL;
4449 /* we saw '##', so we need more processing to handle it */
4450 cstr_new(&cstr);
4451 tok_str_new(&macro_str1);
4452 saved_macro_ptr = macro_ptr;
4453 /* XXX: get rid of the use of macro_ptr here */
4454 macro_ptr = (int *)macro_str;
4455 for(;;) {
4456 next_nomacro_spc();
4457 if (tok == 0)
4458 break;
4459 if (tok == TOK_TWOSHARPS)
4460 continue;
4461 while (*macro_ptr == TOK_TWOSHARPS) {
4462 t = *++macro_ptr;
4463 if (t && t != TOK_TWOSHARPS) {
4464 TOK_GET(t, macro_ptr, cval);
4465 /* We concatenate the two tokens if we have an
4466 identifier or a preprocessing number */
4467 cstr_reset(&cstr);
4468 p1 = get_tok_str(tok, &tokc);
4469 cstr_cat(&cstr, p1);
4470 p2 = get_tok_str(t, &cval);
4471 cstr_cat(&cstr, p2);
4472 cstr_ccat(&cstr, '\0');
4474 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4475 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4476 if (tok == TOK_PPNUM) {
4477 /* if number, then create a number token */
4478 /* NOTE: no need to allocate because
4479 tok_str_add2() does it */
4480 cstr_reset(&tokcstr);
4481 tokcstr = cstr;
4482 cstr_new(&cstr);
4483 tokc.cstr = &tokcstr;
4484 } else {
4485 /* if identifier, we must do a test to
4486 validate we have a correct identifier */
4487 if (t == TOK_PPNUM) {
4488 const char *p;
4489 int c;
4491 p = p2;
4492 for(;;) {
4493 c = *p;
4494 if (c == '\0')
4495 break;
4496 p++;
4497 if (!isnum(c) && !isid(c))
4498 goto error_pasting;
4501 ts = tok_alloc(cstr.data, strlen(cstr.data));
4502 tok = ts->tok; /* modify current token */
4504 } else {
4505 const char *str = cstr.data;
4506 const unsigned char *q;
4508 /* we look for a valid token */
4509 /* XXX: do more extensive checks */
4510 if (!strcmp(str, ">>=")) {
4511 tok = TOK_A_SAR;
4512 } else if (!strcmp(str, "<<=")) {
4513 tok = TOK_A_SHL;
4514 } else if (strlen(str) == 2) {
4515 /* search in two bytes table */
4516 q = tok_two_chars;
4517 for(;;) {
4518 if (!*q)
4519 goto error_pasting;
4520 if (q[0] == str[0] && q[1] == str[1])
4521 break;
4522 q += 3;
4524 tok = q[2];
4525 } else {
4526 error_pasting:
4527 /* NOTE: because get_tok_str use a static buffer,
4528 we must save it */
4529 cstr_reset(&cstr);
4530 p1 = get_tok_str(tok, &tokc);
4531 cstr_cat(&cstr, p1);
4532 cstr_ccat(&cstr, '\0');
4533 p2 = get_tok_str(t, &cval);
4534 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4535 /* cannot merge tokens: just add them separately */
4536 tok_str_add2(&macro_str1, tok, &tokc);
4537 /* XXX: free associated memory ? */
4538 tok = t;
4539 tokc = cval;
4544 tok_str_add2(&macro_str1, tok, &tokc);
4546 macro_ptr = (int *)saved_macro_ptr;
4547 cstr_free(&cstr);
4548 tok_str_add(&macro_str1, 0);
4549 return macro_str1.str;
4553 /* do macro substitution of macro_str and add result to
4554 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4555 inside to avoid recursing. */
4556 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4557 const int *macro_str, struct macro_level ** can_read_stream)
4559 Sym *s;
4560 int *macro_str1;
4561 const int *ptr;
4562 int t, ret, spc;
4563 CValue cval;
4564 struct macro_level ml;
4566 /* first scan for '##' operator handling */
4567 ptr = macro_str;
4568 macro_str1 = macro_twosharps(ptr);
4569 if (macro_str1)
4570 ptr = macro_str1;
4571 spc = 0;
4572 while (1) {
4573 /* NOTE: ptr == NULL can only happen if tokens are read from
4574 file stream due to a macro function call */
4575 if (ptr == NULL)
4576 break;
4577 TOK_GET(t, ptr, cval);
4578 if (t == 0)
4579 break;
4580 s = define_find(t);
4581 if (s != NULL) {
4582 /* if nested substitution, do nothing */
4583 if (sym_find2(*nested_list, t))
4584 goto no_subst;
4585 ml.p = macro_ptr;
4586 if (can_read_stream)
4587 ml.prev = *can_read_stream, *can_read_stream = &ml;
4588 macro_ptr = (int *)ptr;
4589 tok = t;
4590 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4591 ptr = (int *)macro_ptr;
4592 macro_ptr = ml.p;
4593 if (can_read_stream && *can_read_stream == &ml)
4594 *can_read_stream = ml.prev;
4595 if (ret != 0)
4596 goto no_subst;
4597 } else {
4598 no_subst:
4599 if (!check_space(t, &spc))
4600 tok_str_add2(tok_str, t, &cval);
4603 if (macro_str1)
4604 tok_str_free(macro_str1);
4607 /* return next token with macro substitution */
4608 static void next(void)
4610 Sym *nested_list, *s;
4611 TokenString str;
4612 struct macro_level *ml;
4614 redo:
4615 if (parse_flags & PARSE_FLAG_SPACES)
4616 next_nomacro_spc();
4617 else
4618 next_nomacro();
4619 if (!macro_ptr) {
4620 /* if not reading from macro substituted string, then try
4621 to substitute macros */
4622 if (tok >= TOK_IDENT &&
4623 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4624 s = define_find(tok);
4625 if (s) {
4626 /* we have a macro: we try to substitute */
4627 tok_str_new(&str);
4628 nested_list = NULL;
4629 ml = NULL;
4630 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4631 /* substitution done, NOTE: maybe empty */
4632 tok_str_add(&str, 0);
4633 macro_ptr = str.str;
4634 macro_ptr_allocated = str.str;
4635 goto redo;
4639 } else {
4640 if (tok == 0) {
4641 /* end of macro or end of unget buffer */
4642 if (unget_buffer_enabled) {
4643 macro_ptr = unget_saved_macro_ptr;
4644 unget_buffer_enabled = 0;
4645 } else {
4646 /* end of macro string: free it */
4647 tok_str_free(macro_ptr_allocated);
4648 macro_ptr = NULL;
4650 goto redo;
4654 /* convert preprocessor tokens into C tokens */
4655 if (tok == TOK_PPNUM &&
4656 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4657 parse_number((char *)tokc.cstr->data);
4661 /* push back current token and set current token to 'last_tok'. Only
4662 identifier case handled for labels. */
4663 static inline void unget_tok(int last_tok)
4665 int i, n;
4666 int *q;
4667 unget_saved_macro_ptr = macro_ptr;
4668 unget_buffer_enabled = 1;
4669 q = unget_saved_buffer;
4670 macro_ptr = q;
4671 *q++ = tok;
4672 n = tok_ext_size(tok) - 1;
4673 for(i=0;i<n;i++)
4674 *q++ = tokc.tab[i];
4675 *q = 0; /* end of token string */
4676 tok = last_tok;
4680 void swap(int *p, int *q)
4682 int t;
4683 t = *p;
4684 *p = *q;
4685 *q = t;
4688 void vsetc(CType *type, int r, CValue *vc)
4690 int v;
4692 if (vtop >= vstack + (VSTACK_SIZE - 1))
4693 error("memory full");
4694 /* cannot let cpu flags if other instruction are generated. Also
4695 avoid leaving VT_JMP anywhere except on the top of the stack
4696 because it would complicate the code generator. */
4697 if (vtop >= vstack) {
4698 v = vtop->r & VT_VALMASK;
4699 if (v == VT_CMP || (v & ~1) == VT_JMP)
4700 gv(RC_INT);
4702 vtop++;
4703 vtop->type = *type;
4704 vtop->r = r;
4705 vtop->r2 = VT_CONST;
4706 vtop->c = *vc;
4709 /* push integer constant */
4710 void vpushi(int v)
4712 CValue cval;
4713 cval.i = v;
4714 vsetc(&int_type, VT_CONST, &cval);
4717 /* push long long constant */
4718 void vpushll(long long v)
4720 CValue cval;
4721 CType ctype;
4722 ctype.t = VT_LLONG;
4723 cval.ull = v;
4724 vsetc(&ctype, VT_CONST, &cval);
4727 /* Return a static symbol pointing to a section */
4728 static Sym *get_sym_ref(CType *type, Section *sec,
4729 unsigned long offset, unsigned long size)
4731 int v;
4732 Sym *sym;
4734 v = anon_sym++;
4735 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4736 sym->type.ref = type->ref;
4737 sym->r = VT_CONST | VT_SYM;
4738 put_extern_sym(sym, sec, offset, size);
4739 return sym;
4742 /* push a reference to a section offset by adding a dummy symbol */
4743 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4745 CValue cval;
4747 cval.ul = 0;
4748 vsetc(type, VT_CONST | VT_SYM, &cval);
4749 vtop->sym = get_sym_ref(type, sec, offset, size);
4752 /* define a new external reference to a symbol 'v' of type 'u' */
4753 static Sym *external_global_sym(int v, CType *type, int r)
4755 Sym *s;
4757 s = sym_find(v);
4758 if (!s) {
4759 /* push forward reference */
4760 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4761 s->type.ref = type->ref;
4762 s->r = r | VT_CONST | VT_SYM;
4764 return s;
4767 /* define a new external reference to a symbol 'v' of type 'u' */
4768 static Sym *external_sym(int v, CType *type, int r)
4770 Sym *s;
4772 s = sym_find(v);
4773 if (!s) {
4774 /* push forward reference */
4775 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4776 s->type.t |= VT_EXTERN;
4777 } else {
4778 if (!is_compatible_types(&s->type, type))
4779 error("incompatible types for redefinition of '%s'",
4780 get_tok_str(v, NULL));
4782 return s;
4785 /* push a reference to global symbol v */
4786 static void vpush_global_sym(CType *type, int v)
4788 Sym *sym;
4789 CValue cval;
4791 sym = external_global_sym(v, type, 0);
4792 cval.ul = 0;
4793 vsetc(type, VT_CONST | VT_SYM, &cval);
4794 vtop->sym = sym;
4797 void vset(CType *type, int r, int v)
4799 CValue cval;
4801 cval.i = v;
4802 vsetc(type, r, &cval);
4805 void vseti(int r, int v)
4807 CType type;
4808 type.t = VT_INT;
4809 vset(&type, r, v);
4812 void vswap(void)
4814 SValue tmp;
4816 tmp = vtop[0];
4817 vtop[0] = vtop[-1];
4818 vtop[-1] = tmp;
4821 void vpushv(SValue *v)
4823 if (vtop >= vstack + (VSTACK_SIZE - 1))
4824 error("memory full");
4825 vtop++;
4826 *vtop = *v;
4829 void vdup(void)
4831 vpushv(vtop);
4834 /* save r to the memory stack, and mark it as being free */
4835 void save_reg(int r)
4837 int l, saved, size, align;
4838 SValue *p, sv;
4839 CType *type;
4841 /* modify all stack values */
4842 saved = 0;
4843 l = 0;
4844 for(p=vstack;p<=vtop;p++) {
4845 if ((p->r & VT_VALMASK) == r ||
4846 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4847 /* must save value on stack if not already done */
4848 if (!saved) {
4849 /* NOTE: must reload 'r' because r might be equal to r2 */
4850 r = p->r & VT_VALMASK;
4851 /* store register in the stack */
4852 type = &p->type;
4853 if ((p->r & VT_LVAL) ||
4854 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4855 #ifdef TCC_TARGET_X86_64
4856 type = &char_pointer_type;
4857 #else
4858 type = &int_type;
4859 #endif
4860 size = type_size(type, &align);
4861 loc = (loc - size) & -align;
4862 sv.type.t = type->t;
4863 sv.r = VT_LOCAL | VT_LVAL;
4864 sv.c.ul = loc;
4865 store(r, &sv);
4866 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
4867 /* x86 specific: need to pop fp register ST0 if saved */
4868 if (r == TREG_ST0) {
4869 o(0xd9dd); /* fstp %st(1) */
4871 #endif
4872 #ifndef TCC_TARGET_X86_64
4873 /* special long long case */
4874 if ((type->t & VT_BTYPE) == VT_LLONG) {
4875 sv.c.ul += 4;
4876 store(p->r2, &sv);
4878 #endif
4879 l = loc;
4880 saved = 1;
4882 /* mark that stack entry as being saved on the stack */
4883 if (p->r & VT_LVAL) {
4884 /* also clear the bounded flag because the
4885 relocation address of the function was stored in
4886 p->c.ul */
4887 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4888 } else {
4889 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4891 p->r2 = VT_CONST;
4892 p->c.ul = l;
4897 /* find a register of class 'rc2' with at most one reference on stack.
4898 * If none, call get_reg(rc) */
4899 int get_reg_ex(int rc, int rc2)
4901 int r;
4902 SValue *p;
4904 for(r=0;r<NB_REGS;r++) {
4905 if (reg_classes[r] & rc2) {
4906 int n;
4907 n=0;
4908 for(p = vstack; p <= vtop; p++) {
4909 if ((p->r & VT_VALMASK) == r ||
4910 (p->r2 & VT_VALMASK) == r)
4911 n++;
4913 if (n <= 1)
4914 return r;
4917 return get_reg(rc);
4920 /* find a free register of class 'rc'. If none, save one register */
4921 int get_reg(int rc)
4923 int r;
4924 SValue *p;
4926 /* find a free register */
4927 for(r=0;r<NB_REGS;r++) {
4928 if (reg_classes[r] & rc) {
4929 for(p=vstack;p<=vtop;p++) {
4930 if ((p->r & VT_VALMASK) == r ||
4931 (p->r2 & VT_VALMASK) == r)
4932 goto notfound;
4934 return r;
4936 notfound: ;
4939 /* no register left : free the first one on the stack (VERY
4940 IMPORTANT to start from the bottom to ensure that we don't
4941 spill registers used in gen_opi()) */
4942 for(p=vstack;p<=vtop;p++) {
4943 r = p->r & VT_VALMASK;
4944 if (r < VT_CONST && (reg_classes[r] & rc))
4945 goto save_found;
4946 /* also look at second register (if long long) */
4947 r = p->r2 & VT_VALMASK;
4948 if (r < VT_CONST && (reg_classes[r] & rc)) {
4949 save_found:
4950 save_reg(r);
4951 return r;
4954 /* Should never comes here */
4955 return -1;
4958 /* save registers up to (vtop - n) stack entry */
4959 void save_regs(int n)
4961 int r;
4962 SValue *p, *p1;
4963 p1 = vtop - n;
4964 for(p = vstack;p <= p1; p++) {
4965 r = p->r & VT_VALMASK;
4966 if (r < VT_CONST) {
4967 save_reg(r);
4972 /* move register 's' to 'r', and flush previous value of r to memory
4973 if needed */
4974 void move_reg(int r, int s)
4976 SValue sv;
4978 if (r != s) {
4979 save_reg(r);
4980 sv.type.t = VT_INT;
4981 sv.r = s;
4982 sv.c.ul = 0;
4983 load(r, &sv);
4987 /* get address of vtop (vtop MUST BE an lvalue) */
4988 void gaddrof(void)
4990 vtop->r &= ~VT_LVAL;
4991 /* tricky: if saved lvalue, then we can go back to lvalue */
4992 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4993 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4996 #ifdef CONFIG_TCC_BCHECK
4997 /* generate lvalue bound code */
4998 void gbound(void)
5000 int lval_type;
5001 CType type1;
5003 vtop->r &= ~VT_MUSTBOUND;
5004 /* if lvalue, then use checking code before dereferencing */
5005 if (vtop->r & VT_LVAL) {
5006 /* if not VT_BOUNDED value, then make one */
5007 if (!(vtop->r & VT_BOUNDED)) {
5008 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
5009 /* must save type because we must set it to int to get pointer */
5010 type1 = vtop->type;
5011 vtop->type.t = VT_INT;
5012 gaddrof();
5013 vpushi(0);
5014 gen_bounded_ptr_add();
5015 vtop->r |= lval_type;
5016 vtop->type = type1;
5018 /* then check for dereferencing */
5019 gen_bounded_ptr_deref();
5022 #endif
5024 /* store vtop a register belonging to class 'rc'. lvalues are
5025 converted to values. Cannot be used if cannot be converted to
5026 register value (such as structures). */
5027 int gv(int rc)
5029 int r, rc2, bit_pos, bit_size, size, align, i;
5031 /* NOTE: get_reg can modify vstack[] */
5032 if (vtop->type.t & VT_BITFIELD) {
5033 CType type;
5034 int bits = 32;
5035 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
5036 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5037 /* remove bit field info to avoid loops */
5038 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5039 /* cast to int to propagate signedness in following ops */
5040 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
5041 type.t = VT_LLONG;
5042 bits = 64;
5043 } else
5044 type.t = VT_INT;
5045 if((vtop->type.t & VT_UNSIGNED) ||
5046 (vtop->type.t & VT_BTYPE) == VT_BOOL)
5047 type.t |= VT_UNSIGNED;
5048 gen_cast(&type);
5049 /* generate shifts */
5050 vpushi(bits - (bit_pos + bit_size));
5051 gen_op(TOK_SHL);
5052 vpushi(bits - bit_size);
5053 /* NOTE: transformed to SHR if unsigned */
5054 gen_op(TOK_SAR);
5055 r = gv(rc);
5056 } else {
5057 if (is_float(vtop->type.t) &&
5058 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5059 Sym *sym;
5060 int *ptr;
5061 unsigned long offset;
5062 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5063 CValue check;
5064 #endif
5066 /* XXX: unify with initializers handling ? */
5067 /* CPUs usually cannot use float constants, so we store them
5068 generically in data segment */
5069 size = type_size(&vtop->type, &align);
5070 offset = (data_section->data_offset + align - 1) & -align;
5071 data_section->data_offset = offset;
5072 /* XXX: not portable yet */
5073 #if defined(__i386__) || defined(__x86_64__)
5074 /* Zero pad x87 tenbyte long doubles */
5075 if (size == LDOUBLE_SIZE)
5076 vtop->c.tab[2] &= 0xffff;
5077 #endif
5078 ptr = section_ptr_add(data_section, size);
5079 size = size >> 2;
5080 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5081 check.d = 1;
5082 if(check.tab[0])
5083 for(i=0;i<size;i++)
5084 ptr[i] = vtop->c.tab[size-1-i];
5085 else
5086 #endif
5087 for(i=0;i<size;i++)
5088 ptr[i] = vtop->c.tab[i];
5089 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
5090 vtop->r |= VT_LVAL | VT_SYM;
5091 vtop->sym = sym;
5092 vtop->c.ul = 0;
5094 #ifdef CONFIG_TCC_BCHECK
5095 if (vtop->r & VT_MUSTBOUND)
5096 gbound();
5097 #endif
5099 r = vtop->r & VT_VALMASK;
5100 rc2 = RC_INT;
5101 if (rc == RC_IRET)
5102 rc2 = RC_LRET;
5103 /* need to reload if:
5104 - constant
5105 - lvalue (need to dereference pointer)
5106 - already a register, but not in the right class */
5107 if (r >= VT_CONST ||
5108 (vtop->r & VT_LVAL) ||
5109 !(reg_classes[r] & rc) ||
5110 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
5111 !(reg_classes[vtop->r2] & rc2))) {
5112 r = get_reg(rc);
5113 #ifndef TCC_TARGET_X86_64
5114 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
5115 int r2;
5116 unsigned long long ll;
5117 /* two register type load : expand to two words
5118 temporarily */
5119 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5120 /* load constant */
5121 ll = vtop->c.ull;
5122 vtop->c.ui = ll; /* first word */
5123 load(r, vtop);
5124 vtop->r = r; /* save register value */
5125 vpushi(ll >> 32); /* second word */
5126 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
5127 (vtop->r & VT_LVAL)) {
5128 /* We do not want to modifier the long long
5129 pointer here, so the safest (and less
5130 efficient) is to save all the other registers
5131 in the stack. XXX: totally inefficient. */
5132 save_regs(1);
5133 /* load from memory */
5134 load(r, vtop);
5135 vdup();
5136 vtop[-1].r = r; /* save register value */
5137 /* increment pointer to get second word */
5138 vtop->type.t = VT_INT;
5139 gaddrof();
5140 vpushi(4);
5141 gen_op('+');
5142 vtop->r |= VT_LVAL;
5143 } else {
5144 /* move registers */
5145 load(r, vtop);
5146 vdup();
5147 vtop[-1].r = r; /* save register value */
5148 vtop->r = vtop[-1].r2;
5150 /* allocate second register */
5151 r2 = get_reg(rc2);
5152 load(r2, vtop);
5153 vpop();
5154 /* write second register */
5155 vtop->r2 = r2;
5156 } else
5157 #endif
5158 if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
5159 int t1, t;
5160 /* lvalue of scalar type : need to use lvalue type
5161 because of possible cast */
5162 t = vtop->type.t;
5163 t1 = t;
5164 /* compute memory access type */
5165 if (vtop->r & VT_LVAL_BYTE)
5166 t = VT_BYTE;
5167 else if (vtop->r & VT_LVAL_SHORT)
5168 t = VT_SHORT;
5169 if (vtop->r & VT_LVAL_UNSIGNED)
5170 t |= VT_UNSIGNED;
5171 vtop->type.t = t;
5172 load(r, vtop);
5173 /* restore wanted type */
5174 vtop->type.t = t1;
5175 } else {
5176 /* one register type load */
5177 load(r, vtop);
5180 vtop->r = r;
5181 #ifdef TCC_TARGET_C67
5182 /* uses register pairs for doubles */
5183 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5184 vtop->r2 = r+1;
5185 #endif
5187 return r;
5190 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
5191 void gv2(int rc1, int rc2)
5193 int v;
5195 /* generate more generic register first. But VT_JMP or VT_CMP
5196 values must be generated first in all cases to avoid possible
5197 reload errors */
5198 v = vtop[0].r & VT_VALMASK;
5199 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
5200 vswap();
5201 gv(rc1);
5202 vswap();
5203 gv(rc2);
5204 /* test if reload is needed for first register */
5205 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
5206 vswap();
5207 gv(rc1);
5208 vswap();
5210 } else {
5211 gv(rc2);
5212 vswap();
5213 gv(rc1);
5214 vswap();
5215 /* test if reload is needed for first register */
5216 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
5217 gv(rc2);
5222 /* wrapper around RC_FRET to return a register by type */
5223 int rc_fret(int t)
5225 #ifdef TCC_TARGET_X86_64
5226 if (t == VT_LDOUBLE) {
5227 return RC_ST0;
5229 #endif
5230 return RC_FRET;
5233 /* wrapper around REG_FRET to return a register by type */
5234 int reg_fret(int t)
5236 #ifdef TCC_TARGET_X86_64
5237 if (t == VT_LDOUBLE) {
5238 return TREG_ST0;
5240 #endif
5241 return REG_FRET;
5244 /* expand long long on stack in two int registers */
5245 void lexpand(void)
5247 int u;
5249 u = vtop->type.t & VT_UNSIGNED;
5250 gv(RC_INT);
5251 vdup();
5252 vtop[0].r = vtop[-1].r2;
5253 vtop[0].r2 = VT_CONST;
5254 vtop[-1].r2 = VT_CONST;
5255 vtop[0].type.t = VT_INT | u;
5256 vtop[-1].type.t = VT_INT | u;
5259 #ifdef TCC_TARGET_ARM
5260 /* expand long long on stack */
5261 void lexpand_nr(void)
5263 int u,v;
5265 u = vtop->type.t & VT_UNSIGNED;
5266 vdup();
5267 vtop->r2 = VT_CONST;
5268 vtop->type.t = VT_INT | u;
5269 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
5270 if (v == VT_CONST) {
5271 vtop[-1].c.ui = vtop->c.ull;
5272 vtop->c.ui = vtop->c.ull >> 32;
5273 vtop->r = VT_CONST;
5274 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
5275 vtop->c.ui += 4;
5276 vtop->r = vtop[-1].r;
5277 } else if (v > VT_CONST) {
5278 vtop--;
5279 lexpand();
5280 } else
5281 vtop->r = vtop[-1].r2;
5282 vtop[-1].r2 = VT_CONST;
5283 vtop[-1].type.t = VT_INT | u;
5285 #endif
5287 /* build a long long from two ints */
5288 void lbuild(int t)
5290 gv2(RC_INT, RC_INT);
5291 vtop[-1].r2 = vtop[0].r;
5292 vtop[-1].type.t = t;
5293 vpop();
5296 /* rotate n first stack elements to the bottom
5297 I1 ... In -> I2 ... In I1 [top is right]
5299 void vrotb(int n)
5301 int i;
5302 SValue tmp;
5304 tmp = vtop[-n + 1];
5305 for(i=-n+1;i!=0;i++)
5306 vtop[i] = vtop[i+1];
5307 vtop[0] = tmp;
5310 /* rotate n first stack elements to the top
5311 I1 ... In -> In I1 ... I(n-1) [top is right]
5313 void vrott(int n)
5315 int i;
5316 SValue tmp;
5318 tmp = vtop[0];
5319 for(i = 0;i < n - 1; i++)
5320 vtop[-i] = vtop[-i - 1];
5321 vtop[-n + 1] = tmp;
5324 #ifdef TCC_TARGET_ARM
5325 /* like vrott but in other direction
5326 In ... I1 -> I(n-1) ... I1 In [top is right]
5328 void vnrott(int n)
5330 int i;
5331 SValue tmp;
5333 tmp = vtop[-n + 1];
5334 for(i = n - 1; i > 0; i--)
5335 vtop[-i] = vtop[-i + 1];
5336 vtop[0] = tmp;
5338 #endif
5340 /* pop stack value */
5341 void vpop(void)
5343 int v;
5344 v = vtop->r & VT_VALMASK;
5345 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
5346 /* for x86, we need to pop the FP stack */
5347 if (v == TREG_ST0 && !nocode_wanted) {
5348 o(0xd9dd); /* fstp %st(1) */
5349 } else
5350 #endif
5351 if (v == VT_JMP || v == VT_JMPI) {
5352 /* need to put correct jump if && or || without test */
5353 gsym(vtop->c.ul);
5355 vtop--;
5358 /* convert stack entry to register and duplicate its value in another
5359 register */
5360 void gv_dup(void)
5362 int rc, t, r, r1;
5363 SValue sv;
5365 t = vtop->type.t;
5366 if ((t & VT_BTYPE) == VT_LLONG) {
5367 lexpand();
5368 gv_dup();
5369 vswap();
5370 vrotb(3);
5371 gv_dup();
5372 vrotb(4);
5373 /* stack: H L L1 H1 */
5374 lbuild(t);
5375 vrotb(3);
5376 vrotb(3);
5377 vswap();
5378 lbuild(t);
5379 vswap();
5380 } else {
5381 /* duplicate value */
5382 rc = RC_INT;
5383 sv.type.t = VT_INT;
5384 if (is_float(t)) {
5385 rc = RC_FLOAT;
5386 #ifdef TCC_TARGET_X86_64
5387 if ((t & VT_BTYPE) == VT_LDOUBLE) {
5388 rc = RC_ST0;
5390 #endif
5391 sv.type.t = t;
5393 r = gv(rc);
5394 r1 = get_reg(rc);
5395 sv.r = r;
5396 sv.c.ul = 0;
5397 load(r1, &sv); /* move r to r1 */
5398 vdup();
5399 /* duplicates value */
5400 vtop->r = r1;
5404 #ifndef TCC_TARGET_X86_64
5405 /* generate CPU independent (unsigned) long long operations */
5406 void gen_opl(int op)
5408 int t, a, b, op1, c, i;
5409 int func;
5410 unsigned short reg_iret = REG_IRET;
5411 unsigned short reg_lret = REG_LRET;
5412 SValue tmp;
5414 switch(op) {
5415 case '/':
5416 case TOK_PDIV:
5417 func = TOK___divdi3;
5418 goto gen_func;
5419 case TOK_UDIV:
5420 func = TOK___udivdi3;
5421 goto gen_func;
5422 case '%':
5423 func = TOK___moddi3;
5424 goto gen_mod_func;
5425 case TOK_UMOD:
5426 func = TOK___umoddi3;
5427 gen_mod_func:
5428 #ifdef TCC_ARM_EABI
5429 reg_iret = TREG_R2;
5430 reg_lret = TREG_R3;
5431 #endif
5432 gen_func:
5433 /* call generic long long function */
5434 vpush_global_sym(&func_old_type, func);
5435 vrott(3);
5436 gfunc_call(2);
5437 vpushi(0);
5438 vtop->r = reg_iret;
5439 vtop->r2 = reg_lret;
5440 break;
5441 case '^':
5442 case '&':
5443 case '|':
5444 case '*':
5445 case '+':
5446 case '-':
5447 t = vtop->type.t;
5448 vswap();
5449 lexpand();
5450 vrotb(3);
5451 lexpand();
5452 /* stack: L1 H1 L2 H2 */
5453 tmp = vtop[0];
5454 vtop[0] = vtop[-3];
5455 vtop[-3] = tmp;
5456 tmp = vtop[-2];
5457 vtop[-2] = vtop[-3];
5458 vtop[-3] = tmp;
5459 vswap();
5460 /* stack: H1 H2 L1 L2 */
5461 if (op == '*') {
5462 vpushv(vtop - 1);
5463 vpushv(vtop - 1);
5464 gen_op(TOK_UMULL);
5465 lexpand();
5466 /* stack: H1 H2 L1 L2 ML MH */
5467 for(i=0;i<4;i++)
5468 vrotb(6);
5469 /* stack: ML MH H1 H2 L1 L2 */
5470 tmp = vtop[0];
5471 vtop[0] = vtop[-2];
5472 vtop[-2] = tmp;
5473 /* stack: ML MH H1 L2 H2 L1 */
5474 gen_op('*');
5475 vrotb(3);
5476 vrotb(3);
5477 gen_op('*');
5478 /* stack: ML MH M1 M2 */
5479 gen_op('+');
5480 gen_op('+');
5481 } else if (op == '+' || op == '-') {
5482 /* XXX: add non carry method too (for MIPS or alpha) */
5483 if (op == '+')
5484 op1 = TOK_ADDC1;
5485 else
5486 op1 = TOK_SUBC1;
5487 gen_op(op1);
5488 /* stack: H1 H2 (L1 op L2) */
5489 vrotb(3);
5490 vrotb(3);
5491 gen_op(op1 + 1); /* TOK_xxxC2 */
5492 } else {
5493 gen_op(op);
5494 /* stack: H1 H2 (L1 op L2) */
5495 vrotb(3);
5496 vrotb(3);
5497 /* stack: (L1 op L2) H1 H2 */
5498 gen_op(op);
5499 /* stack: (L1 op L2) (H1 op H2) */
5501 /* stack: L H */
5502 lbuild(t);
5503 break;
5504 case TOK_SAR:
5505 case TOK_SHR:
5506 case TOK_SHL:
5507 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5508 t = vtop[-1].type.t;
5509 vswap();
5510 lexpand();
5511 vrotb(3);
5512 /* stack: L H shift */
5513 c = (int)vtop->c.i;
5514 /* constant: simpler */
5515 /* NOTE: all comments are for SHL. the other cases are
5516 done by swaping words */
5517 vpop();
5518 if (op != TOK_SHL)
5519 vswap();
5520 if (c >= 32) {
5521 /* stack: L H */
5522 vpop();
5523 if (c > 32) {
5524 vpushi(c - 32);
5525 gen_op(op);
5527 if (op != TOK_SAR) {
5528 vpushi(0);
5529 } else {
5530 gv_dup();
5531 vpushi(31);
5532 gen_op(TOK_SAR);
5534 vswap();
5535 } else {
5536 vswap();
5537 gv_dup();
5538 /* stack: H L L */
5539 vpushi(c);
5540 gen_op(op);
5541 vswap();
5542 vpushi(32 - c);
5543 if (op == TOK_SHL)
5544 gen_op(TOK_SHR);
5545 else
5546 gen_op(TOK_SHL);
5547 vrotb(3);
5548 /* stack: L L H */
5549 vpushi(c);
5550 if (op == TOK_SHL)
5551 gen_op(TOK_SHL);
5552 else
5553 gen_op(TOK_SHR);
5554 gen_op('|');
5556 if (op != TOK_SHL)
5557 vswap();
5558 lbuild(t);
5559 } else {
5560 /* XXX: should provide a faster fallback on x86 ? */
5561 switch(op) {
5562 case TOK_SAR:
5563 func = TOK___ashrdi3;
5564 goto gen_func;
5565 case TOK_SHR:
5566 func = TOK___lshrdi3;
5567 goto gen_func;
5568 case TOK_SHL:
5569 func = TOK___ashldi3;
5570 goto gen_func;
5573 break;
5574 default:
5575 /* compare operations */
5576 t = vtop->type.t;
5577 vswap();
5578 lexpand();
5579 vrotb(3);
5580 lexpand();
5581 /* stack: L1 H1 L2 H2 */
5582 tmp = vtop[-1];
5583 vtop[-1] = vtop[-2];
5584 vtop[-2] = tmp;
5585 /* stack: L1 L2 H1 H2 */
5586 /* compare high */
5587 op1 = op;
5588 /* when values are equal, we need to compare low words. since
5589 the jump is inverted, we invert the test too. */
5590 if (op1 == TOK_LT)
5591 op1 = TOK_LE;
5592 else if (op1 == TOK_GT)
5593 op1 = TOK_GE;
5594 else if (op1 == TOK_ULT)
5595 op1 = TOK_ULE;
5596 else if (op1 == TOK_UGT)
5597 op1 = TOK_UGE;
5598 a = 0;
5599 b = 0;
5600 gen_op(op1);
5601 if (op1 != TOK_NE) {
5602 a = gtst(1, 0);
5604 if (op != TOK_EQ) {
5605 /* generate non equal test */
5606 /* XXX: NOT PORTABLE yet */
5607 if (a == 0) {
5608 b = gtst(0, 0);
5609 } else {
5610 #if defined(TCC_TARGET_I386)
5611 b = psym(0x850f, 0);
5612 #elif defined(TCC_TARGET_ARM)
5613 b = ind;
5614 o(0x1A000000 | encbranch(ind, 0, 1));
5615 #elif defined(TCC_TARGET_C67)
5616 error("not implemented");
5617 #else
5618 #error not supported
5619 #endif
5622 /* compare low. Always unsigned */
5623 op1 = op;
5624 if (op1 == TOK_LT)
5625 op1 = TOK_ULT;
5626 else if (op1 == TOK_LE)
5627 op1 = TOK_ULE;
5628 else if (op1 == TOK_GT)
5629 op1 = TOK_UGT;
5630 else if (op1 == TOK_GE)
5631 op1 = TOK_UGE;
5632 gen_op(op1);
5633 a = gtst(1, a);
5634 gsym(b);
5635 vseti(VT_JMPI, a);
5636 break;
5639 #endif
5641 /* handle integer constant optimizations and various machine
5642 independent opt */
5643 void gen_opic(int op)
5645 int c1, c2, t1, t2, n;
5646 SValue *v1, *v2;
5647 long long l1, l2;
5648 typedef unsigned long long U;
5650 v1 = vtop - 1;
5651 v2 = vtop;
5652 t1 = v1->type.t & VT_BTYPE;
5653 t2 = v2->type.t & VT_BTYPE;
5655 if (t1 == VT_LLONG)
5656 l1 = v1->c.ll;
5657 else if (v1->type.t & VT_UNSIGNED)
5658 l1 = v1->c.ui;
5659 else
5660 l1 = v1->c.i;
5662 if (t2 == VT_LLONG)
5663 l2 = v2->c.ll;
5664 else if (v2->type.t & VT_UNSIGNED)
5665 l2 = v2->c.ui;
5666 else
5667 l2 = v2->c.i;
5669 /* currently, we cannot do computations with forward symbols */
5670 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5671 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5672 if (c1 && c2) {
5673 switch(op) {
5674 case '+': l1 += l2; break;
5675 case '-': l1 -= l2; break;
5676 case '&': l1 &= l2; break;
5677 case '^': l1 ^= l2; break;
5678 case '|': l1 |= l2; break;
5679 case '*': l1 *= l2; break;
5681 case TOK_PDIV:
5682 case '/':
5683 case '%':
5684 case TOK_UDIV:
5685 case TOK_UMOD:
5686 /* if division by zero, generate explicit division */
5687 if (l2 == 0) {
5688 if (const_wanted)
5689 error("division by zero in constant");
5690 goto general_case;
5692 switch(op) {
5693 default: l1 /= l2; break;
5694 case '%': l1 %= l2; break;
5695 case TOK_UDIV: l1 = (U)l1 / l2; break;
5696 case TOK_UMOD: l1 = (U)l1 % l2; break;
5698 break;
5699 case TOK_SHL: l1 <<= l2; break;
5700 case TOK_SHR: l1 = (U)l1 >> l2; break;
5701 case TOK_SAR: l1 >>= l2; break;
5702 /* tests */
5703 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5704 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5705 case TOK_EQ: l1 = l1 == l2; break;
5706 case TOK_NE: l1 = l1 != l2; break;
5707 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5708 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5709 case TOK_LT: l1 = l1 < l2; break;
5710 case TOK_GE: l1 = l1 >= l2; break;
5711 case TOK_LE: l1 = l1 <= l2; break;
5712 case TOK_GT: l1 = l1 > l2; break;
5713 /* logical */
5714 case TOK_LAND: l1 = l1 && l2; break;
5715 case TOK_LOR: l1 = l1 || l2; break;
5716 default:
5717 goto general_case;
5719 v1->c.ll = l1;
5720 vtop--;
5721 } else {
5722 /* if commutative ops, put c2 as constant */
5723 if (c1 && (op == '+' || op == '&' || op == '^' ||
5724 op == '|' || op == '*')) {
5725 vswap();
5726 c2 = c1; //c = c1, c1 = c2, c2 = c;
5727 l2 = l1; //l = l1, l1 = l2, l2 = l;
5729 /* Filter out NOP operations like x*1, x-0, x&-1... */
5730 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5731 op == TOK_PDIV) &&
5732 l2 == 1) ||
5733 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5734 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5735 l2 == 0) ||
5736 (op == '&' &&
5737 l2 == -1))) {
5738 /* nothing to do */
5739 vtop--;
5740 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5741 /* try to use shifts instead of muls or divs */
5742 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5743 n = -1;
5744 while (l2) {
5745 l2 >>= 1;
5746 n++;
5748 vtop->c.ll = n;
5749 if (op == '*')
5750 op = TOK_SHL;
5751 else if (op == TOK_PDIV)
5752 op = TOK_SAR;
5753 else
5754 op = TOK_SHR;
5756 goto general_case;
5757 } else if (c2 && (op == '+' || op == '-') &&
5758 ((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5759 (VT_CONST | VT_SYM) ||
5760 (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
5761 /* symbol + constant case */
5762 if (op == '-')
5763 l2 = -l2;
5764 vtop--;
5765 vtop->c.ll += l2;
5766 } else {
5767 general_case:
5768 if (!nocode_wanted) {
5769 /* call low level op generator */
5770 if (t1 == VT_LLONG || t2 == VT_LLONG)
5771 gen_opl(op);
5772 else
5773 gen_opi(op);
5774 } else {
5775 vtop--;
5781 /* generate a floating point operation with constant propagation */
5782 void gen_opif(int op)
5784 int c1, c2;
5785 SValue *v1, *v2;
5786 long double f1, f2;
5788 v1 = vtop - 1;
5789 v2 = vtop;
5790 /* currently, we cannot do computations with forward symbols */
5791 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5792 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5793 if (c1 && c2) {
5794 if (v1->type.t == VT_FLOAT) {
5795 f1 = v1->c.f;
5796 f2 = v2->c.f;
5797 } else if (v1->type.t == VT_DOUBLE) {
5798 f1 = v1->c.d;
5799 f2 = v2->c.d;
5800 } else {
5801 f1 = v1->c.ld;
5802 f2 = v2->c.ld;
5805 /* NOTE: we only do constant propagation if finite number (not
5806 NaN or infinity) (ANSI spec) */
5807 if (!ieee_finite(f1) || !ieee_finite(f2))
5808 goto general_case;
5810 switch(op) {
5811 case '+': f1 += f2; break;
5812 case '-': f1 -= f2; break;
5813 case '*': f1 *= f2; break;
5814 case '/':
5815 if (f2 == 0.0) {
5816 if (const_wanted)
5817 error("division by zero in constant");
5818 goto general_case;
5820 f1 /= f2;
5821 break;
5822 /* XXX: also handles tests ? */
5823 default:
5824 goto general_case;
5826 /* XXX: overflow test ? */
5827 if (v1->type.t == VT_FLOAT) {
5828 v1->c.f = f1;
5829 } else if (v1->type.t == VT_DOUBLE) {
5830 v1->c.d = f1;
5831 } else {
5832 v1->c.ld = f1;
5834 vtop--;
5835 } else {
5836 general_case:
5837 if (!nocode_wanted) {
5838 gen_opf(op);
5839 } else {
5840 vtop--;
5845 static int pointed_size(CType *type)
5847 int align;
5848 return type_size(pointed_type(type), &align);
5851 static inline int is_null_pointer(SValue *p)
5853 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5854 return 0;
5855 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5856 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5859 static inline int is_integer_btype(int bt)
5861 return (bt == VT_BYTE || bt == VT_SHORT ||
5862 bt == VT_INT || bt == VT_LLONG);
5865 /* check types for comparison or substraction of pointers */
5866 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5868 CType *type1, *type2, tmp_type1, tmp_type2;
5869 int bt1, bt2;
5871 /* null pointers are accepted for all comparisons as gcc */
5872 if (is_null_pointer(p1) || is_null_pointer(p2))
5873 return;
5874 type1 = &p1->type;
5875 type2 = &p2->type;
5876 bt1 = type1->t & VT_BTYPE;
5877 bt2 = type2->t & VT_BTYPE;
5878 /* accept comparison between pointer and integer with a warning */
5879 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5880 if (op != TOK_LOR && op != TOK_LAND )
5881 warning("comparison between pointer and integer");
5882 return;
5885 /* both must be pointers or implicit function pointers */
5886 if (bt1 == VT_PTR) {
5887 type1 = pointed_type(type1);
5888 } else if (bt1 != VT_FUNC)
5889 goto invalid_operands;
5891 if (bt2 == VT_PTR) {
5892 type2 = pointed_type(type2);
5893 } else if (bt2 != VT_FUNC) {
5894 invalid_operands:
5895 error("invalid operands to binary %s", get_tok_str(op, NULL));
5897 if ((type1->t & VT_BTYPE) == VT_VOID ||
5898 (type2->t & VT_BTYPE) == VT_VOID)
5899 return;
5900 tmp_type1 = *type1;
5901 tmp_type2 = *type2;
5902 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5903 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5904 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5905 /* gcc-like error if '-' is used */
5906 if (op == '-')
5907 goto invalid_operands;
5908 else
5909 warning("comparison of distinct pointer types lacks a cast");
5913 /* generic gen_op: handles types problems */
5914 void gen_op(int op)
5916 int u, t1, t2, bt1, bt2, t;
5917 CType type1;
5919 t1 = vtop[-1].type.t;
5920 t2 = vtop[0].type.t;
5921 bt1 = t1 & VT_BTYPE;
5922 bt2 = t2 & VT_BTYPE;
5924 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5925 /* at least one operand is a pointer */
5926 /* relationnal op: must be both pointers */
5927 if (op >= TOK_ULT && op <= TOK_LOR) {
5928 check_comparison_pointer_types(vtop - 1, vtop, op);
5929 /* pointers are handled are unsigned */
5930 #ifdef TCC_TARGET_X86_64
5931 t = VT_LLONG | VT_UNSIGNED;
5932 #else
5933 t = VT_INT | VT_UNSIGNED;
5934 #endif
5935 goto std_op;
5937 /* if both pointers, then it must be the '-' op */
5938 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5939 if (op != '-')
5940 error("cannot use pointers here");
5941 check_comparison_pointer_types(vtop - 1, vtop, op);
5942 /* XXX: check that types are compatible */
5943 u = pointed_size(&vtop[-1].type);
5944 gen_opic(op);
5945 /* set to integer type */
5946 #ifdef TCC_TARGET_X86_64
5947 vtop->type.t = VT_LLONG;
5948 #else
5949 vtop->type.t = VT_INT;
5950 #endif
5951 vpushi(u);
5952 gen_op(TOK_PDIV);
5953 } else {
5954 /* exactly one pointer : must be '+' or '-'. */
5955 if (op != '-' && op != '+')
5956 error("cannot use pointers here");
5957 /* Put pointer as first operand */
5958 if (bt2 == VT_PTR) {
5959 vswap();
5960 swap(&t1, &t2);
5962 type1 = vtop[-1].type;
5963 #ifdef TCC_TARGET_X86_64
5964 vpushll(pointed_size(&vtop[-1].type));
5965 #else
5966 /* XXX: cast to int ? (long long case) */
5967 vpushi(pointed_size(&vtop[-1].type));
5968 #endif
5969 gen_op('*');
5970 #ifdef CONFIG_TCC_BCHECK
5971 /* if evaluating constant expression, no code should be
5972 generated, so no bound check */
5973 if (do_bounds_check && !const_wanted) {
5974 /* if bounded pointers, we generate a special code to
5975 test bounds */
5976 if (op == '-') {
5977 vpushi(0);
5978 vswap();
5979 gen_op('-');
5981 gen_bounded_ptr_add();
5982 } else
5983 #endif
5985 gen_opic(op);
5987 /* put again type if gen_opic() swaped operands */
5988 vtop->type = type1;
5990 } else if (is_float(bt1) || is_float(bt2)) {
5991 /* compute bigger type and do implicit casts */
5992 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5993 t = VT_LDOUBLE;
5994 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5995 t = VT_DOUBLE;
5996 } else {
5997 t = VT_FLOAT;
5999 /* floats can only be used for a few operations */
6000 if (op != '+' && op != '-' && op != '*' && op != '/' &&
6001 (op < TOK_ULT || op > TOK_GT))
6002 error("invalid operands for binary operation");
6003 goto std_op;
6004 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
6005 /* cast to biggest op */
6006 t = VT_LLONG;
6007 /* convert to unsigned if it does not fit in a long long */
6008 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
6009 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
6010 t |= VT_UNSIGNED;
6011 goto std_op;
6012 } else {
6013 /* integer operations */
6014 t = VT_INT;
6015 /* convert to unsigned if it does not fit in an integer */
6016 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
6017 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
6018 t |= VT_UNSIGNED;
6019 std_op:
6020 /* XXX: currently, some unsigned operations are explicit, so
6021 we modify them here */
6022 if (t & VT_UNSIGNED) {
6023 if (op == TOK_SAR)
6024 op = TOK_SHR;
6025 else if (op == '/')
6026 op = TOK_UDIV;
6027 else if (op == '%')
6028 op = TOK_UMOD;
6029 else if (op == TOK_LT)
6030 op = TOK_ULT;
6031 else if (op == TOK_GT)
6032 op = TOK_UGT;
6033 else if (op == TOK_LE)
6034 op = TOK_ULE;
6035 else if (op == TOK_GE)
6036 op = TOK_UGE;
6038 vswap();
6039 type1.t = t;
6040 gen_cast(&type1);
6041 vswap();
6042 /* special case for shifts and long long: we keep the shift as
6043 an integer */
6044 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
6045 type1.t = VT_INT;
6046 gen_cast(&type1);
6047 if (is_float(t))
6048 gen_opif(op);
6049 else
6050 gen_opic(op);
6051 if (op >= TOK_ULT && op <= TOK_GT) {
6052 /* relationnal op: the result is an int */
6053 vtop->type.t = VT_INT;
6054 } else {
6055 vtop->type.t = t;
6060 #ifndef TCC_TARGET_ARM
6061 /* generic itof for unsigned long long case */
6062 void gen_cvt_itof1(int t)
6064 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
6065 (VT_LLONG | VT_UNSIGNED)) {
6067 if (t == VT_FLOAT)
6068 vpush_global_sym(&func_old_type, TOK___floatundisf);
6069 #if LDOUBLE_SIZE != 8
6070 else if (t == VT_LDOUBLE)
6071 vpush_global_sym(&func_old_type, TOK___floatundixf);
6072 #endif
6073 else
6074 vpush_global_sym(&func_old_type, TOK___floatundidf);
6075 vrott(2);
6076 gfunc_call(1);
6077 vpushi(0);
6078 vtop->r = reg_fret(t);
6079 } else {
6080 gen_cvt_itof(t);
6083 #endif
6085 /* generic ftoi for unsigned long long case */
6086 void gen_cvt_ftoi1(int t)
6088 int st;
6090 if (t == (VT_LLONG | VT_UNSIGNED)) {
6091 /* not handled natively */
6092 st = vtop->type.t & VT_BTYPE;
6093 if (st == VT_FLOAT)
6094 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
6095 #if LDOUBLE_SIZE != 8
6096 else if (st == VT_LDOUBLE)
6097 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
6098 #endif
6099 else
6100 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
6101 vrott(2);
6102 gfunc_call(1);
6103 vpushi(0);
6104 vtop->r = REG_IRET;
6105 vtop->r2 = REG_LRET;
6106 } else {
6107 gen_cvt_ftoi(t);
6111 /* force char or short cast */
6112 void force_charshort_cast(int t)
6114 int bits, dbt;
6115 dbt = t & VT_BTYPE;
6116 /* XXX: add optimization if lvalue : just change type and offset */
6117 if (dbt == VT_BYTE)
6118 bits = 8;
6119 else
6120 bits = 16;
6121 if (t & VT_UNSIGNED) {
6122 vpushi((1 << bits) - 1);
6123 gen_op('&');
6124 } else {
6125 bits = 32 - bits;
6126 vpushi(bits);
6127 gen_op(TOK_SHL);
6128 /* result must be signed or the SAR is converted to an SHL
6129 This was not the case when "t" was a signed short
6130 and the last value on the stack was an unsigned int */
6131 vtop->type.t &= ~VT_UNSIGNED;
6132 vpushi(bits);
6133 gen_op(TOK_SAR);
6137 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
6138 static void gen_cast(CType *type)
6140 int sbt, dbt, sf, df, c, p;
6142 /* special delayed cast for char/short */
6143 /* XXX: in some cases (multiple cascaded casts), it may still
6144 be incorrect */
6145 if (vtop->r & VT_MUSTCAST) {
6146 vtop->r &= ~VT_MUSTCAST;
6147 force_charshort_cast(vtop->type.t);
6150 /* bitfields first get cast to ints */
6151 if (vtop->type.t & VT_BITFIELD) {
6152 gv(RC_INT);
6155 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
6156 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
6158 if (sbt != dbt) {
6159 sf = is_float(sbt);
6160 df = is_float(dbt);
6161 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6162 p = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM);
6163 if (c) {
6164 /* constant case: we can do it now */
6165 /* XXX: in ISOC, cannot do it if error in convert */
6166 if (sbt == VT_FLOAT)
6167 vtop->c.ld = vtop->c.f;
6168 else if (sbt == VT_DOUBLE)
6169 vtop->c.ld = vtop->c.d;
6171 if (df) {
6172 if ((sbt & VT_BTYPE) == VT_LLONG) {
6173 if (sbt & VT_UNSIGNED)
6174 vtop->c.ld = vtop->c.ull;
6175 else
6176 vtop->c.ld = vtop->c.ll;
6177 } else if(!sf) {
6178 if (sbt & VT_UNSIGNED)
6179 vtop->c.ld = vtop->c.ui;
6180 else
6181 vtop->c.ld = vtop->c.i;
6184 if (dbt == VT_FLOAT)
6185 vtop->c.f = (float)vtop->c.ld;
6186 else if (dbt == VT_DOUBLE)
6187 vtop->c.d = (double)vtop->c.ld;
6188 } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
6189 vtop->c.ull = (unsigned long long)vtop->c.ld;
6190 } else if (sf && dbt == VT_BOOL) {
6191 vtop->c.i = (vtop->c.ld != 0);
6192 } else {
6193 if(sf)
6194 vtop->c.ll = (long long)vtop->c.ld;
6195 else if (sbt == (VT_LLONG|VT_UNSIGNED))
6196 vtop->c.ll = vtop->c.ull;
6197 else if (sbt & VT_UNSIGNED)
6198 vtop->c.ll = vtop->c.ui;
6199 else if (sbt != VT_LLONG)
6200 vtop->c.ll = vtop->c.i;
6202 if (dbt == (VT_LLONG|VT_UNSIGNED))
6203 vtop->c.ull = vtop->c.ll;
6204 else if (dbt == VT_BOOL)
6205 vtop->c.i = (vtop->c.ll != 0);
6206 else if (dbt != VT_LLONG) {
6207 int s = 0;
6208 if ((dbt & VT_BTYPE) == VT_BYTE)
6209 s = 24;
6210 else if ((dbt & VT_BTYPE) == VT_SHORT)
6211 s = 16;
6213 if(dbt & VT_UNSIGNED)
6214 vtop->c.ui = ((unsigned int)vtop->c.ll << s) >> s;
6215 else
6216 vtop->c.i = ((int)vtop->c.ll << s) >> s;
6219 } else if (p && dbt == VT_BOOL) {
6220 vtop->r = VT_CONST;
6221 vtop->c.i = 1;
6222 } else if (!nocode_wanted) {
6223 /* non constant case: generate code */
6224 if (sf && df) {
6225 /* convert from fp to fp */
6226 gen_cvt_ftof(dbt);
6227 } else if (df) {
6228 /* convert int to fp */
6229 gen_cvt_itof1(dbt);
6230 } else if (sf) {
6231 /* convert fp to int */
6232 if (dbt == VT_BOOL) {
6233 vpushi(0);
6234 gen_op(TOK_NE);
6235 } else {
6236 /* we handle char/short/etc... with generic code */
6237 if (dbt != (VT_INT | VT_UNSIGNED) &&
6238 dbt != (VT_LLONG | VT_UNSIGNED) &&
6239 dbt != VT_LLONG)
6240 dbt = VT_INT;
6241 gen_cvt_ftoi1(dbt);
6242 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
6243 /* additional cast for char/short... */
6244 vtop->type.t = dbt;
6245 gen_cast(type);
6248 #ifndef TCC_TARGET_X86_64
6249 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
6250 if ((sbt & VT_BTYPE) != VT_LLONG) {
6251 /* scalar to long long */
6252 /* machine independent conversion */
6253 gv(RC_INT);
6254 /* generate high word */
6255 if (sbt == (VT_INT | VT_UNSIGNED)) {
6256 vpushi(0);
6257 gv(RC_INT);
6258 } else {
6259 if (sbt == VT_PTR) {
6260 /* cast from pointer to int before we apply
6261 shift operation, which pointers don't support*/
6262 gen_cast(&int_type);
6264 gv_dup();
6265 vpushi(31);
6266 gen_op(TOK_SAR);
6268 /* patch second register */
6269 vtop[-1].r2 = vtop->r;
6270 vpop();
6272 #else
6273 } else if ((dbt & VT_BTYPE) == VT_LLONG ||
6274 (dbt & VT_BTYPE) == VT_PTR) {
6275 /* XXX: not sure if this is perfect... need more tests */
6276 if ((sbt & VT_BTYPE) != VT_LLONG) {
6277 int r = gv(RC_INT);
6278 if (sbt != (VT_INT | VT_UNSIGNED) &&
6279 sbt != VT_PTR && sbt != VT_FUNC) {
6280 /* x86_64 specific: movslq */
6281 o(0x6348);
6282 o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r));
6285 #endif
6286 } else if (dbt == VT_BOOL) {
6287 /* scalar to bool */
6288 vpushi(0);
6289 gen_op(TOK_NE);
6290 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
6291 (dbt & VT_BTYPE) == VT_SHORT) {
6292 if (sbt == VT_PTR) {
6293 vtop->type.t = VT_INT;
6294 warning("nonportable conversion from pointer to char/short");
6296 force_charshort_cast(dbt);
6297 } else if ((dbt & VT_BTYPE) == VT_INT) {
6298 /* scalar to int */
6299 if (sbt == VT_LLONG) {
6300 /* from long long: just take low order word */
6301 lexpand();
6302 vpop();
6304 /* if lvalue and single word type, nothing to do because
6305 the lvalue already contains the real type size (see
6306 VT_LVAL_xxx constants) */
6309 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
6310 /* if we are casting between pointer types,
6311 we must update the VT_LVAL_xxx size */
6312 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
6313 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
6315 vtop->type = *type;
6318 /* return type size. Put alignment at 'a' */
6319 static int type_size(CType *type, int *a)
6321 Sym *s;
6322 int bt;
6324 bt = type->t & VT_BTYPE;
6325 if (bt == VT_STRUCT) {
6326 /* struct/union */
6327 s = type->ref;
6328 *a = s->r;
6329 return s->c;
6330 } else if (bt == VT_PTR) {
6331 if (type->t & VT_ARRAY) {
6332 int ts;
6334 s = type->ref;
6335 ts = type_size(&s->type, a);
6337 if (ts < 0 && s->c < 0)
6338 ts = -ts;
6340 return ts * s->c;
6341 } else {
6342 *a = PTR_SIZE;
6343 return PTR_SIZE;
6345 } else if (bt == VT_LDOUBLE) {
6346 *a = LDOUBLE_ALIGN;
6347 return LDOUBLE_SIZE;
6348 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
6349 #ifdef TCC_TARGET_I386
6350 #ifdef TCC_TARGET_PE
6351 *a = 8;
6352 #else
6353 *a = 4;
6354 #endif
6355 #elif defined(TCC_TARGET_ARM)
6356 #ifdef TCC_ARM_EABI
6357 *a = 8;
6358 #else
6359 *a = 4;
6360 #endif
6361 #else
6362 *a = 8;
6363 #endif
6364 return 8;
6365 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6366 *a = 4;
6367 return 4;
6368 } else if (bt == VT_SHORT) {
6369 *a = 2;
6370 return 2;
6371 } else {
6372 /* char, void, function, _Bool */
6373 *a = 1;
6374 return 1;
6378 /* return the pointed type of t */
6379 static inline CType *pointed_type(CType *type)
6381 return &type->ref->type;
6384 /* modify type so that its it is a pointer to type. */
6385 static void mk_pointer(CType *type)
6387 Sym *s;
6388 s = sym_push(SYM_FIELD, type, 0, -1);
6389 type->t = VT_PTR | (type->t & ~VT_TYPE);
6390 type->ref = s;
6393 /* compare function types. OLD functions match any new functions */
6394 static int is_compatible_func(CType *type1, CType *type2)
6396 Sym *s1, *s2;
6398 s1 = type1->ref;
6399 s2 = type2->ref;
6400 if (!is_compatible_types(&s1->type, &s2->type))
6401 return 0;
6402 /* check func_call */
6403 if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
6404 return 0;
6405 /* XXX: not complete */
6406 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6407 return 1;
6408 if (s1->c != s2->c)
6409 return 0;
6410 while (s1 != NULL) {
6411 if (s2 == NULL)
6412 return 0;
6413 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6414 return 0;
6415 s1 = s1->next;
6416 s2 = s2->next;
6418 if (s2)
6419 return 0;
6420 return 1;
6423 /* return true if type1 and type2 are the same. If unqualified is
6424 true, qualifiers on the types are ignored.
6426 - enums are not checked as gcc __builtin_types_compatible_p ()
6428 static int compare_types(CType *type1, CType *type2, int unqualified)
6430 int bt1, t1, t2;
6432 t1 = type1->t & VT_TYPE;
6433 t2 = type2->t & VT_TYPE;
6434 if (unqualified) {
6435 /* strip qualifiers before comparing */
6436 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6437 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6439 /* XXX: bitfields ? */
6440 if (t1 != t2)
6441 return 0;
6442 /* test more complicated cases */
6443 bt1 = t1 & VT_BTYPE;
6444 if (bt1 == VT_PTR) {
6445 type1 = pointed_type(type1);
6446 type2 = pointed_type(type2);
6447 return is_compatible_types(type1, type2);
6448 } else if (bt1 == VT_STRUCT) {
6449 return (type1->ref == type2->ref);
6450 } else if (bt1 == VT_FUNC) {
6451 return is_compatible_func(type1, type2);
6452 } else {
6453 return 1;
6457 /* return true if type1 and type2 are exactly the same (including
6458 qualifiers).
6460 static int is_compatible_types(CType *type1, CType *type2)
6462 return compare_types(type1,type2,0);
6465 /* return true if type1 and type2 are the same (ignoring qualifiers).
6467 static int is_compatible_parameter_types(CType *type1, CType *type2)
6469 return compare_types(type1,type2,1);
6472 /* print a type. If 'varstr' is not NULL, then the variable is also
6473 printed in the type */
6474 /* XXX: union */
6475 /* XXX: add array and function pointers */
6476 void type_to_str(char *buf, int buf_size,
6477 CType *type, const char *varstr)
6479 int bt, v, t;
6480 Sym *s, *sa;
6481 char buf1[256];
6482 const char *tstr;
6484 t = type->t & VT_TYPE;
6485 bt = t & VT_BTYPE;
6486 buf[0] = '\0';
6487 if (t & VT_CONSTANT)
6488 pstrcat(buf, buf_size, "const ");
6489 if (t & VT_VOLATILE)
6490 pstrcat(buf, buf_size, "volatile ");
6491 if (t & VT_UNSIGNED)
6492 pstrcat(buf, buf_size, "unsigned ");
6493 switch(bt) {
6494 case VT_VOID:
6495 tstr = "void";
6496 goto add_tstr;
6497 case VT_BOOL:
6498 tstr = "_Bool";
6499 goto add_tstr;
6500 case VT_BYTE:
6501 tstr = "char";
6502 goto add_tstr;
6503 case VT_SHORT:
6504 tstr = "short";
6505 goto add_tstr;
6506 case VT_INT:
6507 tstr = "int";
6508 goto add_tstr;
6509 case VT_LONG:
6510 tstr = "long";
6511 goto add_tstr;
6512 case VT_LLONG:
6513 tstr = "long long";
6514 goto add_tstr;
6515 case VT_FLOAT:
6516 tstr = "float";
6517 goto add_tstr;
6518 case VT_DOUBLE:
6519 tstr = "double";
6520 goto add_tstr;
6521 case VT_LDOUBLE:
6522 tstr = "long double";
6523 add_tstr:
6524 pstrcat(buf, buf_size, tstr);
6525 break;
6526 case VT_ENUM:
6527 case VT_STRUCT:
6528 if (bt == VT_STRUCT)
6529 tstr = "struct ";
6530 else
6531 tstr = "enum ";
6532 pstrcat(buf, buf_size, tstr);
6533 v = type->ref->v & ~SYM_STRUCT;
6534 if (v >= SYM_FIRST_ANOM)
6535 pstrcat(buf, buf_size, "<anonymous>");
6536 else
6537 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6538 break;
6539 case VT_FUNC:
6540 s = type->ref;
6541 type_to_str(buf, buf_size, &s->type, varstr);
6542 pstrcat(buf, buf_size, "(");
6543 sa = s->next;
6544 while (sa != NULL) {
6545 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6546 pstrcat(buf, buf_size, buf1);
6547 sa = sa->next;
6548 if (sa)
6549 pstrcat(buf, buf_size, ", ");
6551 pstrcat(buf, buf_size, ")");
6552 goto no_var;
6553 case VT_PTR:
6554 s = type->ref;
6555 pstrcpy(buf1, sizeof(buf1), "*");
6556 if (varstr)
6557 pstrcat(buf1, sizeof(buf1), varstr);
6558 type_to_str(buf, buf_size, &s->type, buf1);
6559 goto no_var;
6561 if (varstr) {
6562 pstrcat(buf, buf_size, " ");
6563 pstrcat(buf, buf_size, varstr);
6565 no_var: ;
6568 /* verify type compatibility to store vtop in 'dt' type, and generate
6569 casts if needed. */
6570 static void gen_assign_cast(CType *dt)
6572 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6573 char buf1[256], buf2[256];
6574 int dbt, sbt;
6576 st = &vtop->type; /* source type */
6577 dbt = dt->t & VT_BTYPE;
6578 sbt = st->t & VT_BTYPE;
6579 if (dt->t & VT_CONSTANT)
6580 warning("assignment of read-only location");
6581 switch(dbt) {
6582 case VT_PTR:
6583 /* special cases for pointers */
6584 /* '0' can also be a pointer */
6585 if (is_null_pointer(vtop))
6586 goto type_ok;
6587 /* accept implicit pointer to integer cast with warning */
6588 if (is_integer_btype(sbt)) {
6589 warning("assignment makes pointer from integer without a cast");
6590 goto type_ok;
6592 type1 = pointed_type(dt);
6593 /* a function is implicitely a function pointer */
6594 if (sbt == VT_FUNC) {
6595 if ((type1->t & VT_BTYPE) != VT_VOID &&
6596 !is_compatible_types(pointed_type(dt), st))
6597 goto error;
6598 else
6599 goto type_ok;
6601 if (sbt != VT_PTR)
6602 goto error;
6603 type2 = pointed_type(st);
6604 if ((type1->t & VT_BTYPE) == VT_VOID ||
6605 (type2->t & VT_BTYPE) == VT_VOID) {
6606 /* void * can match anything */
6607 } else {
6608 /* exact type match, except for unsigned */
6609 tmp_type1 = *type1;
6610 tmp_type2 = *type2;
6611 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6612 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6613 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6614 warning("assignment from incompatible pointer type");
6616 /* check const and volatile */
6617 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6618 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6619 warning("assignment discards qualifiers from pointer target type");
6620 break;
6621 case VT_BYTE:
6622 case VT_SHORT:
6623 case VT_INT:
6624 case VT_LLONG:
6625 if (sbt == VT_PTR || sbt == VT_FUNC) {
6626 warning("assignment makes integer from pointer without a cast");
6628 /* XXX: more tests */
6629 break;
6630 case VT_STRUCT:
6631 tmp_type1 = *dt;
6632 tmp_type2 = *st;
6633 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6634 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6635 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6636 error:
6637 type_to_str(buf1, sizeof(buf1), st, NULL);
6638 type_to_str(buf2, sizeof(buf2), dt, NULL);
6639 error("cannot cast '%s' to '%s'", buf1, buf2);
6641 break;
6643 type_ok:
6644 gen_cast(dt);
6647 /* store vtop in lvalue pushed on stack */
6648 void vstore(void)
6650 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6652 ft = vtop[-1].type.t;
6653 sbt = vtop->type.t & VT_BTYPE;
6654 dbt = ft & VT_BTYPE;
6655 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6656 (sbt == VT_INT && dbt == VT_SHORT)) {
6657 /* optimize char/short casts */
6658 delayed_cast = VT_MUSTCAST;
6659 vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));
6660 /* XXX: factorize */
6661 if (ft & VT_CONSTANT)
6662 warning("assignment of read-only location");
6663 } else {
6664 delayed_cast = 0;
6665 if (!(ft & VT_BITFIELD))
6666 gen_assign_cast(&vtop[-1].type);
6669 if (sbt == VT_STRUCT) {
6670 /* if structure, only generate pointer */
6671 /* structure assignment : generate memcpy */
6672 /* XXX: optimize if small size */
6673 if (!nocode_wanted) {
6674 size = type_size(&vtop->type, &align);
6676 #ifdef TCC_ARM_EABI
6677 if(!(align & 7))
6678 vpush_global_sym(&func_old_type, TOK_memcpy8);
6679 else if(!(align & 3))
6680 vpush_global_sym(&func_old_type, TOK_memcpy4);
6681 else
6682 #endif
6683 vpush_global_sym(&func_old_type, TOK_memcpy);
6685 /* destination */
6686 vpushv(vtop - 2);
6687 vtop->type.t = VT_PTR;
6688 gaddrof();
6689 /* source */
6690 vpushv(vtop - 2);
6691 vtop->type.t = VT_PTR;
6692 gaddrof();
6693 /* type size */
6694 vpushi(size);
6695 gfunc_call(3);
6697 vswap();
6698 vpop();
6699 } else {
6700 vswap();
6701 vpop();
6703 /* leave source on stack */
6704 } else if (ft & VT_BITFIELD) {
6705 /* bitfield store handling */
6706 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6707 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6708 /* remove bit field info to avoid loops */
6709 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6711 /* duplicate source into other register */
6712 gv_dup();
6713 vswap();
6714 vrott(3);
6716 if((ft & VT_BTYPE) == VT_BOOL) {
6717 gen_cast(&vtop[-1].type);
6718 vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
6721 /* duplicate destination */
6722 vdup();
6723 vtop[-1] = vtop[-2];
6725 /* mask and shift source */
6726 if((ft & VT_BTYPE) != VT_BOOL) {
6727 if((ft & VT_BTYPE) == VT_LLONG) {
6728 vpushll((1ULL << bit_size) - 1ULL);
6729 } else {
6730 vpushi((1 << bit_size) - 1);
6732 gen_op('&');
6734 vpushi(bit_pos);
6735 gen_op(TOK_SHL);
6736 /* load destination, mask and or with source */
6737 vswap();
6738 if((ft & VT_BTYPE) == VT_LLONG) {
6739 vpushll(~(((1ULL << bit_size) - 1ULL) << bit_pos));
6740 } else {
6741 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6743 gen_op('&');
6744 gen_op('|');
6745 /* store result */
6746 vstore();
6748 /* pop off shifted source from "duplicate source..." above */
6749 vpop();
6751 } else {
6752 #ifdef CONFIG_TCC_BCHECK
6753 /* bound check case */
6754 if (vtop[-1].r & VT_MUSTBOUND) {
6755 vswap();
6756 gbound();
6757 vswap();
6759 #endif
6760 if (!nocode_wanted) {
6761 rc = RC_INT;
6762 if (is_float(ft)) {
6763 rc = RC_FLOAT;
6764 #ifdef TCC_TARGET_X86_64
6765 if ((ft & VT_BTYPE) == VT_LDOUBLE) {
6766 rc = RC_ST0;
6768 #endif
6770 r = gv(rc); /* generate value */
6771 /* if lvalue was saved on stack, must read it */
6772 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6773 SValue sv;
6774 t = get_reg(RC_INT);
6775 #ifdef TCC_TARGET_X86_64
6776 sv.type.t = VT_PTR;
6777 #else
6778 sv.type.t = VT_INT;
6779 #endif
6780 sv.r = VT_LOCAL | VT_LVAL;
6781 sv.c.ul = vtop[-1].c.ul;
6782 load(t, &sv);
6783 vtop[-1].r = t | VT_LVAL;
6785 store(r, vtop - 1);
6786 #ifndef TCC_TARGET_X86_64
6787 /* two word case handling : store second register at word + 4 */
6788 if ((ft & VT_BTYPE) == VT_LLONG) {
6789 vswap();
6790 /* convert to int to increment easily */
6791 vtop->type.t = VT_INT;
6792 gaddrof();
6793 vpushi(4);
6794 gen_op('+');
6795 vtop->r |= VT_LVAL;
6796 vswap();
6797 /* XXX: it works because r2 is spilled last ! */
6798 store(vtop->r2, vtop - 1);
6800 #endif
6802 vswap();
6803 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6804 vtop->r |= delayed_cast;
6808 /* post defines POST/PRE add. c is the token ++ or -- */
6809 void inc(int post, int c)
6811 test_lvalue();
6812 vdup(); /* save lvalue */
6813 if (post) {
6814 gv_dup(); /* duplicate value */
6815 vrotb(3);
6816 vrotb(3);
6818 /* add constant */
6819 vpushi(c - TOK_MID);
6820 gen_op('+');
6821 vstore(); /* store value */
6822 if (post)
6823 vpop(); /* if post op, return saved value */
6826 /* Parse GNUC __attribute__ extension. Currently, the following
6827 extensions are recognized:
6828 - aligned(n) : set data/function alignment.
6829 - packed : force data alignment to 1
6830 - section(x) : generate data/code in this section.
6831 - unused : currently ignored, but may be used someday.
6832 - regparm(n) : pass function parameters in registers (i386 only)
6834 static void parse_attribute(AttributeDef *ad)
6836 int t, n;
6838 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6839 next();
6840 skip('(');
6841 skip('(');
6842 while (tok != ')') {
6843 if (tok < TOK_IDENT)
6844 expect("attribute name");
6845 t = tok;
6846 next();
6847 switch(t) {
6848 case TOK_SECTION1:
6849 case TOK_SECTION2:
6850 skip('(');
6851 if (tok != TOK_STR)
6852 expect("section name");
6853 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6854 next();
6855 skip(')');
6856 break;
6857 case TOK_ALIGNED1:
6858 case TOK_ALIGNED2:
6859 if (tok == '(') {
6860 next();
6861 n = expr_const();
6862 if (n <= 0 || (n & (n - 1)) != 0)
6863 error("alignment must be a positive power of two");
6864 skip(')');
6865 } else {
6866 n = MAX_ALIGN;
6868 ad->aligned = n;
6869 break;
6870 case TOK_PACKED1:
6871 case TOK_PACKED2:
6872 ad->packed = 1;
6873 break;
6874 case TOK_UNUSED1:
6875 case TOK_UNUSED2:
6876 /* currently, no need to handle it because tcc does not
6877 track unused objects */
6878 break;
6879 case TOK_NORETURN1:
6880 case TOK_NORETURN2:
6881 /* currently, no need to handle it because tcc does not
6882 track unused objects */
6883 break;
6884 case TOK_CDECL1:
6885 case TOK_CDECL2:
6886 case TOK_CDECL3:
6887 FUNC_CALL(ad->func_attr) = FUNC_CDECL;
6888 break;
6889 case TOK_STDCALL1:
6890 case TOK_STDCALL2:
6891 case TOK_STDCALL3:
6892 FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
6893 break;
6894 #ifdef TCC_TARGET_I386
6895 case TOK_REGPARM1:
6896 case TOK_REGPARM2:
6897 skip('(');
6898 n = expr_const();
6899 if (n > 3)
6900 n = 3;
6901 else if (n < 0)
6902 n = 0;
6903 if (n > 0)
6904 FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
6905 skip(')');
6906 break;
6907 case TOK_FASTCALL1:
6908 case TOK_FASTCALL2:
6909 case TOK_FASTCALL3:
6910 FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
6911 break;
6912 #endif
6913 case TOK_DLLEXPORT:
6914 FUNC_EXPORT(ad->func_attr) = 1;
6915 break;
6916 default:
6917 if (tcc_state->warn_unsupported)
6918 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6919 /* skip parameters */
6920 if (tok == '(') {
6921 int parenthesis = 0;
6922 do {
6923 if (tok == '(')
6924 parenthesis++;
6925 else if (tok == ')')
6926 parenthesis--;
6927 next();
6928 } while (parenthesis && tok != -1);
6930 break;
6932 if (tok != ',')
6933 break;
6934 next();
6936 skip(')');
6937 skip(')');
6941 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6942 static void struct_decl(CType *type, int u)
6944 int a, v, size, align, maxalign, c, offset;
6945 int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt;
6946 Sym *s, *ss, *ass, **ps;
6947 AttributeDef ad;
6948 CType type1, btype;
6950 a = tok; /* save decl type */
6951 next();
6952 if (tok != '{') {
6953 v = tok;
6954 next();
6955 /* struct already defined ? return it */
6956 if (v < TOK_IDENT)
6957 expect("struct/union/enum name");
6958 s = struct_find(v);
6959 if (s) {
6960 if (s->type.t != a)
6961 error("invalid type");
6962 goto do_decl;
6964 } else {
6965 v = anon_sym++;
6967 type1.t = a;
6968 /* we put an undefined size for struct/union */
6969 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6970 s->r = 0; /* default alignment is zero as gcc */
6971 /* put struct/union/enum name in type */
6972 do_decl:
6973 type->t = u;
6974 type->ref = s;
6976 if (tok == '{') {
6977 next();
6978 if (s->c != -1)
6979 error("struct/union/enum already defined");
6980 /* cannot be empty */
6981 c = 0;
6982 /* non empty enums are not allowed */
6983 if (a == TOK_ENUM) {
6984 for(;;) {
6985 v = tok;
6986 if (v < TOK_UIDENT)
6987 expect("identifier");
6988 next();
6989 if (tok == '=') {
6990 next();
6991 c = expr_const();
6993 /* enum symbols have static storage */
6994 ss = sym_push(v, &int_type, VT_CONST, c);
6995 ss->type.t |= VT_STATIC;
6996 if (tok != ',')
6997 break;
6998 next();
6999 c++;
7000 /* NOTE: we accept a trailing comma */
7001 if (tok == '}')
7002 break;
7004 skip('}');
7005 } else {
7006 maxalign = 1;
7007 ps = &s->next;
7008 prevbt = VT_INT;
7009 bit_pos = 0;
7010 offset = 0;
7011 while (tok != '}') {
7012 parse_btype(&btype, &ad);
7013 while (1) {
7014 bit_size = -1;
7015 v = 0;
7016 type1 = btype;
7017 if (tok != ':') {
7018 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
7019 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
7020 expect("identifier");
7021 if ((type1.t & VT_BTYPE) == VT_FUNC ||
7022 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
7023 error("invalid type for '%s'",
7024 get_tok_str(v, NULL));
7026 if (tok == ':') {
7027 next();
7028 bit_size = expr_const();
7029 /* XXX: handle v = 0 case for messages */
7030 if (bit_size < 0)
7031 error("negative width in bit-field '%s'",
7032 get_tok_str(v, NULL));
7033 if (v && bit_size == 0)
7034 error("zero width for bit-field '%s'",
7035 get_tok_str(v, NULL));
7037 size = type_size(&type1, &align);
7038 if (ad.aligned) {
7039 if (align < ad.aligned)
7040 align = ad.aligned;
7041 } else if (ad.packed) {
7042 align = 1;
7043 } else if (*tcc_state->pack_stack_ptr) {
7044 if (align > *tcc_state->pack_stack_ptr)
7045 align = *tcc_state->pack_stack_ptr;
7047 lbit_pos = 0;
7048 if (bit_size >= 0) {
7049 bt = type1.t & VT_BTYPE;
7050 if (bt != VT_INT &&
7051 bt != VT_BYTE &&
7052 bt != VT_SHORT &&
7053 bt != VT_BOOL &&
7054 bt != VT_ENUM &&
7055 bt != VT_LLONG)
7056 error("bitfields must have scalar type");
7057 bsize = size * 8;
7058 if (bit_size > bsize) {
7059 error("width of '%s' exceeds its type",
7060 get_tok_str(v, NULL));
7061 } else if (bit_size == bsize) {
7062 /* no need for bit fields */
7063 bit_pos = 0;
7064 } else if (bit_size == 0) {
7065 /* XXX: what to do if only padding in a
7066 structure ? */
7067 /* zero size: means to pad */
7068 bit_pos = 0;
7069 } else {
7070 /* we do not have enough room ?
7071 did the type change?
7072 is it a union? */
7073 if ((bit_pos + bit_size) > bsize ||
7074 bt != prevbt || a == TOK_UNION)
7075 bit_pos = 0;
7076 lbit_pos = bit_pos;
7077 /* XXX: handle LSB first */
7078 type1.t |= VT_BITFIELD |
7079 (bit_pos << VT_STRUCT_SHIFT) |
7080 (bit_size << (VT_STRUCT_SHIFT + 6));
7081 bit_pos += bit_size;
7083 prevbt = bt;
7084 } else {
7085 bit_pos = 0;
7087 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
7088 /* add new memory data only if starting
7089 bit field */
7090 if (lbit_pos == 0) {
7091 if (a == TOK_STRUCT) {
7092 c = (c + align - 1) & -align;
7093 offset = c;
7094 if (size > 0)
7095 c += size;
7096 } else {
7097 offset = 0;
7098 if (size > c)
7099 c = size;
7101 if (align > maxalign)
7102 maxalign = align;
7104 #if 0
7105 printf("add field %s offset=%d",
7106 get_tok_str(v, NULL), offset);
7107 if (type1.t & VT_BITFIELD) {
7108 printf(" pos=%d size=%d",
7109 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
7110 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
7112 printf("\n");
7113 #endif
7115 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
7116 ass = type1.ref;
7117 while ((ass = ass->next) != NULL) {
7118 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
7119 *ps = ss;
7120 ps = &ss->next;
7122 } else if (v) {
7123 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
7124 *ps = ss;
7125 ps = &ss->next;
7127 if (tok == ';' || tok == TOK_EOF)
7128 break;
7129 skip(',');
7131 skip(';');
7133 skip('}');
7134 /* store size and alignment */
7135 s->c = (c + maxalign - 1) & -maxalign;
7136 s->r = maxalign;
7141 /* return 0 if no type declaration. otherwise, return the basic type
7142 and skip it.
7144 static int parse_btype(CType *type, AttributeDef *ad)
7146 int t, u, type_found, typespec_found, typedef_found;
7147 Sym *s;
7148 CType type1;
7150 memset(ad, 0, sizeof(AttributeDef));
7151 type_found = 0;
7152 typespec_found = 0;
7153 typedef_found = 0;
7154 t = 0;
7155 while(1) {
7156 switch(tok) {
7157 case TOK_EXTENSION:
7158 /* currently, we really ignore extension */
7159 next();
7160 continue;
7162 /* basic types */
7163 case TOK_CHAR:
7164 u = VT_BYTE;
7165 basic_type:
7166 next();
7167 basic_type1:
7168 if ((t & VT_BTYPE) != 0)
7169 error("too many basic types");
7170 t |= u;
7171 typespec_found = 1;
7172 break;
7173 case TOK_VOID:
7174 u = VT_VOID;
7175 goto basic_type;
7176 case TOK_SHORT:
7177 u = VT_SHORT;
7178 goto basic_type;
7179 case TOK_INT:
7180 next();
7181 typespec_found = 1;
7182 break;
7183 case TOK_LONG:
7184 next();
7185 if ((t & VT_BTYPE) == VT_DOUBLE) {
7186 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
7187 } else if ((t & VT_BTYPE) == VT_LONG) {
7188 t = (t & ~VT_BTYPE) | VT_LLONG;
7189 } else {
7190 u = VT_LONG;
7191 goto basic_type1;
7193 break;
7194 case TOK_BOOL:
7195 u = VT_BOOL;
7196 goto basic_type;
7197 case TOK_FLOAT:
7198 u = VT_FLOAT;
7199 goto basic_type;
7200 case TOK_DOUBLE:
7201 next();
7202 if ((t & VT_BTYPE) == VT_LONG) {
7203 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
7204 } else {
7205 u = VT_DOUBLE;
7206 goto basic_type1;
7208 break;
7209 case TOK_ENUM:
7210 struct_decl(&type1, VT_ENUM);
7211 basic_type2:
7212 u = type1.t;
7213 type->ref = type1.ref;
7214 goto basic_type1;
7215 case TOK_STRUCT:
7216 case TOK_UNION:
7217 struct_decl(&type1, VT_STRUCT);
7218 goto basic_type2;
7220 /* type modifiers */
7221 case TOK_CONST1:
7222 case TOK_CONST2:
7223 case TOK_CONST3:
7224 t |= VT_CONSTANT;
7225 next();
7226 break;
7227 case TOK_VOLATILE1:
7228 case TOK_VOLATILE2:
7229 case TOK_VOLATILE3:
7230 t |= VT_VOLATILE;
7231 next();
7232 break;
7233 case TOK_SIGNED1:
7234 case TOK_SIGNED2:
7235 case TOK_SIGNED3:
7236 typespec_found = 1;
7237 t |= VT_SIGNED;
7238 next();
7239 break;
7240 case TOK_REGISTER:
7241 case TOK_AUTO:
7242 case TOK_RESTRICT1:
7243 case TOK_RESTRICT2:
7244 case TOK_RESTRICT3:
7245 next();
7246 break;
7247 case TOK_UNSIGNED:
7248 t |= VT_UNSIGNED;
7249 next();
7250 typespec_found = 1;
7251 break;
7253 /* storage */
7254 case TOK_EXTERN:
7255 t |= VT_EXTERN;
7256 next();
7257 break;
7258 case TOK_STATIC:
7259 t |= VT_STATIC;
7260 next();
7261 break;
7262 case TOK_TYPEDEF:
7263 t |= VT_TYPEDEF;
7264 next();
7265 break;
7266 case TOK_INLINE1:
7267 case TOK_INLINE2:
7268 case TOK_INLINE3:
7269 t |= VT_INLINE;
7270 next();
7271 break;
7273 /* GNUC attribute */
7274 case TOK_ATTRIBUTE1:
7275 case TOK_ATTRIBUTE2:
7276 parse_attribute(ad);
7277 break;
7278 /* GNUC typeof */
7279 case TOK_TYPEOF1:
7280 case TOK_TYPEOF2:
7281 case TOK_TYPEOF3:
7282 next();
7283 parse_expr_type(&type1);
7284 goto basic_type2;
7285 default:
7286 if (typespec_found || typedef_found)
7287 goto the_end;
7288 s = sym_find(tok);
7289 if (!s || !(s->type.t & VT_TYPEDEF))
7290 goto the_end;
7291 typedef_found = 1;
7292 t |= (s->type.t & ~VT_TYPEDEF);
7293 type->ref = s->type.ref;
7294 next();
7295 typespec_found = 1;
7296 break;
7298 type_found = 1;
7300 the_end:
7301 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
7302 error("signed and unsigned modifier");
7303 if (tcc_state->char_is_unsigned) {
7304 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
7305 t |= VT_UNSIGNED;
7307 t &= ~VT_SIGNED;
7309 /* long is never used as type */
7310 if ((t & VT_BTYPE) == VT_LONG)
7311 #ifndef TCC_TARGET_X86_64
7312 t = (t & ~VT_BTYPE) | VT_INT;
7313 #else
7314 t = (t & ~VT_BTYPE) | VT_LLONG;
7315 #endif
7316 type->t = t;
7317 return type_found;
7320 /* convert a function parameter type (array to pointer and function to
7321 function pointer) */
7322 static inline void convert_parameter_type(CType *pt)
7324 /* remove const and volatile qualifiers (XXX: const could be used
7325 to indicate a const function parameter */
7326 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
7327 /* array must be transformed to pointer according to ANSI C */
7328 pt->t &= ~VT_ARRAY;
7329 if ((pt->t & VT_BTYPE) == VT_FUNC) {
7330 mk_pointer(pt);
7334 static void post_type(CType *type, AttributeDef *ad)
7336 int n, l, t1, arg_size, align;
7337 Sym **plast, *s, *first;
7338 AttributeDef ad1;
7339 CType pt;
7341 if (tok == '(') {
7342 /* function declaration */
7343 next();
7344 l = 0;
7345 first = NULL;
7346 plast = &first;
7347 arg_size = 0;
7348 if (tok != ')') {
7349 for(;;) {
7350 /* read param name and compute offset */
7351 if (l != FUNC_OLD) {
7352 if (!parse_btype(&pt, &ad1)) {
7353 if (l) {
7354 error("invalid type");
7355 } else {
7356 l = FUNC_OLD;
7357 goto old_proto;
7360 l = FUNC_NEW;
7361 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
7362 break;
7363 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
7364 if ((pt.t & VT_BTYPE) == VT_VOID)
7365 error("parameter declared as void");
7366 arg_size += (type_size(&pt, &align) + 3) & ~3;
7367 } else {
7368 old_proto:
7369 n = tok;
7370 if (n < TOK_UIDENT)
7371 expect("identifier");
7372 pt.t = VT_INT;
7373 next();
7375 convert_parameter_type(&pt);
7376 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
7377 *plast = s;
7378 plast = &s->next;
7379 if (tok == ')')
7380 break;
7381 skip(',');
7382 if (l == FUNC_NEW && tok == TOK_DOTS) {
7383 l = FUNC_ELLIPSIS;
7384 next();
7385 break;
7389 /* if no parameters, then old type prototype */
7390 if (l == 0)
7391 l = FUNC_OLD;
7392 skip(')');
7393 t1 = type->t & VT_STORAGE;
7394 /* NOTE: const is ignored in returned type as it has a special
7395 meaning in gcc / C++ */
7396 type->t &= ~(VT_STORAGE | VT_CONSTANT);
7397 post_type(type, ad);
7398 /* we push a anonymous symbol which will contain the function prototype */
7399 FUNC_ARGS(ad->func_attr) = arg_size;
7400 s = sym_push(SYM_FIELD, type, ad->func_attr, l);
7401 s->next = first;
7402 type->t = t1 | VT_FUNC;
7403 type->ref = s;
7404 } else if (tok == '[') {
7405 /* array definition */
7406 next();
7407 if (tok == TOK_RESTRICT1)
7408 next();
7409 n = -1;
7410 if (tok != ']') {
7411 n = expr_const();
7412 if (n < 0)
7413 error("invalid array size");
7415 skip(']');
7416 /* parse next post type */
7417 t1 = type->t & VT_STORAGE;
7418 type->t &= ~VT_STORAGE;
7419 post_type(type, ad);
7421 /* we push a anonymous symbol which will contain the array
7422 element type */
7423 s = sym_push(SYM_FIELD, type, 0, n);
7424 type->t = t1 | VT_ARRAY | VT_PTR;
7425 type->ref = s;
7429 /* Parse a type declaration (except basic type), and return the type
7430 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7431 expected. 'type' should contain the basic type. 'ad' is the
7432 attribute definition of the basic type. It can be modified by
7433 type_decl().
7435 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7437 Sym *s;
7438 CType type1, *type2;
7439 int qualifiers;
7441 while (tok == '*') {
7442 qualifiers = 0;
7443 redo:
7444 next();
7445 switch(tok) {
7446 case TOK_CONST1:
7447 case TOK_CONST2:
7448 case TOK_CONST3:
7449 qualifiers |= VT_CONSTANT;
7450 goto redo;
7451 case TOK_VOLATILE1:
7452 case TOK_VOLATILE2:
7453 case TOK_VOLATILE3:
7454 qualifiers |= VT_VOLATILE;
7455 goto redo;
7456 case TOK_RESTRICT1:
7457 case TOK_RESTRICT2:
7458 case TOK_RESTRICT3:
7459 goto redo;
7461 mk_pointer(type);
7462 type->t |= qualifiers;
7465 /* XXX: clarify attribute handling */
7466 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7467 parse_attribute(ad);
7469 /* recursive type */
7470 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7471 type1.t = 0; /* XXX: same as int */
7472 if (tok == '(') {
7473 next();
7474 /* XXX: this is not correct to modify 'ad' at this point, but
7475 the syntax is not clear */
7476 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7477 parse_attribute(ad);
7478 type_decl(&type1, ad, v, td);
7479 skip(')');
7480 } else {
7481 /* type identifier */
7482 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7483 *v = tok;
7484 next();
7485 } else {
7486 if (!(td & TYPE_ABSTRACT))
7487 expect("identifier");
7488 *v = 0;
7491 post_type(type, ad);
7492 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7493 parse_attribute(ad);
7494 if (!type1.t)
7495 return;
7496 /* append type at the end of type1 */
7497 type2 = &type1;
7498 for(;;) {
7499 s = type2->ref;
7500 type2 = &s->type;
7501 if (!type2->t) {
7502 *type2 = *type;
7503 break;
7506 *type = type1;
7509 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7510 static int lvalue_type(int t)
7512 int bt, r;
7513 r = VT_LVAL;
7514 bt = t & VT_BTYPE;
7515 if (bt == VT_BYTE || bt == VT_BOOL)
7516 r |= VT_LVAL_BYTE;
7517 else if (bt == VT_SHORT)
7518 r |= VT_LVAL_SHORT;
7519 else
7520 return r;
7521 if (t & VT_UNSIGNED)
7522 r |= VT_LVAL_UNSIGNED;
7523 return r;
7526 /* indirection with full error checking and bound check */
7527 static void indir(void)
7529 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7530 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7531 return;
7532 expect("pointer");
7534 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7535 gv(RC_INT);
7536 vtop->type = *pointed_type(&vtop->type);
7537 /* Arrays and functions are never lvalues */
7538 if (!(vtop->type.t & VT_ARRAY)
7539 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7540 vtop->r |= lvalue_type(vtop->type.t);
7541 /* if bound checking, the referenced pointer must be checked */
7542 if (do_bounds_check)
7543 vtop->r |= VT_MUSTBOUND;
7547 /* pass a parameter to a function and do type checking and casting */
7548 static void gfunc_param_typed(Sym *func, Sym *arg)
7550 int func_type;
7551 CType type;
7553 func_type = func->c;
7554 if (func_type == FUNC_OLD ||
7555 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7556 /* default casting : only need to convert float to double */
7557 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7558 type.t = VT_DOUBLE;
7559 gen_cast(&type);
7561 } else if (arg == NULL) {
7562 error("too many arguments to function");
7563 } else {
7564 type = arg->type;
7565 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7566 gen_assign_cast(&type);
7570 /* parse an expression of the form '(type)' or '(expr)' and return its
7571 type */
7572 static void parse_expr_type(CType *type)
7574 int n;
7575 AttributeDef ad;
7577 skip('(');
7578 if (parse_btype(type, &ad)) {
7579 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7580 } else {
7581 expr_type(type);
7583 skip(')');
7586 static void parse_type(CType *type)
7588 AttributeDef ad;
7589 int n;
7591 if (!parse_btype(type, &ad)) {
7592 expect("type");
7594 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7597 static void vpush_tokc(int t)
7599 CType type;
7600 type.t = t;
7601 vsetc(&type, VT_CONST, &tokc);
7604 static void unary(void)
7606 int n, t, align, size, r;
7607 CType type;
7608 Sym *s;
7609 AttributeDef ad;
7611 /* XXX: GCC 2.95.3 does not generate a table although it should be
7612 better here */
7613 tok_next:
7614 switch(tok) {
7615 case TOK_EXTENSION:
7616 next();
7617 goto tok_next;
7618 case TOK_CINT:
7619 case TOK_CCHAR:
7620 case TOK_LCHAR:
7621 vpushi(tokc.i);
7622 next();
7623 break;
7624 case TOK_CUINT:
7625 vpush_tokc(VT_INT | VT_UNSIGNED);
7626 next();
7627 break;
7628 case TOK_CLLONG:
7629 vpush_tokc(VT_LLONG);
7630 next();
7631 break;
7632 case TOK_CULLONG:
7633 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7634 next();
7635 break;
7636 case TOK_CFLOAT:
7637 vpush_tokc(VT_FLOAT);
7638 next();
7639 break;
7640 case TOK_CDOUBLE:
7641 vpush_tokc(VT_DOUBLE);
7642 next();
7643 break;
7644 case TOK_CLDOUBLE:
7645 vpush_tokc(VT_LDOUBLE);
7646 next();
7647 break;
7648 case TOK___FUNCTION__:
7649 if (!gnu_ext)
7650 goto tok_identifier;
7651 /* fall thru */
7652 case TOK___FUNC__:
7654 void *ptr;
7655 int len;
7656 /* special function name identifier */
7657 len = strlen(funcname) + 1;
7658 /* generate char[len] type */
7659 type.t = VT_BYTE;
7660 mk_pointer(&type);
7661 type.t |= VT_ARRAY;
7662 type.ref->c = len;
7663 vpush_ref(&type, data_section, data_section->data_offset, len);
7664 ptr = section_ptr_add(data_section, len);
7665 memcpy(ptr, funcname, len);
7666 next();
7668 break;
7669 case TOK_LSTR:
7670 #ifdef TCC_TARGET_PE
7671 t = VT_SHORT | VT_UNSIGNED;
7672 #else
7673 t = VT_INT;
7674 #endif
7675 goto str_init;
7676 case TOK_STR:
7677 /* string parsing */
7678 t = VT_BYTE;
7679 str_init:
7680 if (tcc_state->warn_write_strings)
7681 t |= VT_CONSTANT;
7682 type.t = t;
7683 mk_pointer(&type);
7684 type.t |= VT_ARRAY;
7685 memset(&ad, 0, sizeof(AttributeDef));
7686 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7687 break;
7688 case '(':
7689 next();
7690 /* cast ? */
7691 if (parse_btype(&type, &ad)) {
7692 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7693 skip(')');
7694 /* check ISOC99 compound literal */
7695 if (tok == '{') {
7696 /* data is allocated locally by default */
7697 if (global_expr)
7698 r = VT_CONST;
7699 else
7700 r = VT_LOCAL;
7701 /* all except arrays are lvalues */
7702 if (!(type.t & VT_ARRAY))
7703 r |= lvalue_type(type.t);
7704 memset(&ad, 0, sizeof(AttributeDef));
7705 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7706 } else {
7707 unary();
7708 gen_cast(&type);
7710 } else if (tok == '{') {
7711 /* save all registers */
7712 save_regs(0);
7713 /* statement expression : we do not accept break/continue
7714 inside as GCC does */
7715 block(NULL, NULL, NULL, NULL, 0, 1);
7716 skip(')');
7717 } else {
7718 gexpr();
7719 skip(')');
7721 break;
7722 case '*':
7723 next();
7724 unary();
7725 indir();
7726 break;
7727 case '&':
7728 next();
7729 unary();
7730 /* functions names must be treated as function pointers,
7731 except for unary '&' and sizeof. Since we consider that
7732 functions are not lvalues, we only have to handle it
7733 there and in function calls. */
7734 /* arrays can also be used although they are not lvalues */
7735 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7736 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7737 test_lvalue();
7738 mk_pointer(&vtop->type);
7739 gaddrof();
7740 break;
7741 case '!':
7742 next();
7743 unary();
7744 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
7745 CType boolean;
7746 boolean.t = VT_BOOL;
7747 gen_cast(&boolean);
7748 vtop->c.i = !vtop->c.i;
7749 } else if ((vtop->r & VT_VALMASK) == VT_CMP)
7750 vtop->c.i = vtop->c.i ^ 1;
7751 else {
7752 save_regs(1);
7753 vseti(VT_JMP, gtst(1, 0));
7755 break;
7756 case '~':
7757 next();
7758 unary();
7759 vpushi(-1);
7760 gen_op('^');
7761 break;
7762 case '+':
7763 next();
7764 /* in order to force cast, we add zero */
7765 unary();
7766 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7767 error("pointer not accepted for unary plus");
7768 vpushi(0);
7769 gen_op('+');
7770 break;
7771 case TOK_SIZEOF:
7772 case TOK_ALIGNOF1:
7773 case TOK_ALIGNOF2:
7774 t = tok;
7775 next();
7776 if (tok == '(') {
7777 parse_expr_type(&type);
7778 } else {
7779 unary_type(&type);
7781 size = type_size(&type, &align);
7782 if (t == TOK_SIZEOF) {
7783 if (size < 0)
7784 error("sizeof applied to an incomplete type");
7785 vpushi(size);
7786 } else {
7787 vpushi(align);
7789 vtop->type.t |= VT_UNSIGNED;
7790 break;
7792 case TOK_builtin_types_compatible_p:
7794 CType type1, type2;
7795 next();
7796 skip('(');
7797 parse_type(&type1);
7798 skip(',');
7799 parse_type(&type2);
7800 skip(')');
7801 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7802 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7803 vpushi(is_compatible_types(&type1, &type2));
7805 break;
7806 case TOK_builtin_constant_p:
7808 int saved_nocode_wanted, res;
7809 next();
7810 skip('(');
7811 saved_nocode_wanted = nocode_wanted;
7812 nocode_wanted = 1;
7813 gexpr();
7814 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7815 vpop();
7816 nocode_wanted = saved_nocode_wanted;
7817 skip(')');
7818 vpushi(res);
7820 break;
7821 case TOK_builtin_frame_address:
7823 CType type;
7824 next();
7825 skip('(');
7826 if (tok != TOK_CINT) {
7827 error("__builtin_frame_address only takes integers");
7829 if (tokc.i != 0) {
7830 error("TCC only supports __builtin_frame_address(0)");
7832 next();
7833 skip(')');
7834 type.t = VT_VOID;
7835 mk_pointer(&type);
7836 vset(&type, VT_LOCAL, 0);
7838 break;
7839 #ifdef TCC_TARGET_X86_64
7840 case TOK_builtin_malloc:
7841 tok = TOK_malloc;
7842 goto tok_identifier;
7843 case TOK_builtin_free:
7844 tok = TOK_free;
7845 goto tok_identifier;
7846 #endif
7847 case TOK_INC:
7848 case TOK_DEC:
7849 t = tok;
7850 next();
7851 unary();
7852 inc(0, t);
7853 break;
7854 case '-':
7855 next();
7856 vpushi(0);
7857 unary();
7858 gen_op('-');
7859 break;
7860 case TOK_LAND:
7861 if (!gnu_ext)
7862 goto tok_identifier;
7863 next();
7864 /* allow to take the address of a label */
7865 if (tok < TOK_UIDENT)
7866 expect("label identifier");
7867 s = label_find(tok);
7868 if (!s) {
7869 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7870 } else {
7871 if (s->r == LABEL_DECLARED)
7872 s->r = LABEL_FORWARD;
7874 if (!s->type.t) {
7875 s->type.t = VT_VOID;
7876 mk_pointer(&s->type);
7877 s->type.t |= VT_STATIC;
7879 vset(&s->type, VT_CONST | VT_SYM, 0);
7880 vtop->sym = s;
7881 next();
7882 break;
7883 default:
7884 tok_identifier:
7885 t = tok;
7886 next();
7887 if (t < TOK_UIDENT)
7888 expect("identifier");
7889 s = sym_find(t);
7890 if (!s) {
7891 if (tok != '(')
7892 error("'%s' undeclared", get_tok_str(t, NULL));
7893 /* for simple function calls, we tolerate undeclared
7894 external reference to int() function */
7895 if (tcc_state->warn_implicit_function_declaration)
7896 warning("implicit declaration of function '%s'",
7897 get_tok_str(t, NULL));
7898 s = external_global_sym(t, &func_old_type, 0);
7900 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7901 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7902 /* if referencing an inline function, then we generate a
7903 symbol to it if not already done. It will have the
7904 effect to generate code for it at the end of the
7905 compilation unit. Inline function as always
7906 generated in the text section. */
7907 if (!s->c)
7908 put_extern_sym(s, text_section, 0, 0);
7909 r = VT_SYM | VT_CONST;
7910 } else {
7911 r = s->r;
7913 vset(&s->type, r, s->c);
7914 /* if forward reference, we must point to s */
7915 if (vtop->r & VT_SYM) {
7916 vtop->sym = s;
7917 vtop->c.ul = 0;
7919 break;
7922 /* post operations */
7923 while (1) {
7924 if (tok == TOK_INC || tok == TOK_DEC) {
7925 inc(1, tok);
7926 next();
7927 } else if (tok == '.' || tok == TOK_ARROW) {
7928 /* field */
7929 if (tok == TOK_ARROW)
7930 indir();
7931 test_lvalue();
7932 gaddrof();
7933 next();
7934 /* expect pointer on structure */
7935 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7936 expect("struct or union");
7937 s = vtop->type.ref;
7938 /* find field */
7939 tok |= SYM_FIELD;
7940 while ((s = s->next) != NULL) {
7941 if (s->v == tok)
7942 break;
7944 if (!s)
7945 error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL));
7946 /* add field offset to pointer */
7947 vtop->type = char_pointer_type; /* change type to 'char *' */
7948 vpushi(s->c);
7949 gen_op('+');
7950 /* change type to field type, and set to lvalue */
7951 vtop->type = s->type;
7952 /* an array is never an lvalue */
7953 if (!(vtop->type.t & VT_ARRAY)) {
7954 vtop->r |= lvalue_type(vtop->type.t);
7955 /* if bound checking, the referenced pointer must be checked */
7956 if (do_bounds_check)
7957 vtop->r |= VT_MUSTBOUND;
7959 next();
7960 } else if (tok == '[') {
7961 next();
7962 gexpr();
7963 gen_op('+');
7964 indir();
7965 skip(']');
7966 } else if (tok == '(') {
7967 SValue ret;
7968 Sym *sa;
7969 int nb_args;
7971 /* function call */
7972 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7973 /* pointer test (no array accepted) */
7974 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7975 vtop->type = *pointed_type(&vtop->type);
7976 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7977 goto error_func;
7978 } else {
7979 error_func:
7980 expect("function pointer");
7982 } else {
7983 vtop->r &= ~VT_LVAL; /* no lvalue */
7985 /* get return type */
7986 s = vtop->type.ref;
7987 next();
7988 sa = s->next; /* first parameter */
7989 nb_args = 0;
7990 ret.r2 = VT_CONST;
7991 /* compute first implicit argument if a structure is returned */
7992 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7993 /* get some space for the returned structure */
7994 size = type_size(&s->type, &align);
7995 loc = (loc - size) & -align;
7996 ret.type = s->type;
7997 ret.r = VT_LOCAL | VT_LVAL;
7998 /* pass it as 'int' to avoid structure arg passing
7999 problems */
8000 vseti(VT_LOCAL, loc);
8001 ret.c = vtop->c;
8002 nb_args++;
8003 } else {
8004 ret.type = s->type;
8005 /* return in register */
8006 if (is_float(ret.type.t)) {
8007 ret.r = reg_fret(ret.type.t);
8008 } else {
8009 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
8010 ret.r2 = REG_LRET;
8011 ret.r = REG_IRET;
8013 ret.c.i = 0;
8015 if (tok != ')') {
8016 for(;;) {
8017 expr_eq();
8018 gfunc_param_typed(s, sa);
8019 nb_args++;
8020 if (sa)
8021 sa = sa->next;
8022 if (tok == ')')
8023 break;
8024 skip(',');
8027 if (sa)
8028 error("too few arguments to function");
8029 skip(')');
8030 if (!nocode_wanted) {
8031 gfunc_call(nb_args);
8032 } else {
8033 vtop -= (nb_args + 1);
8035 /* return value */
8036 vsetc(&ret.type, ret.r, &ret.c);
8037 vtop->r2 = ret.r2;
8038 } else {
8039 break;
8044 static void uneq(void)
8046 int t;
8048 unary();
8049 if (tok == '=' ||
8050 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
8051 tok == TOK_A_XOR || tok == TOK_A_OR ||
8052 tok == TOK_A_SHL || tok == TOK_A_SAR) {
8053 test_lvalue();
8054 t = tok;
8055 next();
8056 if (t == '=') {
8057 expr_eq();
8058 } else {
8059 vdup();
8060 expr_eq();
8061 gen_op(t & 0x7f);
8063 vstore();
8067 static void expr_prod(void)
8069 int t;
8071 uneq();
8072 while (tok == '*' || tok == '/' || tok == '%') {
8073 t = tok;
8074 next();
8075 uneq();
8076 gen_op(t);
8080 static void expr_sum(void)
8082 int t;
8084 expr_prod();
8085 while (tok == '+' || tok == '-') {
8086 t = tok;
8087 next();
8088 expr_prod();
8089 gen_op(t);
8093 static void expr_shift(void)
8095 int t;
8097 expr_sum();
8098 while (tok == TOK_SHL || tok == TOK_SAR) {
8099 t = tok;
8100 next();
8101 expr_sum();
8102 gen_op(t);
8106 static void expr_cmp(void)
8108 int t;
8110 expr_shift();
8111 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
8112 tok == TOK_ULT || tok == TOK_UGE) {
8113 t = tok;
8114 next();
8115 expr_shift();
8116 gen_op(t);
8120 static void expr_cmpeq(void)
8122 int t;
8124 expr_cmp();
8125 while (tok == TOK_EQ || tok == TOK_NE) {
8126 t = tok;
8127 next();
8128 expr_cmp();
8129 gen_op(t);
8133 static void expr_and(void)
8135 expr_cmpeq();
8136 while (tok == '&') {
8137 next();
8138 expr_cmpeq();
8139 gen_op('&');
8143 static void expr_xor(void)
8145 expr_and();
8146 while (tok == '^') {
8147 next();
8148 expr_and();
8149 gen_op('^');
8153 static void expr_or(void)
8155 expr_xor();
8156 while (tok == '|') {
8157 next();
8158 expr_xor();
8159 gen_op('|');
8163 /* XXX: fix this mess */
8164 static void expr_land_const(void)
8166 expr_or();
8167 while (tok == TOK_LAND) {
8168 next();
8169 expr_or();
8170 gen_op(TOK_LAND);
8174 /* XXX: fix this mess */
8175 static void expr_lor_const(void)
8177 expr_land_const();
8178 while (tok == TOK_LOR) {
8179 next();
8180 expr_land_const();
8181 gen_op(TOK_LOR);
8185 /* only used if non constant */
8186 static void expr_land(void)
8188 int t;
8190 expr_or();
8191 if (tok == TOK_LAND) {
8192 t = 0;
8193 save_regs(1);
8194 for(;;) {
8195 t = gtst(1, t);
8196 if (tok != TOK_LAND) {
8197 vseti(VT_JMPI, t);
8198 break;
8200 next();
8201 expr_or();
8206 static void expr_lor(void)
8208 int t;
8210 expr_land();
8211 if (tok == TOK_LOR) {
8212 t = 0;
8213 save_regs(1);
8214 for(;;) {
8215 t = gtst(0, t);
8216 if (tok != TOK_LOR) {
8217 vseti(VT_JMP, t);
8218 break;
8220 next();
8221 expr_land();
8226 /* XXX: better constant handling */
8227 static void expr_eq(void)
8229 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
8230 SValue sv;
8231 CType type, type1, type2;
8233 if (const_wanted) {
8234 expr_lor_const();
8235 if (tok == '?') {
8236 CType boolean;
8237 int c;
8238 boolean.t = VT_BOOL;
8239 vdup();
8240 gen_cast(&boolean);
8241 c = vtop->c.i;
8242 vpop();
8243 next();
8244 if (tok != ':' || !gnu_ext) {
8245 vpop();
8246 gexpr();
8248 if (!c)
8249 vpop();
8250 skip(':');
8251 expr_eq();
8252 if (c)
8253 vpop();
8255 } else {
8256 expr_lor();
8257 if (tok == '?') {
8258 next();
8259 if (vtop != vstack) {
8260 /* needed to avoid having different registers saved in
8261 each branch */
8262 if (is_float(vtop->type.t)) {
8263 rc = RC_FLOAT;
8264 #ifdef TCC_TARGET_X86_64
8265 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
8266 rc = RC_ST0;
8268 #endif
8270 else
8271 rc = RC_INT;
8272 gv(rc);
8273 save_regs(1);
8275 if (tok == ':' && gnu_ext) {
8276 gv_dup();
8277 tt = gtst(1, 0);
8278 } else {
8279 tt = gtst(1, 0);
8280 gexpr();
8282 type1 = vtop->type;
8283 sv = *vtop; /* save value to handle it later */
8284 vtop--; /* no vpop so that FP stack is not flushed */
8285 skip(':');
8286 u = gjmp(0);
8287 gsym(tt);
8288 expr_eq();
8289 type2 = vtop->type;
8291 t1 = type1.t;
8292 bt1 = t1 & VT_BTYPE;
8293 t2 = type2.t;
8294 bt2 = t2 & VT_BTYPE;
8295 /* cast operands to correct type according to ISOC rules */
8296 if (is_float(bt1) || is_float(bt2)) {
8297 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
8298 type.t = VT_LDOUBLE;
8299 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
8300 type.t = VT_DOUBLE;
8301 } else {
8302 type.t = VT_FLOAT;
8304 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
8305 /* cast to biggest op */
8306 type.t = VT_LLONG;
8307 /* convert to unsigned if it does not fit in a long long */
8308 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
8309 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
8310 type.t |= VT_UNSIGNED;
8311 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
8312 /* XXX: test pointer compatibility */
8313 type = type1;
8314 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
8315 /* XXX: test function pointer compatibility */
8316 type = type1;
8317 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
8318 /* XXX: test structure compatibility */
8319 type = type1;
8320 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
8321 /* NOTE: as an extension, we accept void on only one side */
8322 type.t = VT_VOID;
8323 } else {
8324 /* integer operations */
8325 type.t = VT_INT;
8326 /* convert to unsigned if it does not fit in an integer */
8327 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
8328 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
8329 type.t |= VT_UNSIGNED;
8332 /* now we convert second operand */
8333 gen_cast(&type);
8334 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8335 gaddrof();
8336 rc = RC_INT;
8337 if (is_float(type.t)) {
8338 rc = RC_FLOAT;
8339 #ifdef TCC_TARGET_X86_64
8340 if ((type.t & VT_BTYPE) == VT_LDOUBLE) {
8341 rc = RC_ST0;
8343 #endif
8344 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
8345 /* for long longs, we use fixed registers to avoid having
8346 to handle a complicated move */
8347 rc = RC_IRET;
8350 r2 = gv(rc);
8351 /* this is horrible, but we must also convert first
8352 operand */
8353 tt = gjmp(0);
8354 gsym(u);
8355 /* put again first value and cast it */
8356 *vtop = sv;
8357 gen_cast(&type);
8358 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8359 gaddrof();
8360 r1 = gv(rc);
8361 move_reg(r2, r1);
8362 vtop->r = r2;
8363 gsym(tt);
8368 static void gexpr(void)
8370 while (1) {
8371 expr_eq();
8372 if (tok != ',')
8373 break;
8374 vpop();
8375 next();
8379 /* parse an expression and return its type without any side effect. */
8380 static void expr_type(CType *type)
8382 int saved_nocode_wanted;
8384 saved_nocode_wanted = nocode_wanted;
8385 nocode_wanted = 1;
8386 gexpr();
8387 *type = vtop->type;
8388 vpop();
8389 nocode_wanted = saved_nocode_wanted;
8392 /* parse a unary expression and return its type without any side
8393 effect. */
8394 static void unary_type(CType *type)
8396 int a;
8398 a = nocode_wanted;
8399 nocode_wanted = 1;
8400 unary();
8401 *type = vtop->type;
8402 vpop();
8403 nocode_wanted = a;
8406 /* parse a constant expression and return value in vtop. */
8407 static void expr_const1(void)
8409 int a;
8410 a = const_wanted;
8411 const_wanted = 1;
8412 expr_eq();
8413 const_wanted = a;
8416 /* parse an integer constant and return its value. */
8417 static int expr_const(void)
8419 int c;
8420 expr_const1();
8421 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8422 expect("constant expression");
8423 c = vtop->c.i;
8424 vpop();
8425 return c;
8428 /* return the label token if current token is a label, otherwise
8429 return zero */
8430 static int is_label(void)
8432 int last_tok;
8434 /* fast test first */
8435 if (tok < TOK_UIDENT)
8436 return 0;
8437 /* no need to save tokc because tok is an identifier */
8438 last_tok = tok;
8439 next();
8440 if (tok == ':') {
8441 next();
8442 return last_tok;
8443 } else {
8444 unget_tok(last_tok);
8445 return 0;
8449 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8450 int case_reg, int is_expr)
8452 int a, b, c, d;
8453 Sym *s;
8455 /* generate line number info */
8456 if (do_debug &&
8457 (last_line_num != file->line_num || last_ind != ind)) {
8458 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8459 last_ind = ind;
8460 last_line_num = file->line_num;
8463 if (is_expr) {
8464 /* default return value is (void) */
8465 vpushi(0);
8466 vtop->type.t = VT_VOID;
8469 if (tok == TOK_IF) {
8470 /* if test */
8471 next();
8472 skip('(');
8473 gexpr();
8474 skip(')');
8475 a = gtst(1, 0);
8476 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8477 c = tok;
8478 if (c == TOK_ELSE) {
8479 next();
8480 d = gjmp(0);
8481 gsym(a);
8482 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8483 gsym(d); /* patch else jmp */
8484 } else
8485 gsym(a);
8486 } else if (tok == TOK_WHILE) {
8487 next();
8488 d = ind;
8489 skip('(');
8490 gexpr();
8491 skip(')');
8492 a = gtst(1, 0);
8493 b = 0;
8494 block(&a, &b, case_sym, def_sym, case_reg, 0);
8495 gjmp_addr(d);
8496 gsym(a);
8497 gsym_addr(b, d);
8498 } else if (tok == '{') {
8499 Sym *llabel;
8501 next();
8502 /* record local declaration stack position */
8503 s = local_stack;
8504 llabel = local_label_stack;
8505 /* handle local labels declarations */
8506 if (tok == TOK_LABEL) {
8507 next();
8508 for(;;) {
8509 if (tok < TOK_UIDENT)
8510 expect("label identifier");
8511 label_push(&local_label_stack, tok, LABEL_DECLARED);
8512 next();
8513 if (tok == ',') {
8514 next();
8515 } else {
8516 skip(';');
8517 break;
8521 while (tok != '}') {
8522 decl(VT_LOCAL);
8523 if (tok != '}') {
8524 if (is_expr)
8525 vpop();
8526 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8529 /* pop locally defined labels */
8530 label_pop(&local_label_stack, llabel);
8531 /* pop locally defined symbols */
8532 if(is_expr) {
8533 /* XXX: this solution makes only valgrind happy...
8534 triggered by gcc.c-torture/execute/20000917-1.c */
8535 Sym *p;
8536 switch(vtop->type.t & VT_BTYPE) {
8537 case VT_PTR:
8538 case VT_STRUCT:
8539 case VT_ENUM:
8540 case VT_FUNC:
8541 for(p=vtop->type.ref;p;p=p->prev)
8542 if(p->prev==s)
8543 error("unsupported expression type");
8546 sym_pop(&local_stack, s);
8547 next();
8548 } else if (tok == TOK_RETURN) {
8549 next();
8550 if (tok != ';') {
8551 gexpr();
8552 gen_assign_cast(&func_vt);
8553 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8554 CType type;
8555 /* if returning structure, must copy it to implicit
8556 first pointer arg location */
8557 #ifdef TCC_ARM_EABI
8558 int align, size;
8559 size = type_size(&func_vt,&align);
8560 if(size <= 4)
8562 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8563 && (align & 3))
8565 int addr;
8566 loc = (loc - size) & -4;
8567 addr = loc;
8568 type = func_vt;
8569 vset(&type, VT_LOCAL | VT_LVAL, addr);
8570 vswap();
8571 vstore();
8572 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8574 vtop->type = int_type;
8575 gv(RC_IRET);
8576 } else {
8577 #endif
8578 type = func_vt;
8579 mk_pointer(&type);
8580 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8581 indir();
8582 vswap();
8583 /* copy structure value to pointer */
8584 vstore();
8585 #ifdef TCC_ARM_EABI
8587 #endif
8588 } else if (is_float(func_vt.t)) {
8589 gv(rc_fret(func_vt.t));
8590 } else {
8591 gv(RC_IRET);
8593 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8595 skip(';');
8596 rsym = gjmp(rsym); /* jmp */
8597 } else if (tok == TOK_BREAK) {
8598 /* compute jump */
8599 if (!bsym)
8600 error("cannot break");
8601 *bsym = gjmp(*bsym);
8602 next();
8603 skip(';');
8604 } else if (tok == TOK_CONTINUE) {
8605 /* compute jump */
8606 if (!csym)
8607 error("cannot continue");
8608 *csym = gjmp(*csym);
8609 next();
8610 skip(';');
8611 } else if (tok == TOK_FOR) {
8612 int e;
8613 next();
8614 skip('(');
8615 if (tok != ';') {
8616 gexpr();
8617 vpop();
8619 skip(';');
8620 d = ind;
8621 c = ind;
8622 a = 0;
8623 b = 0;
8624 if (tok != ';') {
8625 gexpr();
8626 a = gtst(1, 0);
8628 skip(';');
8629 if (tok != ')') {
8630 e = gjmp(0);
8631 c = ind;
8632 gexpr();
8633 vpop();
8634 gjmp_addr(d);
8635 gsym(e);
8637 skip(')');
8638 block(&a, &b, case_sym, def_sym, case_reg, 0);
8639 gjmp_addr(c);
8640 gsym(a);
8641 gsym_addr(b, c);
8642 } else
8643 if (tok == TOK_DO) {
8644 next();
8645 a = 0;
8646 b = 0;
8647 d = ind;
8648 block(&a, &b, case_sym, def_sym, case_reg, 0);
8649 skip(TOK_WHILE);
8650 skip('(');
8651 gsym(b);
8652 gexpr();
8653 c = gtst(0, 0);
8654 gsym_addr(c, d);
8655 skip(')');
8656 gsym(a);
8657 skip(';');
8658 } else
8659 if (tok == TOK_SWITCH) {
8660 next();
8661 skip('(');
8662 gexpr();
8663 /* XXX: other types than integer */
8664 case_reg = gv(RC_INT);
8665 vpop();
8666 skip(')');
8667 a = 0;
8668 b = gjmp(0); /* jump to first case */
8669 c = 0;
8670 block(&a, csym, &b, &c, case_reg, 0);
8671 /* if no default, jmp after switch */
8672 if (c == 0)
8673 c = ind;
8674 /* default label */
8675 gsym_addr(b, c);
8676 /* break label */
8677 gsym(a);
8678 } else
8679 if (tok == TOK_CASE) {
8680 int v1, v2;
8681 if (!case_sym)
8682 expect("switch");
8683 next();
8684 v1 = expr_const();
8685 v2 = v1;
8686 if (gnu_ext && tok == TOK_DOTS) {
8687 next();
8688 v2 = expr_const();
8689 if (v2 < v1)
8690 warning("empty case range");
8692 /* since a case is like a label, we must skip it with a jmp */
8693 b = gjmp(0);
8694 gsym(*case_sym);
8695 vseti(case_reg, 0);
8696 vpushi(v1);
8697 if (v1 == v2) {
8698 gen_op(TOK_EQ);
8699 *case_sym = gtst(1, 0);
8700 } else {
8701 gen_op(TOK_GE);
8702 *case_sym = gtst(1, 0);
8703 vseti(case_reg, 0);
8704 vpushi(v2);
8705 gen_op(TOK_LE);
8706 *case_sym = gtst(1, *case_sym);
8708 gsym(b);
8709 skip(':');
8710 is_expr = 0;
8711 goto block_after_label;
8712 } else
8713 if (tok == TOK_DEFAULT) {
8714 next();
8715 skip(':');
8716 if (!def_sym)
8717 expect("switch");
8718 if (*def_sym)
8719 error("too many 'default'");
8720 *def_sym = ind;
8721 is_expr = 0;
8722 goto block_after_label;
8723 } else
8724 if (tok == TOK_GOTO) {
8725 next();
8726 if (tok == '*' && gnu_ext) {
8727 /* computed goto */
8728 next();
8729 gexpr();
8730 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8731 expect("pointer");
8732 ggoto();
8733 } else if (tok >= TOK_UIDENT) {
8734 s = label_find(tok);
8735 /* put forward definition if needed */
8736 if (!s) {
8737 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8738 } else {
8739 if (s->r == LABEL_DECLARED)
8740 s->r = LABEL_FORWARD;
8742 /* label already defined */
8743 if (s->r & LABEL_FORWARD)
8744 s->next = (void *)gjmp((long)s->next);
8745 else
8746 gjmp_addr((long)s->next);
8747 next();
8748 } else {
8749 expect("label identifier");
8751 skip(';');
8752 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8753 asm_instr();
8754 } else {
8755 b = is_label();
8756 if (b) {
8757 /* label case */
8758 s = label_find(b);
8759 if (s) {
8760 if (s->r == LABEL_DEFINED)
8761 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8762 gsym((long)s->next);
8763 s->r = LABEL_DEFINED;
8764 } else {
8765 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8767 s->next = (void *)ind;
8768 /* we accept this, but it is a mistake */
8769 block_after_label:
8770 if (tok == '}') {
8771 warning("deprecated use of label at end of compound statement");
8772 } else {
8773 if (is_expr)
8774 vpop();
8775 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8777 } else {
8778 /* expression case */
8779 if (tok != ';') {
8780 if (is_expr) {
8781 vpop();
8782 gexpr();
8783 } else {
8784 gexpr();
8785 vpop();
8788 skip(';');
8793 /* t is the array or struct type. c is the array or struct
8794 address. cur_index/cur_field is the pointer to the current
8795 value. 'size_only' is true if only size info is needed (only used
8796 in arrays) */
8797 static void decl_designator(CType *type, Section *sec, unsigned long c,
8798 int *cur_index, Sym **cur_field,
8799 int size_only)
8801 Sym *s, *f;
8802 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8803 CType type1;
8805 notfirst = 0;
8806 elem_size = 0;
8807 nb_elems = 1;
8808 if (gnu_ext && (l = is_label()) != 0)
8809 goto struct_field;
8810 while (tok == '[' || tok == '.') {
8811 if (tok == '[') {
8812 if (!(type->t & VT_ARRAY))
8813 expect("array type");
8814 s = type->ref;
8815 next();
8816 index = expr_const();
8817 if (index < 0 || (s->c >= 0 && index >= s->c))
8818 expect("invalid index");
8819 if (tok == TOK_DOTS && gnu_ext) {
8820 next();
8821 index_last = expr_const();
8822 if (index_last < 0 ||
8823 (s->c >= 0 && index_last >= s->c) ||
8824 index_last < index)
8825 expect("invalid index");
8826 } else {
8827 index_last = index;
8829 skip(']');
8830 if (!notfirst)
8831 *cur_index = index_last;
8832 type = pointed_type(type);
8833 elem_size = type_size(type, &align);
8834 c += index * elem_size;
8835 /* NOTE: we only support ranges for last designator */
8836 nb_elems = index_last - index + 1;
8837 if (nb_elems != 1) {
8838 notfirst = 1;
8839 break;
8841 } else {
8842 next();
8843 l = tok;
8844 next();
8845 struct_field:
8846 if ((type->t & VT_BTYPE) != VT_STRUCT)
8847 expect("struct/union type");
8848 s = type->ref;
8849 l |= SYM_FIELD;
8850 f = s->next;
8851 while (f) {
8852 if (f->v == l)
8853 break;
8854 f = f->next;
8856 if (!f)
8857 expect("field");
8858 if (!notfirst)
8859 *cur_field = f;
8860 /* XXX: fix this mess by using explicit storage field */
8861 type1 = f->type;
8862 type1.t |= (type->t & ~VT_TYPE);
8863 type = &type1;
8864 c += f->c;
8866 notfirst = 1;
8868 if (notfirst) {
8869 if (tok == '=') {
8870 next();
8871 } else {
8872 if (!gnu_ext)
8873 expect("=");
8875 } else {
8876 if (type->t & VT_ARRAY) {
8877 index = *cur_index;
8878 type = pointed_type(type);
8879 c += index * type_size(type, &align);
8880 } else {
8881 f = *cur_field;
8882 if (!f)
8883 error("too many field init");
8884 /* XXX: fix this mess by using explicit storage field */
8885 type1 = f->type;
8886 type1.t |= (type->t & ~VT_TYPE);
8887 type = &type1;
8888 c += f->c;
8891 decl_initializer(type, sec, c, 0, size_only);
8893 /* XXX: make it more general */
8894 if (!size_only && nb_elems > 1) {
8895 unsigned long c_end;
8896 uint8_t *src, *dst;
8897 int i;
8899 if (!sec)
8900 error("range init not supported yet for dynamic storage");
8901 c_end = c + nb_elems * elem_size;
8902 if (c_end > sec->data_allocated)
8903 section_realloc(sec, c_end);
8904 src = sec->data + c;
8905 dst = src;
8906 for(i = 1; i < nb_elems; i++) {
8907 dst += elem_size;
8908 memcpy(dst, src, elem_size);
8913 #define EXPR_VAL 0
8914 #define EXPR_CONST 1
8915 #define EXPR_ANY 2
8917 /* store a value or an expression directly in global data or in local array */
8918 static void init_putv(CType *type, Section *sec, unsigned long c,
8919 int v, int expr_type)
8921 int saved_global_expr, bt, bit_pos, bit_size;
8922 void *ptr;
8923 unsigned long long bit_mask;
8924 CType dtype;
8926 switch(expr_type) {
8927 case EXPR_VAL:
8928 vpushi(v);
8929 break;
8930 case EXPR_CONST:
8931 /* compound literals must be allocated globally in this case */
8932 saved_global_expr = global_expr;
8933 global_expr = 1;
8934 expr_const1();
8935 global_expr = saved_global_expr;
8936 /* NOTE: symbols are accepted */
8937 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8938 error("initializer element is not constant");
8939 break;
8940 case EXPR_ANY:
8941 expr_eq();
8942 break;
8945 dtype = *type;
8946 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8948 if (sec) {
8949 /* XXX: not portable */
8950 /* XXX: generate error if incorrect relocation */
8951 gen_assign_cast(&dtype);
8952 bt = type->t & VT_BTYPE;
8953 /* we'll write at most 12 bytes */
8954 if (c + 12 > sec->data_allocated) {
8955 section_realloc(sec, c + 12);
8957 ptr = sec->data + c;
8958 /* XXX: make code faster ? */
8959 if (!(type->t & VT_BITFIELD)) {
8960 bit_pos = 0;
8961 bit_size = 32;
8962 bit_mask = -1LL;
8963 } else {
8964 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8965 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8966 bit_mask = (1LL << bit_size) - 1;
8968 if ((vtop->r & VT_SYM) &&
8969 (bt == VT_BYTE ||
8970 bt == VT_SHORT ||
8971 bt == VT_DOUBLE ||
8972 bt == VT_LDOUBLE ||
8973 bt == VT_LLONG ||
8974 (bt == VT_INT && bit_size != 32)))
8975 error("initializer element is not computable at load time");
8976 switch(bt) {
8977 case VT_BOOL:
8978 vtop->c.i = (vtop->c.i != 0);
8979 case VT_BYTE:
8980 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8981 break;
8982 case VT_SHORT:
8983 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8984 break;
8985 case VT_DOUBLE:
8986 *(double *)ptr = vtop->c.d;
8987 break;
8988 case VT_LDOUBLE:
8989 *(long double *)ptr = vtop->c.ld;
8990 break;
8991 case VT_LLONG:
8992 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8993 break;
8994 default:
8995 if (vtop->r & VT_SYM) {
8996 greloc(sec, vtop->sym, c, R_DATA_32);
8998 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8999 break;
9001 vtop--;
9002 } else {
9003 vset(&dtype, VT_LOCAL|VT_LVAL, c);
9004 vswap();
9005 vstore();
9006 vpop();
9010 /* put zeros for variable based init */
9011 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
9013 if (sec) {
9014 /* nothing to do because globals are already set to zero */
9015 } else {
9016 vpush_global_sym(&func_old_type, TOK_memset);
9017 vseti(VT_LOCAL, c);
9018 vpushi(0);
9019 vpushi(size);
9020 gfunc_call(3);
9024 /* 't' contains the type and storage info. 'c' is the offset of the
9025 object in section 'sec'. If 'sec' is NULL, it means stack based
9026 allocation. 'first' is true if array '{' must be read (multi
9027 dimension implicit array init handling). 'size_only' is true if
9028 size only evaluation is wanted (only for arrays). */
9029 static void decl_initializer(CType *type, Section *sec, unsigned long c,
9030 int first, int size_only)
9032 int index, array_length, n, no_oblock, nb, parlevel, i;
9033 int size1, align1, expr_type;
9034 Sym *s, *f;
9035 CType *t1;
9037 if (type->t & VT_ARRAY) {
9038 s = type->ref;
9039 n = s->c;
9040 array_length = 0;
9041 t1 = pointed_type(type);
9042 size1 = type_size(t1, &align1);
9044 no_oblock = 1;
9045 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
9046 tok == '{') {
9047 skip('{');
9048 no_oblock = 0;
9051 /* only parse strings here if correct type (otherwise: handle
9052 them as ((w)char *) expressions */
9053 if ((tok == TOK_LSTR &&
9054 #ifdef TCC_TARGET_PE
9055 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
9056 #else
9057 (t1->t & VT_BTYPE) == VT_INT
9058 #endif
9059 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
9060 while (tok == TOK_STR || tok == TOK_LSTR) {
9061 int cstr_len, ch;
9062 CString *cstr;
9064 cstr = tokc.cstr;
9065 /* compute maximum number of chars wanted */
9066 if (tok == TOK_STR)
9067 cstr_len = cstr->size;
9068 else
9069 cstr_len = cstr->size / sizeof(nwchar_t);
9070 cstr_len--;
9071 nb = cstr_len;
9072 if (n >= 0 && nb > (n - array_length))
9073 nb = n - array_length;
9074 if (!size_only) {
9075 if (cstr_len > nb)
9076 warning("initializer-string for array is too long");
9077 /* in order to go faster for common case (char
9078 string in global variable, we handle it
9079 specifically */
9080 if (sec && tok == TOK_STR && size1 == 1) {
9081 memcpy(sec->data + c + array_length, cstr->data, nb);
9082 } else {
9083 for(i=0;i<nb;i++) {
9084 if (tok == TOK_STR)
9085 ch = ((unsigned char *)cstr->data)[i];
9086 else
9087 ch = ((nwchar_t *)cstr->data)[i];
9088 init_putv(t1, sec, c + (array_length + i) * size1,
9089 ch, EXPR_VAL);
9093 array_length += nb;
9094 next();
9096 /* only add trailing zero if enough storage (no
9097 warning in this case since it is standard) */
9098 if (n < 0 || array_length < n) {
9099 if (!size_only) {
9100 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
9102 array_length++;
9104 } else {
9105 index = 0;
9106 while (tok != '}') {
9107 decl_designator(type, sec, c, &index, NULL, size_only);
9108 if (n >= 0 && index >= n)
9109 error("index too large");
9110 /* must put zero in holes (note that doing it that way
9111 ensures that it even works with designators) */
9112 if (!size_only && array_length < index) {
9113 init_putz(t1, sec, c + array_length * size1,
9114 (index - array_length) * size1);
9116 index++;
9117 if (index > array_length)
9118 array_length = index;
9119 /* special test for multi dimensional arrays (may not
9120 be strictly correct if designators are used at the
9121 same time) */
9122 if (index >= n && no_oblock)
9123 break;
9124 if (tok == '}')
9125 break;
9126 skip(',');
9129 if (!no_oblock)
9130 skip('}');
9131 /* put zeros at the end */
9132 if (!size_only && n >= 0 && array_length < n) {
9133 init_putz(t1, sec, c + array_length * size1,
9134 (n - array_length) * size1);
9136 /* patch type size if needed */
9137 if (n < 0)
9138 s->c = array_length;
9139 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
9140 (sec || !first || tok == '{')) {
9141 int par_count;
9143 /* NOTE: the previous test is a specific case for automatic
9144 struct/union init */
9145 /* XXX: union needs only one init */
9147 /* XXX: this test is incorrect for local initializers
9148 beginning with ( without {. It would be much more difficult
9149 to do it correctly (ideally, the expression parser should
9150 be used in all cases) */
9151 par_count = 0;
9152 if (tok == '(') {
9153 AttributeDef ad1;
9154 CType type1;
9155 next();
9156 while (tok == '(') {
9157 par_count++;
9158 next();
9160 if (!parse_btype(&type1, &ad1))
9161 expect("cast");
9162 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
9163 #if 0
9164 if (!is_assignable_types(type, &type1))
9165 error("invalid type for cast");
9166 #endif
9167 skip(')');
9169 no_oblock = 1;
9170 if (first || tok == '{') {
9171 skip('{');
9172 no_oblock = 0;
9174 s = type->ref;
9175 f = s->next;
9176 array_length = 0;
9177 index = 0;
9178 n = s->c;
9179 while (tok != '}') {
9180 decl_designator(type, sec, c, NULL, &f, size_only);
9181 index = f->c;
9182 if (!size_only && array_length < index) {
9183 init_putz(type, sec, c + array_length,
9184 index - array_length);
9186 index = index + type_size(&f->type, &align1);
9187 if (index > array_length)
9188 array_length = index;
9189 f = f->next;
9190 if (no_oblock && f == NULL)
9191 break;
9192 if (tok == '}')
9193 break;
9194 skip(',');
9196 /* put zeros at the end */
9197 if (!size_only && array_length < n) {
9198 init_putz(type, sec, c + array_length,
9199 n - array_length);
9201 if (!no_oblock)
9202 skip('}');
9203 while (par_count) {
9204 skip(')');
9205 par_count--;
9207 } else if (tok == '{') {
9208 next();
9209 decl_initializer(type, sec, c, first, size_only);
9210 skip('}');
9211 } else if (size_only) {
9212 /* just skip expression */
9213 parlevel = 0;
9214 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
9215 tok != -1) {
9216 if (tok == '(')
9217 parlevel++;
9218 else if (tok == ')')
9219 parlevel--;
9220 next();
9222 } else {
9223 /* currently, we always use constant expression for globals
9224 (may change for scripting case) */
9225 expr_type = EXPR_CONST;
9226 if (!sec)
9227 expr_type = EXPR_ANY;
9228 init_putv(type, sec, c, 0, expr_type);
9232 /* parse an initializer for type 't' if 'has_init' is non zero, and
9233 allocate space in local or global data space ('r' is either
9234 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
9235 variable 'v' of scope 'scope' is declared before initializers are
9236 parsed. If 'v' is zero, then a reference to the new object is put
9237 in the value stack. If 'has_init' is 2, a special parsing is done
9238 to handle string constants. */
9239 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
9240 int has_init, int v, int scope)
9242 int size, align, addr, data_offset;
9243 int level;
9244 ParseState saved_parse_state = {0};
9245 TokenString init_str;
9246 Section *sec;
9248 size = type_size(type, &align);
9249 /* If unknown size, we must evaluate it before
9250 evaluating initializers because
9251 initializers can generate global data too
9252 (e.g. string pointers or ISOC99 compound
9253 literals). It also simplifies local
9254 initializers handling */
9255 tok_str_new(&init_str);
9256 if (size < 0) {
9257 if (!has_init)
9258 error("unknown type size");
9259 /* get all init string */
9260 if (has_init == 2) {
9261 /* only get strings */
9262 while (tok == TOK_STR || tok == TOK_LSTR) {
9263 tok_str_add_tok(&init_str);
9264 next();
9266 } else {
9267 level = 0;
9268 while (level > 0 || (tok != ',' && tok != ';')) {
9269 if (tok < 0)
9270 error("unexpected end of file in initializer");
9271 tok_str_add_tok(&init_str);
9272 if (tok == '{')
9273 level++;
9274 else if (tok == '}') {
9275 level--;
9276 if (level <= 0) {
9277 next();
9278 break;
9281 next();
9284 tok_str_add(&init_str, -1);
9285 tok_str_add(&init_str, 0);
9287 /* compute size */
9288 save_parse_state(&saved_parse_state);
9290 macro_ptr = init_str.str;
9291 next();
9292 decl_initializer(type, NULL, 0, 1, 1);
9293 /* prepare second initializer parsing */
9294 macro_ptr = init_str.str;
9295 next();
9297 /* if still unknown size, error */
9298 size = type_size(type, &align);
9299 if (size < 0)
9300 error("unknown type size");
9302 /* take into account specified alignment if bigger */
9303 if (ad->aligned) {
9304 if (ad->aligned > align)
9305 align = ad->aligned;
9306 } else if (ad->packed) {
9307 align = 1;
9309 if ((r & VT_VALMASK) == VT_LOCAL) {
9310 sec = NULL;
9311 if (do_bounds_check && (type->t & VT_ARRAY))
9312 loc--;
9313 loc = (loc - size) & -align;
9314 addr = loc;
9315 /* handles bounds */
9316 /* XXX: currently, since we do only one pass, we cannot track
9317 '&' operators, so we add only arrays */
9318 if (do_bounds_check && (type->t & VT_ARRAY)) {
9319 unsigned long *bounds_ptr;
9320 /* add padding between regions */
9321 loc--;
9322 /* then add local bound info */
9323 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
9324 bounds_ptr[0] = addr;
9325 bounds_ptr[1] = size;
9327 if (v) {
9328 /* local variable */
9329 sym_push(v, type, r, addr);
9330 } else {
9331 /* push local reference */
9332 vset(type, r, addr);
9334 } else {
9335 Sym *sym;
9337 sym = NULL;
9338 if (v && scope == VT_CONST) {
9339 /* see if the symbol was already defined */
9340 sym = sym_find(v);
9341 if (sym) {
9342 if (!is_compatible_types(&sym->type, type))
9343 error("incompatible types for redefinition of '%s'",
9344 get_tok_str(v, NULL));
9345 if (sym->type.t & VT_EXTERN) {
9346 /* if the variable is extern, it was not allocated */
9347 sym->type.t &= ~VT_EXTERN;
9348 /* set array size if it was ommited in extern
9349 declaration */
9350 if ((sym->type.t & VT_ARRAY) &&
9351 sym->type.ref->c < 0 &&
9352 type->ref->c >= 0)
9353 sym->type.ref->c = type->ref->c;
9354 } else {
9355 /* we accept several definitions of the same
9356 global variable. this is tricky, because we
9357 must play with the SHN_COMMON type of the symbol */
9358 /* XXX: should check if the variable was already
9359 initialized. It is incorrect to initialized it
9360 twice */
9361 /* no init data, we won't add more to the symbol */
9362 if (!has_init)
9363 goto no_alloc;
9368 /* allocate symbol in corresponding section */
9369 sec = ad->section;
9370 if (!sec) {
9371 if (has_init)
9372 sec = data_section;
9373 else if (tcc_state->nocommon)
9374 sec = bss_section;
9376 if (sec) {
9377 data_offset = sec->data_offset;
9378 data_offset = (data_offset + align - 1) & -align;
9379 addr = data_offset;
9380 /* very important to increment global pointer at this time
9381 because initializers themselves can create new initializers */
9382 data_offset += size;
9383 /* add padding if bound check */
9384 if (do_bounds_check)
9385 data_offset++;
9386 sec->data_offset = data_offset;
9387 /* allocate section space to put the data */
9388 if (sec->sh_type != SHT_NOBITS &&
9389 data_offset > sec->data_allocated)
9390 section_realloc(sec, data_offset);
9391 /* align section if needed */
9392 if (align > sec->sh_addralign)
9393 sec->sh_addralign = align;
9394 } else {
9395 addr = 0; /* avoid warning */
9398 if (v) {
9399 if (scope != VT_CONST || !sym) {
9400 sym = sym_push(v, type, r | VT_SYM, 0);
9402 /* update symbol definition */
9403 if (sec) {
9404 put_extern_sym(sym, sec, addr, size);
9405 } else {
9406 ElfW(Sym) *esym;
9407 /* put a common area */
9408 put_extern_sym(sym, NULL, align, size);
9409 /* XXX: find a nicer way */
9410 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
9411 esym->st_shndx = SHN_COMMON;
9413 } else {
9414 CValue cval;
9416 /* push global reference */
9417 sym = get_sym_ref(type, sec, addr, size);
9418 cval.ul = 0;
9419 vsetc(type, VT_CONST | VT_SYM, &cval);
9420 vtop->sym = sym;
9423 /* handles bounds now because the symbol must be defined
9424 before for the relocation */
9425 if (do_bounds_check) {
9426 unsigned long *bounds_ptr;
9428 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9429 /* then add global bound info */
9430 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9431 bounds_ptr[0] = 0; /* relocated */
9432 bounds_ptr[1] = size;
9435 if (has_init) {
9436 decl_initializer(type, sec, addr, 1, 0);
9437 /* restore parse state if needed */
9438 if (init_str.str) {
9439 tok_str_free(init_str.str);
9440 restore_parse_state(&saved_parse_state);
9443 no_alloc: ;
9446 void put_func_debug(Sym *sym)
9448 char buf[512];
9450 /* stabs info */
9451 /* XXX: we put here a dummy type */
9452 snprintf(buf, sizeof(buf), "%s:%c1",
9453 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9454 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9455 cur_text_section, sym->c);
9456 /* //gr gdb wants a line at the function */
9457 put_stabn(N_SLINE, 0, file->line_num, 0);
9458 last_ind = 0;
9459 last_line_num = 0;
9462 /* parse an old style function declaration list */
9463 /* XXX: check multiple parameter */
9464 static void func_decl_list(Sym *func_sym)
9466 AttributeDef ad;
9467 int v;
9468 Sym *s;
9469 CType btype, type;
9471 /* parse each declaration */
9472 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9473 if (!parse_btype(&btype, &ad))
9474 expect("declaration list");
9475 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9476 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9477 tok == ';') {
9478 /* we accept no variable after */
9479 } else {
9480 for(;;) {
9481 type = btype;
9482 type_decl(&type, &ad, &v, TYPE_DIRECT);
9483 /* find parameter in function parameter list */
9484 s = func_sym->next;
9485 while (s != NULL) {
9486 if ((s->v & ~SYM_FIELD) == v)
9487 goto found;
9488 s = s->next;
9490 error("declaration for parameter '%s' but no such parameter",
9491 get_tok_str(v, NULL));
9492 found:
9493 /* check that no storage specifier except 'register' was given */
9494 if (type.t & VT_STORAGE)
9495 error("storage class specified for '%s'", get_tok_str(v, NULL));
9496 convert_parameter_type(&type);
9497 /* we can add the type (NOTE: it could be local to the function) */
9498 s->type = type;
9499 /* accept other parameters */
9500 if (tok == ',')
9501 next();
9502 else
9503 break;
9506 skip(';');
9510 /* parse a function defined by symbol 'sym' and generate its code in
9511 'cur_text_section' */
9512 static void gen_function(Sym *sym)
9514 int saved_nocode_wanted = nocode_wanted;
9515 nocode_wanted = 0;
9516 ind = cur_text_section->data_offset;
9517 /* NOTE: we patch the symbol size later */
9518 put_extern_sym(sym, cur_text_section, ind, 0);
9519 funcname = get_tok_str(sym->v, NULL);
9520 func_ind = ind;
9521 /* put debug symbol */
9522 if (do_debug)
9523 put_func_debug(sym);
9524 /* push a dummy symbol to enable local sym storage */
9525 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9526 gfunc_prolog(&sym->type);
9527 rsym = 0;
9528 block(NULL, NULL, NULL, NULL, 0, 0);
9529 gsym(rsym);
9530 gfunc_epilog();
9531 cur_text_section->data_offset = ind;
9532 label_pop(&global_label_stack, NULL);
9533 sym_pop(&local_stack, NULL); /* reset local stack */
9534 /* end of function */
9535 /* patch symbol size */
9536 ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size =
9537 ind - func_ind;
9538 if (do_debug) {
9539 put_stabn(N_FUN, 0, 0, ind - func_ind);
9541 /* It's better to crash than to generate wrong code */
9542 cur_text_section = NULL;
9543 funcname = ""; /* for safety */
9544 func_vt.t = VT_VOID; /* for safety */
9545 ind = 0; /* for safety */
9546 nocode_wanted = saved_nocode_wanted;
9549 static void gen_inline_functions(void)
9551 Sym *sym;
9552 CType *type;
9553 int *str, inline_generated;
9555 /* iterate while inline function are referenced */
9556 for(;;) {
9557 inline_generated = 0;
9558 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9559 type = &sym->type;
9560 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9561 (type->t & (VT_STATIC | VT_INLINE)) ==
9562 (VT_STATIC | VT_INLINE) &&
9563 sym->c != 0) {
9564 /* the function was used: generate its code and
9565 convert it to a normal function */
9566 str = INLINE_DEF(sym->r);
9567 sym->r = VT_SYM | VT_CONST;
9568 sym->type.t &= ~VT_INLINE;
9570 macro_ptr = str;
9571 next();
9572 cur_text_section = text_section;
9573 gen_function(sym);
9574 macro_ptr = NULL; /* fail safe */
9576 tok_str_free(str);
9577 inline_generated = 1;
9580 if (!inline_generated)
9581 break;
9584 /* free all remaining inline function tokens */
9585 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9586 type = &sym->type;
9587 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9588 (type->t & (VT_STATIC | VT_INLINE)) ==
9589 (VT_STATIC | VT_INLINE)) {
9590 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9591 if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
9592 continue;
9593 str = INLINE_DEF(sym->r);
9594 tok_str_free(str);
9595 sym->r = 0; /* fail safe */
9600 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9601 static void decl(int l)
9603 int v, has_init, r;
9604 CType type, btype;
9605 Sym *sym;
9606 AttributeDef ad;
9608 while (1) {
9609 if (!parse_btype(&btype, &ad)) {
9610 /* skip redundant ';' */
9611 /* XXX: find more elegant solution */
9612 if (tok == ';') {
9613 next();
9614 continue;
9616 if (l == VT_CONST &&
9617 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9618 /* global asm block */
9619 asm_global_instr();
9620 continue;
9622 /* special test for old K&R protos without explicit int
9623 type. Only accepted when defining global data */
9624 if (l == VT_LOCAL || tok < TOK_DEFINE)
9625 break;
9626 btype.t = VT_INT;
9628 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9629 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9630 tok == ';') {
9631 /* we accept no variable after */
9632 next();
9633 continue;
9635 while (1) { /* iterate thru each declaration */
9636 type = btype;
9637 type_decl(&type, &ad, &v, TYPE_DIRECT);
9638 #if 0
9640 char buf[500];
9641 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
9642 printf("type = '%s'\n", buf);
9644 #endif
9645 if ((type.t & VT_BTYPE) == VT_FUNC) {
9646 /* if old style function prototype, we accept a
9647 declaration list */
9648 sym = type.ref;
9649 if (sym->c == FUNC_OLD)
9650 func_decl_list(sym);
9653 if (tok == '{') {
9654 if (l == VT_LOCAL)
9655 error("cannot use local functions");
9656 if ((type.t & VT_BTYPE) != VT_FUNC)
9657 expect("function definition");
9659 /* reject abstract declarators in function definition */
9660 sym = type.ref;
9661 while ((sym = sym->next) != NULL)
9662 if (!(sym->v & ~SYM_FIELD))
9663 expect("identifier");
9665 /* XXX: cannot do better now: convert extern line to static inline */
9666 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9667 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9669 sym = sym_find(v);
9670 if (sym) {
9671 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9672 goto func_error1;
9673 /* specific case: if not func_call defined, we put
9674 the one of the prototype */
9675 /* XXX: should have default value */
9676 r = sym->type.ref->r;
9677 if (FUNC_CALL(r) != FUNC_CDECL
9678 && FUNC_CALL(type.ref->r) == FUNC_CDECL)
9679 FUNC_CALL(type.ref->r) = FUNC_CALL(r);
9680 if (FUNC_EXPORT(r))
9681 FUNC_EXPORT(type.ref->r) = 1;
9683 if (!is_compatible_types(&sym->type, &type)) {
9684 func_error1:
9685 error("incompatible types for redefinition of '%s'",
9686 get_tok_str(v, NULL));
9688 /* if symbol is already defined, then put complete type */
9689 sym->type = type;
9690 } else {
9691 /* put function symbol */
9692 sym = global_identifier_push(v, type.t, 0);
9693 sym->type.ref = type.ref;
9696 /* static inline functions are just recorded as a kind
9697 of macro. Their code will be emitted at the end of
9698 the compilation unit only if they are used */
9699 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9700 (VT_INLINE | VT_STATIC)) {
9701 TokenString func_str;
9702 int block_level;
9704 tok_str_new(&func_str);
9706 block_level = 0;
9707 for(;;) {
9708 int t;
9709 if (tok == TOK_EOF)
9710 error("unexpected end of file");
9711 tok_str_add_tok(&func_str);
9712 t = tok;
9713 next();
9714 if (t == '{') {
9715 block_level++;
9716 } else if (t == '}') {
9717 block_level--;
9718 if (block_level == 0)
9719 break;
9722 tok_str_add(&func_str, -1);
9723 tok_str_add(&func_str, 0);
9724 INLINE_DEF(sym->r) = func_str.str;
9725 } else {
9726 /* compute text section */
9727 cur_text_section = ad.section;
9728 if (!cur_text_section)
9729 cur_text_section = text_section;
9730 sym->r = VT_SYM | VT_CONST;
9731 gen_function(sym);
9733 break;
9734 } else {
9735 if (btype.t & VT_TYPEDEF) {
9736 /* save typedefed type */
9737 /* XXX: test storage specifiers ? */
9738 sym = sym_push(v, &type, 0, 0);
9739 sym->type.t |= VT_TYPEDEF;
9740 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9741 /* external function definition */
9742 /* specific case for func_call attribute */
9743 if (ad.func_attr)
9744 type.ref->r = ad.func_attr;
9745 external_sym(v, &type, 0);
9746 } else {
9747 /* not lvalue if array */
9748 r = 0;
9749 if (!(type.t & VT_ARRAY))
9750 r |= lvalue_type(type.t);
9751 has_init = (tok == '=');
9752 if ((btype.t & VT_EXTERN) ||
9753 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9754 !has_init && l == VT_CONST && type.ref->c < 0)) {
9755 /* external variable */
9756 /* NOTE: as GCC, uninitialized global static
9757 arrays of null size are considered as
9758 extern */
9759 external_sym(v, &type, r);
9760 } else {
9761 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9762 if (type.t & VT_STATIC)
9763 r |= VT_CONST;
9764 else
9765 r |= l;
9766 if (has_init)
9767 next();
9768 decl_initializer_alloc(&type, &ad, r,
9769 has_init, v, l);
9772 if (tok != ',') {
9773 skip(';');
9774 break;
9776 next();
9782 /* better than nothing, but needs extension to handle '-E' option
9783 correctly too */
9784 static void preprocess_init(TCCState *s1)
9786 s1->include_stack_ptr = s1->include_stack;
9787 /* XXX: move that before to avoid having to initialize
9788 file->ifdef_stack_ptr ? */
9789 s1->ifdef_stack_ptr = s1->ifdef_stack;
9790 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9792 /* XXX: not ANSI compliant: bound checking says error */
9793 vtop = vstack - 1;
9794 s1->pack_stack[0] = 0;
9795 s1->pack_stack_ptr = s1->pack_stack;
9798 /* compile the C file opened in 'file'. Return non zero if errors. */
9799 static int tcc_compile(TCCState *s1)
9801 Sym *define_start;
9802 char buf[512];
9803 volatile int section_sym;
9805 #ifdef INC_DEBUG
9806 printf("%s: **** new file\n", file->filename);
9807 #endif
9808 preprocess_init(s1);
9810 cur_text_section = NULL;
9811 funcname = "";
9812 anon_sym = SYM_FIRST_ANOM;
9814 /* file info: full path + filename */
9815 section_sym = 0; /* avoid warning */
9816 if (do_debug) {
9817 section_sym = put_elf_sym(symtab_section, 0, 0,
9818 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
9819 text_section->sh_num, NULL);
9820 getcwd(buf, sizeof(buf));
9821 #ifdef _WIN32
9822 normalize_slashes(buf);
9823 #endif
9824 pstrcat(buf, sizeof(buf), "/");
9825 put_stabs_r(buf, N_SO, 0, 0,
9826 text_section->data_offset, text_section, section_sym);
9827 put_stabs_r(file->filename, N_SO, 0, 0,
9828 text_section->data_offset, text_section, section_sym);
9830 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9831 symbols can be safely used */
9832 put_elf_sym(symtab_section, 0, 0,
9833 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
9834 SHN_ABS, file->filename);
9836 /* define some often used types */
9837 int_type.t = VT_INT;
9839 char_pointer_type.t = VT_BYTE;
9840 mk_pointer(&char_pointer_type);
9842 func_old_type.t = VT_FUNC;
9843 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9845 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9846 float_type.t = VT_FLOAT;
9847 double_type.t = VT_DOUBLE;
9849 func_float_type.t = VT_FUNC;
9850 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9851 func_double_type.t = VT_FUNC;
9852 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9853 #endif
9855 #if 0
9856 /* define 'void *alloca(unsigned int)' builtin function */
9858 Sym *s1;
9860 p = anon_sym++;
9861 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9862 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9863 s1->next = NULL;
9864 sym->next = s1;
9865 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9867 #endif
9869 define_start = define_stack;
9870 nocode_wanted = 1;
9872 if (setjmp(s1->error_jmp_buf) == 0) {
9873 s1->nb_errors = 0;
9874 s1->error_set_jmp_enabled = 1;
9876 ch = file->buf_ptr[0];
9877 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9878 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9879 next();
9880 decl(VT_CONST);
9881 if (tok != TOK_EOF)
9882 expect("declaration");
9884 /* end of translation unit info */
9885 if (do_debug) {
9886 put_stabs_r(NULL, N_SO, 0, 0,
9887 text_section->data_offset, text_section, section_sym);
9890 s1->error_set_jmp_enabled = 0;
9892 /* reset define stack, but leave -Dsymbols (may be incorrect if
9893 they are undefined) */
9894 free_defines(define_start);
9896 gen_inline_functions();
9898 sym_pop(&global_stack, NULL);
9899 sym_pop(&local_stack, NULL);
9901 return s1->nb_errors != 0 ? -1 : 0;
9904 /* Preprocess the current file */
9905 static int tcc_preprocess(TCCState *s1)
9907 Sym *define_start;
9908 BufferedFile *file_ref;
9909 int token_seen, line_ref;
9911 preprocess_init(s1);
9912 define_start = define_stack;
9913 ch = file->buf_ptr[0];
9914 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9915 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9916 PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES;
9917 token_seen = 0;
9918 line_ref = 0;
9919 file_ref = NULL;
9921 for (;;) {
9922 next();
9923 if (tok == TOK_EOF) {
9924 break;
9925 } else if (tok == TOK_LINEFEED) {
9926 if (!token_seen)
9927 continue;
9928 ++line_ref;
9929 token_seen = 0;
9930 } else if (!token_seen) {
9931 int d = file->line_num - line_ref;
9932 if (file != file_ref || d < 0 || d >= 8)
9933 fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename);
9934 else
9935 while (d)
9936 fputs("\n", s1->outfile), --d;
9937 line_ref = (file_ref = file)->line_num;
9938 token_seen = 1;
9940 fputs(get_tok_str(tok, &tokc), s1->outfile);
9942 free_defines(define_start);
9943 return 0;
9946 #ifdef LIBTCC
9947 int tcc_compile_string(TCCState *s, const char *str)
9949 BufferedFile bf1, *bf = &bf1;
9950 int ret, len;
9951 char *buf;
9953 /* init file structure */
9954 bf->fd = -1;
9955 /* XXX: avoid copying */
9956 len = strlen(str);
9957 buf = tcc_malloc(len + 1);
9958 if (!buf)
9959 return -1;
9960 memcpy(buf, str, len);
9961 buf[len] = CH_EOB;
9962 bf->buf_ptr = buf;
9963 bf->buf_end = buf + len;
9964 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9965 bf->line_num = 1;
9966 file = bf;
9967 ret = tcc_compile(s);
9968 file = NULL;
9969 tcc_free(buf);
9971 /* currently, no need to close */
9972 return ret;
9974 #endif
9976 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9977 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9979 BufferedFile bf1, *bf = &bf1;
9981 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9982 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9983 /* default value */
9984 if (!value)
9985 value = "1";
9986 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9988 /* init file structure */
9989 bf->fd = -1;
9990 bf->buf_ptr = bf->buffer;
9991 bf->buf_end = bf->buffer + strlen(bf->buffer);
9992 *bf->buf_end = CH_EOB;
9993 bf->filename[0] = '\0';
9994 bf->line_num = 1;
9995 file = bf;
9997 s1->include_stack_ptr = s1->include_stack;
9999 /* parse with define parser */
10000 ch = file->buf_ptr[0];
10001 next_nomacro();
10002 parse_define();
10003 file = NULL;
10006 /* undefine a preprocessor symbol */
10007 void tcc_undefine_symbol(TCCState *s1, const char *sym)
10009 TokenSym *ts;
10010 Sym *s;
10011 ts = tok_alloc(sym, strlen(sym));
10012 s = define_find(ts->tok);
10013 /* undefine symbol by putting an invalid name */
10014 if (s)
10015 define_undef(s);
10018 #ifdef CONFIG_TCC_ASM
10020 #ifdef TCC_TARGET_I386
10021 #include "i386-asm.c"
10022 #endif
10023 #include "tccasm.c"
10025 #else
10026 static void asm_instr(void)
10028 error("inline asm() not supported");
10030 static void asm_global_instr(void)
10032 error("inline asm() not supported");
10034 #endif
10036 #include "tccelf.c"
10038 #ifdef TCC_TARGET_COFF
10039 #include "tcccoff.c"
10040 #endif
10042 #ifdef TCC_TARGET_PE
10043 #include "tccpe.c"
10044 #endif
10046 /* print the position in the source file of PC value 'pc' by reading
10047 the stabs debug information */
10048 static void rt_printline(unsigned long wanted_pc)
10050 Stab_Sym *sym, *sym_end;
10051 char func_name[128], last_func_name[128];
10052 unsigned long func_addr, last_pc, pc;
10053 const char *incl_files[INCLUDE_STACK_SIZE];
10054 int incl_index, len, last_line_num, i;
10055 const char *str, *p;
10057 fprintf(stderr, "0x%08lx:", wanted_pc);
10059 func_name[0] = '\0';
10060 func_addr = 0;
10061 incl_index = 0;
10062 last_func_name[0] = '\0';
10063 last_pc = 0xffffffff;
10064 last_line_num = 1;
10065 sym = (Stab_Sym *)stab_section->data + 1;
10066 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
10067 while (sym < sym_end) {
10068 switch(sym->n_type) {
10069 /* function start or end */
10070 case N_FUN:
10071 if (sym->n_strx == 0) {
10072 /* we test if between last line and end of function */
10073 pc = sym->n_value + func_addr;
10074 if (wanted_pc >= last_pc && wanted_pc < pc)
10075 goto found;
10076 func_name[0] = '\0';
10077 func_addr = 0;
10078 } else {
10079 str = stabstr_section->data + sym->n_strx;
10080 p = strchr(str, ':');
10081 if (!p) {
10082 pstrcpy(func_name, sizeof(func_name), str);
10083 } else {
10084 len = p - str;
10085 if (len > sizeof(func_name) - 1)
10086 len = sizeof(func_name) - 1;
10087 memcpy(func_name, str, len);
10088 func_name[len] = '\0';
10090 func_addr = sym->n_value;
10092 break;
10093 /* line number info */
10094 case N_SLINE:
10095 pc = sym->n_value + func_addr;
10096 if (wanted_pc >= last_pc && wanted_pc < pc)
10097 goto found;
10098 last_pc = pc;
10099 last_line_num = sym->n_desc;
10100 /* XXX: slow! */
10101 strcpy(last_func_name, func_name);
10102 break;
10103 /* include files */
10104 case N_BINCL:
10105 str = stabstr_section->data + sym->n_strx;
10106 add_incl:
10107 if (incl_index < INCLUDE_STACK_SIZE) {
10108 incl_files[incl_index++] = str;
10110 break;
10111 case N_EINCL:
10112 if (incl_index > 1)
10113 incl_index--;
10114 break;
10115 case N_SO:
10116 if (sym->n_strx == 0) {
10117 incl_index = 0; /* end of translation unit */
10118 } else {
10119 str = stabstr_section->data + sym->n_strx;
10120 /* do not add path */
10121 len = strlen(str);
10122 if (len > 0 && str[len - 1] != '/')
10123 goto add_incl;
10125 break;
10127 sym++;
10130 /* second pass: we try symtab symbols (no line number info) */
10131 incl_index = 0;
10133 ElfW(Sym) *sym, *sym_end;
10134 int type;
10136 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
10137 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
10138 sym < sym_end;
10139 sym++) {
10140 type = ELFW(ST_TYPE)(sym->st_info);
10141 if (type == STT_FUNC) {
10142 if (wanted_pc >= sym->st_value &&
10143 wanted_pc < sym->st_value + sym->st_size) {
10144 pstrcpy(last_func_name, sizeof(last_func_name),
10145 strtab_section->data + sym->st_name);
10146 goto found;
10151 /* did not find any info: */
10152 fprintf(stderr, " ???\n");
10153 return;
10154 found:
10155 if (last_func_name[0] != '\0') {
10156 fprintf(stderr, " %s()", last_func_name);
10158 if (incl_index > 0) {
10159 fprintf(stderr, " (%s:%d",
10160 incl_files[incl_index - 1], last_line_num);
10161 for(i = incl_index - 2; i >= 0; i--)
10162 fprintf(stderr, ", included from %s", incl_files[i]);
10163 fprintf(stderr, ")");
10165 fprintf(stderr, "\n");
10168 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
10170 #ifdef __i386__
10172 /* fix for glibc 2.1 */
10173 #ifndef REG_EIP
10174 #define REG_EIP EIP
10175 #define REG_EBP EBP
10176 #endif
10178 /* return the PC at frame level 'level'. Return non zero if not found */
10179 static int rt_get_caller_pc(unsigned long *paddr,
10180 ucontext_t *uc, int level)
10182 unsigned long fp;
10183 int i;
10185 if (level == 0) {
10186 #if defined(__FreeBSD__)
10187 *paddr = uc->uc_mcontext.mc_eip;
10188 #elif defined(__dietlibc__)
10189 *paddr = uc->uc_mcontext.eip;
10190 #else
10191 *paddr = uc->uc_mcontext.gregs[REG_EIP];
10192 #endif
10193 return 0;
10194 } else {
10195 #if defined(__FreeBSD__)
10196 fp = uc->uc_mcontext.mc_ebp;
10197 #elif defined(__dietlibc__)
10198 fp = uc->uc_mcontext.ebp;
10199 #else
10200 fp = uc->uc_mcontext.gregs[REG_EBP];
10201 #endif
10202 for(i=1;i<level;i++) {
10203 /* XXX: check address validity with program info */
10204 if (fp <= 0x1000 || fp >= 0xc0000000)
10205 return -1;
10206 fp = ((unsigned long *)fp)[0];
10208 *paddr = ((unsigned long *)fp)[1];
10209 return 0;
10212 #elif defined(__x86_64__)
10213 /* return the PC at frame level 'level'. Return non zero if not found */
10214 static int rt_get_caller_pc(unsigned long *paddr,
10215 ucontext_t *uc, int level)
10217 unsigned long fp;
10218 int i;
10220 if (level == 0) {
10221 /* XXX: only support linux */
10222 *paddr = uc->uc_mcontext.gregs[REG_RIP];
10223 return 0;
10224 } else {
10225 fp = uc->uc_mcontext.gregs[REG_RBP];
10226 for(i=1;i<level;i++) {
10227 /* XXX: check address validity with program info */
10228 if (fp <= 0x1000)
10229 return -1;
10230 fp = ((unsigned long *)fp)[0];
10232 *paddr = ((unsigned long *)fp)[1];
10233 return 0;
10236 #else
10238 #warning add arch specific rt_get_caller_pc()
10240 static int rt_get_caller_pc(unsigned long *paddr,
10241 ucontext_t *uc, int level)
10243 return -1;
10245 #endif
10247 /* emit a run time error at position 'pc' */
10248 void rt_error(ucontext_t *uc, const char *fmt, ...)
10250 va_list ap;
10251 unsigned long pc;
10252 int i;
10254 va_start(ap, fmt);
10255 fprintf(stderr, "Runtime error: ");
10256 vfprintf(stderr, fmt, ap);
10257 fprintf(stderr, "\n");
10258 for(i=0;i<num_callers;i++) {
10259 if (rt_get_caller_pc(&pc, uc, i) < 0)
10260 break;
10261 if (i == 0)
10262 fprintf(stderr, "at ");
10263 else
10264 fprintf(stderr, "by ");
10265 rt_printline(pc);
10267 exit(255);
10268 va_end(ap);
10271 /* signal handler for fatal errors */
10272 static void sig_error(int signum, siginfo_t *siginf, void *puc)
10274 ucontext_t *uc = puc;
10276 switch(signum) {
10277 case SIGFPE:
10278 switch(siginf->si_code) {
10279 case FPE_INTDIV:
10280 case FPE_FLTDIV:
10281 rt_error(uc, "division by zero");
10282 break;
10283 default:
10284 rt_error(uc, "floating point exception");
10285 break;
10287 break;
10288 case SIGBUS:
10289 case SIGSEGV:
10290 if (rt_bound_error_msg && *rt_bound_error_msg)
10291 rt_error(uc, *rt_bound_error_msg);
10292 else
10293 rt_error(uc, "dereferencing invalid pointer");
10294 break;
10295 case SIGILL:
10296 rt_error(uc, "illegal instruction");
10297 break;
10298 case SIGABRT:
10299 rt_error(uc, "abort() called");
10300 break;
10301 default:
10302 rt_error(uc, "caught signal %d", signum);
10303 break;
10305 exit(255);
10307 #endif
10309 /* copy code into memory passed in by the caller and do all relocations
10310 (needed before using tcc_get_symbol()).
10311 returns -1 on error and required size if ptr is NULL */
10312 int tcc_relocate(TCCState *s1, void *ptr)
10314 Section *s;
10315 unsigned long offset, length, mem;
10316 int i;
10318 s1->nb_errors = 0;
10320 if (0 == s1->runtime_added) {
10321 #ifdef TCC_TARGET_PE
10322 pe_add_runtime(s1);
10323 relocate_common_syms();
10324 tcc_add_linker_symbols(s1);
10325 #else
10326 tcc_add_runtime(s1);
10327 relocate_common_syms();
10328 tcc_add_linker_symbols(s1);
10329 build_got_entries(s1);
10330 #endif
10331 s1->runtime_added = 1;
10334 offset = 0;
10335 mem = (unsigned long)ptr;
10336 for(i = 1; i < s1->nb_sections; i++) {
10337 s = s1->sections[i];
10338 if (0 == (s->sh_flags & SHF_ALLOC))
10339 continue;
10340 length = s->data_offset;
10341 if (0 == mem) {
10342 s->sh_addr = 0;
10343 } else if (1 == mem) {
10344 /* section are relocated in place.
10345 We also alloc the bss space */
10346 if (s->sh_type == SHT_NOBITS)
10347 s->data = tcc_malloc(length);
10348 s->sh_addr = (unsigned long)s->data;
10349 } else {
10350 /* sections are relocated to new memory */
10351 s->sh_addr = (mem + offset + 15) & ~15;
10353 offset = (offset + length + 15) & ~15;
10356 #ifdef TCC_TARGET_X86_64
10357 s1->runtime_plt_and_got_offset = 0;
10358 s1->runtime_plt_and_got = (char *)(mem + offset);
10359 /* double the size of the buffer for got and plt entries
10360 XXX: calculate exact size for them? */
10361 offset *= 2;
10362 #endif
10364 if (0 == mem)
10365 return offset + 15;
10367 /* relocate symbols */
10368 relocate_syms(s1, 1);
10369 if (s1->nb_errors)
10370 return -1;
10372 /* relocate each section */
10373 for(i = 1; i < s1->nb_sections; i++) {
10374 s = s1->sections[i];
10375 if (s->reloc)
10376 relocate_section(s1, s);
10379 for(i = 1; i < s1->nb_sections; i++) {
10380 s = s1->sections[i];
10381 if (0 == (s->sh_flags & SHF_ALLOC))
10382 continue;
10383 length = s->data_offset;
10384 // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
10385 ptr = (void*)s->sh_addr;
10386 if (NULL == s->data || s->sh_type == SHT_NOBITS)
10387 memset(ptr, 0, length);
10388 else if (ptr != s->data)
10389 memcpy(ptr, s->data, length);
10390 /* mark executable sections as executable in memory */
10391 if (s->sh_flags & SHF_EXECINSTR)
10392 set_pages_executable(ptr, length);
10394 #ifdef TCC_TARGET_X86_64
10395 set_pages_executable(s1->runtime_plt_and_got,
10396 s1->runtime_plt_and_got_offset);
10397 #endif
10398 return 0;
10401 /* launch the compiled program with the given arguments */
10402 int tcc_run(TCCState *s1, int argc, char **argv)
10404 int (*prog_main)(int, char **);
10405 void *ptr;
10406 int ret;
10408 ret = tcc_relocate(s1, NULL);
10409 if (ret < 0)
10410 return -1;
10411 ptr = tcc_malloc(ret);
10412 tcc_relocate(s1, ptr);
10414 prog_main = tcc_get_symbol_err(s1, "main");
10416 if (do_debug) {
10417 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10418 error("debug mode currently not available for Windows");
10419 #else
10420 struct sigaction sigact;
10421 /* install TCC signal handlers to print debug info on fatal
10422 runtime errors */
10423 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
10424 sigact.sa_sigaction = sig_error;
10425 sigemptyset(&sigact.sa_mask);
10426 sigaction(SIGFPE, &sigact, NULL);
10427 sigaction(SIGILL, &sigact, NULL);
10428 sigaction(SIGSEGV, &sigact, NULL);
10429 sigaction(SIGBUS, &sigact, NULL);
10430 sigaction(SIGABRT, &sigact, NULL);
10431 #endif
10434 #ifdef CONFIG_TCC_BCHECK
10435 if (do_bounds_check) {
10436 void (*bound_init)(void);
10438 /* set error function */
10439 rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
10441 /* XXX: use .init section so that it also work in binary ? */
10442 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
10443 bound_init();
10445 #endif
10446 ret = (*prog_main)(argc, argv);
10447 tcc_free(ptr);
10448 return ret;
10451 void tcc_memstats(void)
10453 #ifdef MEM_DEBUG
10454 printf("memory in use: %d\n", mem_cur_size);
10455 #endif
10458 static void tcc_cleanup(void)
10460 int i, n;
10462 if (NULL == tcc_state)
10463 return;
10464 tcc_state = NULL;
10466 /* free -D defines */
10467 free_defines(NULL);
10469 /* free tokens */
10470 n = tok_ident - TOK_IDENT;
10471 for(i = 0; i < n; i++)
10472 tcc_free(table_ident[i]);
10473 tcc_free(table_ident);
10475 /* free sym_pools */
10476 dynarray_reset(&sym_pools, &nb_sym_pools);
10477 /* string buffer */
10478 cstr_free(&tokcstr);
10479 /* reset symbol stack */
10480 sym_free_first = NULL;
10481 /* cleanup from error/setjmp */
10482 macro_ptr = NULL;
10485 TCCState *tcc_new(void)
10487 const char *p, *r;
10488 TCCState *s;
10489 TokenSym *ts;
10490 int i, c;
10492 tcc_cleanup();
10494 s = tcc_mallocz(sizeof(TCCState));
10495 if (!s)
10496 return NULL;
10497 tcc_state = s;
10498 s->output_type = TCC_OUTPUT_MEMORY;
10500 /* init isid table */
10501 for(i=CH_EOF;i<256;i++)
10502 isidnum_table[i-CH_EOF] = isid(i) || isnum(i);
10504 /* add all tokens */
10505 table_ident = NULL;
10506 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
10508 tok_ident = TOK_IDENT;
10509 p = tcc_keywords;
10510 while (*p) {
10511 r = p;
10512 for(;;) {
10513 c = *r++;
10514 if (c == '\0')
10515 break;
10517 ts = tok_alloc(p, r - p - 1);
10518 p = r;
10521 /* we add dummy defines for some special macros to speed up tests
10522 and to have working defined() */
10523 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
10524 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
10525 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
10526 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
10528 /* standard defines */
10529 tcc_define_symbol(s, "__STDC__", NULL);
10530 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
10531 #if defined(TCC_TARGET_I386)
10532 tcc_define_symbol(s, "__i386__", NULL);
10533 #endif
10534 #if defined(TCC_TARGET_X86_64)
10535 tcc_define_symbol(s, "__x86_64__", NULL);
10536 #endif
10537 #if defined(TCC_TARGET_ARM)
10538 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10539 tcc_define_symbol(s, "__arm_elf__", NULL);
10540 tcc_define_symbol(s, "__arm_elf", NULL);
10541 tcc_define_symbol(s, "arm_elf", NULL);
10542 tcc_define_symbol(s, "__arm__", NULL);
10543 tcc_define_symbol(s, "__arm", NULL);
10544 tcc_define_symbol(s, "arm", NULL);
10545 tcc_define_symbol(s, "__APCS_32__", NULL);
10546 #endif
10547 #ifdef TCC_TARGET_PE
10548 tcc_define_symbol(s, "_WIN32", NULL);
10549 #else
10550 tcc_define_symbol(s, "__unix__", NULL);
10551 tcc_define_symbol(s, "__unix", NULL);
10552 #if defined(__linux)
10553 tcc_define_symbol(s, "__linux__", NULL);
10554 tcc_define_symbol(s, "__linux", NULL);
10555 #endif
10556 #endif
10557 /* tiny C specific defines */
10558 tcc_define_symbol(s, "__TINYC__", NULL);
10560 /* tiny C & gcc defines */
10561 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10562 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10563 #ifdef TCC_TARGET_PE
10564 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10565 #else
10566 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10567 #endif
10569 #ifndef TCC_TARGET_PE
10570 /* default library paths */
10571 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/local/lib");
10572 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/lib");
10573 tcc_add_library_path(s, CONFIG_SYSROOT "/lib");
10574 #endif
10576 /* no section zero */
10577 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10579 /* create standard sections */
10580 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10581 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10582 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10584 /* symbols are always generated for linking stage */
10585 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10586 ".strtab",
10587 ".hashtab", SHF_PRIVATE);
10588 strtab_section = symtab_section->link;
10590 /* private symbol table for dynamic symbols */
10591 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10592 ".dynstrtab",
10593 ".dynhashtab", SHF_PRIVATE);
10594 s->alacarte_link = 1;
10596 #ifdef CHAR_IS_UNSIGNED
10597 s->char_is_unsigned = 1;
10598 #endif
10599 #if defined(TCC_TARGET_PE) && 0
10600 /* XXX: currently the PE linker is not ready to support that */
10601 s->leading_underscore = 1;
10602 #endif
10603 return s;
10606 void tcc_delete(TCCState *s1)
10608 int i;
10610 tcc_cleanup();
10612 /* free all sections */
10613 for(i = 1; i < s1->nb_sections; i++)
10614 free_section(s1->sections[i]);
10615 dynarray_reset(&s1->sections, &s1->nb_sections);
10617 for(i = 0; i < s1->nb_priv_sections; i++)
10618 free_section(s1->priv_sections[i]);
10619 dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
10621 /* free any loaded DLLs */
10622 for ( i = 0; i < s1->nb_loaded_dlls; i++) {
10623 DLLReference *ref = s1->loaded_dlls[i];
10624 if ( ref->handle )
10625 dlclose(ref->handle);
10628 /* free loaded dlls array */
10629 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
10631 /* free library paths */
10632 dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
10634 /* free include paths */
10635 dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
10636 dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
10637 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
10639 tcc_free(s1);
10642 int tcc_add_include_path(TCCState *s1, const char *pathname)
10644 char *pathname1;
10646 pathname1 = tcc_strdup(pathname);
10647 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10648 return 0;
10651 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10653 char *pathname1;
10655 pathname1 = tcc_strdup(pathname);
10656 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10657 return 0;
10660 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10662 const char *ext;
10663 ElfW(Ehdr) ehdr;
10664 int fd, ret;
10665 BufferedFile *saved_file;
10667 /* find source file type with extension */
10668 ext = tcc_fileextension(filename);
10669 if (ext[0])
10670 ext++;
10672 /* open the file */
10673 saved_file = file;
10674 file = tcc_open(s1, filename);
10675 if (!file) {
10676 if (flags & AFF_PRINT_ERROR) {
10677 error_noabort("file '%s' not found", filename);
10679 ret = -1;
10680 goto fail1;
10683 if (flags & AFF_PREPROCESS) {
10684 ret = tcc_preprocess(s1);
10685 } else if (!ext[0] || !PATHCMP(ext, "c")) {
10686 /* C file assumed */
10687 ret = tcc_compile(s1);
10688 } else
10689 #ifdef CONFIG_TCC_ASM
10690 if (!strcmp(ext, "S")) {
10691 /* preprocessed assembler */
10692 ret = tcc_assemble(s1, 1);
10693 } else if (!strcmp(ext, "s")) {
10694 /* non preprocessed assembler */
10695 ret = tcc_assemble(s1, 0);
10696 } else
10697 #endif
10698 #ifdef TCC_TARGET_PE
10699 if (!PATHCMP(ext, "def")) {
10700 ret = pe_load_def_file(s1, file->fd);
10701 } else
10702 #endif
10704 fd = file->fd;
10705 /* assume executable format: auto guess file type */
10706 ret = read(fd, &ehdr, sizeof(ehdr));
10707 lseek(fd, 0, SEEK_SET);
10708 if (ret <= 0) {
10709 error_noabort("could not read header");
10710 goto fail;
10711 } else if (ret != sizeof(ehdr)) {
10712 goto try_load_script;
10715 if (ehdr.e_ident[0] == ELFMAG0 &&
10716 ehdr.e_ident[1] == ELFMAG1 &&
10717 ehdr.e_ident[2] == ELFMAG2 &&
10718 ehdr.e_ident[3] == ELFMAG3) {
10719 file->line_num = 0; /* do not display line number if error */
10720 if (ehdr.e_type == ET_REL) {
10721 ret = tcc_load_object_file(s1, fd, 0);
10722 } else if (ehdr.e_type == ET_DYN) {
10723 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10724 #ifdef TCC_TARGET_PE
10725 ret = -1;
10726 #else
10727 void *h;
10728 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10729 if (h)
10730 ret = 0;
10731 else
10732 ret = -1;
10733 #endif
10734 } else {
10735 ret = tcc_load_dll(s1, fd, filename,
10736 (flags & AFF_REFERENCED_DLL) != 0);
10738 } else {
10739 error_noabort("unrecognized ELF file");
10740 goto fail;
10742 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10743 file->line_num = 0; /* do not display line number if error */
10744 ret = tcc_load_archive(s1, fd);
10745 } else
10746 #ifdef TCC_TARGET_COFF
10747 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10748 ret = tcc_load_coff(s1, fd);
10749 } else
10750 #endif
10751 #ifdef TCC_TARGET_PE
10752 if (pe_test_res_file(&ehdr, ret)) {
10753 ret = pe_load_res_file(s1, fd);
10754 } else
10755 #endif
10757 /* as GNU ld, consider it is an ld script if not recognized */
10758 try_load_script:
10759 ret = tcc_load_ldscript(s1);
10760 if (ret < 0) {
10761 error_noabort("unrecognized file type");
10762 goto fail;
10766 the_end:
10767 tcc_close(file);
10768 fail1:
10769 file = saved_file;
10770 return ret;
10771 fail:
10772 ret = -1;
10773 goto the_end;
10776 int tcc_add_file(TCCState *s, const char *filename)
10778 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10781 int tcc_add_library_path(TCCState *s, const char *pathname)
10783 char *pathname1;
10785 pathname1 = tcc_strdup(pathname);
10786 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10787 return 0;
10790 /* find and load a dll. Return non zero if not found */
10791 /* XXX: add '-rpath' option support ? */
10792 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10794 char buf[1024];
10795 int i;
10797 for(i = 0; i < s->nb_library_paths; i++) {
10798 snprintf(buf, sizeof(buf), "%s/%s",
10799 s->library_paths[i], filename);
10800 if (tcc_add_file_internal(s, buf, flags) == 0)
10801 return 0;
10803 return -1;
10806 /* the library name is the same as the argument of the '-l' option */
10807 int tcc_add_library(TCCState *s, const char *libraryname)
10809 char buf[1024];
10810 int i;
10812 /* first we look for the dynamic library if not static linking */
10813 if (!s->static_link) {
10814 #ifdef TCC_TARGET_PE
10815 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10816 #else
10817 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10818 #endif
10819 if (tcc_add_dll(s, buf, 0) == 0)
10820 return 0;
10823 /* then we look for the static library */
10824 for(i = 0; i < s->nb_library_paths; i++) {
10825 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10826 s->library_paths[i], libraryname);
10827 if (tcc_add_file_internal(s, buf, 0) == 0)
10828 return 0;
10830 return -1;
10833 int tcc_add_symbol(TCCState *s, const char *name, void *val)
10835 add_elf_sym(symtab_section, (unsigned long)val, 0,
10836 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
10837 SHN_ABS, name);
10838 return 0;
10841 int tcc_set_output_type(TCCState *s, int output_type)
10843 char buf[1024];
10845 s->output_type = output_type;
10847 if (!s->nostdinc) {
10848 /* default include paths */
10849 /* XXX: reverse order needed if -isystem support */
10850 #ifndef TCC_TARGET_PE
10851 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/local/include");
10852 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/include");
10853 #endif
10854 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10855 tcc_add_sysinclude_path(s, buf);
10856 #ifdef TCC_TARGET_PE
10857 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10858 tcc_add_sysinclude_path(s, buf);
10859 #endif
10862 /* if bound checking, then add corresponding sections */
10863 #ifdef CONFIG_TCC_BCHECK
10864 if (do_bounds_check) {
10865 /* define symbol */
10866 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10867 /* create bounds sections */
10868 bounds_section = new_section(s, ".bounds",
10869 SHT_PROGBITS, SHF_ALLOC);
10870 lbounds_section = new_section(s, ".lbounds",
10871 SHT_PROGBITS, SHF_ALLOC);
10873 #endif
10875 if (s->char_is_unsigned) {
10876 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10879 /* add debug sections */
10880 if (do_debug) {
10881 /* stab symbols */
10882 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10883 stab_section->sh_entsize = sizeof(Stab_Sym);
10884 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10885 put_elf_str(stabstr_section, "");
10886 stab_section->link = stabstr_section;
10887 /* put first entry */
10888 put_stabs("", 0, 0, 0, 0);
10891 /* add libc crt1/crti objects */
10892 #ifndef TCC_TARGET_PE
10893 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10894 !s->nostdlib) {
10895 if (output_type != TCC_OUTPUT_DLL)
10896 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10897 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10899 #endif
10901 #ifdef TCC_TARGET_PE
10902 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10903 tcc_add_library_path(s, buf);
10904 #endif
10906 return 0;
10909 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10910 #define FD_INVERT 0x0002 /* invert value before storing */
10912 typedef struct FlagDef {
10913 uint16_t offset;
10914 uint16_t flags;
10915 const char *name;
10916 } FlagDef;
10918 static const FlagDef warning_defs[] = {
10919 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10920 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10921 { offsetof(TCCState, warn_error), 0, "error" },
10922 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10923 "implicit-function-declaration" },
10926 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10927 const char *name, int value)
10929 int i;
10930 const FlagDef *p;
10931 const char *r;
10933 r = name;
10934 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10935 r += 3;
10936 value = !value;
10938 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10939 if (!strcmp(r, p->name))
10940 goto found;
10942 return -1;
10943 found:
10944 if (p->flags & FD_INVERT)
10945 value = !value;
10946 *(int *)((uint8_t *)s + p->offset) = value;
10947 return 0;
10951 /* set/reset a warning */
10952 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10954 int i;
10955 const FlagDef *p;
10957 if (!strcmp(warning_name, "all")) {
10958 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10959 if (p->flags & WD_ALL)
10960 *(int *)((uint8_t *)s + p->offset) = 1;
10962 return 0;
10963 } else {
10964 return set_flag(s, warning_defs, countof(warning_defs),
10965 warning_name, value);
10969 static const FlagDef flag_defs[] = {
10970 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10971 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10972 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10973 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10976 /* set/reset a flag */
10977 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10979 return set_flag(s, flag_defs, countof(flag_defs),
10980 flag_name, value);
10983 #if !defined(LIBTCC)
10985 static int64_t getclock_us(void)
10987 #ifdef _WIN32
10988 struct _timeb tb;
10989 _ftime(&tb);
10990 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10991 #else
10992 struct timeval tv;
10993 gettimeofday(&tv, NULL);
10994 return tv.tv_sec * 1000000LL + tv.tv_usec;
10995 #endif
10998 void help(void)
11000 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
11001 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
11002 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
11003 " [-static] [infile1 infile2...] [-run infile args...]\n"
11004 "\n"
11005 "General options:\n"
11006 " -v display current version, increase verbosity\n"
11007 " -c compile only - generate an object file\n"
11008 " -o outfile set output filename\n"
11009 " -Bdir set tcc internal library path\n"
11010 " -bench output compilation statistics\n"
11011 " -run run compiled source\n"
11012 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
11013 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
11014 " -w disable all warnings\n"
11015 "Preprocessor options:\n"
11016 " -E preprocess only\n"
11017 " -Idir add include path 'dir'\n"
11018 " -Dsym[=val] define 'sym' with value 'val'\n"
11019 " -Usym undefine 'sym'\n"
11020 "Linker options:\n"
11021 " -Ldir add library path 'dir'\n"
11022 " -llib link with dynamic or static library 'lib'\n"
11023 " -shared generate a shared library\n"
11024 " -soname set name for shared library to be used at runtime\n"
11025 " -static static linking\n"
11026 " -rdynamic export all global symbols to dynamic linker\n"
11027 " -r generate (relocatable) object file\n"
11028 "Debugger options:\n"
11029 " -g generate runtime debug info\n"
11030 #ifdef CONFIG_TCC_BCHECK
11031 " -b compile with built-in memory and bounds checker (implies -g)\n"
11032 #endif
11033 " -bt N show N callers in stack traces\n"
11037 #define TCC_OPTION_HAS_ARG 0x0001
11038 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
11040 typedef struct TCCOption {
11041 const char *name;
11042 uint16_t index;
11043 uint16_t flags;
11044 } TCCOption;
11046 enum {
11047 TCC_OPTION_HELP,
11048 TCC_OPTION_I,
11049 TCC_OPTION_D,
11050 TCC_OPTION_U,
11051 TCC_OPTION_L,
11052 TCC_OPTION_B,
11053 TCC_OPTION_l,
11054 TCC_OPTION_bench,
11055 TCC_OPTION_bt,
11056 TCC_OPTION_b,
11057 TCC_OPTION_g,
11058 TCC_OPTION_c,
11059 TCC_OPTION_static,
11060 TCC_OPTION_shared,
11061 TCC_OPTION_soname,
11062 TCC_OPTION_o,
11063 TCC_OPTION_r,
11064 TCC_OPTION_Wl,
11065 TCC_OPTION_W,
11066 TCC_OPTION_O,
11067 TCC_OPTION_m,
11068 TCC_OPTION_f,
11069 TCC_OPTION_nostdinc,
11070 TCC_OPTION_nostdlib,
11071 TCC_OPTION_print_search_dirs,
11072 TCC_OPTION_rdynamic,
11073 TCC_OPTION_run,
11074 TCC_OPTION_v,
11075 TCC_OPTION_w,
11076 TCC_OPTION_pipe,
11077 TCC_OPTION_E,
11080 static const TCCOption tcc_options[] = {
11081 { "h", TCC_OPTION_HELP, 0 },
11082 { "?", TCC_OPTION_HELP, 0 },
11083 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
11084 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
11085 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
11086 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
11087 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
11088 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11089 { "bench", TCC_OPTION_bench, 0 },
11090 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
11091 #ifdef CONFIG_TCC_BCHECK
11092 { "b", TCC_OPTION_b, 0 },
11093 #endif
11094 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11095 { "c", TCC_OPTION_c, 0 },
11096 { "static", TCC_OPTION_static, 0 },
11097 { "shared", TCC_OPTION_shared, 0 },
11098 { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
11099 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
11100 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11101 { "rdynamic", TCC_OPTION_rdynamic, 0 },
11102 { "r", TCC_OPTION_r, 0 },
11103 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11104 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11105 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11106 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
11107 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11108 { "nostdinc", TCC_OPTION_nostdinc, 0 },
11109 { "nostdlib", TCC_OPTION_nostdlib, 0 },
11110 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
11111 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
11112 { "w", TCC_OPTION_w, 0 },
11113 { "pipe", TCC_OPTION_pipe, 0},
11114 { "E", TCC_OPTION_E, 0},
11115 { NULL },
11118 /* convert 'str' into an array of space separated strings */
11119 static int expand_args(char ***pargv, const char *str)
11121 const char *s1;
11122 char **argv, *arg;
11123 int argc, len;
11125 argc = 0;
11126 argv = NULL;
11127 for(;;) {
11128 while (is_space(*str))
11129 str++;
11130 if (*str == '\0')
11131 break;
11132 s1 = str;
11133 while (*str != '\0' && !is_space(*str))
11134 str++;
11135 len = str - s1;
11136 arg = tcc_malloc(len + 1);
11137 memcpy(arg, s1, len);
11138 arg[len] = '\0';
11139 dynarray_add((void ***)&argv, &argc, arg);
11141 *pargv = argv;
11142 return argc;
11145 static char **files;
11146 static int nb_files, nb_libraries;
11147 static int multiple_files;
11148 static int print_search_dirs;
11149 static int output_type;
11150 static int reloc_output;
11151 static const char *outfile;
11153 int parse_args(TCCState *s, int argc, char **argv)
11155 int optind;
11156 const TCCOption *popt;
11157 const char *optarg, *p1, *r1;
11158 char *r;
11160 optind = 0;
11161 while (optind < argc) {
11163 r = argv[optind++];
11164 if (r[0] != '-' || r[1] == '\0') {
11165 /* add a new file */
11166 dynarray_add((void ***)&files, &nb_files, r);
11167 if (!multiple_files) {
11168 optind--;
11169 /* argv[0] will be this file */
11170 break;
11172 } else {
11173 /* find option in table (match only the first chars */
11174 popt = tcc_options;
11175 for(;;) {
11176 p1 = popt->name;
11177 if (p1 == NULL)
11178 error("invalid option -- '%s'", r);
11179 r1 = r + 1;
11180 for(;;) {
11181 if (*p1 == '\0')
11182 goto option_found;
11183 if (*r1 != *p1)
11184 break;
11185 p1++;
11186 r1++;
11188 popt++;
11190 option_found:
11191 if (popt->flags & TCC_OPTION_HAS_ARG) {
11192 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
11193 optarg = r1;
11194 } else {
11195 if (optind >= argc)
11196 error("argument to '%s' is missing", r);
11197 optarg = argv[optind++];
11199 } else {
11200 if (*r1 != '\0')
11201 return 0;
11202 optarg = NULL;
11205 switch(popt->index) {
11206 case TCC_OPTION_HELP:
11207 return 0;
11209 case TCC_OPTION_I:
11210 if (tcc_add_include_path(s, optarg) < 0)
11211 error("too many include paths");
11212 break;
11213 case TCC_OPTION_D:
11215 char *sym, *value;
11216 sym = (char *)optarg;
11217 value = strchr(sym, '=');
11218 if (value) {
11219 *value = '\0';
11220 value++;
11222 tcc_define_symbol(s, sym, value);
11224 break;
11225 case TCC_OPTION_U:
11226 tcc_undefine_symbol(s, optarg);
11227 break;
11228 case TCC_OPTION_L:
11229 tcc_add_library_path(s, optarg);
11230 break;
11231 case TCC_OPTION_B:
11232 /* set tcc utilities path (mainly for tcc development) */
11233 tcc_lib_path = optarg;
11234 break;
11235 case TCC_OPTION_l:
11236 dynarray_add((void ***)&files, &nb_files, r);
11237 nb_libraries++;
11238 break;
11239 case TCC_OPTION_bench:
11240 do_bench = 1;
11241 break;
11242 case TCC_OPTION_bt:
11243 num_callers = atoi(optarg);
11244 break;
11245 #ifdef CONFIG_TCC_BCHECK
11246 case TCC_OPTION_b:
11247 do_bounds_check = 1;
11248 do_debug = 1;
11249 break;
11250 #endif
11251 case TCC_OPTION_g:
11252 do_debug = 1;
11253 break;
11254 case TCC_OPTION_c:
11255 multiple_files = 1;
11256 output_type = TCC_OUTPUT_OBJ;
11257 break;
11258 case TCC_OPTION_static:
11259 s->static_link = 1;
11260 break;
11261 case TCC_OPTION_shared:
11262 output_type = TCC_OUTPUT_DLL;
11263 break;
11264 case TCC_OPTION_soname:
11265 s->soname = optarg;
11266 break;
11267 case TCC_OPTION_o:
11268 multiple_files = 1;
11269 outfile = optarg;
11270 break;
11271 case TCC_OPTION_r:
11272 /* generate a .o merging several output files */
11273 reloc_output = 1;
11274 output_type = TCC_OUTPUT_OBJ;
11275 break;
11276 case TCC_OPTION_nostdinc:
11277 s->nostdinc = 1;
11278 break;
11279 case TCC_OPTION_nostdlib:
11280 s->nostdlib = 1;
11281 break;
11282 case TCC_OPTION_print_search_dirs:
11283 print_search_dirs = 1;
11284 break;
11285 case TCC_OPTION_run:
11287 int argc1;
11288 char **argv1;
11289 argc1 = expand_args(&argv1, optarg);
11290 if (argc1 > 0) {
11291 parse_args(s, argc1, argv1);
11293 multiple_files = 0;
11294 output_type = TCC_OUTPUT_MEMORY;
11296 break;
11297 case TCC_OPTION_v:
11298 do {
11299 if (0 == verbose++)
11300 printf("tcc version %s\n", TCC_VERSION);
11301 } while (*optarg++ == 'v');
11302 break;
11303 case TCC_OPTION_f:
11304 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
11305 goto unsupported_option;
11306 break;
11307 case TCC_OPTION_W:
11308 if (tcc_set_warning(s, optarg, 1) < 0 &&
11309 s->warn_unsupported)
11310 goto unsupported_option;
11311 break;
11312 case TCC_OPTION_w:
11313 s->warn_none = 1;
11314 break;
11315 case TCC_OPTION_rdynamic:
11316 s->rdynamic = 1;
11317 break;
11318 case TCC_OPTION_Wl:
11320 const char *p;
11321 if (strstart(optarg, "-Ttext,", &p)) {
11322 s->text_addr = strtoul(p, NULL, 16);
11323 s->has_text_addr = 1;
11324 } else if (strstart(optarg, "--oformat,", &p)) {
11325 if (strstart(p, "elf32-", NULL)) {
11326 s->output_format = TCC_OUTPUT_FORMAT_ELF;
11327 } else if (!strcmp(p, "binary")) {
11328 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
11329 } else
11330 #ifdef TCC_TARGET_COFF
11331 if (!strcmp(p, "coff")) {
11332 s->output_format = TCC_OUTPUT_FORMAT_COFF;
11333 } else
11334 #endif
11336 error("target %s not found", p);
11338 } else {
11339 error("unsupported linker option '%s'", optarg);
11342 break;
11343 case TCC_OPTION_E:
11344 output_type = TCC_OUTPUT_PREPROCESS;
11345 break;
11346 default:
11347 if (s->warn_unsupported) {
11348 unsupported_option:
11349 warning("unsupported option '%s'", r);
11351 break;
11355 return optind + 1;
11358 int main(int argc, char **argv)
11360 int i;
11361 TCCState *s;
11362 int nb_objfiles, ret, optind;
11363 char objfilename[1024];
11364 int64_t start_time = 0;
11366 #ifdef _WIN32
11367 tcc_lib_path = w32_tcc_lib_path();
11368 #endif
11370 s = tcc_new();
11371 output_type = TCC_OUTPUT_EXE;
11372 outfile = NULL;
11373 multiple_files = 1;
11374 files = NULL;
11375 nb_files = 0;
11376 nb_libraries = 0;
11377 reloc_output = 0;
11378 print_search_dirs = 0;
11379 ret = 0;
11381 optind = parse_args(s, argc - 1, argv + 1);
11382 if (print_search_dirs) {
11383 /* enough for Linux kernel */
11384 printf("install: %s/\n", tcc_lib_path);
11385 return 0;
11387 if (optind == 0 || nb_files == 0) {
11388 if (optind && verbose)
11389 return 0;
11390 help();
11391 return 1;
11394 nb_objfiles = nb_files - nb_libraries;
11396 /* if outfile provided without other options, we output an
11397 executable */
11398 if (outfile && output_type == TCC_OUTPUT_MEMORY)
11399 output_type = TCC_OUTPUT_EXE;
11401 /* check -c consistency : only single file handled. XXX: checks file type */
11402 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
11403 /* accepts only a single input file */
11404 if (nb_objfiles != 1)
11405 error("cannot specify multiple files with -c");
11406 if (nb_libraries != 0)
11407 error("cannot specify libraries with -c");
11411 if (output_type == TCC_OUTPUT_PREPROCESS) {
11412 if (!outfile) {
11413 s->outfile = stdout;
11414 } else {
11415 s->outfile = fopen(outfile, "w");
11416 if (!s->outfile)
11417 error("could not open '%s", outfile);
11419 } else if (output_type != TCC_OUTPUT_MEMORY) {
11420 if (!outfile) {
11421 /* compute default outfile name */
11422 char *ext;
11423 const char *name =
11424 strcmp(files[0], "-") == 0 ? "a" : tcc_basename(files[0]);
11425 pstrcpy(objfilename, sizeof(objfilename), name);
11426 ext = tcc_fileextension(objfilename);
11427 #ifdef TCC_TARGET_PE
11428 if (output_type == TCC_OUTPUT_DLL)
11429 strcpy(ext, ".dll");
11430 else
11431 if (output_type == TCC_OUTPUT_EXE)
11432 strcpy(ext, ".exe");
11433 else
11434 #endif
11435 if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
11436 strcpy(ext, ".o");
11437 else
11438 pstrcpy(objfilename, sizeof(objfilename), "a.out");
11439 outfile = objfilename;
11443 if (do_bench) {
11444 start_time = getclock_us();
11447 tcc_set_output_type(s, output_type);
11449 /* compile or add each files or library */
11450 for(i = 0; i < nb_files && ret == 0; i++) {
11451 const char *filename;
11453 filename = files[i];
11454 if (output_type == TCC_OUTPUT_PREPROCESS) {
11455 if (tcc_add_file_internal(s, filename,
11456 AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
11457 ret = 1;
11458 } else if (filename[0] == '-' && filename[1]) {
11459 if (tcc_add_library(s, filename + 2) < 0)
11460 error("cannot find %s", filename);
11461 } else {
11462 if (1 == verbose)
11463 printf("-> %s\n", filename);
11464 if (tcc_add_file(s, filename) < 0)
11465 ret = 1;
11469 /* free all files */
11470 tcc_free(files);
11472 if (ret)
11473 goto the_end;
11475 if (do_bench) {
11476 double total_time;
11477 total_time = (double)(getclock_us() - start_time) / 1000000.0;
11478 if (total_time < 0.001)
11479 total_time = 0.001;
11480 if (total_bytes < 1)
11481 total_bytes = 1;
11482 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11483 tok_ident - TOK_IDENT, total_lines, total_bytes,
11484 total_time, (int)(total_lines / total_time),
11485 total_bytes / total_time / 1000000.0);
11488 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
11489 if (outfile)
11490 fclose(s->outfile);
11491 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
11492 ret = tcc_run(s, argc - optind, argv + optind);
11493 } else
11494 ret = tcc_output_file(s, outfile) ? 1 : 0;
11495 the_end:
11496 /* XXX: cannot do it with bound checking because of the malloc hooks */
11497 if (!do_bounds_check)
11498 tcc_delete(s);
11500 #ifdef MEM_DEBUG
11501 if (do_bench) {
11502 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
11504 #endif
11505 return ret;
11508 #endif